aboutsummaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/game')
-rw-r--r--src/game/AccountMgr.cpp6
-rw-r--r--src/game/AchievementMgr.cpp1145
-rw-r--r--src/game/AchievementMgr.h174
-rw-r--r--src/game/AddonHandler.cpp65
-rw-r--r--src/game/ArenaTeam.cpp29
-rw-r--r--src/game/ArenaTeamHandler.cpp2
-rw-r--r--src/game/AuctionHouse.cpp20
-rw-r--r--src/game/AuctionHouseObject.h12
-rw-r--r--src/game/Bag.cpp2
-rw-r--r--src/game/BattleGround.cpp24
-rw-r--r--src/game/BattleGround.h16
-rw-r--r--src/game/BattleGroundAA.cpp2
-rw-r--r--src/game/BattleGroundAA.h2
-rw-r--r--src/game/BattleGroundAB.cpp6
-rw-r--r--src/game/BattleGroundAB.h2
-rw-r--r--src/game/BattleGroundAV.cpp2
-rw-r--r--src/game/BattleGroundAV.h2
-rw-r--r--src/game/BattleGroundBE.cpp2
-rw-r--r--src/game/BattleGroundBE.h2
-rw-r--r--src/game/BattleGroundDS.cpp63
-rw-r--r--src/game/BattleGroundDS.h47
-rw-r--r--src/game/BattleGroundEY.cpp2
-rw-r--r--src/game/BattleGroundEY.h2
-rw-r--r--src/game/BattleGroundHandler.cpp22
-rw-r--r--src/game/BattleGroundMgr.cpp309
-rw-r--r--src/game/BattleGroundMgr.h61
-rw-r--r--src/game/BattleGroundNA.cpp2
-rw-r--r--src/game/BattleGroundNA.h2
-rw-r--r--src/game/BattleGroundRL.cpp2
-rw-r--r--src/game/BattleGroundRL.h2
-rw-r--r--src/game/BattleGroundRV.cpp63
-rw-r--r--src/game/BattleGroundRV.h47
-rw-r--r--src/game/BattleGroundSA.cpp67
-rw-r--r--src/game/BattleGroundSA.h52
-rw-r--r--src/game/BattleGroundWS.cpp2
-rw-r--r--src/game/BattleGroundWS.h2
-rw-r--r--src/game/CMakeLists.txt17
-rw-r--r--src/game/Calendar.cpp17
-rw-r--r--src/game/Calendar.h26
-rw-r--r--src/game/CalendarHandler.cpp159
-rw-r--r--src/game/Cell.h4
-rw-r--r--src/game/CharacterHandler.cpp355
-rw-r--r--src/game/Chat.cpp251
-rw-r--r--src/game/Chat.h34
-rw-r--r--src/game/ChatHandler.cpp2
-rw-r--r--src/game/Corpse.cpp35
-rw-r--r--src/game/Corpse.h2
-rw-r--r--src/game/Creature.cpp77
-rw-r--r--src/game/Creature.h29
-rw-r--r--src/game/DynamicObject.cpp4
-rw-r--r--src/game/Formulas.h73
-rw-r--r--src/game/GameEvent.cpp113
-rw-r--r--src/game/GameObject.cpp130
-rw-r--r--src/game/GameObject.h38
-rw-r--r--src/game/GlobalEvents.cpp2
-rw-r--r--src/game/GossipDef.cpp26
-rw-r--r--src/game/GridNotifiers.cpp19
-rw-r--r--src/game/GridNotifiers.h78
-rw-r--r--src/game/GridNotifiersImpl.h93
-rw-r--r--src/game/Group.cpp152
-rw-r--r--src/game/Group.h13
-rw-r--r--src/game/GroupHandler.cpp56
-rw-r--r--src/game/Guild.cpp53
-rw-r--r--src/game/Guild.h9
-rw-r--r--src/game/GuildHandler.cpp2
-rw-r--r--src/game/InstanceSaveMgr.cpp8
-rw-r--r--src/game/Item.cpp22
-rw-r--r--src/game/Item.h42
-rw-r--r--src/game/ItemHandler.cpp27
-rw-r--r--src/game/ItemPrototype.h98
-rw-r--r--src/game/Language.h40
-rw-r--r--src/game/Level0.cpp2
-rw-r--r--src/game/Level1.cpp429
-rw-r--r--src/game/Level2.cpp754
-rw-r--r--src/game/Level3.cpp597
-rw-r--r--src/game/LootHandler.cpp20
-rw-r--r--src/game/LootMgr.cpp134
-rw-r--r--src/game/LootMgr.h17
-rw-r--r--src/game/Mail.cpp8
-rw-r--r--src/game/Makefile.am555
-rw-r--r--src/game/Map.cpp45
-rw-r--r--src/game/Map.h41
-rw-r--r--src/game/MapManager.cpp8
-rw-r--r--src/game/MapManager.h16
-rw-r--r--src/game/MiscHandler.cpp155
-rw-r--r--src/game/MotionMaster.cpp4
-rw-r--r--src/game/MovementHandler.cpp288
-rw-r--r--src/game/NPCHandler.cpp38
-rw-r--r--src/game/Object.cpp125
-rw-r--r--src/game/Object.h30
-rw-r--r--src/game/ObjectAccessor.cpp71
-rw-r--r--src/game/ObjectAccessor.h32
-rw-r--r--src/game/ObjectDefines.h4
-rw-r--r--src/game/ObjectGridLoader.cpp2
-rw-r--r--src/game/ObjectMgr.cpp546
-rw-r--r--src/game/ObjectMgr.h20
-rw-r--r--src/game/ObjectPosSelector.cpp157
-rw-r--r--src/game/ObjectPosSelector.h155
-rw-r--r--src/game/Opcodes.cpp2253
-rw-r--r--src/game/Opcodes.h403
-rw-r--r--src/game/OutdoorPvP.cpp8
-rw-r--r--src/game/OutdoorPvPSI.cpp4
-rw-r--r--src/game/Pet.cpp644
-rw-r--r--src/game/Pet.h59
-rw-r--r--src/game/PetAI.cpp4
-rw-r--r--src/game/PetHandler.cpp262
-rw-r--r--src/game/PetitionsHandler.cpp8
-rw-r--r--src/game/Player.cpp2643
-rw-r--r--src/game/Player.h366
-rw-r--r--src/game/QueryHandler.cpp45
-rw-r--r--src/game/QuestDef.cpp107
-rw-r--r--src/game/QuestDef.h47
-rw-r--r--src/game/QuestHandler.cpp8
-rw-r--r--src/game/ScriptCalls.cpp3
-rw-r--r--src/game/SharedDefines.h394
-rw-r--r--src/game/SkillDiscovery.cpp78
-rw-r--r--src/game/SkillDiscovery.h1
-rw-r--r--src/game/SkillHandler.cpp6
-rw-r--r--src/game/SocialMgr.cpp7
-rw-r--r--src/game/SocialMgr.h3
-rw-r--r--src/game/Spell.cpp941
-rw-r--r--src/game/Spell.h72
-rw-r--r--src/game/SpellAuraDefines.h82
-rw-r--r--src/game/SpellAuras.cpp2318
-rw-r--r--src/game/SpellAuras.h107
-rw-r--r--src/game/SpellEffects.cpp1740
-rw-r--r--src/game/SpellHandler.cpp98
-rw-r--r--src/game/SpellMgr.cpp841
-rw-r--r--src/game/SpellMgr.h517
-rw-r--r--src/game/StatSystem.cpp119
-rw-r--r--src/game/TaxiHandler.cpp8
-rw-r--r--src/game/ThreatManager.cpp35
-rw-r--r--src/game/ThreatManager.h8
-rw-r--r--src/game/Totem.cpp24
-rw-r--r--src/game/Totem.h4
-rw-r--r--src/game/TotemAI.cpp15
-rw-r--r--src/game/Transports.cpp19
-rw-r--r--src/game/Transports.h12
-rw-r--r--src/game/Traveller.h8
-rw-r--r--src/game/Unit.cpp6074
-rw-r--r--src/game/Unit.h261
-rw-r--r--src/game/UpdateData.cpp2
-rw-r--r--src/game/UpdateData.h5
-rw-r--r--src/game/UpdateFields.h531
-rw-r--r--src/game/UpdateMask.h28
-rw-r--r--src/game/Vehicle.cpp102
-rw-r--r--src/game/Vehicle.h58
-rw-r--r--src/game/WaypointManager.cpp2
-rw-r--r--src/game/WaypointMovementGenerator.h4
-rw-r--r--src/game/Weather.cpp2
-rw-r--r--src/game/Weather.h2
-rw-r--r--src/game/World.cpp160
-rw-r--r--src/game/World.h22
-rw-r--r--src/game/WorldLog.h4
-rw-r--r--src/game/WorldSession.cpp94
-rw-r--r--src/game/WorldSession.h54
-rw-r--r--src/game/WorldSocket.cpp198
-rw-r--r--src/game/WorldSocket.h20
-rw-r--r--src/game/debugcmds.cpp77
159 files changed, 19024 insertions, 11618 deletions
diff --git a/src/game/AccountMgr.cpp b/src/game/AccountMgr.cpp
index adf47f8acab..fd112e6c18e 100644
--- a/src/game/AccountMgr.cpp
+++ b/src/game/AccountMgr.cpp
@@ -25,11 +25,7 @@
#include "Policies/SingletonImp.h"
#include "Util.h"
-#ifdef DO_POSTGRESQL
-extern DatabasePostgre LoginDatabase;
-#else
-extern DatabaseMysql LoginDatabase;
-#endif
+extern DatabaseType LoginDatabase;
INSTANTIATE_SINGLETON_1(AccountMgr);
diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp
new file mode 100644
index 00000000000..1a68eae772a
--- /dev/null
+++ b/src/game/AchievementMgr.cpp
@@ -0,0 +1,1145 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "AchievementMgr.h"
+#include "Common.h"
+#include "Player.h"
+#include "WorldPacket.h"
+#include "Database/DBCEnums.h"
+#include "ObjectMgr.h"
+#include "Guild.h"
+#include "Database/DatabaseEnv.h"
+#include "GameEvent.h"
+#include "World.h"
+#include "SpellMgr.h"
+#include "ProgressBar.h"
+
+#include "Policies/SingletonImp.h"
+
+INSTANTIATE_SINGLETON_1(AchievementGlobalMgr);
+
+const CriteriaCastSpellRequirement AchievementGlobalMgr::m_criteriaCastSpellRequirements[CRITERIA_CAST_SPELL_REQ_COUNT] =
+ {
+ {5272, 3057, 0, 0},
+ {5273, 2784, 0, 0},
+ {5752, 9099, 0, 0},
+ {5753, 8403, 0, 0},
+ {5772, 0, 0, RACE_GNOME},
+ {5774, 0, 0, RACE_BLOODELF},
+ {5775, 0, 0, RACE_DRAENEI},
+ {5776, 0, 0, RACE_DWARF},
+ {5777, 0, 0, RACE_HUMAN},
+ {5778, 0, 0, RACE_NIGHTELF},
+ {5779, 0, 0, RACE_ORC},
+ {5780, 0, 0, RACE_TAUREN},
+ {5781, 0, 0, RACE_TROLL},
+ {5782, 0, 0, RACE_UNDEAD_PLAYER},
+ {6225, 5661, 0, 0},
+ {6226, 26044, 0, 0},
+ {6228, 739, 0, 0},
+ {6229, 927, 0, 0},
+ {6230, 1444, 0, 0},
+ {6231, 8140, 0, 0},
+ {6232, 5489, 0, 0},
+ {6233,12336, 0, 0},
+ {6234, 1351, 0, 0},
+ {6235, 5484, 0, 0},
+ {6236, 1182, 0, 0},
+ {6237, 0, CLASS_DEATH_KNIGHT, RACE_ORC},
+ {6238, 0, CLASS_WARRIOR, RACE_HUMAN},
+ {6239, 0, CLASS_SHAMAN, RACE_TAUREN},
+ {6240, 0, CLASS_DRUID, RACE_NIGHTELF},
+ {6241, 0, CLASS_ROGUE, RACE_UNDEAD_PLAYER},
+ {6242, 0, CLASS_HUNTER, RACE_TROLL},
+ {6243, 0, CLASS_MAGE, RACE_GNOME},
+ {6244, 0, CLASS_PALADIN, RACE_DWARF},
+ {6245, 0, CLASS_WARLOCK, RACE_BLOODELF},
+ {6246, 0, CLASS_PRIEST, RACE_DRAENEI},
+ {6312, 0, CLASS_WARLOCK, RACE_GNOME},
+ {6313, 0, CLASS_DEATH_KNIGHT, RACE_HUMAN},
+ {6314, 0, CLASS_PRIEST, RACE_NIGHTELF},
+ {6315, 0, CLASS_SHAMAN, RACE_ORC},
+ {6316, 0, CLASS_DRUID, RACE_TAUREN},
+ {6317, 0, CLASS_ROGUE, RACE_TROLL},
+ {6318, 0, CLASS_WARRIOR, RACE_UNDEAD_PLAYER},
+ {6319, 0, CLASS_MAGE, RACE_BLOODELF},
+ {6320, 0, CLASS_PALADIN, RACE_DRAENEI},
+ {6321, 0, CLASS_HUNTER, RACE_DWARF},
+ {6662, 31261, 0, 0}
+ };
+
+AchievementMgr::AchievementMgr(Player *player)
+{
+ m_player = player;
+}
+
+AchievementMgr::~AchievementMgr()
+{
+}
+
+void AchievementMgr::SaveToDB()
+{
+ if(!m_completedAchievements.empty())
+ {
+ bool need_execute = false;
+ std::ostringstream ssdel;
+ std::ostringstream ssins;
+ for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); iter++)
+ {
+ if(!iter->second.changed)
+ continue;
+
+ /// first new/changed record prefix
+ if(!need_execute)
+ {
+ ssdel << "DELETE FROM character_achievement WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND achievement IN (";
+ ssins << "INSERT INTO character_achievement (guid, achievement, date) VALUES ";
+ need_execute = true;
+ }
+ /// next new/changed record prefix
+ else
+ {
+ ssdel << ", ";
+ ssins << ", ";
+ }
+
+ // new/changed record data
+ ssdel << iter->first;
+ ssins << "("<<GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << uint64(iter->second.date) << ")";
+
+ /// mark as saved in db
+ iter->second.changed = false;
+ }
+
+ if(need_execute)
+ ssdel << ")";
+
+ if(need_execute)
+ {
+ CharacterDatabase.BeginTransaction ();
+ CharacterDatabase.Execute( ssdel.str().c_str() );
+ CharacterDatabase.Execute( ssins.str().c_str() );
+ CharacterDatabase.CommitTransaction ();
+ }
+ }
+
+ if(!m_criteriaProgress.empty())
+ {
+ /// prepare deleting and insert
+ bool need_execute_del = false;
+ bool need_execute_ins = false;
+ std::ostringstream ssdel;
+ std::ostringstream ssins;
+ for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
+ {
+ if(!iter->second.changed)
+ continue;
+
+ // deleted data (including 0 progress state)
+ {
+ /// first new/changed record prefix (for any counter value)
+ if(!need_execute_del)
+ {
+ ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND criteria IN (";
+ need_execute_del = true;
+ }
+ /// next new/changed record prefix
+ else
+ ssdel << ", ";
+
+ // new/changed record data
+ ssdel << iter->first;
+ }
+
+ // store data only for real progress
+ if(iter->second.counter != 0)
+ {
+ /// first new/changed record prefix
+ if(!need_execute_ins)
+ {
+ ssins << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES ";
+ need_execute_ins = true;
+ }
+ /// next new/changed record prefix
+ else
+ ssins << ", ";
+
+ // new/changed record data
+ ssins << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second.counter << ", " << iter->second.date << ")";
+ }
+
+ /// mark as updated in db
+ iter->second.changed = false;
+ }
+
+ if(need_execute_del) // DELETE ... IN (.... _)_
+ ssdel << ")";
+
+ if(need_execute_del || need_execute_ins)
+ {
+ CharacterDatabase.BeginTransaction ();
+ if(need_execute_del)
+ CharacterDatabase.Execute( ssdel.str().c_str() );
+ if(need_execute_ins)
+ CharacterDatabase.Execute( ssins.str().c_str() );
+ CharacterDatabase.CommitTransaction ();
+ }
+ }
+}
+
+void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult)
+{
+ if(achievementResult)
+ {
+ do
+ {
+ Field *fields = achievementResult->Fetch();
+ CompletedAchievementData& ca = m_completedAchievements[fields[0].GetUInt32()];
+ ca.date = time_t(fields[1].GetUInt64());
+ ca.changed = false;
+ } while(achievementResult->NextRow());
+ delete achievementResult;
+ }
+
+ if(criteriaResult)
+ {
+ do
+ {
+ Field *fields = criteriaResult->Fetch();
+
+ uint32 id = fields[0].GetUInt32();
+ uint32 counter = fields[1].GetUInt32();
+ time_t date = time_t(fields[2].GetUInt64());
+
+ AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(id);
+ if(!criteria || criteria->timeLimit && date + criteria->timeLimit < time(NULL))
+ continue;
+
+ CriteriaProgress& progress = m_criteriaProgress[id];
+ progress.counter = counter;
+ progress.date = date;
+ progress.changed = false;
+ } while(criteriaResult->NextRow());
+ delete criteriaResult;
+ }
+
+}
+
+void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
+{
+ sLog.outString("AchievementMgr::SendAchievementEarned(%u)", achievement->ID);
+
+ const char *msg = "|Hplayer:$N|h[$N]|h has earned the achievement $a!";
+ if(Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()))
+ {
+ WorldPacket data(SMSG_MESSAGECHAT, 200);
+ data << uint8(CHAT_MSG_GUILD_ACHIEVEMENT);
+ data << uint32(LANG_UNIVERSAL);
+ data << uint64(GetPlayer()->GetGUID());
+ data << uint32(5);
+ data << uint64(GetPlayer()->GetGUID());
+ data << uint32(strlen(msg)+1);
+ data << msg;
+ data << uint8(0);
+ data << uint32(achievement->ID);
+ guild->BroadcastPacket(&data);
+ }
+ if(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL|ACHIEVEMENT_FLAG_REALM_FIRST_REACH))
+ {
+ // broadcast realm first reached
+ WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, strlen(GetPlayer()->GetName())+1+8+4+4);
+ data << GetPlayer()->GetName();
+ data << uint64(GetPlayer()->GetGUID());
+ data << uint32(achievement->ID);
+ data << uint32(0); // 1=link supplied string as player name, 0=display plain string
+ sWorld.SendGlobalMessage(&data);
+ }
+ else
+ {
+ WorldPacket data(SMSG_MESSAGECHAT, 200);
+ data << uint8(CHAT_MSG_ACHIEVEMENT);
+ data << uint32(LANG_UNIVERSAL);
+ data << uint64(GetPlayer()->GetGUID());
+ data << uint32(5);
+ data << uint64(GetPlayer()->GetGUID());
+ data << uint32(strlen(msg)+1);
+ data << msg;
+ data << uint8(0);
+ data << uint32(achievement->ID);
+ GetPlayer()->SendMessageToSet(&data, true);
+
+ }
+ WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8);
+ data.append(GetPlayer()->GetPackGUID());
+ data << uint32(achievement->ID);
+ data << uint32(secsToTimeBitFields(time(NULL)));
+ data << uint32(0);
+ GetPlayer()->SendMessageToSet(&data, true);
+}
+
+void AchievementMgr::SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress)
+{
+ WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8);
+ data << uint32(id);
+
+ // the counter is packed like a packed Guid
+ data.appendPackGUID(progress->counter);
+
+ data.append(GetPlayer()->GetPackGUID());
+ data << uint32(0);
+ data << uint32(secsToTimeBitFields(progress->date));
+ data << uint32(0); // timer 1
+ data << uint32(0); // timer 2
+ GetPlayer()->SendMessageToSet(&data, true);
+}
+
+/**
+ * called at player login. The player might have fulfilled some achievements when the achievement system wasn't working yet
+ */
+void AchievementMgr::CheckAllAchievementCriteria()
+{
+ // suppress sending packets
+ for(uint32 i=0; i<ACHIEVEMENT_CRITERIA_TYPE_TOTAL; i++)
+ UpdateAchievementCriteria(AchievementCriteriaTypes(i));
+}
+
+/**
+ * this function will be called whenever the user might have done a criteria relevant action
+ */
+void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time)
+{
+ sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time);
+
+ if (!sWorld.getConfig(CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS) && m_player->GetSession()->GetSecurity() > SEC_PLAYER)
+ return;
+
+ AchievementCriteriaEntryList const& achievementCriteriaList = achievementmgr.GetAchievementCriteriaByType(type);
+ for(AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i!=achievementCriteriaList.end(); ++i)
+ {
+ AchievementCriteriaEntry const *achievementCriteria = (*i);
+
+ // don't update already completed criteria
+ if(IsCompletedCriteria(achievementCriteria))
+ continue;
+
+ if(achievementCriteria->groupFlag & ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP && GetPlayer()->GetGroup())
+ continue;
+
+ AchievementEntry const *achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement);
+ if(!achievement)
+ continue;
+
+ if(achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_HORDE && GetPlayer()->GetTeam() != HORDE ||
+ achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_ALLIANCE && GetPlayer()->GetTeam() != ALLIANCE)
+ continue;
+
+ switch (type)
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel());
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
+ SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
+ if(!miscvalue1)
+ continue;
+ if(achievementCriteria->kill_creature.creatureID != miscvalue1)
+ continue;
+ SetCriteriaProgress(achievementCriteria, miscvalue2, true);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ if(uint32 skillvalue = GetPlayer()->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID))
+ SetCriteriaProgress(achievementCriteria, skillvalue);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ {
+ uint32 counter =0;
+ for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++)
+ if(itr->second.m_rewarded)
+ counter++;
+ SetCriteriaProgress(achievementCriteria, counter);
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ {
+ uint32 counter =0;
+ for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++)
+ {
+ Quest const* quest = objmgr.GetQuestTemplate(itr->first);
+ if(itr->second.m_rewarded && quest->GetZoneOrSort() == achievementCriteria->complete_quests_in_zone.zoneID)
+ counter++;
+ }
+ SetCriteriaProgress(achievementCriteria, counter);
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
+ if(!miscvalue1)
+ continue;
+ SetCriteriaProgress(achievementCriteria, miscvalue1, true);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
+ if(!miscvalue1)
+ continue;
+ if(GetPlayer()->GetMapId() != achievementCriteria->complete_battleground.mapID)
+ continue;
+ SetCriteriaProgress(achievementCriteria, miscvalue1, true);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
+ if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID))
+ SetCriteriaProgress(achievementCriteria, 1);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ if(m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end())
+ SetCriteriaProgress(achievementCriteria, 1);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
+ if(!miscvalue1)
+ continue;
+ if(GetPlayer()->GetMapId() != achievementCriteria->death_at_map.mapID)
+ continue;
+ SetCriteriaProgress(achievementCriteria, 1, true);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
+ if(!miscvalue1)
+ continue;
+ if(miscvalue1 != achievementCriteria->killed_by_creature.creatureEntry)
+ continue;
+ SetCriteriaProgress(achievementCriteria, 1, true);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
+ if(!miscvalue1)
+ continue;
+ SetCriteriaProgress(achievementCriteria, 1, true);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ {
+ // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
+ if(!miscvalue1)
+ continue;
+ if(achievement->ID == 1260)
+ {
+ if(Player::GetDrunkenstateByValue(GetPlayer()->GetDrunkValue()) != DRUNKEN_SMASHED)
+ continue;
+ // TODO: hardcoding eventid is bad, it can differ from DB to DB - maye implement something using HolidayNames.dbc?
+ if(!gameeventmgr.IsActiveEvent(26))
+ continue;
+ }
+ // miscvalue1 is the ingame fallheight*100 as stored in dbc
+ SetCriteriaProgress(achievementCriteria, miscvalue1);
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
+ if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID))
+ SetCriteriaProgress(achievementCriteria, 1);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
+ if(!miscvalue1)
+ continue;
+ if(achievementCriteria->use_item.itemID != miscvalue1)
+ continue;
+ SetCriteriaProgress(achievementCriteria, 1, true);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ // speedup for non-login case
+ if(miscvalue1 && achievementCriteria->own_item.itemID!=miscvalue1)
+ continue;
+ SetCriteriaProgress(achievementCriteria, GetPlayer()->GetItemCount(achievementCriteria->own_item.itemID, true));
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ // You _have_ to loot that item, just owning it when logging in does _not_ count!
+ if(!miscvalue1)
+ continue;
+ if(miscvalue1 != achievementCriteria->own_item.itemID)
+ continue;
+ SetCriteriaProgress(achievementCriteria, miscvalue2, true);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ if (!miscvalue1 || miscvalue1 != achievementCriteria->be_spell_target.spellID)
+ continue;
+ SetCriteriaProgress(achievementCriteria, 1, true);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID)
+ continue;
+ SetCriteriaProgress(achievementCriteria, 1, true);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ {
+ if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID)
+ continue;
+
+ // those requirements couldn't be found in the dbc
+ if (CriteriaCastSpellRequirement const* requirement = AchievementGlobalMgr::GetCriteriaCastSpellRequirement(achievementCriteria))
+ {
+ if (!unit)
+ continue;
+
+ if (requirement->creatureEntry && unit->GetEntry() != requirement->creatureEntry)
+ continue;
+
+ if (requirement->playerRace && (unit->GetTypeId() != TYPEID_PLAYER || unit->getRace()!=requirement->playerRace))
+ continue;
+
+ if (requirement->playerClass && (unit->GetTypeId() != TYPEID_PLAYER || unit->getClass()!=requirement->playerClass))
+ continue;
+ }
+
+ SetCriteriaProgress(achievementCriteria, 1, true);
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ {
+ uint32 spellCount = 0;
+ for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin();
+ spellIter != GetPlayer()->GetSpellMap().end();
+ spellIter++)
+ {
+ for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first);
+ skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first);
+ skillIter++)
+ {
+ if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine)
+ spellCount++;
+ }
+ }
+ SetCriteriaProgress(achievementCriteria, spellCount);
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ {
+ // skip for login case
+ if(!miscvalue1)
+ continue;
+ SetCriteriaProgress(achievementCriteria, 1);
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
+ {
+ int32 reputation = GetPlayer()->GetReputation(achievementCriteria->gain_reputation.factionID);
+ if (reputation > 0)
+ SetCriteriaProgress(achievementCriteria, reputation);
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ {
+ uint32 counter = 0;
+ const FactionStateList factionStateList = GetPlayer()->GetFactionStateList();
+ for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); iter++)
+ {
+ if(GetPlayer()->ReputationToRank(iter->second.Standing) >= REP_EXALTED)
+ ++counter;
+ }
+ SetCriteriaProgress(achievementCriteria, counter);
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ {
+ WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference);
+ if(!worldOverlayEntry)
+ break;
+
+ int32 exploreFlag = GetAreaFlagByAreaID(worldOverlayEntry->areatableID);
+ if(exploreFlag < 0)
+ break;
+
+ uint32 playerIndexOffset = uint32(exploreFlag) / 32;
+ uint32 mask = 1<< (uint32(exploreFlag) % 32);
+
+ if(GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
+ SetCriteriaProgress(achievementCriteria, 1);
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ {
+ // miscvalue1 = itemid
+ // miscvalue2 = diced value
+ if(!miscvalue1)
+ continue;
+ if(miscvalue2 != achievementCriteria->roll_greed_on_loot.rollValue)
+ continue;
+ ItemPrototype const *pProto = objmgr.GetItemPrototype( miscvalue1 );
+
+ uint32 requiredItemLevel = 0;
+ if (achievementCriteria->ID == 2412 || achievementCriteria->ID == 2358)
+ requiredItemLevel = 185;
+
+ if(!pProto || pProto->ItemLevel <requiredItemLevel)
+ continue;
+ SetCriteriaProgress(achievementCriteria, 1, true);
+ break;
+ }
+ }
+ if(IsCompletedCriteria(achievementCriteria))
+ CompletedCriteria(achievementCriteria);
+ }
+}
+
+bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria)
+{
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement);
+ if(!achievement)
+ return false;
+
+ // counter can never complete
+ if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER)
+ return false;
+
+ if(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
+ {
+ // someone on this realm has already completed that achievement
+ if(achievementmgr.IsRealmCompleted(achievement))
+ return false;
+ }
+
+ CriteriaProgressMap::const_iterator itr = m_criteriaProgress.find(achievementCriteria->ID);
+ if(itr == m_criteriaProgress.end())
+ return false;
+
+ CriteriaProgress const* progress = &itr->second;
+
+ switch(achievementCriteria->requiredType)
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ if(achievement->ID == 467 && GetPlayer()->getClass() != CLASS_SHAMAN ||
+ achievement->ID == 466 && GetPlayer()->getClass() != CLASS_DRUID ||
+ achievement->ID == 465 && GetPlayer()->getClass() != CLASS_PALADIN ||
+ achievement->ID == 464 && GetPlayer()->getClass() != CLASS_PRIEST ||
+ achievement->ID == 463 && GetPlayer()->getClass() != CLASS_WARLOCK ||
+ achievement->ID == 462 && GetPlayer()->getClass() != CLASS_HUNTER ||
+ achievement->ID == 461 && GetPlayer()->getClass() != CLASS_DEATH_KNIGHT ||
+ achievement->ID == 460 && GetPlayer()->getClass() != CLASS_MAGE ||
+ achievement->ID == 459 && GetPlayer()->getClass() != CLASS_WARRIOR ||
+ achievement->ID == 458 && GetPlayer()->getClass() != CLASS_ROGUE ||
+
+ achievement->ID == 1404 && GetPlayer()->getRace() != RACE_GNOME ||
+ achievement->ID == 1405 && GetPlayer()->getRace() != RACE_BLOODELF ||
+ achievement->ID == 1406 && GetPlayer()->getRace() != RACE_DRAENEI ||
+ achievement->ID == 1407 && GetPlayer()->getRace() != RACE_DWARF ||
+ achievement->ID == 1408 && GetPlayer()->getRace() != RACE_HUMAN ||
+ achievement->ID == 1409 && GetPlayer()->getRace() != RACE_NIGHTELF ||
+ achievement->ID == 1410 && GetPlayer()->getRace() != RACE_ORC ||
+ achievement->ID == 1411 && GetPlayer()->getRace() != RACE_TAUREN ||
+ achievement->ID == 1412 && GetPlayer()->getRace() != RACE_TROLL ||
+ achievement->ID == 1413 && GetPlayer()->getRace() != RACE_UNDEAD_PLAYER )
+ return false;
+ return progress->counter >= achievementCriteria->reach_level.level;
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
+ return progress->counter >= achievementCriteria->buy_bank_slot.numberOfSlots;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ return progress->counter >= achievementCriteria->kill_creature.creatureCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ return progress->counter >= 1;
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ return progress->counter >= achievementCriteria->reach_skill_level.skillLevel;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ return progress->counter >= achievementCriteria->complete_quest_count.totalQuestCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ return progress->counter >= achievementCriteria->complete_quests_in_zone.questCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ return progress->counter >= achievementCriteria->complete_daily_quest.questCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
+ return progress->counter >= 1;
+ case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ return progress->counter >= achievementCriteria->fall_without_dying.fallHeight;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
+ return progress->counter >= 1;
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ return progress->counter >= achievementCriteria->use_item.itemCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ return progress->counter >= achievementCriteria->own_item.itemCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ return progress->counter >= achievementCriteria->loot_item.itemCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ return progress->counter >= achievementCriteria->be_spell_target.spellCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ return progress->counter >= achievementCriteria->cast_spell.castCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ return progress->counter >= achievementCriteria->visit_barber.numberOfVisits;
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
+ return progress->counter >= achievementCriteria->gain_reputation.reputationAmount;
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ return progress->counter >= achievementCriteria->gain_exalted_reputation.numberOfExaltedFactions;
+ case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ return progress->counter >= 1;
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ return progress->counter >= achievementCriteria->roll_greed_on_loot.count;
+
+ // handle all statistic-only criteria here
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ return false;
+ }
+ return false;
+}
+
+void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria)
+{
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement);
+ if(!achievement)
+ return;
+ // counter can never complete
+ if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER)
+ return;
+
+ if(criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL || GetAchievementCompletionState(achievement)==ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED)
+ {
+ CompletedAchievement(achievement);
+ }
+}
+
+// TODO: achievement 705 requires 4 criteria to be fulfilled
+AchievementCompletionState AchievementMgr::GetAchievementCompletionState(AchievementEntry const* entry)
+{
+ if(m_completedAchievements.find(entry->ID)!=m_completedAchievements.end())
+ return ACHIEVEMENT_COMPLETED_COMPLETED_STORED;
+
+ bool foundOutstanding = false;
+ for (uint32 entryId = 0; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++)
+ {
+ AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId);
+ if(!criteria || criteria->referredAchievement!= entry->ID)
+ continue;
+
+ if(IsCompletedCriteria(criteria) && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL)
+ return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED;
+
+ // found an umcompleted criteria, but DONT return false yet - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL
+ if(!IsCompletedCriteria(criteria))
+ foundOutstanding = true;
+ }
+ if(foundOutstanding)
+ return ACHIEVEMENT_COMPLETED_NONE;
+ else
+ return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED;
+}
+
+void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative)
+{
+ sLog.outDetail("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue);
+ CriteriaProgress *progress = NULL;
+
+ CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID);
+
+ if(iter == m_criteriaProgress.end())
+ {
+ // not create record for 0 counter
+ if(newValue == 0)
+ return;
+
+ progress = &m_criteriaProgress[entry->ID];
+ progress->counter = newValue;
+ progress->date = time(NULL);
+ }
+ else
+ {
+ progress = &iter->second;
+ if(relative)
+ newValue += progress->counter;
+
+ // not update (not mark as changed) if counter will have same value
+ if(progress->counter == newValue)
+ return;
+
+ progress->counter = newValue;
+ }
+
+ progress->changed = true;
+
+ if(entry->timeLimit)
+ {
+ time_t now = time(NULL);
+ if(progress->date + entry->timeLimit < now)
+ {
+ progress->counter = 1;
+ }
+ // also it seems illogical, the timeframe will be extended at every criteria update
+ progress->date = now;
+ }
+ SendCriteriaUpdate(entry->ID,progress);
+}
+
+void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
+{
+ sLog.outDetail("AchievementMgr::CompletedAchievement(%u)", achievement->ID);
+ if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER || m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end())
+ return;
+
+ SendAchievementEarned(achievement);
+ CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
+ ca.date = time(NULL);
+ ca.changed = true;
+
+ // don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement
+ // TODO: where do set this instead?
+ if(!(achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
+ achievementmgr.SetRealmCompleted(achievement);
+
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT);
+
+ // reward items and titles if any
+ AchievementReward const* reward = achievementmgr.GetAchievementReward(achievement);
+
+ // no rewards
+ if(!reward)
+ return;
+
+ // titles
+ if(uint32 titleId = reward->titleId[GetPlayer()->GetTeam() == HORDE?0:1])
+ {
+ if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId))
+ GetPlayer()->SetTitle(titleEntry);
+ }
+
+ // mail
+ if(reward->sender)
+ {
+ Item* item = reward->itemId ? Item::CreateItem(reward->itemId,1,GetPlayer ()) : NULL;
+
+ MailItemsInfo mi;
+ if(item)
+ {
+ // save new item before send
+ item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
+
+ // item
+ mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item);
+ }
+
+ int loc_idx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex();
+
+ // subject and text
+ std::string subject = reward->subject;
+ std::string text = reward->text;
+ if ( loc_idx >= 0 )
+ {
+ if(AchievementRewardLocale const* loc = achievementmgr.GetAchievementRewardLocale(achievement))
+ {
+ if (loc->subject.size() > size_t(loc_idx) && !loc->subject[loc_idx].empty())
+ subject = loc->subject[loc_idx];
+ if (loc->text.size() > size_t(loc_idx) && !loc->text[loc_idx].empty())
+ text = loc->text[loc_idx];
+ }
+ }
+
+ uint32 itemTextId = objmgr.CreateItemText( text );
+
+ WorldSession::SendMailTo(GetPlayer(), MAIL_CREATURE, MAIL_STATIONERY_NORMAL, reward->sender, GetPlayer()->GetGUIDLow(), subject, itemTextId , &mi, 0, 0, MAIL_CHECK_MASK_NONE);
+ }
+}
+
+void AchievementMgr::SendAllAchievementData()
+{
+ // since we don't know the exact size of the packed GUIDs this is just an approximation
+ WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, 4*2+m_completedAchievements.size()*4*2+m_completedAchievements.size()*7*4);
+ BuildAllDataPacket(&data);
+ GetPlayer()->GetSession()->SendPacket(&data);
+}
+
+void AchievementMgr::SendRespondInspectAchievements(Player* player)
+{
+ // since we don't know the exact size of the packed GUIDs this is just an approximation
+ WorldPacket data(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, 4+4*2+m_completedAchievements.size()*4*2+m_completedAchievements.size()*7*4);
+ data.append(GetPlayer()->GetPackGUID());
+ BuildAllDataPacket(&data);
+ player->GetSession()->SendPacket(&data);
+}
+
+/**
+ * used by both SMSG_ALL_ACHIEVEMENT_DATA and SMSG_RESPOND_INSPECT_ACHIEVEMENT
+ */
+void AchievementMgr::BuildAllDataPacket(WorldPacket *data)
+{
+ for(CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter)
+ {
+ *data << uint32(iter->first);
+ *data << uint32(secsToTimeBitFields(iter->second.date));
+ }
+ *data << int32(-1);
+
+ for(CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
+ {
+ *data << uint32(iter->first);
+ data->appendPackGUID(iter->second.counter);
+ data->append(GetPlayer()->GetPackGUID());
+ *data << uint32(0);
+ *data << uint32(secsToTimeBitFields(iter->second.date));
+ *data << uint32(0);
+ *data << uint32(0);
+ }
+
+ *data << int32(-1);
+}
+
+//==========================================================
+AchievementCriteriaEntryList const& AchievementGlobalMgr::GetAchievementCriteriaByType(AchievementCriteriaTypes type)
+{
+ return m_AchievementCriteriasByType[type];
+}
+
+void AchievementGlobalMgr::LoadAchievementCriteriaList()
+{
+ if(sAchievementCriteriaStore.GetNumRows()==0)
+ {
+ barGoLink bar(1);
+ bar.step();
+
+ sLog.outString("");
+ sLog.outErrorDb(">> Loaded 0 achievement criteria.");
+ return;
+ }
+
+ barGoLink bar( sAchievementCriteriaStore.GetNumRows() );
+ for (uint32 entryId = 0; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++)
+ {
+ bar.step();
+
+ AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId);
+ if(!criteria)
+ continue;
+
+ m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria);
+ }
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u achievement criteria.",m_AchievementCriteriasByType->size());
+}
+
+
+void AchievementGlobalMgr::LoadCompletedAchievements()
+{
+ QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement");
+
+ if(!result)
+ {
+ barGoLink bar(1);
+ bar.step();
+
+ sLog.outString("");
+ sLog.outString(">> Loaded 0 realm completed achievements . DB table `character_achievement` is empty.");
+ return;
+ }
+
+ barGoLink bar(result->GetRowCount());
+ do
+ {
+ bar.step();
+ Field *fields = result->Fetch();
+ m_allCompletedAchievements.insert(fields[0].GetUInt32());
+ } while(result->NextRow());
+
+ delete result;
+
+ sLog.outString("");
+ sLog.outString(">> Loaded %u realm completed achievements.",m_allCompletedAchievements.size());
+}
+
+void AchievementGlobalMgr::LoadRewards()
+{
+ m_achievementRewards.clear(); // need for reload case
+
+ // 0 1 2 3 4 5 6
+ QueryResult *result = WorldDatabase.Query("SELECT entry, title_A, title_H, item, sender, subject, text FROM achievement_reward");
+
+ if(!result)
+ {
+ barGoLink bar(1);
+
+ bar.step();
+
+ sLog.outString("");
+ sLog.outErrorDb(">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty.");
+ return;
+ }
+
+ barGoLink bar(result->GetRowCount());
+
+ do
+ {
+ bar.step();
+
+ Field *fields = result->Fetch();
+ uint32 entry = fields[0].GetUInt32();
+ if (!sAchievementStore.LookupEntry(entry))
+ {
+ sLog.outErrorDb( "Table `achievement_reward` has wrong achievement (Entry: %u), ignore", entry);
+ continue;
+ }
+
+ AchievementReward reward;
+ reward.titleId[0] = fields[1].GetUInt32();
+ reward.titleId[1] = fields[2].GetUInt32();
+ reward.itemId = fields[3].GetUInt32();
+ reward.sender = fields[4].GetUInt32();
+ reward.subject = fields[5].GetCppString();
+ reward.text = fields[6].GetCppString();
+
+ if ((reward.titleId[0]==0)!=(reward.titleId[1]==0))
+ sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has title (A: %u H: %u) only for one from teams.", entry, reward.titleId[0], reward.titleId[1]);
+
+ // must be title or mail at least
+ if (!reward.titleId[0] && !reward.titleId[1] && !reward.sender)
+ {
+ sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have title or item reward data, ignore.", entry);
+ continue;
+ }
+
+ if (reward.titleId[0])
+ {
+ CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.titleId[0]);
+ if (!titleEntry)
+ {
+ sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid title id (%u) in `title_A`, set to 0", entry, reward.titleId[0]);
+ reward.titleId[0] = 0;
+ }
+ }
+
+ if (reward.titleId[1])
+ {
+ CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.titleId[1]);
+ if (!titleEntry)
+ {
+ sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid title id (%u) in `title_A`, set to 0", entry, reward.titleId[1]);
+ reward.titleId[1] = 0;
+ }
+ }
+
+ //check mail data before item for report including wrong item case
+ if (reward.sender)
+ {
+ if (!objmgr.GetCreatureTemplate(reward.sender))
+ {
+ sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid creature entry %u as sender, mail reward skipped.", entry, reward.sender);
+ reward.sender = 0;
+ }
+ }
+ else
+ {
+ if (reward.itemId)
+ sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have item reward, item will not rewarded", entry);
+
+ if (!reward.subject.empty())
+ sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have mail subject.", entry);
+
+ if (!reward.text.empty())
+ sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have mail text.", entry);
+ }
+
+ if (reward.itemId)
+ {
+ if (!objmgr.GetItemPrototype(reward.itemId))
+ {
+ sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid item id %u, reward mail will be without item.", entry, reward.itemId);
+ reward.itemId = 0;
+ }
+ }
+
+ m_achievementRewards[entry] = reward;
+
+ } while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u achievement reward locale strings", m_achievementRewardLocales.size() );
+}
+
+void AchievementGlobalMgr::LoadRewardLocales()
+{
+ m_achievementRewardLocales.clear(); // need for reload case
+
+ QueryResult *result = WorldDatabase.Query("SELECT entry,subject_loc1,text_loc1,subject_loc2,text_loc2,subject_loc3,text_loc3,subject_loc4,text_loc4,subject_loc5,text_loc5,subject_loc6,text_loc6,subject_loc7,text_loc7,subject_loc8,text_loc8 FROM locales_achievement_reward");
+
+ if(!result)
+ {
+ barGoLink bar(1);
+
+ bar.step();
+
+ sLog.outString("");
+ sLog.outString(">> Loaded 0 achievement reward locale strings. DB table `locales_achievement_reward` is empty.");
+ return;
+ }
+
+ barGoLink bar(result->GetRowCount());
+
+ do
+ {
+ Field *fields = result->Fetch();
+ bar.step();
+
+ uint32 entry = fields[0].GetUInt32();
+
+ if(m_achievementRewards.find(entry)==m_achievementRewards.end())
+ {
+ sLog.outErrorDb( "Table `locales_achievement_reward` (Entry: %u) has locale strings for not existed achievement reward .", entry);
+ continue;
+ }
+
+ AchievementRewardLocale& data = m_achievementRewardLocales[entry];
+
+ for(int i = 1; i < MAX_LOCALE; ++i)
+ {
+ std::string str = fields[1+2*(i-1)].GetCppString();
+ if(!str.empty())
+ {
+ int idx = objmgr.GetOrNewIndexForLocale(LocaleConstant(i));
+ if(idx >= 0)
+ {
+ if(data.subject.size() <= idx)
+ data.subject.resize(idx+1);
+
+ data.subject[idx] = str;
+ }
+ }
+ str = fields[1+2*(i-1)+1].GetCppString();
+ if(!str.empty())
+ {
+ int idx = objmgr.GetOrNewIndexForLocale(LocaleConstant(i));
+ if(idx >= 0)
+ {
+ if(data.text.size() <= idx)
+ data.text.resize(idx+1);
+
+ data.text[idx] = str;
+ }
+ }
+ }
+ } while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u achievement reward locale strings", m_achievementRewardLocales.size() );
+}
diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h
new file mode 100644
index 00000000000..9b41cd7588c
--- /dev/null
+++ b/src/game/AchievementMgr.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __MANGOS_ACHIEVEMENTMGR_H
+#define __MANGOS_ACHIEVEMENTMGR_H
+
+#include "Common.h"
+#include "Policies/Singleton.h"
+#include "Database/DBCEnums.h"
+#include "Database/DBCStores.h"
+#include "Database/DatabaseEnv.h"
+
+#include <map>
+#include <string>
+
+#define CRITERIA_CAST_SPELL_REQ_COUNT 46
+#define ACHIEVEMENT_REWARD_COUNT 57
+
+typedef std::list<const AchievementCriteriaEntry*> AchievementCriteriaEntryList;
+
+struct CriteriaProgress
+{
+ uint32 counter;
+ time_t date;
+ bool changed;
+};
+
+struct CriteriaCastSpellRequirement
+{
+ uint32 achievementCriteriaId;
+ uint32 creatureEntry;
+ uint8 playerClass;
+ uint8 playerRace;
+};
+
+struct AchievementReward
+{
+ uint32 titleId[2];
+ uint32 itemId;
+ uint32 sender;
+ std::string subject;
+ std::string text;
+};
+
+typedef std::map<uint32,AchievementReward> AchievementRewards;
+
+struct AchievementRewardLocale
+{
+ std::vector<std::string> subject;
+ std::vector<std::string> text;
+};
+
+typedef std::map<uint32,AchievementRewardLocale> AchievementRewardLocales;
+
+
+struct CompletedAchievementData
+{
+ time_t date;
+ bool changed;
+};
+
+typedef UNORDERED_MAP<uint32, CriteriaProgress> CriteriaProgressMap;
+typedef UNORDERED_MAP<uint32, CompletedAchievementData> CompletedAchievementMap;
+
+class Unit;
+class Player;
+class WorldPacket;
+
+enum AchievementCompletionState
+{
+ ACHIEVEMENT_COMPLETED_NONE,
+ ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED,
+ ACHIEVEMENT_COMPLETED_COMPLETED_STORED,
+};
+
+class AchievementMgr
+{
+ public:
+ AchievementMgr(Player* pl);
+ ~AchievementMgr();
+
+ void LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult);
+ void SaveToDB();
+ void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0);
+ void CheckAllAchievementCriteria();
+ void SendAllAchievementData();
+ void SendRespondInspectAchievements(Player* player);
+ Player* GetPlayer() { return m_player;}
+
+ private:
+ void SendAchievementEarned(AchievementEntry const* achievement);
+ void SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress);
+ void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative=false);
+ void CompletedCriteria(AchievementCriteriaEntry const* entry);
+ void CompletedAchievement(AchievementEntry const* entry);
+ bool IsCompletedCriteria(AchievementCriteriaEntry const* entry);
+ AchievementCompletionState GetAchievementCompletionState(AchievementEntry const* entry);
+ void BuildAllDataPacket(WorldPacket *data);
+
+ Player* m_player;
+ CriteriaProgressMap m_criteriaProgress;
+ CompletedAchievementMap m_completedAchievements;
+};
+
+class AchievementGlobalMgr
+{
+ public:
+ AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type);
+
+ AchievementReward const* GetAchievementReward(AchievementEntry const* achievement) const
+ {
+ AchievementRewards::const_iterator iter = m_achievementRewards.find(achievement->ID);
+ return iter!=m_achievementRewards.end() ? &iter->second : NULL;
+ }
+
+ AchievementRewardLocale const* GetAchievementRewardLocale(AchievementEntry const* achievement) const
+ {
+ AchievementRewardLocales::const_iterator iter = m_achievementRewardLocales.find(achievement->ID);
+ return iter!=m_achievementRewardLocales.end() ? &iter->second : NULL;
+ }
+
+ static CriteriaCastSpellRequirement const * GetCriteriaCastSpellRequirement(AchievementCriteriaEntry const *achievementCriteria)
+ {
+ for (uint32 i=0; i < CRITERIA_CAST_SPELL_REQ_COUNT; ++i)
+ if (m_criteriaCastSpellRequirements[i].achievementCriteriaId == achievementCriteria->ID)
+ return &m_criteriaCastSpellRequirements[i];
+
+ return NULL;
+ }
+
+ bool IsRealmCompleted(AchievementEntry const* achievement) const
+ {
+ return m_allCompletedAchievements.find(achievement->ID) != m_allCompletedAchievements.end();
+ }
+
+ void SetRealmCompleted(AchievementEntry const* achievement)
+ {
+ m_allCompletedAchievements.insert(achievement->ID);
+ }
+
+ void LoadAchievementCriteriaList();
+ void LoadCompletedAchievements();
+ void LoadRewards();
+ void LoadRewardLocales();
+ private:
+ static const CriteriaCastSpellRequirement m_criteriaCastSpellRequirements[];
+
+ // store achievement criterias by type to speed up lookup
+ AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
+
+ typedef std::set<uint32> AllCompletedAchievements;
+ AllCompletedAchievements m_allCompletedAchievements;
+
+ AchievementRewards m_achievementRewards;
+ AchievementRewardLocales m_achievementRewardLocales;
+};
+
+#define achievementmgr Trinity::Singleton<AchievementGlobalMgr>::Instance()
+
+#endif
diff --git a/src/game/AddonHandler.cpp b/src/game/AddonHandler.cpp
index 74bb4d9d6bc..37fd719253f 100644
--- a/src/game/AddonHandler.cpp
+++ b/src/game/AddonHandler.cpp
@@ -66,63 +66,84 @@ bool AddonHandler::BuildAddonPacket(WorldPacket *Source, WorldPacket *Target)
if (Source->rpos() + 4 > Source->size())
return false;
- *Source >> TempValue; //get real size of the packed structure
+ *Source >> TempValue; // get real size of the packed structure
// empty addon packet, nothing process, can't be received from real client
if(!TempValue)
return false;
- AddonRealSize = TempValue; //temp value because ZLIB only excepts uLongf
+ AddonRealSize = TempValue; // temp value because ZLIB only excepts uLongf
- CurrentPosition = Source->rpos(); //get the position of the pointer in the structure
+ CurrentPosition = Source->rpos(); // get the position of the pointer in the structure
- AddOnPacked.resize(AddonRealSize); //resize target for zlib action
+ AddOnPacked.resize(AddonRealSize); // resize target for zlib action
if (!uncompress(const_cast<uint8*>(AddOnPacked.contents()), &AddonRealSize, const_cast<uint8*>((*Source).contents() + CurrentPosition), (*Source).size() - CurrentPosition)!= Z_OK)
{
Target->Initialize(SMSG_ADDON_INFO);
- while(AddOnPacked.rpos() < AddOnPacked.size())
+ uint32 addonsCount;
+ AddOnPacked >> addonsCount; // addons count?
+
+ for(uint32 i = 0; i < addonsCount; ++i)
{
- std::string AddonNames;
- uint8 unk6;
- uint32 crc, unk7;
+ std::string addonName;
+ uint8 enabled;
+ uint32 crc, unk2;
// check next addon data format correctness
- if(AddOnPacked.rpos()+1+4+4+1 > AddOnPacked.size())
+ if(AddOnPacked.rpos()+1 > AddOnPacked.size())
return false;
- AddOnPacked >> AddonNames;
+ AddOnPacked >> addonName;
// recheck next addon data format correctness
- if(AddOnPacked.rpos()+4+4+1 > AddOnPacked.size())
+ if(AddOnPacked.rpos()+1+4+4 > AddOnPacked.size())
return false;
- AddOnPacked >> crc >> unk7 >> unk6;
+ AddOnPacked >> enabled >> crc >> unk2;
- //sLog.outDebug("ADDON: Name:%s CRC:%x Unknown1 :%x Unknown2 :%x", AddonNames.c_str(), crc, unk7, unk6);
+ sLog.outDebug("ADDON: Name: %s, Enabled: 0x%x, CRC: 0x%x, Unknown2: 0x%x", addonName.c_str(), enabled, crc, unk2);
- *Target << (uint8)2;
+ uint8 state = (enabled ? 2 : 1);
+ *Target << uint8(state);
- uint8 unk1 = 1;
- *Target << (uint8)unk1;
+ uint8 unk1 = (enabled ? 1 : 0);
+ *Target << uint8(unk1);
if (unk1)
{
- uint8 unk2 = crc != 0x1c776d01LL; //If addon is Standard addon CRC
- *Target << (uint8)unk2;
+ uint8 unk2 = (crc != 0x4c1c776d); // If addon is Standard addon CRC
+ *Target << uint8(unk2);
if (unk2)
Target->append(tdata, sizeof(tdata));
- *Target << (uint32)0;
+ *Target << uint32(0);
}
- uint8 unk3 = 0;
- *Target << (uint8)unk3;
+ uint8 unk3 = (enabled ? 0 : 1);
+ *Target << uint8(unk3);
if (unk3)
{
- // String, 256
+ // String, 256 (null terminated?)
+ *Target << uint8(0);
}
}
+
+ uint32 unk4;
+ AddOnPacked >> unk4;
+
+ uint32 count = 0;
+ *Target << uint32(count);
+ /*for(uint32 i = 0; i < count; ++i)
+ {
+ uint32
+ string (16 bytes)
+ string (16 bytes)
+ uint32
+ }*/
+
+ if(AddOnPacked.rpos() != AddOnPacked.size())
+ sLog.outDebug("packet under read!");
}
else
{
diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp
index 5f1dfdb93d7..3d7b9146b02 100644
--- a/src/game/ArenaTeam.cpp
+++ b/src/game/ArenaTeam.cpp
@@ -304,8 +304,11 @@ void ArenaTeam::Roster(WorldSession *session)
{
Player *pl = NULL;
+ uint8 unk308 = 0;
+
WorldPacket data(SMSG_ARENA_TEAM_ROSTER, 100);
data << uint32(GetId()); // arena team id
+ data << uint8(unk308); // 308 unknown value but affect packet structure
data << uint32(GetMembersSize()); // members count
data << uint32(GetType()); // arena team type?
@@ -313,18 +316,24 @@ void ArenaTeam::Roster(WorldSession *session)
{
pl = objmgr.GetPlayer(itr->guid);
- data << uint64(itr->guid); // guid
- data << uint8((pl ? 1 : 0)); // online flag
- data << itr->name; // member name
+ data << uint64(itr->guid); // guid
+ data << uint8((pl ? 1 : 0)); // online flag
+ data << itr->name; // member name
data << uint32((itr->guid == GetCaptain() ? 0 : 1));// captain flag 0 captain 1 member
- data << uint8((pl ? pl->getLevel() : 0)); // unknown, level?
- data << uint8(itr->Class); // class
- data << uint32(itr->games_week); // played this week
- data << uint32(itr->wins_week); // wins this week
- data << uint32(itr->games_season); // played this season
- data << uint32(itr->wins_season); // wins this season
- data << uint32(itr->personal_rating); // personal rating
+ data << uint8((pl ? pl->getLevel() : 0)); // unknown, level?
+ data << uint8(itr->Class); // class
+ data << uint32(itr->games_week); // played this week
+ data << uint32(itr->wins_week); // wins this week
+ data << uint32(itr->games_season); // played this season
+ data << uint32(itr->wins_season); // wins this season
+ data << uint32(itr->personal_rating); // personal rating
+ if(unk308)
+ {
+ data << float(0.0); // 308 unk
+ data << float(0.0); // 308 unk
+ }
}
+
session->SendPacket(&data);
sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_ROSTER");
}
diff --git a/src/game/ArenaTeamHandler.cpp b/src/game/ArenaTeamHandler.cpp
index d2c9f54d04b..69f8de2f797 100644
--- a/src/game/ArenaTeamHandler.cpp
+++ b/src/game/ArenaTeamHandler.cpp
@@ -173,7 +173,7 @@ void WorldSession::HandleArenaTeamInviteAcceptOpcode(WorldPacket & /*recv_data*/
if(!at)
return;
- if(_player->GetArenaTeamIdFromDB(_player->GetGUIDLow(), at->GetType()))
+ if(_player->GetArenaTeamId(at->GetSlot()))
{
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ALREADY_IN_ARENA_TEAM); // already in arena team that size
return;
diff --git a/src/game/AuctionHouse.cpp b/src/game/AuctionHouse.cpp
index c200c9751a6..39aaa864bd2 100644
--- a/src/game/AuctionHouse.cpp
+++ b/src/game/AuctionHouse.cpp
@@ -756,3 +756,23 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
data << (uint32) 300; // unk 2.3.0 const?
SendPacket(&data);
}
+
+void WorldSession::HandleAuctionListPendingSales( WorldPacket & recv_data )
+{
+ sLog.outDebug("CMSG_AUCTION_LIST_PENDING_SALES");
+ recv_data.hexlike();
+
+ uint32 count = 0;
+
+ WorldPacket data(SMSG_AUCTION_LIST_PENDING_SALES, 4);
+ data << uint32(count); // count
+ /*for(uint32 i = 0; i < count; ++i)
+ {
+ data << ""; // string
+ data << ""; // string
+ data << uint32(0);
+ data << uint32(0);
+ data << float(0);
+ }*/
+ SendPacket(&data);
+}
diff --git a/src/game/AuctionHouseObject.h b/src/game/AuctionHouseObject.h
index cccba8413da..d7edfd5869b 100644
--- a/src/game/AuctionHouseObject.h
+++ b/src/game/AuctionHouseObject.h
@@ -84,20 +84,12 @@ class AuctionHouseObject
AuctionEntry* GetAuction(uint32 id) const
{
AuctionEntryMap::const_iterator itr = AuctionsMap.find( id );
- if( itr != AuctionsMap.end() )
- return itr->second;
- return NULL;
+ return itr != AuctionsMap.end() ? itr->second : NULL;
}
bool RemoveAuction(uint32 id)
{
- AuctionEntryMap::iterator i = AuctionsMap.find(id);
- if (i == AuctionsMap.end())
- {
- return false;
- }
- AuctionsMap.erase(i);
- return true;
+ return AuctionsMap.erase(id) ? true : false;
}
private:
diff --git a/src/game/Bag.cpp b/src/game/Bag.cpp
index 765d40f3962..5c870bdb2b7 100644
--- a/src/game/Bag.cpp
+++ b/src/game/Bag.cpp
@@ -34,7 +34,7 @@ Bag::Bag( ): Item()
m_valuesCount = CONTAINER_END;
- memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE); // Maximum 20 Slots
+ memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE);
}
Bag::~Bag()
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp
index d392f074600..c7f4df1de24 100644
--- a/src/game/BattleGround.cpp
+++ b/src/game/BattleGround.cpp
@@ -120,7 +120,7 @@ BattleGround::~BattleGround()
this->RemoveFromBGFreeSlotQueue();
}
-void BattleGround::Update(time_t diff)
+void BattleGround::Update(uint32 diff)
{
if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize())
//BG is empty
@@ -573,9 +573,10 @@ void BattleGround::EndBattleGround(uint32 winner)
sBattleGroundMgr.BuildPvpLogDataPacket(&data, this);
plr->GetSession()->SendPacket(&data);
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType());
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
plr->GetSession()->SendPacket(&data);
+ plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
}
if(isArena() && isRated() && winner_arena_team && loser_arena_team)
@@ -593,7 +594,7 @@ void BattleGround::EndBattleGround(uint32 winner)
}
// inform invited players about the removal
- sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
+ sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
if(Source)
{
@@ -789,7 +790,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
if(!team) team = plr->GetTeam();
uint32 bgTypeId = GetTypeID();
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType());
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
// if arena, remove the specific arena auras
if(isArena())
{
@@ -1178,7 +1179,8 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float
// and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
// so we must create it specific for this instance
GameObject * go = new GameObject;
- if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1))
+ if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,
+ PHASEMASK_NORMAL, x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1))
{
sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry);
sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry);
@@ -1301,7 +1303,7 @@ Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, f
return NULL;
Creature* pCreature = new Creature;
- if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, entry, teamval))
+ if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, PHASEMASK_NORMAL, entry, teamval))
{
sLog.outError("Can't create creature entry: %u",entry);
delete pCreature;
@@ -1405,10 +1407,10 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float
pCreature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pCreature->GetGUID());
// aura
- pCreature->SetUInt32Value(UNIT_FIELD_AURA, SPELL_SPIRIT_HEAL_CHANNEL);
- pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009);
- pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C);
- pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF);
+ pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
+ //pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009);
+ //pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C);
+ //pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF);
// casting visual effect
pCreature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL);
// correct cast speed
@@ -1440,7 +1442,7 @@ void BattleGround::EndNow()
SetStatus(STATUS_WAIT_LEAVE);
SetEndTime(TIME_TO_AUTOREMOVE);
// inform invited players about the removal
- sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
+ sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
}
// Battleground messages are localized using the dbc lang, they are not client language dependent
diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h
index 3c98afe6d17..ba3bcce1750 100644
--- a/src/game/BattleGround.h
+++ b/src/game/BattleGround.h
@@ -132,8 +132,6 @@ struct BattleGroundObjectInfo
uint32 spellid;
};
-#define MAX_QUEUED_PLAYERS_MAP 7
-
enum BattleGroundTypeId
{
BATTLEGROUND_AV = 1,
@@ -143,7 +141,10 @@ enum BattleGroundTypeId
BATTLEGROUND_BE = 5,
BATTLEGROUND_AA = 6,
BATTLEGROUND_EY = 7,
- BATTLEGROUND_RL = 8
+ BATTLEGROUND_RL = 8,
+ BATTLEGROUND_SA = 9,
+ BATTLEGROUND_DS = 10,
+ BATTLEGROUND_RV = 11
};
// handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time
@@ -153,9 +154,10 @@ enum BattleGroundQueueTypeId
BATTLEGROUND_QUEUE_WS = 2,
BATTLEGROUND_QUEUE_AB = 3,
BATTLEGROUND_QUEUE_EY = 4,
- BATTLEGROUND_QUEUE_2v2 = 5,
- BATTLEGROUND_QUEUE_3v3 = 6,
- BATTLEGROUND_QUEUE_5v5 = 7,
+ BATTLEGROUND_QUEUE_SA = 5,
+ BATTLEGROUND_QUEUE_2v2 = 6,
+ BATTLEGROUND_QUEUE_3v3 = 7,
+ BATTLEGROUND_QUEUE_5v5 = 8,
};
enum ScoreType
@@ -262,7 +264,7 @@ class BattleGround
BattleGround();
/*BattleGround(const BattleGround& bg);*/
virtual ~BattleGround();
- virtual void Update(time_t diff); // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version
+ virtual void Update(uint32 diff); // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version
virtual bool SetupBattleGround() // must be implemented in BG subclass
{
return true;
diff --git a/src/game/BattleGroundAA.cpp b/src/game/BattleGroundAA.cpp
index 8737088894a..63ae9f7c59a 100644
--- a/src/game/BattleGroundAA.cpp
+++ b/src/game/BattleGroundAA.cpp
@@ -32,7 +32,7 @@ BattleGroundAA::~BattleGroundAA()
}
-void BattleGroundAA::Update(time_t diff)
+void BattleGroundAA::Update(uint32 diff)
{
BattleGround::Update(diff);
}
diff --git a/src/game/BattleGroundAA.h b/src/game/BattleGroundAA.h
index edddc110600..955b74fd2f0 100644
--- a/src/game/BattleGroundAA.h
+++ b/src/game/BattleGroundAA.h
@@ -37,7 +37,7 @@ class BattleGroundAA : public BattleGround
public:
BattleGroundAA();
~BattleGroundAA();
- void Update(time_t diff);
+ void Update(uint32 diff);
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp
index 00e1090d8d5..0023c935db2 100644
--- a/src/game/BattleGroundAB.cpp
+++ b/src/game/BattleGroundAB.cpp
@@ -52,7 +52,7 @@ BattleGroundAB::~BattleGroundAB()
{
}
-void BattleGroundAB::Update(time_t diff)
+void BattleGroundAB::Update(uint32 diff)
{
BattleGround::Update(diff);
@@ -425,9 +425,9 @@ void BattleGroundAB::_NodeDeOccupied(uint8 node)
{
WorldSafeLocsEntry const *ClosestGrave = NULL;
Player *plr;
- for (std::vector<uint64>::iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr)
+ for (std::vector<uint64>::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr)
{
- plr = objmgr.GetPlayer(*ghost_list.begin());
+ plr = objmgr.GetPlayer(*itr);
if( !plr )
continue;
if( !ClosestGrave )
diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h
index 464108d63c9..fca7986bc24 100644
--- a/src/game/BattleGroundAB.h
+++ b/src/game/BattleGroundAB.h
@@ -238,7 +238,7 @@ class BattleGroundAB : public BattleGround
BattleGroundAB();
~BattleGroundAB();
- void Update(time_t diff);
+ void Update(uint32 diff);
void AddPlayer(Player *plr);
void RemovePlayer(Player *plr,uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp
index 6b892a0fa5d..bffe9d0e4ad 100644
--- a/src/game/BattleGroundAV.cpp
+++ b/src/game/BattleGroundAV.cpp
@@ -294,7 +294,7 @@ Creature* BattleGroundAV::AddAVCreature(uint16 cinfoid, uint16 type )
return creature;
}
-void BattleGroundAV::Update(time_t diff)
+void BattleGroundAV::Update(uint32 diff)
{
BattleGround::Update(diff);
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
diff --git a/src/game/BattleGroundAV.h b/src/game/BattleGroundAV.h
index e80ad47d869..f9343ddfcbc 100644
--- a/src/game/BattleGroundAV.h
+++ b/src/game/BattleGroundAV.h
@@ -1500,7 +1500,7 @@ class BattleGroundAV : public BattleGround
public:
BattleGroundAV();
~BattleGroundAV();
- void Update(time_t diff);
+ void Update(uint32 diff);
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp
index 6f4ac89c64e..604ca339680 100644
--- a/src/game/BattleGroundBE.cpp
+++ b/src/game/BattleGroundBE.cpp
@@ -37,7 +37,7 @@ BattleGroundBE::~BattleGroundBE()
}
-void BattleGroundBE::Update(time_t diff)
+void BattleGroundBE::Update(uint32 diff)
{
BattleGround::Update(diff);
diff --git a/src/game/BattleGroundBE.h b/src/game/BattleGroundBE.h
index a16464dd31b..6abf33eb8f2 100644
--- a/src/game/BattleGroundBE.h
+++ b/src/game/BattleGroundBE.h
@@ -57,7 +57,7 @@ class BattleGroundBE : public BattleGround
public:
BattleGroundBE();
~BattleGroundBE();
- void Update(time_t diff);
+ void Update(uint32 diff);
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
diff --git a/src/game/BattleGroundDS.cpp b/src/game/BattleGroundDS.cpp
new file mode 100644
index 00000000000..825a52967b6
--- /dev/null
+++ b/src/game/BattleGroundDS.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Player.h"
+#include "BattleGround.h"
+#include "BattleGroundDS.h"
+
+BattleGroundDS::BattleGroundDS()
+{
+
+}
+
+BattleGroundDS::~BattleGroundDS()
+{
+
+}
+
+void BattleGroundDS::Update(uint32 diff)
+{
+ BattleGround::Update(diff);
+}
+
+void BattleGroundDS::AddPlayer(Player *plr)
+{
+ BattleGround::AddPlayer(plr);
+ //create score and add it to map, default values are set in constructor
+ BattleGroundDSScore* sc = new BattleGroundDSScore;
+
+ m_PlayerScores[plr->GetGUID()] = sc;
+}
+
+void BattleGroundDS::RemovePlayer(Player * /*plr*/, uint64 /*guid*/)
+{
+}
+
+void BattleGroundDS::HandleKillPlayer(Player* player, Player* killer)
+{
+ BattleGround::HandleKillPlayer(player, killer);
+}
+
+void BattleGroundDS::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/)
+{
+}
+
+bool BattleGroundDS::SetupBattleGround()
+{
+ return true;
+}
diff --git a/src/game/BattleGroundDS.h b/src/game/BattleGroundDS.h
new file mode 100644
index 00000000000..7f9de8ca7de
--- /dev/null
+++ b/src/game/BattleGroundDS.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __BATTLEGROUNDDS_H
+#define __BATTLEGROUNDDS_H
+
+class BattleGround;
+
+class BattleGroundDSScore : public BattleGroundScore
+{
+ public:
+ BattleGroundDSScore() {};
+ virtual ~BattleGroundDSScore() {};
+ //TODO fix me
+};
+
+class BattleGroundDS : public BattleGround
+{
+ friend class BattleGroundMgr;
+
+ public:
+ BattleGroundDS();
+ ~BattleGroundDS();
+ void Update(uint32 diff);
+
+ /* inherited from BattlegroundClass */
+ virtual void AddPlayer(Player *plr);
+ void RemovePlayer(Player *plr, uint64 guid);
+ void HandleAreaTrigger(Player *Source, uint32 Trigger);
+ bool SetupBattleGround();
+ void HandleKillPlayer(Player* player, Player *killer);
+};
+#endif
diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp
index 1af6aaabf8b..9872a49125a 100644
--- a/src/game/BattleGroundEY.cpp
+++ b/src/game/BattleGroundEY.cpp
@@ -51,7 +51,7 @@ BattleGroundEY::~BattleGroundEY()
{
}
-void BattleGroundEY::Update(time_t diff)
+void BattleGroundEY::Update(uint32 diff)
{
BattleGround::Update(diff);
// after bg start we get there (once)
diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h
index 0152a889f30..f512112ba53 100644
--- a/src/game/BattleGroundEY.h
+++ b/src/game/BattleGroundEY.h
@@ -300,7 +300,7 @@ class BattleGroundEY : public BattleGround
public:
BattleGroundEY();
~BattleGroundEY();
- void Update(time_t diff);
+ void Update(uint32 diff);
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp
index fc99fe3f1fe..e725e4edf63 100644
--- a/src/game/BattleGroundHandler.cpp
+++ b/src/game/BattleGroundHandler.cpp
@@ -96,7 +96,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid);
// can do this, since it's battleground, not arena
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, 0);
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0);
// ignore if player is already in BG
if(_player->InBattleGround())
@@ -180,6 +180,8 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
}
sLog.outDebug("Battleground: group end");
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel());
+ if(!ginfo->IsInvitedToBGInstanceGUID)
+ sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
}
else
{
@@ -196,6 +198,8 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel());
+ if(!ginfo->IsInvitedToBGInstanceGUID)
+ sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());
}
}
@@ -366,7 +370,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
uint32 bgQueueTypeId = 0;
// get the bg what we were invited to
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus;
- bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId,type);
+ bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId,type);
itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end())
@@ -527,7 +531,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
BattleGround *bg = _player->GetBattleGround();
if(bg)
{
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);
if((bg->GetStatus() <= STATUS_IN_PROGRESS))
{
@@ -537,7 +541,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
uint32 queue_id = _player->GetBattleGroundQueueId(i); // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong
- uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id);
+ uint8 arenatype = BattleGroundMgr::BGArenaType(queue_id);
uint8 isRated = 0;
if (i == queueSlot || !queue_id) // we need to get the instance ids
continue;
@@ -549,7 +553,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
isRated = itrPlayerStatus->second.GroupInfo->IsRated;
}
- BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(sBattleGroundMgr.BGTemplateId(queue_id)); // try this
+ BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(BattleGroundMgr::BGTemplateId(queue_id)); // try this
if(bg2)
{
//in this call is small bug, this call should be filled by player's waiting time in queue
@@ -568,8 +572,8 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
uint32 queue_id = _player->GetBattleGroundQueueId(i);
if(!queue_id)
continue;
- uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id);
- uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id);
+ uint32 bgTypeId = BattleGroundMgr::BGTemplateId(queue_id);
+ uint8 arenatype = BattleGroundMgr::BGArenaType(queue_id);
uint8 isRated = 0;
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
@@ -697,7 +701,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
}
uint8 bgTypeId = bg->GetTypeID();
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype);
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype);
// check queueing conditions
if(!asGroup)
@@ -784,6 +788,8 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
}
sLog.outDebug("Battleground: arena join as group end");
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating);
+ if(isRated)
+ sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
}
else
{
diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp
index b4a28d93fd8..c0975f799e7 100644
--- a/src/game/BattleGroundMgr.cpp
+++ b/src/game/BattleGroundMgr.cpp
@@ -29,6 +29,9 @@
#include "BattleGroundBE.h"
#include "BattleGroundAA.h"
#include "BattleGroundRL.h"
+#include "BattleGroundSA.h"
+#include "BattleGroundDS.h"
+#include "BattleGroundRV.h"
#include "SharedDefines.h"
#include "Policies/SingletonImp.h"
#include "MapManager.h"
@@ -36,7 +39,6 @@
#include "MapInstanced.h"
#include "ObjectMgr.h"
#include "ProgressBar.h"
-#include "World.h"
#include "Chat.h"
#include "ArenaTeam.h"
@@ -177,7 +179,7 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo)
ginfo->Players[plr->GetGUID()] = &info;
}
-void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount)
+void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCount)
{
Player *plr = objmgr.GetPlayer(guid);
@@ -260,6 +262,11 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount)
// remove player queue info
m_QueuedPlayers[queue_id].erase(itr);
// remove group queue info if needed
+
+ //if we left BG queue(not porting) OR if arena team left queue for rated match
+ if((decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty()))
+ AnnounceWorld(group, guid, false);
+
if(group->Players.empty())
{
m_QueuedGroups[queue_id].erase(group_itr);
@@ -275,7 +282,7 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount)
if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first))
{
BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId);
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(group->BgTypeId,group->ArenaType);
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(group->BgTypeId,group->ArenaType);
uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId);
plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
WorldPacket data;
@@ -288,6 +295,85 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount)
}
}
+void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue)
+{
+
+ if(ginfo->ArenaType) //if Arena
+ {
+ if( sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE) && ginfo->IsRated)
+ {
+ BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId);
+ if(!bg)
+ return;
+
+ char const* bgName = bg->GetName();
+ if(isAddedToQueue)
+ sWorld.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, bgName, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating);
+ else
+ sWorld.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, bgName, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating);
+ }
+ }
+ else //if BG
+ {
+ if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) )
+ {
+ Player *plr = objmgr.GetPlayer(playerGUID);
+ if(!plr)
+ return;
+
+ BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId);
+ if(!bg)
+ return;
+
+ uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel();
+ char const* bgName = bg->GetName();
+
+ uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id);
+ uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id);
+
+ // replace hardcoded max level by player max level for nice output
+ if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
+ q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL);
+
+ int8 MinPlayers = bg->GetMinPlayersPerTeam();
+
+ uint8 qHorde = 0;
+ uint8 qAlliance = 0;
+
+ uint32 bgTypeId = ginfo->BgTypeId;
+ QueuedPlayersMap::iterator itr;
+ for(itr = m_QueuedPlayers[queue_id].begin(); itr!= m_QueuedPlayers[queue_id].end(); ++itr)
+ {
+ if(itr->second.GroupInfo->BgTypeId == bgTypeId)
+ {
+ switch(itr->second.GroupInfo->Team)
+ {
+ case HORDE:
+ qHorde++; break;
+ case ALLIANCE:
+ qAlliance++; break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // Show queue status to player only (when joining queue)
+ if(sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY))
+ {
+ ChatHandler(plr).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF,
+ bgName, q_min_level, q_max_level, qAlliance, MinPlayers, qHorde, MinPlayers);
+ }
+ // System message
+ else
+ {
+ sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD,
+ bgName, q_min_level, q_max_level, qAlliance, MinPlayers, qHorde, MinPlayers);
+ }
+ }
+ }
+}
+
bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side)
{
// set side if needed
@@ -299,7 +385,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
// not yet invited
// set invitation
ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
// loop through the players
for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr)
{
@@ -414,7 +500,7 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg)
{
uint32 queue_id = bg->GetQueueType();
uint32 bgInstanceId = bg->GetInstanceID();
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
QueuedGroupsList::iterator itr, next;
for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); itr = next)
{
@@ -484,7 +570,7 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype
if (m_QueuedGroups[queue_id].empty())
return;
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype);
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype);
//battleground with free slot for player should be always the last in this queue
BGFreeSlotQueueType::iterator itr, next;
@@ -635,6 +721,15 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype
{
// create new battleground
bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId);
+ if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) )
+ {
+ char const* bgName = bg2->GetName();
+ uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id);
+ uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id);
+ if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
+ q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL);
+ sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, bgName, q_min_level, q_max_level);
+ }
}
if(!bg2)
@@ -853,7 +948,7 @@ 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
{
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
{
@@ -890,7 +985,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID);
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
+ uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
{
@@ -933,16 +1028,10 @@ void BGQueueRemoveEvent::Abort(uint64 /*e_time*/)
/*** BATTLEGROUND MANAGER ***/
/*********************************************************/
-BattleGroundMgr::BattleGroundMgr()
+BattleGroundMgr::BattleGroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTesting(false)
{
m_BattleGrounds.clear();
- m_AutoDistributePoints = (bool)sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS);
- m_MaxRatingDifference = sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE);
- m_RatingDiscardTimer = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER);
- m_PrematureFinishTimer = sWorld.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER);
- m_NextRatingDiscardUpdate = m_RatingDiscardTimer;
- m_AutoDistributionTimeChecker = 0;
- m_ArenaTesting = false;
+ m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER);
}
BattleGroundMgr::~BattleGroundMgr()
@@ -960,7 +1049,7 @@ BattleGroundMgr::~BattleGroundMgr()
}
// used to update running battlegrounds, and delete finished ones
-void BattleGroundMgr::Update(time_t diff)
+void BattleGroundMgr::Update(uint32 diff)
{
BattleGroundSet::iterator itr, next;
for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next)
@@ -978,7 +1067,7 @@ void BattleGroundMgr::Update(time_t diff)
}
}
// if rating difference counts, maybe force-update queues
- if(m_MaxRatingDifference)
+ if(sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE))
{
// it's time to force update
if(m_NextRatingDiscardUpdate < diff)
@@ -987,12 +1076,12 @@ void BattleGroundMgr::Update(time_t diff)
m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA,6,ARENA_TYPE_2v2,true,0);
m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA,6,ARENA_TYPE_3v3,true,0);
m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA,6,ARENA_TYPE_5v5,true,0);
- m_NextRatingDiscardUpdate = m_RatingDiscardTimer;
+ m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER);
}
else
m_NextRatingDiscardUpdate -= diff;
}
- if(m_AutoDistributePoints)
+ if(sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
{
if(m_AutoDistributionTimeChecker < diff)
{
@@ -1054,6 +1143,15 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro
case BATTLEGROUND_RL:
*data << uint8(8);
break;
+ case BATTLEGROUND_SA:
+ *data << uint8(9);
+ break;
+ case BATTLEGROUND_DS:
+ *data << uint8(10);
+ break;
+ case BATTLEGROUND_RV:
+ *data << uint8(11);
+ break;
default: // unknown
*data << uint8(0);
break;
@@ -1098,17 +1196,18 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro
void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
{
uint8 type = (bg->isArena() ? 1 : 0);
- // last check on 2.4.1
+ // last check on 3.0.3
data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize()));
- *data << uint8(type); // seems to be type (battleground=0/arena=1)
+ *data << uint8(type); // type (battleground=0/arena=1)
if(type) // arena
{
// it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H
for(int i = 1; i >= 0; --i)
{
- *data << uint32(3000-bg->m_ArenaTeamRatingChanges[i]); // rating change: showed value - 3000
+ *data << uint32(bg->m_ArenaTeamRatingChanges[i]);
*data << uint32(3999); // huge thanks for TOM_RUS for this!
+ *data << uint32(0); // unknown - new in 3.0.3
sLog.outDebug("rating change: %d", bg->m_ArenaTeamRatingChanges[i]);
}
for(int i = 1; i >= 0; --i)
@@ -1122,9 +1221,9 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
}
}
- if(bg->GetWinner() == 2)
+ if(bg->GetStatus() != STATUS_WAIT_LEAVE)
{
- *data << uint8(0); // bg in progress
+ *data << uint8(0); // bg not ended
}
else
{
@@ -1138,9 +1237,6 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
{
*data << (uint64)itr->first;
*data << (int32)itr->second->KillingBlows;
- Player *plr = objmgr.GetPlayer(itr->first);
- uint32 team = bg->GetPlayerTeam(itr->first);
- if(!team && plr) team = plr->GetTeam();
if(type == 0)
{
*data << (int32)itr->second->HonorableKills;
@@ -1149,18 +1245,12 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
}
else
{
- // that part probably wrong
- if(plr)
- {
- if(team == HORDE)
- *data << uint8(0);
- else if(team == ALLIANCE)
- {
- *data << uint8(1);
- }
- else
- *data << uint8(0);
- }
+ Player *plr = objmgr.GetPlayer(itr->first);
+ uint32 team = bg->GetPlayerTeam(itr->first);
+ if(!team && plr)
+ team = plr->GetTeam();
+ if( ( bg->GetWinner()==0 && team == ALLIANCE ) || ( bg->GetWinner()==1 && team==HORDE ) )
+ *data << uint8(1);
else
*data << uint8(0);
}
@@ -1187,13 +1277,16 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
*data << (uint32)((BattleGroundABScore*)itr->second)->BasesDefended; // bases defended
break;
case BATTLEGROUND_EY:
- *data << (uint32)0x00000001; // count of next fields
+ *data << (uint32)0x00000001; // count of next fields
*data << (uint32)((BattleGroundEYScore*)itr->second)->FlagCaptures; // flag captures
break;
case BATTLEGROUND_NA:
case BATTLEGROUND_BE:
case BATTLEGROUND_AA:
case BATTLEGROUND_RL:
+ case BATTLEGROUND_SA: // wotlk
+ case BATTLEGROUND_DS: // wotlk
+ case BATTLEGROUND_RV: // wotlk
*data << (int32)0; // 0
break;
default:
@@ -1327,6 +1420,15 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(uint32 bgTypeId)
case BATTLEGROUND_RL:
bg = new BattleGroundRL(*(BattleGroundRL*)bg_template);
break;
+ case BATTLEGROUND_SA:
+ bg = new BattleGroundSA(*(BattleGroundSA*)bg_template);
+ break;
+ case BATTLEGROUND_DS:
+ bg = new BattleGroundDS(*(BattleGroundDS*)bg_template);
+ break;
+ case BATTLEGROUND_RV:
+ bg = new BattleGroundRV(*(BattleGroundRV*)bg_template);
+ break;
default:
//bg = new BattleGround;
return 0;
@@ -1373,6 +1475,9 @@ uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPer
case BATTLEGROUND_AA: bg = new BattleGroundAA; break;
case BATTLEGROUND_EY: bg = new BattleGroundEY; break;
case BATTLEGROUND_RL: bg = new BattleGroundRL; break;
+ case BATTLEGROUND_SA: bg = new BattleGroundSA; break;
+ case BATTLEGROUND_DS: bg = new BattleGroundDS; break;
+ case BATTLEGROUND_RV: bg = new BattleGroundRV; break;
default:bg = new BattleGround; break; // placeholder for non implemented BG
}
@@ -1526,7 +1631,7 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
void BattleGroundMgr::InitAutomaticArenaPointDistribution()
{
- if(m_AutoDistributePoints)
+ if(sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
{
sLog.outDebug("Initializing Automatic Arena Point Distribution");
QueryResult * result = CharacterDatabase.Query("SELECT NextArenaPointDistributionTime FROM saved_variables");
@@ -1595,7 +1700,7 @@ void BattleGroundMgr::DistributeArenaPoints()
sWorld.SendGlobalText("Done flushing Arena points.", NULL);
}
-void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player* plr, uint32 bgTypeId)
+void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint64& guid, Player* plr, uint32 bgTypeId)
{
uint32 PlayerLevel = 10;
@@ -1651,7 +1756,7 @@ void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId)
}
}
-void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid)
+void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid)
{
WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12);
uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds
@@ -1661,14 +1766,7 @@ void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *
pl->GetSession()->SendPacket(&data);
}
-void BattleGroundMgr::RemoveBattleGround(uint32 instanceID)
-{
- BattleGroundSet::iterator itr = m_BattleGrounds.find(instanceID);
- if(itr!=m_BattleGrounds.end())
- m_BattleGrounds.erase(itr);
-}
-
-bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const
+bool BattleGroundMgr::IsArenaType(uint32 bgTypeId)
{
return ( bgTypeId == BATTLEGROUND_AA ||
bgTypeId == BATTLEGROUND_BE ||
@@ -1676,76 +1774,77 @@ bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const
bgTypeId == BATTLEGROUND_RL );
}
-bool BattleGroundMgr::IsBattleGroundType(uint32 bgTypeId) const
-{
- return !IsArenaType(bgTypeId);
-}
-
-uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const
+uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType)
{
switch(bgTypeId)
{
- case BATTLEGROUND_WS:
- return BATTLEGROUND_QUEUE_WS;
- case BATTLEGROUND_AB:
- return BATTLEGROUND_QUEUE_AB;
- case BATTLEGROUND_AV:
- return BATTLEGROUND_QUEUE_AV;
- case BATTLEGROUND_EY:
- return BATTLEGROUND_QUEUE_EY;
- case BATTLEGROUND_AA:
- case BATTLEGROUND_NA:
- case BATTLEGROUND_RL:
- case BATTLEGROUND_BE:
- switch(arenaType)
- {
- case ARENA_TYPE_2v2:
- return BATTLEGROUND_QUEUE_2v2;
- case ARENA_TYPE_3v3:
- return BATTLEGROUND_QUEUE_3v3;
- case ARENA_TYPE_5v5:
- return BATTLEGROUND_QUEUE_5v5;
+ case BATTLEGROUND_WS:
+ return BATTLEGROUND_QUEUE_WS;
+ case BATTLEGROUND_AB:
+ return BATTLEGROUND_QUEUE_AB;
+ case BATTLEGROUND_AV:
+ return BATTLEGROUND_QUEUE_AV;
+ case BATTLEGROUND_EY:
+ return BATTLEGROUND_QUEUE_EY;
+ case BATTLEGROUND_SA:
+ return BATTLEGROUND_QUEUE_SA;
+ case BATTLEGROUND_AA:
+ case BATTLEGROUND_NA:
+ case BATTLEGROUND_RL:
+ case BATTLEGROUND_BE:
+ case BATTLEGROUND_DS:
+ case BATTLEGROUND_RV:
+ switch(arenaType)
+ {
+ case ARENA_TYPE_2v2:
+ return BATTLEGROUND_QUEUE_2v2;
+ case ARENA_TYPE_3v3:
+ return BATTLEGROUND_QUEUE_3v3;
+ case ARENA_TYPE_5v5:
+ return BATTLEGROUND_QUEUE_5v5;
+ default:
+ return 0;
+ }
default:
return 0;
- }
- default:
- return 0;
}
}
-uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) const
+uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId)
{
switch(bgQueueTypeId)
{
- case BATTLEGROUND_QUEUE_WS:
- return BATTLEGROUND_WS;
- case BATTLEGROUND_QUEUE_AB:
- return BATTLEGROUND_AB;
- case BATTLEGROUND_QUEUE_AV:
- return BATTLEGROUND_AV;
- case BATTLEGROUND_QUEUE_EY:
- return BATTLEGROUND_EY;
- case BATTLEGROUND_QUEUE_2v2:
- case BATTLEGROUND_QUEUE_3v3:
- case BATTLEGROUND_QUEUE_5v5:
- return BATTLEGROUND_AA;
- default:
- return 0;
+ case BATTLEGROUND_QUEUE_WS:
+ return BATTLEGROUND_WS;
+ case BATTLEGROUND_QUEUE_AB:
+ return BATTLEGROUND_AB;
+ case BATTLEGROUND_QUEUE_AV:
+ return BATTLEGROUND_AV;
+ case BATTLEGROUND_QUEUE_EY:
+ return BATTLEGROUND_EY;
+ case BATTLEGROUND_QUEUE_SA:
+ return BATTLEGROUND_SA;
+ case BATTLEGROUND_QUEUE_2v2:
+ case BATTLEGROUND_QUEUE_3v3:
+ case BATTLEGROUND_QUEUE_5v5:
+ return BATTLEGROUND_AA;
+ default:
+ return 0;
}
}
-uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId) const
+uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId)
{
switch(bgQueueTypeId)
{
- case BATTLEGROUND_QUEUE_2v2:
- return ARENA_TYPE_2v2;
- case BATTLEGROUND_QUEUE_3v3:
- return ARENA_TYPE_3v3;
- case BATTLEGROUND_QUEUE_5v5:
- return ARENA_TYPE_5v5;
- default:
- return 0;
+ case BATTLEGROUND_QUEUE_2v2:
+ return ARENA_TYPE_2v2;
+ case BATTLEGROUND_QUEUE_3v3:
+ return ARENA_TYPE_3v3;
+ case BATTLEGROUND_QUEUE_5v5:
+ return ARENA_TYPE_5v5;
+ default:
+ return 0;
}
}
diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h
index 70b899d5f85..3e833f1c7bb 100644
--- a/src/game/BattleGroundMgr.h
+++ b/src/game/BattleGroundMgr.h
@@ -22,7 +22,7 @@
#define __BATTLEGROUNDMGR_H
#include "BattleGround.h"
-#include "Policies/Singleton.h"
+#include "World.h"
class BattleGround;
@@ -32,11 +32,11 @@ typedef std::map<uint32, BattleGround*> BattleGroundSet;
//typedef std::map<uint32, BattleGroundQueue*> BattleGroundQueueSet;
typedef std::deque<BattleGround*> BGFreeSlotQueueType;
-#define MAX_BATTLEGROUND_QUEUES 7 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70+
+#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
-#define MAX_BATTLEGROUND_QUEUE_TYPES 8
+#define MAX_BATTLEGROUND_QUEUE_TYPES 9
#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
@@ -74,9 +74,10 @@ class BattleGroundQueue
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 RemovePlayer(const uint64& guid, bool decreaseInvitedCount);
void DecreaseGroupLength(uint32 queueId, uint32 AsGroup);
void BGEndedRemoveInvites(BattleGround * bg);
+ void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue);
typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap;
QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES];
@@ -137,7 +138,7 @@ class BattleGroundQueue
class BGQueueInviteEvent : public BasicEvent
{
public:
- BGQueueInviteEvent(uint64 pl_guid, uint32 BgInstanceGUID) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID) {};
+ BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID) {};
virtual ~BGQueueInviteEvent() {};
virtual bool Execute(uint64 e_time, uint32 p_time);
@@ -153,7 +154,10 @@ class BGQueueInviteEvent : public BasicEvent
class BGQueueRemoveEvent : public BasicEvent
{
public:
- BGQueueRemoveEvent(uint64 pl_guid, uint32 bgInstanceGUID, uint32 playersTeam) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_PlayersTeam(playersTeam) {};
+ BGQueueRemoveEvent(const uint64& pl_guid, uint32 bgInstanceGUID, uint32 playersTeam) :
+ m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_PlayersTeam(playersTeam)
+ {
+ };
virtual ~BGQueueRemoveEvent() {};
virtual bool Execute(uint64 e_time, uint32 p_time);
@@ -170,33 +174,31 @@ class BattleGroundMgr
/* Construction */
BattleGroundMgr();
~BattleGroundMgr();
- void Update(time_t diff);
+ void Update(uint32 diff);
/* Packet Building */
void BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr);
void BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr);
- void BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player *plr, uint32 bgTypeId);
+ void BuildBattleGroundListPacket(WorldPacket *data, const uint64& guid, Player *plr, uint32 bgTypeId);
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, uint32 arenatype = 0, uint8 israted = 0);
void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid);
+ void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid);
/* Player invitation */
// called from Queue update, or from Addplayer to queue
void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team);
/* Battlegrounds */
BattleGroundSet::iterator GetBattleGroundsBegin() { return m_BattleGrounds.begin(); };
- BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); };
+ BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); };
BattleGround* GetBattleGround(uint32 ID)
{
BattleGroundSet::iterator i = m_BattleGrounds.find(ID);
- if(i != m_BattleGrounds.end())
- return i->second;
- else
- return NULL;
+ return ( (i != m_BattleGrounds.end()) ? i->second : NULL );
};
BattleGround * GetBattleGroundTemplate(uint32 bgTypeId);
@@ -204,8 +206,8 @@ class BattleGroundMgr
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 AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; };
+ void RemoveBattleGround(uint32 instanceID) { m_BattleGrounds.erase(instanceID); }
void CreateInitialBattleGrounds();
@@ -217,35 +219,30 @@ class BattleGroundMgr
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;}
+ uint32 GetMaxRatingDifference() const { return sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); }
+ uint32 GetRatingDiscardTimer() const { return sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); }
+ uint32 GetPrematureFinishTime() const { return sWorld.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER); }
void InitAutomaticArenaPointDistribution();
void DistributeArenaPoints();
- uint32 GetPrematureFinishTime() const {return m_PrematureFinishTimer;}
void ToggleArenaTesting();
- const bool isArenaTesting() const { return m_ArenaTesting; }
void SetHolidayWeekends(uint32 mask);
+
+ bool isArenaTesting() const { return m_ArenaTesting; }
+
+ static bool IsArenaType(uint32 bgTypeId);
+ static bool IsBattleGroundType(uint32 bgTypeId) { return !BattleGroundMgr::IsArenaType(bgTypeId); }
+ static uint32 BGQueueTypeId(uint32 bgTypeId, uint8 arenaType);
+ static uint32 BGTemplateId(uint32 bgQueueTypeId);
+ static uint8 BGArenaType(uint32 bgQueueTypeId);
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;
};
diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp
index f06910af986..1079c510b24 100644
--- a/src/game/BattleGroundNA.cpp
+++ b/src/game/BattleGroundNA.cpp
@@ -37,7 +37,7 @@ BattleGroundNA::~BattleGroundNA()
}
-void BattleGroundNA::Update(time_t diff)
+void BattleGroundNA::Update(uint32 diff)
{
BattleGround::Update(diff);
diff --git a/src/game/BattleGroundNA.h b/src/game/BattleGroundNA.h
index 45dc9efec31..f31555d65f9 100644
--- a/src/game/BattleGroundNA.h
+++ b/src/game/BattleGroundNA.h
@@ -58,7 +58,7 @@ class BattleGroundNA : public BattleGround
public:
BattleGroundNA();
~BattleGroundNA();
- void Update(time_t diff);
+ void Update(uint32 diff);
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp
index 193578e88b0..6585a164211 100644
--- a/src/game/BattleGroundRL.cpp
+++ b/src/game/BattleGroundRL.cpp
@@ -37,7 +37,7 @@ BattleGroundRL::~BattleGroundRL()
}
-void BattleGroundRL::Update(time_t diff)
+void BattleGroundRL::Update(uint32 diff)
{
BattleGround::Update(diff);
diff --git a/src/game/BattleGroundRL.h b/src/game/BattleGroundRL.h
index d3f58264833..567b677769e 100644
--- a/src/game/BattleGroundRL.h
+++ b/src/game/BattleGroundRL.h
@@ -54,7 +54,7 @@ class BattleGroundRL : public BattleGround
public:
BattleGroundRL();
~BattleGroundRL();
- void Update(time_t diff);
+ void Update(uint32 diff);
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
diff --git a/src/game/BattleGroundRV.cpp b/src/game/BattleGroundRV.cpp
new file mode 100644
index 00000000000..a66f0ce30e2
--- /dev/null
+++ b/src/game/BattleGroundRV.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Player.h"
+#include "BattleGround.h"
+#include "BattleGroundRV.h"
+
+BattleGroundRV::BattleGroundRV()
+{
+
+}
+
+BattleGroundRV::~BattleGroundRV()
+{
+
+}
+
+void BattleGroundRV::Update(uint32 diff)
+{
+ BattleGround::Update(diff);
+}
+
+void BattleGroundRV::AddPlayer(Player *plr)
+{
+ BattleGround::AddPlayer(plr);
+ //create score and add it to map, default values are set in constructor
+ BattleGroundRVScore* sc = new BattleGroundRVScore;
+
+ m_PlayerScores[plr->GetGUID()] = sc;
+}
+
+void BattleGroundRV::RemovePlayer(Player * /*plr*/, uint64 /*guid*/)
+{
+}
+
+void BattleGroundRV::HandleKillPlayer(Player* player, Player* killer)
+{
+ BattleGround::HandleKillPlayer(player, killer);
+}
+
+void BattleGroundRV::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/)
+{
+}
+
+bool BattleGroundRV::SetupBattleGround()
+{
+ return true;
+}
diff --git a/src/game/BattleGroundRV.h b/src/game/BattleGroundRV.h
new file mode 100644
index 00000000000..2d2ad12c941
--- /dev/null
+++ b/src/game/BattleGroundRV.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __BATTLEGROUNDRV_H
+#define __BATTLEGROUNDRV_H
+
+class BattleGround;
+
+class BattleGroundRVScore : public BattleGroundScore
+{
+ public:
+ BattleGroundRVScore() {};
+ virtual ~BattleGroundRVScore() {};
+ //TODO fix me
+};
+
+class BattleGroundRV : public BattleGround
+{
+ friend class BattleGroundMgr;
+
+ public:
+ BattleGroundRV();
+ ~BattleGroundRV();
+ void Update(uint32 diff);
+
+ /* inherited from BattlegroundClass */
+ virtual void AddPlayer(Player *plr);
+ void RemovePlayer(Player *plr, uint64 guid);
+ void HandleAreaTrigger(Player *Source, uint32 Trigger);
+ bool SetupBattleGround();
+ void HandleKillPlayer(Player* player, Player *killer);
+};
+#endif
diff --git a/src/game/BattleGroundSA.cpp b/src/game/BattleGroundSA.cpp
new file mode 100644
index 00000000000..20a69297609
--- /dev/null
+++ b/src/game/BattleGroundSA.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "BattleGround.h"
+#include "BattleGroundSA.h"
+
+BattleGroundSA::BattleGroundSA()
+{
+
+}
+
+BattleGroundSA::~BattleGroundSA()
+{
+
+}
+
+void BattleGroundSA::Update(uint32 diff)
+{
+ BattleGround::Update(diff);
+}
+
+void BattleGroundSA::AddPlayer(Player *plr)
+{
+ BattleGround::AddPlayer(plr);
+ //create score and add it to map, default values are set in constructor
+ BattleGroundSAScore* sc = new BattleGroundSAScore;
+
+ m_PlayerScores[plr->GetGUID()] = sc;
+}
+
+void BattleGroundSA::RemovePlayer(Player* /*plr*/,uint64 /*guid*/)
+{
+
+}
+
+void BattleGroundSA::HandleAreaTrigger(Player *Source, uint32 Trigger)
+{
+ // this is wrong way to implement these things. On official it done by gameobject spell cast.
+ if(GetStatus() != STATUS_IN_PROGRESS)
+ return;
+}
+
+void BattleGroundSA::UpdatePlayerScore(Player* Source, uint32 type, uint32 value)
+{
+
+ std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
+
+ if(itr == m_PlayerScores.end()) // player not found...
+ return;
+
+ BattleGround::UpdatePlayerScore(Source,type,value);
+}
diff --git a/src/game/BattleGroundSA.h b/src/game/BattleGroundSA.h
new file mode 100644
index 00000000000..331a41455fd
--- /dev/null
+++ b/src/game/BattleGroundSA.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __BATTLEGROUNDSA_H
+#define __BATTLEGROUNDSA_H
+
+class BattleGround;
+
+class BattleGroundSAScore : public BattleGroundScore
+{
+ public:
+ BattleGroundSAScore() {};
+ virtual ~BattleGroundSAScore() {};
+};
+
+class BattleGroundSA : public BattleGround
+{
+ friend class BattleGroundMgr;
+
+ public:
+ BattleGroundSA();
+ ~BattleGroundSA();
+ void Update(uint32 diff);
+
+ /* inherited from BattlegroundClass */
+ virtual void AddPlayer(Player *plr);
+
+ void RemovePlayer(Player *plr,uint64 guid);
+ void HandleAreaTrigger(Player *Source, uint32 Trigger);
+ //bool SetupBattleGround();
+
+ /* Scorekeeping */
+ void UpdatePlayerScore(Player *Source, uint32 type, uint32 value);
+
+ private:
+};
+#endif
diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp
index 755089473e8..51ec6595b93 100644
--- a/src/game/BattleGroundWS.cpp
+++ b/src/game/BattleGroundWS.cpp
@@ -58,7 +58,7 @@ BattleGroundWS::~BattleGroundWS()
{
}
-void BattleGroundWS::Update(time_t diff)
+void BattleGroundWS::Update(uint32 diff)
{
BattleGround::Update(diff);
diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h
index 17b59d98343..426fb2ebcb1 100644
--- a/src/game/BattleGroundWS.h
+++ b/src/game/BattleGroundWS.h
@@ -136,7 +136,7 @@ class BattleGroundWS : public BattleGround
/* Construction */
BattleGroundWS();
~BattleGroundWS();
- void Update(time_t diff);
+ void Update(uint32 diff);
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt
index 8cee1325205..795d83a0300 100644
--- a/src/game/CMakeLists.txt
+++ b/src/game/CMakeLists.txt
@@ -4,6 +4,8 @@
SET(game_STAT_SRCS
AccountMgr.cpp
AccountMgr.h
+ AchievementMgr.h
+ AchievementMgr.cpp
AddonHandler.cpp
AddonHandler.h
AggressorAI.cpp
@@ -23,22 +25,31 @@ SET(game_STAT_SRCS
BattleGroundAB.cpp
BattleGroundAV.cpp
BattleGroundBE.cpp
+ BattleGroundDS.cpp
BattleGroundEY.cpp
BattleGroundNA.cpp
BattleGroundRL.cpp
+ BattleGroundRV.cpp
+ BattleGroundSA.cpp
BattleGroundWS.cpp
BattleGround.h
BattleGroundAA.h
BattleGroundAB.h
BattleGroundAV.h
BattleGroundBE.h
+ BattleGroundDS.h
BattleGroundEY.h
BattleGroundNA.h
BattleGroundRL.h
+ BattleGroundRV.h
+ BattleGroundSA.h
BattleGroundWS.h
BattleGroundHandler.cpp
BattleGroundMgr.cpp
BattleGroundMgr.h
+ Calendar.cpp
+ Calendar.h
+ CalendarHandler.cpp
Cell.h
CellImpl.h
Channel.cpp
@@ -130,6 +141,8 @@ SET(game_STAT_SRCS
MapInstanced.h
MapManager.cpp
MapManager.h
+ MapReference.h
+ MapRefManager.h
MiscHandler.cpp
MotionMaster.cpp
MotionMaster.h
@@ -150,6 +163,8 @@ SET(game_STAT_SRCS
Object.h
ObjectMgr.cpp
ObjectMgr.h
+ ObjectPosSelector.cpp
+ ObjectPosSelector.h
Opcodes.cpp
Opcodes.h
OutdoorPvP.cpp
@@ -240,6 +255,8 @@ SET(game_STAT_SRCS
UpdateData.h
UpdateFields.h
UpdateMask.h
+ Vehicle.cpp
+ Vehicle.h
VoiceChatHandler.cpp
WaypointManager.cpp
WaypointManager.h
diff --git a/src/game/Calendar.cpp b/src/game/Calendar.cpp
new file mode 100644
index 00000000000..cebf7252e78
--- /dev/null
+++ b/src/game/Calendar.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
diff --git a/src/game/Calendar.h b/src/game/Calendar.h
new file mode 100644
index 00000000000..94e4ff103f5
--- /dev/null
+++ b/src/game/Calendar.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MANGOS_CALENDAR_H
+#define MANGOS_CALENDAR_H
+
+class Calendar
+{
+
+};
+#endif
diff --git a/src/game/CalendarHandler.cpp b/src/game/CalendarHandler.cpp
new file mode 100644
index 00000000000..9d1171687b6
--- /dev/null
+++ b/src/game/CalendarHandler.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://www.mangosproject.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Common.h"
+#include "Log.h"
+#include "Player.h"
+#include "WorldPacket.h"
+#include "WorldSession.h"
+#include "Opcodes.h"
+#include "InstanceSaveMgr.h"
+
+void WorldSession::HandleCalendarGetCalendar(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_GET_CALENDAR");
+ recv_data.hexlike();
+
+ time_t cur_time = time(NULL);
+
+ WorldPacket data(SMSG_CALENDAR_SEND_CALENDAR,4+4*0+4+4*0+4+4);
+
+ // TODO: calendar invite event output
+ data << (uint32) 0; //invite node count
+ // TODO: calendar event output
+ data << (uint32) 0; //event count
+
+ data << (uint32) 0; //wtf??
+ data << (uint32) secsToTimeBitFields(cur_time); // current time
+
+ uint32 counter = 0;
+ size_t p_counter = data.wpos();
+ data << uint32(counter); // instance save count
+
+ for(int i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ {
+ for (Player::BoundInstancesMap::iterator itr = _player->m_boundInstances[i].begin(); itr != _player->m_boundInstances[i].end(); ++itr)
+ {
+ if(itr->second.perm)
+ {
+ InstanceSave *save = itr->second.save;
+ data << uint32(save->GetMapId());
+ data << uint32(save->GetDifficulty());
+ data << uint32(save->GetResetTime() - cur_time);
+ data << uint64(save->GetInstanceId()); // instance save id as unique instance copy id
+ ++counter;
+ }
+ }
+ }
+ data.put<uint32>(p_counter,counter);
+
+ data << (uint32) 1135753200; //wtf?? (28.12.2005 12:00)
+ data << (uint32) 0; // unk counter 4
+ data << (uint32) 0; // unk counter 5
+ //sLog.outDebug("Sending calendar");
+ //data.hexlike();
+ SendPacket(&data);
+}
+
+void WorldSession::HandleCalendarGetEvent(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_GET_EVENT");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarGuildFilter(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_GUILD_FILTER");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarArenaTeam(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_ARENA_TEAM");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarAddEvent(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_ADD_EVENT");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarUpdateEvent(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_UPDATE_EVENT");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarRemoveEvent(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_REMOVE_EVENT");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarCopyEvent(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_COPY_EVENT");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarEventInvite(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_INVITE");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarEventRsvp(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_RSVP");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_REMOVE_INVITE");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarEventStatus(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_STATUS");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_MODERATOR_STATUS");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarComplain(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_COMPLAIN");
+ recv_data.hexlike();
+}
+
+void WorldSession::HandleCalendarGetNumPending(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_CALENDAR_GET_NUM_PENDING");
+ recv_data.hexlike();
+
+ WorldPacket data(SMSG_CALENDAR_SEND_NUM_PENDING, 4);
+ data << uint32(0); // 0 - no pending invites, 1 - some pending invites
+ SendPacket(&data);
+}
diff --git a/src/game/Cell.h b/src/game/Cell.h
index 35bcdbeea8a..a7e40a29683 100644
--- a/src/game/Cell.h
+++ b/src/game/Cell.h
@@ -93,13 +93,13 @@ struct TRINITY_DLL_DECL Cell
y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y;
}
- inline bool DiffCell(const Cell &cell) const
+ bool DiffCell(const Cell &cell) const
{
return( data.Part.cell_x != cell.data.Part.cell_x ||
data.Part.cell_y != cell.data.Part.cell_y );
}
- inline bool DiffGrid(const Cell &cell) const
+ bool DiffGrid(const Cell &cell) const
{
return( data.Part.grid_x != cell.data.Part.grid_x ||
data.Part.grid_y != cell.data.Part.grid_y );
diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp
index ccc6594a72c..498836ad5ee 100644
--- a/src/game/CharacterHandler.cpp
+++ b/src/game/CharacterHandler.cpp
@@ -68,7 +68,7 @@ bool LoginQueryHolder::Initialize()
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid));
- res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,slot,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid));
+ res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, "SELECT quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4 FROM character_queststatus WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest,time FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADTUTORIALS, "SELECT tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7 FROM character_tutorial WHERE account = '%u' AND realmid = '%u'", GetAccountId(), realmID);
@@ -85,6 +85,8 @@ bool LoginQueryHolder::Initialize()
// in other case still be dummy query
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid));
+ res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = '%u'", GUID_LOPART(m_guid));
+ res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS,"SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = '%u'", GUID_LOPART(m_guid));
return res;
}
@@ -234,17 +236,16 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
if (raceEntry->addon > Expansion())
{
data << (uint8)CHAR_CREATE_EXPANSION;
- sLog.outError("Not Expansion 1 account:[%d] but tried to Create character with expansion 1 race (%u)",GetAccountId(),race_);
+ sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->addon,race_);
SendPacket( &data );
return;
}
// prevent character creating Expansion class without Expansion account
- // TODO: use possible addon field in ChrClassesEntry in next dbc version
- if (Expansion() < 2 && class_ == CLASS_DEATH_KNIGHT)
+ if (classEntry->addon > Expansion())
{
- data << (uint8)CHAR_CREATE_EXPANSION;
- sLog.outError("Not Expansion 2 account:[%d] but tried to Create character with expansion 2 class (%u)",GetAccountId(),class_);
+ data << (uint8)CHAR_CREATE_EXPANSION_CLASS;
+ sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)",Expansion(),GetAccountId(),classEntry->addon,class_);
SendPacket( &data );
return;
}
@@ -311,29 +312,77 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
}
}
+ // speedup check for heroic class disabled case
+ uint32 heroic_free_slots = sWorld.getConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
+ if(heroic_free_slots==0 && GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT)
+ {
+ data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT;
+ SendPacket( &data );
+ return;
+ }
+
+ // speedup check for heroic class disabled case
+ uint32 req_level_for_heroic = sWorld.getConfig(CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING);
+ if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
+ {
+ data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT;
+ SendPacket( &data );
+ return;
+ }
+
bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER;
uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS);
bool have_same_race = false;
- if(!AllowTwoSideAccounts || skipCinematics == 1)
+
+ // if 0 then allowed creating without any characters
+ bool have_req_level_for_heroic = (req_level_for_heroic==0);
+
+ if(!AllowTwoSideAccounts || skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT)
{
- QueryResult *result2 = CharacterDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1");
+ QueryResult *result2 = CharacterDatabase.PQuery("SELECT guid,race,class FROM characters WHERE account = '%u' %s",
+ GetAccountId(), (skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) ? "" : "LIMIT 1");
if(result2)
{
uint32 team_= Player::TeamForRace(race_);
Field* field = result2->Fetch();
- uint8 race = field[0].GetUInt32();
+ uint8 acc_race = field[1].GetUInt32();
+
+ if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT)
+ {
+ uint8 acc_class = field[2].GetUInt32();
+ if(acc_class == CLASS_DEATH_KNIGHT)
+ {
+ if(heroic_free_slots > 0)
+ --heroic_free_slots;
+
+ if(heroic_free_slots==0)
+ {
+ data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT;
+ SendPacket( &data );
+ return;
+ }
+ }
+
+ if(!have_req_level_for_heroic)
+ {
+ uint32 acc_guid = field[0].GetUInt32();
+ uint32 acc_level = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,acc_guid);
+ if(acc_level >= req_level_for_heroic)
+ have_req_level_for_heroic = true;
+ }
+ }
// need to check team only for first character
// TODO: what to if account already has characters of both races?
if (!AllowTwoSideAccounts)
{
- uint32 team=0;
- if(race > 0)
- team = Player::TeamForRace(race);
+ uint32 acc_team=0;
+ if(acc_race > 0)
+ acc_team = Player::TeamForRace(acc_race);
- if(team != team_)
+ if(acc_team != team_)
{
data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION;
SendPacket( &data );
@@ -342,20 +391,55 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
}
}
- if (skipCinematics == 1)
+ // search same race for cinematic or same class if need
+ // TODO: check if cinematic already shown? (already logged in?; cinematic field)
+ while ((skipCinematics == 1 && !have_same_race) || class_ == CLASS_DEATH_KNIGHT)
{
- // TODO: check if cinematic already shown? (already logged in?; cinematic field)
- while (race_ != race && result2->NextRow())
+ if(!result2->NextRow())
+ break;
+
+ field = result2->Fetch();
+ acc_race = field[1].GetUInt32();
+
+ if(!have_same_race)
+ have_same_race = race_ == acc_race;
+
+ if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT)
{
- field = result2->Fetch();
- race = field[0].GetUInt32();
+ uint8 acc_class = field[2].GetUInt32();
+ if(acc_class == CLASS_DEATH_KNIGHT)
+ {
+ if(heroic_free_slots > 0)
+ --heroic_free_slots;
+
+ if(heroic_free_slots==0)
+ {
+ data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT;
+ SendPacket( &data );
+ return;
+ }
+ }
+
+ if(!have_req_level_for_heroic)
+ {
+ uint32 acc_guid = field[0].GetUInt32();
+ uint32 acc_level = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,acc_guid);
+ if(acc_level >= req_level_for_heroic)
+ have_req_level_for_heroic = true;
+ }
}
- have_same_race = race_ == race;
}
delete result2;
}
}
+ if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && !have_req_level_for_heroic)
+ {
+ data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT;
+ SendPacket( &data );
+ return;
+ }
+
// extract other data required for player creating
uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId;
recv_data >> gender >> skin >> face;
@@ -514,9 +598,11 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
data << pCurrChar->GetOrientation();
SendPacket(&data);
- data.Initialize( SMSG_ACCOUNT_DATA_TIMES, 128 );
- for(int i = 0; i < 32; i++)
- data << uint32(0);
+ data.Initialize( SMSG_ACCOUNT_DATA_TIMES, 4+1+8*4 ); // changed in WotLK
+ data << uint32(time(NULL)); // unix time of something
+ data << uint8(1);
+ for(int i = 0; i < NUM_ACCOUNT_DATA_TYPES; i++)
+ data << uint32(GetAccountData(i)->Time); // also unix time
SendPacket(&data);
data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0
@@ -619,17 +705,25 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
{
pCurrChar->setCinematic(1);
- ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace());
- if(rEntry)
+ if(ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass()))
{
- data.Initialize( SMSG_TRIGGER_CINEMATIC,4 );
- data << uint32(rEntry->startmovie);
- SendPacket( &data );
-
+ if(cEntry->CinematicSequence)
+ {
+ data.Initialize(SMSG_TRIGGER_CINEMATIC, 4);
+ data << uint32(cEntry->CinematicSequence);
+ SendPacket( &data );
+ }
+ else if(ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace()))
+ {
+ data.Initialize(SMSG_TRIGGER_CINEMATIC, 4);
+ data << uint32(rEntry->CinematicSequence);
+ SendPacket( &data );
+ }
+
// send new char string if not empty
if (!sWorld.GetNewCharString().empty())
chH.PSendSysMessage(sWorld.GetNewCharString().c_str());
- }
+ }
}
if (!pCurrChar->GetMap()->Add(pCurrChar))
@@ -672,22 +766,6 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form)
pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?)
- //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+41, 8326);
- //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+42, 20584);
- //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAFLAGS+6, 238);
- //pCurrChar->SetUInt32Value(UNIT_FIELD_AURALEVELS+11, 514);
- //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+11, 65535);
- //pCurrChar->SetUInt32Value(UNIT_FIELD_DISPLAYID, 1825);
- //if (pCurrChar->getRace() == RACE_NIGHTELF)
- //{
- // pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true);
- // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true);
- //}
- //else
- //{
- // pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true);
- // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true);
- //}
pCurrChar->SetMovement(MOVE_WATER_WALK);
}
@@ -747,7 +825,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
// Set FFA PvP for non GM in non-rest mode
if(sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING) )
- pCurrChar->SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP);
+ pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
if(pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP))
pCurrChar->SetContestedPvP();
@@ -917,11 +995,11 @@ void WorldSession::HandleToggleCloakOpcode( WorldPacket & /*recv_data*/ )
void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data)
{
+ CHECK_PACKET_SIZE(recv_data, 8+1);
+
uint64 guid;
std::string newname;
- CHECK_PACKET_SIZE(recv_data, 8+1);
-
recv_data >> guid;
recv_data >> newname;
@@ -929,15 +1007,15 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data)
if(!normalizePlayerName(newname))
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
- data << (uint8)CHAR_NAME_NO_NAME;
+ data << uint8(CHAR_NAME_NO_NAME);
SendPacket( &data );
return;
}
- if(!ObjectMgr::IsValidName(newname,true))
+ if(!ObjectMgr::IsValidName(newname, true))
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
- data << (uint8)CHAR_NAME_INVALID_CHARACTER;
+ data << uint8(CHAR_NAME_INVALID_CHARACTER);
SendPacket( &data );
return;
}
@@ -946,7 +1024,7 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data)
if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname))
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
- data << (uint8)CHAR_NAME_RESERVED;
+ data << uint8(CHAR_NAME_RESERVED);
SendPacket( &data );
return;
}
@@ -975,7 +1053,7 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uin
if (!result)
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
- data << (uint8)CHAR_CREATE_ERROR;
+ data << uint8(CHAR_CREATE_ERROR);
session->SendPacket( &data );
return;
}
@@ -989,11 +1067,11 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uin
CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME), guidLow);
CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", guidLow);
- sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s",session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str());
+ sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str());
- WorldPacket data(SMSG_CHAR_RENAME,1+8+(newname.size()+1));
- data << (uint8)RESPONSE_SUCCESS;
- data << guid;
+ WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1));
+ data << uint8(RESPONSE_SUCCESS);
+ data << uint64(guid);
data << newname;
session->SendPacket(&data);
}
@@ -1087,3 +1165,166 @@ void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data)
data << uint64(guid);
SendPacket(&data);
}
+
+void WorldSession::HandleAlterAppearance( WorldPacket & recv_data )
+{
+ sLog.outDebug("CMSG_ALTER_APPEARANCE");
+
+ CHECK_PACKET_SIZE(recv_data, 4+4+4);
+
+ uint32 Hair, Color, FacialHair;
+ recv_data >> Hair >> Color >> FacialHair;
+
+ BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair);
+
+ if(!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->getGender())
+ return;
+
+ BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair);
+
+ if(!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->getGender())
+ return;
+
+ uint32 Cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id);
+
+ // 0 - ok
+ // 1,3 - not enough money
+ // 2 - you have to seat on barber chair
+ if(_player->GetMoney() < Cost)
+ {
+ WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4);
+ data << uint32(1); // no money
+ SendPacket(&data);
+ return;
+ }
+ else
+ {
+ WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4);
+ data << uint32(0); // ok
+ SendPacket(&data);
+ }
+
+ _player->SetMoney(_player->GetMoney() - Cost); // it isn't free
+
+ _player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id));
+ _player->SetByteValue(PLAYER_BYTES, 3, uint8(Color));
+ _player->SetByteValue(PLAYER_BYTES_2, 0, uint8(bs_facialHair->hair_id));
+
+ _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1);
+
+ _player->SetStandState(0); // stand up
+}
+
+void WorldSession::HandleRemoveGlyph( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data, 4);
+
+ uint32 slot;
+ recv_data >> slot;
+
+ if(slot > MAX_GLYPH_SLOT_INDEX)
+ {
+ sLog.outDebug("Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot);
+ return;
+ }
+
+ if(uint32 glyph = _player->GetGlyph(slot))
+ {
+ if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
+ {
+ _player->RemoveAurasDueToSpell(gp->SpellId);
+ _player->SetGlyph(slot, 0);
+ }
+ }
+}
+
+void WorldSession::HandleCharCustomize(WorldPacket& recv_data)
+{
+ CHECK_PACKET_SIZE(recv_data, 8+1);
+
+ uint64 guid;
+ std::string newname;
+
+ recv_data >> guid;
+ recv_data >> newname;
+
+ CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1+1+1+1+1+1);
+
+ uint8 gender, skin, face, hairStyle, hairColor, facialHair;
+ recv_data >> gender >> skin >> face >> hairStyle >> hairColor >> facialHair;
+
+ QueryResult *result = CharacterDatabase.PQuery("SELECT at_login FROM characters WHERE guid ='%u'", GUID_LOPART(guid));
+ if (!result)
+ {
+ WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
+ data << uint8(CHAR_CREATE_ERROR);
+ SendPacket( &data );
+ return;
+ }
+
+ Field *fields = result->Fetch();
+ uint32 at_loginFlags = fields[0].GetUInt32();
+ delete result;
+
+ if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE))
+ {
+ WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
+ data << uint8(CHAR_CREATE_ERROR);
+ SendPacket( &data );
+ return;
+ }
+
+ // prevent character rename to invalid name
+ if(!normalizePlayerName(newname))
+ {
+ WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
+ data << uint8(CHAR_NAME_NO_NAME);
+ SendPacket( &data );
+ return;
+ }
+
+ if(!ObjectMgr::IsValidName(newname,true))
+ {
+ WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
+ data << uint8(CHAR_NAME_INVALID_CHARACTER);
+ SendPacket( &data );
+ return;
+ }
+
+ // check name limitations
+ if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname))
+ {
+ WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
+ data << uint8(CHAR_NAME_RESERVED);
+ SendPacket( &data );
+ return;
+ }
+
+ if(objmgr.GetPlayerGUIDByName(newname)) // character with this name already exist
+ {
+ WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
+ data << uint8(CHAR_CREATE_NAME_IN_USE);
+ SendPacket( &data );
+ return;
+ }
+
+ CharacterDatabase.escape_string(newname);
+ Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair);
+ CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_CUSTOMIZE), GUID_LOPART(guid));
+ CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid));
+
+ std::string IP_str = GetRemoteAddress();
+ sLog.outChar("Account: %d (IP: %s), Character guid: %u Customized to: %s", GetAccountId(), IP_str.c_str(), GUID_LOPART(guid), newname.c_str());
+
+ WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1+8+(newname.size()+1)+6);
+ data << uint8(RESPONSE_SUCCESS);
+ data << uint64(guid);
+ data << newname;
+ data << uint8(gender);
+ data << uint8(skin);
+ data << uint8(face);
+ data << uint8(hairStyle);
+ data << uint8(hairColor);
+ data << uint8(facialHair);
+ SendPacket(&data);
+}
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
index d6cdde47a8c..17acc5e957f 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -33,8 +33,26 @@
#include "MapManager.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
+#include "AccountMgr.h"
#include "TicketMgr.h"
+// Supported shift-links (client generated and server side)
+// |color|Harea:area_id|h[name]|h|r
+// |color|Hcreature:creature_guid|h[name]|h|r
+// |color|Hcreature_entry:creature_id|h[name]|h|r
+// |color|Hgameevent:id|h[name]|h|r
+// |color|Hgameobject:go_guid|h[name]|h|r
+// |color|Hgameobject_entry:go_id|h[name]|h|r
+// |color|Hitem:item_id:perm_ench_id:0:0|h[name]|h|r
+// |color|Hitemset:itemset_id|h[name]|h|r
+// |color|Hplayer:name|h[name]|h|r - client, in some messages, at click copy only name instead link
+// |color|Hquest:quest_id|h[name]|h|r
+// |color|Hskill:skill_id|h[name]|h|r
+// |color|Hspell:spell_id|h[name]|h|r - client, spellbook spell icon shift-click
+// |color|Htalent:talent_id,rank|h[name]|h|r - client, talent icon shift-click
+// |color|Htele:id|h[name]|h|r
+// |color|Htrade:spell_id,cur_value,max_value,unk3int,unk3str|h[name]|h|r - client, spellbook profession icon shift-click
+
bool ChatHandler::load_command_table = true;
ChatCommand * ChatHandler::getCommandTable()
@@ -112,6 +130,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "hp", SEC_MODERATOR, false, &ChatHandler::HandleModifyHPCommand, "", NULL },
{ "mana", SEC_MODERATOR, false, &ChatHandler::HandleModifyManaCommand, "", NULL },
{ "rage", SEC_MODERATOR, false, &ChatHandler::HandleModifyRageCommand, "", NULL },
+ { "runicpower", SEC_MODERATOR, false, &ChatHandler::HandleModifyRunicPowerCommand, "", NULL },
{ "energy", SEC_MODERATOR, false, &ChatHandler::HandleModifyEnergyCommand, "", NULL },
{ "money", SEC_MODERATOR, false, &ChatHandler::HandleModifyMoneyCommand, "", NULL },
{ "speed", SEC_MODERATOR, false, &ChatHandler::HandleModifySpeedCommand, "", NULL },
@@ -132,6 +151,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "drunk", SEC_MODERATOR, false, &ChatHandler::HandleDrunkCommand, "", NULL },
{ "standstate", SEC_GAMEMASTER, false, &ChatHandler::HandleStandStateCommand, "", NULL },
{ "morph", SEC_GAMEMASTER, false, &ChatHandler::HandleMorphCommand, "", NULL },
+ { "phase", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyPhaseCommand, "", NULL },
{ "gender", SEC_ADMINISTRATOR, false, &ChatHandler::HandleModifyGenderCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
@@ -192,6 +212,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "sellerr", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSellErrorCommand, "", NULL },
{ "buyerr", SEC_ADMINISTRATOR, false, &ChatHandler::HandleBuyErrorCommand, "", NULL },
{ "sendopcode", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendOpcodeCommand, "", NULL },
+ { "spawnvehicle", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSpawnVehicle, "", NULL },
{ "uws", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUpdateWorldStateCommand, "", NULL },
{ "ps", SEC_ADMINISTRATOR, false, &ChatHandler::HandlePlaySound2Command, "", NULL },
{ "scn", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendChannelNotifyCommand, "", NULL },
@@ -205,6 +226,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleAnimCommand, "", NULL },
{ "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleGetLootRecipient, "", NULL },
{ "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL },
+ { "sendlargepacket",SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendLargePacketCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
@@ -265,6 +287,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
{ "trinity_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadTrinityStringCommand, "", NULL },
+ { "milling_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMillingCommand, "", NULL },
{ "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL },
{ "npc_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcOptionCommand, "", NULL },
{ "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL },
@@ -286,8 +309,10 @@ ChatCommand * ChatHandler::getCommandTable()
{ "spell_required", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellRequiredCommand, "", NULL },
{ "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL },
{ "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL },
+ { "spell_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSpellCommand, "", NULL },
{ "spell_pet_auras", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL },
{ "spell_proc_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL },
+ { "spell_bonus_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellBonusesCommand, "", NULL },
{ "spell_script_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL },
{ "spell_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL },
{ "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL },
@@ -302,7 +327,6 @@ ChatCommand * ChatHandler::getCommandTable()
{ "waypoint_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadWpScriptsCommand, "", NULL },
{ "gm_tickets", SEC_ADMINISTRATOR, true, &ChatHandler::HandleGMTicketReloadCommand, "", NULL },
- { "", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
@@ -435,6 +459,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "info", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcInfoCommand, "", NULL },
{ "playemote", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcPlayEmoteCommand, "", NULL },
{ "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL },
+ { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetPhaseCommand, "", NULL },
{ "unfollow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcUnFollowCommand, "", NULL },
{ "whisper", SEC_MODERATOR, false, &ChatHandler::HandleNpcWhisperCommand, "", NULL },
{ "yell", SEC_MODERATOR, false, &ChatHandler::HandleNpcYellCommand, "", NULL },
@@ -468,12 +493,13 @@ ChatCommand * ChatHandler::getCommandTable()
{
{ "add", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectCommand, "", NULL },
{ "delete", SEC_GAMEMASTER, false, &ChatHandler::HandleDelObjectCommand, "", NULL },
- { "target", SEC_GAMEMASTER, false, &ChatHandler::HandleTargetObjectCommand, "", NULL },
- { "turn", SEC_GAMEMASTER, false, &ChatHandler::HandleTurnObjectCommand, "", NULL },
{ "move", SEC_GAMEMASTER, false, &ChatHandler::HandleMoveObjectCommand, "", NULL },
{ "near", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNearObjectCommand, "", NULL },
{ "activate", SEC_GAMEMASTER, false, &ChatHandler::HandleActivateObjectCommand, "", NULL },
{ "addtemp", SEC_GAMEMASTER, false, &ChatHandler::HandleTempGameObjectCommand, "", NULL },
+ { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleGOPhaseCommand, "", NULL },
+ { "target", SEC_GAMEMASTER, false, &ChatHandler::HandleTargetObjectCommand, "", NULL },
+ { "turn", SEC_GAMEMASTER, false, &ChatHandler::HandleTurnObjectCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
@@ -609,6 +635,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "sendmail", SEC_MODERATOR, true, &ChatHandler::HandleSendMailCommand, "", NULL },
{ "sendmoney", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMoneyCommand, "", NULL },
{ "rename", SEC_GAMEMASTER, true, &ChatHandler::HandleRenameCommand, "", NULL },
+ { "customize", SEC_GAMEMASTER, true, &ChatHandler::HandleCustomizeCommand, "", NULL },
{ "loadscripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLoadScriptsCommand, "", NULL },
{ "mute", SEC_GAMEMASTER, true, &ChatHandler::HandleMuteCommand, "", NULL },
{ "unmute", SEC_GAMEMASTER, true, &ChatHandler::HandleUnmuteCommand, "", NULL },
@@ -686,6 +713,55 @@ bool ChatHandler::isAvailable(ChatCommand const& cmd) const
return m_session->GetSecurity() >= cmd.SecurityLevel;
}
+bool ChatHandler::HasLowerSecurity(Player* target, uint64 guid, bool strong)
+{
+ WorldSession* target_session = NULL;
+ uint32 target_account = 0;
+
+ if (target)
+ target_session = target->GetSession();
+ else if (guid)
+ target_account = objmgr.GetPlayerAccountIdByGUID(guid);
+
+ if(!target_session && !target_account)
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
+ return true;
+ }
+
+ return HasLowerSecurityAccount(target_session,target_account,strong);
+}
+
+bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_account, bool strong)
+{
+ uint32 target_sec;
+
+ // allow everything from console and RA console
+ if (!m_session)
+ return false;
+
+ // ignore only for non-players for non strong checks (when allow apply command at least to same sec level)
+ if (m_session->GetSecurity() > SEC_PLAYER && !strong && !sWorld.getConfig(CONFIG_GM_LOWER_SECURITY))
+ return false;
+
+ if (target)
+ target_sec = target->GetSecurity();
+ else if (target_account)
+ target_sec = accmgr.GetSecurity(target_account);
+ else
+ return true; // caller must report error for (target==NULL && target_account==0)
+
+ if (m_session->GetSecurity() < target_sec || strong && m_session->GetSecurity() <= target_sec)
+ {
+ SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
+ SetSentErrorMessage(true);
+ return true;
+ }
+
+ return false;
+}
+
bool ChatHandler::hasStringAbbr(const char* name, const char* part)
{
// non "" command
@@ -771,9 +847,9 @@ void ChatHandler::PSendSysMessage(int32 entry, ...)
{
const char *format = GetTrinityString(entry);
va_list ap;
- char str [1024];
+ char str [2048];
va_start(ap, entry);
- vsnprintf(str,1024,format, ap );
+ vsnprintf(str,2048,format, ap );
va_end(ap);
SendSysMessage(str);
}
@@ -781,9 +857,9 @@ void ChatHandler::PSendSysMessage(int32 entry, ...)
void ChatHandler::PSendSysMessage(const char *format, ...)
{
va_list ap;
- char str [1024];
+ char str [2048];
va_start(ap, format);
- vsnprintf(str,1024,format, ap );
+ vsnprintf(str,2048,format, ap );
va_end(ap);
SendSysMessage(str);
}
@@ -1099,7 +1175,7 @@ Creature* ChatHandler::getSelectedCreature()
if(!m_session)
return NULL;
- return ObjectAccessor::GetCreatureOrPet(*m_session->GetPlayer(),m_session->GetPlayer()->GetSelection());
+ return ObjectAccessor::GetCreatureOrPetOrVehicle(*m_session->GetPlayer(),m_session->GetPlayer()->GetSelection());
}
char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** something1)
@@ -1170,12 +1246,23 @@ char* ChatHandler::extractKeyFromLink(char* text, char const* const* linkTypes,
// [name] Shift-click form |color|linkType:key|h[name]|h|r
// or
// [name] Shift-click form |color|linkType:key:something1:...:somethingN|h[name]|h|r
+ // or
+ // [name] Shift-click form |linkType:key|h[name]|h|r
- char* check = strtok(text, "|"); // skip color
- if(!check)
- return NULL; // end of data
+ char* tail;
- char* cLinkType = strtok(NULL, ":"); // linktype
+ if(text[1]=='c')
+ {
+ char* check = strtok(text, "|"); // skip color
+ if(!check)
+ return NULL; // end of data
+
+ tail = strtok(NULL, ""); // tail
+ }
+ else
+ tail = text+1; // skip first |
+
+ char* cLinkType = strtok(tail, ":"); // linktype
if(!cLinkType)
return NULL; // end of data
@@ -1251,8 +1338,8 @@ GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
- Trinity::GameObjectWithDbGUIDCheck go_check(*pl,lowguid);
- Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(obj,go_check);
+ MaNGOS::GameObjectWithDbGUIDCheck go_check(*pl,lowguid);
+ MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(pl,obj,go_check);
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -1262,9 +1349,18 @@ GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid
return obj;
}
-static char const* const spellTalentKeys[] = {
- "Hspell",
- "Htalent",
+enum SpellLinkType
+{
+ SPELL_LINK_SPELL = 0,
+ SPELL_LINK_TALENT = 1,
+ SPELL_LINK_TRADE = 2
+};
+
+static char const* const spellKeys[] =
+{
+ "Hspell", // normal spell
+ "Htalent", // talent spell
+ "Htrade", // profession/skill spell
0
};
@@ -1272,31 +1368,41 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text)
{
// number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r
// number or [name] Shift-click form |color|Htalent:talent_id,rank|h[name]|h|r
+ // number or [name] Shift-click form |color|Htrade:spell_id,skill_id,max_value,cur_value|h[name]|h|r
int type = 0;
- char* rankS = NULL;
- char* idS = extractKeyFromLink(text,spellTalentKeys,&type,&rankS);
+ char* param1_str = NULL;
+ char* idS = extractKeyFromLink(text,spellKeys,&type,&param1_str);
if(!idS)
return 0;
uint32 id = (uint32)atol(idS);
- // spell
- if(type==0)
- return id;
+ switch(type)
+ {
+ case SPELL_LINK_SPELL:
+ return id;
+ case SPELL_LINK_TALENT:
+ {
+ // talent
+ TalentEntry const* talentEntry = sTalentStore.LookupEntry(id);
+ if(!talentEntry)
+ return 0;
- // talent
- TalentEntry const* talentEntry = sTalentStore.LookupEntry(id);
- if(!talentEntry)
- return 0;
+ int32 rank = param1_str ? (uint32)atol(param1_str) : 0;
+ if(rank >= 5)
+ return 0;
- int32 rank = rankS ? (uint32)atol(rankS) : 0;
- if(rank >= 5)
- return 0;
+ if(rank < 0)
+ rank = 0;
- if(rank < 0)
- rank = 0;
+ return talentEntry->RankID[rank];
+ }
+ case SPELL_LINK_TRADE:
+ return id;
+ }
- return talentEntry->RankID[rank];
+ // unknown type?
+ return 0;
}
GameTele const* ChatHandler::extractGameTeleFromLink(char* text)
@@ -1314,9 +1420,84 @@ GameTele const* ChatHandler::extractGameTeleFromLink(char* text)
return objmgr.GetGameTele(cId);
}
-const char *ChatHandler::GetName() const
+enum GuidLinkType
+{
+ SPELL_LINK_PLAYER = 0, // must be first for selection in not link case
+ SPELL_LINK_CREATURE = 1,
+ SPELL_LINK_GAMEOBJECT = 2
+};
+
+static char const* const guidKeys[] =
+{
+ "Hplayer",
+ "Hcreature",
+ "Hgameobject",
+ 0
+};
+
+uint64 ChatHandler::extractGuidFromLink(char* text)
{
- return m_session->GetPlayer()->GetName();
+ int type = 0;
+
+ // |color|Hcreature:creature_guid|h[name]|h|r
+ // |color|Hgameobject:go_guid|h[name]|h|r
+ // |color|Hplayer:name|h[name]|h|r
+ char* idS = extractKeyFromLink(text,guidKeys,&type);
+ if(!idS)
+ return 0;
+
+ switch(type)
+ {
+ case SPELL_LINK_PLAYER:
+ {
+ std::string name = idS;
+ if(!normalizePlayerName(name))
+ return 0;
+
+ if(Player* player = objmgr.GetPlayer(name.c_str()))
+ return player->GetGUID();
+
+ if(uint64 guid = objmgr.GetPlayerGUIDByName(name))
+ return guid;
+
+ return 0;
+ }
+ case SPELL_LINK_CREATURE:
+ {
+ uint32 lowguid = (uint32)atol(idS);
+
+ if(CreatureData const* data = objmgr.GetCreatureData(lowguid) )
+ return MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT);
+ else
+ return 0;
+ }
+ case SPELL_LINK_GAMEOBJECT:
+ {
+ uint32 lowguid = (uint32)atol(idS);
+
+ if(GameObjectData const* data = objmgr.GetGOData(lowguid) )
+ return MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_GAMEOBJECT);
+ else
+ return 0;
+ }
+ }
+
+ // unknown type?
+ return 0;
+}
+
+std::string ChatHandler::extractPlayerNameFromLink(char* text)
+{
+ // |color|Hplayer:name|h[name]|h|r
+ char* name_str = extractKeyFromLink(text,"Hplayer");
+ if(!name_str)
+ return "";
+
+ std::string name = name_str;
+ if(!normalizePlayerName(name))
+ return "";
+
+ return name;
}
bool ChatHandler::needReportToTarget(Player* chr) const
@@ -1342,7 +1523,7 @@ void CliHandler::SendSysMessage(const char *str)
m_print("\r\n");
}
-const char *CliHandler::GetName() const
+std::string CliHandler::GetNameLink() const
{
return GetTrinityString(LANG_CONSOLE_COMMAND);
}
diff --git a/src/game/Chat.h b/src/game/Chat.h
index 90936c9ac91..a6329215e2f 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -71,9 +71,6 @@ class ChatHandler
std::string PGetParseString(int32 entry, ...);
int ParseCommands(const char* text);
-
- virtual char const* GetName() const;
-
protected:
explicit ChatHandler() : m_session(NULL) {} // for CLI subclass
@@ -81,6 +78,8 @@ class ChatHandler
virtual bool isAvailable(ChatCommand const& cmd) const;
virtual bool needReportToTarget(Player* chr) const;
+ bool HasLowerSecurity(Player* target, uint64 guid, bool strong = false);
+ bool HasLowerSecurityAccount(WorldSession* target, uint32 account, bool strong = false);
void SendGlobalSysMessage(const char *str);
void SendGlobalGMSysMessage(const char *str);
@@ -166,6 +165,7 @@ class ChatHandler
bool HandleModifyHPCommand(const char* args);
bool HandleModifyManaCommand(const char* args);
bool HandleModifyRageCommand(const char* args);
+ bool HandleModifyRunicPowerCommand(const char* args);
bool HandleModifyEnergyCommand(const char* args);
bool HandleModifyMoneyCommand(const char* args);
bool HandleModifyASpeedCommand(const char* args);
@@ -182,6 +182,7 @@ class ChatHandler
bool HandleModifyHonorCommand (const char* args);
bool HandleModifyRepCommand(const char* args);
bool HandleModifyArenaCommand(const char* args);
+ bool HandleModifyPhaseCommand(const char* args);
bool HandleModifyGenderCommand(const char* args);
bool HandleNpcAddCommand(const char* args);
@@ -197,6 +198,7 @@ class ChatHandler
bool HandleNpcSayCommand(const char* args);
bool HandleNpcSetModelCommand(const char* args);
bool HandleNpcSetMoveTypeCommand(const char* args);
+ bool HandleNpcSetPhaseCommand(const char* args);
bool HandleNpcSpawnDistCommand(const char* args);
bool HandleNpcSpawnTimeCommand(const char* args);
bool HandleNpcTameCommand(const char* args);
@@ -206,7 +208,6 @@ class ChatHandler
bool HandleNpcYellCommand(const char* args);
bool HandleNpcAddFormationCommand(const char* args);
- bool HandleReloadCommand(const char* args);
bool HandleReloadAllCommand(const char* args);
bool HandleReloadAllAreaCommand(const char* args);
bool HandleReloadAllItemCommand(const char* args);
@@ -237,11 +238,13 @@ class ChatHandler
bool HandleReloadLootTemplatesFishingCommand(const char* args);
bool HandleReloadLootTemplatesGameobjectCommand(const char* args);
bool HandleReloadLootTemplatesItemCommand(const char* args);
+ bool HandleReloadLootTemplatesMillingCommand(const char* args);
bool HandleReloadLootTemplatesPickpocketingCommand(const char* args);
bool HandleReloadLootTemplatesProspectingCommand(const char* args);
bool HandleReloadLootTemplatesReferenceCommand(const char* args);
bool HandleReloadLootTemplatesQuestMailCommand(const char* args);
bool HandleReloadLootTemplatesSkinningCommand(const char* args);
+ bool HandleReloadLootTemplatesSpellCommand(const char* args);
bool HandleReloadTrinityStringCommand(const char* args);
bool HandleReloadNpcGossipCommand(const char* args);
bool HandleReloadNpcOptionCommand(const char* args);
@@ -260,6 +263,7 @@ class ChatHandler
bool HandleReloadSpellElixirCommand(const char* args);
bool HandleReloadSpellLearnSpellCommand(const char* args);
bool HandleReloadSpellProcEventCommand(const char* args);
+ bool HandleReloadSpellBonusesCommand(const char* args);
bool HandleReloadSpellScriptTargetCommand(const char* args);
bool HandleReloadSpellScriptsCommand(const char* args);
bool HandleReloadSpellTargetPositionCommand(const char* args);
@@ -321,6 +325,7 @@ class ChatHandler
bool HandleTargetObjectCommand(const char* args);
bool HandleDelObjectCommand(const char* args);
bool HandleMoveObjectCommand(const char* args);
+ bool HandleGOPhaseCommand(const char* args);
bool HandleTurnObjectCommand(const char* args);
bool HandleObjectStateCommand(const char* args);
bool HandlePInfoCommand(const char* args);
@@ -452,6 +457,7 @@ class ChatHandler
bool HandleSendChannelNotifyCommand(const char* args);
bool HandleSendChatMsgCommand(const char* args);
bool HandleRenameCommand(const char * args);
+ bool HandleCustomizeCommand(const char * args);
bool HandleLoadPDumpCommand(const char *args);
bool HandleWritePDumpCommand(const char *args);
bool HandleCastCommand(const char *args);
@@ -488,15 +494,25 @@ class ChatHandler
bool HandleUnPossessCommand(const char* args);
bool HandleBindSightCommand(const char* args);
bool HandleUnbindSightCommand(const char* args);
+ bool HandleSpawnVehicle(const char * args);
+ bool HandleSendLargePacketCommand(const char * args);
Player* getSelectedPlayer();
Creature* getSelectedCreature();
Unit* getSelectedUnit();
+
char* extractKeyFromLink(char* text, char const* linkType, char** something1 = NULL);
char* extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1 = NULL);
+
uint32 extractSpellIdFromLink(char* text);
+ uint64 extractGuidFromLink(char* text);
GameTele const* extractGameTeleFromLink(char* text);
bool GetPlayerGroupAndGUIDByName(const char* cname, Player* &plr, Group* &group, uint64 &guid, bool offline = false);
+ std::string extractPlayerNameFromLink(char* text);
+
+ std::string playerLink(std::string const& name) const { return m_session ? "|cffffffff|Hplayer:"+name+"|h["+name+"]|h|r" : name; }
+ virtual std::string GetNameLink() const { return GetNameLink(m_session->GetPlayer()); }
+ std::string GetNameLink(Player* chr) const { return playerLink(chr->GetName()); }
GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry);
@@ -523,11 +539,11 @@ class CliHandler : public ChatHandler
typedef void Print(char const*);
explicit CliHandler(Print* zprint) : m_print(zprint) {}
- // overwrite functions
- const char *GetTrinityString(int32 entry) const;
- bool isAvailable(ChatCommand const& cmd) const;
- void SendSysMessage(const char *str);
- char const* GetName() const;
+ // overwrite functions
+ const char *GetTrinityString(int32 entry) const;
+ bool isAvailable(ChatCommand const& cmd) const;
+ void SendSysMessage(const char *str);
+ std::string GetNameLink() const;
bool needReportToTarget(Player* chr) const;
private:
diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp
index 9c603bf3e2d..ea59facefd9 100644
--- a/src/game/ChatHandler.cpp
+++ b/src/game/ChatHandler.cpp
@@ -192,7 +192,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
Player *player = objmgr.GetPlayer(to.c_str());
uint32 tSecurity = GetSecurity();
- uint32 pSecurity = player ? player->GetSession()->GetSecurity() : 0;
+ uint32 pSecurity = player ? player->GetSession()->GetSecurity() : SEC_PLAYER;
if(!player || tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers())
{
WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1));
diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp
index 989ccd61151..071074de75b 100644
--- a/src/game/Corpse.cpp
+++ b/src/game/Corpse.cpp
@@ -36,7 +36,7 @@ Corpse::Corpse(CorpseType type) : WorldObject()
m_objectType |= TYPEMASK_CORPSE;
m_objectTypeId = TYPEID_CORPSE;
// 2.3.2 - 0x58
- m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION);
+ m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION);
m_valuesCount = CORPSE_END;
@@ -71,26 +71,26 @@ bool Corpse::Create( uint32 guidlow )
return true;
}
-bool Corpse::Create( uint32 guidlow, Player *owner, uint32 mapid, float x, float y, float z, float ang )
+bool Corpse::Create( uint32 guidlow, Player *owner)
{
SetInstanceId(owner->GetInstanceId());
- WorldObject::_Create(guidlow, HIGHGUID_CORPSE, mapid);
+ WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetMapId(), owner->GetPhaseMask());
- Relocate(x,y,z,ang);
+ Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation());
if(!IsPositionValid())
{
sLog.outError("ERROR: Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
- guidlow,owner->GetName(),x,y);
+ guidlow,owner->GetName(),owner->GetPositionX(), owner->GetPositionY());
return false;
}
SetFloatValue( OBJECT_FIELD_SCALE_X, 1 );
- SetFloatValue( CORPSE_FIELD_POS_X, x );
- SetFloatValue( CORPSE_FIELD_POS_Y, y );
- SetFloatValue( CORPSE_FIELD_POS_Z, z );
- SetFloatValue( CORPSE_FIELD_FACING, ang );
+ SetFloatValue( CORPSE_FIELD_POS_X, GetPositionX() );
+ SetFloatValue( CORPSE_FIELD_POS_Y, GetPositionY() );
+ SetFloatValue( CORPSE_FIELD_POS_Z, GetPositionZ() );
+ SetFloatValue( CORPSE_FIELD_FACING, GetOrientation() );
SetUInt64Value( CORPSE_FIELD_OWNER, owner->GetGUID() );
m_grid = Trinity::ComputeGridPair(GetPositionX(), GetPositionY());
@@ -100,17 +100,18 @@ bool Corpse::Create( uint32 guidlow, Player *owner, uint32 mapid, float x, float
void Corpse::SaveToDB()
{
- // prevent DB data inconsistance problems and duplicates
+ // prevent DB data inconsistence problems and duplicates
CharacterDatabase.BeginTransaction();
DeleteFromDB();
std::ostringstream ss;
- ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance) VALUES ("
+ ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance,phaseMask) VALUES ("
<< GetGUIDLow() << ", " << GUID_LOPART(GetOwnerGUID()) << ", " << GetPositionX() << ", " << GetPositionY() << ", " << GetPositionZ() << ", "
<< GetOrientation() << ", " << GetZoneId() << ", " << GetMapId() << ", '";
for(uint16 i = 0; i < m_valuesCount; i++ )
ss << GetUInt32Value(i) << " ";
- ss << "'," << uint64(m_time) <<", " << uint32(GetType()) << ", " << int(GetInstanceId()) << ")";
+ ss << "'," << uint64(m_time) <<", " << uint32(GetType())
+ << ", " << int(GetInstanceId()) << ", " << int(GetPhaseMask()) << ")";
CharacterDatabase.Execute( ss.str().c_str() );
CharacterDatabase.CommitTransaction();
}
@@ -143,8 +144,8 @@ bool Corpse::LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId)
{
bool external = (result != NULL);
if (!external)
- // 0 1 2 3 4 5 6 7 8
- result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance FROM corpse WHERE guid = '%u'",guid);
+ // 0 1 2 3 4 5 6 7 8 9
+ result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance,phaseMask FROM corpse WHERE guid = '%u'",guid);
if( ! result )
{
@@ -166,8 +167,8 @@ bool Corpse::LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId)
bool Corpse::LoadFromDB(uint32 guid, Field *fields)
{
- // 0 1 2 3 4 5 6 7 8
- //result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance FROM corpse WHERE guid = '%u'",guid);
+ // 0 1 2 3 4 5 6 7 8 9
+ //result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance,phaseMask FROM corpse WHERE guid = '%u'",guid);
float positionX = fields[0].GetFloat();
float positionY = fields[1].GetFloat();
float positionZ = fields[2].GetFloat();
@@ -188,6 +189,7 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields)
return false;
}
uint32 instanceid = fields[8].GetUInt32();
+ uint32 phaseMask = fields[9].GetUInt32();
// overwrite possible wrong/corrupted guid
SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_CORPSE));
@@ -195,6 +197,7 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields)
// place
SetInstanceId(instanceid);
SetMapId(mapid);
+ SetPhaseMask(phaseMask,false);
Relocate(positionX,positionY,positionZ,ort);
if(!IsPositionValid())
diff --git a/src/game/Corpse.h b/src/game/Corpse.h
index 3cd6299a494..1616269d999 100644
--- a/src/game/Corpse.h
+++ b/src/game/Corpse.h
@@ -58,7 +58,7 @@ class Corpse : public WorldObject
void RemoveFromWorld();
bool Create( uint32 guidlow );
- bool Create( uint32 guidlow, Player *owner, uint32 mapid, float x, float y, float z, float ang );
+ bool Create( uint32 guidlow, Player *owner );
void SaveToDB();
bool LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId);
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 9949effb975..9ff0e7a1f8e 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -145,11 +145,12 @@ Unit(), i_AI(NULL), i_AI_possessed(NULL),
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
m_lootMoney(0), m_lootRecipient(0),
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
-m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false), m_reactState(REACT_AGGRESSIVE),
-m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
+m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false), m_isVehicle(false), m_reactState(REACT_AGGRESSIVE),
+m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
m_AlreadyCallAssistance(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false),
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL), m_DBTableGuid(0), m_formationID(0)
{
+ m_regenTimer = 200;
m_valuesCount = UNIT_END;
for(int i =0; i<4; ++i)
@@ -316,7 +317,6 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data )
// creatures always have melee weapon ready if any
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
- SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_AURAS );
SelectLevel(GetCreatureInfo());
if (team == HORDE)
@@ -360,10 +360,8 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data )
SetPvP(true);
}
- m_spells[0] = GetCreatureInfo()->spell1;
- m_spells[1] = GetCreatureInfo()->spell2;
- m_spells[2] = GetCreatureInfo()->spell3;
- m_spells[3] = GetCreatureInfo()->spell4;
+ for(int i=0; i < CREATURE_MAX_SPELLS; ++i)
+ m_spells[i] = GetCreatureInfo()->spells[i];
// HACK: trigger creature is always not selectable
if(isTrigger())
@@ -637,11 +635,11 @@ void Creature::DisablePossessedAI()
m_AI_enabled = true;
}
-bool Creature::Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data)
+bool Creature::Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 team, const CreatureData *data)
{
SetMapId(map->GetId());
SetInstanceId(map->GetInstanceId());
- //m_DBTableGuid = guidlow;
+ SetPhaseMask(phaseMask,false);
//oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0;
const bool bResult = CreateFromProto(guidlow, Entry, team, data);
@@ -778,8 +776,11 @@ bool Creature::isCanInteractWithBattleMaster(Player* pPlayer, bool msg) const
case BATTLEGROUND_NA:
case BATTLEGROUND_BE:
case BATTLEGROUND_AA:
- case BATTLEGROUND_RL: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break;
- break;
+ case BATTLEGROUND_RL:
+ case BATTLEGROUND_SA:
+ case BATTLEGROUND_DS:
+ case BATTLEGROUND_RV: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break;
+ default: break;
}
return false;
}
@@ -921,13 +922,11 @@ void Creature::sendPreparedGossip(Player* player)
if(!player)
return;
- GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu();
-
if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_WORLDEVENT) // if world event npc then
gameeventmgr.HandleWorldEventGossip(player, this); // update world state with progress
// in case empty gossip menu open quest menu if any
- if (gossipmenu.Empty() && GetNpcTextId() == 0)
+ if (player->PlayerTalkClass->GetGossipMenu().Empty() && !player->PlayerTalkClass->GetQuestMenu().Empty())
{
player->SendPreparedQuest(GetGUID());
return;
@@ -1191,10 +1190,10 @@ void Creature::SaveToDB()
return;
}
- SaveToDB(GetMapId(), data->spawnMask);
+ SaveToDB(GetMapId(), data->spawnMask,GetPhaseMask());
}
-void Creature::SaveToDB(uint32 mapid, uint8 spawnMask)
+void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
{
// update in loaded data
if (!m_DBTableGuid)
@@ -1214,6 +1213,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask)
// data->guid = guid don't must be update at save
data.id = GetEntry();
data.mapid = mapid;
+ data.phaseMask = phaseMask;
data.displayid = displayId;
data.equipmentId = GetEquipmentId();
data.posX = GetPositionX();
@@ -1243,6 +1243,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask)
<< GetEntry() << ","
<< mapid <<","
<< (uint32)spawnMask << ","
+ << (uint32)GetPhaseMask() << ","
<< displayId <<","
<< GetEquipmentId() <<","
<< GetPositionX() << ","
@@ -1412,7 +1413,7 @@ bool Creature::LoadFromDB(uint32 guid, Map *map)
if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_UNIT);
uint16 team = 0;
- if(!Create(guid,map,data->id,team,data))
+ if(!Create(guid,map,data->phaseMask,data->id,team,data))
return false;
Relocate(data->posX,data->posY,data->posZ,data->orientation);
@@ -1473,11 +1474,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force)
if (force)
{
for (uint8 i = 0; i < 3; i++)
- {
- SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, 0);
- SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), 0);
- SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, 0);
- }
+ SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, 0);
m_equipmentId = 0;
}
return;
@@ -1489,11 +1486,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force)
m_equipmentId = equip_entry;
for (uint8 i = 0; i < 3; i++)
- {
- SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, einfo->equipmodel[i]);
- SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), einfo->equipinfo[i]);
- SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, einfo->equipslot[i]);
- }
+ SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, einfo->equipentry[i]);
}
bool Creature::hasQuest(uint32 quest_id) const
@@ -1551,6 +1544,10 @@ bool Creature::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList, bo
if (u == this)
return true;
+ // phased visibility (both must phased in same way)
+ if(!InSamePhase(u))
+ return false;
+
// always seen by owner
if(GetGUID() == u->GetCharmerOrOwnerGUID())
return true;
@@ -1721,7 +1718,7 @@ void Creature::Respawn()
}
}
-bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges)
+bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo)
{
if (!spellInfo)
return false;
@@ -1729,15 +1726,15 @@ bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges)
if (GetCreatureInfo()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1)))
return true;
- return Unit::IsImmunedToSpell(spellInfo, useCharges);
+ return Unit::IsImmunedToSpell(spellInfo);
}
-bool Creature::IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const
+bool Creature::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const
{
- if (GetCreatureInfo()->MechanicImmuneMask & (1 << (mechanic-1)))
+ if (GetCreatureInfo()->MechanicImmuneMask & (1 << (spellInfo->EffectMechanic[index] - 1)))
return true;
- return Unit::IsImmunedToSpellEffect(effect, mechanic);
+ return Unit::IsImmunedToSpellEffect(spellInfo, index);
}
SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim)
@@ -1781,7 +1778,9 @@ SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim)
// continue;
if( dist > range || dist < minrange )
continue;
- if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
+ if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
+ continue;
+ if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))
continue;
return spellInfo;
}
@@ -1825,7 +1824,9 @@ SpellEntry const *Creature::reachWithSpellCure(Unit *pVictim)
// continue;
if( dist > range || dist < minrange )
continue;
- if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
+ if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
+ continue;
+ if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))
continue;
return spellInfo;
}
@@ -1873,7 +1874,7 @@ void Creature::DoFleeToGetAssistance(float radius) // Optional parameter
Creature* pCreature = NULL;
Trinity::NearestAssistCreatureInCreatureRangeCheck u_check(this,getVictim(),radius);
- Trinity::CreatureLastSearcher<Trinity::NearestAssistCreatureInCreatureRangeCheck> searcher(pCreature, u_check);
+ Trinity::CreatureLastSearcher<Trinity::NearestAssistCreatureInCreatureRangeCheck> searcher(this, pCreature, u_check);
VisitNearbyGridObject(radius, searcher);
if(!pCreature)
@@ -1893,7 +1894,7 @@ Unit* Creature::SelectNearestTarget(float dist) const
{
Trinity::NearestHostileUnitInAttackDistanceCheck u_check(this, dist);
- Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck> searcher(target, u_check);
+ Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck> searcher(this, target, u_check);
TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
@@ -1923,8 +1924,8 @@ void Creature::CallAssistance()
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
- Trinity::AnyAssistCreatureInRangeCheck u_check(this, getVictim(), radius);
- Trinity::CreatureListSearcher<Trinity::AnyAssistCreatureInRangeCheck> searcher(assistList, u_check);
+ MaNGOS::AnyAssistCreatureInRangeCheck u_check(this, getVictim(), radius);
+ MaNGOS::CreatureListSearcher<MaNGOS::AnyAssistCreatureInRangeCheck> searcher(this, assistList, u_check);
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AnyAssistCreatureInRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher);
diff --git a/src/game/Creature.h b/src/game/Creature.h
index 14fc77cf24a..d2a4ff9fd20 100644
--- a/src/game/Creature.h
+++ b/src/game/Creature.h
@@ -176,7 +176,7 @@ struct CreatureInfo
uint32 rangeattacktime;
uint32 unit_flags; // enum UnitFlags mask values
uint32 dynamicflags;
- uint32 family; // enum CreatureFamily values for type==CREATURE_TYPE_BEAST, or 0 in another cases
+ uint32 family; // enum CreatureFamily values (optional)
uint32 trainer_type;
uint32 trainer_spell;
uint32 classNum;
@@ -195,10 +195,7 @@ struct CreatureInfo
int32 resistance4;
int32 resistance5;
int32 resistance6;
- uint32 spell1;
- uint32 spell2;
- uint32 spell3;
- uint32 spell4;
+ uint32 spells[CREATURE_MAX_SPELLS];
uint32 PetSpellDataId;
uint32 mingold;
uint32 maxgold;
@@ -221,6 +218,8 @@ struct CreatureInfo
return SKILL_HERBALISM;
else if(type_flags & CREATURE_TYPEFLAGS_MININGLOOT)
return SKILL_MINING;
+ else if(type_flags & CREATURE_TYPEFLAGS_ENGINEERLOOT)
+ return SKILL_ENGINERING;
else
return SKILL_SKINNING; // normal case
}
@@ -246,9 +245,7 @@ struct NpcOptionLocale
struct EquipmentInfo
{
uint32 entry;
- uint32 equipmodel[3];
- uint32 equipinfo[3];
- uint32 equipslot[3];
+ uint32 equipentry[3];
};
// from `creature` table
@@ -256,6 +253,7 @@ struct CreatureData
{
uint32 id; // entry in creature_template
uint16 mapid;
+ uint16 phaseMask;
uint32 displayid;
int32 equipmentId;
float posX;
@@ -374,6 +372,10 @@ struct TrainerSpell
uint32 reqskill;
uint32 reqskillvalue;
uint32 reqlevel;
+ uint32 learned_spell;
+
+ // helpers
+ bool IsCastable() const { return learned_spell != spell; }
};
typedef std::vector<TrainerSpell*> TrainerSpellList;
@@ -412,7 +414,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
void AddToWorld();
void RemoveFromWorld();
- bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data = NULL);
+ bool Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 team, const CreatureData *data = NULL);
bool LoadCreaturesAddon(bool reload = false);
void SelectLevel(const CreatureInfo *cinfo);
void LoadEquipment(uint32 equip_entry, bool force=false);
@@ -425,6 +427,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
uint32 GetEquipmentId() const { return m_equipmentId; }
bool isPet() const { return m_isPet; }
+ bool isVehicle() const { return m_isVehicle; }
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
bool isTotem() const { return m_isTotem; }
bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; }
@@ -441,9 +444,9 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool isCanInteractWithBattleMaster(Player* player, bool msg) const;
bool isCanTrainingAndResetTalentsOf(Player* pPlayer) const;
bool IsOutOfThreatArea(Unit* pVictim) const;
- bool IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges = false);
+ bool IsImmunedToSpell(SpellEntry const* spellInfo);
// redefine Unit::IsImmunedToSpell
- bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const;
+ bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const;
// redefine Unit::IsImmunedToSpellEffect
bool isElite() const
{
@@ -544,7 +547,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool LoadFromDB(uint32 guid, Map *map);
void SaveToDB();
// overwrited in Pet
- virtual void SaveToDB(uint32 mapid, uint8 spawnMask);
+ virtual void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask);
virtual void DeleteFromDB(); // overwrited in Pet
Loot loot;
@@ -660,11 +663,11 @@ class TRINITY_DLL_SPEC Creature : public Unit
uint8 m_emoteState;
bool m_isPet; // set only in Pet::Pet
+ bool m_isVehicle; // set only in Vehicle::Vehicle
bool m_isTotem; // set only in Totem::Totem
ReactStates m_reactState; // for AI, not charmInfo
void RegenerateMana();
void RegenerateHealth();
- uint32 m_regenTimer;
MovementGeneratorType m_defaultMovementType;
Cell m_currentCell; // store current cell where creature listed
uint32 m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid
diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp
index d7badd57892..90f87ad20a3 100644
--- a/src/game/DynamicObject.cpp
+++ b/src/game/DynamicObject.cpp
@@ -38,7 +38,7 @@ DynamicObject::DynamicObject() : WorldObject()
m_objectType |= TYPEMASK_DYNAMICOBJECT;
m_objectTypeId = TYPEID_DYNAMICOBJECT;
// 2.3.2 - 0x58
- m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION);
+ m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION);
m_valuesCount = DYNAMICOBJECT_END;
}
@@ -61,7 +61,7 @@ bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, uint32
{
SetInstanceId(caster->GetInstanceId());
- WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetMapId());
+ WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetMapId(), caster->GetPhaseMask());
Relocate(x,y,z,0);
if(!IsPositionValid())
diff --git a/src/game/Formulas.h b/src/game/Formulas.h
index f9915a2001c..cdfe971eba6 100644
--- a/src/game/Formulas.h
+++ b/src/game/Formulas.h
@@ -80,8 +80,17 @@ namespace Trinity
inline uint32 BaseGain(uint32 pl_level, uint32 mob_level, ContentLevels content)
{
- //TODO: need modifier for CONTENT_71_80 different from CONTENT_61_70?
- const uint32 nBaseExp = content == CONTENT_1_60 ? 45 : 235;
+ uint32 nBaseExp;
+ switch(content)
+ {
+ case CONTENT_1_60: nBaseExp = 45; break;
+ case CONTENT_61_70: nBaseExp = 235; break;
+ case CONTENT_71_80: nBaseExp = 580; break;
+ default:
+ sLog.outError("BaseGain: Unsupported content level %u",content);
+ nBaseExp = 45; break;
+ }
+
if( mob_level >= pl_level )
{
uint32 nLevelDiff = mob_level - pl_level;
@@ -118,66 +127,6 @@ namespace Trinity
return (uint32)(xp_gain*sWorld.getRate(RATE_XP_KILL));
}
- inline uint32 xp_Diff(uint32 lvl)
- {
- if( lvl < 29 )
- return 0;
- if( lvl == 29 )
- return 1;
- if( lvl == 30 )
- return 3;
- if( lvl == 31 )
- return 6;
- else
- return (5*(lvl-30));
- }
-
- inline uint32 mxp(uint32 lvl)
- {
- if (lvl < 60)
- {
- return (45 + (5*lvl));
- }
- else
- {
- return (235 + (5*lvl));
- }
- }
-
- inline uint32 xp_to_level(uint32 lvl)
- {
- uint32 xp = 0;
- if (lvl < 60)
- {
- xp = (8*lvl + xp_Diff(lvl)) * mxp(lvl);
- }
- else if (lvl == 60)
- {
- xp = (155 + mxp(lvl) * (1344 - 70 - ((69 - lvl) * (7 + (69 - lvl) * 8 - 1)/2)));
- }
- else if (lvl < 70)
- {
- xp = (155 + mxp(lvl) * (1344 - ((69-lvl) * (7 + (69 - lvl) * 8 - 1)/2)));
- }else
- {
- // level higher than 70 is not supported
- xp = (uint32)(779700 * (pow(sWorld.getRate(RATE_XP_PAST_70), (int32)lvl - 69)));
- return ((xp < 0x7fffffff) ? xp : 0x7fffffff);
- }
-
- // The XP to Level is always rounded to the nearest 100 points (50 rounded to high).
- xp = ((xp + 50) / 100) * 100; // use additional () for prevent free association operations in C++
-
- if ((lvl > 10) && (lvl < 60)) // compute discount added in 2.3.x
- {
- uint32 discount = (lvl < 28) ? (lvl - 10) : 18;
- xp = (xp * (100 - discount)) / 100; // apply discount
- xp = (xp / 100) * 100; // floor to hundreds
- }
-
- return xp;
- }
-
inline float xp_in_group_rate(uint32 count, bool isRaid)
{
if(isRaid)
diff --git a/src/game/GameEvent.cpp b/src/game/GameEvent.cpp
index 9ceed9024c4..f08ba179797 100644
--- a/src/game/GameEvent.cpp
+++ b/src/game/GameEvent.cpp
@@ -190,50 +190,52 @@ void GameEvent::LoadFromDB()
if( !result )
{
mGameEvent.clear();
- sLog.outString(">> Table game_event is empty:");
+ sLog.outString(">> Table game_event is empty!");
sLog.outString();
return;
}
uint32 count = 0;
- barGoLink bar( result->GetRowCount() );
- do
{
- ++count;
- Field *fields = result->Fetch();
+ barGoLink bar( result->GetRowCount() );
+ do
+ {
+ ++count;
+ Field *fields = result->Fetch();
- bar.step();
+ bar.step();
- uint16 event_id = fields[0].GetUInt16();
- if(event_id==0)
- {
- sLog.outErrorDb("`game_event` game event id (%i) is reserved and can't be used.",event_id);
- continue;
- }
+ uint16 event_id = fields[0].GetUInt16();
+ if(event_id==0)
+ {
+ sLog.outErrorDb("`game_event` game event id (%i) is reserved and can't be used.",event_id);
+ continue;
+ }
- GameEventData& pGameEvent = mGameEvent[event_id];
- uint64 starttime = fields[1].GetUInt64();
- pGameEvent.start = time_t(starttime);
- uint64 endtime = fields[2].GetUInt64();
- pGameEvent.end = time_t(endtime);
- pGameEvent.occurence = fields[3].GetUInt32();
- pGameEvent.length = fields[4].GetUInt32();
- pGameEvent.description = fields[5].GetCppString();
- pGameEvent.state = (GameEventState)(fields[6].GetUInt8());
- pGameEvent.nextstart = 0;
-
- if(pGameEvent.length==0 && pGameEvent.state == GAMEEVENT_NORMAL) // length>0 is validity check
- {
- sLog.outErrorDb("`game_event` game event id (%i) isn't a world event and has length = 0, thus it can't be used.",event_id);
- continue;
- }
+ GameEventData& pGameEvent = mGameEvent[event_id];
+ uint64 starttime = fields[1].GetUInt64();
+ pGameEvent.start = time_t(starttime);
+ uint64 endtime = fields[2].GetUInt64();
+ pGameEvent.end = time_t(endtime);
+ pGameEvent.occurence = fields[3].GetUInt32();
+ pGameEvent.length = fields[4].GetUInt32();
+ pGameEvent.description = fields[5].GetCppString();
+ pGameEvent.state = (GameEventState)(fields[6].GetUInt8());
+ pGameEvent.nextstart = 0;
+
+ if(pGameEvent.length==0 && pGameEvent.state == GAMEEVENT_NORMAL) // length>0 is validity check
+ {
+ sLog.outErrorDb("`game_event` game event id (%i) isn't a world event and has length = 0, thus it can't be used.",event_id);
+ continue;
+ }
- } while( result->NextRow() );
+ } while( result->NextRow() );
+ delete result;
- sLog.outString();
- sLog.outString( ">> Loaded %u game events", count );
- delete result;
+ sLog.outString();
+ sLog.outString( ">> Loaded %u game events", count );
+ }
// load game event saves
// 0 1 2
@@ -346,8 +348,8 @@ void GameEvent::LoadFromDB()
count = 0;
if( !result )
{
- barGoLink bar2(1);
- bar2.step();
+ barGoLink bar(1);
+ bar.step();
sLog.outString();
sLog.outString(">> Loaded %u creatures in game events", count );
@@ -355,12 +357,12 @@ void GameEvent::LoadFromDB()
else
{
- barGoLink bar2( result->GetRowCount() );
+ barGoLink bar( result->GetRowCount() );
do
{
Field *fields = result->Fetch();
- bar2.step();
+ bar.step();
uint32 guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt16();
@@ -378,9 +380,10 @@ void GameEvent::LoadFromDB()
crelist.push_back(guid);
} while( result->NextRow() );
+ delete result;
+
sLog.outString();
sLog.outString( ">> Loaded %u creatures in game events", count );
- delete result;
}
mGameEventGameobjectGuids.resize(mGameEvent.size()*2-1);
@@ -391,8 +394,8 @@ void GameEvent::LoadFromDB()
count = 0;
if( !result )
{
- barGoLink bar3(1);
- bar3.step();
+ barGoLink bar(1);
+ bar.step();
sLog.outString();
sLog.outString(">> Loaded %u gameobjects in game events", count );
@@ -400,12 +403,12 @@ void GameEvent::LoadFromDB()
else
{
- barGoLink bar3( result->GetRowCount() );
+ barGoLink bar( result->GetRowCount() );
do
{
Field *fields = result->Fetch();
- bar3.step();
+ bar.step();
uint32 guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt16();
@@ -423,10 +426,10 @@ void GameEvent::LoadFromDB()
golist.push_back(guid);
} while( result->NextRow() );
+ delete result;
+
sLog.outString();
sLog.outString( ">> Loaded %u gameobjects in game events", count );
-
- delete result;
}
mGameEventModelEquip.resize(mGameEvent.size());
@@ -439,8 +442,8 @@ void GameEvent::LoadFromDB()
count = 0;
if( !result )
{
- barGoLink bar3(1);
- bar3.step();
+ barGoLink bar(1);
+ bar.step();
sLog.outString();
sLog.outString(">> Loaded %u model/equipment changes in game events", count );
@@ -448,12 +451,12 @@ void GameEvent::LoadFromDB()
else
{
- barGoLink bar3( result->GetRowCount() );
+ barGoLink bar( result->GetRowCount() );
do
{
Field *fields = result->Fetch();
- bar3.step();
+ bar.step();
uint32 guid = fields[0].GetUInt32();
uint16 event_id = fields[1].GetUInt16();
@@ -483,10 +486,10 @@ void GameEvent::LoadFromDB()
equiplist.push_back(std::pair<uint32, ModelEquip>(guid, newModelEquipSet));
} while( result->NextRow() );
+ delete result;
+
sLog.outString();
sLog.outString( ">> Loaded %u model/equipment changes in game events", count );
-
- delete result;
}
mGameEventCreatureQuests.resize(mGameEvent.size());
@@ -496,8 +499,8 @@ void GameEvent::LoadFromDB()
count = 0;
if( !result )
{
- barGoLink bar3(1);
- bar3.step();
+ barGoLink bar(1);
+ bar.step();
sLog.outString();
sLog.outString(">> Loaded %u quests additions in game events", count );
@@ -505,12 +508,12 @@ void GameEvent::LoadFromDB()
else
{
- barGoLink bar3( result->GetRowCount() );
+ barGoLink bar( result->GetRowCount() );
do
{
Field *fields = result->Fetch();
- bar3.step();
+ bar.step();
uint32 id = fields[0].GetUInt32();
uint32 quest = fields[1].GetUInt32();
uint16 event_id = fields[2].GetUInt16();
@@ -569,10 +572,10 @@ void GameEvent::LoadFromDB()
questlist.push_back(QuestRelation(id, quest));
} while( result->NextRow() );
+ delete result;
+
sLog.outString();
sLog.outString( ">> Loaded %u quests additions in game events", count );
-
- delete result;
}
// Load quest to (event,condition) mapping
diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp
index 28c39ee5bbe..206e9d3f852 100644
--- a/src/game/GameObject.cpp
+++ b/src/game/GameObject.cpp
@@ -46,7 +46,7 @@ GameObject::GameObject() : WorldObject()
m_objectType |= TYPEMASK_GAMEOBJECT;
m_objectTypeId = TYPEID_GAMEOBJECT;
// 2.3.2 - 0x58
- m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION);
+ m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION);
m_valuesCount = GAMEOBJECT_END;
m_respawnTime = 0;
@@ -93,11 +93,12 @@ void GameObject::RemoveFromWorld()
WorldObject::RemoveFromWorld();
}
-bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state, uint32 ArtKit)
+bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state, uint32 ArtKit)
{
Relocate(x,y,z,ang);
SetMapId(map->GetId());
SetInstanceId(map->GetInstanceId());
+ SetPhaseMask(phaseMask,false);
if(!IsPositionValid())
{
@@ -127,17 +128,33 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float
SetFloatValue(GAMEOBJECT_POS_Z, z);
SetFloatValue(GAMEOBJECT_FACING, ang); //this is not facing angle
- SetFloatValue (GAMEOBJECT_ROTATION, rotation0);
- SetFloatValue (GAMEOBJECT_ROTATION+1, rotation1);
- SetFloatValue (GAMEOBJECT_ROTATION+2, rotation2);
- SetFloatValue (GAMEOBJECT_ROTATION+3, rotation3);
+ int64 rotation = 0;
+
+ float f_rot1 = sin(ang / 2.0f);
+ int64 i_rot1 = f_rot1 / atan(pow(2.0f, -20.0f));
+ rotation |= (i_rot1 << 43 >> 43) & 0x00000000001FFFFF;
+
+ //float f_rot2 = sin(0.0f / 2.0f);
+ //int64 i_rot2 = f_rot2 / atan(pow(2.0f, -20.0f));
+ //rotation |= (((i_rot2 << 22) >> 32) >> 11) & 0x000003FFFFE00000;
+
+ //float f_rot3 = sin(0.0f / 2.0f);
+ //int64 i_rot3 = f_rot3 / atan(pow(2.0f, -21.0f));
+ //rotation |= (i_rot3 >> 42) & 0x7FFFFC0000000000;
+
+ SetUInt64Value(GAMEOBJECT_ROTATION, rotation);
+
+ SetFloatValue(GAMEOBJECT_PARENTROTATION+0, rotation0);
+ SetFloatValue(GAMEOBJECT_PARENTROTATION+1, rotation1);
+ SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2);
+ SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3);
SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size);
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
- SetUInt32Value(OBJECT_FIELD_ENTRY, goinfo->id);
+ SetEntry(goinfo->id);
SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId);
@@ -146,7 +163,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float
SetGoAnimProgress(animprogress);
- SetUInt32Value (GAMEOBJECT_ARTKIT, ArtKit);
+ SetByteValue(GAMEOBJECT_BYTES_1, 2, ArtKit);
// Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22)
if (goinfo->type == GAMEOBJECT_TYPE_SPELLCASTER)
@@ -264,7 +281,7 @@ void GameObject::Update(uint32 /*p_time*/)
return;
}
// respawn timer
- MapManager::Instance().GetMap(GetMapId(), this)->Add(this);
+ GetMap()->Add(this);
break;
}
}
@@ -309,8 +326,8 @@ void GameObject::Update(uint32 /*p_time*/)
// search unfriendly creature
if(owner && NeedDespawn) // hunter trap
{
- Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius);
- Trinity::UnitSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> checker(ok, u_check);
+ MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius);
+ MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(this,ok, u_check);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -330,8 +347,8 @@ void GameObject::Update(uint32 /*p_time*/)
// affect only players
Player* p_ok = NULL;
- Trinity::AnyPlayerInObjectRangeCheck p_check(this, radius);
- Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck> checker(p_ok, p_check);
+ MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius);
+ MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> checker(this,p_ok, p_check);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -344,8 +361,8 @@ void GameObject::Update(uint32 /*p_time*/)
{
//Unit *caster = owner ? owner : ok;
- //caster->CastSpell(ok, goInfo->trap.spellId, true);
CastSpell(ok, goInfo->trap.spellId);
+ //caster->CastSpell(ok, goInfo->trap.spellId, true, 0, 0, GetGUID());
m_cooldownTime = time(NULL) + 4; // 4 seconds
if(NeedDespawn)
@@ -395,7 +412,7 @@ void GameObject::Update(uint32 /*p_time*/)
for (; it != end; it++)
{
Unit* owner = Unit::GetUnit(*this, uint64(*it));
- if (owner) owner->CastSpell(owner, spellId, false);
+ if (owner) owner->CastSpell(owner, spellId, false, 0, 0, GetGUID());
}
m_unique_users.clear();
@@ -414,7 +431,7 @@ void GameObject::Update(uint32 /*p_time*/)
//burning flags in some battlegrounds, if you find better condition, just add it
if (GetGoAnimProgress() > 0)
{
- SendObjectDeSpawnAnim(this->GetGUID());
+ SendObjectDeSpawnAnim(GetGUID());
//reset flags
SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags);
}
@@ -451,7 +468,7 @@ void GameObject::Refresh()
return;
if(isSpawned())
- MapManager::Instance().GetMap(GetMapId(), this)->Add(this);
+ GetMap()->Add(this);
}
void GameObject::AddUniqueUse(Player* player)
@@ -495,16 +512,16 @@ void GameObject::SaveToDB()
return;
}
- SaveToDB(GetMapId(), data->spawnMask);
+ SaveToDB(GetMapId(), data->spawnMask, data->phaseMask);
}
-void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask)
+void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
{
const GameObjectInfo *goI = GetGOInfo();
if (!goI)
return;
-
+
if (!m_DBTableGuid)
m_DBTableGuid = GetGUIDLow();
// update in loaded data (changing data only in this place)
@@ -513,38 +530,40 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask)
// data->guid = guid don't must be update at save
data.id = GetEntry();
data.mapid = mapid;
+ data.phaseMask = phaseMask;
data.posX = GetFloatValue(GAMEOBJECT_POS_X);
data.posY = GetFloatValue(GAMEOBJECT_POS_Y);
data.posZ = GetFloatValue(GAMEOBJECT_POS_Z);
data.orientation = GetFloatValue(GAMEOBJECT_FACING);
- data.rotation0 = GetFloatValue(GAMEOBJECT_ROTATION+0);
- data.rotation1 = GetFloatValue(GAMEOBJECT_ROTATION+1);
- data.rotation2 = GetFloatValue(GAMEOBJECT_ROTATION+2);
- data.rotation3 = GetFloatValue(GAMEOBJECT_ROTATION+3);
+ data.rotation0 = GetFloatValue(GAMEOBJECT_PARENTROTATION+0);
+ data.rotation1 = GetFloatValue(GAMEOBJECT_PARENTROTATION+1);
+ data.rotation2 = GetFloatValue(GAMEOBJECT_PARENTROTATION+2);
+ data.rotation3 = GetFloatValue(GAMEOBJECT_PARENTROTATION+3);
data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime;
data.animprogress = GetGoAnimProgress();
data.go_state = GetGoState();
data.spawnMask = spawnMask;
- data.ArtKit = GetUInt32Value (GAMEOBJECT_ARTKIT);
+ data.ArtKit = GetGoArtKit();
// updated in DB
std::ostringstream ss;
ss << "INSERT INTO gameobject VALUES ( "
<< m_DBTableGuid << ", "
- << GetUInt32Value (OBJECT_FIELD_ENTRY) << ", "
+ << GetEntry() << ", "
<< mapid << ", "
<< (uint32)spawnMask << ", "
+ << (uint32)GetPhaseMask() << ","
<< GetFloatValue(GAMEOBJECT_POS_X) << ", "
<< GetFloatValue(GAMEOBJECT_POS_Y) << ", "
<< GetFloatValue(GAMEOBJECT_POS_Z) << ", "
<< GetFloatValue(GAMEOBJECT_FACING) << ", "
- << GetFloatValue(GAMEOBJECT_ROTATION) << ", "
- << GetFloatValue(GAMEOBJECT_ROTATION+1) << ", "
- << GetFloatValue(GAMEOBJECT_ROTATION+2) << ", "
- << GetFloatValue(GAMEOBJECT_ROTATION+3) << ", "
+ << GetFloatValue(GAMEOBJECT_PARENTROTATION) << ", "
+ << GetFloatValue(GAMEOBJECT_PARENTROTATION+1) << ", "
+ << GetFloatValue(GAMEOBJECT_PARENTROTATION+2) << ", "
+ << GetFloatValue(GAMEOBJECT_PARENTROTATION+3) << ", "
<< m_respawnDelayTime << ", "
- << GetGoAnimProgress() << ", "
- << GetGoState() << ")";
+ << (uint32)GetGoAnimProgress() << ", "
+ << (uint32)GetGoState() << ")";
WorldDatabase.BeginTransaction();
WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid);
@@ -563,7 +582,8 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
}
uint32 entry = data->id;
- uint32 map_id = data->mapid;
+ //uint32 map_id = data->mapid; // already used before call
+ uint32 phaseMask = data->phaseMask;
float x = data->posX;
float y = data->posY;
float z = data->posZ;
@@ -581,7 +601,7 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
m_DBTableGuid = guid;
if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
- if (!Create(guid,entry, map, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, ArtKit) )
+ if (!Create(guid,entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, ArtKit) )
return false;
switch(GetGOInfo()->type)
@@ -724,10 +744,6 @@ bool GameObject::isVisibleForInState(Player const* u, bool inVisibleList) const
if(check stuff here)
return false;
}*/
-
- // Smuggled Mana Cell required 10 invisibility type detection/state
- if(GetEntry()==187039 && ((u->m_detectInvisibilityMask | u->m_invisibilityMask) & (1<<10))==0)
- return false;
}
// check distance
@@ -799,8 +815,8 @@ void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target)
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
- Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*target,trapEntry,range);
- Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(trapGO,go_check);
+ MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*target,trapEntry,range);
+ MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck> checker(this, trapGO,go_check);
TypeContainerVisitor<Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -810,7 +826,7 @@ void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target)
// found correct GO
// FIXME: when GO casting will be implemented trap must cast spell to target
if(trapGO)
- target->CastSpell(target,trapSpell,true);
+ target->CastSpell(target,trapSpell,true, 0, 0, GetGUID());
}
GameObject* GameObject::LookupFishingHoleAround(float range)
@@ -820,8 +836,8 @@ GameObject* GameObject::LookupFishingHoleAround(float range)
CellPair p(Trinity::ComputeCellPair(GetPositionX(),GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
- Trinity::NearestGameObjectFishingHole u_check(*this, range);
- Trinity::GameObjectSearcher<Trinity::NearestGameObjectFishingHole> checker(ok, u_check);
+ MaNGOS::NearestGameObjectFishingHole u_check(*this, range);
+ MaNGOS::GameObjectSearcher<MaNGOS::NearestGameObjectFishingHole> checker(this, ok, u_check);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -846,9 +862,9 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore)
}
-void GameObject::SetGoArtKit(uint32 kit)
+void GameObject::SetGoArtKit(uint8 kit)
{
- SetUInt32Value(GAMEOBJECT_ARTKIT, kit);
+ SetByteValue(GAMEOBJECT_BYTES_1, 2, kit);
GameObjectData *data = const_cast<GameObjectData*>(objmgr.GetGOData(m_DBTableGuid));
if(data)
data->ArtKit = kit;
@@ -953,7 +969,7 @@ void GameObject::Use(Unit* user)
// fallback, will always work
player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET);
}
- player->SetStandState(PLAYER_STATE_SIT_LOW_CHAIR+info->chair.height);
+ player->SetStandState(UNIT_STAND_STATE_SIT_LOW_CHAIR+info->chair.height);
return;
}
//big gun, its a spell/aura
@@ -1209,7 +1225,7 @@ void GameObject::Use(Unit* user)
Player* player = (Player*)user;
- if( player->isAllowUseBattleGroundObject() )
+ if( player->isAllowUseBattleGroundObject() )
{
// in battleground check
BattleGround *bg = player->GetBattleGround();
@@ -1247,6 +1263,26 @@ void GameObject::Use(Unit* user)
}
break;
}
+ case GAMEOBJECT_TYPE_BARBER_CHAIR: //32
+ {
+ GameObjectInfo const* info = GetGOInfo();
+ if(!info)
+ return;
+
+ if(user->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ Player* player = (Player*)user;
+
+ // fallback, will always work
+ player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET);
+
+ WorldPacket data(SMSG_ENABLE_BARBER_SHOP, 0);
+ player->GetSession()->SendPacket(&data);
+
+ player->SetStandState(UNIT_STAND_STATE_SIT_LOW_CHAIR+info->barberChair.chairheight);
+ return;
+ }
default:
sLog.outDebug("Unknown Object Type %u", GetGoType());
break;
diff --git a/src/game/GameObject.h b/src/game/GameObject.h
index afeaba98cc9..8269487240c 100644
--- a/src/game/GameObject.h
+++ b/src/game/GameObject.h
@@ -336,12 +336,12 @@ struct GameObjectInfo
uint32 mapID; //0
uint32 difficulty; //1
} dungeonDifficulty;
- //32 GAMEOBJECT_TYPE_DO_NOT_USE_YET
+ //32 GAMEOBJECT_TYPE_BARBER_CHAIR
struct
{
- uint32 mapID; //0
- uint32 difficulty; //1
- } doNotUseYet;
+ uint32 chairheight; //0
+ uint32 heightOffset; //1
+ } barberChair;
//33 GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING
struct
{
@@ -350,6 +350,13 @@ struct GameObjectInfo
uint32 state1Name; //2
uint32 state2Name; //3
} destructibleBuilding;
+ //34 GAMEOBJECT_TYPE_TRAPDOOR
+ struct
+ {
+ uint32 whenToPause; // 0
+ uint32 startOpen; // 1
+ uint32 autoClose; // 2
+ } trapDoor;
// not use for specific field access (only for output with loop by all filed), also this determinate max union size
struct // GAMEOBJECT_TYPE_SPELLCASTER
@@ -370,7 +377,8 @@ struct GameObjectLocale
struct GameObjectData
{
uint32 id; // entry in gamobject_template
- uint32 mapid;
+ uint16 mapid;
+ uint16 phaseMask;
float posX;
float posY;
float posZ;
@@ -419,7 +427,7 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject
void AddToWorld();
void RemoveFromWorld();
- bool Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state, uint32 ArtKit = 0);
+ bool Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state, uint32 ArtKit = 0);
void Update(uint32 p_time);
static GameObject* GetGameObject(WorldObject& object, uint64 guid);
GameObjectInfo const* GetGOInfo() const;
@@ -449,7 +457,7 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject
const char* GetNameForLocaleIdx(int32 locale_idx) const;
void SaveToDB();
- void SaveToDB(uint32 mapid, uint8 spawnMask);
+ void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask);
bool LoadFromDB(uint32 guid, Map *map);
void DeleteFromDB();
void SetLootState(LootState s) { m_lootState = s; }
@@ -504,14 +512,14 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject
void SetSpellId(uint32 id) { m_spellId = id;}
uint32 GetSpellId() const { return m_spellId;}
void getFishLoot(Loot *loot);
- GameobjectTypes GetGoType() const { return GameobjectTypes(GetUInt32Value(GAMEOBJECT_TYPE_ID)); }
- void SetGoType(GameobjectTypes type) { SetUInt32Value(GAMEOBJECT_TYPE_ID, type); }
- uint32 GetGoState() const { return GetUInt32Value(GAMEOBJECT_STATE); }
- void SetGoState(uint32 state) { SetUInt32Value(GAMEOBJECT_STATE, state); }
- uint32 GetGoArtKit() const { return GetUInt32Value(GAMEOBJECT_ARTKIT); }
- void SetGoArtKit(uint32 artkit);
- uint32 GetGoAnimProgress() const { return GetUInt32Value(GAMEOBJECT_ANIMPROGRESS); }
- void SetGoAnimProgress(uint32 animprogress) { SetUInt32Value(GAMEOBJECT_ANIMPROGRESS, animprogress); }
+ GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); }
+ void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); }
+ uint8 GetGoState() const { return GetByteValue(GAMEOBJECT_BYTES_1, 0); }
+ void SetGoState(uint8 state) { SetByteValue(GAMEOBJECT_BYTES_1, 0, state); }
+ uint8 GetGoArtKit() const { return GetByteValue(GAMEOBJECT_BYTES_1, 2); }
+ void SetGoArtKit(uint8 artkit);
+ uint8 GetGoAnimProgress() const { return GetByteValue(GAMEOBJECT_BYTES_1, 3); }
+ void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); }
void Use(Unit* user);
diff --git a/src/game/GlobalEvents.cpp b/src/game/GlobalEvents.cpp
index 635d426f694..27de7df03b4 100644
--- a/src/game/GlobalEvents.cpp
+++ b/src/game/GlobalEvents.cpp
@@ -55,7 +55,7 @@ static void CorpsesEraseCallBack(QueryResult *result, bool bones)
{
if(!ObjectAccessor::Instance().ConvertCorpseForPlayer(player_guid))
{
- sLog.outDebug("Corpse %u not found in world. Delete from DB.",guidlow);
+ sLog.outDebug("Corpse %u not found in world or bones creating forbidden. Delete from DB.",guidlow);
CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow);
}
}
diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp
index 85414fa3372..8b6c8209233 100644
--- a/src/game/GossipDef.cpp
+++ b/src/game/GossipDef.cpp
@@ -127,7 +127,7 @@ bool PlayerMenu::GossipOptionCoded( unsigned int Selection )
void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID )
{
WorldPacket data( SMSG_GOSSIP_MESSAGE, (100) ); // guess size
- data << npcGUID;
+ data << uint64(npcGUID);
data << uint32(0); // new 2.4.0
data << uint32( TitleTextId );
data << uint32( mGossipMenu.MenuItemCount() ); // max count 0x0F
@@ -417,10 +417,14 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID
}
data << uint64(npcGUID);
+ data << uint64(0); // wotlk, something todo with quest sharing?
data << uint32(pQuest->GetQuestId());
- data << Title << Details << Objectives;
+ data << Title;
+ data << Details;
+ data << Objectives;
data << uint32(ActivateAccept);
data << uint32(pQuest->GetSuggestedPlayers());
+ data << uint8(0); // new wotlk
if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
{
@@ -466,6 +470,7 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID
data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0)
data << uint32(pQuest->GetRewSpellCast()); // casted spell
data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
+ data << uint32(pQuest->GetBonusTalents()); // bonus talents
data << uint32(QUEST_EMOTE_COUNT);
for (uint32 i=0; i < QUEST_EMOTE_COUNT; i++)
@@ -542,6 +547,8 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
data << uint32(pQuest->GetSrcItemId());
data << uint32(pQuest->GetFlags() & 0xFFFF);
data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
+ data << uint32(pQuest->GetPlayersSlain()); // players slain
+ data << uint32(pQuest->GetBonusTalents()); // bonus talents
int iI;
@@ -588,15 +595,23 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
data << uint32(pQuest->ReqCreatureOrGOId[iI]);
}
data << uint32(pQuest->ReqCreatureOrGOCount[iI]);
+ data << uint32(0); // added in WotLK, dunno if offset if correct
+ }
+
+ for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; ++iI)
+ {
data << uint32(pQuest->ReqItemId[iI]);
data << uint32(pQuest->ReqItemCount[iI]);
}
+ data << uint32(0); // TODO: 5 item objective
+ data << uint32(0);
+
for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; iI++)
data << ObjectiveText[iI];
pSession->SendPacket( &data );
- sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u",pQuest->GetQuestId() );
+ sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", pQuest->GetQuestId() );
}
void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, bool EnbleNext )
@@ -678,9 +693,10 @@ void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID,
data << uint32(0x08); // unused by client?
data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0)
data << uint32(pQuest->GetRewSpellCast()); // casted spell
- data << uint32(0x00); // unk, NOT honor
+ data << uint32(0); // unknown
+ data << uint32(pQuest->GetBonusTalents()); // bonus talents
pSession->SendPacket( &data );
- sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() );
+ sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), pQuest->GetQuestId() );
}
void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel )
diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp
index 7f40df0d46f..491c75b8f63 100644
--- a/src/game/GridNotifiers.cpp
+++ b/src/game/GridNotifiers.cpp
@@ -146,7 +146,7 @@ VisibleNotifier::Notify()
// send data at target visibility change (adding to client)
for(std::set<WorldObject*>::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr)
if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT))
- i_player.SendAuraDurationsForTarget((Unit*)(*vItr));
+ i_player.SendAurasForTarget((Unit*)(*vItr));
}
void
@@ -154,6 +154,11 @@ Deliverer::Visit(PlayerMapType &m)
{
for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
+ //if (!i_source.InSamePhase(iter->getSource()))
+ // continue;
+ if(!iter->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if (!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist)
{
// Send packet to all who are sharing the player's vision
@@ -174,6 +179,9 @@ Deliverer::Visit(CreatureMapType &m)
{
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
+ if(!iter->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if (!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist)
{
// Send packet to all who are sharing the creature's vision
@@ -192,6 +200,9 @@ Deliverer::Visit(DynamicObjectMapType &m)
{
for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
+ if(!iter->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID()))
{
// Send packet back to the caster if the caster has vision of dynamic object
@@ -249,9 +260,6 @@ ObjectUpdater::Visit(GridRefManager<T> &m)
}
}
-template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &);
-template void ObjectUpdater::Visit<DynamicObject>(DynamicObjectMapType &);
-
bool CannibalizeObjectCheck::operator()(Corpse* u)
{
// ignore bones
@@ -268,3 +276,6 @@ bool CannibalizeObjectCheck::operator()(Corpse* u)
return false;
}
+
+template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &);
+template void ObjectUpdater::Visit<DynamicObject>(DynamicObjectMapType &);
diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h
index eb15d8ea7b2..ae0c50e46c8 100644
--- a/src/game/GridNotifiers.h
+++ b/src/game/GridNotifiers.h
@@ -96,8 +96,10 @@ namespace Trinity
std::set<uint64> plr_list;
bool i_toPossessor;
bool i_toSelf;
+ uint32 i_phaseMask;
float i_dist;
- Deliverer(WorldObject &src, WorldPacket *msg, bool to_possessor, bool to_self, float dist = 0.0f) : i_source(src), i_message(msg), i_toPossessor(to_possessor), i_toSelf(to_self), i_dist(dist) {}
+ Deliverer(WorldObject &src, WorldPacket *msg, bool to_possessor, bool to_self, float dist = 0.0f)
+ : i_source(src), i_message(msg), i_toPossessor(to_possessor), i_toSelf(to_self), i_dist(dist), i_phaseMask(src.GetPhaseMask()) {}
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
void Visit(DynamicObjectMapType &m);
@@ -215,10 +217,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL WorldObjectSearcher
{
+ uint32 i_phaseMask;
WorldObject* &i_object;
Check &i_check;
- WorldObjectSearcher(WorldObject* & result, Check& check) : i_object(result),i_check(check) {}
+ WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {}
void Visit(GameObjectMapType &m);
void Visit(PlayerMapType &m);
@@ -232,10 +236,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL WorldObjectListSearcher
{
+ uint32 i_phaseMask;
std::list<WorldObject*> &i_objects;
Check& i_check;
- WorldObjectListSearcher(std::list<WorldObject*> &objects, Check & check) : i_objects(objects),i_check(check) {}
+ WorldObjectListSearcher(WorldObject const* searcher, std::list<WorldObject*> &objects, Check & check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {}
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
@@ -249,37 +255,44 @@ namespace Trinity
template<class Do>
struct TRINITY_DLL_DECL WorldObjectWorker
{
+ uint32 i_phaseMask;
Do const& i_do;
- explicit WorldObjectWorker(Do const& _do) : i_do(_do) {}
+ WorldObjectWorker(WorldObject const* searcher, Do const& _do)
+ : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {}
void Visit(GameObjectMapType &m)
{
for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- i_do(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ i_do(itr->getSource());
}
void Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- i_do(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ i_do(itr->getSource());
}
void Visit(CreatureMapType &m)
{
for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- i_do(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ i_do(itr->getSource());
}
void Visit(CorpseMapType &m)
{
for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- i_do(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ i_do(itr->getSource());
}
void Visit(DynamicObjectMapType &m)
{
for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- i_do(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ i_do(itr->getSource());
}
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
@@ -290,10 +303,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL GameObjectSearcher
{
+ uint32 i_phaseMask;
GameObject* &i_object;
Check &i_check;
- GameObjectSearcher(GameObject* & result, Check& check) : i_object(result),i_check(check) {}
+ GameObjectSearcher(WorldObject const* searcher, GameObject* & result, Check& check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {}
void Visit(GameObjectMapType &m);
@@ -304,10 +319,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL GameObjectLastSearcher
{
+ uint32 i_phaseMask;
GameObject* &i_object;
Check& i_check;
- GameObjectLastSearcher(GameObject* & result, Check& check) : i_object(result),i_check(check) {}
+ GameObjectLastSearcher(WorldObject const* searcher, GameObject* & result, Check& check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(GameObjectMapType &m);
@@ -317,10 +334,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL GameObjectListSearcher
{
+ uint32 i_phaseMask;
std::list<GameObject*> &i_objects;
Check& i_check;
- GameObjectListSearcher(std::list<GameObject*> &objects, Check & check) : i_objects(objects),i_check(check) {}
+ GameObjectListSearcher(WorldObject const* searcher, std::list<GameObject*> &objects, Check & check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {}
void Visit(GameObjectMapType &m);
@@ -333,10 +352,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL UnitSearcher
{
+ uint32 i_phaseMask;
Unit* &i_object;
Check & i_check;
- UnitSearcher(Unit* & result, Check & check) : i_object(result),i_check(check) {}
+ UnitSearcher(WorldObject const* searcher, Unit* & result, Check & check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {}
void Visit(CreatureMapType &m);
void Visit(PlayerMapType &m);
@@ -348,10 +369,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL UnitLastSearcher
{
+ uint32 i_phaseMask;
Unit* &i_object;
Check & i_check;
- UnitLastSearcher(Unit* & result, Check & check) : i_object(result),i_check(check) {}
+ UnitLastSearcher(WorldObject const* searcher, Unit* & result, Check & check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {}
void Visit(CreatureMapType &m);
void Visit(PlayerMapType &m);
@@ -363,10 +386,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL UnitListSearcher
{
+ uint32 i_phaseMask;
std::list<Unit*> &i_objects;
Check& i_check;
- UnitListSearcher(std::list<Unit*> &objects, Check & check) : i_objects(objects),i_check(check) {}
+ UnitListSearcher(WorldObject const* searcher, std::list<Unit*> &objects, Check & check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {}
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
@@ -379,10 +404,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL CreatureSearcher
{
+ uint32 i_phaseMask;
Creature* &i_object;
Check & i_check;
- CreatureSearcher(Creature* & result, Check & check) : i_object(result),i_check(check) {}
+ CreatureSearcher(WorldObject const* searcher, Creature* & result, Check & check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {}
void Visit(CreatureMapType &m);
@@ -393,10 +420,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL CreatureLastSearcher
{
+ uint32 i_phaseMask;
Creature* &i_object;
Check & i_check;
- CreatureLastSearcher(Creature* & result, Check & check) : i_object(result),i_check(check) {}
+ CreatureLastSearcher(WorldObject const* searcher, Creature* & result, Check & check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {}
void Visit(CreatureMapType &m);
@@ -406,10 +435,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL CreatureListSearcher
{
+ uint32 i_phaseMask;
std::list<Creature*> &i_objects;
Check& i_check;
- CreatureListSearcher(std::list<Creature*> &objects, Check & check) : i_objects(objects),i_check(check) {}
+ CreatureListSearcher(WorldObject const* searcher, std::list<Creature*> &objects, Check & check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {}
void Visit(CreatureMapType &m);
@@ -421,10 +452,12 @@ namespace Trinity
template<class Check>
struct TRINITY_DLL_DECL PlayerSearcher
{
+ uint32 i_phaseMask;
Player* &i_object;
Check & i_check;
- PlayerSearcher(Player* & result, Check & check) : i_object(result),i_check(check) {}
+ PlayerSearcher(WorldObject const* searcher, Player* & result, Check & check)
+ : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {}
void Visit(PlayerMapType &m);
@@ -434,14 +467,17 @@ namespace Trinity
template<class Do>
struct TRINITY_DLL_DECL PlayerWorker
{
+ uint32 i_phaseMask;
Do& i_do;
- explicit PlayerWorker(Do& _do) : i_do(_do) {}
+ PlayerWorker(WorldObject const* searcher, Do& _do)
+ : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {}
void Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- i_do(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ i_do(itr->getSource());
}
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h
index dfb202a37e1..8f074d946a4 100644
--- a/src/game/GridNotifiersImpl.h
+++ b/src/game/GridNotifiersImpl.h
@@ -155,7 +155,7 @@ inline void Trinity::DynamicObjectUpdater::VisitHelper(Unit* target)
if( target->GetTypeId()==TYPEID_PLAYER && target != i_check && (((Player*)target)->isGameMaster() || ((Player*)target)->GetVisibility()==VISIBILITY_OFF) )
return;
- if( i_check->GetTypeId()==TYPEID_PLAYER )
+ if (i_check->GetTypeId()==TYPEID_PLAYER )
{
if (i_check->IsFriendlyTo( target ))
return;
@@ -172,7 +172,7 @@ inline void Trinity::DynamicObjectUpdater::VisitHelper(Unit* target)
SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId());
uint32 eff_index = i_dynobject.GetEffIndex();
// Check target immune to spell or aura
- if (target->IsImmunedToSpell(spellInfo) || target->IsImmunedToSpellEffect(spellInfo->Effect[eff_index], spellInfo->EffectMechanic[eff_index]))
+ if (target->IsImmunedToSpell(spellInfo) || target->IsImmunedToSpellEffect(spellInfo, eff_index))
return;
// Apply PersistentAreaAura on target
PersistentAreaAura* Aur = new PersistentAreaAura(spellInfo, eff_index, NULL, target, i_dynobject.GetCaster());
@@ -209,7 +209,10 @@ void Trinity::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m)
for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if(i_check(itr->getSource()))
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
{
i_object = itr->getSource();
return;
@@ -226,6 +229,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(PlayerMapType &m)
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
{
i_object = itr->getSource();
@@ -243,6 +249,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CreatureMapType &m)
for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
{
i_object = itr->getSource();
@@ -260,6 +269,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CorpseMapType &m)
for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
{
i_object = itr->getSource();
@@ -277,6 +289,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m)
for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
{
i_object = itr->getSource();
@@ -289,40 +304,45 @@ template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if(i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ if(i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m)
{
for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if(i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ if(i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m)
{
for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if(i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ if(i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m)
{
for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if(i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ if(i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(DynamicObjectMapType &m)
{
for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if(i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ if(i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
// Gameobject searchers
@@ -336,6 +356,9 @@ void Trinity::GameObjectSearcher<Check>::Visit(GameObjectMapType &m)
for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
{
i_object = itr->getSource();
@@ -349,6 +372,9 @@ void Trinity::GameObjectLastSearcher<Check>::Visit(GameObjectMapType &m)
{
for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
i_object = itr->getSource();
}
@@ -358,8 +384,9 @@ template<class Check>
void Trinity::GameObjectListSearcher<Check>::Visit(GameObjectMapType &m)
{
for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if(i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ if(i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
// Unit searchers
@@ -373,6 +400,9 @@ void Trinity::UnitSearcher<Check>::Visit(CreatureMapType &m)
for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
{
i_object = itr->getSource();
@@ -390,6 +420,9 @@ void Trinity::UnitSearcher<Check>::Visit(PlayerMapType &m)
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
{
i_object = itr->getSource();
@@ -403,6 +436,9 @@ void Trinity::UnitLastSearcher<Check>::Visit(CreatureMapType &m)
{
for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
i_object = itr->getSource();
}
@@ -413,6 +449,9 @@ void Trinity::UnitLastSearcher<Check>::Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
i_object = itr->getSource();
}
@@ -422,16 +461,18 @@ template<class Check>
void Trinity::UnitListSearcher<Check>::Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if(i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ if(i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
template<class Check>
void Trinity::UnitListSearcher<Check>::Visit(CreatureMapType &m)
{
for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if(i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ if(i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
// Creature searchers
@@ -445,6 +486,9 @@ void Trinity::CreatureSearcher<Check>::Visit(CreatureMapType &m)
for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
{
i_object = itr->getSource();
@@ -458,6 +502,9 @@ void Trinity::CreatureLastSearcher<Check>::Visit(CreatureMapType &m)
{
for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
i_object = itr->getSource();
}
@@ -467,8 +514,9 @@ template<class Check>
void Trinity::CreatureListSearcher<Check>::Visit(CreatureMapType &m)
{
for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if(i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ if( i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
template<class Check>
@@ -480,6 +528,9 @@ void Trinity::PlayerSearcher<Check>::Visit(PlayerMapType &m)
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
+ if(!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
if(i_check(itr->getSource()))
{
i_object = itr->getSource();
diff --git a/src/game/Group.cpp b/src/game/Group.cpp
index 85c707d41f0..8da41311902 100644
--- a/src/game/Group.cpp
+++ b/src/game/Group.cpp
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
- * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -10,12 +10,12 @@
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Common.h"
@@ -44,7 +44,7 @@ Group::Group()
m_lootMethod = (LootMethod)0;
m_looterGuid = 0;
m_lootThreshold = ITEM_QUALITY_UNCOMMON;
- m_subGroupsCounts = NULL;
+ m_subGroupsCounts = NULL;
for(int i=0; i<TARGETICONCOUNT; i++)
m_targetIcons[i] = 0;
@@ -74,8 +74,10 @@ Group::~Group()
for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++)
for(BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
itr->second.save->RemoveGroup(this);
- if (m_subGroupsCounts)
- delete[] m_subGroupsCounts;
+
+ // Sub group counters clean up
+ if (m_subGroupsCounts)
+ delete[] m_subGroupsCounts;
}
bool Group::Create(const uint64 &guid, const char * name)
@@ -84,10 +86,10 @@ bool Group::Create(const uint64 &guid, const char * name)
m_leaderName = name;
m_groupType = isBGGroup() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL;
-
- if (m_groupType == GROUPTYPE_RAID)
- _initRaidSubGroupsCounter();
-
+
+ if (m_groupType == GROUPTYPE_RAID)
+ _initRaidSubGroupsCounter();
+
m_lootMethod = GROUP_LOOT;
m_lootThreshold = ITEM_QUALITY_UNCOMMON;
m_looterGuid = guid;
@@ -143,10 +145,10 @@ bool Group::LoadGroupFromDB(const uint64 &leaderGuid, QueryResult *result, bool
}
m_groupType = (*result)[13].GetBool() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL;
-
- if (m_groupType == GROUPTYPE_RAID)
- _initRaidSubGroupsCounter();
-
+
+ if (m_groupType == GROUPTYPE_RAID)
+ _initRaidSubGroupsCounter();
+
m_difficulty = (*result)[14].GetUInt8();
m_mainTank = (*result)[0].GetUInt64();
m_mainAssistant = (*result)[1].GetUInt64();
@@ -189,20 +191,25 @@ bool Group::LoadMemberFromDB(uint32 guidLow, uint8 subgroup, bool assistant)
member.group = subgroup;
member.assistant = assistant;
m_memberSlots.push_back(member);
-
- SubGroupCounterIncrease(subgroup);
-
+
+ SubGroupCounterIncrease(subgroup);
+
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();
+ m_groupType = GROUPTYPE_RAID;
+
+ _initRaidSubGroupsCounter();
+
+ if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
+ SendUpdate();
+
+ // update quest related GO states (quest activity dependent from raid membership)
+ for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
+ if(Player* player = objmgr.GetPlayer(citr->guid))
+ player->UpdateForQuestsGO();
}
bool Group::AddInvite(Player *player)
@@ -288,6 +295,10 @@ bool Group::AddMember(const uint64 &guid, const char* name)
}
player->SetGroupUpdateFlag(GROUP_UPDATE_FULL);
UpdatePlayerOutOfRange(player);
+
+ // quest related GO state dependent from raid memebership
+ if(isRaidGroup())
+ player->UpdateForQuestsGO();
}
return true;
@@ -302,9 +313,12 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
{
bool leaderChanged = _removeMember(guid);
- Player *player = objmgr.GetPlayer( guid ); // FG: TODO: could be removed, its just here for consistency
- if (player)
+ if(Player *player = objmgr.GetPlayer( guid ))
{
+ // quest related GO state dependent from raid membership
+ if(isRaidGroup())
+ player->UpdateForQuestsGO();
+
WorldPacket data;
if(method == 1)
@@ -363,6 +377,11 @@ void Group::Disband(bool hideDestroy)
player->SetGroup(NULL);
+ // quest related GO state dependent from raid membership
+ if(isRaidGroup())
+ player->UpdateForQuestsGO();
+
+
if(!player->GetSession())
continue;
@@ -729,6 +748,8 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
if(player && player->GetSession())
{
+ player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT, roll->itemid, maxresul);
+
ItemPosCountVec dest;
LootItem *item = &(roll->getLoot()->items[roll->itemSlot]);
uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count );
@@ -774,6 +795,8 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
if(player && player->GetSession())
{
+ player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT, roll->itemid, maxresul);
+
ItemPosCountVec dest;
LootItem *item = &(roll->getLoot()->items[roll->itemSlot]);
uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count );
@@ -835,13 +858,10 @@ void Group::GetDataForXPAtKill(Unit const* victim, uint32& count,uint32& sum_lev
++count;
sum_level += member->getLevel();
- // store maximum member level
if(!member_with_max_level || member_with_max_level->getLevel() < member->getLevel())
member_with_max_level = member;
- uint32 gray_level = Trinity::XP::GetGrayLevel(member->getLevel());
- // if the victim is higher level than the gray level of the currently examined group member,
- // then set not_gray_member_with_max_level if needed.
+ uint32 gray_level = MaNGOS::XP::GetGrayLevel(member->getLevel());
if( victim->getLevel() > gray_level && (!not_gray_member_with_max_level
|| not_gray_member_with_max_level->getLevel() < member->getLevel()))
not_gray_member_with_max_level = member;
@@ -905,7 +925,6 @@ void Group::SendUpdate()
data << (uint64)m_looterGuid; // looter guid
data << (uint8)m_lootThreshold; // loot threshold
data << (uint8)m_difficulty; // Heroic Mod Group
-
}
player->GetSession()->SendPacket( &data );
}
@@ -974,17 +993,17 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant)
if (m_subGroupsCounts)
{
bool groupFound = false;
- for (; groupid < MAXRAIDSIZE/MAXGROUPSIZE; ++groupid)
- {
- if (m_subGroupsCounts[groupid] < MAXGROUPSIZE)
- {
- groupFound = true;
- break;
- }
- }
- // We are raid group and no one slot is free
- if (!groupFound)
- return false;
+ for (; groupid < MAXRAIDSIZE/MAXGROUPSIZE; ++groupid)
+ {
+ if (m_subGroupsCounts[groupid] < MAXGROUPSIZE)
+ {
+ groupFound = true;
+ break;
+ }
+ }
+ // We are raid group and no one slot is free
+ if (!groupFound)
+ return false;
}
return _addMember(guid, name, isAssistant, groupid);
@@ -1006,8 +1025,8 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant, u
member.group = group;
member.assistant = isAssistant;
m_memberSlots.push_back(member);
-
- SubGroupCounterIncrease(group);
+
+ SubGroupCounterIncrease(group);
if(player)
{
@@ -1046,10 +1065,11 @@ bool Group::_removeMember(const uint64 &guid)
member_witerator slot = _getMemberWSlot(guid);
if (slot != m_memberSlots.end())
- {
- SubGroupCounterDecrease(slot->group);
+ {
+ SubGroupCounterDecrease(slot->group);
+
m_memberSlots.erase(slot);
- }
+ }
if(!isBGGroup())
CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid='%u'", GUID_LOPART(guid));
@@ -1149,11 +1169,11 @@ bool Group::_setMembersGroup(const uint64 &guid, const uint8 &group)
return false;
slot->group = group;
-
- SubGroupCounterIncrease(group);
-
+
+ SubGroupCounterIncrease(group);
+
if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE group_member SET subgroup='%u' WHERE memberGuid='%u'", group, GUID_LOPART(guid));
-
+
return true;
}
@@ -1207,18 +1227,20 @@ void Group::ChangeMembersGroup(const uint64 &guid, const uint8 &group)
if(!isRaidGroup())
return;
Player *player = objmgr.GetPlayer(guid);
+
if (!player)
{
- uint8 prevSubGroup;
- prevSubGroup = GetMemberGroup(guid);
-
- SubGroupCounterDecrease(prevSubGroup);
-
+ uint8 prevSubGroup;
+ prevSubGroup = GetMemberGroup(guid);
+
+ SubGroupCounterDecrease(prevSubGroup);
+
if(_setMembersGroup(guid, group))
SendUpdate();
}
else
- ChangeMembersGroup(player, group);
+ // This methods handles itself groupcounter decrease
+ ChangeMembersGroup(player, group);
}
// only for online members
@@ -1228,11 +1250,11 @@ void Group::ChangeMembersGroup(Player *player, const uint8 &group)
return;
if(_setMembersGroup(player->GetGUID(), group))
{
- uint8 prevSubGroup;
- prevSubGroup = player->GetSubGroup();
-
- SubGroupCounterDecrease(prevSubGroup);
-
+ uint8 prevSubGroup;
+ prevSubGroup = player->GetSubGroup();
+
+ SubGroupCounterDecrease(prevSubGroup);
+
player->GetGroupRef().setSubGroup(group);
SendUpdate();
}
@@ -1366,7 +1388,7 @@ uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint
void Roll::targetObjectBuildLink()
{
// called from link()
- this->getTarget()->addLootValidatorRef(this);
+ getTarget()->addLootValidatorRef(this);
}
void Group::SetDifficulty(uint8 difficulty)
@@ -1474,7 +1496,7 @@ InstanceGroupBind* Group::BindToInstance(InstanceSave *save, bool permanent, boo
InstanceGroupBind& bind = m_boundInstances[save->GetDifficulty()][save->GetMapId()];
if(bind.save)
{
- // when a boss is killed or when copying the player's binds to the group
+ // when a boss is killed or when copying the players's binds to the group
if(permanent != bind.perm || save != bind.save)
if(!load) CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u', permanent = '%u' WHERE leaderGuid = '%u' AND instance = '%u'", save->GetInstanceId(), permanent, GUID_LOPART(GetLeaderGUID()), bind.save->GetInstanceId());
}
@@ -1535,4 +1557,4 @@ void Group::BroadcastGroupUpdate(void)
DEBUG_LOG("-- Forced group value update for '%s'", pp->GetName());
}
}
-} \ No newline at end of file
+}
diff --git a/src/game/Group.h b/src/game/Group.h
index 7cb37b17ff0..aef5a8619af 100644
--- a/src/game/Group.h
+++ b/src/game/Group.h
@@ -66,24 +66,25 @@ enum GroupUpdateFlags
{
GROUP_UPDATE_FLAG_NONE = 0x00000000, // nothing
GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16, flags
- GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint16
- GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint16
+ GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint32
+ GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint32
GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000008, // uint8
GROUP_UPDATE_FLAG_CUR_POWER = 0x00000010, // uint16
GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // uint16
GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16
GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16
GROUP_UPDATE_FLAG_POSITION = 0x00000100, // uint16, uint16
- GROUP_UPDATE_FLAG_AURAS = 0x00000200, // uint64 mask, for each bit set uint16 spellid + uint8 unk
+ GROUP_UPDATE_FLAG_AURAS = 0x00000200, // uint64 mask, for each bit set uint32 spellid + uint8 unk
GROUP_UPDATE_FLAG_PET_GUID = 0x00000400, // uint64 pet guid
GROUP_UPDATE_FLAG_PET_NAME = 0x00000800, // pet name, NULL terminated string
GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00001000, // uint16, model id
- GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00002000, // uint16 pet cur health
- GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00004000, // uint16 pet max health
+ GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00002000, // uint32 pet cur health
+ GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00004000, // uint32 pet max health
GROUP_UPDATE_FLAG_PET_POWER_TYPE = 0x00008000, // uint8 pet power type
GROUP_UPDATE_FLAG_PET_CUR_POWER = 0x00010000, // uint16 pet cur power
GROUP_UPDATE_FLAG_PET_MAX_POWER = 0x00020000, // uint16 pet max power
- GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint16 spellid + uint8 unk, pet auras...
+ GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint32 spellid + uint8 unk, pet auras...
+ GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00080000, // uint32 vehicle_seat_id (index from VehicleSeat.dbc)
GROUP_UPDATE_PET = 0x0007FC00, // all pet flags
GROUP_UPDATE_FULL = 0x0007FFFF, // all known flags
};
diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp
index 679c16ced58..9fd074d4b96 100644
--- a/src/game/GroupHandler.cpp
+++ b/src/game/GroupHandler.cpp
@@ -162,6 +162,7 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data )
// ok, we do it
WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size
+ data << uint8(1); // ok
data << GetPlayer()->GetName();
player->GetSession()->SendPacket(&data);
@@ -554,8 +555,17 @@ void WorldSession::HandleGroupChangeSubGroupOpcode( WorldPacket & recv_data )
return;
/********************/
+ //Do not allow leader to change group of player in combat
+ Player *movedPlayer=objmgr.GetPlayer(name.c_str());
+ if (movedPlayer->isInCombat())
+ {
+ WorldPacket data(SMSG_GROUP_SWAP_FAILED, (0));
+ SendPacket(&data);
+ return;
+ }
+
// everything's fine, do it
- group->ChangeMembersGroup(objmgr.GetPlayer(name.c_str()), groupNr);
+ group->ChangeMembersGroup(movedPlayer, groupNr);
}
void WorldSession::HandleGroupAssistantOpcode( WorldPacket & recv_data )
@@ -690,10 +700,10 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
}
if (mask & GROUP_UPDATE_FLAG_CUR_HP)
- *data << (uint16) player->GetHealth();
+ *data << (uint32) player->GetHealth();
if (mask & GROUP_UPDATE_FLAG_MAX_HP)
- *data << (uint16) player->GetMaxHealth();
+ *data << (uint32) player->GetMaxHealth();
Powers powerType = player->getPowerType();
if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)
@@ -716,14 +726,14 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
if (mask & GROUP_UPDATE_FLAG_AURAS)
{
- uint64 auramask = player->GetAuraUpdateMask();
+ const uint64& auramask = player->GetAuraUpdateMask();
*data << uint64(auramask);
for(uint32 i = 0; i < MAX_AURAS; ++i)
{
if(auramask & (uint64(1) << i))
{
- uint32 updatedAura=player->GetUInt32Value(UNIT_FIELD_AURA + i);
- *data << uint16(updatedAura);
+ uint32 updatedAura = player->GetVisibleAura(i);
+ *data << uint32(updatedAura);
*data << uint8(1);
//TODO: find a safe place to do this cleanup
//if(!updatedAura)
@@ -760,17 +770,17 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP)
{
if(pet)
- *data << (uint16) pet->GetHealth();
+ *data << (uint32) pet->GetHealth();
else
- *data << (uint16) 0;
+ *data << (uint32) 0;
}
if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP)
{
if(pet)
- *data << (uint16) pet->GetMaxHealth();
+ *data << (uint32) pet->GetMaxHealth();
else
- *data << (uint16) 0;
+ *data << (uint32) 0;
}
if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
@@ -801,14 +811,14 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
{
if(pet)
{
- uint64 auramask = pet->GetAuraUpdateMask();
+ const uint64& auramask = pet->GetAuraUpdateMask();
*data << uint64(auramask);
for(uint32 i = 0; i < MAX_AURAS; ++i)
{
if(auramask & (uint64(1) << i))
{
- uint32 updatedAura=pet->GetUInt32Value(UNIT_FIELD_AURA + i);
- *data << uint16(updatedAura);
+ uint32 updatedAura = pet->GetVisibleAura(i);
+ *data << uint32(updatedAura);
*data << uint8(1);
//TODO: find a safe place to do this cleanup
//if(!updatedAura)
@@ -834,6 +844,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
if(!player)
{
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2);
+ data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
data.appendPackGUID(Guid);
data << (uint32) GROUP_UPDATE_FLAG_STATUS;
data << (uint16) MEMBER_STATUS_OFFLINE;
@@ -844,6 +855,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
Pet *pet = player->GetPet();
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8);
+ data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
data.append(player->GetPackGUID());
uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF
@@ -853,8 +865,8 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
Powers powerType = player->getPowerType();
data << (uint32) mask1; // group update mask
data << (uint16) MEMBER_STATUS_ONLINE; // member's online status
- data << (uint16) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP
- data << (uint16) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP
+ data << (uint32) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP
+ data << (uint32) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP
data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE
data << (uint16) player->GetPower(powerType); // GROUP_UPDATE_FLAG_CUR_POWER
data << (uint16) player->GetMaxPower(powerType); // GROUP_UPDATE_FLAG_MAX_POWER
@@ -868,11 +880,11 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
data << (uint64) auramask; // placeholder
for(uint8 i = 0; i < MAX_AURAS; ++i)
{
- if(uint32 aura = player->GetUInt32Value(UNIT_FIELD_AURA + i))
+ if(uint32 aura = player->GetVisibleAura(i))
{
auramask |= (uint64(1) << i);
- data << uint16(aura);
- data << uint8(1);
+ data << (uint32) aura;
+ data << (uint8) 1;
}
}
data.put<uint64>(maskPos,auramask); // GROUP_UPDATE_FLAG_AURAS
@@ -883,8 +895,8 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID
data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME
data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID
- data << (uint16) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP
- data << (uint16) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP
+ data << (uint32) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP
+ data << (uint32) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP
data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE
data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER
data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER
@@ -894,10 +906,10 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
data << (uint64) petauramask; // placeholder
for(uint8 i = 0; i < MAX_AURAS; ++i)
{
- if(uint32 petaura = pet->GetUInt32Value(UNIT_FIELD_AURA + i))
+ if(uint32 petaura = pet->GetVisibleAura(i))
{
petauramask |= (uint64(1) << i);
- data << (uint16) petaura;
+ data << (uint32) petaura;
data << (uint8) 1;
}
}
diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp
index 897110afe55..9dbba57ac12 100644
--- a/src/game/Guild.cpp
+++ b/src/game/Guild.cpp
@@ -785,6 +785,7 @@ void Guild::Query(WorldSession *session)
data << uint32(BorderStyle);
data << uint32(BorderColor);
data << uint32(BackgroundColor);
+ data << uint32(0); // something new in WotLK
session->SendPacket( &data );
sLog.outDebug( "WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)" );
@@ -1212,18 +1213,19 @@ void Guild::LoadGuildBankFromDB()
delete result;
- // 0 1 2 3
- result = CharacterDatabase.PQuery("SELECT TabId, SlotId, item_guid, item_entry FROM guild_bank_item WHERE guildid='%u' ORDER BY TabId", Id);
+ // data needs to be at first place for Item::LoadFromDB
+ // 0 1 2 3 4
+ result = CharacterDatabase.PQuery("SELECT data, TabId, SlotId, item_guid, item_entry FROM guild_bank_item JOIN item_instance ON item_guid = guid WHERE guildid='%u' ORDER BY TabId", Id);
if(!result)
return;
do
{
Field *fields = result->Fetch();
- uint8 TabId = fields[0].GetUInt8();
- uint8 SlotId = fields[1].GetUInt8();
- uint32 ItemGuid = fields[2].GetUInt32();
- uint32 ItemEntry = fields[3].GetUInt32();
+ uint8 TabId = fields[1].GetUInt8();
+ uint8 SlotId = fields[2].GetUInt8();
+ uint32 ItemGuid = fields[3].GetUInt32();
+ uint32 ItemEntry = fields[4].GetUInt32();
if (TabId >= purchased_tabs || TabId >= GUILD_BANK_MAX_TABS)
{
@@ -1246,7 +1248,7 @@ void Guild::LoadGuildBankFromDB()
}
Item *pItem = NewItemOrBag(proto);
- if(!pItem->LoadFromDB(ItemGuid, 0))
+ if(!pItem->LoadFromDB(ItemGuid, 0, result))
{
CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'", Id, uint32(TabId), uint32(SlotId));
sLog.outError("Item GUID %u not found in item_instance, deleting from Guild Bank!", ItemGuid);
@@ -1602,7 +1604,21 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
{
data << uint8((*itr)->LogEntry);
data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER));
- data << uint32((*itr)->ItemOrMoney);
+ if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
+ (*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY ||
+ (*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY ||
+ (*itr)->LogEntry == GUILD_BANK_LOG_UNK1 ||
+ (*itr)->LogEntry == GUILD_BANK_LOG_UNK2)
+ {
+ data << uint32((*itr)->ItemOrMoney);
+ }
+ else
+ {
+ data << uint32((*itr)->ItemOrMoney);
+ data << uint32((*itr)->ItemStackCount);
+ if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2)
+ data << uint8((*itr)->DestTabId); // moved tab
+ }
data << uint32(time(NULL)-(*itr)->TimeStamp);
}
session->SendPacket(&data);
@@ -1618,10 +1634,21 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
{
data << uint8((*itr)->LogEntry);
data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER));
- data << uint32((*itr)->ItemOrMoney);
- data << uint8((*itr)->ItemStackCount);
- if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2)
- data << uint8((*itr)->DestTabId); // moved tab
+ if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
+ (*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY ||
+ (*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY ||
+ (*itr)->LogEntry == GUILD_BANK_LOG_UNK1 ||
+ (*itr)->LogEntry == GUILD_BANK_LOG_UNK2)
+ {
+ data << uint32((*itr)->ItemOrMoney);
+ }
+ else
+ {
+ data << uint32((*itr)->ItemOrMoney);
+ data << uint32((*itr)->ItemStackCount);
+ if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2)
+ data << uint8((*itr)->DestTabId); // moved tab
+ }
data << uint32(time(NULL)-(*itr)->TimeStamp);
}
session->SendPacket(&data);
@@ -1703,7 +1730,7 @@ void Guild::AppendDisplayGuildBankSlot( WorldPacket& data, GuildBankTab const *t
// SuffixFactor +4
data << (uint32) pItem->GetItemSuffixFactor();
// +12 // ITEM_FIELD_STACK_COUNT
- data << uint8(pItem->GetCount());
+ data << uint32(pItem->GetCount());
data << uint32(0); // +16 // Unknown value
data << uint8(0); // unknown 2.4.2
if (uint32 Enchant0 = pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT))
diff --git a/src/game/Guild.h b/src/game/Guild.h
index 683ff980e3a..f56e80c2b85 100644
--- a/src/game/Guild.h
+++ b/src/game/Guild.h
@@ -56,7 +56,8 @@ enum GuildRankRights
GR_RIGHT_REPAIR_FROM_GUILD = 0x00020000, // unused in 2.4.x?, Remove money withdraw capacity
GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair
GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold
- GR_RIGHT_ALL = 0x000FF1FF
+ GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk
+ GR_RIGHT_ALL = 0x001FF1FF
};
enum Typecommand
@@ -156,6 +157,8 @@ enum GuildBankLogEntries
GUILD_BANK_LOG_WITHDRAW_MONEY = 5,
GUILD_BANK_LOG_REPAIR_MONEY = 6,
GUILD_BANK_LOG_MOVE_ITEM2 = 7,
+ GUILD_BANK_LOG_UNK1 = 8,
+ GUILD_BANK_LOG_UNK2 = 9,
};
enum GuildEventLogEntryTypes
@@ -217,12 +220,12 @@ struct GuildBankTab
struct GuildItemPosCount
{
- GuildItemPosCount(uint8 _slot, uint8 _count) : slot(_slot), count(_count) {}
+ GuildItemPosCount(uint8 _slot, uint32 _count) : slot(_slot), count(_count) {}
bool isContainedIn(std::vector<GuildItemPosCount> const& vec) const;
uint8 slot;
- uint8 count;
+ uint32 count;
};
typedef std::vector<GuildItemPosCount> GuildItemPosCountVec;
diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp
index 15433602010..94db5ad1ca1 100644
--- a/src/game/GuildHandler.cpp
+++ b/src/game/GuildHandler.cpp
@@ -375,7 +375,7 @@ void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket)
guild->ChangeRank(plGuid, (slot->RankId+1));
// Put record into guildlog
- guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), (slot->RankId));
+ guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), slot->RankId);
WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size
data << (uint8)GE_DEMOTION;
diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp
index cb95dac6978..52e513b7c97 100644
--- a/src/game/InstanceSaveMgr.cpp
+++ b/src/game/InstanceSaveMgr.cpp
@@ -361,8 +361,8 @@ void InstanceSaveManager::PackInstances()
bar.step();
}
- sLog.outString();
sLog.outString( ">> Instance numbers remapped, next instance id is %u", InstanceNumber );
+ sLog.outString();
}
void InstanceSaveManager::LoadResetTimes()
@@ -454,7 +454,7 @@ void InstanceSaveManager::LoadResetTimes()
// add the global reset times to the priority queue
for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++)
{
- InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(i);
+ InstanceTemplate const* temp = objmgr.GetInstanceTemplate(i);
if(!temp) continue;
// only raid/heroic maps have a global reset time
const MapEntry* entry = sMapStore.LookupEntry(temp->map);
@@ -583,7 +583,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
{
// global reset for all instances of the given map
// note: this isn't fast but it's meant to be executed very rarely
- Map *map = (MapInstanced*)MapManager::Instance().GetBaseMap(mapid);
+ Map const *map = MapManager::Instance().GetBaseMap(mapid);
if(!map->Instanceable())
return;
uint64 now = (uint64)time(NULL);
@@ -591,7 +591,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
if(!warn)
{
// this is called one minute before the reset time
- InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(mapid);
+ InstanceTemplate const* temp = objmgr.GetInstanceTemplate(mapid);
if(!temp || !temp->reset_delay)
{
sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid);
diff --git a/src/game/Item.cpp b/src/game/Item.cpp
index b0c2109a5b5..c39b573e24a 100644
--- a/src/game/Item.cpp
+++ b/src/game/Item.cpp
@@ -206,6 +206,10 @@ bool ItemCanGoIntoBag(ItemPrototype const *pProto, ItemPrototype const *pBagProt
if(!(pProto->BagFamily & BAG_FAMILY_MASK_LEATHERWORKING_SUPP))
return false;
return true;
+ case ITEM_SUBCLASS_INSCRIPTION_CONTAINER:
+ if(!(pProto->BagFamily & BAG_FAMILY_MASK_INSCRIPTION_SUPP))
+ return false;
+ return true;
default:
return false;
}
@@ -450,7 +454,7 @@ uint32 Item::GetSkill()
const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] =
{
- 0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0
+ 0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0,0
};
ItemPrototype const* proto = GetProto();
@@ -765,9 +769,9 @@ void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint
if((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges))
return;
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id);
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
SetState(ITEM_CHANGED);
}
@@ -776,7 +780,7 @@ void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration)
if(GetEnchantmentDuration(slot) == duration)
return;
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
SetState(ITEM_CHANGED);
}
@@ -785,7 +789,7 @@ void Item::SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
if(GetEnchantmentCharges(slot) == charges)
return;
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
SetState(ITEM_CHANGED);
}
@@ -795,7 +799,7 @@ void Item::ClearEnchantment(EnchantmentSlot slot)
return;
for(uint8 x = 0; x < 3; ++x)
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + x, 0);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + x, 0);
SetState(ITEM_CHANGED);
}
@@ -886,8 +890,8 @@ Item* Item::CreateItem( uint32 item, uint32 count, Player const* player )
ItemPrototype const *pProto = objmgr.GetItemPrototype( item );
if( pProto )
{
- if ( count > pProto->Stackable )
- count = pProto->Stackable;
+ if ( count > pProto->GetMaxStackSize())
+ count = pProto->GetMaxStackSize();
assert(count !=0 && "pProto->Stackable==0 but checked at loading already");
diff --git a/src/game/Item.h b/src/game/Item.h
index 72c09b0c1da..a51f06d8d51 100644
--- a/src/game/Item.h
+++ b/src/game/Item.h
@@ -148,29 +148,30 @@ enum SellFailure
// -1 from client enchantment slot number
enum EnchantmentSlot
{
- PERM_ENCHANTMENT_SLOT = 0,
- TEMP_ENCHANTMENT_SLOT = 1,
- SOCK_ENCHANTMENT_SLOT = 2,
- SOCK_ENCHANTMENT_SLOT_2 = 3,
- SOCK_ENCHANTMENT_SLOT_3 = 4,
- BONUS_ENCHANTMENT_SLOT = 5,
- MAX_INSPECTED_ENCHANTMENT_SLOT = 6,
-
- PROP_ENCHANTMENT_SLOT_0 = 6, // used with RandomSuffix
- PROP_ENCHANTMENT_SLOT_1 = 7, // used with RandomSuffix
- PROP_ENCHANTMENT_SLOT_2 = 8, // used with RandomSuffix and RandomProperty
- PROP_ENCHANTMENT_SLOT_3 = 9, // used with RandomProperty
- PROP_ENCHANTMENT_SLOT_4 = 10, // used with RandomProperty
- MAX_ENCHANTMENT_SLOT = 11
+ PERM_ENCHANTMENT_SLOT = 0,
+ TEMP_ENCHANTMENT_SLOT = 1,
+ SOCK_ENCHANTMENT_SLOT = 2,
+ SOCK_ENCHANTMENT_SLOT_2 = 3,
+ SOCK_ENCHANTMENT_SLOT_3 = 4,
+ BONUS_ENCHANTMENT_SLOT = 5,
+ PRISMATIC_ENCHANTMENT_SLOT = 6, // added at apply special permanent enchantment
+ MAX_INSPECTED_ENCHANTMENT_SLOT = 7,
+
+ PROP_ENCHANTMENT_SLOT_0 = 7, // used with RandomSuffix
+ PROP_ENCHANTMENT_SLOT_1 = 8, // used with RandomSuffix
+ PROP_ENCHANTMENT_SLOT_2 = 9, // used with RandomSuffix and RandomProperty
+ PROP_ENCHANTMENT_SLOT_3 = 10, // used with RandomProperty
+ PROP_ENCHANTMENT_SLOT_4 = 11, // used with RandomProperty
+ MAX_ENCHANTMENT_SLOT = 12
};
-#define MAX_VISIBLE_ITEM_OFFSET 16 // 16 fields per visible item (creator(2) + enchantments(12) + properties(1) + pad(1))
+#define MAX_VISIBLE_ITEM_OFFSET 18 // 18 fields per visible item (creator(2) + enchantments(13) + properties(1) + seed(1) + pad(1))
enum EnchantmentOffset
{
ENCHANTMENT_ID_OFFSET = 0,
ENCHANTMENT_DURATION_OFFSET = 1,
- ENCHANTMENT_CHARGES_OFFSET = 2
+ ENCHANTMENT_CHARGES_OFFSET = 2 // now here not only charges, but something new in wotlk
};
#define MAX_ENCHANTMENT_OFFSET 3
@@ -211,6 +212,7 @@ class TRINITY_DLL_SPEC Item : public Object
void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS,ITEM_FLAGS_BINDED,val); }
bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BINDED); }
+ bool IsAccountBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BOA); }
bool IsBindedNotWith(uint64 guid) const { return IsSoulBound() && GetOwnerGUID()!= guid; }
bool IsBoundByEnchant() const;
virtual void SaveToDB();
@@ -230,7 +232,7 @@ class TRINITY_DLL_SPEC Item : public Object
uint32 GetCount() const { return GetUInt32Value (ITEM_FIELD_STACK_COUNT); }
void SetCount(uint32 value) { SetUInt32Value (ITEM_FIELD_STACK_COUNT, value); }
- uint32 GetMaxStackCount() const { return GetProto()->Stackable; }
+ uint32 GetMaxStackCount() const { return GetProto()->GetMaxStackSize(); }
uint8 GetGemCountWithID(uint32 GemID) const;
uint8 GetSlot() const {return m_slot;}
@@ -256,9 +258,9 @@ class TRINITY_DLL_SPEC Item : public Object
void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration);
void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges);
void ClearEnchantment(EnchantmentSlot slot);
- uint32 GetEnchantmentId(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET);}
- uint32 GetEnchantmentDuration(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET);}
- uint32 GetEnchantmentCharges(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET);}
+ uint32 GetEnchantmentId(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET);}
+ uint32 GetEnchantmentDuration(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET);}
+ uint32 GetEnchantmentCharges(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET);}
void SendTimeUpdate(Player* owner);
void UpdateDuration(Player* owner, uint32 diff);
diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp
index 085c9553a30..2c2cf2f82f1 100644
--- a/src/game/ItemHandler.cpp
+++ b/src/game/ItemHandler.cpp
@@ -324,7 +324,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
data << pProto->ItemId;
data << pProto->Class;
data << pProto->SubClass;
- data << uint32(-1); // new 2.0.3, not exist in wdb cache?
+ data << int32(pProto->Unk0); // new 2.0.3, not exist in wdb cache?
data << Name;
data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00);
@@ -346,14 +346,17 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
data << pProto->RequiredCityRank;
data << pProto->RequiredReputationFaction;
data << pProto->RequiredReputationRank;
- data << pProto->MaxCount;
- data << pProto->Stackable;
+ data << int32(pProto->MaxCount);
+ data << int32(pProto->Stackable);
data << pProto->ContainerSlots;
- for(int i = 0; i < 10; i++)
+ data << pProto->StatsCount; // item stats count
+ for(int i = 0; i < pProto->StatsCount; i++)
{
data << pProto->ItemStat[i].ItemStatType;
data << pProto->ItemStat[i].ItemStatValue;
}
+ data << pProto->ScalingStatDistribution; // scaling stats distribution
+ data << pProto->ScalingStatValue; // some kind of flags used to determine stat values column
for(int i = 0; i < 5; i++)
{
data << pProto->Damage[i].DamageMin;
@@ -417,7 +420,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
data << pProto->PageMaterial;
data << pProto->StartQuest;
data << pProto->LockID;
- data << pProto->Material;
+ data << int32(pProto->Material);
data << pProto->Sheath;
data << pProto->RandomProperty;
data << pProto->RandomSuffix;
@@ -437,7 +440,8 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
data << pProto->GemProperties;
data << pProto->RequiredDisenchantSkill;
data << pProto->ArmorDamageModifier;
- data << uint32(0); // added in 2.4.2.8209, duration (seconds)
+ data << pProto->Duration; // added in 2.4.2.8209, duration (seconds)
+ data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory
SendPacket( &data );
}
else
@@ -845,6 +849,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& /*recvPacket*/)
if (_player->GetMoney() < price)
return;
+ _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT, slot);
_player->SetByteValue(PLAYER_BYTES_2, 2, slot);
_player->ModifyMoney(-int32(price));
}
@@ -1109,10 +1114,6 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
CHECK_PACKET_SIZE(recv_data,8*4);
uint64 guids[4];
- uint32 GemEnchants[3], OldEnchants[3];
- Item *Gems[3];
- bool SocketBonusActivated, SocketBonusToBeActivated;
-
for(int i = 0; i < 4; i++)
recv_data >> guids[i];
@@ -1130,6 +1131,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
//this slot is excepted when applying / removing meta gem bonus
uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : NULL_SLOT;
+ Item *Gems[3];
for(int i = 0; i < 3; i++)
Gems[i] = guids[i + 1] ? _player->GetItemByGuid(guids[i + 1]) : NULL;
@@ -1149,6 +1151,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
return;
}
+ uint32 GemEnchants[3], OldEnchants[3];
for(int i = 0; i < 3; ++i) //get new and old enchantments
{
GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0;
@@ -1197,7 +1200,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
}
}
- SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus
+ bool SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus
_player->ToggleMetaGemsActive(slot, false); //turn off all metagems (except for the target item)
//if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met
@@ -1219,7 +1222,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
_player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true);
- SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state
+ bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state
if(SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change...
{
_player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false);
diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h
index 1ca412d246a..b31cc819629 100644
--- a/src/game/ItemPrototype.h
+++ b/src/game/ItemPrototype.h
@@ -57,10 +57,18 @@ enum ItemModType
ITEM_MOD_CRIT_TAKEN_RATING = 34,
ITEM_MOD_RESILIENCE_RATING = 35,
ITEM_MOD_HASTE_RATING = 36,
- ITEM_MOD_EXPERTISE_RATING = 37
+ ITEM_MOD_EXPERTISE_RATING = 37,
+ ITEM_MOD_ATTACK_POWER = 38,
+ ITEM_MOD_RANGED_ATTACK_POWER = 39,
+ ITEM_MOD_FERAL_ATTACK_POWER = 40,
+ ITEM_MOD_SPELL_HEALING_DONE = 41,
+ ITEM_MOD_SPELL_DAMAGE_DONE = 42,
+ ITEM_MOD_MANA_REGENERATION = 43,
+ ITEM_MOD_ARMOR_PENETRATION_RATING = 44,
+ ITEM_MOD_SPELL_POWER = 45
};
-#define MAX_ITEM_MOD 38
+#define MAX_ITEM_MOD 46
enum ItemSpelltriggerType
{
@@ -68,6 +76,12 @@ enum ItemSpelltriggerType
ITEM_SPELLTRIGGER_ON_EQUIP = 1,
ITEM_SPELLTRIGGER_CHANCE_ON_HIT = 2,
ITEM_SPELLTRIGGER_SOULSTONE = 4,
+ /*
+ * ItemSpelltriggerType 5 might have changed on 2.4.3/3.0.3: Such auras
+ * will be applied on item pickup and removed on item loss - maybe on the
+ * other hand the item is destroyed if the aura is removed ("removed on
+ * death" of spell 57348 makes me think so)
+ */
ITEM_SPELLTRIGGER_ON_NO_DELAY_USE = 5, // no equip cooldown
ITEM_SPELLTRIGGER_LEARN_SPELL_ID = 6 // used in item_template.spell_2 with spell_id with SPELL_GENERIC_LEARN in spell_1
};
@@ -185,10 +199,11 @@ enum ItemClass
ITEM_CLASS_QUEST = 12,
ITEM_CLASS_KEY = 13,
ITEM_CLASS_PERMANENT = 14,
- ITEM_CLASS_JUNK = 15
+ ITEM_CLASS_MISC = 15,
+ ITEM_CLASS_GLYPH = 16
};
-#define MAX_ITEM_CLASS 16
+#define MAX_ITEM_CLASS 17
enum ItemSubclassConsumable
{
@@ -214,10 +229,11 @@ enum ItemSubclassContainer
ITEM_SUBCLASS_ENGINEERING_CONTAINER = 4,
ITEM_SUBCLASS_GEM_CONTAINER = 5,
ITEM_SUBCLASS_MINING_CONTAINER = 6,
- ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7
+ ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7,
+ ITEM_SUBCLASS_INSCRIPTION_CONTAINER = 8
};
-#define MAX_ITEM_SUBCLASS_CONTAINER 8
+#define MAX_ITEM_SUBCLASS_CONTAINER 9
enum ItemSubclassWeapon
{
@@ -272,10 +288,11 @@ enum ItemSubclassArmor
ITEM_SUBCLASS_ARMOR_SHIELD = 6,
ITEM_SUBCLASS_ARMOR_LIBRAM = 7,
ITEM_SUBCLASS_ARMOR_IDOL = 8,
- ITEM_SUBCLASS_ARMOR_TOTEM = 9
+ ITEM_SUBCLASS_ARMOR_TOTEM = 9,
+ ITEM_SUBCLASS_ARMOR_SIGIL = 10
};
-#define MAX_ITEM_SUBCLASS_ARMOR 10
+#define MAX_ITEM_SUBCLASS_ARMOR 11
enum ItemSubclassReagent
{
@@ -310,10 +327,12 @@ enum ItemSubclassTradeGoods
ITEM_SUBCLASS_ELEMENTAL = 10,
ITEM_SUBCLASS_TRADE_GOODS_OTHER = 11,
ITEM_SUBCLASS_ENCHANTING = 12,
- ITEM_SUBCLASS_MATERIAL = 13 // Added in 2.4.2
+ ITEM_SUBCLASS_MATERIAL = 13,
+ ITEM_SUBCLASS_ARMOR_ENCHANTMENT = 14,
+ ITEM_SUBCLASS_WEAPON_ENCHANTMENT = 15
};
-#define MAX_ITEM_SUBCLASS_TRADE_GOODS 14
+#define MAX_ITEM_SUBCLASS_TRADE_GOODS 16
enum ItemSubclassGeneric
{
@@ -423,7 +442,8 @@ const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] =
MAX_ITEM_SUBCLASS_QUEST,
MAX_ITEM_SUBCLASS_KEY,
MAX_ITEM_SUBCLASS_PERMANENT,
- MAX_ITEM_SUBCLASS_JUNK
+ MAX_ITEM_SUBCLASS_JUNK,
+ MAX_ITEM_SUBCLASS_GLYPH
};
inline uint8 ItemSubClassToDurabilityMultiplierId(uint32 ItemClass, uint32 ItemSubClass)
@@ -477,7 +497,7 @@ struct ItemPrototype
uint32 ItemId;
uint32 Class; // id from ItemClass.dbc
uint32 SubClass; // id from ItemSubClass.dbc
- uint32 Unk0;
+ int32 Unk0;
char* Name1;
uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc
uint32 Quality;
@@ -497,10 +517,13 @@ struct ItemPrototype
uint32 RequiredCityRank;
uint32 RequiredReputationFaction; // id from Faction.dbc
uint32 RequiredReputationRank;
- uint32 MaxCount;
- uint32 Stackable;
+ int32 MaxCount; // <=0: no limit
+ int32 Stackable; // 0: not allowed, -1: put in player coin info tab and don't limit stacking (so 1 slot)
uint32 ContainerSlots;
+ uint32 StatsCount;
_ItemStat ItemStat[10];
+ uint32 ScalingStatDistribution; // id from ScalingStatDistribution.dbc
+ uint32 ScalingStatValue; // mask for selecting column in ScalingStatValues.dbc
_Damage Damage[5];
uint32 Armor;
uint32 HolyRes;
@@ -520,7 +543,7 @@ struct ItemPrototype
uint32 PageMaterial;
uint32 StartQuest; // id from QuestCache.wdb
uint32 LockID;
- uint32 Material; // id from Material.dbc
+ int32 Material; // id from Material.dbc
uint32 Sheath;
uint32 RandomProperty; // id from ItemRandomProperties.dbc
uint32 RandomSuffix; // id from ItemRandomSuffix.dbc
@@ -536,12 +559,13 @@ struct ItemPrototype
uint32 GemProperties; // id from GemProperties.dbc
uint32 RequiredDisenchantSkill;
float ArmorDamageModifier;
+ int32 Duration; // negative = realtime, positive = ingame time
+ uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc
uint32 ScriptId;
uint32 DisenchantID;
uint32 FoodType;
uint32 MinMoneyLoot;
uint32 MaxMoneyLoot;
- int32 Duration; // negative = realtime, positive = ingame time
// helpers
bool CanChangeEquipStateInCombat() const
@@ -563,6 +587,48 @@ struct ItemPrototype
return false;
}
+
+ uint32 GetScalingStatValuesColumn() const
+ {
+ if(ScalingStatValue & 0x00000001) // stat mod
+ return 0;
+ if(ScalingStatValue & 0x00000002) // stat mod
+ return 1;
+ if(ScalingStatValue & 0x00000004) // stat mod
+ return 2;
+ if(ScalingStatValue & 0x00000008) // stat mod
+ return 3;
+ if(ScalingStatValue & 0x00000010) // stat mod
+ return 4;
+ if(ScalingStatValue & 0x00000020) // armor mod
+ return 5;
+ if(ScalingStatValue & 0x00000040) // armor mod
+ return 6;
+ if(ScalingStatValue & 0x00000080) // armor mod
+ return 7;
+ if(ScalingStatValue & 0x00000100) // armor mod
+ return 8;
+ if(ScalingStatValue & 0x00000200) // damage mod
+ return 9;
+ if(ScalingStatValue & 0x00000400) // damage mod
+ return 10;
+ if(ScalingStatValue & 0x00000800) // damage mod
+ return 11;
+ if(ScalingStatValue & 0x00001000) // damage mod
+ return 12;
+ if(ScalingStatValue & 0x00002000) // damage mod
+ return 13;
+ if(ScalingStatValue & 0x00004000) // damage mod
+ return 14;
+ if(ScalingStatValue & 0x00008000) // spell power
+ return 15;
+ if(ScalingStatValue & 0x00020000) // feral AP
+ return 16;
+
+ return 0;
+ }
+
+ uint32 GetMaxStackSize() const { return Stackable > 0 ? uint32(Stackable) : uint32(0x7FFFFFFF-1); }
};
struct ItemLocale
diff --git a/src/game/Language.h b/src/game/Language.h
index d95489b056f..044934a2309 100644
--- a/src/game/Language.h
+++ b/src/game/Language.h
@@ -170,7 +170,9 @@ enum TrinityStrings
LANG_SOUND_NOT_EXIST = 170,
LANG_TELEPORTED_TO_BY_CONSOLE = 171,
LANG_CONSOLE_COMMAND = 172,
- // Room for more level 1 173-199 not used
+ LANG_YOU_CHANGE_RUNIC_POWER = 173,
+ LANG_YOURS_RUNIC_POWER_CHANGED = 174,
+ // Room for more level 1 175-199 not used
// level 2 chat
LANG_NO_SELECTION = 200,
@@ -322,6 +324,8 @@ enum TrinityStrings
LANG_CREATURE_NOT_FOLLOW_YOU_NOW = 342,
LANG_CREATURE_NON_TAMEABLE = 343,
LANG_YOU_ALREADY_HAVE_PET = 344,
+ LANG_CUSTOMIZE_PLAYER = 345,
+ LANG_CUSTOMIZE_PLAYER_GUID = 346,
// Room for more level 2 345-399 not used
// level 3 chat
@@ -636,11 +640,10 @@ enum TrinityStrings
LANG_BG_QUEUE_ANNOUNCE_SELF = 711,
LANG_BG_QUEUE_ANNOUNCE_WORLD = 712,
-
-
LANG_YOUR_ARENA_LEVEL_REQ_ERROR = 713,
-// LANG_HIS_ARENA_LEVEL_REQ_ERROR = 714, an opcode exists for this
+// = 714, not used
LANG_YOUR_BG_LEVEL_REQ_ERROR = 715,
+
// LANG_YOUR_ARENA_TEAM_FULL = 716, an opcode exists for this
LANG_BG_AV_ALLY = 717,
@@ -706,6 +709,31 @@ enum TrinityStrings
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."
+// = 716, not used
+ LANG_BG_STARTED_ANNOUNCE_WORLD = 717,
+ LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN= 718,
+ LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT= 719,
+
+ /*LANG_BG_GROUP_TOO_LARGE = 720, // "Your group is too large for this battleground. Please regroup to join."
+ LANG_ARENA_GROUP_TOO_LARGE = 721, // "Your group is too large for this arena. Please regroup to join."
+ LANG_ARENA_YOUR_TEAM_ONLY = 722, // "Your group has members not in your arena team. Please regroup to join."
+ LANG_ARENA_NOT_ENOUGH_PLAYERS = 723, // "Your group does not have enough players to join this match."
+ LANG_ARENA_GOLD_WINS = 724, // "The Gold Team wins!"
+ LANG_ARENA_GREEN_WINS = 725, // "The Green Team wins!"
+ LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 726, // The battleground will end soon, because there aren't enough players. Get more ppl or win already!
+ LANG_BG_GROUP_OFFLINE_MEMBER = 727, // "Your group has an offline member. Please remove him before joining."
+ LANG_BG_GROUP_MIXED_FACTION = 728, // "Your group has players from the opposing faction. You can't join the battleground as a group."
+ LANG_BG_GROUP_MIXED_LEVELS = 729, // "Your group has players from different battleground brakets. You can't join as group."
+ LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 730, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group."
+ LANG_BG_GROUP_MEMBER_DESERTER = 731, // "Someone in your party is Deserter. You can't join as group."
+ LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 732, // "Someone in your party is already in three battleground queues. You cannot join as group."
+
+ LANG_CANNOT_TELE_TO_BG = 733, // "You cannot teleport to a battleground or arena map."
+ LANG_CANNOT_SUMMON_TO_BG = 734, // "You cannot summon players to a battleground or arena map."
+ LANG_CANNOT_GO_TO_BG_GM = 735, // "You must be in GM mode to teleport to a player in a battleground."
+ LANG_CANNOT_GO_TO_BG_FROM_BG = 736, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first."*/
+ // Room for batleground/arena strings 737-799 not used
+
// in game strings
LANG_PET_INVALID_NAME = 800,
LANG_NOT_ENOUGH_GOLD = 801,
@@ -757,6 +785,10 @@ enum TrinityStrings
LANG_MUST_MALE_OR_FEMALE = 1119,
LANG_YOU_CHANGE_GENDER = 1120,
LANG_YOUR_GENDER_CHANGED = 1121,
+ LANG_SKILL_VALUES = 1122,
+ // Room for more level 3 1123-1199 not used
+
+ // FREE IDS 1200-9999
// Ticket Strings 2000-2029
LANG_COMMAND_TICKETNEW = 2000,
diff --git a/src/game/Level0.cpp b/src/game/Level0.cpp
index ff7d58f8da1..a3f3046a4ff 100644
--- a/src/game/Level0.cpp
+++ b/src/game/Level0.cpp
@@ -172,7 +172,7 @@ bool ChatHandler::HandleGMListIngameCommand(const char* /*args*/)
first = false;
}
- SendSysMessage(itr->second->GetName());
+ SendSysMessage(GetNameLink(itr->second).c_str());
}
}
diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp
index 8dacbc4954b..6a2e3158818 100644
--- a/src/game/Level1.cpp
+++ b/src/game/Level1.cpp
@@ -115,6 +115,10 @@ bool ChatHandler::HandleNpcWhisperCommand(const char* args)
uint64 receiver_guid= atol(receiver_str);
+ // check online security
+ if (HasLowerSecurity(objmgr.GetPlayer(receiver_guid), 0))
+ return false;
+
pCreature->Whisper(text,receiver_guid);
return true;
@@ -125,8 +129,7 @@ bool ChatHandler::HandleNameAnnounceCommand(const char* args)
WorldPacket data;
if(!*args)
return false;
- //char str[1024];
- //sprintf(str, GetTrinityString(LANG_ANNOUNCE_COLOR), m_session->GetPlayer()->GetName(), args);
+
sWorld.SendWorldText(LANG_ANNOUNCE_COLOR, m_session->GetPlayer()->GetName(), args);
return true;
}
@@ -650,14 +653,16 @@ bool ChatHandler::HandleVisibleCommand(const char* args)
return false;
}
+
+
bool ChatHandler::HandleGPSCommand(const char* args)
{
WorldObject *obj = NULL;
if (*args)
{
- std::string name = args;
- if(normalizePlayerName(name))
- obj = objmgr.GetPlayer(name.c_str());
+ uint64 guid = extractGuidFromLink((char*)args);
+ if(guid)
+ obj = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*m_session->GetPlayer(),guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
if(!obj)
{
@@ -708,18 +713,20 @@ bool ChatHandler::HandleGPSCommand(const char* args)
obj->GetMapId(), (mapEntry ? mapEntry->name[m_session->GetSessionDbcLocale()] : "<unknown>" ),
zone_id, (zoneEntry ? zoneEntry->area_name[m_session->GetSessionDbcLocale()] : "<unknown>" ),
area_id, (areaEntry ? areaEntry->area_name[m_session->GetSessionDbcLocale()] : "<unknown>" ),
+ obj->GetPhaseMask(),
obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(),
cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(),
zone_x, zone_y, ground_z, floor_z, have_map, have_vmap );
sLog.outDebug("Player %s GPS call for %s '%s' (%s: %u):",
- GetName(),
+ m_session ? GetNameLink().c_str() : GetMangosString(LANG_CONSOLE_COMMAND),
(obj->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), obj->GetName(),
(obj->GetTypeId() == TYPEID_PLAYER ? "GUID" : "Entry"), (obj->GetTypeId() == TYPEID_PLAYER ? obj->GetGUIDLow(): obj->GetEntry()) );
sLog.outDebug(GetTrinityString(LANG_MAP_POSITION),
obj->GetMapId(), (mapEntry ? mapEntry->name[sWorld.GetDefaultDbcLocale()] : "<unknown>" ),
zone_id, (zoneEntry ? zoneEntry->area_name[sWorld.GetDefaultDbcLocale()] : "<unknown>" ),
area_id, (areaEntry ? areaEntry->area_name[sWorld.GetDefaultDbcLocale()] : "<unknown>" ),
+ obj->GetPhaseMask(),
obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(),
cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(),
zone_x, zone_y, ground_z, floor_z, have_map, have_vmap );
@@ -733,9 +740,8 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
if(!*args)
return false;
- std::string name = args;
-
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -745,9 +751,14 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
Player *chr = objmgr.GetPlayer(name.c_str());
if (chr)
{
+ std::string nameLink = playerLink(name);
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
if(chr->IsBeingTeleported()==true)
{
- PSendSysMessage(LANG_IS_TELEPORTED, chr->GetName());
+ PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str());
SetSentErrorMessage(true);
return false;
}
@@ -757,7 +768,7 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
if(pMap->IsBattleGroundOrArena())
{
// cannot summon to bg
- PSendSysMessage(LANG_CANNOT_SUMMON_TO_BG,chr->GetName());
+ PSendSysMessage(LANG_CANNOT_SUMMON_TO_BG,nameLink.c_str());
SetSentErrorMessage(true);
return false;
}
@@ -767,7 +778,7 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
if( cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId() )
{
// cannot summon from instance to instance
- PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,chr->GetName());
+ PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str());
SetSentErrorMessage(true);
return false;
}
@@ -778,15 +789,15 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
(m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) )
// the last check is a bit excessive, but let it be, just in case
{
- PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,chr->GetName());
+ PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str());
SetSentErrorMessage(true);
return false;
}
}
- PSendSysMessage(LANG_SUMMONING, chr->GetName(),"");
+ PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),"");
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_SUMMONED_BY, GetName());
+ ChatHandler(chr).PSendSysMessage(LANG_SUMMONED_BY, nameLink.c_str());
// stop flight if need
if(chr->isInFlight())
@@ -805,7 +816,13 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
}
else if (uint64 guid = objmgr.GetPlayerGUIDByName(name))
{
- PSendSysMessage(LANG_SUMMONING, name.c_str(),GetTrinityString(LANG_OFFLINE));
+ // check offline security
+ if (HasLowerSecurity(NULL, guid))
+ return false;
+
+ std::string nameLink = playerLink(name);
+
+ PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),GetMangosString(LANG_OFFLINE));
// in point where GM stay
Player::SavePositionInDB(m_session->GetPlayer()->GetMapId(),
@@ -833,9 +850,8 @@ bool ChatHandler::HandleGonameCommand(const char* args)
Player* _player = m_session->GetPlayer();
- std::string name = args;
-
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -845,20 +861,26 @@ bool ChatHandler::HandleGonameCommand(const char* args)
Player *chr = objmgr.GetPlayer(name.c_str());
if (chr)
{
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ std::string chrNameLink = playerLink(name);
+
Map* cMap = chr->GetMap();
if(cMap->IsBattleGroundOrArena())
{
// only allow if gm mode is on
if (!_player->isGameMaster())
{
- PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chr->GetName());
+ PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
// if already in a bg, don't let port to other
else if (_player->GetBattleGroundId())
{
- PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chr->GetName());
+ PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
@@ -878,7 +900,7 @@ bool ChatHandler::HandleGonameCommand(const char* args)
// we are in group, we can go only if we are in the player group
if (_player->GetGroup() != chr->GetGroup())
{
- PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY,chr->GetName());
+ PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY,chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
@@ -888,7 +910,7 @@ bool ChatHandler::HandleGonameCommand(const char* args)
// we are not in group, let's verify our GM mode
if (!_player->isGameMaster())
{
- PSendSysMessage(LANG_CANNOT_GO_TO_INST_GM,chr->GetName());
+ PSendSysMessage(LANG_CANNOT_GO_TO_INST_GM,chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
@@ -912,10 +934,9 @@ bool ChatHandler::HandleGonameCommand(const char* args)
_player->SetDifficulty(chr->GetDifficulty());
}
- PSendSysMessage(LANG_APPEARING_AT, chr->GetName());
-
+ PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str());
if (_player->IsVisibleGloballyFor(chr))
- ChatHandler(chr).PSendSysMessage(LANG_APPEARING_TO, _player->GetName());
+ ChatHandler(chr).PSendSysMessage(LANG_APPEARING_TO, GetNameLink().c_str());
// stop flight if need
if(_player->isInFlight())
@@ -938,7 +959,13 @@ bool ChatHandler::HandleGonameCommand(const char* args)
if (uint64 guid = objmgr.GetPlayerGUIDByName(name))
{
- PSendSysMessage(LANG_APPEARING_AT, name.c_str());
+ // check offline security
+ if (HasLowerSecurity(NULL, guid))
+ return false;
+
+ std::string nameLink = playerLink(name);
+
+ PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str());
// to point where player stay (if loaded)
float x,y,z,o;
@@ -977,12 +1004,15 @@ bool ChatHandler::HandleRecallCommand(const char* args)
chr = getSelectedPlayer();
if(!chr)
chr = m_session->GetPlayer();
+
+ // check online security
+ else if (HasLowerSecurity(chr, 0))
+ return false;
}
else
{
- std::string name = args;
-
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -997,11 +1027,15 @@ bool ChatHandler::HandleRecallCommand(const char* args)
SetSentErrorMessage(true);
return false;
}
+
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
}
if(chr->IsBeingTeleported())
{
- PSendSysMessage(LANG_IS_TELEPORTED, chr->GetName());
+ PSendSysMessage(LANG_IS_TELEPORTED, GetNameLink(chr).c_str());
SetSentErrorMessage(true);
return false;
}
@@ -1035,6 +1069,10 @@ bool ChatHandler::HandleModifyKnownTitlesCommand(const char* args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
uint64 titles2 = titles;
for(int i=1; i < sCharTitlesStore.GetNumRows(); ++i)
@@ -1084,9 +1122,13 @@ bool ChatHandler::HandleModifyHPCommand(const char* args)
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_HP, chr->GetName(), hp, hpm);
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ PSendSysMessage(LANG_YOU_CHANGE_HP, GetNameLink(chr).c_str(), hp, hpm);
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, GetName(), hp, hpm);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, GetNameLink().c_str(), hp, hpm);
chr->SetMaxHealth( hpm );
chr->SetHealth( hp );
@@ -1128,9 +1170,13 @@ bool ChatHandler::HandleModifyManaCommand(const char* args)
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_MANA, chr->GetName(), mana, manam);
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ PSendSysMessage(LANG_YOU_CHANGE_MANA, GetNameLink(chr).c_str(), mana, manam);
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, GetName(), mana, manam);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, GetNameLink().c_str(), mana, manam);
chr->SetMaxPower(POWER_MANA,manam );
chr->SetPower(POWER_MANA, mana );
@@ -1173,9 +1219,13 @@ bool ChatHandler::HandleModifyEnergyCommand(const char* args)
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_ENERGY, chr->GetName(), energy/10, energym/10);
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ PSendSysMessage(LANG_YOU_CHANGE_ENERGY, GetNameLink(chr).c_str(), energy/10, energym/10);
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, GetName(), energy/10, energym/10);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, GetNameLink().c_str(), energy/10, energym/10);
chr->SetMaxPower(POWER_ENERGY,energym );
chr->SetPower(POWER_ENERGY, energy );
@@ -1220,9 +1270,13 @@ bool ChatHandler::HandleModifyRageCommand(const char* args)
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_RAGE, chr->GetName(), rage/10, ragem/10);
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ PSendSysMessage(LANG_YOU_CHANGE_RAGE, GetNameLink(chr).c_str(), rage/10, ragem/10);
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, GetName(), rage/10, ragem/10);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, GetNameLink().c_str(), rage/10, ragem/10);
chr->SetMaxPower(POWER_RAGE,ragem );
chr->SetPower(POWER_RAGE, rage );
@@ -1230,6 +1284,40 @@ bool ChatHandler::HandleModifyRageCommand(const char* args)
return true;
}
+// Edit Player Runic Power
+bool ChatHandler::HandleModifyRunicPowerCommand(const char* args)
+{
+ if(!*args)
+ return false;
+
+ int32 rune = atoi((char*)args)*10;
+ int32 runem = atoi((char*)args)*10;
+
+ if (rune <= 0 || runem <= 0 || runem < rune)
+ {
+ SendSysMessage(LANG_BAD_VALUE);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ Player *chr = getSelectedPlayer();
+ if (chr == NULL)
+ {
+ SendSysMessage(LANG_NO_CHAR_SELECTED);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ PSendSysMessage(LANG_YOU_CHANGE_RUNIC_POWER, GetNameLink(chr).c_str(), rune/10, runem/10);
+ if (needReportToTarget(chr))
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_RUNIC_POWER_CHANGED, GetNameLink().c_str(), rune/10, runem/10);
+
+ chr->SetMaxPower(POWER_RUNIC_POWER,runem );
+ chr->SetPower(POWER_RUNIC_POWER, rune );
+
+ return true;
+}
+
//Edit Player Faction
bool ChatHandler::HandleModifyFactionCommand(const char* args)
{
@@ -1344,9 +1432,13 @@ bool ChatHandler::HandleModifySpellCommand(const char* args)
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_SPELLFLATID, spellflatid, val, mark, chr->GetName());
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ PSendSysMessage(LANG_YOU_CHANGE_SPELLFLATID, spellflatid, val, mark, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, GetName(), spellflatid, val, mark);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, GetNameLink().c_str(), spellflatid, val, mark);
WorldPacket data(SMSG_SET_FLAT_SPELL_MODIFIER, (1+1+2+2));
data << uint8(spellflatid);
@@ -1374,6 +1466,11 @@ bool ChatHandler::HandleModifyTalentCommand (const char* args)
SetSentErrorMessage(true);
return false;
}
+
+ // check online security
+ if (HasLowerSecurity(player, 0))
+ return false;
+
player->SetFreeTalentPoints(tp);
return true;
}
@@ -1398,21 +1495,25 @@ bool ChatHandler::HandleTaxiCheatCommand(const char* args)
chr=m_session->GetPlayer();
}
+ // check online security
+ else if (HasLowerSecurity(chr, 0))
+ return false;
+
if (argstr == "on")
{
chr->SetTaxiCheater(true);
- PSendSysMessage(LANG_YOU_GIVE_TAXIS, chr->GetName());
+ PSendSysMessage(LANG_YOU_GIVE_TAXIS, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, GetName());
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, GetNameLink().c_str());
return true;
}
if (argstr == "off")
{
chr->SetTaxiCheater(false);
- PSendSysMessage(LANG_YOU_REMOVE_TAXIS, chr->GetName());
+ PSendSysMessage(LANG_YOU_REMOVE_TAXIS, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, GetName());
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, GetNameLink().c_str());
return true;
}
@@ -1445,16 +1546,22 @@ bool ChatHandler::HandleModifyASpeedCommand(const char* args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ std::string chrNameLink = GetNameLink(chr);
+
if(chr->isInFlight())
{
- PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName());
+ PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, chr->GetName());
+ PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, chrNameLink.c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetName(), ASpeed);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetNameLink().c_str(), ASpeed);
chr->SetSpeed(MOVE_WALK, ASpeed,true);
chr->SetSpeed(MOVE_RUN, ASpeed,true);
@@ -1487,16 +1594,22 @@ bool ChatHandler::HandleModifySpeedCommand(const char* args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ std::string chrNameLink = GetNameLink(chr);
+
if(chr->isInFlight())
{
- PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName());
+ PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, chr->GetName());
+ PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, chrNameLink.c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetName(), Speed);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetNameLink().c_str(), Speed);
chr->SetSpeed(MOVE_RUN,Speed,true);
@@ -1526,16 +1639,22 @@ bool ChatHandler::HandleModifySwimCommand(const char* args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ std::string chrNameLink = GetNameLink(chr);
+
if(chr->isInFlight())
{
- PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName());
+ PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, chr->GetName());
+ PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, chrNameLink.c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetName(), Swim);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetNameLink().c_str(), Swim);
chr->SetSpeed(MOVE_SWIM,Swim,true);
@@ -1565,16 +1684,22 @@ bool ChatHandler::HandleModifyBWalkCommand(const char* args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ std::string chrNameLink = GetNameLink(chr);
+
if(chr->isInFlight())
{
- PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName());
+ PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, chr->GetName());
+ PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, chrNameLink.c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetName(), BSpeed);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetNameLink().c_str(), BSpeed);
chr->SetSpeed(MOVE_RUN_BACK,BSpeed,true);
@@ -1604,9 +1729,13 @@ bool ChatHandler::HandleModifyFlyCommand(const char* args)
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, chr->GetName());
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetName(), FSpeed);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetNameLink().c_str(), FSpeed);
chr->SetSpeed(MOVE_FLIGHT,FSpeed,true);
@@ -1635,9 +1764,13 @@ bool ChatHandler::HandleModifyScaleCommand(const char* args)
return false;
}
- PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, chr->GetName());
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetName(), Scale);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetNameLink().c_str(), Scale);
chr->SetFloatValue(OBJECT_FIELD_SCALE_X, Scale);
@@ -1878,9 +2011,13 @@ bool ChatHandler::HandleModifyMountCommand(const char* args)
return false;
}
- PSendSysMessage(LANG_YOU_GIVE_MOUNT, chr->GetName());
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ PSendSysMessage(LANG_YOU_GIVE_MOUNT, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_MOUNT_GIVED, GetName());
+ ChatHandler(chr).PSendSysMessage(LANG_MOUNT_GIVED, GetNameLink().c_str());
chr->SetUInt32Value( UNIT_FIELD_FLAGS , 0x001000 );
chr->Mount(mId);
@@ -1915,6 +2052,10 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
int32 addmoney = atoi((char*)args);
uint32 moneyuser = chr->GetMoney();
@@ -1926,25 +2067,25 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args)
sLog.outDetail(GetTrinityString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney);
if(newmoney <= 0 )
{
- PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, chr->GetName());
+ PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, GetName());
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, GetNameLink().c_str());
chr->SetMoney(0);
}
else
{
- PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), chr->GetName());
+ PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetName(), abs(addmoney));
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetNameLink().c_str(), abs(addmoney));
chr->SetMoney( newmoney );
}
}
else
{
- PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, chr->GetName());
+ PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetName(), addmoney);
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetNameLink().c_str(), addmoney);
chr->ModifyMoney( addmoney );
}
@@ -1953,20 +2094,24 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args)
return true;
}
-//Edit Player field
+//Edit Unit field
bool ChatHandler::HandleModifyBitCommand(const char* args)
{
if( !*args )
return false;
- Player *chr = getSelectedPlayer();
- if (chr == NULL)
+ Unit *unit = getSelectedUnit();
+ if (!unit)
{
SendSysMessage(LANG_NO_CHAR_SELECTED);
SetSentErrorMessage(true);
return false;
}
+ // check online security
+ if (unit->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player *)unit, 0))
+ return false;
+
char* pField = strtok((char*)args, " ");
if (!pField)
return false;
@@ -1978,13 +2123,12 @@ bool ChatHandler::HandleModifyBitCommand(const char* args)
uint16 field = atoi(pField);
uint32 bit = atoi(pBit);
- if (field < 1 || field >= PLAYER_END)
+ if (field < OBJECT_END || field >= unit->GetValuesCount())
{
SendSysMessage(LANG_BAD_VALUE);
SetSentErrorMessage(true);
return false;
}
-
if (bit < 1 || bit > 32)
{
SendSysMessage(LANG_BAD_VALUE);
@@ -1992,17 +2136,16 @@ bool ChatHandler::HandleModifyBitCommand(const char* args)
return false;
}
- if ( chr->HasFlag( field, (1<<(bit-1)) ) )
+ if ( unit->HasFlag( field, (1<<(bit-1)) ) )
{
- chr->RemoveFlag( field, (1<<(bit-1)) );
+ unit->RemoveFlag( field, (1<<(bit-1)) );
PSendSysMessage(LANG_REMOVE_BIT, bit, field);
}
else
{
- chr->SetFlag( field, (1<<(bit-1)) );
+ unit->SetFlag( field, (1<<(bit-1)) );
PSendSysMessage(LANG_SET_BIT, bit, field);
}
-
return true;
}
@@ -2019,11 +2162,15 @@ bool ChatHandler::HandleModifyHonorCommand (const char* args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(target, 0))
+ return false;
+
int32 amount = (uint32)atoi(args);
target->ModifyHonorPoints(amount);
- PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, target->GetName(), target->GetHonorPoints());
+ PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, GetNameLink(target).c_str(), target->GetHonorPoints());
return true;
}
@@ -2116,9 +2263,9 @@ bool ChatHandler::HandleLookupAreaCommand(const char* args)
// send area in "id - [name]" format
std::ostringstream ss;
if (m_session)
- ss << areaEntry->ID << " - |cffffffff|Harea:" << areaEntry->ID << "|h[" << name << " " << localeNames[loc]<< "]|h|r";
- else
- ss << areaEntry->ID << " - " << name << " " << localeNames[loc];
+ ss << areaEntry->ID << " - |cffffffff|Harea:" << areaEntry->ID << "|h[" << name << " " << localeNames[loc]<< "]|h|r";
+ else
+ ss << areaEntry->ID << " - " << name << " " << localeNames[loc];
SendSysMessage (ss.str ().c_str());
@@ -2126,8 +2273,10 @@ bool ChatHandler::HandleLookupAreaCommand(const char* args)
}
}
}
+
if (counter == 0) // if counter == 0 then we found nth
SendSysMessage (LANG_COMMAND_NOAREAFOUND);
+
return true;
}
@@ -2156,7 +2305,7 @@ bool ChatHandler::HandleLookupTeleCommand(const char * args)
std::ostringstream reply;
- GameTeleMap const & teleMap = objmgr.GetGameTeleMap();
+ GameTeleMap const & teleMap = objmgr.GetGameTeleMap();
for(GameTeleMap::const_iterator itr = teleMap.begin(); itr != teleMap.end(); ++itr)
{
GameTele const* tele = &itr->second;
@@ -2165,9 +2314,9 @@ bool ChatHandler::HandleLookupTeleCommand(const char * args)
continue;
if (m_session)
- reply << " |cffffffff|Htele:" << itr->first << "|h[" << tele->name << "]|h|r\n";
- else
- reply << " " << itr->first << " " << tele->name << "\n";
+ reply << " |cffffffff|Htele:" << itr->first << "|h[" << tele->name << "]|h|r\n";
+ else
+ reply << " " << itr->first << " " << tele->name << "\n";
}
if(reply.str().empty())
@@ -2254,9 +2403,13 @@ bool ChatHandler::HandleSendMailCommand(const char* args)
// format: name "subject text" "mail text"
- char* pName = strtok((char*)args, " ");
- if(!pName)
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
return false;
+ }
char* tail1 = strtok(NULL, "");
if(!tail1)
@@ -2294,18 +2447,10 @@ bool ChatHandler::HandleSendMailCommand(const char* args)
if (!msgText)
return false;
- // pName, msgSubject, msgText isn't NUL after prev. check
- std::string name = pName;
+ // msgSubject, msgText isn't NUL after prev. check
std::string subject = msgSubject;
std::string text = msgText;
- if(!normalizePlayerName(name))
- {
- SendSysMessage(LANG_PLAYER_NOT_FOUND);
- SetSentErrorMessage(true);
- return false;
- }
-
uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name);
if(!receiver_guid)
{
@@ -2314,7 +2459,6 @@ bool ChatHandler::HandleSendMailCommand(const char* args)
return false;
}
- uint32 mailId = objmgr.GenerateMailID();
// from console show not existed sender
uint32 sender_guidlo = m_session ? m_session->GetPlayer()->GetGUIDLow() : 0;
@@ -2326,7 +2470,8 @@ bool ChatHandler::HandleSendMailCommand(const char* args)
WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, NULL, 0, 0, MAIL_CHECK_MASK_NONE);
- PSendSysMessage(LANG_MAIL_SENT, name.c_str());
+ std::string nameLink = playerLink(name);
+ PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str());
return true;
}
@@ -2336,14 +2481,8 @@ bool ChatHandler::HandleNameTeleCommand(const char * args)
if(!*args)
return false;
- char* pName = strtok((char*)args, " ");
-
- if(!pName)
- return false;
-
- std::string name = pName;
-
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -2374,17 +2513,22 @@ bool ChatHandler::HandleNameTeleCommand(const char * args)
Player *chr = objmgr.GetPlayer(name.c_str());
if (chr)
{
+ // check online security
+ if (HasLowerSecurity(chr, 0))
+ return false;
+
+ std::string chrNameLink = playerLink(name);
if(chr->IsBeingTeleported()==true)
{
- PSendSysMessage(LANG_IS_TELEPORTED, chr->GetName());
+ PSendSysMessage(LANG_IS_TELEPORTED, chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
- PSendSysMessage(LANG_TELEPORTING_TO, chr->GetName(),"", tele->name.c_str());
+ PSendSysMessage(LANG_TELEPORTING_TO, chrNameLink.c_str(),"", tele->name.c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetName());
+ ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetNameLink().c_str());
// stop flight if need
if(chr->isInFlight())
@@ -2398,10 +2542,17 @@ bool ChatHandler::HandleNameTeleCommand(const char * args)
chr->TeleportTo(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation);
}
- else if (uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str()))
+ else if (uint64 guid = objmgr.GetPlayerGUIDByName(name))
{
- PSendSysMessage(LANG_TELEPORTING_TO, name.c_str(), GetTrinityString(LANG_OFFLINE), tele->name.c_str());
- Player::SavePositionInDB(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation,MapManager::Instance().GetZoneId(tele->mapId,tele->position_x,tele->position_y),guid);
+ // check offline security
+ if (HasLowerSecurity(NULL, guid))
+ return false;
+
+ std::string nameLink = playerLink(name);
+
+ PSendSysMessage(LANG_TELEPORTING_TO, nameLink.c_str(), GetMangosString(LANG_OFFLINE), tele->name.c_str());
+ Player::SavePositionInDB(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation,
+ MapManager::Instance().GetZoneId(tele->mapId,tele->position_x,tele->position_y,tele->position_z),guid);
}
else
PSendSysMessage(LANG_NO_PLAYER, name.c_str());
@@ -2423,6 +2574,10 @@ bool ChatHandler::HandleGroupTeleCommand(const char * args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(player, 0))
+ return false;
+
// id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r
GameTele const* tele = extractGameTeleFromLink((char*)args);
if(!tele)
@@ -2439,10 +2594,13 @@ bool ChatHandler::HandleGroupTeleCommand(const char * args)
SetSentErrorMessage(true);
return false;
}
+
+ std::string nameLink = GetNameLink(player);
+
Group *grp = player->GetGroup();
if(!grp)
{
- PSendSysMessage(LANG_NOT_IN_GROUP,player->GetName());
+ PSendSysMessage(LANG_NOT_IN_GROUP,nameLink.c_str());
SetSentErrorMessage(true);
return false;
}
@@ -2454,15 +2612,21 @@ bool ChatHandler::HandleGroupTeleCommand(const char * args)
if(!pl || !pl->GetSession() )
continue;
+ // check online security
+ if (HasLowerSecurity(pl, 0))
+ return false;
+
+ std::string plNameLink = GetNameLink(pl);
+
if(pl->IsBeingTeleported())
{
- PSendSysMessage(LANG_IS_TELEPORTED, pl->GetName());
+ PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str());
continue;
}
- PSendSysMessage(LANG_TELEPORTING_TO, pl->GetName(),"", tele->name.c_str());
+ PSendSysMessage(LANG_TELEPORTING_TO, plNameLink.c_str(),"", tele->name.c_str());
if (needReportToTarget(pl))
- ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetName());
+ ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, nameLink.c_str());
// stop flight if need
if(pl->isInFlight())
@@ -2486,9 +2650,8 @@ bool ChatHandler::HandleGroupgoCommand(const char* args)
if(!*args)
return false;
- std::string name = args;
-
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -2503,16 +2666,22 @@ bool ChatHandler::HandleGroupgoCommand(const char* args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(player, 0))
+ return false;
+
Group *grp = player->GetGroup();
+ std::string nameLink = playerLink(name);
+
if(!grp)
{
- PSendSysMessage(LANG_NOT_IN_GROUP,player->GetName());
+ PSendSysMessage(LANG_NOT_IN_GROUP,nameLink.c_str());
SetSentErrorMessage(true);
return false;
}
- Map* gmMap = MapManager::Instance().GetMap(m_session->GetPlayer()->GetMapId(),m_session->GetPlayer());
+ Map* gmMap = m_session->GetPlayer()->GetMap();
bool to_instance = gmMap->Instanceable();
// we are in instance, and can summon only player in our group with us as lead
@@ -2533,29 +2702,35 @@ bool ChatHandler::HandleGroupgoCommand(const char* args)
if(!pl || pl==m_session->GetPlayer() || !pl->GetSession() )
continue;
+ // check online security
+ if (HasLowerSecurity(pl, 0))
+ return false;
+
+ std::string plNameLink = playerLink(name);
+
if(pl->IsBeingTeleported()==true)
{
- PSendSysMessage(LANG_IS_TELEPORTED, pl->GetName());
+ PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
if (to_instance)
{
- Map* plMap = MapManager::Instance().GetMap(pl->GetMapId(),pl);
+ Map* plMap = pl->GetMap();
if ( plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId() )
{
// cannot summon from instance to instance
- PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,pl->GetName());
+ PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,plNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
}
- PSendSysMessage(LANG_SUMMONING, pl->GetName(),"");
+ PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(),"");
if (needReportToTarget(pl))
- ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetName());
+ ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, nameLink.c_str());
// stop flight if need
if(pl->isInFlight())
diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp
index d926c153e65..ad422e3ed3d 100644
--- a/src/game/Level2.cpp
+++ b/src/game/Level2.cpp
@@ -10,12 +10,12 @@
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Common.h"
@@ -36,6 +36,7 @@
#include "GameEvent.h"
#include "SpellMgr.h"
#include "AccountMgr.h"
+//#include "GMTicketMgr.h"
#include "WaypointManager.h"
#include "Util.h"
#include <cctype>
@@ -58,11 +59,13 @@ bool ChatHandler::HandleMuteCommand(const char* args)
if (!*args)
return false;
- char *charname = strtok((char*)args, " ");
- if (!charname)
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
return false;
-
- std::string cname = charname;
+ }
char *timetonotspeak = strtok(NULL, " ");
if(!timetonotspeak)
@@ -70,14 +73,7 @@ bool ChatHandler::HandleMuteCommand(const char* args)
uint32 notspeaktime = (uint32) atoi(timetonotspeak);
- if(!normalizePlayerName(cname))
- {
- SendSysMessage(LANG_PLAYER_NOT_FOUND);
- SetSentErrorMessage(true);
- return false;
- }
-
- uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
+ uint64 guid = objmgr.GetPlayerGUIDByName(name);
if(!guid)
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
@@ -87,27 +83,11 @@ bool ChatHandler::HandleMuteCommand(const char* args)
Player *chr = objmgr.GetPlayer(guid);
- // check security
- uint32 account_id = 0;
- uint32 security = 0;
-
- if (chr)
- {
- account_id = chr->GetSession()->GetAccountId();
- security = chr->GetSession()->GetSecurity();
- }
- else
- {
- account_id = objmgr.GetPlayerAccountIdByGUID(guid);
- security = accmgr.GetSecurity(account_id);
- }
-
- if(m_session && security >= m_session->GetSecurity())
- {
- SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
- SetSentErrorMessage(true);
+ // must have strong lesser security level
+ if(HasLowerSecurity (chr,guid,true))
return false;
- }
+
+ uint32 account_id = chr ? chr->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(guid);
time_t mutetime = time(NULL) + notspeaktime*60;
@@ -119,7 +99,9 @@ bool ChatHandler::HandleMuteCommand(const char* args)
if(chr)
ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
- PSendSysMessage(LANG_YOU_DISABLE_CHAT, cname.c_str(), notspeaktime);
+ std::string nameLink = playerLink(name);
+
+ PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime);
return true;
}
@@ -130,20 +112,15 @@ bool ChatHandler::HandleUnmuteCommand(const char* args)
if (!*args)
return false;
- char *charname = strtok((char*)args, " ");
- if (!charname)
- return false;
-
- std::string cname = charname;
-
- if(!normalizePlayerName(cname))
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
return false;
}
- uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
+ uint64 guid = objmgr.GetPlayerGUIDByName(name);
if(!guid)
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
@@ -153,27 +130,11 @@ bool ChatHandler::HandleUnmuteCommand(const char* args)
Player *chr = objmgr.GetPlayer(guid);
- // check security
- uint32 account_id = 0;
- uint32 security = 0;
-
- if (chr)
- {
- account_id = chr->GetSession()->GetAccountId();
- security = chr->GetSession()->GetSecurity();
- }
- else
- {
- account_id = objmgr.GetPlayerAccountIdByGUID(guid);
- security = accmgr.GetSecurity(account_id);
- }
-
- if(m_session && security >= m_session->GetSecurity())
- {
- SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
- SetSentErrorMessage(true);
+ // must have strong lesser security level
+ if(HasLowerSecurity (chr,guid,true))
return false;
- }
+
+ uint32 account_id = chr ? chr->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(guid);
if (chr)
{
@@ -192,7 +153,9 @@ bool ChatHandler::HandleUnmuteCommand(const char* args)
if(chr)
ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
- PSendSysMessage(LANG_YOU_ENABLE_CHAT, cname.c_str());
+ std::string nameLink = playerLink(name);
+
+ PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str());
return true;
}
@@ -562,7 +525,7 @@ bool ChatHandler::HandleLookupFactionCommand(const char* args)
return false;
// Can be NULL at console call
- Player *target = getSelectedPlayer ();
+ Player *target = getSelectedPlayer ();
std::string namepart = args;
std::wstring wnamepart;
@@ -581,12 +544,13 @@ bool ChatHandler::HandleLookupFactionCommand(const char* args)
if (factionEntry)
{
FactionState const* repState = NULL;
- if(target)
- {
- FactionStateList::const_iterator repItr = target->m_factions.find (factionEntry->reputationListID);
- if(repItr != target->m_factions.end())
- repState = &repItr->second;
- }
+ if(target)
+ {
+ FactionStateList::const_iterator repItr = target->m_factions.find (factionEntry->reputationListID);
+ if(repItr != target->m_factions.end())
+ repState = &repItr->second;
+ }
+
int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale();
std::string name = factionEntry->name[loc];
@@ -616,9 +580,9 @@ bool ChatHandler::HandleLookupFactionCommand(const char* args)
// or "id - [faction] [no reputation]" format
std::ostringstream ss;
if (m_session)
- ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
- else
- ss << id << " - " << name << " " << localeNames[loc];
+ ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
+ else
+ ss << id << " - " << name << " " << localeNames[loc];
if (repState) // and then target!=NULL also
{
@@ -668,6 +632,10 @@ bool ChatHandler::HandleModifyRepCommand(const char * args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(target, 0))
+ return false;
+
char* factionTxt = extractKeyFromLink((char*)args,"Hfaction");
if(!factionTxt)
return false;
@@ -745,11 +713,11 @@ bool ChatHandler::HandleModifyRepCommand(const char * args)
}
target->SetFactionReputation(factionEntry,amount);
- PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, target->GetName(), target->GetReputation(factionId));
+ PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, GetNameLink(target).c_str(), target->GetReputation(factionId));
return true;
}
-bool ChatHandler::HandleNameCommand(const char* args)
+bool ChatHandler::HandleNameCommand(const char* /*args*/)
{
/* Temp. disabled
if(!*args)
@@ -882,8 +850,8 @@ bool ChatHandler::HandleNpcAddCommand(const char* args)
{
if(!*args)
return false;
- char* charID = strtok((char*)args, " ");
- if (!charID)
+ char* charID = extractKeyFromLink((char*)args,"Hcreature_entry");
+ if(!charID)
return false;
char* team = strtok(NULL, " ");
@@ -901,7 +869,7 @@ bool ChatHandler::HandleNpcAddCommand(const char* args)
Map *map = chr->GetMap();
Creature* pCreature = new Creature;
- if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, (uint32)teamval))
+ if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, (uint32)teamval))
{
delete pCreature;
return false;
@@ -916,7 +884,7 @@ bool ChatHandler::HandleNpcAddCommand(const char* args)
return false;
}
- pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
+ pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
uint32 db_guid = pCreature->GetDBTableGUIDLow();
@@ -949,7 +917,7 @@ bool ChatHandler::HandleNpcDeleteCommand(const char* args)
else
unit = getSelectedCreature();
- if(!unit || unit->isPet() || unit->isTotem())
+ if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle())
{
SendSysMessage(LANG_SELECT_CREATURE);
SetSentErrorMessage(true);
@@ -1056,14 +1024,14 @@ bool ChatHandler::HandleTurnObjectCommand(const char* args)
float rot2 = sin(o/2);
float rot3 = cos(o/2);
- Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
+ Map* map = obj->GetMap();
map->Remove(obj,false);
obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
obj->SetFloatValue(GAMEOBJECT_FACING, o);
- obj->SetFloatValue(GAMEOBJECT_ROTATION+2, rot2);
- obj->SetFloatValue(GAMEOBJECT_ROTATION+3, rot3);
+ obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2);
+ obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3);
map->Add(obj);
@@ -1140,7 +1108,7 @@ bool ChatHandler::HandleNpcMoveCommand(const char* args)
const_cast<CreatureData*>(data)->posZ = z;
const_cast<CreatureData*>(data)->orientation = o;
}
- MapManager::Instance().GetMap(pCreature->GetMapId(),pCreature)->CreatureRelocation(pCreature,x, y, z,o);
+ pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o);
pCreature->GetMotionMaster()->Initialize();
if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
{
@@ -1187,7 +1155,7 @@ bool ChatHandler::HandleMoveObjectCommand(const char* args)
{
Player *chr = m_session->GetPlayer();
- Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
+ Map* map = obj->GetMap();
map->Remove(obj,false);
obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation());
@@ -1213,7 +1181,7 @@ bool ChatHandler::HandleMoveObjectCommand(const char* args)
return false;
}
- Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
+ Map* map = obj->GetMap();
map->Remove(obj,false);
obj->Relocate(x, y, z, obj->GetOrientation());
@@ -1239,6 +1207,11 @@ bool ChatHandler::HandleDeMorphCommand(const char* /*args*/)
if(!target)
target = m_session->GetPlayer();
+
+ // check online security
+ else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
+ return false;
+
target->DeMorph();
return true;
@@ -1314,7 +1287,6 @@ bool ChatHandler::HandleDelVendorItemCommand(const char* args)
}
uint32 itemId = atol(pitem);
-
if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId))
{
PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
@@ -1629,6 +1601,10 @@ bool ChatHandler::HandleMorphCommand(const char* args)
if(!target)
target = m_session->GetPlayer();
+ // check online security
+ else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
+ return false;
+
target->SetDisplayId(display_id);
return true;
@@ -1688,7 +1664,7 @@ bool ChatHandler::HandleKickPlayerCommand(const char *args)
kicker = m_session->GetPlayer()->GetName();
if(!kickName)
- {
+ {
Player* player = getSelectedPlayer();
if(!player)
{
@@ -1703,15 +1679,17 @@ bool ChatHandler::HandleKickPlayerCommand(const char *args)
SetSentErrorMessage(true);
return false;
}
-
+
+ // check online security
+ if (HasLowerSecurity(player, 0))
+ return false;
+
if(sWorld.getConfig(CONFIG_SHOW_KICK_IN_WORLD) == 1)
{
-
sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, player->GetName(), kicker.c_str(), reason.c_str());
}
else
{
-
PSendSysMessage(LANG_COMMAND_KICKMESSAGE, player->GetName(), kicker.c_str(), reason.c_str());
}
@@ -1719,8 +1697,8 @@ bool ChatHandler::HandleKickPlayerCommand(const char *args)
}
else
{
- std::string name = kickName;
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink((char*)kickName);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -1742,34 +1720,56 @@ bool ChatHandler::HandleKickPlayerCommand(const char *args)
return false;
}
- if(m_session && player->GetSession()->GetSecurity() > m_session->GetSecurity())
+ if(HasLowerSecurity(player, 0))
{
SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); //maybe replacement string for this later on
SetSentErrorMessage(true);
return false;
}
+
+ std::string nameLink = playerLink(name);
- if(sWorld.KickPlayer(name.c_str()))
+ if(sWorld.KickPlayer(name))
{
if(sWorld.getConfig(CONFIG_SHOW_KICK_IN_WORLD) == 1)
{
-
- sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, name.c_str(), kicker.c_str(), reason.c_str());
+ sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, nameLink.c_str(), kicker.c_str(), reason.c_str());
}
else
{
- PSendSysMessage(LANG_COMMAND_KICKMESSAGE, name.c_str(), kicker.c_str(), reason.c_str());
+ PSendSysMessage(LANG_COMMAND_KICKMESSAGE,nameLink.c_str());
}
}
else
{
- PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER, name.c_str());
+ PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,nameLink.c_str());
return false;
}
}
return true;
}
+//set temporary phase mask for player
+bool ChatHandler::HandleModifyPhaseCommand(const char* args)
+{
+ if (!*args)
+ return false;
+
+ uint32 phasemask = (uint32)atoi((char*)args);
+
+ Unit *target = getSelectedUnit();
+ if(!target)
+ target = m_session->GetPlayer();
+
+ // check online security
+ else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
+ return false;
+
+ target->SetPhaseMask(phasemask,true);
+
+ return true;
+}
+
//show info of player
bool ChatHandler::HandlePInfoCommand(const char* args)
{
@@ -1783,12 +1783,8 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
if (px)
{
- name = px;
-
+ name = extractPlayerNameFromLink(px);
if(name.empty())
- return false;
-
- if(!normalizePlayerName(name))
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -1829,6 +1825,10 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
// get additional information from Player object
if(target)
{
+ // check online security
+ if (HasLowerSecurity(target, 0))
+ return false;
+
targetGUID = target->GetGUID();
name = target->GetName(); // re-read for case getSelectedPlayer() target
accId = target->GetSession()->GetAccountId();
@@ -1840,6 +1840,11 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
// get additional information from DB
else
{
+ // check offline security
+ if (HasLowerSecurity(NULL, targetGUID))
+ return false;
+
+ // 0
QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(targetGUID));
if (!result)
{
@@ -1850,7 +1855,7 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
Field *fields = result->Fetch();
total_player_time = fields[0].GetUInt32();
delete result;
-
+
Tokens data;
if (!Player::LoadValuesArrayFromDB(data,targetGUID))
{
@@ -1858,7 +1863,7 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
SetSentErrorMessage(true);
return false;
}
-
+
money = Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_COINAGE);
level = Player::GetUInt32ValueFromArray(data, UNIT_FIELD_LEVEL);
accId = objmgr.GetPlayerAccountIdByGUID(targetGUID);
@@ -1875,8 +1880,8 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
Field* fields = result->Fetch();
username = fields[0].GetCppString();
security = fields[1].GetUInt32();
-
- if(!m_session || m_session->GetSecurity() >= security)
+
+ if(!m_session || m_session->GetSecurity() >= security)
{
last_ip = fields[2].GetCppString();
last_login = fields[3].GetCppString();
@@ -1890,7 +1895,9 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
delete result;
}
- PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetTrinityString(LANG_OFFLINE)), name.c_str(), GUID_LOPART(targetGUID), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency);
+ std::string nameLink = playerLink(name);
+
+ PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetMangosString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(targetGUID), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency);
std::string timeStr = secsToTimeString(total_player_time,true,true);
uint32 gold = money /GOLD;
@@ -1940,6 +1947,191 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
return true;
}
+/*//show tickets
+void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
+{
+ std::string name;
+ if(!objmgr.GetPlayerNameByGUID(guid,name))
+ name = GetTrinityString(LANG_UNKNOWN);
+
+ std::string nameLink = playerLink(name);
+
+ PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(),time,text);
+}
+
+//ticket commands
+bool ChatHandler::HandleTicketCommand(const char* args)
+{
+ char* px = strtok((char*)args, " ");
+
+ // ticket<end>
+ if (!px)
+ {
+ if(!m_session)
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ size_t count = ticketmgr.GetTicketCount();
+
+ bool accept = m_session->GetPlayer()->isAcceptTickets();
+
+ PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetTrinityString(LANG_ON) : GetTrinityString(LANG_OFF));
+ return true;
+ }
+
+ // ticket on
+ if(strncmp(px,"on",3) == 0)
+ {
+ if(!m_session)
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ m_session->GetPlayer()->SetAcceptTicket(true);
+ SendSysMessage(LANG_COMMAND_TICKETON);
+ return true;
+ }
+
+ // ticket off
+ if(strncmp(px,"off",4) == 0)
+ {
+ if(!m_session)
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ m_session->GetPlayer()->SetAcceptTicket(false);
+ SendSysMessage(LANG_COMMAND_TICKETOFF);
+ return true;
+ }
+
+ // ticket #num
+ int num = atoi(px);
+ if(num > 0)
+ {
+ QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
+
+ if(!result)
+ {
+ PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ Field* fields = result->Fetch();
+
+ uint32 guid = fields[0].GetUInt32();
+ char const* text = fields[1].GetString();
+ char const* time = fields[2].GetString();
+
+ ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time);
+ delete result;
+ return true;
+ }
+
+ std::string name = extractPlayerNameFromLink(px);
+ if(name.empty())
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ uint64 guid = objmgr.GetPlayerGUIDByName(name);
+
+ if(!guid)
+ return false;
+
+ // ticket $char_name
+ GMTicket* ticket = ticketmgr.GetGMTicket(GUID_LOPART(guid));
+ if(!ticket)
+ return false;
+
+ std::string time = TimeToTimestampStr(ticket->GetLastUpdate());
+
+ ShowTicket(guid, ticket->GetText(), time.c_str());
+
+ return true;
+}
+
+//dell all tickets
+bool ChatHandler::HandleDelTicketCommand(const char *args)
+{
+ char* px = strtok((char*)args, " ");
+ if (!px)
+ return false;
+
+ // delticket all
+ if(strncmp(px,"all",4) == 0)
+ {
+ ticketmgr.DeleteAll();
+ SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
+ return true;
+ }
+
+ int num = (uint32)atoi(px);
+
+ // delticket #num
+ if(num > 0)
+ {
+ QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
+ if(!result)
+ {
+ PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
+ SetSentErrorMessage(true);
+ return false;
+ }
+ Field* fields = result->Fetch();
+ uint32 guid = fields[0].GetUInt32();
+ delete result;
+
+ ticketmgr.Delete(guid);
+
+ //notify player
+ if(Player* pl = objmgr.GetPlayer(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)))
+ {
+ pl->GetSession()->SendGMTicketGetTicket(0x0A, 0);
+ PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, GetNameLink(pl).c_str());
+ }
+ else
+ PSendSysMessage(LANG_COMMAND_TICKETDEL);
+
+ return true;
+ }
+
+ std::string name = extractPlayerNameFromLink(px);
+ if(name.empty())
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ uint64 guid = objmgr.GetPlayerGUIDByName(name);
+
+ if(!guid)
+ return false;
+
+ // delticket $char_name
+ ticketmgr.Delete(GUID_LOPART(guid));
+
+ // notify players about ticket deleting
+ if(Player* sender = objmgr.GetPlayer(guid))
+ sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
+
+ std::string nameLink = playerLink(name);
+
+ PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,nameLink.c_str());
+ return true;
+}*/
+
//set spawn dist of creature
bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
{
@@ -2569,7 +2761,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
wpCreature->AddObjectToRemoveList();
// re-create
Creature* wpCreature2 = new Creature;
- if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, VISUAL_WAYPOINT, 0))
+ if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0))
{
PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
delete wpCreature2;
@@ -2584,7 +2776,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
return false;
}
- wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
+ wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
map->Add(wpCreature2);
@@ -2618,7 +2810,6 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
}
PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
-
return true;
}
@@ -2800,7 +2991,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
float o = chr->GetOrientation();
Creature* wpCreature = new Creature;
- if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
+ if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0))
{
PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete wpCreature;
@@ -2822,7 +3013,8 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
// set "wpguid" column to the visual waypoint
WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point);
- wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
+ wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
map->Add(wpCreature);
@@ -2863,7 +3055,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
Map *map = chr->GetMap();
Creature* pCreature = new Creature;
- if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, id, 0))
+ if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, chr->GetPhaseMaskForSpawn(), id, 0))
{
PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete pCreature;
@@ -2880,8 +3072,8 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
delete result;
return false;
}
-
- pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
+
+ pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
map->Add(pCreature);
@@ -2928,7 +3120,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
Map *map = chr->GetMap();
Creature* pCreature = new Creature;
- if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
+ if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0))
{
PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
delete pCreature;
@@ -2945,8 +3137,8 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
delete result;
return false;
}
-
- pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
+
+ pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
map->Add(pCreature);
@@ -3028,9 +3220,8 @@ bool ChatHandler::HandleRenameCommand(const char* args)
if(px)
{
- oldname = px;
-
- if(!normalizePlayerName(oldname))
+ oldname = extractPlayerNameFromLink(px);
+ if(oldname.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -3057,19 +3248,83 @@ bool ChatHandler::HandleRenameCommand(const char* args)
if(target)
{
- PSendSysMessage(LANG_RENAME_PLAYER, target->GetName());
+ // check online security
+ if (HasLowerSecurity(target, 0))
+ return false;
+
+ PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str());
target->SetAtLoginFlag(AT_LOGIN_RENAME);
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
}
else
{
- PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID));
+ // check offline security
+ if (HasLowerSecurity(NULL, targetGUID))
+ return false;
+
+ std::string oldNameLink = playerLink(oldname);
+
+ PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGUID));
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID));
}
return true;
}
+// customize characters
+bool ChatHandler::HandleCustomizeCommand(const char* args)
+{
+ Player* target = NULL;
+ uint64 targetGUID = 0;
+ std::string oldname;
+
+ char* px = strtok((char*)args, " ");
+
+ if(px)
+ {
+ oldname = extractPlayerNameFromLink(px);
+ if(oldname.empty())
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ target = objmgr.GetPlayer(oldname.c_str());
+
+ if (!target)
+ targetGUID = objmgr.GetPlayerGUIDByName(oldname);
+ }
+
+ if(!target && !targetGUID)
+ {
+ target = getSelectedPlayer();
+ }
+
+ if(!target && !targetGUID)
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ if(target)
+ {
+ PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str());
+ target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
+ CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow());
+ }
+ else
+ {
+ std::string oldNameLink = playerLink(oldname);
+
+ PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGUID));
+ CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(targetGUID));
+ }
+
+ return true;
+}
+
//spawn go
bool ChatHandler::HandleGameObjectCommand(const char* args)
{
@@ -3108,7 +3363,7 @@ bool ChatHandler::HandleGameObjectCommand(const char* args)
GameObject* pGameObj = new GameObject;
uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
- if(!pGameObj->Create(db_lowGUID, goI->id, map, x, y, z, o, 0, 0, rot2, rot3, 0, 1))
+ if(!pGameObj->Create(db_lowGUID, goI->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0, 0, rot2, rot3, 0, 1))
{
delete pGameObj;
return false;
@@ -3122,7 +3377,7 @@ bool ChatHandler::HandleGameObjectCommand(const char* args)
}
// fill the gameobject data and save to the db
- pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
+ pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()),chr->GetPhaseMaskForSpawn());
// this will generate a new guid if the object is in an instance
if(!pGameObj->LoadFromDB(db_lowGUID, map))
@@ -3178,6 +3433,10 @@ bool ChatHandler::HandleAddHonorCommand(const char* args)
return false;
}
+ // check online security
+ if (HasLowerSecurity(target, 0))
+ return false;
+
uint32 amount = (uint32)atoi(args);
target->RewardHonor(NULL, 1, amount);
return true;
@@ -3193,6 +3452,10 @@ bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
return false;
}
+ // check online security
+ if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
+ return false;
+
m_session->GetPlayer()->RewardHonor(target, 1);
return true;
}
@@ -3207,6 +3470,10 @@ bool ChatHandler::HandleUpdateHonorFieldsCommand(const char* /*args*/)
return false;
}
+ // check online security
+ if (HasLowerSecurity(target, 0))
+ return false;
+
target->UpdateHonorFields();
return true;
}
@@ -3241,11 +3508,11 @@ bool ChatHandler::HandleLookupEventCommand(const char* args)
if (Utf8FitTo(descr, wnamepart))
{
char const* active = activeEvents.find(id) != activeEvents.end() ? GetTrinityString(LANG_ACTIVE) : "";
-
- if(m_session)
- PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
- else
- PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
+
+ if(m_session)
+ PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
+ else
+ PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
++counter;
}
@@ -3272,9 +3539,9 @@ bool ChatHandler::HandleEventActiveListCommand(const char* args)
GameEventData const& eventData = events[event_id];
if(m_session)
- PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active );
- else
- PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active );
+ PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active );
+ else
+ PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active );
++counter;
}
@@ -3423,9 +3690,8 @@ bool ChatHandler::HandleCombatStopCommand(const char* args)
if(*args)
{
- std::string playername = args;
-
- if(!normalizePlayerName(playername))
+ std::string playername = extractPlayerNameFromLink((char*)args);
+ if(playername.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -3449,6 +3715,10 @@ bool ChatHandler::HandleCombatStopCommand(const char* args)
player = m_session->GetPlayer();
}
+ // check online security
+ if (HasLowerSecurity(player, 0))
+ return false;
+
player->CombatStop();
player->getHostilRefManager().deleteReferences();
return true;
@@ -3487,7 +3757,7 @@ bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
continue;
- m_session->GetPlayer()->learnSpell(skillLine->spellId);
+ m_session->GetPlayer()->learnSpell(skillLine->spellId,false);
}
}
}
@@ -3560,7 +3830,7 @@ bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
continue;
if( !target->HasSpell(spellInfo->Id) )
- m_session->GetPlayer()->learnSpell(skillLine->spellId);
+ m_session->GetPlayer()->learnSpell(skillLine->spellId,false);
}
uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id);
@@ -3575,13 +3845,13 @@ bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
{
-
+
if (!*args)
return false;
std::string ip = strtok ((char*)args, " ");
- char* limit_str = strtok (NULL, " ");
- int32 limit = limit_str ? atoi (limit_str) : -1;
+ char* limit_str = strtok (NULL, " ");
+ int32 limit = limit_str ? atoi (limit_str) : -1;
LoginDatabase.escape_string (ip);
@@ -3596,8 +3866,8 @@ bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
return false;
std::string account = strtok ((char*)args, " ");
- char* limit_str = strtok (NULL, " ");
- int32 limit = limit_str ? atoi (limit_str) : -1;
+ char* limit_str = strtok (NULL, " ");
+ int32 limit = limit_str ? atoi (limit_str) : -1;
if (!AccountMgr::normilizeString (account))
return false;
@@ -3611,13 +3881,13 @@ bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
{
-
+
if (!*args)
return false;
std::string email = strtok ((char*)args, " ");
- char* limit_str = strtok (NULL, " ");
- int32 limit = limit_str ? atoi (limit_str) : -1;
+ char* limit_str = strtok (NULL, " ");
+ int32 limit = limit_str ? atoi (limit_str) : -1;
LoginDatabase.escape_string (email);
@@ -3641,7 +3911,7 @@ bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
Field* fields = result->Fetch();
uint32 acc_id = fields[0].GetUInt32();
std::string acc_name = fields[1].GetCppString();
-
+
QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
if(chars)
{
@@ -3673,8 +3943,8 @@ bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
/// Triggering corpses expire check in world
bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
{
- CorpsesErase();
- return true;
+ CorpsesErase();
+ return true;
}
bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
@@ -3686,14 +3956,52 @@ bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
PSendSysMessage(LANG_NO_CHAR_SELECTED);
SetSentErrorMessage(true);
return false;
- }
+ }
+
+ // check online security
+ if (HasLowerSecurity(target, 0))
+ return false;
// Repair items
target->DurabilityRepairAll(false, 0, false);
- PSendSysMessage(LANG_YOU_REPAIR_ITEMS, target->GetName());
+ PSendSysMessage(LANG_YOU_REPAIR_ITEMS, GetNameLink(target).c_str());
if(needReportToTarget(target))
- ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetName());
+ ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetNameLink().c_str());
+ return true;
+}
+
+bool ChatHandler::HandleWaterwalkCommand(const char* args)
+{
+ if(!*args)
+ return false;
+
+ Player *player = getSelectedPlayer();
+
+ if(!player)
+ {
+ PSendSysMessage(LANG_NO_CHAR_SELECTED);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ // check online security
+ if (HasLowerSecurity(player, 0))
+ return false;
+
+ if (strncmp(args, "on", 3) == 0)
+ player->SetMovement(MOVE_WATER_WALK); // ON
+ else if (strncmp(args, "off", 4) == 0)
+ player->SetMovement(MOVE_LAND_WALK); // OFF
+ else
+ {
+ SendSysMessage(LANG_USE_BOL);
+ return false;
+ }
+
+ PSendSysMessage(LANG_YOU_SET_WATERWALK, args, GetNameLink(player).c_str());
+ if(needReportToTarget(player))
+ ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetNameLink().c_str());
return true;
}
@@ -3753,6 +4061,72 @@ bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
return true;
}
+bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
+{
+ Creature *creatureTarget = getSelectedCreature ();
+ if (!creatureTarget || creatureTarget->isPet ())
+ {
+ PSendSysMessage (LANG_SELECT_CREATURE);
+ SetSentErrorMessage (true);
+ return false;
+ }
+
+ Player *player = m_session->GetPlayer ();
+
+ if(player->GetPetGUID ())
+ {
+ SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
+ SetSentErrorMessage (true);
+ return false;
+ }
+
+ CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
+
+ if (!cInfo->isTameable ())
+ {
+ PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
+ SetSentErrorMessage (true);
+ return false;
+ }
+
+ // Everything looks OK, create new pet
+ Pet* pet = player->CreateTamedPetFrom (creatureTarget);
+ if (!pet)
+ {
+ PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
+ SetSentErrorMessage (true);
+ return false;
+ }
+
+ // place pet before player
+ float x,y,z;
+ player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
+ pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
+
+ // set pet to defensive mode by default (some classes can't control controlled pets in fact).
+ pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
+
+ // calculate proper level
+ uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel();
+
+ // prepare visual effect for levelup
+ pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
+
+ // add to world
+ pet->GetMap()->Add((Creature*)pet);
+
+ // visual effect for levelup
+ pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
+
+ // caster have pet now
+ player->SetPet(pet);
+
+ pet->SavePetToDB(PET_SAVE_AS_CURRENT);
+ player->PetSpellInitialize();
+
+ return true;
+}
+
bool ChatHandler::HandleCreatePetCommand(const char* args)
{
Player *player = m_session->GetPlayer();
@@ -3912,7 +4286,7 @@ bool ChatHandler::HandlePetTpCommand(const char *args)
uint32 tp = atol(args);
- pet->SetTP(tp);
+ //pet->SetTP(tp);
PSendSysMessage("Pet's tp changed to %u", tp);
return true;
@@ -4053,3 +4427,71 @@ bool ChatHandler::HandleNpcAddFormationCommand(const char* args)
return true;
}
+
+//change phasemask of creature or pet
+bool ChatHandler::HandleNpcSetPhaseCommand(const char* args)
+{
+ if (!*args)
+ return false;
+
+ uint32 phasemask = (uint32) atoi((char*)args);
+ if ( phasemask == 0 )
+ {
+ SendSysMessage(LANG_BAD_VALUE);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ Creature* pCreature = getSelectedCreature();
+ if(!pCreature)
+ {
+ SendSysMessage(LANG_SELECT_CREATURE);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ pCreature->SetPhaseMask(phasemask,true);
+
+ if(!pCreature->isPet())
+ pCreature->SaveToDB();
+
+ return true;
+}
+
+//set pahsemask for selected object
+bool ChatHandler::HandleGOPhaseCommand(const char* args)
+{
+ // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
+ char* cId = extractKeyFromLink((char*)args,"Hgameobject");
+ if(!cId)
+ return false;
+
+ uint32 lowguid = atoi(cId);
+ if(!lowguid)
+ return false;
+
+ GameObject* obj = NULL;
+ // by DB guid
+ if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
+ obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
+
+ if(!obj)
+ {
+ PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ char* phaseStr = strtok (NULL, " ");
+ uint32 phasemask = phaseStr? atoi(phaseStr) : 0;
+ if ( phasemask == 0 )
+ {
+ SendSysMessage(LANG_BAD_VALUE);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ obj->SetPhaseMask(phasemask,true);
+ obj->SaveToDB();
+ return true;
+}
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index 7e7228f5885..3516ad8df62 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -427,17 +427,8 @@ bool ChatHandler::HandleAHBotOptionsCommand(const char* args)
}
//reload commands
-bool ChatHandler::HandleReloadCommand(const char* arg)
-{
- // this is error catcher for wrong table name in .reload commands
- PSendSysMessage("Db table with name starting from '%s' not found and can't be reloaded.",arg);
- SetSentErrorMessage(true);
- return false;
-}
-
bool ChatHandler::HandleReloadAllCommand(const char*)
{
- HandleReloadAreaTriggerTeleportCommand("");
HandleReloadSkillFishingBaseLevelCommand("");
HandleReloadAllAreaCommand("");
@@ -522,6 +513,7 @@ bool ChatHandler::HandleReloadAllSpellCommand(const char*)
HandleReloadSpellElixirCommand("a");
HandleReloadSpellLearnSpellCommand("a");
HandleReloadSpellProcEventCommand("a");
+ HandleReloadSpellBonusesCommand("a");
HandleReloadSpellScriptTargetCommand("a");
HandleReloadSpellTargetPositionCommand("a");
HandleReloadSpellThreatsCommand("a");
@@ -624,6 +616,11 @@ bool ChatHandler::HandleReloadQuestTemplateCommand(const char*)
sLog.outString( "Re-Loading Quest Templates..." );
objmgr.LoadQuests();
SendGlobalGMSysMessage("DB table `quest_template` (quest definitions) reloaded.");
+
+ /// dependent also from `gameobject` but this table not reloaded anyway
+ sLog.outString( "Re-Loading GameObjects for quests..." );
+ objmgr.LoadGameObjectForQuests();
+ SendGlobalGMSysMessage("Data GameObjects for quests reloaded.");
return true;
}
@@ -672,6 +669,15 @@ bool ChatHandler::HandleReloadLootTemplatesItemCommand(const char*)
return true;
}
+bool ChatHandler::HandleReloadLootTemplatesMillingCommand(const char*)
+{
+ sLog.outString( "Re-Loading Loot Tables... (`milling_loot_template`)" );
+ LoadLootTemplates_Milling();
+ LootTemplates_Milling.CheckLootRefs();
+ SendGlobalSysMessage("DB table `milling_loot_template` reloaded.");
+ return true;
+}
+
bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(const char*)
{
sLog.outString( "Re-Loading Loot Tables... (`pickpocketing_loot_template`)" );
@@ -716,6 +722,15 @@ bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(const char*)
return true;
}
+bool ChatHandler::HandleReloadLootTemplatesSpellCommand(const char*)
+{
+ sLog.outString( "Re-Loading Loot Tables... (`spell_loot_template`)" );
+ LoadLootTemplates_Spell();
+ LootTemplates_Spell.CheckLootRefs();
+ SendGlobalSysMessage("DB table `spell_loot_template` reloaded.");
+ return true;
+}
+
bool ChatHandler::HandleReloadTrinityStringCommand(const char*)
{
sLog.outString( "Re-Loading trinity_string Table!" );
@@ -828,6 +843,14 @@ bool ChatHandler::HandleReloadSpellProcEventCommand(const char*)
return true;
}
+bool ChatHandler::HandleReloadSpellBonusesCommand(const char*)
+{
+ sLog.outString( "Re-Loading Spell Bonus Data..." );
+ spellmgr.LoadSpellBonusess();
+ SendGlobalSysMessage("DB table `spell_bonus_data` (spell damage/healing coefficients) reloaded.");
+ return true;
+}
+
bool ChatHandler::HandleReloadSpellScriptTargetCommand(const char*)
{
sLog.outString( "Re-Loading SpellsScriptTarget..." );
@@ -1213,19 +1236,10 @@ bool ChatHandler::HandleAccountSetPasswordCommand(const char* args)
return false;
}
- uint32 targetSecurity = accmgr.GetSecurity(targetAccountId);
-
- /// m_session==NULL only for console
- uint32 plSecurity = m_session ? m_session->GetSecurity() : SEC_CONSOLE;
-
/// can set password only for target with less security
/// This is also reject self apply in fact
- if (targetSecurity >= plSecurity)
- {
- SendSysMessage (LANG_YOURS_SECURITY_IS_LOW);
- SetSentErrorMessage (true);
+ if(HasLowerSecurityAccount (NULL,targetAccountId,true))
return false;
- }
if (strcmp(szPassword1,szPassword2))
{
@@ -1303,7 +1317,6 @@ bool ChatHandler::HandleSetSkillCommand(const char* args)
char *max_p = strtok (NULL, " ");
int32 skill = atoi(skill_p);
-
if (skill <= 0)
{
PSendSysMessage(LANG_INVALID_SKILL_ID, skill);
@@ -1329,9 +1342,11 @@ bool ChatHandler::HandleSetSkillCommand(const char* args)
return false;
}
+ std::string tNameLink = GetNameLink(target);
+
if(!target->GetSkillValue(skill))
{
- PSendSysMessage(LANG_SET_SKILL_ERROR, target->GetName(), skill, sl->name[0]);
+ PSendSysMessage(LANG_SET_SKILL_ERROR, tNameLink.c_str(), skill, sl->name[0]);
SetSentErrorMessage(true);
return false;
}
@@ -1342,7 +1357,7 @@ bool ChatHandler::HandleSetSkillCommand(const char* args)
return false;
target->SetSkill(skill, level, max);
- PSendSysMessage(LANG_SET_SKILL, skill, sl->name[0], target->GetName(), level, max);
+ PSendSysMessage(LANG_SET_SKILL, skill, sl->name[0], tNameLink.c_str(), level, max);
return true;
}
@@ -1353,27 +1368,12 @@ bool ChatHandler::HandleUnLearnCommand(const char* args)
return false;
// number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r
- uint32 min_id = extractSpellIdFromLink((char*)args);
- if(!min_id)
+ uint32 spell_id = extractSpellIdFromLink((char*)args);
+ if(!spell_id)
return false;
- // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r
- char* tail = strtok(NULL,"");
-
- uint32 max_id = extractSpellIdFromLink(tail);
-
- if (!max_id)
- {
- // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r
- max_id = min_id+1;
- }
- else
- {
- if (max_id < min_id)
- std::swap(min_id,max_id);
-
- max_id=max_id+1;
- }
+ char const* allStr = strtok(NULL," ");
+ bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false;
Player* target = getSelectedPlayer();
if(!target)
@@ -1383,13 +1383,13 @@ bool ChatHandler::HandleUnLearnCommand(const char* args)
return false;
}
- for(uint32 spell=min_id;spell<max_id;spell++)
- {
- if (target->HasSpell(spell))
- target->removeSpell(spell);
- else
- SendSysMessage(LANG_FORGET_SPELL);
- }
+ if(allRanks)
+ spell_id = spellmgr.GetFirstSpellInChain (spell_id);
+
+ if (target->HasSpell(spell_id))
+ target->removeSpell(spell_id,false,!allRanks);
+ else
+ SendSysMessage(LANG_FORGET_SPELL);
return true;
}
@@ -1404,10 +1404,12 @@ bool ChatHandler::HandleCooldownCommand(const char* args)
return false;
}
+ std::string tNameLink = GetNameLink(target);
+
if (!*args)
{
target->RemoveAllSpellCooldown();
- PSendSysMessage(LANG_REMOVEALL_COOLDOWN, target->GetName());
+ PSendSysMessage(LANG_REMOVEALL_COOLDOWN, tNameLink.c_str());
}
else
{
@@ -1418,7 +1420,7 @@ bool ChatHandler::HandleCooldownCommand(const char* args)
if(!sSpellStore.LookupEntry(spell_id))
{
- PSendSysMessage(LANG_UNKNOWN_SPELL, target==m_session->GetPlayer() ? GetTrinityString(LANG_YOU) : target->GetName());
+ PSendSysMessage(LANG_UNKNOWN_SPELL, target==m_session->GetPlayer() ? GetMangosString(LANG_YOU) : tNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
@@ -1428,8 +1430,8 @@ bool ChatHandler::HandleCooldownCommand(const char* args)
data << uint64(target->GetGUID());
target->GetSession()->SendPacket(&data);
target->RemoveSpellCooldown(spell_id);
- PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target==m_session->GetPlayer() ? GetTrinityString(LANG_YOU) : target->GetName());
- }
+ PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target==m_session->GetPlayer() ? GetMangosString(LANG_YOU) : tNameLink.c_str());
+ }
return true;
}
@@ -2054,7 +2056,7 @@ bool ChatHandler::HandleLearnAllCommand(const char* /*args*/)
continue;
}
- m_session->GetPlayer()->learnSpell(spell);
+ m_session->GetPlayer()->learnSpell(spell,false);
}
SendSysMessage(LANG_COMMAND_LEARN_MANY_SPELLS);
@@ -2094,7 +2096,7 @@ bool ChatHandler::HandleLearnAllGMCommand(const char* /*args*/)
continue;
}
- m_session->GetPlayer()->learnSpell(spell);
+ m_session->GetPlayer()->learnSpell(spell,false);
}
SendSysMessage(LANG_LEARNING_GM_SKILLS);
@@ -2121,6 +2123,10 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/)
if(!spellInfo)
continue;
+ // skip server-side/triggered spells
+ if(spellInfo->spellLevel==0)
+ continue;
+
// skip wrong class/race skills
if(!m_session->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id))
continue;
@@ -2129,8 +2135,6 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/)
if( spellInfo->SpellFamilyName != family)
continue;
- //TODO: skip triggered spells
-
// skip spells with first rank learned as talent (and all talents then also)
uint32 first_rank = spellmgr.GetFirstSpellInChain(spellInfo->Id);
if(GetTalentSpellCost(first_rank) > 0 )
@@ -2140,27 +2144,13 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/)
if(!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
continue;
- m_session->GetPlayer()->learnSpell(i);
+ m_session->GetPlayer()->learnSpell(i,false);
}
SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS);
return true;
}
-static void learnAllHighRanks(Player* player, uint32 spellid)
-{
- SpellChainNode const* node;
- do
- {
- node = spellmgr.GetSpellChainNode(spellid);
- player->learnSpell(spellid);
- if (!node)
- break;
- spellid=node->next;
- }
- while (node->next);
-}
-
bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/)
{
Player* player = m_session->GetPlayer();
@@ -2198,11 +2188,8 @@ bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/)
if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
continue;
- // learn highest rank of talent
- player->learnSpell(spellid);
-
- // and learn all non-talent spell ranks (recursive by tree)
- learnAllHighRanks(player,spellid);
+ // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree)
+ player->learnSpellHighRank(spellid);
}
SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS);
@@ -2213,7 +2200,7 @@ bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/)
{
// skipping UNIVERSAL language (0)
for(int i = 1; i < LANGUAGES_COUNT; ++i)
- m_session->GetPlayer()->learnSpell(lang_description[i].spell_id);
+ m_session->GetPlayer()->learnSpell(lang_description[i].spell_id,false);
SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG);
return true;
@@ -2221,13 +2208,11 @@ bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/)
bool ChatHandler::HandleLearnAllDefaultCommand(const char* args)
{
- char* pName = strtok((char*)args, "");
Player *player = NULL;
- if (pName)
+ if (*args)
{
- std::string name = pName;
-
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -2249,7 +2234,7 @@ bool ChatHandler::HandleLearnAllDefaultCommand(const char* args)
player->learnDefaultSpells();
player->learnQuestRewardedSpells();
- PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST,player->GetName());
+ PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST,GetNameLink(player).c_str());
return true;
}
@@ -2269,25 +2254,31 @@ bool ChatHandler::HandleLearnCommand(const char* args)
if(!spell || !sSpellStore.LookupEntry(spell))
return false;
- if (targetPlayer->HasSpell(spell))
+ char const* allStr = strtok(NULL," ");
+ bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false;
+
+ SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
+ if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer()))
{
- if(targetPlayer == m_session->GetPlayer())
- SendSysMessage(LANG_YOU_KNOWN_SPELL);
- else
- PSendSysMessage(LANG_TARGET_KNOWN_SPELL,targetPlayer->GetName());
+ PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell);
SetSentErrorMessage(true);
return false;
}
- SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
- if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer()))
+ if (!allRanks && targetPlayer->HasSpell(spell))
{
- PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell);
+ if(targetPlayer == m_session->GetPlayer())
+ SendSysMessage(LANG_YOU_KNOWN_SPELL);
+ else
+ PSendSysMessage(LANG_TARGET_KNOWN_SPELL,GetNameLink(targetPlayer).c_str());
SetSentErrorMessage(true);
return false;
}
- targetPlayer->learnSpell(spell);
+ if(allRanks)
+ targetPlayer->learnSpellHighRank(spell);
+ else
+ targetPlayer->learnSpell(spell,false);
return true;
}
@@ -2357,7 +2348,7 @@ bool ChatHandler::HandleAddItemCommand(const char* args)
if (count < 0)
{
plTarget->DestroyItemCount(itemId, -count, true, false);
- PSendSysMessage(LANG_REMOVEITEM, itemId, -count, plTarget->GetName());
+ PSendSysMessage(LANG_REMOVEITEM, itemId, -count, GetNameLink(plTarget).c_str());
return true;
}
@@ -3097,15 +3088,25 @@ bool ChatHandler::HandleLookupSkillCommand(const char* args)
if(loc < MAX_LOCALE)
{
+ char valStr[50] = "";
char const* knownStr = "";
if(target && target->HasSkill(id))
+ {
knownStr = GetTrinityString(LANG_KNOWN);
+ uint32 curValue = target->GetPureSkillValue(id);
+ uint32 maxValue = target->GetPureMaxSkillValue(id);
+ uint32 permValue = target->GetSkillPermBonusValue(id);
+ uint32 tempValue = target->GetSkillTempBonusValue(id);
+
+ char const* valFormat = GetTrinityString(LANG_SKILL_VALUES);
+ snprintf(valStr,50,valFormat,curValue,maxValue,permValue,tempValue);
+ }
// send skill in "id - [namedlink locale]" format
if (m_session)
- PSendSysMessage(LANG_SKILL_LIST_CHAT,id,id,name.c_str(),localeNames[loc],knownStr);
+ PSendSysMessage(LANG_SKILL_LIST_CHAT,id,id,name.c_str(),localeNames[loc],knownStr,valStr);
else
- PSendSysMessage(LANG_SKILL_LIST_CONSOLE,id,name.c_str(),localeNames[loc],knownStr);
+ PSendSysMessage(LANG_SKILL_LIST_CONSOLE,id,name.c_str(),localeNames[loc],knownStr,valStr);
++counter;
}
@@ -3172,7 +3173,7 @@ bool ChatHandler::HandleLookupSpellCommand(const char* args)
bool talent = (talentCost > 0);
bool passive = IsPassiveSpell(id);
- bool active = target && (target->HasAura(id,0) || target->HasAura(id,1) || target->HasAura(id,2));
+ bool active = target && target->HasAura(id);
// unit32 used to prevent interpreting uint8 as char at output
// find rank of learned spell for learning spell, or talent rank
@@ -3519,11 +3520,11 @@ bool ChatHandler::HandleGuildInviteCommand(const char *args)
if (!targetGuild)
return false;
- std::string plName = par1;
- if (!normalizePlayerName (plName))
+ std::string plName = extractPlayerNameFromLink(par1);
+ if(plName.empty())
{
- SendSysMessage (LANG_PLAYER_NOT_FOUND);
- SetSentErrorMessage (true);
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
return false;
}
@@ -3531,7 +3532,7 @@ bool ChatHandler::HandleGuildInviteCommand(const char *args)
if (Player* targetPlayer = ObjectAccessor::Instance ().FindPlayerByName (plName.c_str ()))
plGuid = targetPlayer->GetGUID ();
else
- plGuid = objmgr.GetPlayerGUIDByName (plName.c_str ());
+ plGuid = objmgr.GetPlayerGUIDByName (plName);
if (!plGuid)
false;
@@ -3552,11 +3553,11 @@ bool ChatHandler::HandleGuildUninviteCommand(const char *args)
if(!par1)
return false;
- std::string plName = par1;
- if (!normalizePlayerName (plName))
+ std::string plName = extractPlayerNameFromLink(par1);
+ if(plName.empty())
{
- SendSysMessage (LANG_PLAYER_NOT_FOUND);
- SetSentErrorMessage (true);
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
return false;
}
@@ -3569,7 +3570,7 @@ bool ChatHandler::HandleGuildUninviteCommand(const char *args)
}
else
{
- plGuid = objmgr.GetPlayerGUIDByName (plName.c_str ());
+ plGuid = objmgr.GetPlayerGUIDByName (plName);
glId = Player::GetGuildIdFromDB (plGuid);
}
@@ -3594,14 +3595,16 @@ bool ChatHandler::HandleGuildRankCommand(const char *args)
char* par2 = strtok (NULL, " ");
if (!par1 || !par2)
return false;
- std::string plName = par1;
- if (!normalizePlayerName (plName))
+
+ std::string plName = extractPlayerNameFromLink(par1);
+ if(plName.empty())
{
- SendSysMessage (LANG_PLAYER_NOT_FOUND);
- SetSentErrorMessage (true);
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
return false;
}
+
uint64 plGuid = 0;
uint32 glId = 0;
if (Player* targetPlayer = ObjectAccessor::Instance ().FindPlayerByName (plName.c_str ()))
@@ -3611,7 +3614,7 @@ bool ChatHandler::HandleGuildRankCommand(const char *args)
}
else
{
- plGuid = objmgr.GetPlayerGUIDByName (plName.c_str ());
+ plGuid = objmgr.GetPlayerGUIDByName (plName);
glId = Player::GetGuildIdFromDB (plGuid);
}
@@ -3800,7 +3803,7 @@ bool ChatHandler::HandleDamageCommand(const char * args)
SpellSchoolMask schoolmask = SpellSchoolMask(1 << school);
if ( schoolmask & SPELL_SCHOOL_MASK_NORMAL )
- damage = m_session->GetPlayer()->CalcArmorReducedDamage(target, damage);
+ damage = m_session->GetPlayer()->CalcArmorReducedDamage(target, damage, NULL, BASE_ATTACK);
char* spellStr = strtok((char*)NULL, " ");
@@ -3850,7 +3853,7 @@ bool ChatHandler::HandleModifyArenaCommand(const char * args)
target->ModifyArenaPoints(amount);
- PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, target->GetName(), target->GetArenaPoints());
+ PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, GetNameLink(target).c_str(), target->GetArenaPoints());
return true;
}
@@ -3861,8 +3864,8 @@ bool ChatHandler::HandleReviveCommand(const char* args)
if (*args)
{
- std::string name = args;
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -3889,10 +3892,6 @@ bool ChatHandler::HandleReviveCommand(const char* args)
bool ChatHandler::HandleAuraCommand(const char* args)
{
- char* px = strtok((char*)args, " ");
- if (!px)
- return false;
-
Unit *target = getSelectedUnit();
if(!target)
{
@@ -3901,7 +3900,9 @@ bool ChatHandler::HandleAuraCommand(const char* args)
return false;
}
- uint32 spellID = (uint32)atoi(px);
+ // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form
+ uint32 spellID = extractSpellIdFromLink((char*)args);
+
SpellEntry const *spellInfo = sSpellStore.LookupEntry( spellID );
if(spellInfo)
{
@@ -3925,10 +3926,6 @@ bool ChatHandler::HandleAuraCommand(const char* args)
bool ChatHandler::HandleUnAuraCommand(const char* args)
{
- char* px = strtok((char*)args, " ");
- if (!px)
- return false;
-
Unit *target = getSelectedUnit();
if(!target)
{
@@ -3944,7 +3941,11 @@ bool ChatHandler::HandleUnAuraCommand(const char* args)
return true;
}
- uint32 spellID = (uint32)atoi(px);
+ // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form
+ uint32 spellID = extractSpellIdFromLink((char*)args);
+ if(!spellID)
+ return false;
+
target->RemoveAurasDueToSpell(spellID);
return true;
@@ -4148,15 +4149,15 @@ bool ChatHandler::HandleExploreCheatCommand(const char* args)
if (flag != 0)
{
- PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, chr->GetName());
+ PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,GetName());
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,GetNameLink().c_str());
}
else
{
- PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, chr->GetName());
+ PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
- ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,GetName());
+ ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,GetNameLink().c_str());
}
for (uint8 i=0; i<128; i++)
@@ -4193,36 +4194,6 @@ bool ChatHandler::HandleHoverCommand(const char* args)
return true;
}
-bool ChatHandler::HandleWaterwalkCommand(const char* args)
-{
- if(!args)
- return false;
-
- Player *player = getSelectedPlayer();
- if(!player)
- {
- PSendSysMessage(LANG_NO_CHAR_SELECTED);
- SetSentErrorMessage(true);
- return false;
- }
-
- if (strncmp(args, "on", 3) == 0)
- player->SetMovement(MOVE_WATER_WALK); // ON
- else if (strncmp(args, "off", 4) == 0)
- player->SetMovement(MOVE_LAND_WALK); // OFF
- else
- {
- SendSysMessage(LANG_USE_BOL);
- return false;
- }
-
- PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName());
- if(needReportToTarget(player))
- ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName());
- return true;
-
-}
-
bool ChatHandler::HandleLevelUpCommand(const char* args)
{
char* px = strtok((char*)args, " ");
@@ -4254,8 +4225,8 @@ bool ChatHandler::HandleLevelUpCommand(const char* args)
if(pname) // player by name
{
- name = pname;
- if(!normalizePlayerName(name))
+ name = extractPlayerNameFromLink(pname);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -4285,7 +4256,7 @@ bool ChatHandler::HandleLevelUpCommand(const char* args)
return false;
}
- name = chr->GetName();
+ name = GetNameLink(chr);
}
assert(chr || chr_guid);
@@ -4323,7 +4294,10 @@ bool ChatHandler::HandleLevelUpCommand(const char* args)
}
if(m_session->GetPlayer() != chr) // including chr==NULL
- PSendSysMessage(LANG_YOU_CHANGE_LVL,name.c_str(),newlevel);
+ {
+ std::string nameLink = playerLink(name);
+ PSendSysMessage(LANG_YOU_CHANGE_LVL,nameLink.c_str(),newlevel);
+ }
return true;
}
@@ -4332,8 +4306,6 @@ bool ChatHandler::HandleShowAreaCommand(const char* args)
if (!*args)
return false;
- int area = atoi((char*)args);
-
Player *chr = getSelectedPlayer();
if (chr == NULL)
{
@@ -4342,10 +4314,11 @@ bool ChatHandler::HandleShowAreaCommand(const char* args)
return false;
}
+ int area = GetAreaFlagByAreaID(atoi((char*)args));
int offset = area / 32;
uint32 val = (uint32)(1 << (area % 32));
- if(offset >= 128)
+ if(area<0 || offset >= 128)
{
SendSysMessage(LANG_BAD_VALUE);
SetSentErrorMessage(true);
@@ -4364,8 +4337,6 @@ bool ChatHandler::HandleHideAreaCommand(const char* args)
if (!*args)
return false;
- int area = atoi((char*)args);
-
Player *chr = getSelectedPlayer();
if (chr == NULL)
{
@@ -4374,10 +4345,11 @@ bool ChatHandler::HandleHideAreaCommand(const char* args)
return false;
}
+ int area = GetAreaFlagByAreaID(atoi((char*)args));
int offset = area / 32;
uint32 val = (uint32)(1 << (area % 32));
- if(offset >= 128)
+ if(area<0 || offset >= 128)
{
SendSysMessage(LANG_BAD_VALUE);
SetSentErrorMessage(true);
@@ -4723,11 +4695,28 @@ bool ChatHandler::HandleListAurasCommand (const char * /*args*/)
for (Unit::AuraMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr)
{
bool talent = GetTalentSpellCost(itr->second->GetId()) > 0;
- PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffIndex(),
- itr->second->GetModifier()->m_auraname, itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(),
- itr->second->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()],
- (itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
- IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID()));
+
+ char const* name = itr->second->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()];
+
+ if (m_session)
+ {
+ std::ostringstream ss_name;
+ ss_name << "|cffffffff|Hspell:" << itr->second->GetId() << "|h[" << name << "]|h|r";
+
+ PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffIndex(),
+ itr->second->GetModifier()->m_auraname, itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(),
+ ss_name.str().c_str(),
+ (itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
+ IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID()));
+ }
+ else
+ {
+ PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffIndex(),
+ itr->second->GetModifier()->m_auraname, itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(),
+ name,
+ (itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
+ IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID()));
+ }
}
for (int i = 0; i < TOTAL_AURAS; i++)
{
@@ -4737,9 +4726,24 @@ bool ChatHandler::HandleListAurasCommand (const char * /*args*/)
for (Unit::AuraList::const_iterator itr = uAuraList.begin(); itr != uAuraList.end(); ++itr)
{
bool talent = GetTalentSpellCost((*itr)->GetId()) > 0;
- PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(),
- (*itr)->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()],((*itr)->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
- IS_PLAYER_GUID((*itr)->GetCasterGUID()) ? "player" : "creature",GUID_LOPART((*itr)->GetCasterGUID()));
+
+ char const* name = (*itr)->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()];
+
+ if (m_session)
+ {
+ std::ostringstream ss_name;
+ ss_name << "|cffffffff|Hspell:" << (*itr)->GetId() << "|h[" << name << "]|h|r";
+
+ PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(),
+ ss_name.str().c_str(),((*itr)->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
+ IS_PLAYER_GUID((*itr)->GetCasterGUID()) ? "player" : "creature",GUID_LOPART((*itr)->GetCasterGUID()));
+ }
+ else
+ {
+ PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(),
+ name,((*itr)->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
+ IS_PLAYER_GUID((*itr)->GetCasterGUID()) ? "player" : "creature",GUID_LOPART((*itr)->GetCasterGUID()));
+ }
}
}
return true;
@@ -4751,15 +4755,15 @@ bool ChatHandler::HandleResetHonorCommand (const char * args)
Player *player = NULL;
if (pName)
{
- std::string name = pName;
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink(pName);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
return false;
}
- uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str());
+ uint64 guid = objmgr.GetPlayerGUIDByName(name);
player = objmgr.GetPlayer(guid);
}
else
@@ -4794,19 +4798,6 @@ static bool HandleResetStatsOrLevelHelper(Player* player)
uint8 powertype = cEntry->powerType;
- uint32 unitfield;
- if(powertype == POWER_RAGE)
- unitfield = 0x1100EE00;
- else if(powertype == POWER_ENERGY)
- unitfield = 0x00000000;
- else if(powertype == POWER_MANA)
- unitfield = 0x0000EE00;
- else
- {
- sLog.outError("Invalid default powertype %u for player (class %u)",powertype,player->getClass());
- return false;
- }
-
// reset m_form if no aura
if(!player->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT))
player->m_form = FORM_NONE;
@@ -4836,9 +4827,7 @@ static bool HandleResetStatsOrLevelHelper(Player* player)
}
}
- // set UNIT_FIELD_BYTES_1 to init state but preserve m_form value
- player->SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield);
- player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_UNK5 );
+ player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP );
player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form);
player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
@@ -4856,15 +4845,15 @@ bool ChatHandler::HandleResetLevelCommand(const char * args)
Player *player = NULL;
if (pName)
{
- std::string name = pName;
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink(pName);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
return false;
}
- uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str());
+ uint64 guid = objmgr.GetPlayerGUIDByName(name);
player = objmgr.GetPlayer(guid);
}
else
@@ -4880,17 +4869,26 @@ bool ChatHandler::HandleResetLevelCommand(const char * args)
if(!HandleResetStatsOrLevelHelper(player))
return false;
- player->SetLevel(1);
+ // set starting level
+ uint32 start_level = player->getClass() != CLASS_DEATH_KNIGHT
+ ? sWorld.getConfig(CONFIG_START_PLAYER_LEVEL)
+ : sWorld.getConfig(CONFIG_START_HEROIC_PLAYER_LEVEL);
+
+ player->SetLevel(start_level);
+ player->InitRunes();
player->InitStatsForLevel(true);
player->InitTaxiNodesForLevel();
+ player->InitGlyphsForLevel();
player->InitTalentForLevel();
player->SetUInt32Value(PLAYER_XP,0);
// reset level to summoned pet
Pet* pet = player->GetPet();
if(pet && pet->getPetType()==SUMMON_PET)
+ {
pet->InitStatsForLevel(1);
-
+ pet->InitTalentForLevel();
+ }
return true;
}
@@ -4900,15 +4898,15 @@ bool ChatHandler::HandleResetStatsCommand(const char * args)
Player *player = NULL;
if (pName)
{
- std::string name = pName;
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink(pName);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
return false;
}
- uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str());
+ uint64 guid = objmgr.GetPlayerGUIDByName(name);
player = objmgr.GetPlayer(guid);
}
else
@@ -4924,8 +4922,10 @@ bool ChatHandler::HandleResetStatsCommand(const char * args)
if(!HandleResetStatsOrLevelHelper(player))
return false;
+ player->InitRunes();
player->InitStatsForLevel(true);
player->InitTaxiNodesForLevel();
+ player->InitGlyphsForLevel();
player->InitTalentForLevel();
return true;
@@ -4938,9 +4938,8 @@ bool ChatHandler::HandleResetSpellsCommand(const char * args)
uint64 playerGUID = 0;
if (pName)
{
- std::string name = pName;
-
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink(pName);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -4949,7 +4948,7 @@ bool ChatHandler::HandleResetSpellsCommand(const char * args)
player = objmgr.GetPlayer(name.c_str());
if(!player)
- playerGUID = objmgr.GetPlayerGUIDByName(name.c_str());
+ playerGUID = objmgr.GetPlayerGUIDByName(name);
}
else
player = getSelectedPlayer();
@@ -4966,9 +4965,8 @@ bool ChatHandler::HandleResetSpellsCommand(const char * args)
player->resetSpells();
ChatHandler(player).SendSysMessage(LANG_RESET_SPELLS);
-
if(m_session->GetPlayer()!=player)
- PSendSysMessage(LANG_RESET_SPELLS_ONLINE,player->GetName());
+ PSendSysMessage(LANG_RESET_SPELLS_ONLINE,GetNameLink(player).c_str());
}
else
{
@@ -4986,8 +4984,8 @@ bool ChatHandler::HandleResetTalentsCommand(const char * args)
uint64 playerGUID = 0;
if (pName)
{
- std::string name = pName;
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink(pName);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -4996,34 +4994,47 @@ bool ChatHandler::HandleResetTalentsCommand(const char * args)
player = objmgr.GetPlayer(name.c_str());
if(!player)
- playerGUID = objmgr.GetPlayerGUIDByName(name.c_str());
+ playerGUID = objmgr.GetPlayerGUIDByName(name);
}
else
player = getSelectedPlayer();
- if(!player && !playerGUID)
- {
- SendSysMessage(LANG_NO_CHAR_SELECTED);
- SetSentErrorMessage(true);
- return false;
- }
-
if(player)
{
player->resetTalents(true);
ChatHandler(player).SendSysMessage(LANG_RESET_TALENTS);
-
if(m_session->GetPlayer()!=player)
- PSendSysMessage(LANG_RESET_TALENTS_ONLINE,player->GetName());
+ PSendSysMessage(LANG_RESET_TALENTS_ONLINE,GetNameLink(player).c_str());
+
+ return true;
}
- else
+ else if (playerGUID)
{
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_TALENTS), GUID_LOPART(playerGUID) );
- PSendSysMessage(LANG_RESET_TALENTS_OFFLINE,pName);
+ std::string nameLink = playerLink(pName);
+ PSendSysMessage(LANG_RESET_TALENTS_OFFLINE,nameLink.c_str());
+ return true;
+ }
+ // Try reset talenents as Hunter Pet
+ Creature* creature = getSelectedCreature();
+ if (creature && creature->isPet() && ((Pet *)creature)->getPetType() == HUNTER_PET)
+ {
+ ((Pet *)creature)->resetTalents(true);
+ Unit *owner = creature->GetOwner();
+ if (owner && owner->GetTypeId() == TYPEID_PLAYER)
+ {
+ player = (Player *)owner;
+ ChatHandler(player).SendSysMessage(LANG_RESET_TALENTS);
+ if(m_session->GetPlayer()!=player)
+ PSendSysMessage(LANG_RESET_TALENTS_ONLINE,GetNameLink(player).c_str());
+ }
+ return true;
}
- return true;
+ SendSysMessage(LANG_NO_CHAR_SELECTED);
+ SetSentErrorMessage(true);
+ return false;
}
bool ChatHandler::HandleResetAllCommand(const char * args)
@@ -5580,12 +5591,8 @@ bool ChatHandler::HandleBanInfoCharacterCommand(const char* args)
if(!args)
return false;
- char* cname = strtok ((char*)args, "");
- if(!cname)
- return false;
-
- std::string name = cname;
- if(!normalizePlayerName(name))
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
@@ -5897,8 +5904,8 @@ bool ChatHandler::HandleRespawnCommand(const char* /*args*/)
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
- Trinity::RespawnDo u_do;
- Trinity::WorldObjectWorker<Trinity::RespawnDo> worker(u_do);
+ MaNGOS::RespawnDo u_do;
+ MaNGOS::WorldObjectWorker<MaNGOS::RespawnDo> worker(pl,u_do);
TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::RespawnDo>, GridTypeMapContainer > obj_worker(worker);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -5912,9 +5919,9 @@ bool ChatHandler::HandleFlyModeCommand(const char* args)
if(!args)
return false;
- Unit *unit = getSelectedUnit();
- if (!unit || (unit->GetTypeId() != TYPEID_PLAYER))
- unit = m_session->GetPlayer();
+ Player *target = getSelectedPlayer();
+ if (!target)
+ target = m_session->GetPlayer();
WorldPacket data(12);
if (strncmp(args, "on", 3) == 0)
@@ -5926,10 +5933,10 @@ bool ChatHandler::HandleFlyModeCommand(const char* args)
SendSysMessage(LANG_USE_BOL);
return false;
}
- data.append(unit->GetPackGUID());
+ data.append(target->GetPackGUID());
data << uint32(0); // unknown
- unit->SendMessageToSet(&data, true);
- PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, unit->GetName(), args);
+ target->SendMessageToSet(&data, true);
+ PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, GetNameLink(target).c_str(), args);
return true;
}
@@ -6085,12 +6092,11 @@ bool ChatHandler::HandleWritePDumpCommand(const char *args)
guid = atoi(p2);
else
{
- std::string name = p2;
-
- if (!normalizePlayerName (name))
+ std::string name = extractPlayerNameFromLink(p2);
+ if(name.empty())
{
- SendSysMessage (LANG_PLAYER_NOT_FOUND);
- SetSentErrorMessage (true);
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
return false;
}
@@ -6682,8 +6688,15 @@ bool ChatHandler::HandleAccountSetAddonCommand(const char* args)
SetSentErrorMessage(true);
return false;
}
+
}
+ // Let set addon state only for lesser (strong) security level
+ // or to self account
+ if (m_session && m_session->GetAccountId () != account_id &&
+ HasLowerSecurityAccount (NULL,account_id,true))
+ return false;
+
int lev=atoi(szExp); //get int anyway (0 if error)
if(lev < 0)
return false;
@@ -6702,9 +6715,13 @@ bool ChatHandler::HandleSendItemsCommand(const char* args)
// format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12]
- char* pName = strtok((char*)args, " ");
- if(!pName)
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
return false;
+ }
char* tail1 = strtok(NULL, "");
if(!tail1)
@@ -6742,8 +6759,7 @@ bool ChatHandler::HandleSendItemsCommand(const char* args)
if (!msgText)
return false;
- // pName, msgSubject, msgText isn't NUL after prev. check
- std::string name = pName;
+ // msgSubject, msgText isn't NUL after prev. check
std::string subject = msgSubject;
std::string text = msgText;
@@ -6778,17 +6794,17 @@ bool ChatHandler::HandleSendItemsCommand(const char* args)
}
uint32 item_count = itemCountStr ? atoi(itemCountStr) : 1;
- if(item_count < 1 || item_proto->MaxCount && item_count > item_proto->MaxCount)
+ if(item_count < 1 || item_proto->MaxCount > 0 && item_count > uint32(item_proto->MaxCount))
{
PSendSysMessage(LANG_COMMAND_INVALID_ITEM_COUNT, item_count,item_id);
SetSentErrorMessage(true);
return false;
}
- while(item_count > item_proto->Stackable)
+ while(item_count > item_proto->GetMaxStackSize())
{
- items.push_back(ItemPair(item_id,item_proto->Stackable));
- item_count -= item_proto->Stackable;
+ items.push_back(ItemPair(item_id,item_proto->GetMaxStackSize()));
+ item_count -= item_proto->GetMaxStackSize();
}
items.push_back(ItemPair(item_id,item_count));
@@ -6801,13 +6817,6 @@ bool ChatHandler::HandleSendItemsCommand(const char* args)
}
}
- if(!normalizePlayerName(name))
- {
- SendSysMessage(LANG_PLAYER_NOT_FOUND);
- SetSentErrorMessage(true);
- return false;
- }
-
uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name);
if(!receiver_guid)
{
@@ -6839,7 +6848,8 @@ bool ChatHandler::HandleSendItemsCommand(const char* args)
WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, &mi, 0, 0, MAIL_CHECK_MASK_NONE);
- PSendSysMessage(LANG_MAIL_SENT, name.c_str());
+ std::string nameLink = playerLink(name);
+ PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str());
return true;
}
@@ -6851,9 +6861,13 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args)
/// format: name "subject text" "mail text" money
- char* pName = strtok((char*)args, " ");
- if (!pName)
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
return false;
+ }
char* tail1 = strtok(NULL, "");
if (!tail1)
@@ -6896,18 +6910,10 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args)
if (money <= 0)
return false;
- // pName, msgSubject, msgText isn't NUL after prev. check
- std::string name = pName;
+ // msgSubject, msgText isn't NUL after prev. check
std::string subject = msgSubject;
std::string text = msgText;
- if (!normalizePlayerName(name))
- {
- SendSysMessage(LANG_PLAYER_NOT_FOUND);
- SetSentErrorMessage(true);
- return false;
- }
-
uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name);
if (!receiver_guid)
{
@@ -6929,7 +6935,8 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args)
WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, NULL, money, 0, MAIL_CHECK_MASK_NONE);
- PSendSysMessage(LANG_MAIL_SENT, name.c_str());
+ std::string nameLink = playerLink(name);
+ PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str());
return true;
}
@@ -6937,15 +6944,16 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args)
bool ChatHandler::HandleSendMessageCommand(const char* args)
{
///- Get the command line arguments
- char* name_str = strtok((char*)args, " ");
- char* msg_str = strtok(NULL, "");
-
- if(!name_str || !msg_str)
+ std::string name = extractPlayerNameFromLink((char*)args);
+ if(name.empty())
+ {
+ SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ SetSentErrorMessage(true);
return false;
+ }
- std::string name = name_str;
-
- if(!normalizePlayerName(name))
+ char* msg_str = strtok(NULL, "");
+ if(!msg_str)
return false;
///- Find the player and check that he is not logging out.
@@ -6970,7 +6978,8 @@ bool ChatHandler::HandleSendMessageCommand(const char* args)
rPlayer->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r");
//Confirmation message
- PSendSysMessage(LANG_SENDMESSAGE,name.c_str(),msg_str);
+ std::string nameLink = playerLink(name);
+ PSendSysMessage(LANG_SENDMESSAGE,nameLink.c_str(),msg_str);
return true;
}
@@ -6994,30 +7003,27 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args)
return false;
}
+ PlayerInfo const* info = objmgr.GetPlayerInfo(player->getRace(), player->getClass());
+ if(!info)
+ return false;
+
char const* gender_str = (char*)args;
int gender_len = strlen(gender_str);
- uint32 displayId = player->GetNativeDisplayId();
- char const* gender_full = NULL;
- uint32 new_displayId = displayId;
Gender gender;
- if(!strncmp(gender_str,"male",gender_len)) // MALE
+ if(!strncmp(gender_str, "male", gender_len)) // MALE
{
if(player->getGender() == GENDER_MALE)
return true;
- gender_full = "male";
- new_displayId = player->getRace() == RACE_BLOODELF ? displayId+1 : displayId-1;
gender = GENDER_MALE;
}
- else if (!strncmp(gender_str,"female",gender_len)) // FEMALE
+ else if (!strncmp(gender_str, "female", gender_len)) // FEMALE
{
if(player->getGender() == GENDER_FEMALE)
return true;
- gender_full = "female";
- new_displayId = player->getRace() == RACE_BLOODELF ? displayId-1 : displayId+1;
gender = GENDER_FEMALE;
}
else
@@ -7029,14 +7035,19 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args)
// Set gender
player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender);
+ player->SetByteValue(PLAYER_BYTES_3, 0, gender);
// Change display ID
- player->SetDisplayId(new_displayId);
- player->SetNativeDisplayId(new_displayId);
+ player->SetDisplayId(gender ? info->displayId_f : info->displayId_m);
+ player->SetNativeDisplayId(gender ? info->displayId_f : info->displayId_m);
+
+ char const* gender_full = gender ? "female" : "male";
+
+ PSendSysMessage(LANG_YOU_CHANGE_GENDER, GetNameLink(player).c_str(), gender_full);
- PSendSysMessage(LANG_YOU_CHANGE_GENDER, player->GetName(),gender_full);
if (needReportToTarget(player))
- ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full,GetName());
+ ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full, GetNameLink().c_str());
+
return true;
}
diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp
index a4a8a7a1f01..8f8b5d2b6e9 100644
--- a/src/game/LootHandler.cpp
+++ b/src/game/LootHandler.cpp
@@ -154,6 +154,7 @@ void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data )
--loot->unlootedCount;
player->SendNewItem(newitem, uint32(item->count), false, false, true);
+ player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count);
}
else
player->SendEquipError( msg, NULL, NULL );
@@ -326,7 +327,7 @@ void WorldSession::DoLootRelease( uint64 lguid )
int32 ReqValue = 175;
LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId);
if(lockInfo)
- ReqValue = lockInfo->requiredminingskill;
+ ReqValue = lockInfo->Skill[0];
float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25);
double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses));
if(roll_chance_f(100*chance+skill))
@@ -383,14 +384,22 @@ void WorldSession::DoLootRelease( uint64 lguid )
Item *pItem = player->GetItemByGuid(lguid );
if(!pItem)
return;
- if( (pItem->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP) &&
- pItem->GetProto()->Class == ITEM_CLASS_TRADE_GOODS &&
- pItem->GetCount() >= 5)
+
+ ItemPrototype const* proto = pItem->GetProto();
+
+ // destroy only 5 items from stack in case prospecting and milling
+ if( (proto->BagFamily & (BAG_FAMILY_MASK_MINING_SUPP|BAG_FAMILY_MASK_HERBS)) &&
+ proto->Class == ITEM_CLASS_TRADE_GOODS)
{
pItem->m_lootGenerated = false;
pItem->loot.clear();
- uint32 count = 5;
+ uint32 count = pItem->GetCount();
+
+ // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks.
+ if(count > 5)
+ count = 5;
+
player->DestroyItemCount(pItem, count, true);
}
else
@@ -495,6 +504,7 @@ void WorldSession::HandleLootMasterGiveOpcode( WorldPacket & recv_data )
// not move item from loot to target inventory
Item * newitem = target->StoreNewItem( dest, item.itemid, true, item.randomPropertyId );
target->SendNewItem(newitem, uint32(item.count), false, false, true );
+ target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count);
// mark as looted
item.count=0;
diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp
index 9271c14ed13..f3148c09f15 100644
--- a/src/game/LootMgr.cpp
+++ b/src/game/LootMgr.cpp
@@ -25,6 +25,7 @@
#include "World.h"
#include "Util.h"
#include "SharedDefines.h"
+#include "SpellMgr.h"
static Rates const qualityToRate[MAX_ITEM_QUALITY] = {
RATE_DROP_ITEM_POOR, // ITEM_QUALITY_POOR
@@ -36,16 +37,18 @@ static Rates const qualityToRate[MAX_ITEM_QUALITY] = {
RATE_DROP_ITEM_ARTIFACT, // ITEM_QUALITY_ARTIFACT
};
-LootStore LootTemplates_Creature( "creature_loot_template", "creature entry");
-LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id");
-LootStore LootTemplates_Fishing( "fishing_loot_template", "area id");
-LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry");
-LootStore LootTemplates_Item( "item_loot_template", "item entry");
-LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid");
-LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry");
-LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id");
-LootStore LootTemplates_Reference( "reference_loot_template", "reference id");
-LootStore LootTemplates_Skinning( "skinning_loot_template", "creature skinning id");
+LootStore LootTemplates_Creature( "creature_loot_template", "creature entry", true);
+LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id", true);
+LootStore LootTemplates_Fishing( "fishing_loot_template", "area id", true);
+LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry", true);
+LootStore LootTemplates_Item( "item_loot_template", "item entry", true);
+LootStore LootTemplates_Milling( "milling_loot_template", "item entry (herb)", true);
+LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid", true);
+LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry (ore)", true);
+LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id (with mail template)",false);
+LootStore LootTemplates_Reference( "reference_loot_template", "reference id", false);
+LootStore LootTemplates_Skinning( "skinning_loot_template", "creature skinning id", true);
+LootStore LootTemplates_Spell( "spell_loot_template", "spell id (explicitly discovering ability)",false);
class LootTemplate::LootGroup // A set of loot definitions for items (refs are not allowed)
@@ -55,7 +58,7 @@ class LootTemplate::LootGroup // A set of loot def
bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry
bool HasQuestDropForPlayer(Player const * player) const;
// The same for active quests of the player
- void Process(Loot& loot) const; // Rolls an item from the group (if any) and adds the item to the loot
+ void Process(Loot& loot, bool rate) const; // Rolls an item from the group (if any) and adds the item to the loot
float RawTotalChance() const; // Overall chance for the group (without equal chanced items)
float TotalChance() const; // Overall chance for the group
@@ -66,7 +69,7 @@ class LootTemplate::LootGroup // A set of loot def
LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB
LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance
- LootStoreItem const * Roll() const; // Rolls an item from the group, returns NULL if all miss their chances
+ LootStoreItem const * Roll(bool rate) const; // Rolls an item from the group, returns NULL if all miss their chances
};
//Remove all data and free all memory
@@ -230,17 +233,17 @@ void LootStore::ReportNotExistedId(uint32 id) const
// Checks if the entry (quest, non-quest, reference) takes it's chance (at loot generation)
// RATE_DROP_ITEMS is no longer used for all types of entries
-bool LootStoreItem::Roll() const
+bool LootStoreItem::Roll(bool rate) const
{
if(chance>=100.f)
return true;
if(mincountOrRef < 0) // reference case
- return roll_chance_f(chance*sWorld.getRate(RATE_DROP_ITEM_REFERENCED));
+ return roll_chance_f(chance* (rate ? sWorld.getRate(RATE_DROP_ITEM_REFERENCED) : 1.0f));
ItemPrototype const *pProto = objmgr.GetItemPrototype(itemid);
- float qualityModifier = pProto ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f;
+ float qualityModifier = pProto && rate ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f;
return roll_chance_f(chance*qualityModifier);
}
@@ -379,7 +382,7 @@ void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner)
items.reserve(MAX_NR_LOOT_ITEMS);
quest_items.reserve(MAX_NR_QUEST_ITEMS);
- tab->Process(*this, store); // Processing is done there, callback via Loot::AddItem()
+ tab->Process(*this, store,store.IsRatesAllowed ()); // Processing is done there, callback via Loot::AddItem()
// Setting access rights fow group-looting case
if(!loot_owner)
@@ -765,7 +768,7 @@ void LootTemplate::LootGroup::AddEntry(LootStoreItem& item)
}
// Rolls an item from the group, returns NULL if all miss their chances
-LootStoreItem const * LootTemplate::LootGroup::Roll() const
+LootStoreItem const * LootTemplate::LootGroup::Roll(bool rate) const
{
if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked
{
@@ -777,7 +780,8 @@ LootStoreItem const * LootTemplate::LootGroup::Roll() const
return &ExplicitlyChanced[i];
ItemPrototype const *pProto = objmgr.GetItemPrototype(ExplicitlyChanced[i].itemid);
- Roll -= ExplicitlyChanced[i].chance;
+ //float qualityMultiplier = pProto && rate ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f;
+ Roll -= ExplicitlyChanced[i].chance;// * qualityMultiplier;
if (Roll < 0)
return &ExplicitlyChanced[i];
}
@@ -813,9 +817,9 @@ bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const * player) const
}
// Rolls an item from the group (if any takes its chance) and adds the item to the loot
-void LootTemplate::LootGroup::Process(Loot& loot) const
+void LootTemplate::LootGroup::Process(Loot& loot, bool rate) const
{
- LootStoreItem const * item = Roll();
+ LootStoreItem const * item = Roll(rate);
if (item != NULL)
loot.AddItem(*item);
}
@@ -900,21 +904,21 @@ void LootTemplate::AddEntry(LootStoreItem& item)
}
// Rolls for every item in the template and adds the rolled items the the loot
-void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) const
+void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint8 groupId) const
{
if (groupId) // Group reference uses own processing of the group
{
if (groupId > Groups.size())
return; // Error message already printed at loading stage
- Groups[groupId-1].Process(loot);
+ Groups[groupId-1].Process(loot,rate);
return;
}
// Rolling non-grouped items
for (LootStoreItemList::const_iterator i = Entries.begin() ; i != Entries.end() ; ++i )
{
- if ( !i->Roll() )
+ if (!i->Roll(rate))
continue; // Bad luck for the entry
if (i->mincountOrRef < 0) // References processing
@@ -925,7 +929,7 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) co
continue; // Error message already printed at loading stage
for (uint32 loop=0; loop < i->maxcount; ++loop )// Ref multiplicator
- Referenced->Process(loot, store, i->group); // Ref processing
+ Referenced->Process(loot, store, rate, i->group);
}
else // Plain entries (not a reference, not grouped)
loot.AddItem(*i); // Chance is already checked, just add
@@ -933,7 +937,7 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) co
// Now processing groups
for (LootGroups::const_iterator i = Groups.begin( ) ; i != Groups.end( ) ; ++i )
- i->Process(loot);
+ i->Process(loot,rate);
}
// True if template includes at least 1 quest drop entry
@@ -995,7 +999,7 @@ bool LootTemplate::HasQuestDropForPlayer(LootTemplateMap const& store, Player co
// Now checking groups
for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i )
- if (i->HasQuestDrop())
+ if (i->HasQuestDropForPlayer(player))
return true;
return false;
@@ -1137,6 +1141,29 @@ void LoadLootTemplates_Item()
LootTemplates_Item.ReportUnusedIds(ids_set);
}
+void LoadLootTemplates_Milling()
+{
+ LootIdSet ids_set;
+ LootTemplates_Milling.LoadAndCollectLootIds(ids_set);
+
+ // remove real entries and check existence loot
+ for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i )
+ {
+ ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i);
+ if(!proto)
+ continue;
+
+ if((proto->BagFamily & BAG_FAMILY_MASK_HERBS)==0)
+ continue;
+
+ if(ids_set.count(proto->ItemId))
+ ids_set.erase(proto->ItemId);
+ }
+
+ // output error for any still listed (not referenced from appropriate table) ids
+ LootTemplates_Milling.ReportUnusedIds(ids_set);
+}
+
void LoadLootTemplates_Pickpocketing()
{
LootIdSet ids_set, ids_setUsed;
@@ -1170,9 +1197,17 @@ void LoadLootTemplates_Prospecting()
// remove real entries and check existence loot
for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i )
- if(ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i))
- if(ids_set.count(proto->ItemId))
- ids_set.erase(proto->ItemId);
+ {
+ ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i);
+ if(!proto)
+ continue;
+
+ if((proto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP)==0)
+ continue;
+
+ if(ids_set.count(proto->ItemId))
+ ids_set.erase(proto->ItemId);
+ }
// output error for any still listed (not referenced from appropriate table) ids
LootTemplates_Prospecting.ReportUnusedIds(ids_set);
@@ -1186,8 +1221,17 @@ void LoadLootTemplates_QuestMail()
// remove real entries and check existence loot
ObjectMgr::QuestMap const& questMap = objmgr.GetQuestTemplates();
for(ObjectMgr::QuestMap::const_iterator itr = questMap.begin(); itr != questMap.end(); ++itr )
+ {
+ if(!itr->second->GetRewMailTemplateId())
+ continue;
+
if(ids_set.count(itr->first))
ids_set.erase(itr->first);
+ /* disabled reporting: some quest mails not include items
+ else
+ LootTemplates_QuestMail.ReportNotExistedId(itr->first);
+ */
+ }
// output error for any still listed (not referenced from appropriate table) ids
LootTemplates_QuestMail.ReportUnusedIds(ids_set);
@@ -1219,6 +1263,37 @@ void LoadLootTemplates_Skinning()
LootTemplates_Skinning.ReportUnusedIds(ids_set);
}
+void LoadLootTemplates_Spell()
+{
+ LootIdSet ids_set;
+ LootTemplates_Spell.LoadAndCollectLootIds(ids_set);
+
+ // remove real entries and check existence loot
+ for(uint32 spell_id = 1; spell_id < sSpellStore.GetNumRows(); ++spell_id)
+ {
+ SpellEntry const* spellInfo = sSpellStore.LookupEntry (spell_id);
+ if(!spellInfo)
+ continue;
+
+ // possible cases
+ if(!IsExplicitDiscoverySpell (spellInfo))
+ continue;
+
+ if(!ids_set.count(spell_id))
+ {
+ // not report about not trainable spells (optionally supported by DB)
+ // 61756 (Northrend Inscription Research (FAST QA VERSION) for example
+ if(spellInfo->Attributes & SPELL_ATTR_UNK5)
+ LootTemplates_Spell.ReportNotExistedId(spell_id);
+ }
+ else
+ ids_set.erase(spell_id);
+ }
+
+ // output error for any still listed (not referenced from appropriate table) ids
+ LootTemplates_QuestMail.ReportUnusedIds(ids_set);
+}
+
void LoadLootTemplates_Reference()
{
LootIdSet ids_set;
@@ -1229,6 +1304,7 @@ void LoadLootTemplates_Reference()
LootTemplates_Fishing.CheckLootRefs(&ids_set);
LootTemplates_Gameobject.CheckLootRefs(&ids_set);
LootTemplates_Item.CheckLootRefs(&ids_set);
+ LootTemplates_Milling.CheckLootRefs(&ids_set);
LootTemplates_Pickpocketing.CheckLootRefs(&ids_set);
LootTemplates_Skinning.CheckLootRefs(&ids_set);
LootTemplates_Disenchant.CheckLootRefs(&ids_set);
diff --git a/src/game/LootMgr.h b/src/game/LootMgr.h
index 1cb02c29bfc..9da36c90b93 100644
--- a/src/game/LootMgr.h
+++ b/src/game/LootMgr.h
@@ -77,7 +77,7 @@ struct LootStoreItem
group(_group), maxcount(_maxcount), conditionId(_conditionId),
needs_quest(_chanceOrQuestChance < 0) {}
- bool Roll() const; // Checks if the entry takes it's chance (at loot generation)
+ bool Roll(bool rate) const; // Checks if the entry takes it's chance (at loot generation)
bool IsValid(LootStore const& store, uint32 entry) const;
// Checks correctness of values
};
@@ -129,7 +129,8 @@ typedef std::set<uint32> LootIdSet;
class LootStore
{
public:
- explicit LootStore(char const* name, char const* entryName) : m_name(name), m_entryName(entryName) {}
+ explicit LootStore(char const* name, char const* entryName, bool ratesAllowed)
+ : m_name(name), m_entryName(entryName), m_ratesAllowed(ratesAllowed) {}
virtual ~LootStore() { Clear(); }
void Verify() const;
@@ -147,6 +148,7 @@ class LootStore
char const* GetName() const { return m_name; }
char const* GetEntryName() const { return m_entryName; }
+ bool IsRatesAllowed() const { return m_ratesAllowed; }
protected:
void LoadLootTable();
void Clear();
@@ -154,6 +156,7 @@ class LootStore
LootTemplateMap m_LootTemplates;
char const* m_name;
char const* m_entryName;
+ bool m_ratesAllowed;
};
class LootTemplate
@@ -165,7 +168,7 @@ class LootTemplate
// Adds an entry to the group (at loading stage)
void AddEntry(LootStoreItem& item);
// Rolls for every item in the template and adds the rolled items the the loot
- void Process(Loot& loot, LootStore const& store, uint8 GroupId = 0) const;
+ void Process(Loot& loot, LootStore const& store, bool rate, uint8 GroupId = 0) const;
// True if template includes at least 1 quest drop entry
bool HasQuestDrop(LootTemplateMap const& store, uint8 GroupId = 0) const;
@@ -297,21 +300,26 @@ extern LootStore LootTemplates_Creature;
extern LootStore LootTemplates_Fishing;
extern LootStore LootTemplates_Gameobject;
extern LootStore LootTemplates_Item;
+extern LootStore LootTemplates_Milling;
extern LootStore LootTemplates_Pickpocketing;
extern LootStore LootTemplates_Skinning;
extern LootStore LootTemplates_Disenchant;
extern LootStore LootTemplates_Prospecting;
extern LootStore LootTemplates_QuestMail;
+extern LootStore LootTemplates_Spell;
void LoadLootTemplates_Creature();
void LoadLootTemplates_Fishing();
void LoadLootTemplates_Gameobject();
void LoadLootTemplates_Item();
+void LoadLootTemplates_Milling();
void LoadLootTemplates_Pickpocketing();
void LoadLootTemplates_Skinning();
void LoadLootTemplates_Disenchant();
void LoadLootTemplates_Prospecting();
void LoadLootTemplates_QuestMail();
+
+void LoadLootTemplates_Spell();
void LoadLootTemplates_Reference();
inline void LoadLootTables()
@@ -320,11 +328,14 @@ inline void LoadLootTables()
LoadLootTemplates_Fishing();
LoadLootTemplates_Gameobject();
LoadLootTemplates_Item();
+ LoadLootTemplates_Milling();
LoadLootTemplates_Pickpocketing();
LoadLootTemplates_Skinning();
LoadLootTemplates_Disenchant();
LoadLootTemplates_Prospecting();
LoadLootTemplates_QuestMail();
+ LoadLootTemplates_Spell();
+
LoadLootTemplates_Reference();
}
diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp
index 48bf94c4411..398b6c42ada 100644
--- a/src/game/Mail.cpp
+++ b/src/game/Mail.cpp
@@ -601,7 +601,7 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data )
data << (uint32) (*itr)->mailTemplateId; // mail template (MailTemplate.dbc)
data << (*itr)->subject; // Subject string - once 00, when mail type = 3
- data << (uint8) item_count;
+ data << (uint8) item_count; // client limit is 0x10
for(uint8 i = 0; i < item_count; ++i)
{
@@ -612,7 +612,7 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data )
data << (uint32) (item ? item->GetGUIDLow() : 0);
// entry
data << (uint32) (item ? item->GetEntry() : 0);
- for(uint8 j = 0; j < 6; ++j)
+ for(uint8 j = 0; j < 7; ++j)
{
// unsure
data << (uint32) (item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0);
@@ -626,13 +626,15 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data )
// unk
data << (uint32) (item ? item->GetItemSuffixFactor() : 0);
// stack count
- data << (uint8) (item ? item->GetCount() : 0);
+ data << (uint32) (item ? item->GetCount() : 0);
// charges
data << (uint32) (item ? item->GetSpellCharges() : 0);
// durability
data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0);
// durability
data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0);
+ // unknown wotlk
+ data << (uint8) 0;
}
mails_count += 1;
diff --git a/src/game/Makefile.am b/src/game/Makefile.am
index 21ee6172fb3..37d649c1208 100644
--- a/src/game/Makefile.am
+++ b/src/game/Makefile.am
@@ -9,295 +9,304 @@
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## Process this file with automake to produce Makefile.in
## Sub-directories to parse
## CPP flags for includes, defines, etc.
-AM_CPPFLAGS =
+AM_CPPFLAGS = $(TRINI_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../dep/include -I$(srcdir)/../framework -I$(srcdir)/../shared -I$(srcdir)/../shared/vmap -I$(srcdir)/../realmd -DSYSCONFDIR=\"$(sysconfdir)/\"
## Build MaNGOS game library as convenience library.
# All libraries will be convenience libraries. Might be changed to shared
# later.
-noinst_LIBRARIES = libgame.a
-
-libgame_a_CPPFLAGS = \
-$(MYSQL_INCLUDES) \
-$(POSTGRE_INCLUDES) \
-$(TRINI_INCLUDES) \
--I$(top_srcdir)/dep/include \
--I$(top_srcdir)/src/framework \
--I$(top_srcdir)/src/shared \
--I$(top_srcdir)/src/shared/vmap
+noinst_LIBRARIES = libmangosgame.a
# libmangossgame library will later be reused by ...
-libgame_a_SOURCES = \
-$(srcdir)/AccountMgr.cpp \
-$(srcdir)/AccountMgr.h \
-$(srcdir)/AddonHandler.cpp \
-$(srcdir)/AddonHandler.h \
-$(srcdir)/AggressorAI.cpp \
-$(srcdir)/AggressorAI.h \
-$(srcdir)/AnimalRandomMovementGenerator.h \
-$(srcdir)/ArenaTeam.cpp \
-$(srcdir)/ArenaTeam.h \
-$(srcdir)/ArenaTeamHandler.cpp \
-$(srcdir)/AuctionHouse.cpp \
-$(srcdir)/AuctionHouseObject.h \
-$(srcdir)/Bag.cpp \
-$(srcdir)/Bag.h \
-$(srcdir)/BattleGround.cpp \
-$(srcdir)/BattleGroundAA.cpp \
-$(srcdir)/BattleGroundAB.cpp \
-$(srcdir)/BattleGroundAV.cpp \
-$(srcdir)/BattleGroundBE.cpp \
-$(srcdir)/BattleGroundEY.cpp \
-$(srcdir)/BattleGroundNA.cpp \
-$(srcdir)/BattleGroundRL.cpp \
-$(srcdir)/BattleGroundWS.cpp \
-$(srcdir)/BattleGround.h \
-$(srcdir)/BattleGroundAA.h \
-$(srcdir)/BattleGroundAB.h \
-$(srcdir)/BattleGroundAV.h \
-$(srcdir)/BattleGroundBE.h \
-$(srcdir)/BattleGroundEY.h \
-$(srcdir)/BattleGroundNA.h \
-$(srcdir)/BattleGroundRL.h \
-$(srcdir)/BattleGroundWS.h \
-$(srcdir)/BattleGroundHandler.cpp \
-$(srcdir)/BattleGroundMgr.cpp \
-$(srcdir)/BattleGroundMgr.h \
-$(srcdir)/Cell.h \
-$(srcdir)/CellImpl.h \
-$(srcdir)/Channel.cpp \
-$(srcdir)/Channel.h \
-$(srcdir)/ChannelHandler.cpp \
-$(srcdir)/ChannelMgr.h \
-$(srcdir)/CharacterHandler.cpp \
-$(srcdir)/Chat.cpp \
-$(srcdir)/Chat.h \
-$(srcdir)/ChatHandler.cpp \
-$(srcdir)/CombatHandler.cpp \
-$(srcdir)/ConfusedMovementGenerator.cpp \
-$(srcdir)/ConfusedMovementGenerator.h \
-$(srcdir)/Corpse.cpp \
-$(srcdir)/Corpse.h \
-$(srcdir)/CreatureAI.cpp \
-$(srcdir)/CreatureAI.h \
-$(srcdir)/CreatureAIImpl.h \
-$(srcdir)/CreatureAIRegistry.cpp \
-$(srcdir)/CreatureAIRegistry.h \
-$(srcdir)/CreatureAISelector.cpp \
-$(srcdir)/CreatureAISelector.h \
-$(srcdir)/CreatureGroups.cpp \
-$(srcdir)/CreatureGroups.h \
-$(srcdir)/Creature.cpp \
-$(srcdir)/Creature.h \
-$(srcdir)/debugcmds.cpp \
-$(srcdir)/DestinationHolder.cpp \
-$(srcdir)/DestinationHolder.h \
-$(srcdir)/DestinationHolderImp.h \
-$(srcdir)/DuelHandler.cpp \
-$(srcdir)/DynamicObject.cpp \
-$(srcdir)/DynamicObject.h \
-$(srcdir)/FleeingMovementGenerator.cpp \
-$(srcdir)/FleeingMovementGenerator.h \
-$(srcdir)/Formulas.h \
-$(srcdir)/GameEvent.cpp \
-$(srcdir)/GameEvent.h \
-$(srcdir)/GameObject.cpp \
-$(srcdir)/GameObject.h \
-$(srcdir)/GlobalEvents.cpp \
-$(srcdir)/GlobalEvents.h \
-$(srcdir)/GossipDef.cpp \
-$(srcdir)/GossipDef.h \
-$(srcdir)/GridDefines.h \
-$(srcdir)/GridNotifiers.cpp \
-$(srcdir)/GridNotifiers.h \
-$(srcdir)/GridNotifiersImpl.h \
-$(srcdir)/GridStates.cpp \
-$(srcdir)/GridStates.h \
-$(srcdir)/Group.cpp \
-$(srcdir)/Group.h \
-$(srcdir)/GroupHandler.cpp \
-$(srcdir)/GuardAI.cpp \
-$(srcdir)/GuardAI.h \
-$(srcdir)/Guild.cpp \
-$(srcdir)/Guild.h \
-$(srcdir)/GuildHandler.cpp \
-$(srcdir)/HomeMovementGenerator.cpp \
-$(srcdir)/HomeMovementGenerator.h \
-$(srcdir)/HostilRefManager.cpp \
-$(srcdir)/HostilRefManager.h \
-$(srcdir)/IdleMovementGenerator.cpp \
-$(srcdir)/IdleMovementGenerator.h \
-$(srcdir)/InstanceData.cpp \
-$(srcdir)/InstanceData.h \
-$(srcdir)/InstanceSaveMgr.cpp \
-$(srcdir)/InstanceSaveMgr.h \
-$(srcdir)/Item.cpp \
-$(srcdir)/Item.h \
-$(srcdir)/ItemEnchantmentMgr.cpp \
-$(srcdir)/ItemEnchantmentMgr.h \
-$(srcdir)/ItemHandler.cpp \
-$(srcdir)/ItemPrototype.h \
-$(srcdir)/Language.h \
-$(srcdir)/Level0.cpp \
-$(srcdir)/Level1.cpp \
-$(srcdir)/Level2.cpp \
-$(srcdir)/Level3.cpp \
-$(srcdir)/LFGHandler.cpp \
-$(srcdir)/LootHandler.cpp \
-$(srcdir)/LootMgr.cpp \
-$(srcdir)/LootMgr.h \
-$(srcdir)/Mail.cpp \
-$(srcdir)/Mail.h \
-$(srcdir)/Map.cpp \
-$(srcdir)/Map.h \
-$(srcdir)/MapInstanced.cpp \
-$(srcdir)/MapInstanced.h \
-$(srcdir)/MapManager.cpp \
-$(srcdir)/MapManager.h \
-$(srcdir)/MiscHandler.cpp \
-$(srcdir)/MotionMaster.cpp \
-$(srcdir)/MotionMaster.h \
-$(srcdir)/MovementGenerator.cpp \
-$(srcdir)/MovementGenerator.h \
-$(srcdir)/MovementGeneratorImpl.h \
-$(srcdir)/MovementHandler.cpp \
-$(srcdir)/NPCHandler.cpp \
-$(srcdir)/NPCHandler.h \
-$(srcdir)/NullCreatureAI.cpp \
-$(srcdir)/NullCreatureAI.h \
-$(srcdir)/ObjectAccessor.cpp \
-$(srcdir)/ObjectAccessor.h \
-$(srcdir)/Object.cpp \
-$(srcdir)/ObjectDefines.h \
-$(srcdir)/ObjectGridLoader.cpp \
-$(srcdir)/ObjectGridLoader.h \
-$(srcdir)/Object.h \
-$(srcdir)/ObjectMgr.cpp \
-$(srcdir)/ObjectMgr.h \
-$(srcdir)/Opcodes.cpp \
-$(srcdir)/Opcodes.h \
-$(srcdir)/OutdoorPvP.cpp \
-$(srcdir)/OutdoorPvP.h \
-$(srcdir)/OutdoorPvPEP.cpp \
-$(srcdir)/OutdoorPvPEP.h \
-$(srcdir)/OutdoorPvPHP.cpp \
-$(srcdir)/OutdoorPvPHP.h \
-$(srcdir)/OutdoorPvPMgr.cpp \
-$(srcdir)/OutdoorPvPMgr.h \
-$(srcdir)/OutdoorPvPNA.cpp \
-$(srcdir)/OutdoorPvPNA.h \
-$(srcdir)/OutdoorPvPObjectiveAI.cpp \
-$(srcdir)/OutdoorPvPObjectiveAI.h \
-$(srcdir)/OutdoorPvPSI.cpp \
-$(srcdir)/OutdoorPvPSI.h \
-$(srcdir)/OutdoorPvPTF.cpp \
-$(srcdir)/OutdoorPvPTF.h \
-$(srcdir)/OutdoorPvPZM.cpp \
-$(srcdir)/OutdoorPvPZM.h \
-$(srcdir)/Path.h \
-$(srcdir)/PetAI.cpp \
-$(srcdir)/PetAI.h \
-$(srcdir)/Pet.cpp \
-$(srcdir)/Pet.h \
-$(srcdir)/PetHandler.cpp \
-$(srcdir)/PetitionsHandler.cpp \
-$(srcdir)/Player.cpp \
-$(srcdir)/Player.h \
-$(srcdir)/PlayerDump.cpp \
-$(srcdir)/PlayerDump.h \
-$(srcdir)/PointMovementGenerator.cpp \
-$(srcdir)/PointMovementGenerator.h \
-$(srcdir)/PossessedAI.cpp \
-$(srcdir)/PossessedAI.h \
-$(srcdir)/QueryHandler.cpp \
-$(srcdir)/QuestDef.cpp \
-$(srcdir)/QuestDef.h \
-$(srcdir)/QuestHandler.cpp \
-$(srcdir)/RandomMovementGenerator.cpp \
-$(srcdir)/RandomMovementGenerator.h \
-$(srcdir)/ReactorAI.cpp \
-$(srcdir)/ReactorAI.h \
-$(srcdir)/ScriptCalls.cpp \
-$(srcdir)/ScriptCalls.h \
-$(srcdir)/SharedDefines.h \
-$(srcdir)/SkillHandler.cpp \
-$(srcdir)/SpellAuraDefines.h \
-$(srcdir)/SpellAuras.cpp \
-$(srcdir)/SpellAuras.h \
-$(srcdir)/Spell.cpp \
-$(srcdir)/SpellEffects.cpp \
-$(srcdir)/Spell.h \
-$(srcdir)/SkillDiscovery.cpp \
-$(srcdir)/SkillDiscovery.h \
-$(srcdir)/SkillExtraItems.cpp \
-$(srcdir)/SkillExtraItems.h \
-$(srcdir)/SpellHandler.cpp \
-$(srcdir)/SocialMgr.cpp \
-$(srcdir)/SocialMgr.h \
-$(srcdir)/SpellMgr.cpp \
-$(srcdir)/SpellMgr.h \
-$(srcdir)/StatSystem.cpp \
-$(srcdir)/TargetedMovementGenerator.cpp \
-$(srcdir)/TargetedMovementGenerator.h \
-$(srcdir)/TaxiHandler.cpp \
-$(srcdir)/TemporarySummon.cpp \
-$(srcdir)/TemporarySummon.h \
-$(srcdir)/TicketHandler.cpp \
-$(srcdir)/TicketMgr.cpp \
-$(srcdir)/TicketMgr.h \
-$(srcdir)/tools.cpp \
-$(srcdir)/Tools.h \
-$(srcdir)/TotemAI.cpp \
-$(srcdir)/TotemAI.h \
-$(srcdir)/Totem.cpp \
-$(srcdir)/Totem.h \
-$(srcdir)/TradeHandler.cpp \
-$(srcdir)/Transports.cpp \
-$(srcdir)/Transports.h \
-$(srcdir)/ThreatManager.cpp \
-$(srcdir)/ThreatManager.h \
-$(srcdir)/Traveller.h \
-$(srcdir)/Unit.cpp \
-$(srcdir)/Unit.h \
-$(srcdir)/UnitEvents.h \
-$(srcdir)/UpdateData.cpp \
-$(srcdir)/UpdateData.h \
-$(srcdir)/UpdateFields.h \
-$(srcdir)/UpdateMask.h \
-$(srcdir)/VoiceChatHandler.cpp \
-$(srcdir)/WaypointManager.cpp \
-$(srcdir)/WaypointManager.h \
-$(srcdir)/WaypointMovementGenerator.cpp \
-$(srcdir)/WaypointMovementGenerator.h \
-$(srcdir)/Weather.cpp \
-$(srcdir)/Weather.h \
-$(srcdir)/World.cpp \
-$(srcdir)/World.h \
-$(srcdir)/WorldLog.cpp \
-$(srcdir)/WorldLog.h \
-$(srcdir)/WorldSession.cpp \
-$(srcdir)/WorldSession.h \
-$(srcdir)/WorldSocket.cpp \
-$(srcdir)/WorldSocket.h \
-$(srcdir)/WorldSocketMgr.cpp \
-$(srcdir)/WorldSocketMgr.h \
-$(srcdir)/FollowerReference.cpp \
-$(srcdir)/FollowerReference.h \
-$(srcdir)/FollowerRefManager.h \
-$(srcdir)/GroupReference.cpp \
-$(srcdir)/GroupReference.h \
-$(srcdir)/GroupRefManager.h
+libmangosgame_a_SOURCES = \
+ AccountMgr.cpp \
+ AccountMgr.h \
+ AchievementMgr.h \
+ AchievementMgr.cpp \
+ AddonHandler.cpp \
+ AddonHandler.h \
+ AggressorAI.cpp \
+ AggressorAI.h \
+ AnimalRandomMovementGenerator.h \
+ ArenaTeam.cpp \
+ ArenaTeam.h \
+ ArenaTeamHandler.cpp \
+ AuctionHouse.cpp \
+ AuctionHouseObject.h \
+ Bag.cpp \
+ Bag.h \
+ BattleGround.cpp \
+ BattleGroundAA.cpp \
+ BattleGroundAB.cpp \
+ BattleGroundAV.cpp \
+ BattleGroundBE.cpp \
+ BattleGroundDS.cpp \
+ BattleGroundEY.cpp \
+ BattleGroundNA.cpp \
+ BattleGroundRL.cpp \
+ BattleGroundRV.cpp \
+ BattleGroundSA.cpp \
+ BattleGroundWS.cpp \
+ BattleGround.h \
+ BattleGroundAA.h \
+ BattleGroundAB.h \
+ BattleGroundAV.h \
+ BattleGroundBE.h \
+ BattleGroundDS.h \
+ BattleGroundEY.h \
+ BattleGroundNA.h \
+ BattleGroundRL.h \
+ BattleGroundRV.h \
+ BattleGroundSA.h \
+ BattleGroundWS.h \
+ BattleGroundHandler.cpp \
+ BattleGroundMgr.cpp \
+ BattleGroundMgr.h \
+ Calendar.cpp \
+ Calendar.h \
+ CalendarHandler.cpp \
+ Cell.h \
+ CellImpl.h \
+ Channel.cpp \
+ Channel.h \
+ ChannelHandler.cpp \
+ ChannelMgr.h \
+ CharacterHandler.cpp \
+ Chat.cpp \
+ Chat.h \
+ ChatHandler.cpp \
+ CombatHandler.cpp \
+ ConfusedMovementGenerator.cpp \
+ ConfusedMovementGenerator.h \
+ Corpse.cpp \
+ Corpse.h \
+ CreatureAI.cpp \
+ CreatureAI.h \
+ CreatureAIImpl.h \
+ CreatureAIRegistry.cpp \
+ CreatureAIRegistry.h \
+ CreatureAISelector.cpp \
+ CreatureAISelector.h \
+ CreatureGroups.cpp \
+ CreatureGroups.h \
+ Creature.cpp \
+ Creature.h \
+ debugcmds.cpp \
+ DestinationHolder.cpp \
+ DestinationHolder.h \
+ DestinationHolderImp.h \
+ DuelHandler.cpp \
+ DynamicObject.cpp \
+ DynamicObject.h \
+ FleeingMovementGenerator.cpp \
+ FleeingMovementGenerator.h \
+ Formulas.h \
+ GameEvent.cpp \
+ GameEvent.h \
+ GameObject.cpp \
+ GameObject.h \
+ GlobalEvents.cpp \
+ GlobalEvents.h \
+ GossipDef.cpp \
+ GossipDef.h \
+ GridDefines.h \
+ GridNotifiers.cpp \
+ GridNotifiers.h \
+ GridNotifiersImpl.h \
+ GridStates.cpp \
+ GridStates.h \
+ Group.cpp \
+ Group.h \
+ GroupHandler.cpp \
+ GuardAI.cpp \
+ GuardAI.h \
+ Guild.cpp \
+ Guild.h \
+ GuildHandler.cpp \
+ HomeMovementGenerator.cpp \
+ HomeMovementGenerator.h \
+ HostilRefManager.cpp \
+ HostilRefManager.h \
+ IdleMovementGenerator.cpp \
+ IdleMovementGenerator.h \
+ InstanceData.cpp \
+ InstanceData.h \
+ InstanceSaveMgr.cpp \
+ InstanceSaveMgr.h \
+ Item.cpp \
+ Item.h \
+ ItemEnchantmentMgr.cpp \
+ ItemEnchantmentMgr.h \
+ ItemHandler.cpp \
+ ItemPrototype.h \
+ Language.h \
+ Level0.cpp \
+ Level1.cpp \
+ Level2.cpp \
+ Level3.cpp \
+ LFGHandler.cpp \
+ LootHandler.cpp \
+ LootMgr.cpp \
+ LootMgr.h \
+ Mail.cpp \
+ Mail.h \
+ Map.cpp \
+ Map.h \
+ MapInstanced.cpp \
+ MapInstanced.h \
+ MapManager.cpp \
+ MapManager.h \
+ MapReference.h \
+ MapRefManager.h \
+ MiscHandler.cpp \
+ MotionMaster.cpp \
+ MotionMaster.h \
+ MovementGenerator.cpp \
+ MovementGenerator.h \
+ MovementGeneratorImpl.h \
+ MovementHandler.cpp \
+ NPCHandler.cpp \
+ NPCHandler.h \
+ NullCreatureAI.cpp \
+ NullCreatureAI.h \
+ ObjectAccessor.cpp \
+ ObjectAccessor.h \
+ Object.cpp \
+ ObjectDefines.h \
+ ObjectGridLoader.cpp \
+ ObjectGridLoader.h \
+ Object.h \
+ ObjectMgr.cpp \
+ ObjectMgr.h \
+ ObjectPosSelector.cpp \
+ ObjectPosSelector.h \
+ Opcodes.cpp \
+ Opcodes.h \
+ OutdoorPvP.cpp \
+ OutdoorPvP.h \
+ OutdoorPvPEP.cpp \
+ OutdoorPvPEP.h \
+ OutdoorPvPHP.cpp \
+ OutdoorPvPHP.h \
+ OutdoorPvPMgr.cpp \
+ OutdoorPvPMgr.h \
+ OutdoorPvPNA.cpp \
+ OutdoorPvPNA.h \
+ OutdoorPvPObjectiveAI.cpp \
+ OutdoorPvPObjectiveAI.h \
+ OutdoorPvPSI.cpp \
+ OutdoorPvPSI.h \
+ OutdoorPvPTF.cpp \
+ OutdoorPvPTF.h \
+ OutdoorPvPZM.cpp \
+ OutdoorPvPZM.h \
+ Path.h \
+ PetAI.cpp \
+ PetAI.h \
+ Pet.cpp \
+ Pet.h \
+ PetHandler.cpp \
+ PetitionsHandler.cpp \
+ Player.cpp \
+ Player.h \
+ PlayerDump.cpp \
+ PlayerDump.h \
+ PossessedAI.cpp \
+ PossessedAI.h \
+ PointMovementGenerator.cpp \
+ PointMovementGenerator.h \
+ QueryHandler.cpp \
+ QuestDef.cpp \
+ QuestDef.h \
+ QuestHandler.cpp \
+ RandomMovementGenerator.cpp \
+ RandomMovementGenerator.h \
+ ReactorAI.cpp \
+ ReactorAI.h \
+ ScriptCalls.cpp \
+ ScriptCalls.h \
+ SharedDefines.h \
+ SkillHandler.cpp \
+ SpellAuraDefines.h \
+ SpellAuras.cpp \
+ SpellAuras.h \
+ Spell.cpp \
+ SpellEffects.cpp \
+ Spell.h \
+ SkillDiscovery.cpp \
+ SkillDiscovery.h \
+ SkillExtraItems.cpp \
+ SkillExtraItems.h \
+ SpellHandler.cpp \
+ SocialMgr.cpp \
+ SocialMgr.h \
+ SpellMgr.cpp \
+ SpellMgr.h \
+ StatSystem.cpp \
+ TargetedMovementGenerator.cpp \
+ TargetedMovementGenerator.h \
+ TaxiHandler.cpp \
+ TemporarySummon.cpp \
+ TemporarySummon.h \
+ TotemAI.cpp \
+ TotemAI.h \
+ Totem.cpp \
+ Totem.h \
+ TradeHandler.cpp \
+ Transports.cpp \
+ Transports.h \
+ ThreatManager.cpp \
+ ThreatManager.h \
+ TicketHandler.cpp \
+ TicketMgr.cpp \
+ TicketMgr.h \
+ Traveller.h \
+ Unit.cpp \
+ Unit.h \
+ UnitEvents.h \
+ UpdateData.cpp \
+ UpdateData.h \
+ UpdateFields.h \
+ UpdateMask.h \
+ Vehicle.cpp \
+ Vehicle.h \
+ VoiceChatHandler.cpp \
+ WaypointManager.cpp \
+ WaypointManager.h \
+ WaypointMovementGenerator.cpp \
+ WaypointMovementGenerator.h \
+ Weather.cpp \
+ Weather.h \
+ World.cpp \
+ World.h \
+ WorldLog.cpp \
+ WorldLog.h \
+ WorldSession.cpp \
+ WorldSession.h \
+ WorldSocket.cpp \
+ WorldSocket.h \
+ WorldSocketMgr.cpp \
+ WorldSocketMgr.h \
+ FollowerReference.cpp \
+ FollowerReference.h \
+ FollowerRefManager.h \
+ GroupReference.cpp \
+ GroupReference.h \
+ GroupRefManager.h
+
+## Link against shared library
+libmangosgame_a_LIBADD = ../shared/libmangosshared.a ../shared/Auth/libmangosauth.a ../shared/Config/libmangosconfig.a ../shared/Database/libmangosdatabase.a ../shared/vmap/libmangosvmaps.a
## Additional files to include when running 'make dist'
# Nothing yet.
diff --git a/src/game/Map.cpp b/src/game/Map.cpp
index 7bf4c3fa83e..9ebd3357175 100644
--- a/src/game/Map.cpp
+++ b/src/game/Map.cpp
@@ -45,7 +45,7 @@
#define MAX_GRID_LOAD_TIME 50
// magic *.map header
-const char MAP_MAGIC[] = "MAP_2.00";
+const char MAP_MAGIC[] = "MAP_2.01";
GridState* si_GridStates[MAX_GRID_STATE];
@@ -257,7 +257,7 @@ template<>
void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell)
{
// add to world object registry in grid
- if(obj->isPet() /*&& IS_PLAYER_GUID(obj->GetOwnerGUID())*/ || obj->isPossessedByPlayer())
+ if(obj->isPet() || obj->isPossessedByPlayer() || obj->isVehicle())
{
(*grid)(cell.CellX(), cell.CellY()).AddWorldObject<Creature>(obj, obj->GetGUID());
obj->SetCurrentCell(cell);
@@ -301,7 +301,7 @@ template<>
void Map::RemoveFromGrid(Creature* obj, NGridType *grid, Cell const& cell)
{
// remove from world object registry in grid
- if(obj->isPet() || obj->isPossessedByPlayer())
+ if(obj->isPet() || obj->isPossessedByPlayer() || obj->isVehicle())
{
(*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject<Creature>(obj, obj->GetGUID());
}
@@ -1289,7 +1289,7 @@ float Map::GetVmapHeight(float x, float y, float z, bool useMaps) const
return vmapHeight;
}
-uint16 Map::GetAreaFlag(float x, float y ) const
+uint16 Map::GetAreaFlag(float x, float y, float z) const
{
//local x,y coords
float lx,ly;
@@ -1307,11 +1307,30 @@ uint16 Map::GetAreaFlag(float x, float y ) const
// ensure GridMap is loaded
const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy));
+ uint16 areaflag;
if(GridMaps[gx][gy])
- return GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)];
+ areaflag = GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)];
// this used while not all *.map files generated (instances)
else
- return GetAreaFlagByMapId(i_id);
+ areaflag = GetAreaFlagByMapId(i_id);
+
+ //FIXME: some hacks for areas above or underground for ground area
+ // required for area specific spells/etc, until map/vmap data
+ // not provided correct areaflag with this hacks
+ switch(areaflag)
+ {
+ // Acherus: The Ebon Hold (Plaguelands: The Scarlet Enclave)
+ case 1984: // Plaguelands: The Scarlet Enclave
+ case 2076: // Death's Breach (Plaguelands: The Scarlet Enclave)
+ case 2745: // The Noxious Pass (Plaguelands: The Scarlet Enclave)
+ if(z > 350.0f) areaflag = 2048; break;
+ // Acherus: The Ebon Hold (Eastern Plaguelands)
+ case 856: // The Noxious Glade (Eastern Plaguelands)
+ case 2456: // Death's Breach (Eastern Plaguelands)
+ if(z > 350.0f) areaflag = 1950; break;
+ }
+
+ return areaflag;
}
uint8 Map::GetTerrainType(float x, float y ) const
@@ -1752,10 +1771,10 @@ bool InstanceMap::CanEnter(Player *player)
}
// cannot enter if the instance is full (player cap), GMs don't count
- InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId());
- if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= iTemplate->maxPlayers)
+ uint32 maxPlayers = GetMaxPlayers();
+ if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= maxPlayers)
{
- sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), iTemplate->maxPlayers, player->GetName());
+ sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName());
player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
return false;
}
@@ -2065,6 +2084,14 @@ void InstanceMap::SetResetSchedule(bool on)
}
}
+uint32 InstanceMap::GetMaxPlayers() const
+{
+ InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId());
+ if(!iTemplate)
+ return 0;
+ return IsHeroic() ? iTemplate->maxPlayersHeroic : iTemplate->maxPlayers;
+}
+
/* ******* Battleground Instance Maps ******* */
BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId)
diff --git a/src/game/Map.h b/src/game/Map.h
index bcdf3ec8f6a..0c4fbd0ece4 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -100,7 +100,8 @@ struct InstanceTemplate
uint32 levelMin;
uint32 levelMax;
uint32 maxPlayers;
- uint32 reset_delay;
+ uint32 maxPlayersHeroic;
+ uint32 reset_delay; // FIX ME: now exist normal/heroic raids with possible different time of reset.
float startLocX;
float startLocY;
float startLocZ;
@@ -134,13 +135,11 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
// currently unused for normal maps
bool CanUnload(uint32 diff)
- {
- if(!m_unloadTimer)
- return false;
- if(m_unloadTimer <= diff)
- return true;
- m_unloadTimer -= diff;
- return false;
+ {
+ if(!m_unloadTimer) return false;
+ if(m_unloadTimer <= diff) return true;
+ m_unloadTimer -= diff;
+ return false;
}
virtual bool Add(Player *);
@@ -160,7 +159,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> &visitor);
- inline bool IsRemovalGrid(float x, float y) const
+ bool IsRemovalGrid(float x, float y) const
{
GridPair p = Trinity::ComputeGridPair(x, y);
return( !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL );
@@ -194,7 +193,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
float GetVmapHeight(float x, float y, float z, bool useMaps) const;
bool IsInWater(float x, float y, float z) const; // does not use z pos. This is for future use
- uint16 GetAreaFlag(float x, float y ) const;
+ uint16 GetAreaFlag(float x, float y, float z) const;
uint8 GetTerrainType(float x, float y ) const;
float GetWaterLevel(float x, float y ) const;
bool IsUnderWater(float x, float y, float z) const;
@@ -202,14 +201,14 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
static uint32 GetAreaId(uint16 areaflag,uint32 map_id);
static uint32 GetZoneId(uint16 areaflag,uint32 map_id);
- uint32 GetAreaId(float x, float y) const
+ uint32 GetAreaId(float x, float y, float z) const
{
- return GetAreaId(GetAreaFlag(x,y),i_id);
+ return GetAreaId(GetAreaFlag(x,y,z),i_id);
}
- uint32 GetZoneId(float x, float y) const
+ uint32 GetZoneId(float x, float y, float z) const
{
- return GetZoneId(GetAreaFlag(x,y),i_id);
+ return GetZoneId(GetAreaFlag(x,y,z),i_id);
}
virtual void MoveAllCreaturesInMoveList();
@@ -233,6 +232,17 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); }
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
+ bool GetEntrancePos(int32 &mapid, float &x, float &y)
+ {
+ if(!i_mapEntry)
+ return false;
+ if(i_mapEntry->entrance_map < 0)
+ return false;
+ mapid = i_mapEntry->entrance_map;
+ x = i_mapEntry->entrance_x;
+ y = i_mapEntry->entrance_y;
+ return true;
+ }
void AddObjectToRemoveList(WorldObject *obj);
void DoDelayedMovesAndRemoves();
@@ -304,7 +314,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x,y)->isGridObjectDataLoaded(); }
void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); }
- inline void setNGrid(NGridType* grid, uint32 x, uint32 y);
+ void setNGrid(NGridType* grid, uint32 x, uint32 y);
void UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff);
protected:
@@ -375,6 +385,7 @@ class TRINITY_DLL_SPEC InstanceMap : public Map
bool CanEnter(Player* player);
void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on);
+ uint32 GetMaxPlayers() const;
private:
bool m_resetAfterUnload;
bool m_unloadWhenEmpty;
diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp
index fdd62d2d4ce..e9a77d13b7c 100644
--- a/src/game/MapManager.cpp
+++ b/src/game/MapManager.cpp
@@ -175,7 +175,8 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player)
//The player has a heroic mode and tries to enter into instance which has no a heroic mode
if (!entry->SupportsHeroicMode() && player->GetDifficulty() == DIFFICULTY_HEROIC)
{
- player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY2); //Send aborted message
+ //Send aborted message
+ player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, DIFFICULTY_HEROIC);
return false;
}
@@ -240,7 +241,7 @@ void MapManager::RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y)
}
void
-MapManager::Update(time_t diff)
+MapManager::Update(uint32 diff)
{
i_timer.Update(diff);
if( !i_timer.Passed() )
@@ -286,7 +287,8 @@ bool MapManager::ExistMapAndVMap(uint32 mapid, float x,float y)
bool MapManager::IsValidMAP(uint32 mapid)
{
MapEntry const* mEntry = sMapStore.LookupEntry(mapid);
- return mEntry && (!mEntry->Instanceable() || objmgr.GetInstanceTemplate(mapid));
+ return mEntry && (!mEntry->IsDungeon() || objmgr.GetInstanceTemplate(mapid));
+ // TODO: add check for battleground template
}
void MapManager::LoadGrid(int mapid, float x, float y, const WorldObject* obj, bool no_unload)
diff --git a/src/game/MapManager.h b/src/game/MapManager.h
index cba0a86d1a5..9bd63e4bb78 100644
--- a/src/game/MapManager.h
+++ b/src/game/MapManager.h
@@ -47,18 +47,18 @@ class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinit
Map const* GetBaseMap(uint32 id) const { return const_cast<MapManager*>(this)->_GetBaseMap(id); }
void DeleteInstance(uint32 mapid, uint32 instanceId);
- inline uint16 GetAreaFlag(uint32 mapid, float x, float y) const
+ uint16 GetAreaFlag(uint32 mapid, float x, float y, float z) const
{
Map const* m = GetBaseMap(mapid);
- return m->GetAreaFlag(x, y);
+ return m->GetAreaFlag(x, y, z);
}
- inline uint32 GetAreaId(uint32 mapid, float x, float y) { return Map::GetAreaId(GetAreaFlag(mapid, x, y),mapid); }
- inline uint32 GetZoneId(uint32 mapid, float x, float y) { return Map::GetZoneId(GetAreaFlag(mapid, x, y),mapid); }
+ uint32 GetAreaId(uint32 mapid, float x, float y, float z) const { return Map::GetAreaId(GetAreaFlag(mapid, x, y, z),mapid); }
+ uint32 GetZoneId(uint32 mapid, float x, float y, float z) const { return Map::GetZoneId(GetAreaFlag(mapid, x, y, z),mapid); }
void Initialize(void);
- void Update(time_t);
+ void Update(uint32);
- inline void SetGridCleanUpDelay(uint32 t)
+ void SetGridCleanUpDelay(uint32 t)
{
if( t < MIN_GRID_DELAY )
i_gridCleanUpDelay = MIN_GRID_DELAY;
@@ -66,7 +66,7 @@ class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinit
i_gridCleanUpDelay = t;
}
- inline void SetMapUpdateInterval(uint32 t)
+ void SetMapUpdateInterval(uint32 t)
{
if( t > MIN_MAP_UPDATE_DELAY )
t = MIN_MAP_UPDATE_DELAY;
@@ -108,7 +108,7 @@ class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinit
bool CanPlayerEnter(uint32 mapid, Player* player);
void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y);
- inline uint32 GenerateInstanceId() { return ++i_MaxInstanceId; }
+ uint32 GenerateInstanceId() { return ++i_MaxInstanceId; }
void InitMaxInstanceId();
/* statistics */
diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp
index cfba9a5f7c4..eda08ebcd25 100644
--- a/src/game/MiscHandler.cpp
+++ b/src/game/MiscHandler.cpp
@@ -306,13 +306,13 @@ void WorldSession::HandleLogoutRequestOpcode( WorldPacket & /*recv_data*/ )
// not set flags if player can't free move to prevent lost state at logout cancel
if(GetPlayer()->CanFreeMove())
{
- GetPlayer()->SetStandState(PLAYER_STATE_SIT);
+ GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT);
WorldPacket data( SMSG_FORCE_MOVE_ROOT, (8+4) ); // guess size
data.append(GetPlayer()->GetPackGUID());
data << (uint32)2;
SendPacket( &data );
- GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+ GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
}
WorldPacket data( SMSG_LOGOUT_RESPONSE, 5 );
@@ -346,10 +346,10 @@ void WorldSession::HandleLogoutCancelOpcode( WorldPacket & /*recv_data*/ )
SendPacket( &data );
//! Stand Up
- GetPlayer()->SetStandState(PLAYER_STATE_NONE);
+ GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND);
//! DISABLE_ROTATE
- GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+ GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
}
sLog.outDebug( "WORLD: sent SMSG_LOGOUT_CANCEL_ACK Message" );
@@ -363,10 +363,12 @@ void WorldSession::HandleTogglePvP( WorldPacket & recv_data )
bool newPvPStatus;
recv_data >> newPvPStatus;
GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP, newPvPStatus);
+ GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER, !newPvPStatus);
}
else
{
GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP);
+ GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER);
}
if(GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
@@ -816,7 +818,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
GetPlayer()->SetRestType(REST_TYPE_IN_TAVERN);
if(sWorld.IsFFAPvPRealm())
- GetPlayer()->RemoveFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP);
+ GetPlayer()->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
return;
}
@@ -886,7 +888,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
if(missingItem)
SendAreaTriggerMessage(GetTrinityString(LANG_LEVEL_MINREQUIRED_AND_ITEM), at->requiredLevel, objmgr.GetItemPrototype(missingItem)->Name1);
else if(missingKey)
- GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY2);
+ GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, DIFFICULTY_HEROIC);
else if(missingHeroicQuest)
SendAreaTriggerMessage(at->heroicQuestFailedText.c_str());
else if(missingQuest)
@@ -900,16 +902,96 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
GetPlayer()->TeleportTo(at->target_mapId,at->target_X,at->target_Y,at->target_Z,at->target_Orientation,TELE_TO_NOT_LEAVE_TRANSPORT);
}
-void WorldSession::HandleUpdateAccountData(WorldPacket &/*recv_data*/)
+void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data)
{
sLog.outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA");
- //recv_data.hexlike();
+
+ CHECK_PACKET_SIZE(recv_data, 4+4+4);
+
+ uint32 type, timestamp, decompressedSize;
+ recv_data >> type >> timestamp >> decompressedSize;
+
+ sLog.outDebug("UAD: type %u, time %u, decompressedSize %u", type, timestamp, decompressedSize);
+
+ if(type > NUM_ACCOUNT_DATA_TYPES)
+ return;
+
+ if(decompressedSize == 0) // erase
+ {
+ SetAccountData(type, timestamp, "");
+
+ WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4);
+ data << uint32(type);
+ data << uint32(0);
+ SendPacket(&data);
+
+ return;
+ }
+
+ if(decompressedSize > 0xFFFF)
+ {
+ sLog.outError("UAD: Account data packet too big, size %u", decompressedSize);
+ return;
+ }
+
+ ByteBuffer dest;
+ dest.resize(decompressedSize);
+
+ uLongf realSize = decompressedSize;
+ if(uncompress(const_cast<uint8*>(dest.contents()), &realSize, const_cast<uint8*>(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK)
+ {
+ sLog.outError("UAD: Failed to decompress account data");
+ return;
+ }
+
+ std::string adata;
+ dest >> adata;
+
+ SetAccountData(type, timestamp, adata);
+
+ WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4);
+ data << uint32(type);
+ data << uint32(0);
+ SendPacket(&data);
}
-void WorldSession::HandleRequestAccountData(WorldPacket& /*recv_data*/)
+void WorldSession::HandleRequestAccountData(WorldPacket& recv_data)
{
sLog.outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA");
- //recv_data.hexlike();
+
+ CHECK_PACKET_SIZE(recv_data, 4);
+
+ uint32 type;
+ recv_data >> type;
+
+ sLog.outDebug("RAD: type %u", type);
+
+ if(type > NUM_ACCOUNT_DATA_TYPES)
+ return;
+
+ AccountData *adata = GetAccountData(type);
+
+ uint32 size = adata->Data.size();
+
+ ByteBuffer dest;
+ dest.resize(size);
+
+ uLongf destSize = size;
+ if(size && compress(const_cast<uint8*>(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK)
+ {
+ sLog.outDebug("RAD: Failed to compress account data");
+ return;
+ }
+
+ dest.resize(destSize);
+
+ WorldPacket data (SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize);
+ data << uint64(_player->GetGUID()); // player guid
+ data << uint32(type); // type (0-7)
+ data << uint32(adata->Time); // unix time
+ data << uint32(size); // decompressed length
+ data.append(dest); // compressed data
+ SendPacket(&data);
}
void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data)
@@ -1441,11 +1523,11 @@ void WorldSession::HandleChooseTitleOpcode( WorldPacket & recv_data )
GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title);
}
-void WorldSession::HandleAllowMoveAckOpcode( WorldPacket & recv_data )
+void WorldSession::HandleTimeSyncResp( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data, 4+4);
- sLog.outDebug("CMSG_ALLOW_MOVE_ACK");
+ sLog.outDebug("CMSG_TIME_SYNC_RESP");
uint32 counter, time_;
recv_data >> counter >> time_;
@@ -1515,26 +1597,6 @@ void WorldSession::HandleDungeonDifficultyOpcode( WorldPacket & recv_data )
}
}
-void WorldSession::HandleNewUnknownOpcode( WorldPacket & recv_data )
-{
- sLog.outDebug("New Unknown Opcode %u", recv_data.GetOpcode());
- recv_data.hexlike();
- /*
- New Unknown Opcode 837
- STORAGE_SIZE: 60
- 02 00 00 00 00 00 00 00 | 00 00 00 00 01 20 00 00
- 89 EB 33 01 71 5C 24 C4 | 15 03 35 45 74 47 8B 42
- BA B8 1B 40 00 00 00 00 | 00 00 00 00 77 66 42 BF
- 23 91 26 3F 00 00 60 41 | 00 00 00 00
-
- New Unknown Opcode 837
- STORAGE_SIZE: 44
- 02 00 00 00 00 00 00 00 | 00 00 00 00 00 00 80 00
- 7B 80 34 01 84 EA 2B C4 | 5F A1 36 45 C9 39 1C 42
- BA B8 1B 40 CE 06 00 00 | 00 00 80 3F
- */
-}
-
void WorldSession::HandleDismountOpcode( WorldPacket & /*recv_data*/ )
{
sLog.outDebug("WORLD: CMSG_CANCEL_MOUNT_AURA");
@@ -1601,3 +1663,32 @@ void WorldSession::HandleSetTaxiBenchmarkOpcode( WorldPacket & recv_data )
sLog.outDebug("Client used \"/timetest %d\" command", mode);
}
+
+void WorldSession::HandleSpellClick( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data, 8);
+
+ uint64 guid;
+ recv_data >> guid;
+
+ Vehicle *vehicle = ObjectAccessor::GetVehicle(guid);
+
+ if(!vehicle)
+ return;
+
+ _player->EnterVehicle(vehicle);
+}
+
+void WorldSession::HandleInspectAchievements( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data, 1);
+ uint64 guid;
+ if(!recv_data.readPackGUID(guid))
+ return;
+
+ Player *player = objmgr.GetPlayer(guid);
+ if(!player)
+ return;
+
+ player->GetAchievementMgr().SendRespondInspectAchievements(_player);
+}
diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp
index afc1940f89b..60f7f1eee40 100644
--- a/src/game/MotionMaster.cpp
+++ b/src/game/MotionMaster.cpp
@@ -161,8 +161,8 @@ void MotionMaster::MoveIdle(MovementSlot slot)
void
MotionMaster::MoveTargetedHome()
{
- if(i_owner->hasUnitState(UNIT_STAT_FLEEING))
- return;
+ //if(i_owner->hasUnitState(UNIT_STAT_FLEEING))
+ // return;
Clear(false);
diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
index 0a310cddd96..a114d6b4de6 100644
--- a/src/game/MovementHandler.cpp
+++ b/src/game/MovementHandler.cpp
@@ -178,64 +178,15 @@ void WorldSession::HandleMoveWorldportAckOpcode()
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
- CHECK_PACKET_SIZE(recv_data, 4+1+4+4+4+4+4);
+ uint32 opcode = recv_data.GetOpcode();
+ sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
+
+ if(GetPlayer()->GetDontMove())
+ return;
/* extract packet */
MovementInfo movementInfo;
- uint32 MovementFlags;
-
- recv_data >> MovementFlags;
- recv_data >> movementInfo.unk1;
- recv_data >> movementInfo.time;
- recv_data >> movementInfo.x;
- recv_data >> movementInfo.y;
- recv_data >> movementInfo.z;
- recv_data >> movementInfo.o;
-
- if(MovementFlags & MOVEMENTFLAG_ONTRANSPORT)
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4);
-
- recv_data >> movementInfo.t_guid;
- recv_data >> movementInfo.t_x;
- recv_data >> movementInfo.t_y;
- recv_data >> movementInfo.t_z;
- recv_data >> movementInfo.t_o;
- recv_data >> movementInfo.t_time;
- }
-
- if(MovementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
-
- recv_data >> movementInfo.s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up
- }
-
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
-
- recv_data >> movementInfo.fallTime; // duration of last jump (when in jump duration from jump begin to now)
-
- if(MovementFlags & MOVEMENTFLAG_JUMPING)
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4);
-
- recv_data >> movementInfo.j_unk; // constant, but different when jumping in water and on land?
- recv_data >> movementInfo.j_sinAngle; // sin of angle between orientation0 and players orientation
- recv_data >> movementInfo.j_cosAngle; // cos of angle between orientation0 and players orientation
- recv_data >> movementInfo.j_xyspeed; // speed of xy movement
- }
-
- if(MovementFlags & MOVEMENTFLAG_SPLINE)
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
-
- recv_data >> movementInfo.u_unk1; // unknown
- }
+ ReadMovementInfo(recv_data, &movementInfo);
/*----------------*/
if(recv_data.size() != recv_data.rpos())
@@ -248,22 +199,8 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
if (!Trinity::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
return;
- // Handle possessed unit movement separately
- Unit* pos_unit = GetPlayer()->GetCharm();
- if (pos_unit && pos_unit->isPossessed()) // can be charmed but not possessed
- {
- HandlePossessedMovement(recv_data, movementInfo, MovementFlags);
- return;
- }
-
- if (GetPlayer()->GetDontMove())
- return;
-
- //Save movement flags
- GetPlayer()->SetUnitMovementFlags(MovementFlags);
-
/* handle special cases */
- if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT)
+ if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
{
// transports size limited
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
@@ -282,9 +219,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
if ((*iter)->GetGUID() == movementInfo.t_guid)
{
- // unmount before boarding
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
-
GetPlayer()->m_transport = (*iter);
(*iter)->AddPassenger(GetPlayer());
break;
@@ -301,13 +235,14 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
movementInfo.t_z = 0.0f;
movementInfo.t_o = 0.0f;
movementInfo.t_time = 0;
+ movementInfo.t_seat = -1;
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
- if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight())
+ if (opcode == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight())
GetPlayer()->HandleFallDamage(movementInfo);
- if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater())
+ if(((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater())
{
// now client not include swimming flag in case jumping under water
GetPlayer()->SetInWater( !GetPlayer()->IsInWater() || GetPlayer()->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) );
@@ -316,100 +251,54 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
/*----------------------*/
/* process position-change */
- recv_data.put<uint32>(5, getMSTime()); // offset flags(4) + unk(1)
- WorldPacket data(recv_data.GetOpcode(), (GetPlayer()->GetPackGUID().size()+recv_data.size()));
- data.append(GetPlayer()->GetPackGUID());
+ Unit *mover = _player->m_mover;
+ recv_data.put<uint32>(6, getMSTime()); // fix time, offset flags(4) + unk(2)
+ WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size()));
+ data.append(_player->m_mover->GetPackGUID()); // use mover guid
data.append(recv_data.contents(), recv_data.size());
GetPlayer()->SendMessageToSet(&data, false);
- GetPlayer()->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
- GetPlayer()->m_movementInfo = movementInfo;
- if (GetPlayer()->m_lastFallTime >= movementInfo.fallTime || GetPlayer()->m_lastFallZ <=movementInfo.z || recv_data.GetOpcode() == MSG_MOVE_FALL_LAND)
- GetPlayer()->SetFallInformation(movementInfo.fallTime, movementInfo.z);
-
- if(GetPlayer()->isMovingOrTurning())
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- if(movementInfo.z < -500.0f)
- GetPlayer()->HandleFallUnderMap();
-}
-
-void WorldSession::HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& movementInfo, uint32& MovementFlags)
-{
- // Whatever the client is controlling, it will send the GUID of the original player.
- // If current player is controlling, it must be handled like the controlled player sent these opcodes
-
- Unit* pos_unit = GetPlayer()->GetCharm();
-
- if (pos_unit->GetTypeId() == TYPEID_PLAYER && ((Player*)pos_unit)->GetDontMove())
- return;
-
- //Save movement flags
- pos_unit->SetUnitMovementFlags(MovementFlags);
-
- // Remove possession if possessed unit enters a transport
- if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT)
+ if(!_player->GetCharmGUID()) // nothing is charmed
{
- GetPlayer()->RemovePossess(true);
- return;
+ _player->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
+ _player->m_movementInfo = movementInfo;
+ _player->SetUnitMovementFlags(movementInfo.flags);
}
-
- recv_data.put<uint32>(5, getMSTime());
- WorldPacket data(recv_data.GetOpcode(), pos_unit->GetPackGUID().size()+recv_data.size());
- data.append(pos_unit->GetPackGUID());
- data.append(recv_data.contents(), recv_data.size());
- // Send the packet to self but not to the possessed player; for creatures the first bool is irrelevant
- pos_unit->SendMessageToSet(&data, true, false);
-
- // Possessed is a player
- if (pos_unit->GetTypeId() == TYPEID_PLAYER)
+ else
{
- Player* plr = (Player*)pos_unit;
-
- if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND)
- plr->HandleFallDamage(movementInfo);
-
- if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != plr->IsInWater())
+ if(mover->GetTypeId() != TYPEID_PLAYER) // unit, creature, pet, vehicle...
{
- // Now client not include swimming flag in case jumping under water
- plr->SetInWater( !plr->IsInWater() || plr->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) );
+ if(Map *map = mover->GetMap())
+ map->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
+ mover->SetUnitMovementFlags(movementInfo.flags);
}
-
- plr->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o, false);
- plr->m_movementInfo = movementInfo;
-
- if(plr->isMovingOrTurning())
- plr->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- if(movementInfo.z < -500.0f)
+ else // player
{
- GetPlayer()->RemovePossess(false);
- plr->HandleFallUnderMap();
+ ((Player*)mover)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
+ ((Player*)mover)->m_movementInfo = movementInfo;
+ ((Player*)mover)->SetUnitMovementFlags(movementInfo.flags);
}
- }
- else // Possessed unit is a creature
- {
- Map* map = MapManager::Instance().GetMap(pos_unit->GetMapId(), pos_unit);
- map->CreatureRelocation((Creature*)pos_unit, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
}
+
+ if (GetPlayer()->m_lastFallTime >= movementInfo.fallTime || GetPlayer()->m_lastFallZ <=movementInfo.z || recv_data.GetOpcode() == MSG_MOVE_FALL_LAND)
+ GetPlayer()->SetFallInformation(movementInfo.fallTime, movementInfo.z);
+
+ if(GetPlayer()->isMovingOrTurning())
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ if(movementInfo.z < -500.0f)
+ GetPlayer()->HandleFallUnderMap();
}
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
{
- CHECK_PACKET_SIZE(recv_data, 8+4+4+1+4+4+4+4+4);
+ sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode());
+
+ CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4);
/* extract packet */
uint64 guid;
- uint8 unkB;
- uint32 unk1, flags, time, fallTime;
- float x, y, z, orientation;
-
- uint64 t_GUID;
- float t_x, t_y, t_z, t_o;
- uint32 t_time;
- float s_pitch;
- float j_unk1, j_sinAngle, j_cosAngle, j_xyspeed;
- float u_unk1;
+ uint32 unk1;
float newspeed;
recv_data >> guid;
@@ -420,47 +309,10 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
// continue parse packet
- recv_data >> unk1;
- recv_data >> flags >> unkB >> time;
- recv_data >> x >> y >> z >> orientation;
- if (flags & MOVEMENTFLAG_ONTRANSPORT)
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4);
-
- recv_data >> t_GUID;
- recv_data >> t_x >> t_y >> t_z >> t_o >> t_time;
- }
- if (flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
-
- recv_data >> s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up
- }
-
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
-
- recv_data >> fallTime; // duration of last jump (when in jump duration from jump begin to now)
-
- if ((flags & MOVEMENTFLAG_JUMPING) || (flags & MOVEMENTFLAG_FALLING))
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4);
-
- recv_data >> j_unk1; // ?constant, but different when jumping in water and on land?
- recv_data >> j_sinAngle >> j_cosAngle; // sin + cos of angle between orientation0 and players orientation
- recv_data >> j_xyspeed; // speed of xy movement
- }
-
- if(flags & MOVEMENTFLAG_SPLINE)
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
+ recv_data >> unk1; // counter or moveEvent
- recv_data >> u_unk1; // unknown
- }
+ MovementInfo movementInfo;
+ ReadMovementInfo(recv_data, &movementInfo);
// recheck
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
@@ -473,7 +325,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
UnitMoveType move_type;
UnitMoveType force_move_type;
- static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack" };
+ static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" };
uint16 opcode = recv_data.GetOpcode();
switch(opcode)
@@ -486,6 +338,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break;
case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break;
case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break;
+ case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break;
default:
sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode);
return;
@@ -520,20 +373,61 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: Recvd CMSG_SET_ACTIVE_MOVER");
+ recv_data.hexlike();
- CHECK_PACKET_SIZE(recv_data,8);
+ CHECK_PACKET_SIZE(recv_data, 8);
uint64 guid;
recv_data >> guid;
- WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement
- data << uint32(0x00000000); // on blizz it increments periodically
- SendPacket(&data);
+ if(_player->m_mover->GetGUID() != guid)
+ {
+ sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " I64FMT " and should be " I64FMT, _player->m_mover->GetGUID(), guid);
+ return;
+ }
}
-void WorldSession::HandleNotActiveMoverOpcode(WorldPacket& /*recv_data*/)
+void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER");
+ recv_data.hexlike();
+
+ CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8);
+
+ uint64 old_mover_guid;
+ recv_data >> old_mover_guid;
+
+ if(_player->m_mover->GetGUID() == old_mover_guid)
+ {
+ sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " I64FMT, _player->m_mover->GetGUID(), _player->GetGUID(), old_mover_guid);
+ return;
+ }
+
+ MovementInfo mi;
+ ReadMovementInfo(recv_data, &mi);
+ _player->m_movementInfo = mi;
+}
+
+void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE");
+ recv_data.hexlike();
+
+ uint64 vehicleGUID = _player->GetCharmGUID();
+
+ if(!vehicleGUID) // something wrong here...
+ return;
+
+ MovementInfo mi;
+ ReadMovementInfo(recv_data, &mi);
+ _player->m_movementInfo = mi;
+
+ // using charm guid, because we don't have vehicle guid...
+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID))
+ {
+ _player->ExitVehicle(vehicle);
+ vehicle->Dismiss();
+ }
}
void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/)
diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp
index fd23991392a..fda02c08977 100644
--- a/src/game/NPCHandler.cpp
+++ b/src/game/NPCHandler.cpp
@@ -166,17 +166,17 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle )
{
TrainerSpell const* tSpell = *itr;
- if(!_player->IsSpellFitByClassAndRace(tSpell->spell))
+ if(!_player->IsSpellFitByClassAndRace(tSpell->learned_spell))
continue;
++count;
- bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell);
+ bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->learned_spell);
- SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell);
+ SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->learned_spell);
uint32 req_spell = spellmgr.GetSpellRequired(tSpell->spell);
- data << uint32(tSpell->spell);
+ data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case)
data << uint8(_player->GetTrainerSpellState(tSpell));
data << uint32(floor(tSpell->spellcost * fDiscountMod));
@@ -241,6 +241,8 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
if(_player->GetMoney() < nSpellCost )
return;
+ _player->ModifyMoney( -int32(nSpellCost) );
+
WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer
data << uint64(guid) << uint32(0xB3);
SendPacket(&data);
@@ -249,13 +251,15 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
data << uint64(_player->GetGUID()) << uint32(0x016A);
SendPacket(&data);
- _player->ModifyMoney( -int32(nSpellCost) );
-
- // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation
- _player->learnSpell(trainer_spell->spell);
+ // learn explicitly or cast explicitly
+ if(trainer_spell->IsCastable ())
+ //FIXME: prof. spell entry in trainer list not marked gray until list re-open.
+ _player->CastSpell(_player,trainer_spell->spell,true);
+ else
+ _player->learnSpell(spellId,false);
data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
- data << uint64(guid) << uint32(spellId);
+ data << uint64(guid) << uint32(trainer_spell->spell);
SendPacket(&data);
}
@@ -528,13 +532,12 @@ void WorldSession::SendStablePet(uint64 guid )
data << uint32(pet->GetEntry());
data << uint32(pet->getLevel());
data << pet->GetName(); // petname
- data << uint32(pet->GetLoyaltyLevel()); // loyalty
- data << uint8(0x01); // client slot 1 == current pet (0)
+ data << uint8(0x01); // flags?, client slot 1 == current pet (0)
++num;
}
- // 0 1 2 3 4 5 6
- QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, loyalty, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow());
+ // 0 1 2 3 4 5
+ QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow());
if(result)
{
@@ -545,8 +548,7 @@ void WorldSession::SendStablePet(uint64 guid )
data << uint32(fields[2].GetUInt32()); // petnumber
data << uint32(fields[3].GetUInt32()); // creature entry
data << uint32(fields[4].GetUInt32()); // level
- data << fields[6].GetString(); // name
- data << uint32(fields[5].GetUInt32()); // loyalty
+ data << fields[5].GetString(); // name
data << uint8(fields[1].GetUInt32()+1); // slot
++num;
@@ -596,7 +598,7 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data )
uint32 free_slot = 1;
- QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3 ORDER BY slot ",_player->GetGUIDLow());
+ QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5 ORDER BY slot ",_player->GetGUIDLow());
if(result)
{
do
@@ -660,7 +662,7 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
Pet *newpet = NULL;
- QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow(),petnumber);
+ QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow(),petnumber);
if(result)
{
Field *fields = result->Fetch();
@@ -704,7 +706,7 @@ void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data )
WorldPacket data(SMSG_STABLE_RESULT, 200);
- if(GetPlayer()->m_stableSlots < 2) // max slots amount = 2
+ if(GetPlayer()->m_stableSlots < 4) // max slots amount = 4
{
StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
if(_player->GetMoney() >= SlotPrice->Price)
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index 7599245eaac..0a9d37a2754 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -58,8 +58,9 @@ uint32 GuidHigh2TypeId(uint32 guid_hi)
case HIGHGUID_DYNAMICOBJECT:return TYPEID_DYNAMICOBJECT;
case HIGHGUID_CORPSE: return TYPEID_CORPSE;
case HIGHGUID_MO_TRANSPORT: return TYPEID_GAMEOBJECT;
+ case HIGHGUID_VEHICLE: return TYPEID_UNIT;
}
- return 10; // unknown
+ return MAX_TYPEID; // unknown
}
Object::Object( )
@@ -146,15 +147,9 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c
/** lower flag1 **/
if(target == this) // building packet for oneself
- {
flags |= UPDATEFLAG_SELF;
- /*** temporary reverted - until real source of stack corruption will not found
- updatetype = UPDATETYPE_CREATE_OBJECT2;
- ****/
- }
-
- if(flags & UPDATEFLAG_HASPOSITION)
+ if(flags & UPDATEFLAG_HAS_POSITION)
{
// UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
if(isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER))
@@ -180,6 +175,12 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c
break;
}
}
+
+ if(isType(TYPEMASK_UNIT))
+ {
+ if(((Unit*)this)->getVictim())
+ flags |= UPDATEFLAG_HAS_TARGET;
+ }
}
//sLog.outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2);
@@ -251,11 +252,18 @@ void Object::DestroyForPlayer(Player *target) const
WorldPacket data(SMSG_DESTROY_OBJECT, 8);
data << GetGUID();
+ data << uint8(0); // WotLK (bool)
target->GetSession()->SendPacket( &data );
}
-void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 ) const
+void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2) const
{
+ uint16 unk_flags = ((GetTypeId() == TYPEID_PLAYER) ? ((Player*)this)->m_movementInfo.unk1 : 0);
+
+ if(GetTypeId() == TYPEID_UNIT)
+ if(((Creature*)this)->isVehicle())
+ unk_flags |= 0x20; // always allow pitch
+
*data << (uint8)flags; // update flags
// 0x20
@@ -292,12 +300,12 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
}
*data << uint32(flags2); // movement flags
- *data << uint8(0); // unk 2.3.0
+ *data << uint16(unk_flags); // unknown 2.3.0
*data << uint32(getMSTime()); // time (in milliseconds)
}
// 0x40
- if (flags & UPDATEFLAG_HASPOSITION)
+ if (flags & UPDATEFLAG_HAS_POSITION)
{
// 0x02
if(flags & UPDATEFLAG_TRANSPORT && ((GameObject*)this)->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT)
@@ -330,12 +338,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
*data << (float)((Player*)this)->GetTransOffsetZ();
*data << (float)((Player*)this)->GetTransOffsetO();
*data << (uint32)((Player*)this)->GetTransTime();
+ *data << (int8)((Player*)this)->GetTransSeat();
}
//TrinIty currently not have support for other than player on transport
}
// 0x02200000
- if(flags2 & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))
+ if((flags2 & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (unk_flags & 0x20))
{
if(GetTypeId() == TYPEID_PLAYER)
*data << (float)((Player*)this)->m_movementInfo.s_pitch;
@@ -384,6 +393,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
*data << ((Unit*)this)->GetSpeed( MOVE_FLIGHT );
*data << ((Unit*)this)->GetSpeed( MOVE_FLIGHT_BACK );
*data << ((Unit*)this)->GetSpeed( MOVE_TURN_RATE );
+ *data << ((Unit*)this)->GetSpeed( MOVE_PITCH_RATE );
// 0x08000000
if(flags2 & MOVEMENTFLAG_SPLINE2)
@@ -448,6 +458,8 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
*data << path.GetNodes()[i].z;
}
+ *data << uint8(0); // added in 3.0.8
+
/*for(uint32 i = 0; i < poscount; i++)
{
// path points
@@ -485,7 +497,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
break;
case TYPEID_PLAYER:
if(flags & UPDATEFLAG_SELF)
- *data << uint32(0x00000015); // unk, can be 0x15 or 0x22
+ *data << uint32(0x0000002F); // unk, can be 0x15 or 0x22
else
*data << uint32(0x00000008); // unk, can be 0x7 or 0x8
break;
@@ -508,6 +520,15 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
case TYPEID_CORPSE:
*data << uint32(GetGUIDHigh()); // GetGUIDHigh()
break;
+ case TYPEID_UNIT:
+ *data << uint32(0x0000000B); // unk, can be 0xB or 0xC
+ break;
+ case TYPEID_PLAYER:
+ if(flags & UPDATEFLAG_SELF)
+ *data << uint32(0x0000002F); // unk, can be 0x15 or 0x22
+ else
+ *data << uint32(0x00000008); // unk, can be 0x7 or 0x8
+ break;
default:
*data << uint32(0x00000000); // unk
break;
@@ -515,9 +536,12 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
}
// 0x4
- if(flags & UPDATEFLAG_FULLGUID)
+ if(flags & UPDATEFLAG_HAS_TARGET) // packed guid (current target guid)
{
- *data << uint8(0); // packed guid (probably target guid)
+ if(Unit *victim = ((Unit*)this)->getVictim())
+ data->append(victim->GetPackGUID());
+ else
+ *data << uint8(0);
}
// 0x2
@@ -525,6 +549,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
{
*data << uint32(getMSTime()); // ms time
}
+
+ // 0x80
+ if(flags & UPDATEFLAG_VEHICLE) // unused for now
+ {
+ *data << uint32(((Vehicle*)this)->GetVehicleId()); // vehicle id
+ *data << float(0); // facing adjustment
+ }
}
void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const
@@ -540,10 +571,10 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
if ( ((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster())
{
IsActivateToQuest = true;
- updateMask->SetBit(GAMEOBJECT_DYN_FLAGS);
+ updateMask->SetBit(GAMEOBJECT_DYNAMIC);
}
- if (GetUInt32Value(GAMEOBJECT_ARTKIT))
- updateMask->SetBit(GAMEOBJECT_ARTKIT);
+ if (((GameObject*)this)->GetGoArtKit())
+ updateMask->SetBit(GAMEOBJECT_BYTES_1);
}
}
else //case UPDATETYPE_VALUES
@@ -554,8 +585,8 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
{
IsActivateToQuest = true;
}
- updateMask->SetBit(GAMEOBJECT_DYN_FLAGS);
- updateMask->SetBit(GAMEOBJECT_ANIMPROGRESS);
+ updateMask->SetBit(GAMEOBJECT_DYNAMIC);
+ updateMask->SetBit(GAMEOBJECT_BYTES_1);
}
}
@@ -572,7 +603,6 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
if( updateMask->GetBit( index ) )
{
// remove custom flag before send
-
if( index == UNIT_NPC_FLAGS )
*data << uint32(m_uint32Values[ index ] & ~(UNIT_NPC_FLAG_GUARD + UNIT_NPC_FLAG_OUTDOORPVP));
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
@@ -673,7 +703,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
if( updateMask->GetBit( index ) )
{
// send in current format (float as float, uint32 as uint32)
- if ( index == GAMEOBJECT_DYN_FLAGS )
+ if ( index == GAMEOBJECT_DYNAMIC )
{
if(IsActivateToQuest )
{
@@ -1054,6 +1084,9 @@ bool Object::PrintIndexError(uint32 index, bool set) const
}
WorldObject::WorldObject()
+ : m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL),
+ m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f),
+ mSemaphoreTeleport(false)
{
m_positionX = 0.0f;
m_positionY = 0.0f;
@@ -1106,26 +1139,27 @@ void WorldObject::RemoveFromWorld()
Object::RemoveFromWorld();
}
-void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid )
+void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid, uint32 phaseMask )
{
Object::_Create(guidlow, 0, guidhigh);
m_mapId = mapid;
+ m_phaseMask = phaseMask;
}
uint32 WorldObject::GetZoneId() const
{
- return MapManager::Instance().GetBaseMap(m_mapId)->GetZoneId(m_positionX,m_positionY);
+ return MapManager::Instance().GetBaseMap(m_mapId)->GetZoneId(m_positionX,m_positionY,m_positionZ);
}
uint32 WorldObject::GetAreaId() const
{
- return MapManager::Instance().GetBaseMap(m_mapId)->GetAreaId(m_positionX,m_positionY);
+ return MapManager::Instance().GetBaseMap(m_mapId)->GetAreaId(m_positionX,m_positionY,m_positionZ);
}
InstanceData* WorldObject::GetInstanceData()
{
- Map *map = MapManager::Instance().GetMap(m_mapId, this);
+ Map *map = GetMap();
return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceData() : NULL;
}
@@ -1356,7 +1390,7 @@ namespace Trinity
{
public:
MessageChatLocaleCacheDo(WorldObject const& obj, ChatMsg msgtype, int32 textId, uint32 language, uint64 targetGUID, float dist)
- : i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language),
+ : i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language),
i_targetGUID(targetGUID), i_dist(dist)
{
}
@@ -1417,9 +1451,9 @@ void WorldObject::MonsterSay(int32 textId, uint32 language, uint64 TargetGuid)
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
- Trinity::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY));
- Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo> say_worker(say_do);
- TypeContainerVisitor<Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker);
+ MaNGOS::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY));
+ MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo> say_worker(this,say_do);
+ TypeContainerVisitor<MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
}
@@ -1432,9 +1466,9 @@ void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid)
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
- Trinity::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL));
- Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo> say_worker(say_do);
- TypeContainerVisitor<Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker);
+ MaNGOS::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL));
+ MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo> say_worker(this,say_do);
+ TypeContainerVisitor<MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
}
@@ -1447,9 +1481,9 @@ void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossE
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
- Trinity::MessageChatLocaleCacheDo say_do(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId,LANG_UNIVERSAL,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
- Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo> say_worker(say_do);
- TypeContainerVisitor<Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker);
+ MaNGOS::MessageChatLocaleCacheDo say_do(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId,LANG_UNIVERSAL,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
+ MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo> say_worker(this,say_do);
+ TypeContainerVisitor<MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
}
@@ -1501,7 +1535,7 @@ void WorldObject::BuildHeartBeatMsg(WorldPacket *data) const
data->Initialize(MSG_MOVE_HEARTBEAT, 32);
data->append(GetPackGUID());
*data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags
- *data << uint8(0); // 2.3.0
+ *data << uint16(0); // 2.3.0
*data << getMSTime(); // time
*data << m_positionX;
*data << m_positionY;
@@ -1520,7 +1554,7 @@ void WorldObject::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float
data->append(GetPackGUID());
*data << uint32(0); // this value increments every time
*data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags
- *data << uint8(0); // 2.3.0
+ *data << uint16(0); // 2.3.0
*data << getMSTime(); // time
*data << x;
*data << y;
@@ -1577,7 +1611,7 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa
if (GetTypeId()==TYPEID_PLAYER)
team = ((Player*)this)->GetTeam();
- if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), GetMap(), id, team))
+ if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), GetMap(), GetPhaseMask(), id, team))
{
delete pCreature;
return NULL;
@@ -1616,17 +1650,16 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float
{
if(!IsInWorld())
return NULL;
- Map * map = GetMap();
- if(!map)
- return NULL;
+
GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry);
if(!goinfo)
{
sLog.outErrorDb("Gameobject template %u not found in database!", entry);
return NULL;
}
+ Map *map = GetMap();
GameObject *go = new GameObject();
- if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry,map,x,y,z,ang,rotation0,rotation1,rotation2,rotation3,100,1))
+ if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, map, GetPhaseMask(), x,y,z,ang,rotation0,rotation1,rotation2,rotation3,100,1))
return NULL;
go->SetRespawnTime(respawnTime);
if(GetTypeId()==TYPEID_PLAYER || GetTypeId()==TYPEID_UNIT) //not sure how to handle this
@@ -1685,4 +1718,10 @@ void WorldObject::GetGroundPoint(float &x, float &y, float &z, float dist, float
UpdateGroundPositionZ(x, y, z);
}
+void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
+{
+ m_phaseMask = newPhaseMask;
+ if(update && IsInWorld())
+ ObjectAccessor::UpdateObjectVisibility(this);
+}
diff --git a/src/game/Object.h b/src/game/Object.h
index d4d9759ed1b..2a4ffb7cbb0 100644
--- a/src/game/Object.h
+++ b/src/game/Object.h
@@ -56,7 +56,8 @@ enum TypeMask
TYPEMASK_DYNAMICOBJECT = 0x0040,
TYPEMASK_CORPSE = 0x0080,
TYPEMASK_AIGROUP = 0x0100,
- TYPEMASK_AREATRIGGER = 0x0200
+ TYPEMASK_AREATRIGGER = 0x0200,
+ TYPEMASK_FARSIGHTOBJ = TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT
};
enum TypeID
@@ -72,6 +73,7 @@ enum TypeID
TYPEID_AIGROUP = 8,
TYPEID_AREATRIGGER = 9
};
+#define MAX_TYPEID 10
uint32 GuidHigh2TypeId(uint32 guid_hi);
@@ -87,6 +89,12 @@ enum TempSummonType
TEMPSUMMON_MANUAL_DESPAWN = 8 // despawns when UnSummon() is called
};
+enum PhaseMasks
+{
+ PHASEMASK_NORMAL = 0x00000001,
+ PHASEMASK_ANYWHERE = 0xFFFFFFFF
+};
+
class WorldPacket;
class UpdateData;
class ByteBuffer;
@@ -358,7 +366,7 @@ class TRINITY_DLL_SPEC WorldObject : public Object
virtual void Update ( uint32 /*time_diff*/ ) { }
- void _Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid );
+ void _Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid, uint32 phaseMask);
void Relocate(float x, float y, float z, float orientation)
{
@@ -420,9 +428,13 @@ class TRINITY_DLL_SPEC WorldObject : public Object
void GetRandomPoint( float x, float y, float z, float distance, float &rand_x, float &rand_y, float &rand_z ) const;
void SetMapId(uint32 newMap) { m_mapId = newMap; }
-
uint32 GetMapId() const { return m_mapId; }
+ virtual void SetPhaseMask(uint32 newPhaseMask, bool update);
+ uint32 GetPhaseMask() const { return m_phaseMask; }
+ bool InSamePhase(WorldObject const* obj) const { return InSamePhase(obj->GetPhaseMask()); }
+ bool InSamePhase(uint32 phasemask) const { return GetPhaseMask()==0 && phasemask==0 || (GetPhaseMask() & phasemask); }
+
uint32 GetZoneId() const;
uint32 GetAreaId() const;
@@ -439,7 +451,11 @@ class TRINITY_DLL_SPEC WorldObject : public Object
float GetDistance2d(const WorldObject* obj) const;
float GetDistance2d(const float x, const float y) const;
float GetDistanceZ(const WorldObject* obj) const;
- bool IsInMap(const WorldObject* obj) const { return GetMapId()==obj->GetMapId() && GetInstanceId()==obj->GetInstanceId(); }
+ bool IsInMap(const WorldObject* obj) const
+ {
+ return IsInWorld() && obj->IsInWorld() && GetMapId()==obj->GetMapId() &&
+ GetInstanceId()==obj->GetInstanceId() && InSamePhase(obj);
+ }
bool IsWithinDistInMap(const WorldObject* obj, const float dist2compare, const bool is3D = true) const;
bool IsWithinLOS(const float x, const float y, const float z ) const;
bool IsWithinLOSInMap(const WorldObject* obj) const;
@@ -499,7 +515,9 @@ class TRINITY_DLL_SPEC WorldObject : public Object
bool m_isActive;
private:
- uint32 m_mapId;
+ uint32 m_mapId; // object at map with map_id
+ uint32 m_InstanceId; // in map copy with instance id
+ uint32 m_phaseMask; // in area phase state
float m_positionX;
float m_positionY;
@@ -507,7 +525,5 @@ class TRINITY_DLL_SPEC WorldObject : public Object
float m_orientation;
bool mSemaphoreTeleport;
-
- uint32 m_InstanceId;
};
#endif
diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp
index d2b0878c595..e7006b38dce 100644
--- a/src/game/ObjectAccessor.cpp
+++ b/src/game/ObjectAccessor.cpp
@@ -38,6 +38,7 @@
#include "Opcodes.h"
#include "ObjectDefines.h"
#include "MapInstanced.h"
+#include "World.h"
#include <cmath>
@@ -129,11 +130,14 @@ ObjectAccessor::GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint3
}
Creature*
-ObjectAccessor::GetCreatureOrPet(WorldObject const &u, uint64 guid)
+ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const &u, uint64 guid)
{
if(Creature *unit = GetPet(guid))
return unit;
+ if(Creature *unit = GetVehicle(guid))
+ return unit;
+
return GetCreature(u, guid);
}
@@ -162,18 +166,23 @@ ObjectAccessor::GetUnit(WorldObject const &u, uint64 guid)
if(IS_PLAYER_GUID(guid))
return FindPlayer(guid);
- return GetCreatureOrPet(u, guid);
+ return GetCreatureOrPetOrVehicle(u, guid);
}
Corpse*
ObjectAccessor::GetCorpse(WorldObject const &u, uint64 guid)
{
Corpse * ret = GetObjectInWorld(guid, (Corpse*)NULL);
- if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL;
+ if(!ret)
+ return NULL;
+ if(ret->GetMapId() != u.GetMapId())
+ return NULL;
+ if(ret->GetInstanceId() != u.GetInstanceId())
+ return NULL;
return ret;
}
-Object* ObjectAccessor::GetObjectByTypeMask(Player const &p, uint64 guid, uint32 typemask)
+Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const &p, uint64 guid, uint32 typemask)
{
Object *obj = NULL;
@@ -185,7 +194,7 @@ Object* ObjectAccessor::GetObjectByTypeMask(Player const &p, uint64 guid, uint32
if(typemask & TYPEMASK_UNIT)
{
- obj = GetCreatureOrPet(p,guid);
+ obj = GetCreatureOrPetOrVehicle(p,guid);
if(obj) return obj;
}
@@ -201,9 +210,9 @@ Object* ObjectAccessor::GetObjectByTypeMask(Player const &p, uint64 guid, uint32
if(obj) return obj;
}
- if(typemask & TYPEMASK_ITEM)
+ if(typemask & TYPEMASK_ITEM && p.GetTypeId() == TYPEID_PLAYER)
{
- obj = p.GetItemByGuid( guid );
+ obj = ((Player const &)p).GetItemByGuid( guid );
if(obj) return obj;
}
@@ -214,15 +223,25 @@ GameObject*
ObjectAccessor::GetGameObject(WorldObject const &u, uint64 guid)
{
GameObject * ret = GetObjectInWorld(guid, (GameObject*)NULL);
- if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL;
+ if(!ret)
+ return NULL;
+ if(ret->GetMapId() != u.GetMapId())
+ return NULL;
+ if(ret->GetInstanceId() != u.GetInstanceId())
+ return NULL;
return ret;
}
DynamicObject*
-ObjectAccessor::GetDynamicObject(Unit const &u, uint64 guid)
+ObjectAccessor::GetDynamicObject(WorldObject const &u, uint64 guid)
{
DynamicObject * ret = GetObjectInWorld(guid, (DynamicObject*)NULL);
- if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL;
+ if(!ret)
+ return NULL;
+ if(ret->GetMapId() != u.GetMapId())
+ return NULL;
+ if(ret->GetInstanceId() != u.GetInstanceId())
+ return NULL;
return ret;
}
@@ -273,22 +292,6 @@ ObjectAccessor::UpdateObject(Object* obj, Player* exceptPlayer)
}
void
-ObjectAccessor::AddUpdateObject(Object *obj)
-{
- Guard guard(i_updateGuard);
- i_objects.insert(obj);
-}
-
-void
-ObjectAccessor::RemoveUpdateObject(Object *obj)
-{
- Guard guard(i_updateGuard);
- std::set<Object *>::iterator iter = i_objects.find(obj);
- if( iter != i_objects.end() )
- i_objects.erase( iter );
-}
-
-void
ObjectAccessor::_buildUpdateObject(Object *obj, UpdateDataMapType &update_players)
{
bool build_for_all = true;
@@ -351,6 +354,12 @@ ObjectAccessor::GetPet(uint64 guid)
return GetObjectInWorld(guid, (Pet*)NULL);
}
+Vehicle*
+ObjectAccessor::GetVehicle(uint64 guid)
+{
+ return GetObjectInWorld(guid, (Vehicle*)NULL);
+}
+
Corpse*
ObjectAccessor::GetCorpseForPlayerGUID(uint64 guid)
{
@@ -423,7 +432,7 @@ ObjectAccessor::AddCorpsesToGrid(GridPair const& gridpair,GridType& grid,Map* ma
}
Corpse*
-ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid)
+ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia)
{
Corpse *corpse = GetCorpseForPlayerGUID(player_guid);
if(!corpse)
@@ -449,7 +458,10 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid)
Corpse *bones = NULL;
// create the bones only if the map and the grid is loaded at the corpse's location
- if(map && !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY()))
+ // ignore bones creating option in case insignia
+ if (map && (insignia ||
+ (map->IsBattleGroundOrArena() ? sWorld.getConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld.getConfig(CONFIG_DEATH_BONES_WORLD))) &&
+ !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY()))
{
// Create bones, don't change Corpse
bones = new Corpse;
@@ -465,6 +477,7 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid)
bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation());
bones->SetMapId(corpse->GetMapId());
bones->SetInstanceId(corpse->GetInstanceId());
+ bones->SetPhaseMask(corpse->GetPhaseMask(),false);
bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES);
bones->SetUInt64Value(CORPSE_FIELD_OWNER, 0);
@@ -602,6 +615,7 @@ template <class T> ZThread::FastMutex HashMapHolder<T>::i_lock;
template class HashMapHolder<Player>;
template class HashMapHolder<Pet>;
+template class HashMapHolder<Vehicle>;
template class HashMapHolder<GameObject>;
template class HashMapHolder<DynamicObject>;
template class HashMapHolder<Creature>;
@@ -609,6 +623,7 @@ template class HashMapHolder<Corpse>;
template Player* ObjectAccessor::GetObjectInWorld<Player>(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/);
template Pet* ObjectAccessor::GetObjectInWorld<Pet>(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/);
+template Vehicle* ObjectAccessor::GetObjectInWorld<Vehicle>(uint32 mapid, float x, float y, uint64 guid, Vehicle* /*fake*/);
template Creature* ObjectAccessor::GetObjectInWorld<Creature>(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/);
template Corpse* ObjectAccessor::GetObjectInWorld<Corpse>(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/);
template GameObject* ObjectAccessor::GetObjectInWorld<GameObject>(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/);
diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h
index 879c73288cc..350bc62ebad 100644
--- a/src/game/ObjectAccessor.h
+++ b/src/game/ObjectAccessor.h
@@ -33,6 +33,7 @@
#include "GridDefines.h"
#include "Object.h"
#include "Player.h"
+#include "Vehicle.h"
#include <set>
@@ -58,9 +59,7 @@ class HashMapHolder
static void Remove(T* o)
{
Guard guard(i_lock);
- typename MapType::iterator itr = m_objectMap.find(o->GetGUID());
- if (itr != m_objectMap.end())
- m_objectMap.erase(itr);
+ m_objectMap.erase(o->GetGUID());
}
static T* Find(uint64 guid)
@@ -139,17 +138,18 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor
else return NULL;
}
- static Object* GetObjectByTypeMask(Player const &, uint64, uint32 typemask);
+ static Object* GetObjectByTypeMask(WorldObject const &, uint64, uint32 typemask);
static Creature* GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint32 npcflagmask);
static Creature* GetCreature(WorldObject const &, uint64);
- static Creature* GetCreatureOrPet(WorldObject const &, uint64);
+ static Creature* GetCreatureOrPetOrVehicle(WorldObject const &, uint64);
static Unit* GetUnit(WorldObject const &, uint64);
static Pet* GetPet(Unit const &, uint64 guid) { return GetPet(guid); }
static Player* GetPlayer(Unit const &, uint64 guid) { return FindPlayer(guid); }
static GameObject* GetGameObject(WorldObject const &, uint64);
- static DynamicObject* GetDynamicObject(Unit const &, uint64);
+ static DynamicObject* GetDynamicObject(WorldObject const &, uint64);
static Corpse* GetCorpse(WorldObject const &u, uint64 guid);
static Pet* GetPet(uint64 guid);
+ static Vehicle* GetVehicle(uint64 guid);
static Player* FindPlayer(uint64);
Player* FindPlayerByName(const char *name) ;
@@ -174,16 +174,22 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor
HashMapHolder<Player>::Remove(pl);
Guard guard(i_updateGuard);
-
- std::set<Object *>::iterator iter2 = std::find(i_objects.begin(), i_objects.end(), (Object *)pl);
- if( iter2 != i_objects.end() )
- i_objects.erase(iter2);
+ i_objects.erase((Object *)pl);
}
void SaveAllPlayers();
- void AddUpdateObject(Object *obj);
- void RemoveUpdateObject(Object *obj);
+ void AddUpdateObject(Object *obj)
+ {
+ Guard guard(i_updateGuard);
+ i_objects.insert(obj);
+ }
+
+ void RemoveUpdateObject(Object *obj)
+ {
+ Guard guard(i_updateGuard);
+ i_objects.erase( obj );
+ }
void Update(uint32 diff);
void UpdatePlayers(uint32 diff);
@@ -192,7 +198,7 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor
void RemoveCorpse(Corpse *corpse);
void AddCorpse(Corpse* corpse);
void AddCorpsesToGrid(GridPair const& gridpair,GridType& grid,Map* map);
- Corpse* ConvertCorpseForPlayer(uint64 player_guid);
+ Corpse* ConvertCorpseForPlayer(uint64 player_guid, bool insignia = false);
static void UpdateObject(Object* obj, Player* exceptPlayer);
static void _buildUpdateObject(Object* obj, UpdateDataMapType &);
diff --git a/src/game/ObjectDefines.h b/src/game/ObjectDefines.h
index 88840ebd251..06072cb9917 100644
--- a/src/game/ObjectDefines.h
+++ b/src/game/ObjectDefines.h
@@ -41,6 +41,7 @@ enum HighGuid
HIGHGUID_TRANSPORT = 0xF120, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT)
HIGHGUID_UNIT = 0xF130, // blizz F130
HIGHGUID_PET = 0xF140, // blizz F140
+ HIGHGUID_VEHICLE = 0xF150, // blizz F550
HIGHGUID_DYNAMICOBJECT = 0xF100, // blizz F100
HIGHGUID_CORPSE = 0xF101, // blizz F100
HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
@@ -50,6 +51,7 @@ enum HighGuid
#define IS_CREATURE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_UNIT )
#define IS_PET_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PET )
+#define IS_VEHICLE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_VEHICLE )
#define IS_CREATURE_OR_PET_GUID(Guid)( IS_CREATURE_GUID(Guid) || IS_PET_GUID(Guid) )
#define IS_PLAYER_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PLAYER && Guid!=0 )
#define IS_UNIT_GUID(Guid) ( IS_CREATURE_OR_PET_GUID(Guid) || IS_PLAYER_GUID(Guid) )
@@ -87,6 +89,7 @@ inline bool IsGuidHaveEnPart(uint64 const& guid)
case HIGHGUID_TRANSPORT:
case HIGHGUID_UNIT:
case HIGHGUID_PET:
+ case HIGHGUID_VEHICLE:
case HIGHGUID_MO_TRANSPORT:
default:
return true;
@@ -106,6 +109,7 @@ inline char const* GetLogNameForGuid(uint64 guid)
case HIGHGUID_TRANSPORT: return "transport";
case HIGHGUID_UNIT: return "creature";
case HIGHGUID_PET: return "pet";
+ case HIGHGUID_VEHICLE: return "vehicle";
case HIGHGUID_DYNAMICOBJECT:return "dynobject";
case HIGHGUID_CORPSE: return "corpse";
case HIGHGUID_MO_TRANSPORT: return "mo_transport";
diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp
index 0e2b6ae329d..e58ef1d7de5 100644
--- a/src/game/ObjectGridLoader.cpp
+++ b/src/game/ObjectGridLoader.cpp
@@ -59,7 +59,7 @@ ObjectGridRespawnMover::Visit(CreatureMapType &m)
Creature * c = iter->getSource();
- assert(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets");
+ assert((!c->isPet() || !c->isVehicle()) && "ObjectGridRespawnMover don't must be called for pets");
Cell const& cur_cell = c->GetCurrentCell();
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 6ceb9a08334..c4cdc057815 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -116,6 +116,7 @@ ObjectMgr::ObjectMgr()
m_hiCharGuid = 1;
m_hiCreatureGuid = 1;
m_hiPetGuid = 1;
+ m_hiVehicleGuid = 1;
m_hiItemGuid = 1;
m_hiGoGuid = 1;
m_hiDoGuid = 1;
@@ -842,6 +843,19 @@ void ObjectMgr::LoadCreatureTemplates()
if((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE)
sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u",cInfo->Entry,cInfo->trainer_type);
+ if(cInfo->type && !sCreatureTypeStore.LookupEntry(cInfo->type))
+ {
+ sLog.outErrorDb("Creature (Entry: %u) has invalid creature type (%u) in `type`",cInfo->Entry,cInfo->type);
+ const_cast<CreatureInfo*>(cInfo)->type = CREATURE_TYPE_HUMANOID;
+ }
+
+ // must exist or used hidden but used in data horse case
+ if(cInfo->family && !sCreatureFamilyStore.LookupEntry(cInfo->family) && cInfo->family != CREATURE_FAMILY_HORSE_CUSTOM )
+ {
+ sLog.outErrorDb("Creature (Entry: %u) has invalid creature family (%u) in `family`",cInfo->Entry,cInfo->family);
+ const_cast<CreatureInfo*>(cInfo)->family = 0;
+ }
+
if(cInfo->InhabitType <= 0 || cInfo->InhabitType > INHABIT_ANYWHERE)
{
sLog.outErrorDb("Creature (Entry: %u) has wrong value (%u) in `InhabitType`, creature will not correctly walk/swim/fly",cInfo->Entry,cInfo->InhabitType);
@@ -855,6 +869,15 @@ void ObjectMgr::LoadCreatureTemplates()
sLog.outErrorDb("Creature (Entry: %u) has non-existing PetSpellDataId (%u)", cInfo->Entry, cInfo->PetSpellDataId);
}
+ for(int i = 0; i < CREATURE_MAX_SPELLS; ++i)
+ {
+ if(cInfo->spells[i] && !sSpellStore.LookupEntry(cInfo->spells[i]))
+ {
+ sLog.outErrorDb("Creature (Entry: %u) has non-existing Spell%d (%u), set to 0", cInfo->Entry, i+1,cInfo->spells[i]);
+ const_cast<CreatureInfo*>(cInfo)->spells[i] = 0;
+ }
+ }
+
if(cInfo->MovementType >= MAX_DB_MOTION_TYPE)
{
sLog.outErrorDb("Creature (Entry: %u) has wrong movement generator type (%u), ignore and set to IDLE.",cInfo->Entry,cInfo->MovementType);
@@ -1003,8 +1026,47 @@ void ObjectMgr::LoadEquipmentTemplates()
{
sEquipmentStorage.Load();
+ for(uint32 i=0; i< sEquipmentStorage.MaxEntry; ++i)
+ {
+ EquipmentInfo const* eqInfo = sEquipmentStorage.LookupEntry<EquipmentInfo>(i);
+
+ if(!eqInfo)
+ continue;
+
+ for(uint8 j=0; j<3; j++)
+ {
+ if(!eqInfo->equipentry[j])
+ continue;
+
+ ItemEntry const *dbcitem = sItemStore.LookupEntry(eqInfo->equipentry[j]);
+
+ if(!dbcitem)
+ {
+ sLog.outErrorDb("Unknown item (entry=%u) in creature_equip_template.equipentry%u for entry = %u, forced to 0.", eqInfo->equipentry[j], j+1, i);
+ const_cast<EquipmentInfo*>(eqInfo)->equipentry[j] = 0;
+ continue;
+ }
+
+ if(dbcitem->InventoryType != INVTYPE_WEAPON &&
+ dbcitem->InventoryType != INVTYPE_SHIELD &&
+ dbcitem->InventoryType != INVTYPE_RANGED &&
+ dbcitem->InventoryType != INVTYPE_2HWEAPON &&
+ dbcitem->InventoryType != INVTYPE_WEAPONMAINHAND &&
+ dbcitem->InventoryType != INVTYPE_WEAPONOFFHAND &&
+ dbcitem->InventoryType != INVTYPE_HOLDABLE &&
+ dbcitem->InventoryType != INVTYPE_THROWN &&
+ dbcitem->InventoryType != INVTYPE_RANGEDRIGHT)
+ {
+ sLog.outErrorDb("Item (entry=%u) in creature_equip_template.equipentry%u for entry = %u is not equipable in a hand, forced to 0.", eqInfo->equipentry[j], j+1, i);
+ const_cast<EquipmentInfo*>(eqInfo)->equipentry[j] = 0;
+ }
+ }
+ }
sLog.outString( ">> Loaded %u equipment template", sEquipmentStorage.RecordCount );
sLog.outString();
+
+ // This DBC is currently only used for item templates and creature equipments checks.
+ sItemStore.Clear();
}
CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelid)
@@ -1076,8 +1138,8 @@ void ObjectMgr::LoadCreatures()
QueryResult *result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid,"
// 4 5 6 7 8 9 10 11
"equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint,"
- // 12 13 14 15 16 17
- "curhealth, curmana, DeathState, MovementType, spawnMask, event "
+ // 12 13 14 15 16 17 18
+ "curhealth, curmana, DeathState, MovementType, spawnMask, phaseMask, event "
"FROM creature LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid");
if(!result)
@@ -1125,7 +1187,8 @@ void ObjectMgr::LoadCreatures()
data.is_dead = fields[14].GetBool();
data.movementType = fields[15].GetUInt8();
data.spawnMask = fields[16].GetUInt8();
- int16 gameEvent = fields[17].GetInt16();
+ data.phaseMask = fields[17].GetUInt16();
+ int16 gameEvent = fields[18].GetInt16();
CreatureInfo const* cInfo = GetCreatureTemplate(data.id);
if(!cInfo)
@@ -1183,6 +1246,40 @@ void ObjectMgr::LoadCreatures()
}
}
+ if(data.phaseMask==0)
+ {
+ sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id );
+ data.phaseMask = 1;
+ }
+ else
+ {
+ int count = 0;
+ for(int i=0; i < sizeof(data.phaseMask)*8; ++i)
+ if(data.phaseMask & (1 << i))
+ ++count;
+
+ if(count > 1)
+ {
+ uint32 phaseMask = data.phaseMask & ~PHASEMASK_NORMAL;
+ count = 0;
+ for(int i=0; i < sizeof(phaseMask)*8; ++i)
+ if(phaseMask & (1 << i))
+ ++count;
+
+ if(count > 1)
+ {
+ sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with more single bit set in `phaseMask` (not visible for anyone), set to 1.",guid,data.id );
+ data.phaseMask = phaseMask;
+ }
+ else
+ {
+ sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with more single bit set in `phaseMask` (not visible for anyone), set to %u (possible expected).",guid,data.id,phaseMask);
+ data.phaseMask = 1;
+ }
+
+ }
+ }
+
if (gameEvent==0) // if not this is to be managed by GameEvent System
AddCreatureToGrid(guid, &data);
++count;
@@ -1233,8 +1330,8 @@ void ObjectMgr::LoadGameobjects()
// 0 1 2 3 4 5 6
QueryResult *result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation,"
- // 7 8 9 10 11 12 13 14 15
- "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, event "
+ // 7 8 9 10 11 12 13 14 15 16
+ "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, event "
"FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid");
if(!result)
@@ -1274,7 +1371,8 @@ void ObjectMgr::LoadGameobjects()
data.go_state = fields[13].GetUInt32();
data.ArtKit = 0;
data.spawnMask = fields[14].GetUInt8();
- int16 gameEvent = fields[15].GetInt16();
+ data.phaseMask = fields[15].GetUInt16();
+ int16 gameEvent = fields[16].GetInt16();
GameObjectInfo const* gInfo = GetGameObjectInfo(data.id);
if(!gInfo)
@@ -1283,6 +1381,12 @@ void ObjectMgr::LoadGameobjects()
continue;
}
+ if(data.phaseMask==0)
+ {
+ sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id );
+ data.phaseMask = 1;
+ }
+
if (gameEvent==0) // if not this is to be managed by GameEvent System
AddGameobjectToGrid(guid, &data);
++count;
@@ -1502,18 +1606,36 @@ void ObjectMgr::LoadAuctions()
{
QueryResult *result = CharacterDatabase.Query("SELECT COUNT(*) FROM auctionhouse");
if( !result )
+ {
+ barGoLink bar(1);
+ bar.step();
+ sLog.outString("");
+ sLog.outString(">> Loaded 0 auctions. DB table `auctionhouse` is empty.");
return;
+ }
Field *fields = result->Fetch();
uint32 AuctionCount=fields[0].GetUInt32();
delete result;
if(!AuctionCount)
+ {
+ barGoLink bar(1);
+ bar.step();
+ sLog.outString("");
+ sLog.outString(">> Loaded 0 auctions. DB table `auctionhouse` is empty.");
return;
+ }
result = CharacterDatabase.Query( "SELECT id,auctioneerguid,itemguid,item_template,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit,location FROM auctionhouse" );
if( !result )
+ {
+ barGoLink bar(1);
+ bar.step();
+ sLog.outString("");
+ sLog.outString(">> Loaded 0 auctions. DB table `auctionhouse` is empty.");
return;
+ }
barGoLink bar( AuctionCount );
@@ -1554,7 +1676,6 @@ void ObjectMgr::LoadAuctions()
sLog.outString();
sLog.outString( ">> Loaded %u auctions", AuctionCount );
- sLog.outString();
}
void ObjectMgr::LoadItemLocales()
@@ -1653,6 +1774,32 @@ void ObjectMgr::LoadItemPrototypes()
if(dbcitem)
{
+ if(proto->Class != dbcitem->Class)
+ {
+ sLog.outErrorDb("Item (Entry: %u) not correct class %u, must be %u (still using DB value).",i,proto->Class,dbcitem->Class);
+ // It safe let use Class from DB
+ }
+ /* disabled: have some strange wrong cases for Subclass values.
+ for enable also uncomment Subclass field in ItemEntry structure and in Itemfmt[]
+ if(proto->SubClass != dbcitem->SubClass)
+ {
+ sLog.outErrorDb("Item (Entry: %u) not correct (Class: %u, Sub: %u) pair, must be (Class: %u, Sub: %u) (still using DB value).",i,proto->Class,proto->SubClass,dbcitem->Class,dbcitem->SubClass);
+ // It safe let use Subclass from DB
+ }
+ */
+
+ if(proto->Unk0 != dbcitem->Unk0)
+ {
+ sLog.outErrorDb("Item (Entry: %u) not correct %i Unk0, must be %i (still using DB value).",i,proto->Unk0,dbcitem->Unk0);
+ // It safe let use Unk0 from DB
+ }
+
+ if(proto->Material != dbcitem->Material)
+ {
+ sLog.outErrorDb("Item (Entry: %u) not correct %i material, must be %i (still using DB value).",i,proto->Material,dbcitem->Material);
+ // It safe let use Material from DB
+ }
+
if(proto->InventoryType != dbcitem->InventoryType)
{
sLog.outErrorDb("Item (Entry: %u) not correct %u inventory type, must be %u (still using DB value).",i,proto->InventoryType,dbcitem->InventoryType);
@@ -1678,7 +1825,7 @@ void ObjectMgr::LoadItemPrototypes()
if(proto->Class >= MAX_ITEM_CLASS)
{
sLog.outErrorDb("Item (Entry: %u) has wrong Class value (%u)",i,proto->Class);
- const_cast<ItemPrototype*>(proto)->Class = ITEM_CLASS_JUNK;
+ const_cast<ItemPrototype*>(proto)->Class = ITEM_CLASS_MISC;
}
if(proto->SubClass >= MaxItemSubclassValues[proto->Class])
@@ -1711,14 +1858,30 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(proto)->RequiredSkill = 0;
}
- if(!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE))
{
- sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped.",i,proto->AllowableClass);
- }
- if(!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE))
- {
- sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped.",i,proto->AllowableRace);
+ // can be used in equip slot, as page read use in inventory, or spell casting at use
+ bool req = proto->InventoryType!=INVTYPE_NON_EQUIP || proto->PageText;
+ if(!req)
+ {
+ for (int j = 0; j < 5; ++j)
+ {
+ if(proto->Spells[j].SpellId)
+ {
+ req = true;
+ break;
+ }
+ }
+ }
+
+ if(req)
+ {
+ if(!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE))
+ sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped or use.",i,proto->AllowableClass);
+
+ if(!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE))
+ sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped or use.",i,proto->AllowableRace);
+ }
}
if(proto->RequiredSpell && !sSpellStore.LookupEntry(proto->RequiredSpell))
@@ -1744,11 +1907,22 @@ void ObjectMgr::LoadItemPrototypes()
else if(proto->RequiredReputationRank > MIN_REPUTATION_RANK)
sLog.outErrorDb("Item (Entry: %u) has RequiredReputationFaction ==0 but RequiredReputationRank > 0, rank setting is useless.",i);
+ if(proto->MaxCount < -1)
+ {
+ sLog.outErrorDb("Item (Entry: %u) has too large negative in maxcount (%i), replace by value (-1) no storing limits.",i,proto->MaxCount);
+ const_cast<ItemPrototype*>(proto)->MaxCount = -1;
+ }
+
if(proto->Stackable==0)
{
- sLog.outErrorDb("Item (Entry: %u) has wrong value in stackable (%u), replace by default 1.",i,proto->Stackable);
+ sLog.outErrorDb("Item (Entry: %u) has wrong value in stackable (%i), replace by default 1.",i,proto->Stackable);
const_cast<ItemPrototype*>(proto)->Stackable = 1;
}
+ else if(proto->Stackable < -1)
+ {
+ sLog.outErrorDb("Item (Entry: %u) has too large negative in stackable (%i), replace by value (-1) no stacking limits.",i,proto->Stackable);
+ const_cast<ItemPrototype*>(proto)->Stackable = -1;
+ }
else if(proto->Stackable > 255)
{
sLog.outErrorDb("Item (Entry: %u) has too large value in stackable (%u), replace by hardcoded upper limit (255).",i,proto->Stackable);
@@ -1775,7 +1949,7 @@ void ObjectMgr::LoadItemPrototypes()
}
// special format
- if(proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN)
+ if((proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN) || (proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN_PET))
{
// spell_1
if(proto->Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE)
@@ -1812,7 +1986,7 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
}
// allowed only in special format
- else if(proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN)
+ else if((proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN) || (proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN_PET))
{
sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,1+1,proto->Spells[1].SpellId);
const_cast<ItemPrototype*>(proto)->Spells[0].SpellId = 0;
@@ -1858,7 +2032,7 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(proto)->Spells[j].SpellId = 0;
}
// allowed only in special format
- else if(proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN)
+ else if((proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN) || (proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN_PET))
{
sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,j+1,proto->Spells[j].SpellId);
const_cast<ItemPrototype*>(proto)->Spells[j].SpellId = 0;
@@ -1927,17 +2101,21 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(proto)->FoodType = 0;
}
}
-
- // this DBC used currently only for check item templates in DB.
- sItemStore.Clear();
}
void ObjectMgr::LoadAuctionItems()
{
- QueryResult *result = CharacterDatabase.Query( "SELECT itemguid,item_template FROM auctionhouse" );
+ // data needs to be at first place for Item::LoadFromDB
+ QueryResult *result = CharacterDatabase.Query( "SELECT data,itemguid,item_template FROM auctionhouse JOIN item_instance ON itemguid = guid" );
if( !result )
+ {
+ barGoLink bar(1);
+ bar.step();
+ sLog.outString("");
+ sLog.outString(">> Loaded 0 auction items");
return;
+ }
barGoLink bar( result->GetRowCount() );
@@ -1949,8 +2127,8 @@ void ObjectMgr::LoadAuctionItems()
bar.step();
fields = result->Fetch();
- uint32 item_guid = fields[0].GetUInt32();
- uint32 item_template = fields[1].GetUInt32();
+ uint32 item_guid = fields[1].GetUInt32();
+ uint32 item_template = fields[2].GetUInt32();
ItemPrototype const *proto = GetItemPrototype(item_template);
@@ -1962,7 +2140,7 @@ void ObjectMgr::LoadAuctionItems()
Item *item = NewItemOrBag(proto);
- if(!item->LoadFromDB(item_guid,0))
+ if(!item->LoadFromDB(item_guid,0, result))
{
delete item;
continue;
@@ -1972,7 +2150,6 @@ void ObjectMgr::LoadAuctionItems()
++count;
}
while( result->NextRow() );
-
delete result;
sLog.outString();
@@ -2260,7 +2437,7 @@ void ObjectMgr::LoadPlayerInfo()
if(sWorld.getConfig(CONFIG_START_ALL_SPELLS))
result = WorldDatabase.Query("SELECT race, class, Spell, Active FROM playercreateinfo_spell_custom");
else
- result = WorldDatabase.Query("SELECT race, class, Spell, Active FROM playercreateinfo_spell");
+ result = WorldDatabase.Query("SELECT race, class, Spell FROM playercreateinfo_spell");
uint32 count = 0;
@@ -2295,7 +2472,7 @@ void ObjectMgr::LoadPlayerInfo()
}
PlayerInfo* pInfo = &playerInfo[current_race][current_class];
- pInfo->spell.push_back(CreateSpellPair(fields[2].GetUInt16(), fields[3].GetUInt8()));
+ pInfo->spell.push_back(fields[2].GetUInt32());
bar.step();
++count;
@@ -2567,6 +2744,67 @@ void ObjectMgr::LoadPlayerInfo()
}
}
}
+
+ // Loading xp per level data
+ {
+ mPlayerXPperLevel.resize(sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
+ for (uint32 level = 0; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level)
+ mPlayerXPperLevel[level] = 0;
+
+ // 0 1
+ QueryResult *result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM player_xp_for_level");
+
+ uint32 count = 0;
+
+ if (!result)
+ {
+ barGoLink bar( 1 );
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u xp for level definitions", count );
+ sLog.outErrorDb( "Error loading `player_xp_for_level` table or empty table.");
+ exit(1);
+ }
+
+ barGoLink bar( result->GetRowCount() );
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 current_level = fields[0].GetUInt32();
+ uint32 current_xp = fields[1].GetUInt32();
+
+ if(current_level >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
+ {
+ if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
+ sLog.outErrorDb("Wrong (> %u) level %u in `player_xp_for_level` table, ignoring.", STRONG_MAX_LEVEL,current_level);
+ else
+ sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_xp_for_levels` table, ignoring.",current_level);
+ continue;
+ }
+ //PlayerXPperLevel
+ mPlayerXPperLevel[current_level] = current_xp;
+ bar.step();
+ ++count;
+ }
+ while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u xp for level definitions", count );
+ }
+
+ // fill level gaps
+ for (uint32 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level)
+ {
+ if( mPlayerXPperLevel[level] == 0)
+ {
+ sLog.outErrorDb("Level %i does not have XP for level data. Using data of level [%i] + 100.",level+1, level);
+ mPlayerXPperLevel[level] = mPlayerXPperLevel[level-1]+100;
+ }
+ }
}
void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint32 level, PlayerClassLevelInfo* info) const
@@ -2919,31 +3157,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)
@@ -4296,14 +4534,20 @@ void ObjectMgr::LoadInstanceTemplate()
else if(!entry->HasResetTime())
continue;
+ //FIXME: now exist heroic instance, normal/heroic raid instances
+ // entry->resetTimeHeroic store reset time for both heroic mode instance (raid and non-raid)
+ // entry->resetTimeRaid store reset time for normal raid only
+ // for current state entry->resetTimeRaid == entry->resetTimeHeroic in case raid instances with heroic mode.
+ // but at some point wee need implement reset time dependen from raid insatance mode
if(temp->reset_delay == 0)
{
// use defaults from the DBC
- if(entry->SupportsHeroicMode())
+ if(entry->resetTimeHeroic) // for both raid and non raids, read above
{
temp->reset_delay = entry->resetTimeHeroic / DAY;
}
else if (entry->resetTimeRaid && entry->map_type == MAP_RAID)
+ // for normal raid only
{
temp->reset_delay = entry->resetTimeRaid / DAY;
}
@@ -4481,14 +4725,27 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
// 0 1 2 3 4 5 6 7 8 9
QueryResult* result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,itemTextId,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" I64FMTD "'", (uint64)basetime);
if ( !result )
+ {
+ barGoLink bar(1);
+ bar.step();
+ sLog.outString("");
+ sLog.outString(">> Only expired mails (need to be return or delete) or DB table `mail` is empty.");
return; // any mails need to be returned or deleted
- Field *fields;
+ }
+
//std::ostringstream delitems, delmails; //will be here for optimization
//bool deletemail = false, deleteitem = false;
//delitems << "DELETE FROM item_instance WHERE guid IN ( ";
//delmails << "DELETE FROM mail WHERE id IN ( "
+
+ barGoLink bar( result->GetRowCount() );
+ uint32 count = 0;
+ Field *fields;
+
do
{
+ bar.step();
+
fields = result->Fetch();
Mail *m = new Mail;
m->messageID = fields[0].GetUInt32();
@@ -4554,8 +4811,12 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
//delmails << m->messageID << ", ";
CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID);
delete m;
+ ++count;
} while (result->NextRow());
delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u mails", count );
}
void ObjectMgr::LoadQuestAreaTriggers()
@@ -4712,7 +4973,7 @@ void ObjectMgr::LoadAreaTriggerScripts()
sLog.outString( ">> Loaded %u areatrigger scripts", count );
}
-uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid )
+uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid, uint32 team )
{
bool found = false;
float dist;
@@ -4721,24 +4982,31 @@ uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid )
for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i)
{
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i);
- if(node && node->map_id == mapid)
+ if(!node || node->map_id != mapid || !node->MountCreatureID[team == ALLIANCE ? 1 : 0])
+ continue;
+
+ uint8 field = (uint8)((i - 1) / 32);
+ uint32 submask = 1<<((i-1)%32);
+
+ // skip not taxi network nodes
+ if((sTaxiNodesMask[field] & submask)==0)
+ continue;
+
+ float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z);
+ if(found)
{
- float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z);
- if(found)
- {
- if(dist2 < dist)
- {
- dist = dist2;
- id = i;
- }
- }
- else
+ if(dist2 < dist)
{
- found = true;
dist = dist2;
id = i;
}
}
+ else
+ {
+ found = true;
+ dist = dist2;
+ id = i;
+ }
}
return id;
@@ -4776,17 +5044,19 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team )
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id);
if(node)
{
- if (team == ALLIANCE) mount_entry = node->alliance_mount_type;
- else mount_entry = node->horde_mount_type;
-
- CreatureInfo const *cinfo = GetCreatureTemplate(mount_entry);
- if (cinfo)
+ if (team == ALLIANCE)
{
- if(! (mount_id = cinfo->GetRandomValidModelId()))
- {
- sLog.outErrorDb("No displayid found for the taxi mount with the entry %u! Can't load it!", mount_entry);
- return false;
- }
+ mount_entry = node->MountCreatureID[1];
+ CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
+ if(ci)
+ mount_id = ci->Modelid1;
+ }
+ if (team == HORDE)
+ {
+ mount_entry = node->MountCreatureID[0];
+ CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
+ if(ci)
+ mount_id = ci->Modelid3;
}
}
@@ -4914,7 +5184,7 @@ void ObjectMgr::LoadGraveyardZones()
WorldSafeLocsEntry const *ObjectMgr::GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team)
{
// search for zone associated closest graveyard
- uint32 zoneId = MapManager::Instance().GetZoneId(MapId,x,y);
+ uint32 zoneId = MapManager::Instance().GetZoneId(MapId,x,y,z);
// Simulate std. algorithm:
// found some graveyard associated to (ghost_zone,ghost_map)
@@ -5242,6 +5512,9 @@ void ObjectMgr::LoadAreaTriggerTeleports()
sLog.outString( ">> Loaded %u area trigger teleport definitions", count );
}
+/*
+ * Searches for the areatrigger which teleports players out of the given map
+ */
AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const
{
const MapEntry *mapEntry = sMapStore.LookupEntry(Map);
@@ -5258,6 +5531,23 @@ AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const
return NULL;
}
+/**
+ * Searches for the areatrigger which teleports players to the given map
+ */
+AreaTrigger const* ObjectMgr::GetMapEntranceTrigger(uint32 Map) const
+{
+ for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); ++itr)
+ {
+ if(itr->second.target_mapId == Map)
+ {
+ AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first);
+ if(atEntry)
+ return &itr->second;
+ }
+ }
+ return NULL;
+}
+
void ObjectMgr::SetHighestGuids()
{
QueryResult *result = CharacterDatabase.Query( "SELECT MAX(guid) FROM characters" );
@@ -5274,9 +5564,6 @@ void ObjectMgr::SetHighestGuids()
delete result;
}
- // pet guids are not saved to DB, set to 0 (pet guid != pet id)
- m_hiPetGuid = 0;
-
result = CharacterDatabase.Query( "SELECT MAX(guid) FROM item_instance" );
if( result )
{
@@ -5429,6 +5716,13 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
World::StopNow(ERROR_EXIT_CODE);
}
return m_hiPetGuid++;
+ case HIGHGUID_VEHICLE:
+ if(m_hiVehicleGuid>=0x00FFFFFF)
+ {
+ sLog.outError("Vehicle guid overflow!! Can't continue, shutting down server. ");
+ World::StopNow(ERROR_EXIT_CODE);
+ }
+ return m_hiVehicleGuid++;
case HIGHGUID_PLAYER:
if(m_hiCharGuid>=0xFFFFFFFE)
{
@@ -5616,10 +5910,10 @@ void ObjectMgr::LoadGameobjectInfo()
break;
}
case GAMEOBJECT_TYPE_CHAIR: //7
- if(goInfo->chair.height > 2)
+ if(goInfo->chair.height > (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) )
{
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..2.",
- id,goInfo->type,goInfo->chair.height);
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..%i.",
+ id,goInfo->type,goInfo->chair.height,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
// prevent client and server unexpected work
const_cast<GameObjectInfo*>(goInfo)->chair.height = 0;
@@ -5714,6 +6008,16 @@ void ObjectMgr::LoadGameobjectInfo()
}
break;
}
+ case GAMEOBJECT_TYPE_BARBER_CHAIR: //32
+ if(goInfo->barberChair.chairheight > (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) )
+ {
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..%i.",
+ id,goInfo->type,goInfo->barberChair.chairheight,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
+
+ // prevent client and server unexpected work
+ const_cast<GameObjectInfo*>(goInfo)->barberChair.chairheight = 0;
+ }
+ break;
}
}
@@ -5762,6 +6066,13 @@ uint32 ObjectMgr::GetBaseXP(uint32 level)
return mBaseXPTable[level] ? mBaseXPTable[level] : 0;
}
+uint32 ObjectMgr::GetXPForLevel(uint32 level)
+{
+ if (level < mPlayerXPperLevel.size())
+ return mPlayerXPperLevel[level];
+ return 0;
+}
+
void ObjectMgr::LoadPetNames()
{
uint32 count = 0;
@@ -6230,11 +6541,18 @@ void ObjectMgr::LoadReservedPlayersNames()
bar.step();
fields = result->Fetch();
std::string name= fields[0].GetCppString();
- if(normalizePlayerName(name))
+
+ std::wstring wstr;
+ if(!Utf8toWStr (name,wstr))
{
- m_ReservedNames.insert(name);
- ++count;
+ sLog.outError("Table `reserved_name` have invalid name: %s", name.c_str() );
+ continue;
}
+
+ wstrToLower(wstr);
+
+ m_ReservedNames.insert(wstr);
+ ++count;
} while ( result->NextRow() );
delete result;
@@ -6243,6 +6561,17 @@ void ObjectMgr::LoadReservedPlayersNames()
sLog.outString( ">> Loaded %u reserved player names", count );
}
+bool ObjectMgr::IsReservedName( const std::string& name ) const
+{
+ std::wstring wstr;
+ if(!Utf8toWStr (name,wstr))
+ return false;
+
+ wstrToLower(wstr);
+
+ return m_ReservedNames.find(wstr) != m_ReservedNames.end();
+}
+
enum LanguageType
{
LT_BASIC_LATIN = 0x0000,
@@ -6435,11 +6764,22 @@ void ObjectMgr::LoadGameObjectForQuests()
{
mGameObjectForQuestSet.clear(); // need for reload case
+ if( !sGOStorage.MaxEntry )
+ {
+ barGoLink bar( 1 );
+ bar.step();
+ sLog.outString();
+ sLog.outString( ">> Loaded 0 GameObjects for quests" );
+ return;
+ }
+
+ barGoLink bar( sGOStorage.MaxEntry - 1 );
uint32 count = 0;
// collect GO entries for GO that must activated
for(uint32 go_entry = 1; go_entry < sGOStorage.MaxEntry; ++go_entry)
{
+ bar.step();
GameObjectInfo const* goInfo = sGOStorage.LookupEntry<GameObjectInfo>(go_entry);
if(!goInfo)
continue;
@@ -6474,7 +6814,7 @@ void ObjectMgr::LoadGameObjectForQuests()
}
sLog.outString();
- sLog.outString( ">> Loaded %u GameObject for quests", count );
+ sLog.outString( ">> Loaded %u GameObjects for quests", count );
}
bool ObjectMgr::LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value)
@@ -6767,7 +7107,7 @@ bool PlayerCondition::Meets(Player const * player) const
{
Unit::AuraMap const& auras = player->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
- if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual==3580)
+ if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual[0]==3580)
return true;
return false;
}
@@ -6944,7 +7284,7 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial)
return SKILL_RANGE_MONO;
case SKILL_CATEGORY_ARMOR:
case SKILL_CATEGORY_CLASS:
- if(pSkill->id != SKILL_POISONS && pSkill->id != SKILL_LOCKPICKING)
+ if(pSkill->id != SKILL_LOCKPICKING)
return SKILL_RANGE_MONO;
else
return SKILL_RANGE_LEVEL;
@@ -6959,7 +7299,7 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial)
return SKILL_RANGE_MONO;
default:
case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc
- case SKILL_CATEGORY_NOT_DISPLAYED: //only GENEREC(DND)
+ case SKILL_CATEGORY_GENERIC: //only GENERIC(DND)
return SKILL_RANGE_NONE;
}
}
@@ -7020,11 +7360,10 @@ void ObjectMgr::LoadGameTele()
++count;
}
while (result->NextRow());
-
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u game tele's", count );
+ sLog.outString( ">> Loaded %u GameTeleports", count );
}
GameTele const* ObjectMgr::GetGameTele(const std::string& name) const
@@ -7170,6 +7509,19 @@ void ObjectMgr::LoadTrainerSpell()
if(!pTrainerSpell->reqlevel)
pTrainerSpell->reqlevel = spellinfo->spellLevel;
+ // calculate learned spell for profession case when stored cast-spell
+ pTrainerSpell->learned_spell = spell;
+ for(int i = 0; i <3; ++i)
+ {
+ if(spellinfo->Effect[i]!=SPELL_EFFECT_LEARN_SPELL)
+ continue;
+
+ if(SpellMgr::IsProfessionOrRidingSpell(spellinfo->EffectTriggerSpell[i]))
+ {
+ pTrainerSpell->learned_spell = spellinfo->EffectTriggerSpell[i];
+ break;
+ }
+ }
TrainerSpellData& data = m_mCacheTrainerSpellMap[entry];
@@ -7183,7 +7535,7 @@ void ObjectMgr::LoadTrainerSpell()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded Trainers %d", count );
+ sLog.outString( ">> Loaded %d Trainers", count );
}
void ObjectMgr::LoadVendors()
@@ -7461,16 +7813,30 @@ void ObjectMgr::LoadScriptNames()
"SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(script) FROM instance_template WHERE script <> ''");
- if(result)
+
+ if( !result )
{
- do
- {
- m_scriptNames.push_back((*result)[0].GetString());
- } while (result->NextRow());
- delete result;
+ barGoLink bar( 1 );
+ bar.step();
+ sLog.outString();
+ sLog.outErrorDb(">> Loaded empty set of Script Names!");
+ return;
}
+ barGoLink bar( result->GetRowCount() );
+ uint32 count = 0;
+
+ do
+ {
+ bar.step();
+ m_scriptNames.push_back((*result)[0].GetString());
+ ++count;
+ } while (result->NextRow());
+ delete result;
+
std::sort(m_scriptNames.begin(), m_scriptNames.end());
+ sLog.outString();
+ sLog.outString( ">> Loaded %d Script Names", count );
}
uint32 ObjectMgr::GetScriptId(const char *name)
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
index b942ae21c37..4c8339d7f6f 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -435,7 +435,7 @@ class ObjectMgr
uint32 GetPlayerAccountIdByGUID(const uint64 &guid) const;
uint32 GetPlayerAccountIdByPlayerName(const std::string& name) const;
- uint32 GetNearestTaxiNode( float x, float y, float z, uint32 mapid );
+ uint32 GetNearestTaxiNode( float x, float y, float z, uint32 mapid, uint32 team );
void GetTaxiPath( uint32 source, uint32 destination, uint32 &path, uint32 &cost);
uint16 GetTaxiMount( uint32 id, uint32 team );
void GetTaxiPathNodes( uint32 path, Path &pathnodes, std::vector<uint32>& mapIds );
@@ -491,6 +491,7 @@ class ObjectMgr
}
AreaTrigger const* GetGoBackTrigger(uint32 Map) const;
+ AreaTrigger const* GetMapEntranceTrigger(uint32 Map) const;
uint32 GetAreaTriggerScriptId(uint32 trigger_id);
@@ -594,9 +595,10 @@ class ObjectMgr
void LoadNpcTextId();
void LoadVendors();
void LoadTrainerSpell();
-
+
std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint32 level);
+ uint32 GetXPForLevel(uint32 level);
int32 GetFishingBaseSkillLevel(uint32 entry) const
{
@@ -734,10 +736,7 @@ class ObjectMgr
// reserved names
void LoadReservedPlayersNames();
- bool IsReservedName(const std::string& name) const
- {
- return m_ReservedNames.find(name) != m_ReservedNames.end();
- }
+ bool IsReservedName(const std::string& name) const;
// name with valid structure and symbols
static bool IsValidName( const std::string& name, bool create = false );
@@ -811,6 +810,8 @@ class ObjectMgr
ScriptNameMap &GetScriptNames() { return m_scriptNames; }
const char * GetScriptName(uint32 id) { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; }
uint32 GetScriptId(const char *name);
+
+ int GetOrNewIndexForLocale(LocaleConstant loc);
protected:
// first free id for selected id type
@@ -825,6 +826,7 @@ class ObjectMgr
uint32 m_hiCharGuid;
uint32 m_hiCreatureGuid;
uint32 m_hiPetGuid;
+ uint32 m_hiVehicleGuid;
uint32 m_hiItemGuid;
uint32 m_hiGoGuid;
uint32 m_hiDoGuid;
@@ -867,7 +869,7 @@ class ObjectMgr
PetCreateSpellMap mPetCreateSpell;
//character reserved names
- typedef std::set<std::string> ReservedNamesMap;
+ typedef std::set<std::wstring> ReservedNamesMap;
ReservedNamesMap m_ReservedNames;
std::set<uint32> m_DisabledPlayerSpells;
@@ -881,7 +883,6 @@ class ObjectMgr
typedef std::vector<LocaleConstant> LocalForIndex;
LocalForIndex m_LocalForIndex;
- int GetOrNewIndexForLocale(LocaleConstant loc);
int DBCLocaleIndex;
@@ -900,6 +901,9 @@ class ObjectMgr
void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const;
PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES];
+ typedef std::vector<uint32> PlayerXPperLevel; // [level]
+ PlayerXPperLevel mPlayerXPperLevel;
+
typedef std::map<uint32,uint32> BaseXPMap; // [area level][base xp]
BaseXPMap mBaseXPTable;
diff --git a/src/game/ObjectPosSelector.cpp b/src/game/ObjectPosSelector.cpp
new file mode 100644
index 00000000000..6855e21f82a
--- /dev/null
+++ b/src/game/ObjectPosSelector.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ObjectPosSelector.h"
+
+ObjectPosSelector::ObjectPosSelector(float x,float y,float size,float dist)
+: m_center_x(x),m_center_y(y),m_size(size),m_dist(dist)
+{
+ m_anglestep = acos(m_dist/(m_dist+2*m_size));
+
+ m_nextUsedPos[USED_POS_PLUS] = m_UsedPosLists[USED_POS_PLUS].end();
+ m_nextUsedPos[USED_POS_MINUS] = m_UsedPosLists[USED_POS_MINUS].end();
+
+ m_smallStepAngle[USED_POS_PLUS] = 0;
+ m_smallStepAngle[USED_POS_MINUS] = 0;
+
+ m_smallStepOk[USED_POS_PLUS] = false;
+ m_smallStepOk[USED_POS_MINUS] = false;
+
+ m_smallStepNextUsedPos[USED_POS_PLUS] = NULL;
+ m_smallStepNextUsedPos[USED_POS_MINUS] = NULL;
+}
+
+ObjectPosSelector::UsedPosList::value_type const* ObjectPosSelector::nextUsedPos(UsedPosType uptype)
+{
+ UsedPosList::const_iterator itr = m_nextUsedPos[uptype];
+ if(itr!=m_UsedPosLists[uptype].end())
+ ++itr;
+
+ if(itr==m_UsedPosLists[uptype].end())
+ {
+ if(!m_UsedPosLists[~uptype].empty())
+ return &*m_UsedPosLists[~uptype].rbegin();
+ else
+ return NULL;
+ }
+ else
+ return &*itr;
+}
+
+void ObjectPosSelector::AddUsedPos(float size,float angle,float dist)
+{
+ if(angle>=0)
+ m_UsedPosLists[USED_POS_PLUS].insert(UsedPosList::value_type(angle,UsedPos(1.0,size,dist)));
+ else
+ m_UsedPosLists[USED_POS_MINUS].insert(UsedPosList::value_type(-angle,UsedPos(-1.0,size,dist)));
+}
+
+void ObjectPosSelector::InitializeAngle()
+{
+ m_nextUsedPos[USED_POS_PLUS] = m_UsedPosLists[USED_POS_PLUS].begin();
+ m_nextUsedPos[USED_POS_MINUS] = m_UsedPosLists[USED_POS_MINUS].begin();
+
+ m_smallStepAngle[USED_POS_PLUS] = 0;
+ m_smallStepAngle[USED_POS_MINUS] = 0;
+
+ m_smallStepOk[USED_POS_PLUS] = true;
+ m_smallStepOk[USED_POS_MINUS] = true;
+}
+
+bool ObjectPosSelector::FirstAngle(float& angle)
+{
+ if(m_UsedPosLists[USED_POS_PLUS].empty() && !m_UsedPosLists[USED_POS_MINUS].empty() )
+ return NextAngleFor(*m_UsedPosLists[USED_POS_MINUS].begin(),1.0,USED_POS_PLUS,angle);
+ else if(m_UsedPosLists[USED_POS_MINUS].empty() && !m_UsedPosLists[USED_POS_PLUS].empty() )
+ return NextAngleFor(*m_UsedPosLists[USED_POS_PLUS].begin(),-1.0,USED_POS_MINUS,angle);
+
+ return false;
+}
+
+bool ObjectPosSelector::NextAngle(float& angle)
+{
+ while(m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() ||
+ m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end() ||
+ m_smallStepOk[USED_POS_PLUS] || m_smallStepOk[USED_POS_MINUS] )
+ {
+ // calculate next possible angle
+ if(NextPosibleAngle(angle))
+ return true;
+ }
+
+ return false;
+}
+
+bool ObjectPosSelector::NextUsedAngle(float& angle)
+{
+ while(m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() ||
+ m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end() )
+ {
+ // calculate next possible angle
+ if(!NextPosibleAngle(angle))
+ return true;
+ }
+
+ return false;
+}
+
+bool ObjectPosSelector::NextPosibleAngle( float& angle )
+{
+ // ++ direction less updated
+ if( m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() &&
+ (m_nextUsedPos[USED_POS_MINUS]==m_UsedPosLists[USED_POS_MINUS].end() || m_nextUsedPos[USED_POS_PLUS]->first <= m_nextUsedPos[USED_POS_MINUS]->first) )
+ {
+ bool ok;
+ if(m_smallStepOk[USED_POS_PLUS])
+ ok = NextSmallStepAngle(1.0,USED_POS_PLUS,angle);
+ else
+ ok = NextAngleFor(*m_nextUsedPos[USED_POS_PLUS],1.0,USED_POS_PLUS,angle);
+
+ if(!ok)
+ ++m_nextUsedPos[USED_POS_PLUS]; // increase. only at fail (original or checked)
+ return ok;
+ }
+ // -- direction less updated
+ else if( m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end())
+ {
+ bool ok;
+ if(m_smallStepOk[USED_POS_MINUS])
+ ok = NextSmallStepAngle(-1.0,USED_POS_MINUS,angle);
+ else
+ ok = NextAngleFor(*m_nextUsedPos[USED_POS_MINUS],-1.0,USED_POS_MINUS,angle);
+
+ if(!ok)
+ ++m_nextUsedPos[USED_POS_MINUS];
+ return ok;
+ }
+ else // both list empty
+ {
+ if( m_smallStepOk[USED_POS_PLUS] && (!m_smallStepOk[USED_POS_MINUS] || m_smallStepAngle[USED_POS_PLUS] <= m_smallStepAngle[USED_POS_MINUS]) )
+ {
+ return NextSmallStepAngle(1.0,USED_POS_PLUS,angle);
+ }
+ // -- direction less updated
+ else if( m_smallStepOk[USED_POS_MINUS] )
+ {
+ return NextSmallStepAngle(-1.0,USED_POS_MINUS,angle);
+ }
+ }
+
+ // no angles
+ return false;
+}
diff --git a/src/game/ObjectPosSelector.h b/src/game/ObjectPosSelector.h
new file mode 100644
index 00000000000..bc4de0c1d02
--- /dev/null
+++ b/src/game/ObjectPosSelector.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _OBJECT_POS_SELECTOR_H
+#define _OBJECT_POS_SELECTOR_H
+
+#include<Common.h>
+
+#include<map>
+
+enum UsedPosType { USED_POS_PLUS, USED_POS_MINUS };
+
+inline UsedPosType operator ~(UsedPosType uptype)
+{
+ return uptype==USED_POS_PLUS ? USED_POS_MINUS : USED_POS_PLUS;
+}
+
+struct ObjectPosSelector
+{
+ struct UsedPos
+ {
+ UsedPos(float sign_, float size_,float dist_) : sign(sign_), size(size_),dist(dist_) {}
+
+ float sign;
+
+ float size; // size of point
+ float dist; // dist to central point (including central point size)
+ };
+
+ typedef std::multimap<float,UsedPos> UsedPosList; // abs(angle)->Node
+
+ ObjectPosSelector(float x,float y,float size,float dist);
+
+ void AddUsedPos(float size,float angle,float dist);
+ void InitializeAngle();
+
+ bool FirstAngle(float& angle);
+ bool NextAngle(float& angle);
+ bool NextUsedAngle(float& angle);
+
+ bool NextPosibleAngle( float& angle );
+
+ bool CheckAngle(UsedPosList::value_type const& nextUsedPos, float sign, float angle ) const
+ {
+ float angle_step2 = GetAngle(nextUsedPos.second);
+
+ float next_angle = nextUsedPos.first;
+ if(nextUsedPos.second.sign * sign < 0) // last node from diff. list (-pi+alpha)
+ next_angle = 2*M_PI-next_angle; // move to positive
+
+ return fabs(angle)+angle_step2 <= next_angle;
+ }
+
+ bool CheckOriginal() const
+ {
+ return (m_UsedPosLists[USED_POS_PLUS].empty() || CheckAngle( *m_UsedPosLists[USED_POS_PLUS].begin(),1.0,0)) &&
+ (m_UsedPosLists[USED_POS_MINUS].empty() || CheckAngle( *m_UsedPosLists[USED_POS_MINUS].begin(),-1.0,0));
+ }
+
+ bool IsNonBalanced() const { return m_UsedPosLists[USED_POS_PLUS].empty() != m_UsedPosLists[USED_POS_MINUS].empty(); }
+
+ bool NextAngleFor( UsedPosList::value_type const& usedPos, float sign, UsedPosType uptype, float &angle )
+ {
+ float angle_step = GetAngle(usedPos.second);
+
+ // next possible angle
+ angle = usedPos.first * usedPos.second.sign + angle_step * sign;
+
+ UsedPosList::value_type const* nextNode = nextUsedPos(uptype);
+ if(nextNode)
+ {
+ // if next node permit use selected angle, then do it
+ if(!CheckAngle(*nextNode, sign, angle))
+ {
+ m_smallStepOk[uptype] = false;
+ return false;
+ }
+ }
+
+ // possible more points
+ m_smallStepOk[uptype] = true;
+ m_smallStepAngle[uptype] = angle;
+ m_smallStepNextUsedPos[uptype] = nextNode;
+
+ return true;
+ }
+
+ bool NextSmallStepAngle( float sign, UsedPosType uptype, float &angle )
+ {
+ // next possible angle
+ angle = m_smallStepAngle[uptype] + m_anglestep * sign;
+
+ if(fabs(angle) > M_PI)
+ {
+ m_smallStepOk[uptype] = false;
+ return false;
+ }
+
+ if(m_smallStepNextUsedPos[uptype])
+ {
+ if(fabs(angle) >= m_smallStepNextUsedPos[uptype]->first)
+ {
+ m_smallStepOk[uptype] = false;
+ return false;
+ }
+
+ // if next node permit use selected angle, then do it
+ if(!CheckAngle(*m_smallStepNextUsedPos[uptype], sign, angle))
+ {
+ m_smallStepOk[uptype] = false;
+ return false;
+ }
+ }
+
+ // possible more points
+ m_smallStepAngle[uptype] = angle;
+ return true;
+ }
+
+ // next used post for m_nextUsedPos[uptype]
+ UsedPosList::value_type const* nextUsedPos(UsedPosType uptype);
+
+ // angle from used pos to next possible free pos
+ float GetAngle(UsedPos const& usedPos) const { return acos(m_dist/(usedPos.dist+usedPos.size+m_size)); }
+
+ float m_center_x;
+ float m_center_y;
+ float m_size; // size of object in center
+ float m_dist; // distance for searching pos (including central object size)
+ float m_anglestep;
+
+ UsedPosList m_UsedPosLists[2];
+ UsedPosList::const_iterator m_nextUsedPos[2];
+
+ // field for small step from first after next used pos until next pos
+ float m_smallStepAngle[2];
+ bool m_smallStepOk[2];
+ UsedPosList::value_type const* m_smallStepNextUsedPos[2];
+};
+#endif
diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp
index 73b6650caa1..8cc987545eb 100644
--- a/src/game/Opcodes.cpp
+++ b/src/game/Opcodes.cpp
@@ -28,1064 +28,1201 @@
/// Correspondence between opcodes and their names
OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
{
- /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, &WorldSession::HandleWorldTeleportOpcode },
- /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },
- /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x00D*/ { "CMSG_EMBLAZON_TABARD_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x00E*/ { "CMSG_UNEMBLAZON_TABARD_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x01E*/ { "SMSG_DEBUGINFOSPELLMISS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x032*/ { "CMSG_PVP_PORT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, &WorldSession::HandleCharCreateOpcode },
- /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode },
- /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, &WorldSession::HandleCharDeleteOpcode },
- /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, &WorldSession::HandlePlayerLoginOpcode },
- /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, &WorldSession::HandlePlayerLogoutOpcode },
- /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLogoutRequestOpcode },
- /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleLogoutCancelOpcode },
- /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNameQueryOpcode },
- /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetNameQuery },
- /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, &WorldSession::HandleGuildQueryOpcode },
- /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, &WorldSession::HandleItemQuerySingleOpcode },
- /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePageQueryOpcode },
- /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestQueryOpcode },
- /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectQueryOpcode },
- /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCreatureQueryOpcode },
- /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, &WorldSession::HandleWhoOpcode },
- /*0x063*/ { "SMSG_WHO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, &WorldSession::HandleWhoisOpcode },
- /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, &WorldSession::HandleFriendListOpcode },
- /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleAddFriendOpcode },
- /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleDelFriendOpcode },
- /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, &WorldSession::HandleSetFriendNoteOpcode },
- /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleAddIgnoreOpcode },
- /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleDelIgnoreOpcode },
- /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupInviteOpcode },
- /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, &WorldSession::Handle_Deprecated },
- /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGroupAcceptOpcode },
- /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGroupDeclineOpcode },
- /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteNameOpcode },
- /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteGuidOpcode },
- /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupSetLeaderOpcode },
- /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, &WorldSession::HandleLootMethodOpcode },
- /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGroupLeaveOpcode },
- /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildCreateOpcode },
- /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGuildInviteOpcode },
- /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGuildAcceptOpcode },
- /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDeclineOpcode },
- /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, &WorldSession::HandleGuildInfoOpcode },
- /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleGuildRosterOpcode },
- /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildPromoteOpcode },
- /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDemoteOpcode },
- /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaveOpcode },
- /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildRemoveOpcode },
- /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGuildDisbandOpcode },
- /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaderOpcode },
- /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, &WorldSession::HandleGuildMOTDOpcode },
- /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, &WorldSession::HandleMessagechatOpcode },
- /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoin },
- /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelLeave },
- /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelList },
- /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, &WorldSession::HandleChannelPassword },
- /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelSetOwner },
- /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelOwner },
- /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerator },
- /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmoderator },
- /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelMute },
- /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmute },
- /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelInvite },
- /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, &WorldSession::HandleChannelKick },
- /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelBan },
- /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnban },
- /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleChannelAnnounce },
- /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerate },
- /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleUseItemOpcode },
- /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleOpenItemOpcode },
- /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleReadItem },
- /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectUseOpcode },
- /*0x0B2*/ { "CMSG_GAMEOBJ_CHAIR_USE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, &WorldSession::HandleAreaTriggerOpcode },
- /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck },
- /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER_PENDING, &WorldSession::HandleMoveWorldportAckOpcode},
- /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0E0*/ { "MSG_MOVE_SET_RAW_POSITION_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
- /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck },
- /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
- /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck },
- /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck },
- /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck },
- /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck },
- /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, &WorldSession::HandleNextCinematicCamera },
- /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, &WorldSession::HandleCompleteCinema },
- /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, &WorldSession::HandleTutorialFlag },
- /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, &WorldSession::HandleTutorialClear },
- /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleTutorialReset },
- /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, &WorldSession::HandleStandStateChangeOpcode },
- /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleEmoteOpcode },
- /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleTextEmoteOpcode },
- /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutostoreLootItemOpcode },
- /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemOpcode },
- /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBagItemOpcode },
- /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapItem },
- /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapInvItemOpcode },
- /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSplitItemOpcode },
- /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemSlotOpcode },
- /*0x110*/ { "OBSOLETE_DROP_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, &WorldSession::HandleDestroyItemOpcode },
- /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, &WorldSession::HandleInspectOpcode },
- /*0x115*/ { "SMSG_INSPECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleInitiateTradeOpcode },
- /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBeginTradeOpcode },
- /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBusyTradeOpcode },
- /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleIgnoreTradeOpcode },
- /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleAcceptTradeOpcode },
- /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleUnacceptTradeOpcode },
- /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_AUTHED, &WorldSession::HandleCancelTradeOpcode },
- /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeItemOpcode },
- /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleClearTradeItemOpcode },
- /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeGoldOpcode },
- /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionAtWar },
- /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionCheat },
- /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, &WorldSession::HandleSetActionButtonOpcode },
- /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCastSpellOpcode },
- /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, &WorldSession::HandleCancelCastOpcode },
- /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelAuraOpcode },
- /*0x137*/ { "SMSG_UPDATE_AURA_DURATION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, &WorldSession::HandleCancelChanneling },
- /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, &WorldSession::HandleSetSelectionOpcode },
- /*0x13E*/ { "CMSG_SET_TARGET_OBSOLETE", STATUS_LOGGEDIN, &WorldSession::HandleSetTargetOpcode },
- /*0x13F*/ { "CMSG_UNUSED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x140*/ { "CMSG_UNUSED2", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, &WorldSession::HandleAttackSwingOpcode },
- /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, &WorldSession::HandleAttackStopOpcode },
- /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x147*/ { "SMSG_ATTACKSWING_NOTSTANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x14B*/ { "SMSG_VICTIMSTATEUPDATE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x14C*/ { "SMSG_DAMAGE_DONE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x14D*/ { "SMSG_DAMAGE_TAKEN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x14F*/ { "SMSG_PLAYER_COMBAT_XP_GAIN_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x152*/ { "CMSG_SHEATHE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleRepopRequestOpcode },
- /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleResurrectResponseOpcode },
- /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, &WorldSession::HandleLootOpcode },
- /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleLootMoneyOpcode },
- /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, &WorldSession::HandleLootReleaseOpcode },
- /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, &WorldSession::HandleDuelAcceptedOpcode },
- /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, &WorldSession::HandleDuelCancelledOpcode },
- /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x170*/ { "SMSG_PUREMOUNT_CANCELLED_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, &WorldSession::HandleMountSpecialAnimOpcode },
- /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetSetAction },
- /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetAction },
- /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, &WorldSession::HandlePetAbandon },
- /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetRename },
- /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleGossipHelloOpcode },
- /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, &WorldSession::HandleGossipSelectOptionOpcode },
- /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNpcTextQueryOpcode },
- /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryOpcode},
- /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverHelloOpcode },
- /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQuestQueryOpcode},
- /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, &WorldSession::HandleQuestAutoLaunch },
- /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverAcceptQuestOpcode},
- /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestComplete },
- /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverRequestRewardOpcode},
- /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverChooseRewardOpcode},
- /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCancel },
- /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogSwapQuest },
- /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogRemoveQuest },
- /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleQuestConfirmAccept },
- /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushToParty },
- /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, &WorldSession::HandleListInventoryOpcode },
- /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSellItemOpcode },
- /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemOpcode },
- /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemInSlotOpcode },
- /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNodeStatusQueryOpcode },
- /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodesOpcode},
- /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiOpcode },
- /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, &WorldSession::HandleTrainerListOpcode },
- /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleTrainerBuySpellOpcode },
- /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBinderActivateOpcode },
- /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBankerActivateOpcode },
- /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyBankSlotOpcode },
- /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowListOpcode },
- /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionBuyOpcode },
- /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowSignOpcode },
- /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, &WorldSession::HandlePetitionSignOpcode },
- /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandlePetitionDeclineOpcode },
- /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleOfferPetitionOpcode },
- /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleTurnInPetitionOpcode },
- /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionQueryOpcode },
- /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, &WorldSession::HandleBugOpcode },
- /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, &WorldSession::HandlePlayedTime },
- /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryTimeOpcode },
- /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, &WorldSession::HandleCorpseReclaimOpcode },
- /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleWrapItemOpcode },
- /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, &WorldSession::HandleMinimapPingOpcode },
- /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, &WorldSession::Handle_EarlyProccess },
- /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, &WorldSession::HandleSetSheathedOpcode },
- /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1E3*/ { "CMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1E4*/ { "SMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, &WorldSession::Handle_EarlyProccess },
- /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandlePetCastSpellOpcode },
- /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, &WorldSession::HandleGuildSaveEmblemOpcode },
- /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleTabardVendorActivateOpcode},
- /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, &WorldSession::HandleZoneUpdateOpcode },
- /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleRandomRollOpcode },
- /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1FD*/ { "CMSG_RWHOIS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x1FF*/ { "MSG_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLookingForGroup },
- /*0x200*/ { "CMSG_SET_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleSetLfgOpcode },
- /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, &WorldSession::HandleUnlearnSkillOpcode },
- /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketCreateOpcode },
- /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, &WorldSession::HandleWorldTeleportOpcode },
+ /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },
+ /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x00D*/ { "CMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x00E*/ { "SMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x01E*/ { "SMSG_REFER_A_FRIEND_EXPIRED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x032*/ { "SMSG_DESTRUCTIBLE_BUILDING_DAMAGE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, &WorldSession::HandleCharCreateOpcode },
+ /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode },
+ /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, &WorldSession::HandleCharDeleteOpcode },
+ /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, &WorldSession::HandlePlayerLoginOpcode },
+ /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, &WorldSession::HandlePlayerLogoutOpcode },
+ /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLogoutRequestOpcode },
+ /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleLogoutCancelOpcode },
+ /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNameQueryOpcode },
+ /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetNameQuery },
+ /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, &WorldSession::HandleGuildQueryOpcode },
+ /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, &WorldSession::HandleItemQuerySingleOpcode },
+ /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePageQueryOpcode },
+ /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestQueryOpcode },
+ /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectQueryOpcode },
+ /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCreatureQueryOpcode },
+ /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, &WorldSession::HandleWhoOpcode },
+ /*0x063*/ { "SMSG_WHO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, &WorldSession::HandleWhoisOpcode },
+ /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, &WorldSession::HandleFriendListOpcode },
+ /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleAddFriendOpcode },
+ /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleDelFriendOpcode },
+ /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, &WorldSession::HandleSetFriendNoteOpcode },
+ /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleAddIgnoreOpcode },
+ /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleDelIgnoreOpcode },
+ /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupInviteOpcode },
+ /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, &WorldSession::Handle_Deprecated },
+ /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGroupAcceptOpcode },
+ /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGroupDeclineOpcode },
+ /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteNameOpcode },
+ /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteGuidOpcode },
+ /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupSetLeaderOpcode },
+ /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, &WorldSession::HandleLootMethodOpcode },
+ /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGroupLeaveOpcode },
+ /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildCreateOpcode },
+ /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGuildInviteOpcode },
+ /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGuildAcceptOpcode },
+ /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDeclineOpcode },
+ /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, &WorldSession::HandleGuildInfoOpcode },
+ /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleGuildRosterOpcode },
+ /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildPromoteOpcode },
+ /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDemoteOpcode },
+ /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaveOpcode },
+ /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildRemoveOpcode },
+ /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGuildDisbandOpcode },
+ /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaderOpcode },
+ /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, &WorldSession::HandleGuildMOTDOpcode },
+ /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, &WorldSession::HandleMessagechatOpcode },
+ /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoin },
+ /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelLeave },
+ /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelList },
+ /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, &WorldSession::HandleChannelPassword },
+ /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelSetOwner },
+ /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelOwner },
+ /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerator },
+ /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmoderator },
+ /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelMute },
+ /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmute },
+ /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelInvite },
+ /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, &WorldSession::HandleChannelKick },
+ /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelBan },
+ /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnban },
+ /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleChannelAnnounce },
+ /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerate },
+ /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleUseItemOpcode },
+ /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleOpenItemOpcode },
+ /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleReadItem },
+ /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectUseOpcode },
+ /*0x0B2*/ { "CMSG_DESTROY_ITEMS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, &WorldSession::HandleAreaTriggerOpcode },
+ /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck },
+ /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER_PENDING,&WorldSession::HandleMoveWorldportAckOpcode},
+ /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0E0*/ { "MSG_MOVE_SET_RAW_POSITION_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
+ /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
+ /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
+ /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck },
+ /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck },
+ /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck },
+ /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck },
+ /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, &WorldSession::HandleNextCinematicCamera },
+ /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, &WorldSession::HandleCompleteCinema },
+ /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, &WorldSession::HandleTutorialFlag },
+ /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, &WorldSession::HandleTutorialClear },
+ /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleTutorialReset },
+ /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, &WorldSession::HandleStandStateChangeOpcode },
+ /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleEmoteOpcode },
+ /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleTextEmoteOpcode },
+ /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutostoreLootItemOpcode },
+ /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemOpcode },
+ /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBagItemOpcode },
+ /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapItem },
+ /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapInvItemOpcode },
+ /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSplitItemOpcode },
+ /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemSlotOpcode },
+ /*0x110*/ { "OBSOLETE_DROP_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, &WorldSession::HandleDestroyItemOpcode },
+ /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, &WorldSession::HandleInspectOpcode },
+ /*0x115*/ { "SMSG_INSPECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleInitiateTradeOpcode },
+ /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBeginTradeOpcode },
+ /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBusyTradeOpcode },
+ /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleIgnoreTradeOpcode },
+ /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleAcceptTradeOpcode },
+ /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleUnacceptTradeOpcode },
+ /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_AUTHED, &WorldSession::HandleCancelTradeOpcode },
+ /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeItemOpcode },
+ /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleClearTradeItemOpcode },
+ /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeGoldOpcode },
+ /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionAtWar },
+ /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionCheat },
+ /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, &WorldSession::HandleSetActionButtonOpcode },
+ /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCastSpellOpcode },
+ /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, &WorldSession::HandleCancelCastOpcode },
+ /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelAuraOpcode },
+ /*0x137*/ { "SMSG_UPDATE_AURA_DURATION_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, &WorldSession::HandleCancelChanneling },
+ /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, &WorldSession::HandleSetSelectionOpcode },
+ /*0x13E*/ { "CMSG_SET_TARGET_OBSOLETE", STATUS_LOGGEDIN, &WorldSession::HandleSetTargetOpcode },
+ /*0x13F*/ { "CMSG_UNUSED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x140*/ { "CMSG_UNUSED2", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, &WorldSession::HandleAttackSwingOpcode },
+ /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, &WorldSession::HandleAttackStopOpcode },
+ /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x147*/ { "SMSG_ATTACKSWING_NOTSTANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x14B*/ { "SMSG_VICTIMSTATEUPDATE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x14C*/ { "SMSG_DAMAGE_DONE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x14D*/ { "SMSG_DAMAGE_TAKEN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x14F*/ { "SMSG_SPELLBREAKLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x152*/ { "SMSG_BREAK_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleRepopRequestOpcode },
+ /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleResurrectResponseOpcode },
+ /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, &WorldSession::HandleLootOpcode },
+ /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleLootMoneyOpcode },
+ /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, &WorldSession::HandleLootReleaseOpcode },
+ /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, &WorldSession::HandleDuelAcceptedOpcode },
+ /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, &WorldSession::HandleDuelCancelledOpcode },
+ /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x170*/ { "SMSG_PUREMOUNT_CANCELLED_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, &WorldSession::HandleMountSpecialAnimOpcode },
+ /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetSetAction },
+ /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetAction },
+ /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, &WorldSession::HandlePetAbandon },
+ /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetRename },
+ /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleGossipHelloOpcode },
+ /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, &WorldSession::HandleGossipSelectOptionOpcode },
+ /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNpcTextQueryOpcode },
+ /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryOpcode},
+ /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverHelloOpcode },
+ /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQuestQueryOpcode},
+ /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, &WorldSession::HandleQuestAutoLaunch },
+ /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverAcceptQuestOpcode},
+ /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestComplete },
+ /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverRequestRewardOpcode},
+ /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverChooseRewardOpcode},
+ /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCancel },
+ /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogSwapQuest },
+ /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogRemoveQuest },
+ /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleQuestConfirmAccept },
+ /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushToParty },
+ /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, &WorldSession::HandleListInventoryOpcode },
+ /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSellItemOpcode },
+ /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemOpcode },
+ /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemInSlotOpcode },
+ /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNodeStatusQueryOpcode },
+ /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodes },
+ /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiOpcode },
+ /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, &WorldSession::HandleTrainerListOpcode },
+ /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleTrainerBuySpellOpcode },
+ /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBinderActivateOpcode },
+ /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBankerActivateOpcode },
+ /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyBankSlotOpcode },
+ /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowListOpcode },
+ /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionBuyOpcode },
+ /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowSignOpcode },
+ /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, &WorldSession::HandlePetitionSignOpcode },
+ /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandlePetitionDeclineOpcode },
+ /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleOfferPetitionOpcode },
+ /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleTurnInPetitionOpcode },
+ /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionQueryOpcode },
+ /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, &WorldSession::HandleBugOpcode },
+ /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, &WorldSession::HandlePlayedTime },
+ /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryTimeOpcode },
+ /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, &WorldSession::HandleCorpseReclaimOpcode },
+ /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleWrapItemOpcode },
+ /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, &WorldSession::HandleMinimapPingOpcode },
+ /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, &WorldSession::Handle_EarlyProccess },
+ /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, &WorldSession::HandleSetSheathedOpcode },
+ /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1E3*/ { "CMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1E4*/ { "SMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, &WorldSession::Handle_EarlyProccess },
+ /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandlePetCastSpellOpcode },
+ /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, &WorldSession::HandleGuildSaveEmblemOpcode },
+ /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleTabardVendorActivateOpcode},
+ /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, &WorldSession::HandleZoneUpdateOpcode },
+ /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleRandomRollOpcode },
+ /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1FD*/ { "CMSG_RWHOIS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x1FF*/ { "MSG_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLookingForGroup },
+ /*0x200*/ { "CMSG_SET_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleSetLfgOpcode },
+ /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, &WorldSession::HandleUnlearnSkillOpcode },
+ /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketCreateOpcode },
+ /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketUpdateOpcode },
- /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleRequestAccountData },
- /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleUpdateAccountData },
- /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x20E*/ { "SMSG_POWERGAINLOG_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketGetTicketOpcode },
- /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x214*/ { "SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseQueryOpcode },
- /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketDeleteOpcode },
- /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketSystemStatusOpcode},
- /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode},
- /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x21E*/ { "SMSG_SET_REST_START", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, &WorldSession::HandleChatIgnoredOpcode },
- /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildRankOpcode },
- /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildAddRankOpcode },
- /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildDelRankOpcode },
- /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetPublicNoteOpcode },
- /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetOfficerNoteOpcode },
- /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, &WorldSession::HandleSendMail },
- /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleGetMail },
- /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundListOpcode },
- /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x23F*/ { "SMSG_BATTLEFIELD_WIN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x240*/ { "SMSG_BATTLEFIELD_LOSE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemTextQuery },
- /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleTakeMoney },
- /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleTakeItem },
- /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, &WorldSession::HandleMarkAsRead },
- /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, &WorldSession::HandleReturnToSender },
- /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleMailDelete },
- /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailCreateTextItem },
- /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandleLearnTalentOpcode },
- /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, &WorldSession::HandleTogglePvP },
- /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleAuctionHelloOpcode },
- /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionSellItem },
- /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionRemoveItem },
- /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListItems },
- /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListOwnerItems },
- /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, &WorldSession::HandleAuctionPlaceBid },
- /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x261*/ { "SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE",STATUS_NEVER,&WorldSession::Handle_ServerSide },
- /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListBidderItems },
- /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, &WorldSession::HandleSetAmmoOpcode },
- /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode },
- /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandlePetCancelAuraOpcode },
- /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCancelAutoRepeatSpellOpcode},
- /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode },
- /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStablePet },
- /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleUnstablePet },
- /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyStableSlot },
- /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableRevivePet },
- /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableSwapPet },
- /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushResult },
- /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestPetInfoOpcode },
- /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, &WorldSession::HandleFarSightOpcode },
- /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleGroupChangeSubGroupOpcode },
- /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, &WorldSession::HandleRequestPartyMemberStatsOpcode},
- /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBankItemOpcode },
- /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoBankItemOpcode },
- /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, &WorldSession::HandleMsgQueryNextMailtime },
- /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, &WorldSession::HandleRaidConvertOpcode },
- /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantOpcode },
- /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuybackItem },
- /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x292*/ { "CMSG_MEETINGSTONE_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x293*/ { "CMSG_MEETINGSTONE_LEAVE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x294*/ { "CMSG_MEETINGSTONE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x295*/ { "SMSG_MEETINGSTONE_SETQUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x296*/ { "CMSG_MEETINGSTONE_INFO", STATUS_LOGGEDIN, &WorldSession::HandleMeetingStoneInfo },
- /*0x297*/ { "SMSG_MEETINGSTONE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x298*/ { "SMSG_MEETINGSTONE_IN_PROGRESS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x29A*/ { "CMSG_GMTICKETSYSTEM_TOGGLE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelGrowthAuraOpcode },
- /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleLootRoll },
- /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, &WorldSession::HandleLootMasterGiveOpcode },
- /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleRepairItemOpcode },
- /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, &WorldSession::HandleTalentWipeOpcode },
- /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleSummonResponseOpcode },
- /*0x2AD*/ { "MSG_MOVE_TOGGLE_GRAVITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, &WorldSession::HandleSelfResOpcode },
- /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2B9*/ { "CMSG_TOGGLE_HELM", STATUS_LOGGEDIN, &WorldSession::HandleToggleHelmOpcode },
- /*0x2BA*/ { "CMSG_TOGGLE_CLOAK", STATUS_LOGGEDIN, &WorldSession::HandleToggleCloakOpcode },
- /*0x2BB*/ { "SMSG_MEETINGSTONE_JOINFAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, &WorldSession::HandleSetActionBar },
- /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetitionRenameOpcode },
- /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemNameQueryOpcode },
- /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, &WorldSession::HandleChangePlayerNameOpcode },
- /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNextDestinationOpcode },
- /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestRaidInfoOpcode },
- /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, &WorldSession::HandleMoveTimeSkippedOpcode },
- /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, &WorldSession::HandleFeatherFallAck },
- /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck },
- /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleNotActiveMoverOpcode },
- /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldStatusOpcode },
- /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPortOpcode},
- /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, &WorldSession::HandleInspectHonorStatsOpcode },
- /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundHelloOpcode },
- /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
- /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck },
- /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
- /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPVPlogdataOpcode},
- /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundLeaveOpcode },
- /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueryOpcode},
- /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueueOpcode},
- /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode },
- /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS",STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPositionsOpcode},
- /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundJoinOpcode },
- /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_LOGGEDIN, &WorldSession::HandlePetUnlearnOpcode },
- /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, &WorldSession::HandlePetSpellAutocastOpcode },
- /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildChangeInfoOpcode },
- /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiFarOpcode },
- /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionInactiveOpcode},
- /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionIndexOpcode},
- /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, &WorldSession::HandleResetInstancesOpcode },
- /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleRaidIconTargetOpcode },
- /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckOpcode },
- /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleDungeonDifficultyOpcode },
- /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },//&WorldSession::HandleGMSurveySubmit
- /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED",STATUS_NEVER,&WorldSession::Handle_ServerSide },
- /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x33E*/ { "SMSG_MOVE_SET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x33F*/ { "SMSG_MOVE_UNSET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x340*/ { "CMSG_MOVE_FLIGHT_ACK_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveFlyModeChangeAckOpcode},
- /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, &WorldSession::HandleSocketOpcode },
- /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x34A*/ { "UMSG_UPDATE_ARENA_TEAM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamQueryOpcode },
- /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRosterOpcode },
- /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamAddMemberOpcode },
- /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteAcceptOpcode},
- /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteDeclineOpcode},
- /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaveOpcode },
- /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRemoveFromTeamOpcode},
- /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDisbandOpcode },
- /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamPromoteToCaptainOpcode},
- /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundArenaJoin },
- /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x35C*/ { "CMSG_LFG_SET_AUTOJOIN", STATUS_AUTHED, &WorldSession::HandleLfgAutoJoinOpcode },
- /*0x35D*/ { "CMSG_LFG_CLEAR_AUTOJOIN", STATUS_LOGGEDIN, &WorldSession::HandleLfgCancelAutoJoinOpcode },
- /*0x35E*/ { "CMSG_LFM_SET_AUTOFILL", STATUS_AUTHED, &WorldSession::HandleLfmAutoAddMembersOpcode },
- /*0x35F*/ { "CMSG_LFM_CLEAR_AUTOFILL", STATUS_LOGGEDIN, &WorldSession::HandleLfmCancelAutoAddmembersOpcode},
- /*0x360*/ { "CMSG_ACCEPT_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x361*/ { "CMSG_DECLINE_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x362*/ { "CMSG_CANCEL_PENDING_LFG", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x363*/ { "CMSG_CLEAR_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLfgClearOpcode },
- /*0x364*/ { "CMSG_CLEAR_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetNoneOpcode },
- /*0x365*/ { "CMSG_SET_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetOpcode },
- /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetCommentOpcode },
- /*0x367*/ { "SMSG_LFG_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x368*/ { "SMSG_LFG_OTHER_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x369*/ { "SMSG_LFG_AUTOJOIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x36A*/ { "SMSG_LFG_AUTOJOIN_FAILED_NO_PLAYER",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x36B*/ { "SMSG_LFG_LEADER_IS_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x36C*/ { "SMSG_LFG_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x36D*/ { "SMSG_LFG_UPDATE_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x36E*/ { "SMSG_LFG_UPDATE_LFG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x36F*/ { "SMSG_LFG_UPDATE_QUEUED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x370*/ { "SMSG_LFG_PENDING_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x371*/ { "SMSG_LFG_PENDING_MATCH", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x372*/ { "SMSG_LFG_PENDING_MATCH_DONE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, &WorldSession::HandleChooseTitleOpcode },
- /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, &WorldSession::HandleDismountOpcode },
- /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, &WorldSession::HandleInspectArenaStatsOpcode },
- /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, &WorldSession::HandleCancelTempItemEnchantmentOpcode},
- /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck },
- /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck },
- /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, &WorldSession::HandleSetTaxiBenchmarkOpcode },
- /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, &WorldSession::HandleRealmStateRequestOpcode },
- /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, &WorldSession::HandleGroupPromoteOpcode },
- /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, &WorldSession::HandleAllowMoveAckOpcode },
- /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE",STATUS_NEVER,&WorldSession::Handle_ServerSide },
- /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE",STATUS_NEVER,&WorldSession::Handle_ServerSide},
- /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST",STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
- /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, &WorldSession::HandleVoiceSettingsOpcode },
- /*0x3B0*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3B1*/ { "CMSG_GM_WHISPER", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3B2*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3B3*/ { "MSG_GM_GEARRATING", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3B4*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3B5*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3B6*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3B7*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3B8*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3B9*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3BA*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3BB*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3BC*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3BD*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND",STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3BE*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3BF*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3C0*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3C1*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3C3*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3C4*/ { "SMSG_KICK_REASON", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3C5*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckFinishOpcode},
- /*0x3C6*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleReportSpamOpcode },
- /*0x3C7*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3C8*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3C9*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3CA*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3CB*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3CD*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3CF*/ { "CMSG_TARGET_CAST", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3D0*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3D1*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelRosterQuery },
- /*0x3D2*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, &WorldSession::HandleChannelVoiceChatQuery },
- /*0x3D3*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, &WorldSession::HandleChannelInfoQuery },
- /*0x3D4*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3D5*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, &WorldSession::HandleChannelEnableVoiceOpcode },
- /*0x3D6*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3D7*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3D8*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3D9*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3DA*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3DB*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3DC*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3DD*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3DE*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3DF*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3E0*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3E1*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3E2*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3E3*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundReportAFK },
- /*0x3E4*/ { "CMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3E5*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankQuery },
- /*0x3E6*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabColon },
- /*0x3E7*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3E8*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDepositItem },
- /*0x3E9*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankBuyTab },
- /*0x3EA*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankModifyTab },
- /*0x3EB*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDeposit },
- /*0x3EC*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankWithdraw },
- /*0x3ED*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankLog },
- /*0x3EE*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoinNotify },
- /*0x3EF*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3F0*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3F1*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3F2*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3F3*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3F4*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3F5*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3F6*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3F7*/ { "CMSG_SPELLCLICK", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3F8*/ { "SMSG_LOOT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3F9*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3FA*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x3FB*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x3FC*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetRights },
- /*0x3FD*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetMoneyAmount },
- /*0x3FE*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogOpcode },
- /*0x3FF*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x400*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x401*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x402*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x403*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK",STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x404*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT",STATUS_NEVER,&WorldSession::Handle_NULL },
- /*0x405*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT",STATUS_NEVER,&WorldSession::Handle_ServerSide },
- /*0x406*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, &WorldSession::Handle_EarlyProccess },
- /*0x407*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x408*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, &WorldSession::HandleGroupPassOnLootOpcode },
- /*0x409*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabText },
- /*0x40A*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankSetTabText },
- /*0x40B*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x40C*/ { "CMSG_GRANT_LEVEL", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x40D*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x40E*/ { "MSG_GM_CHANGE_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleRequestAccountData },
+ /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_AUTHED, &WorldSession::HandleUpdateAccountData },
+ /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x20E*/ { "SMSG_POWERGAINLOG_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketGetTicketOpcode },
+ /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x214*/ { "SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseQueryOpcode },
+ /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketDeleteOpcode },
+ /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketSystemStatusOpcode},
+ /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode},
+ /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x21E*/ { "SMSG_SET_REST_START_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, &WorldSession::HandleChatIgnoredOpcode },
+ /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildRankOpcode },
+ /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildAddRankOpcode },
+ /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildDelRankOpcode },
+ /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetPublicNoteOpcode },
+ /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetOfficerNoteOpcode },
+ /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, &WorldSession::HandleSendMail },
+ /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleGetMail },
+ /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundListOpcode },
+ /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x23F*/ { "SMSG_BATTLEFIELD_WIN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x240*/ { "SMSG_BATTLEFIELD_LOSE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemTextQuery },
+ /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleTakeMoney },
+ /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleTakeItem },
+ /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, &WorldSession::HandleMarkAsRead },
+ /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, &WorldSession::HandleReturnToSender },
+ /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleMailDelete },
+ /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailCreateTextItem },
+ /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandleLearnTalentOpcode },
+ /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, &WorldSession::HandleTogglePvP },
+ /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleAuctionHelloOpcode },
+ /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionSellItem },
+ /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionRemoveItem },
+ /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListItems },
+ /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListOwnerItems },
+ /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, &WorldSession::HandleAuctionPlaceBid },
+ /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x261*/ { "SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListBidderItems },
+ /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, &WorldSession::HandleSetAmmoOpcode },
+ /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode },
+ /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandlePetCancelAuraOpcode },
+ /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCancelAutoRepeatSpellOpcode},
+ /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode },
+ /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStablePet },
+ /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleUnstablePet },
+ /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyStableSlot },
+ /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableRevivePet },
+ /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableSwapPet },
+ /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushResult },
+ /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestPetInfoOpcode },
+ /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, &WorldSession::HandleFarSightOpcode },
+ /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleGroupChangeSubGroupOpcode },
+ /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, &WorldSession::HandleRequestPartyMemberStatsOpcode},
+ /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBankItemOpcode },
+ /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoBankItemOpcode },
+ /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, &WorldSession::HandleMsgQueryNextMailtime },
+ /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, &WorldSession::HandleRaidConvertOpcode },
+ /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantOpcode },
+ /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuybackItem },
+ /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x292*/ { "CMSG_MEETINGSTONE_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x293*/ { "CMSG_MEETINGSTONE_LEAVE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x294*/ { "CMSG_MEETINGSTONE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x295*/ { "SMSG_MEETINGSTONE_SETQUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x296*/ { "CMSG_MEETINGSTONE_INFO", STATUS_LOGGEDIN, &WorldSession::HandleMeetingStoneInfo },
+ /*0x297*/ { "SMSG_MEETINGSTONE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x298*/ { "SMSG_MEETINGSTONE_IN_PROGRESS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x29A*/ { "CMSG_GMTICKETSYSTEM_TOGGLE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelGrowthAuraOpcode },
+ /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleLootRoll },
+ /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, &WorldSession::HandleLootMasterGiveOpcode },
+ /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleRepairItemOpcode },
+ /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, &WorldSession::HandleTalentWipeOpcode },
+ /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleSummonResponseOpcode },
+ /*0x2AD*/ { "MSG_MOVE_TOGGLE_GRAVITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, &WorldSession::HandleSelfResOpcode },
+ /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2B9*/ { "CMSG_SHOWING_HELM", STATUS_LOGGEDIN, &WorldSession::HandleToggleHelmOpcode },
+ /*0x2BA*/ { "CMSG_SHOWING_CLOAK", STATUS_LOGGEDIN, &WorldSession::HandleToggleCloakOpcode },
+ /*0x2BB*/ { "SMSG_MEETINGSTONE_JOINFAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, &WorldSession::HandleSetActionBar },
+ /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetitionRenameOpcode },
+ /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemNameQueryOpcode },
+ /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, &WorldSession::HandleChangePlayerNameOpcode },
+ /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNextDestinationOpcode },
+ /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestRaidInfoOpcode },
+ /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, &WorldSession::HandleMoveTimeSkippedOpcode },
+ /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, &WorldSession::HandleFeatherFallAck },
+ /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck },
+ /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleMoveNotActiveMover },
+ /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldStatusOpcode },
+ /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPortOpcode},
+ /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, &WorldSession::HandleInspectHonorStatsOpcode },
+ /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundHelloOpcode },
+ /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
+ /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
+ /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
+ /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPVPlogdataOpcode},
+ /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundLeaveOpcode },
+ /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueryOpcode},
+ /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueueOpcode},
+ /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode },
+ /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPositionsOpcode},
+ /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundJoinOpcode },
+ /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_LOGGEDIN, &WorldSession::HandlePetUnlearnOpcode },
+ /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, &WorldSession::HandlePetSpellAutocastOpcode },
+ /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildChangeInfoOpcode },
+ /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiFarOpcode },
+ /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionInactiveOpcode},
+ /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionIndexOpcode},
+ /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, &WorldSession::HandleResetInstancesOpcode },
+ /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleRaidIconTargetOpcode },
+ /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckOpcode },
+ /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleDungeonDifficultyOpcode },
+ /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_NEVER, &WorldSession::Handle_NULL },//LOGGEDIN, &WorldSession::HandleGMSurveySubmit },
+ /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x33E*/ { "SMSG_MOVE_SET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x33F*/ { "SMSG_MOVE_UNSET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x340*/ { "CMSG_MOVE_FLIGHT_ACK_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveFlyModeChangeAckOpcode},
+ /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, &WorldSession::HandleSocketOpcode },
+ /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x34A*/ { "UMSG_UPDATE_ARENA_TEAM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamQueryOpcode },
+ /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRosterOpcode },
+ /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamAddMemberOpcode },
+ /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteAcceptOpcode},
+ /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteDeclineOpcode},
+ /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaveOpcode },
+ /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRemoveFromTeamOpcode},
+ /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDisbandOpcode },
+ /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamPromoteToCaptainOpcode},
+ /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundArenaJoin },
+ /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x35C*/ { "CMSG_LFG_SET_AUTOJOIN", STATUS_AUTHED, &WorldSession::HandleLfgAutoJoinOpcode },
+ /*0x35D*/ { "CMSG_LFG_CLEAR_AUTOJOIN", STATUS_LOGGEDIN, &WorldSession::HandleLfgCancelAutoJoinOpcode },
+ /*0x35E*/ { "CMSG_LFM_SET_AUTOFILL", STATUS_AUTHED, &WorldSession::HandleLfmAutoAddMembersOpcode },
+ /*0x35F*/ { "CMSG_LFM_CLEAR_AUTOFILL", STATUS_LOGGEDIN, &WorldSession::HandleLfmCancelAutoAddmembersOpcode},
+ /*0x360*/ { "CMSG_ACCEPT_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x361*/ { "CMSG_DECLINE_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x362*/ { "CMSG_CANCEL_PENDING_LFG", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x363*/ { "CMSG_CLEAR_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLfgClearOpcode },
+ /*0x364*/ { "CMSG_CLEAR_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetNoneOpcode },
+ /*0x365*/ { "CMSG_SET_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetOpcode },
+ /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetCommentOpcode },
+ /*0x367*/ { "SMSG_LFG_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x368*/ { "SMSG_LFG_OTHER_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x369*/ { "SMSG_LFG_AUTOJOIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x36A*/ { "SMSG_LFG_AUTOJOIN_FAILED_NO_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x36B*/ { "SMSG_LFG_LEADER_IS_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x36C*/ { "SMSG_LFG_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x36D*/ { "SMSG_LFG_UPDATE_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x36E*/ { "SMSG_LFG_UPDATE_LFG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x36F*/ { "SMSG_LFG_UPDATE_QUEUED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x370*/ { "SMSG_LFG_PENDING_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x371*/ { "SMSG_LFG_PENDING_MATCH", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x372*/ { "SMSG_LFG_PENDING_MATCH_DONE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, &WorldSession::HandleChooseTitleOpcode },
+ /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, &WorldSession::HandleDismountOpcode },
+ /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, &WorldSession::HandleInspectArenaStatsOpcode },
+ /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, &WorldSession::HandleCancelTempItemEnchantmentOpcode},
+ /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
+ /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck },
+ /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, &WorldSession::HandleSetTaxiBenchmarkOpcode },
+ /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, &WorldSession::HandleRealmStateRequestOpcode },
+ /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, &WorldSession::HandleGroupPromoteOpcode },
+ /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, &WorldSession::HandleTimeSyncResp },
+ /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE",STATUS_NEVER,&WorldSession::Handle_ServerSide },
+ /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes },
+ /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, &WorldSession::HandleVoiceSettingsOpcode },
+ /*0x3B0*/ { "SMSG_VOICE_SESSION_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3B1*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3B2*/ { "CMSG_GM_WHISPER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3B3*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3B4*/ { "MSG_GM_GEARRATING", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3B5*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3B6*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3B7*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3B8*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3B9*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3BA*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3BB*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3BC*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3BD*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3BE*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3BF*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3C0*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3C1*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3C3*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3C4*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3C5*/ { "SMSG_KICK_REASON", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3C6*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckFinishOpcode},
+ /*0x3C7*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleReportSpamOpcode },
+ /*0x3C8*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3C9*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3CA*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3CB*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3CD*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3CF*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3D0*/ { "CMSG_TARGET_CAST", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3D1*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3D2*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelRosterQuery },
+ /*0x3D3*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, &WorldSession::HandleChannelVoiceChatQuery },
+ /*0x3D4*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, &WorldSession::HandleChannelInfoQuery },
+ /*0x3D5*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3D6*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, &WorldSession::HandleChannelEnableVoiceOpcode },
+ /*0x3D7*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3D8*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3D9*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3DA*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3DB*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3DC*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3DD*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3DE*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3DF*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3E0*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3E1*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3E2*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3E3*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3E4*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundReportAFK },
+ /*0x3E5*/ { "CMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3E6*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankQuery },
+ /*0x3E7*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabColon },
+ /*0x3E8*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3E9*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDepositItem },
+ /*0x3EA*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankBuyTab },
+ /*0x3EB*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankModifyTab },
+ /*0x3EC*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDeposit },
+ /*0x3ED*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankWithdraw },
+ /*0x3EE*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankLog },
+ /*0x3EF*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoinNotify },
+ /*0x3F0*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3F1*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3F2*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3F3*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3F4*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3F5*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3F6*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3F7*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3F8*/ { "CMSG_SPELLCLICK", STATUS_LOGGEDIN, &WorldSession::HandleSpellClick },
+ /*0x3F9*/ { "SMSG_LOOT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3FA*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3FB*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x3FC*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x3FD*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetRights },
+ /*0x3FE*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetMoneyAmount },
+ /*0x3FF*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogOpcode },
+ /*0x400*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x403*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x404*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x405*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x406*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x407*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, &WorldSession::Handle_EarlyProccess },
+ /*0x408*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x409*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, &WorldSession::HandleGroupPassOnLootOpcode },
+ /*0x40A*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabText },
+ /*0x40B*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankSetTabText },
+ /*0x40C*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x40D*/ { "CMSG_GRANT_LEVEL", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x40E*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x40F*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelDeclineInvite },
- /*0x410*/ { "CMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x411*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x412*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x413*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, &WorldSession::HandleTotemDestroy },
- /*0x414*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x415*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x416*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY",STATUS_LOGGEDIN,&WorldSession::HandleQuestgiverStatusQueryMultipleOpcode},
- /*0x417*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x418*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, &WorldSession::HandleDeclinedPlayerNameOpcode },
- /*0x419*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT",STATUS_NEVER,&WorldSession::Handle_ServerSide },
- /*0x41A*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x41B*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x41C*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x41D*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x41E*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x41F*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x420*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x421*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x422*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x423*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x410*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x411*/ { "CMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x412*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x413*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x414*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, &WorldSession::HandleTotemDestroy },
+ /*0x415*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x416*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x417*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryMultipleOpcode},
+ /*0x418*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x419*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, &WorldSession::HandleDeclinedPlayerNameOpcode },
+ /*0x41A*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x41B*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x41C*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x41D*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x41E*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x41F*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x420*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x421*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x422*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x423*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x424*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x425*/ { "CMSG_CHANGE_PERSONAL_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x426*/ { "CMSG_ALTER_APPEARANCE", STATUS_LOGGEDIN, &WorldSession::HandleAlterAppearance },
+ /*0x427*/ { "SMSG_ENABLE_BARBER_SHOP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x428*/ { "SMSG_BARBER_SHOP_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x429*/ { "CMSG_CALENDAR_GET_CALENDAR", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetCalendar },
+ /*0x42A*/ { "CMSG_CALENDAR_GET_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetEvent },
+ /*0x42B*/ { "CMSG_CALENDAR_GUILD_FILTER", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGuildFilter },
+ /*0x42C*/ { "CMSG_CALENDAR_ARENA_TEAM", STATUS_LOGGEDIN, &WorldSession::HandleCalendarArenaTeam },
+ /*0x42D*/ { "CMSG_CALENDAR_ADD_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarAddEvent },
+ /*0x42E*/ { "CMSG_CALENDAR_UPDATE_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarUpdateEvent },
+ /*0x42F*/ { "CMSG_CALENDAR_REMOVE_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarRemoveEvent },
+ /*0x430*/ { "CMSG_CALENDAR_COPY_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarCopyEvent },
+ /*0x431*/ { "CMSG_CALENDAR_EVENT_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventInvite },
+ /*0x432*/ { "CMSG_CALENDAR_EVENT_RSVP", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventRsvp },
+ /*0x433*/ { "CMSG_CALENDAR_EVENT_REMOVE_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventRemoveInvite },
+ /*0x434*/ { "CMSG_CALENDAR_EVENT_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventStatus },
+ /*0x435*/ { "CMSG_CALENDAR_EVENT_MODERATOR_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventModeratorStatus},
+ /*0x436*/ { "SMSG_CALENDAR_SEND_CALENDAR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x437*/ { "SMSG_CALENDAR_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x438*/ { "SMSG_CALENDAR_FILTER_GUILD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x439*/ { "SMSG_CALENDAR_ARENA_TEAM", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x43A*/ { "SMSG_CALENDAR_EVENT_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x43B*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x43C*/ { "SMSG_CALENDAR_EVENT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x43D*/ { "SMSG_CALENDAR_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x43E*/ { "SMSG_CALENDAR_RAID_LOCKOUT_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x43F*/ { "SMSG_CALENDAR_RAID_LOCKOUT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x440*/ { "SMSG_CALENDAR_EVENT_INVITE_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x441*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x442*/ { "SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x443*/ { "SMSG_CALENDAR_EVENT_REMOVED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x444*/ { "SMSG_CALENDAR_EVENT_UPDATED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x445*/ { "SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x446*/ { "CMSG_CALENDAR_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleCalendarComplain },
+ /*0x447*/ { "CMSG_CALENDAR_GET_NUM_PENDING", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetNumPending },
+ /*0x448*/ { "SMSG_CALENDAR_SEND_NUM_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x449*/ { "CMSG_SAVE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x44A*/ { "SMSG_NOTIFY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x44B*/ { "CMSG_PLAY_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x44C*/ { "SMSG_PLAY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x44D*/ { "CMSG_LOAD_DANCES", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x44E*/ { "CMSG_STOP_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x44F*/ { "SMSG_STOP_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x450*/ { "CMSG_SYNC_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x451*/ { "CMSG_DANCE_QUERY", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x452*/ { "SMSG_DANCE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x453*/ { "SMSG_INVALIDATE_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x454*/ { "CMSG_DELETE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x455*/ { "SMSG_LEARNED_DANCE_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x456*/ { "CMSG_LEARN_DANCE_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x457*/ { "CMSG_UNLEARN_DANCE_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x458*/ { "CMSG_SET_RUNE_COUNT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x459*/ { "CMSG_SET_RUNE_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x45A*/ { "MSG_MOVE_SET_PITCH_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x45B*/ { "MSG_MOVE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x45C*/ { "SMSG_FORCE_PITCH_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x45D*/ { "CMSG_FORCE_PITCH_RATE_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x45E*/ { "SMSG_SPLINE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x45F*/ { "SMSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x460*/ { "MSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x461*/ { "CMSG_MOVE_ABANDON_TRANSPORT_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x464*/ { "SMSG_TRIGGER_MOVIE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x465*/ { "CMSG_COMPLETE_MOVIE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x466*/ { "CMSG_SET_GLYPH_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x467*/ { "CMSG_SET_GLYPH", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x468*/ { "SMSG_ACHIEVEMENT_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x469*/ { "SMSG_DYNAMIC_DROP_ROLL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x46A*/ { "SMSG_CRITERIA_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x46B*/ { "CMSG_QUERY_INSPECT_ACHIEVEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleInspectAchievements },
+ /*0x46C*/ { "SMSG_RESPOND_INSPECT_ACHIEVEMENTS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x46D*/ { "CMSG_DISMISS_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, &WorldSession::HandleDismissControlledVehicle },
+ /*0x46E*/ { "CMSG_COMPLETE_ACHIEVEMENT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x46F*/ { "SMSG_QUESTUPDATE_ADD_PVP_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x470*/ { "CMSG_SET_CRITERIA_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x471*/ { "SMSG_GROUP_SWAP_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x472*/ { "CMSG_UNITANIMTIER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, &WorldSession::HandleCharCustomize },
+ /*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x475*/ { "SMSG_PET_RENAMEABLE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x47A*/ { "CMSG_PET_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandlePetLearnTalent },
+ /*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x47C*/ { "SMSG_SET_PHASE_SHIFT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x47D*/ { "SMSG_ALL_ACHIEVEMENT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x47E*/ { "CMSG_FORCE_SAY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x47F*/ { "SMSG_HEALTH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x480*/ { "SMSG_POWER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x481*/ { "CMSG_GAMEOBJ_REPORT_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameobjectReportUse },
+ /*0x482*/ { "SMSG_HIGHEST_THREAT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x483*/ { "SMSG_THREAT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x484*/ { "SMSG_THREAT_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x485*/ { "SMSG_THREAT_CLEAR", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x486*/ { "SMSG_CONVERT_RUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x487*/ { "SMSG_RESYNC_RUNES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x488*/ { "SMSG_ADD_RUNE_POWER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x489*/ { "CMSG_START_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x48A*/ { "CMSG_REMOVE_GLYPH", STATUS_LOGGEDIN, &WorldSession::HandleRemoveGlyph },
+ /*0x48B*/ { "CMSG_DUMP_OBJECTS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x48C*/ { "SMSG_DUMP_OBJECTS_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x48D*/ { "CMSG_DISMISS_CRITTER", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x48E*/ { "SMSG_NOTIFY_DEST_LOC_SPELL_CAST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x48F*/ { "CMSG_AUCTION_LIST_PENDING_SALES", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListPendingSales },
+ /*0x490*/ { "SMSG_AUCTION_LIST_PENDING_SALES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x491*/ { "SMSG_MODIFY_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x492*/ { "SMSG_PET_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x493*/ { "CMSG_ENABLETAXI", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodes },
+ /*0x494*/ { "SMSG_PRE_RESURRECT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x495*/ { "SMSG_AURA_UPDATE_ALL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x496*/ { "SMSG_AURA_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x497*/ { "CMSG_FLOOD_GRACE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x49A*/ { "SMSG_PET_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x49E*/ { "SMSG_CRITERIA_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x49F*/ { "SMSG_ACHIEVEMENT_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4A0*/ { "CMSG_SERVER_INFO_QUERY", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4A1*/ { "SMSG_SERVER_INFO_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4A2*/ { "CMSG_CHECK_LOGIN_CRITERIA", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4A3*/ { "SMSG_SERVER_BUCK_DATA_START", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4A4*/ { "CMSG_QUERY_VEHICLE_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4A5*/ { "SMSG_PET_GUIDS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4A6*/ { "SMSG_CLIENTCACHE_VERSION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4A7*/ { "UMSG_UNKNOWN_1191", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4A8*/ { "UMSG_UNKNOWN_1192", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4A9*/ { "UMSG_UNKNOWN_1193", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4AA*/ { "UMSG_UNKNOWN_1194", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4AB*/ { "UMSG_UNKNOWN_1195", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4AC*/ { "UMSG_UNKNOWN_1196", STATUS_NEVER, &WorldSession::Handle_NULL },
};
diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h
index 202166a57a0..f4d7800d2d9 100644
--- a/src/game/Opcodes.h
+++ b/src/game/Opcodes.h
@@ -49,8 +49,8 @@ enum Opcodes
CMSG_ZONE_MAP = 0x00A,
SMSG_ZONE_MAP = 0x00B,
CMSG_DEBUG_CHANGECELLZONE = 0x00C,
- CMSG_EMBLAZON_TABARD_OBSOLETE = 0x00D,
- CMSG_UNEMBLAZON_TABARD_OBSOLETE = 0x00E,
+ CMSG_MOVE_CHARACTER_CHEAT = 0x00D,
+ SMSG_MOVE_CHARACTER_CHEAT = 0x00E,
CMSG_RECHARGE = 0x00F,
CMSG_LEARN_SPELL = 0x010,
CMSG_CREATEMONSTER = 0x011,
@@ -66,7 +66,7 @@ enum Opcodes
SMSG_FORCEACTIONSHOW = 0x01B,
CMSG_PETGODMODE = 0x01C,
SMSG_PETGODMODE = 0x01D,
- SMSG_DEBUGINFOSPELLMISS_OBSOLETE = 0x01E,
+ SMSG_REFER_A_FRIEND_EXPIRED = 0x01E,
CMSG_WEATHER_SPEED_CHEAT = 0x01F,
CMSG_UNDRESSPLAYER = 0x020,
CMSG_BEASTMASTER = 0x021,
@@ -86,7 +86,7 @@ enum Opcodes
SMSG_DEBUG_AISTATE = 0x02F,
CMSG_DISABLE_PVP_CHEAT = 0x030,
CMSG_ADVANCE_SPAWN_TIME = 0x031,
- CMSG_PVP_PORT_OBSOLETE = 0x032,
+ SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x032,
CMSG_AUTH_SRP6_BEGIN = 0x033,
CMSG_AUTH_SRP6_PROOF = 0x034,
CMSG_AUTH_SRP6_RECODE = 0x035,
@@ -214,7 +214,7 @@ enum Opcodes
SMSG_READ_ITEM_FAILED = 0x0AF,
SMSG_ITEM_COOLDOWN = 0x0B0,
CMSG_GAMEOBJ_USE = 0x0B1,
- CMSG_GAMEOBJ_CHAIR_USE_OBSOLETE = 0x0B2,
+ CMSG_DESTROY_ITEMS = 0x0B2,
SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x0B3,
CMSG_AREATRIGGER = 0x0B4,
MSG_MOVE_START_FORWARD = 0x0B5,
@@ -347,7 +347,7 @@ enum Opcodes
SMSG_SPELL_COOLDOWN = 0x134,
SMSG_COOLDOWN_EVENT = 0x135,
CMSG_CANCEL_AURA = 0x136,
- SMSG_UPDATE_AURA_DURATION = 0x137,
+ SMSG_UPDATE_AURA_DURATION_OBSOLETE = 0x137,
SMSG_PET_CAST_FAILED = 0x138,
MSG_CHANNEL_START = 0x139,
MSG_CHANNEL_UPDATE = 0x13A,
@@ -371,10 +371,10 @@ enum Opcodes
SMSG_DAMAGE_DONE_OBSOLETE = 0x14C,
SMSG_DAMAGE_TAKEN_OBSOLETE = 0x14D,
SMSG_CANCEL_COMBAT = 0x14E,
- SMSG_PLAYER_COMBAT_XP_GAIN_OBSOLETE = 0x14F,
+ SMSG_SPELLBREAKLOG = 0x14F,
SMSG_SPELLHEALLOG = 0x150,
SMSG_SPELLENERGIZELOG = 0x151,
- CMSG_SHEATHE_OBSOLETE = 0x152,
+ SMSG_BREAK_TARGET = 0x152,
CMSG_SAVE_PLAYER = 0x153,
CMSG_SETDEATHBINDPOINT = 0x154,
SMSG_BINDPOINTUPDATE = 0x155,
@@ -578,7 +578,7 @@ enum Opcodes
SMSG_GMTICKET_SYSTEMSTATUS = 0x21B,
CMSG_SPIRIT_HEALER_ACTIVATE = 0x21C,
CMSG_SET_STAT_CHEAT = 0x21D,
- SMSG_SET_REST_START = 0x21E,
+ SMSG_SET_REST_START_OBSOLETE = 0x21E,
CMSG_SKILL_BUY_STEP = 0x21F,
CMSG_SKILL_BUY_RANK = 0x220,
CMSG_XP_CHEAT = 0x221,
@@ -733,8 +733,8 @@ enum Opcodes
SMSG_SCRIPT_MESSAGE = 0x2B6,
SMSG_DUEL_COUNTDOWN = 0x2B7,
SMSG_AREA_TRIGGER_MESSAGE = 0x2B8,
- CMSG_TOGGLE_HELM = 0x2B9,
- CMSG_TOGGLE_CLOAK = 0x2BA,
+ CMSG_SHOWING_HELM = 0x2B9,
+ CMSG_SHOWING_CLOAK = 0x2BA,
SMSG_MEETINGSTONE_JOINFAILED = 0x2BB,
SMSG_PLAYER_SKINNED = 0x2BC,
SMSG_DURABILITY_DAMAGE_DEATH = 0x2BD,
@@ -967,10 +967,10 @@ enum Opcodes
SMSG_VOICE_SESSION_ADJUST_PRIORITY = 0x3A0,
CMSG_VOICE_SET_TALKER_MUTED_REQUEST = 0x3A1,
SMSG_VOICE_SET_TALKER_MUTED = 0x3A2,
- SMSG_INIT_EXTRA_AURA_INFO = 0x3A3,
- SMSG_SET_EXTRA_AURA_INFO = 0x3A4,
- SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE = 0x3A5,
- SMSG_CLEAR_EXTRA_AURA_INFO = 0x3A6,
+ SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE = 0x3A3,
+ SMSG_SET_EXTRA_AURA_INFO_OBSOLETE = 0x3A4,
+ SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE = 0x3A5,
+ SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE = 0x3A6,
MSG_MOVE_START_DESCEND = 0x3A7,
CMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A8,
SMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A9,
@@ -980,127 +980,262 @@ enum Opcodes
MSG_MOVE_UPDATE_CAN_FLY = 0x3AD,
MSG_RAID_READY_CHECK_CONFIRM = 0x3AE,
CMSG_VOICE_SESSION_ENABLE = 0x3AF,
- SMSG_VOICE_PARENTAL_CONTROLS = 0x3B0,
- CMSG_GM_WHISPER = 0x3B1,
- SMSG_GM_MESSAGECHAT = 0x3B2,
- MSG_GM_GEARRATING = 0x3B3,
- CMSG_COMMENTATOR_ENABLE = 0x3B4,
- SMSG_COMMENTATOR_STATE_CHANGED = 0x3B5,
- CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B6,
- SMSG_COMMENTATOR_MAP_INFO = 0x3B7,
- CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B8,
- SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9,
- SMSG_COMMENTATOR_PLAYER_INFO = 0x3BA,
- CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BB,
- CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BC,
- CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BD,
- SMSG_CLEAR_TARGET = 0x3BE,
- CMSG_BOT_DETECTED = 0x3BF,
- SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C0,
- CMSG_CHEAT_PLAYER_LOGIN = 0x3C1,
- CMSG_CHEAT_PLAYER_LOOKUP = 0x3C2,
- SMSG_CHEAT_PLAYER_LOOKUP = 0x3C3,
- SMSG_KICK_REASON = 0x3C4,
- MSG_RAID_READY_CHECK_FINISHED = 0x3C5,
- CMSG_COMPLAIN = 0x3C6,
- SMSG_COMPLAIN_RESULT = 0x3C7,
- SMSG_FEATURE_SYSTEM_STATUS = 0x3C8,
- CMSG_GM_SHOW_COMPLAINTS = 0x3C9,
- CMSG_GM_UNSQUELCH = 0x3CA,
- CMSG_CHANNEL_SILENCE_VOICE = 0x3CB,
- CMSG_CHANNEL_SILENCE_ALL = 0x3CC,
- CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CD,
- CMSG_CHANNEL_UNSILENCE_ALL = 0x3CE,
- CMSG_TARGET_CAST = 0x3CF,
- CMSG_TARGET_SCRIPT_CAST = 0x3D0,
- CMSG_CHANNEL_DISPLAY_LIST = 0x3D1,
- CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D2,
- CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D3,
- SMSG_CHANNEL_MEMBER_COUNT = 0x3D4,
- CMSG_CHANNEL_VOICE_ON = 0x3D5,
- CMSG_CHANNEL_VOICE_OFF = 0x3D6,
- CMSG_DEBUG_LIST_TARGETS = 0x3D7,
- SMSG_DEBUG_LIST_TARGETS = 0x3D8,
- SMSG_AVAILABLE_VOICE_CHANNEL = 0x3D9,
- CMSG_ADD_VOICE_IGNORE = 0x3DA,
- CMSG_DEL_VOICE_IGNORE = 0x3DB,
- CMSG_PARTY_SILENCE = 0x3DC,
- CMSG_PARTY_UNSILENCE = 0x3DD,
- MSG_NOTIFY_PARTY_SQUELCH = 0x3DE,
- SMSG_COMSAT_RECONNECT_TRY = 0x3DF,
- SMSG_COMSAT_DISCONNECT = 0x3E0,
- SMSG_COMSAT_CONNECT_FAIL = 0x3E1,
- SMSG_VOICE_CHAT_STATUS = 0x3E2,
- CMSG_REPORT_PVP_AFK = 0x3E3,
- CMSG_REPORT_PVP_AFK_RESULT = 0x3E4,
- CMSG_GUILD_BANKER_ACTIVATE = 0x3E5,
- CMSG_GUILD_BANK_QUERY_TAB = 0x3E6,
- SMSG_GUILD_BANK_LIST = 0x3E7,
- CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E8,
- CMSG_GUILD_BANK_BUY_TAB = 0x3E9,
- CMSG_GUILD_BANK_UPDATE_TAB = 0x3EA,
- CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EB,
- CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3EC,
- MSG_GUILD_BANK_LOG_QUERY = 0x3ED,
- CMSG_SET_CHANNEL_WATCH = 0x3EE,
- SMSG_USERLIST_ADD = 0x3EF,
- SMSG_USERLIST_REMOVE = 0x3F0,
- SMSG_USERLIST_UPDATE = 0x3F1,
- CMSG_CLEAR_CHANNEL_WATCH = 0x3F2,
- SMSG_INSPECT_TALENT = 0x3F3,
- SMSG_GOGOGO_OBSOLETE = 0x3F4,
- SMSG_ECHO_PARTY_SQUELCH = 0x3F5,
- CMSG_SET_TITLE_SUFFIX = 0x3F6,
- CMSG_SPELLCLICK = 0x3F7,
- SMSG_LOOT_LIST = 0x3F8,
- CMSG_GM_CHARACTER_RESTORE = 0x3F9,
- CMSG_GM_CHARACTER_SAVE = 0x3FA,
- SMSG_VOICESESSION_FULL = 0x3FB,
- MSG_GUILD_PERMISSIONS = 0x3FC,
- MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FD,
- MSG_GUILD_EVENT_LOG_QUERY = 0x3FE,
- CMSG_MAELSTROM_RENAME_GUILD = 0x3FF,
- CMSG_GET_MIRRORIMAGE_DATA = 0x400,
- SMSG_MIRRORIMAGE_DATA = 0x401,
- SMSG_FORCE_DISPLAY_UPDATE = 0x402,
- SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x403,
- CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x404,
- SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405,
- CMSG_KEEP_ALIVE = 0x406,
- SMSG_RAID_READY_CHECK_ERROR = 0x407,
- CMSG_OPT_OUT_OF_LOOT = 0x408,
- MSG_QUERY_GUILD_BANK_TEXT = 0x409,
- CMSG_SET_GUILD_BANK_TEXT = 0x40A,
- CMSG_SET_GRANTABLE_LEVELS = 0x40B,
- CMSG_GRANT_LEVEL = 0x40C,
- CMSG_REFER_A_FRIEND = 0x40D,
- MSG_GM_CHANGE_ARENA_RATING = 0x40E,
- CMSG_DECLINE_CHANNEL_INVITE = 0x40F,
- CMSG_GROUPACTION_THROTTLED = 0x410,
- SMSG_OVERRIDE_LIGHT = 0x411,
- SMSG_TOTEM_CREATED = 0x412,
- CMSG_TOTEM_DESTROYED = 0x413,
- CMSG_EXPIRE_RAID_INSTANCE = 0x414,
- CMSG_NO_SPELL_VARIANCE = 0x415,
- CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x416,
- SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x417,
- CMSG_SET_PLAYER_DECLINED_NAMES = 0x418,
- SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x419,
- CMSG_QUERY_SERVER_BUCK_DATA = 0x41A,
- CMSG_CLEAR_SERVER_BUCK_DATA = 0x41B,
- SMSG_SERVER_BUCK_DATA = 0x41C,
- SMSG_SEND_UNLEARN_SPELLS = 0x41D,
- SMSG_PROPOSE_LEVEL_GRANT = 0x41E,
- CMSG_ACCEPT_LEVEL_GRANT = 0x41F,
- SMSG_REFER_A_FRIEND_FAILURE = 0x420,
- SMSG_SPLINE_MOVE_SET_FLYING = 0x421,
- SMSG_SPLINE_MOVE_UNSET_FLYING = 0x422,
- SMSG_SUMMON_CANCEL = 0x423
+ SMSG_VOICE_SESSION_ENABLE = 0x3B0,
+ SMSG_VOICE_PARENTAL_CONTROLS = 0x3B1,
+ CMSG_GM_WHISPER = 0x3B2,
+ SMSG_GM_MESSAGECHAT = 0x3B3,
+ MSG_GM_GEARRATING = 0x3B4,
+ CMSG_COMMENTATOR_ENABLE = 0x3B5,
+ SMSG_COMMENTATOR_STATE_CHANGED = 0x3B6,
+ CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B7,
+ SMSG_COMMENTATOR_MAP_INFO = 0x3B8,
+ CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9,
+ SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3BA,
+ SMSG_COMMENTATOR_PLAYER_INFO = 0x3BB,
+ CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BC,
+ CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BD,
+ CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BE,
+ SMSG_CLEAR_TARGET = 0x3BF,
+ CMSG_BOT_DETECTED = 0x3C0,
+ SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C1,
+ CMSG_CHEAT_PLAYER_LOGIN = 0x3C2,
+ CMSG_CHEAT_PLAYER_LOOKUP = 0x3C3,
+ SMSG_CHEAT_PLAYER_LOOKUP = 0x3C4,
+ SMSG_KICK_REASON = 0x3C5,
+ MSG_RAID_READY_CHECK_FINISHED = 0x3C6,
+ CMSG_COMPLAIN = 0x3C7,
+ SMSG_COMPLAIN_RESULT = 0x3C8,
+ SMSG_FEATURE_SYSTEM_STATUS = 0x3C9,
+ CMSG_GM_SHOW_COMPLAINTS = 0x3CA,
+ CMSG_GM_UNSQUELCH = 0x3CB,
+ CMSG_CHANNEL_SILENCE_VOICE = 0x3CC,
+ CMSG_CHANNEL_SILENCE_ALL = 0x3CD,
+ CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CE,
+ CMSG_CHANNEL_UNSILENCE_ALL = 0x3CF,
+ CMSG_TARGET_CAST = 0x3D0,
+ CMSG_TARGET_SCRIPT_CAST = 0x3D1,
+ CMSG_CHANNEL_DISPLAY_LIST = 0x3D2,
+ CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D3,
+ CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D4,
+ SMSG_CHANNEL_MEMBER_COUNT = 0x3D5,
+ CMSG_CHANNEL_VOICE_ON = 0x3D6,
+ CMSG_CHANNEL_VOICE_OFF = 0x3D7,
+ CMSG_DEBUG_LIST_TARGETS = 0x3D8,
+ SMSG_DEBUG_LIST_TARGETS = 0x3D9,
+ SMSG_AVAILABLE_VOICE_CHANNEL = 0x3DA,
+ CMSG_ADD_VOICE_IGNORE = 0x3DB,
+ CMSG_DEL_VOICE_IGNORE = 0x3DC,
+ CMSG_PARTY_SILENCE = 0x3DD,
+ CMSG_PARTY_UNSILENCE = 0x3DE,
+ MSG_NOTIFY_PARTY_SQUELCH = 0x3DF,
+ SMSG_COMSAT_RECONNECT_TRY = 0x3E0,
+ SMSG_COMSAT_DISCONNECT = 0x3E1,
+ SMSG_COMSAT_CONNECT_FAIL = 0x3E2,
+ SMSG_VOICE_CHAT_STATUS = 0x3E3,
+ CMSG_REPORT_PVP_AFK = 0x3E4,
+ CMSG_REPORT_PVP_AFK_RESULT = 0x3E5,
+ CMSG_GUILD_BANKER_ACTIVATE = 0x3E6,
+ CMSG_GUILD_BANK_QUERY_TAB = 0x3E7,
+ SMSG_GUILD_BANK_LIST = 0x3E8,
+ CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E9,
+ CMSG_GUILD_BANK_BUY_TAB = 0x3EA,
+ CMSG_GUILD_BANK_UPDATE_TAB = 0x3EB,
+ CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EC,
+ CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3ED,
+ MSG_GUILD_BANK_LOG_QUERY = 0x3EE,
+ CMSG_SET_CHANNEL_WATCH = 0x3EF,
+ SMSG_USERLIST_ADD = 0x3F0,
+ SMSG_USERLIST_REMOVE = 0x3F1,
+ SMSG_USERLIST_UPDATE = 0x3F2,
+ CMSG_CLEAR_CHANNEL_WATCH = 0x3F3,
+ SMSG_INSPECT_TALENT = 0x3F4,
+ SMSG_GOGOGO_OBSOLETE = 0x3F5,
+ SMSG_ECHO_PARTY_SQUELCH = 0x3F6,
+ CMSG_SET_TITLE_SUFFIX = 0x3F7,
+ CMSG_SPELLCLICK = 0x3F8,
+ SMSG_LOOT_LIST = 0x3F9,
+ CMSG_GM_CHARACTER_RESTORE = 0x3FA,
+ CMSG_GM_CHARACTER_SAVE = 0x3FB,
+ SMSG_VOICESESSION_FULL = 0x3FC,
+ MSG_GUILD_PERMISSIONS = 0x3FD,
+ MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FE,
+ MSG_GUILD_EVENT_LOG_QUERY = 0x3FF,
+ CMSG_MAELSTROM_RENAME_GUILD = 0x400,
+ CMSG_GET_MIRRORIMAGE_DATA = 0x401,
+ SMSG_MIRRORIMAGE_DATA = 0x402,
+ SMSG_FORCE_DISPLAY_UPDATE = 0x403,
+ SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x404,
+ CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405,
+ SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x406,
+ CMSG_KEEP_ALIVE = 0x407,
+ SMSG_RAID_READY_CHECK_ERROR = 0x408,
+ CMSG_OPT_OUT_OF_LOOT = 0x409,
+ MSG_QUERY_GUILD_BANK_TEXT = 0x40A,
+ CMSG_SET_GUILD_BANK_TEXT = 0x40B,
+ CMSG_SET_GRANTABLE_LEVELS = 0x40C,
+ CMSG_GRANT_LEVEL = 0x40D,
+ CMSG_REFER_A_FRIEND = 0x40E,
+ MSG_GM_CHANGE_ARENA_RATING = 0x40F,
+ CMSG_DECLINE_CHANNEL_INVITE = 0x410,
+ CMSG_GROUPACTION_THROTTLED = 0x411,
+ SMSG_OVERRIDE_LIGHT = 0x412,
+ SMSG_TOTEM_CREATED = 0x413,
+ CMSG_TOTEM_DESTROYED = 0x414,
+ CMSG_EXPIRE_RAID_INSTANCE = 0x415,
+ CMSG_NO_SPELL_VARIANCE = 0x416,
+ CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x417,
+ SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x418,
+ CMSG_SET_PLAYER_DECLINED_NAMES = 0x419,
+ SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x41A,
+ CMSG_QUERY_SERVER_BUCK_DATA = 0x41B,
+ CMSG_CLEAR_SERVER_BUCK_DATA = 0x41C,
+ SMSG_SERVER_BUCK_DATA = 0x41D,
+ SMSG_SEND_UNLEARN_SPELLS = 0x41E,
+ SMSG_PROPOSE_LEVEL_GRANT = 0x41F,
+ CMSG_ACCEPT_LEVEL_GRANT = 0x420,
+ SMSG_REFER_A_FRIEND_FAILURE = 0x421,
+ SMSG_SPLINE_MOVE_SET_FLYING = 0x422,
+ SMSG_SPLINE_MOVE_UNSET_FLYING = 0x423,
+ SMSG_SUMMON_CANCEL = 0x424,
+ CMSG_CHANGE_PERSONAL_ARENA_RATING = 0x425,
+ CMSG_ALTER_APPEARANCE = 0x426,
+ SMSG_ENABLE_BARBER_SHOP = 0x427,
+ SMSG_BARBER_SHOP_RESULT = 0x428,
+ CMSG_CALENDAR_GET_CALENDAR = 0x429,
+ CMSG_CALENDAR_GET_EVENT = 0x42A,
+ CMSG_CALENDAR_GUILD_FILTER = 0x42B,
+ CMSG_CALENDAR_ARENA_TEAM = 0x42C,
+ CMSG_CALENDAR_ADD_EVENT = 0x42D,
+ CMSG_CALENDAR_UPDATE_EVENT = 0x42E,
+ CMSG_CALENDAR_REMOVE_EVENT = 0x42F,
+ CMSG_CALENDAR_COPY_EVENT = 0x430,
+ CMSG_CALENDAR_EVENT_INVITE = 0x431,
+ CMSG_CALENDAR_EVENT_RSVP = 0x432,
+ CMSG_CALENDAR_EVENT_REMOVE_INVITE = 0x433,
+ CMSG_CALENDAR_EVENT_STATUS = 0x434,
+ CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x435,
+ SMSG_CALENDAR_SEND_CALENDAR = 0x436,
+ SMSG_CALENDAR_SEND_EVENT = 0x437,
+ SMSG_CALENDAR_FILTER_GUILD = 0x438,
+ SMSG_CALENDAR_ARENA_TEAM = 0x439,
+ SMSG_CALENDAR_EVENT_INVITE = 0x43A,
+ SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x43B,
+ SMSG_CALENDAR_EVENT_STATUS = 0x43C,
+ SMSG_CALENDAR_COMMAND_RESULT = 0x43D,
+ SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x43E,
+ SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x43F,
+ SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x440,
+ SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x441,
+ SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x442,
+ SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x443,
+ SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444,
+ SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445,
+ CMSG_CALENDAR_COMPLAIN = 0x446,
+ CMSG_CALENDAR_GET_NUM_PENDING = 0x447,
+ SMSG_CALENDAR_SEND_NUM_PENDING = 0x448,
+ CMSG_SAVE_DANCE = 0x449,
+ SMSG_NOTIFY_DANCE = 0x44A,
+ CMSG_PLAY_DANCE = 0x44B,
+ SMSG_PLAY_DANCE = 0x44C,
+ CMSG_LOAD_DANCES = 0x44D,
+ CMSG_STOP_DANCE = 0x44E,
+ SMSG_STOP_DANCE = 0x44F,
+ CMSG_SYNC_DANCE = 0x450,
+ CMSG_DANCE_QUERY = 0x451,
+ SMSG_DANCE_QUERY_RESPONSE = 0x452,
+ SMSG_INVALIDATE_DANCE = 0x453,
+ CMSG_DELETE_DANCE = 0x454,
+ SMSG_LEARNED_DANCE_MOVES = 0x455,
+ CMSG_LEARN_DANCE_MOVE = 0x456,
+ CMSG_UNLEARN_DANCE_MOVE = 0x457,
+ CMSG_SET_RUNE_COUNT = 0x458,
+ CMSG_SET_RUNE_COOLDOWN = 0x459,
+ MSG_MOVE_SET_PITCH_RATE_CHEAT = 0x45A,
+ MSG_MOVE_SET_PITCH_RATE = 0x45B,
+ SMSG_FORCE_PITCH_RATE_CHANGE = 0x45C,
+ CMSG_FORCE_PITCH_RATE_CHANGE_ACK = 0x45D,
+ SMSG_SPLINE_SET_PITCH_RATE = 0x45E,
+ SMSG_MOVE_ABANDON_TRANSPORT = 0x45F,
+ MSG_MOVE_ABANDON_TRANSPORT = 0x460,
+ CMSG_MOVE_ABANDON_TRANSPORT_ACK = 0x461,
+ CMSG_UPDATE_MISSILE_TRAJECTORY = 0x462,
+ SMSG_UPDATE_ACCOUNT_DATA_COMPLETE = 0x463,
+ SMSG_TRIGGER_MOVIE = 0x464,
+ CMSG_COMPLETE_MOVIE = 0x465,
+ CMSG_SET_GLYPH_SLOT = 0x466,
+ CMSG_SET_GLYPH = 0x467,
+ SMSG_ACHIEVEMENT_EARNED = 0x468,
+ SMSG_DYNAMIC_DROP_ROLL_RESULT = 0x469,
+ SMSG_CRITERIA_UPDATE = 0x46A,
+ CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x46B,
+ SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x46C,
+ CMSG_DISMISS_CONTROLLED_VEHICLE = 0x46D,
+ CMSG_COMPLETE_ACHIEVEMENT_CHEAT = 0x46E,
+ SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x46F,
+ CMSG_SET_CRITERIA_CHEAT = 0x470,
+ SMSG_GROUP_SWAP_FAILED = 0x471,
+ CMSG_UNITANIMTIER_CHEAT = 0x472,
+ CMSG_CHAR_CUSTOMIZE = 0x473,
+ SMSG_CHAR_CUSTOMIZE = 0x474,
+ SMSG_PET_RENAMEABLE = 0x475,
+ CMSG_REQUEST_VEHICLE_EXIT = 0x476,
+ CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x477,
+ CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x478,
+ CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x479,
+ CMSG_PET_LEARN_TALENT = 0x47A,
+ CMSG_PET_UNLEARN_TALENTS = 0x47B,
+ SMSG_SET_PHASE_SHIFT = 0x47C,
+ SMSG_ALL_ACHIEVEMENT_DATA = 0x47D,
+ CMSG_FORCE_SAY_CHEAT = 0x47E,
+ SMSG_HEALTH_UPDATE = 0x47F,
+ SMSG_POWER_UPDATE = 0x480,
+ CMSG_GAMEOBJ_REPORT_USE = 0x481,
+ SMSG_HIGHEST_THREAT_UPDATE = 0x482,
+ SMSG_THREAT_UPDATE = 0x483,
+ SMSG_THREAT_REMOVE = 0x484,
+ SMSG_THREAT_CLEAR = 0x485,
+ SMSG_CONVERT_RUNE = 0x486,
+ SMSG_RESYNC_RUNES = 0x487,
+ SMSG_ADD_RUNE_POWER = 0x488,
+ CMSG_START_QUEST = 0x489,
+ CMSG_REMOVE_GLYPH = 0x48A,
+ CMSG_DUMP_OBJECTS = 0x48B,
+ SMSG_DUMP_OBJECTS_DATA = 0x48C,
+ CMSG_DISMISS_CRITTER = 0x48D,
+ SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x48E,
+ CMSG_AUCTION_LIST_PENDING_SALES = 0x48F,
+ SMSG_AUCTION_LIST_PENDING_SALES = 0x490,
+ SMSG_MODIFY_COOLDOWN = 0x491,
+ SMSG_PET_UPDATE_COMBO_POINTS = 0x492,
+ CMSG_ENABLETAXI = 0x493,
+ SMSG_PRE_RESURRECT = 0x494,
+ SMSG_AURA_UPDATE_ALL = 0x495,
+ SMSG_AURA_UPDATE = 0x496,
+ CMSG_FLOOD_GRACE_CHEAT = 0x497,
+ SMSG_SERVER_FIRST_ACHIEVEMENT = 0x498,
+ SMSG_PET_LEARNED_SPELL = 0x499,
+ SMSG_PET_REMOVED_SPELL = 0x49A,
+ CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE = 0x49B,
+ CMSG_HEARTH_AND_RESURRECT = 0x49C,
+ SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x49D,
+ SMSG_CRITERIA_DELETED = 0x49E,
+ SMSG_ACHIEVEMENT_DELETED = 0x49F,
+ CMSG_SERVER_INFO_QUERY = 0x4A0,
+ SMSG_SERVER_INFO_RESPONSE = 0x4A1,
+ CMSG_CHECK_LOGIN_CRITERIA = 0x4A2,
+ SMSG_SERVER_BUCK_DATA_START = 0x4A3,
+ CMSG_QUERY_VEHICLE_STATUS = 0x4A4,
+ SMSG_PET_GUIDS = 0x4A5,
+ SMSG_CLIENTCACHE_VERSION = 0x4A6,
+ UMSG_UNKNOWN_1191 = 0x4A7,
+ UMSG_UNKNOWN_1192 = 0x4A8,
+ UMSG_UNKNOWN_1193 = 0x4A9,
+ UMSG_UNKNOWN_1194 = 0x4AA,
+ UMSG_UNKNOWN_1195 = 0x4AB,
+ UMSG_UNKNOWN_1196 = 0x4AC,
+ NUM_MSG_TYPES = 0x4AD
};
-// Don't forget to change this value and add opcode name to Opcodes.cpp when you add new opcode!
-#define NUM_MSG_TYPES 0x424
-
/// Player state
enum SessionStatus
{
diff --git a/src/game/OutdoorPvP.cpp b/src/game/OutdoorPvP.cpp
index 06d56897f1e..602534f8c36 100644
--- a/src/game/OutdoorPvP.cpp
+++ b/src/game/OutdoorPvP.cpp
@@ -95,7 +95,7 @@ bool OutdoorPvPObjective::AddObject(uint32 type, uint32 entry, uint32 map, float
if(!pMap)
return true;
GameObject * go = new GameObject;
- if(!go->Create(guid,entry, pMap,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1))
+ if(!go->Create(guid,entry, pMap,PHASEMASK_NORMAL,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1))
{
sLog.outError("Gameobject template %u not found in database.", entry);
delete go;
@@ -156,7 +156,7 @@ bool OutdoorPvPObjective::AddCreature(uint32 type, uint32 entry, uint32 teamval,
if(!pMap)
return true;
Creature* pCreature = new Creature;
- if (!pCreature->Create(guid, pMap, entry, teamval))
+ if (!pCreature->Create(guid, pMap, PHASEMASK_NORMAL, entry, teamval))
{
sLog.outError("Can't create creature entry: %u",entry);
delete pCreature;
@@ -256,7 +256,7 @@ bool OutdoorPvPObjective::AddCapturePoint(uint32 entry, uint32 map, float x, flo
return true;
// add GO...
GameObject * go = new GameObject;
- if(!go->Create(guid,entry, pMap,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1))
+ if(!go->Create(guid,entry, pMap,PHASEMASK_NORMAL,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1))
{
sLog.outError("Gameobject template %u not found in database.", entry);
delete go;
@@ -269,7 +269,7 @@ bool OutdoorPvPObjective::AddCapturePoint(uint32 entry, uint32 map, float x, flo
}
// add creature...
Creature* pCreature = new Creature;
- if (!pCreature->Create(creature_guid, pMap, OPVP_TRIGGER_CREATURE_ENTRY, 0))
+ if (!pCreature->Create(creature_guid, pMap, PHASEMASK_NORMAL, OPVP_TRIGGER_CREATURE_ENTRY, 0))
{
sLog.outError("Can't create creature entry: %u",entry);
delete pCreature;
diff --git a/src/game/OutdoorPvPSI.cpp b/src/game/OutdoorPvPSI.cpp
index bae0d82318d..ceb37ff5349 100644
--- a/src/game/OutdoorPvPSI.cpp
+++ b/src/game/OutdoorPvPSI.cpp
@@ -202,7 +202,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player *plr, uint32 spellId)
Map * map = MapManager::Instance().GetMap(plr->GetMapId(), plr);
if(!map)
return true;
- if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map,plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,1))
+ if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map, plr->GetPhaseMask(), plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,1))
{
delete go;
}
@@ -228,7 +228,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player *plr, uint32 spellId)
Map * map = MapManager::Instance().GetMap(plr->GetMapId(), plr);
if(!map)
return true;
- if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map ,plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,1))
+ if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map, plr->GetPhaseMask() ,plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,1))
{
delete go;
}
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index cafebf45f3f..2cf9214fd7a 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -41,46 +41,14 @@ char const* petTypeSuffix[MAX_PET_TYPE] =
"'s Companion" // MINI_PET
};
-//numbers represent minutes * 100 while happy (you get 100 loyalty points per min while happy)
-uint32 const LevelUpLoyalty[6] =
-{
- 5500,
- 11500,
- 17000,
- 23500,
- 31000,
- 39500,
-};
-
-uint32 const LevelStartLoyalty[6] =
-{
- 2000,
- 4500,
- 7000,
- 10000,
- 13500,
- 17500,
-};
-
-Pet::Pet(PetType type) : Creature()
+Pet::Pet(PetType type) :
+Creature(), m_petType(type), m_removed(false), m_happinessTimer(7500), m_duration(0), m_bonusdamage(0),
+m_resetTalentsCost(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraUpdateMask(0), m_loading(false),
+m_declinedname(NULL)
{
m_isPet = true;
m_name = "Pet";
- m_petType = type;
-
- m_removed = false;
m_regenTimer = 4000;
- m_happinessTimer = 7500;
- m_loyaltyTimer = 12000;
- m_duration = 0;
- m_bonusdamage = 0;
-
- m_loyaltyPoints = 0;
- m_TrainingPoints = 0;
- m_resetTalentsCost = 0;
- m_resetTalentsTime = 0;
-
- m_auraUpdateMask = 0;
// pets always have a charminfo, even if they are not actually charmed
CharmInfo* charmInfo = InitCharmInfo(this);
@@ -90,12 +58,6 @@ Pet::Pet(PetType type) : Creature()
else if(type == GUARDIAN_PET) // always aggressive
charmInfo->SetReactState(REACT_AGGRESSIVE);
- m_spells.clear();
- m_Auras.clear();
- m_CreatureSpellCooldowns.clear();
- m_CreatureCategoryCooldowns.clear();
- m_autospells.clear();
- m_declinedname = NULL;
m_isActive = true;
}
@@ -126,26 +88,28 @@ void Pet::RemoveFromWorld()
Unit::RemoveFromWorld();
}
-bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool current )
+bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool current )
{
+ m_loading = true;
+
uint32 ownerid = owner->GetGUIDLow();
QueryResult *result;
if(petnumber)
- // known petnumber entry 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber);
+ // known petnumber entry 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
+ result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber);
else if(current)
- // current pet (slot 0) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid );
+ // current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
+ result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid );
else if(petentry)
// known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets)
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry );
+ // 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
+ result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry );
else
// any current or other non-stabled pet (for hunter "call pet")
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid);
+ // 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
+ result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid);
if(!result)
return false;
@@ -160,7 +124,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
return false;
}
- uint32 summon_spell_id = fields[21].GetUInt32();
+ uint32 summon_spell_id = fields[19].GetUInt32();
SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id);
bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0;
@@ -175,7 +139,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
Map *map = owner->GetMap();
uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_PET);
uint32 pet_number = fields[0].GetUInt32();
- if(!Create(guid, map, petentry, pet_number))
+ if(!Create(guid, map, owner->GetPhaseMask(), petentry, pet_number))
{
delete result;
return false;
@@ -194,8 +158,8 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
return false;
}
- setPetType(PetType(fields[22].GetUInt8()));
- SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
+ setPetType(PetType(fields[20].GetUInt8()));
+ SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction());
SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);
CreatureInfo const *cinfo = GetCreatureInfo();
@@ -206,72 +170,67 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
delete result;
return true;
}
- if(getPetType()==HUNTER_PET || (getPetType()==SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
+
+ if(getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
m_charmInfo->SetPetNumber(pet_number, true);
else
m_charmInfo->SetPetNumber(pet_number, false);
- SetUInt64Value(UNIT_FIELD_SUMMONEDBY, owner->GetGUID());
+
+ SetOwnerGUID(owner->GetGUID());
SetDisplayId(fields[3].GetUInt32());
SetNativeDisplayId(fields[3].GetUInt32());
- uint32 petlevel=fields[4].GetUInt32();
- SetUInt32Value(UNIT_NPC_FLAGS , 0);
- SetName(fields[11].GetString());
+ uint32 petlevel = fields[4].GetUInt32();
+ SetUInt32Value(UNIT_NPC_FLAGS, 0);
+ SetName(fields[9].GetString());
switch(getPetType())
{
-
case SUMMON_PET:
petlevel=owner->getLevel();
- SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
+ SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
// this enables popup window (pet dismiss, cancel)
break;
case HUNTER_PET:
SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100);
- SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[8].GetUInt32());
- SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
- SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
-
- if(fields[12].GetBool())
- SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
- else
- SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
+ SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[7].GetUInt32());
+ SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
+ SetByteValue(UNIT_FIELD_BYTES_2, 2, fields[10].GetBool() ? UNIT_RENAME_NOT_ALLOWED : UNIT_RENAME_ALLOWED);
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
// this enables popup window (pet abandon, cancel)
- SetTP(fields[9].GetInt32());
- SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS));
- SetPower( POWER_HAPPINESS,fields[15].GetUInt32());
+ SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
+ SetPower(POWER_HAPPINESS, fields[13].GetUInt32());
setPowerType(POWER_FOCUS);
break;
default:
- sLog.outError("Pet have incorrect type (%u) for pet loading.",getPetType());
+ sLog.outError("Pet have incorrect type (%u) for pet loading.", getPetType());
}
- InitStatsForLevel( petlevel);
+
+ InitStatsForLevel(petlevel);
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32());
- SetUInt64Value(UNIT_FIELD_CREATEDBY, owner->GetGUID());
+ SetCreatorGUID(owner->GetGUID());
- m_charmInfo->SetReactState( ReactStates( fields[6].GetUInt8() ));
- m_loyaltyPoints = fields[7].GetInt32();
+ m_charmInfo->SetReactState(ReactStates(fields[6].GetUInt8()));
- uint32 savedhealth = fields[13].GetUInt32();
- uint32 savedmana = fields[14].GetUInt32();
+ uint32 savedhealth = fields[11].GetUInt32();
+ uint32 savedmana = fields[12].GetUInt32();
// set current pet as current
- if(fields[10].GetUInt32() != 0)
+ if(fields[8].GetUInt32() != 0)
{
CharacterDatabase.BeginTransaction();
- CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'",ownerid, m_charmInfo->GetPetNumber());
- CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'",ownerid, m_charmInfo->GetPetNumber());
+ CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'", ownerid, m_charmInfo->GetPetNumber());
+ CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'", ownerid, m_charmInfo->GetPetNumber());
CharacterDatabase.CommitTransaction();
}
if(!is_temporary_summoned)
{
// permanent controlled pets store state in DB
- Tokens tokens = StrSplit(fields[16].GetString(), " ");
+ Tokens tokens = StrSplit(fields[14].GetString(), " ");
if(tokens.size() != 20)
{
@@ -290,11 +249,11 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
// patch for old data where some spells have ACT_DECIDE but should have ACT_CAST
// so overwrite old state
SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_charmInfo->GetActionBarEntry(index)->SpellOrAction);
- if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) m_charmInfo->GetActionBarEntry(index)->Type = ACT_CAST;
+ if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) m_charmInfo->GetActionBarEntry(index)->Type = ACT_ENABLED;
}
//init teach spells
- tokens = StrSplit(fields[17].GetString(), " ");
+ tokens = StrSplit(fields[15].GetString(), " ");
for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index)
{
uint32 tmp = atol((*iter).c_str());
@@ -309,7 +268,10 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
}
// since last save (in seconds)
- uint32 timediff = (time(NULL) - fields[18].GetUInt32());
+ uint32 timediff = (time(NULL) - fields[16].GetUInt32());
+
+ m_resetTalentsCost = fields[17].GetUInt32();
+ m_resetTalentsTime = fields[18].GetUInt64();
delete result;
@@ -375,6 +337,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
}
}
+ m_loading = false;
return true;
}
@@ -417,10 +380,6 @@ void Pet::SavePetToDB(PetSaveMode mode)
case PET_SAVE_IN_STABLE_SLOT_2:
case PET_SAVE_NOT_IN_SLOT:
{
- uint32 loyalty =1;
- if(getPetType()!=HUNTER_PET)
- loyalty = GetLoyaltyLevel();
-
uint32 owner = GUID_LOPART(GetOwnerGUID());
std::string name = m_name;
CharacterDatabase.escape_string(name);
@@ -437,7 +396,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3')", owner );
// save pet
std::ostringstream ss;
- ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata,TeachSpelldata,savetime,resettalents_cost,resettalents_time,CreatedBySpell,PetType) "
+ ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) "
<< "VALUES ("
<< m_charmInfo->GetPetNumber() << ", "
<< GetEntry() << ", "
@@ -446,9 +405,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
<< getLevel() << ", "
<< GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", "
<< uint32(m_charmInfo->GetReactState()) << ", "
- << m_loyaltyPoints << ", "
- << GetLoyaltyLevel() << ", "
- << m_TrainingPoints << ", "
+ << uint32(GetFreeTalentPoints()) << ", "
<< uint32(mode) << ", '"
<< name.c_str() << "', "
<< uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", "
@@ -521,12 +478,12 @@ void Pet::setDeathState(DeathState s) // overwrite virtual
if(!mapEntry || (mapEntry->map_type != MAP_ARENA && mapEntry->map_type != MAP_BATTLEGROUND))
ModifyPower(POWER_HAPPINESS, -HAPPINESS_LEVEL_SIZE);
- SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
}
}
else if(getDeathState()==ALIVE)
{
- RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
CastPetAuras(true);
}
}
@@ -553,6 +510,7 @@ void Pet::Update(uint32 diff)
// unsummon pet that lost owner
Unit* owner = GetOwner();
if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && !isPossessed()) || isControlled() && !owner->GetPetGUID())
+ //if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && (owner->GetCharmGUID() && (owner->GetCharmGUID() != GetGUID()))) || (isControlled() && !owner->GetPetGUID()))
{
Remove(PET_SAVE_NOT_IN_SLOT, true);
return;
@@ -598,14 +556,6 @@ void Pet::Update(uint32 diff)
else
m_happinessTimer -= diff;
- if(m_loyaltyTimer <= diff)
- {
- TickLoyaltyChange();
- m_loyaltyTimer = 12000;
- }
- else
- m_loyaltyTimer -= diff;
-
break;
}
default:
@@ -627,7 +577,7 @@ void Pet::RegenerateFocus()
AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
for(AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i)
if ((*i)->GetModifier()->m_miscvalue == POWER_FOCUS)
- addvalue *= ((*i)->GetModifierValue() + 100) / 100.0f;
+ addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f;
ModifyPower(POWER_FOCUS, (int32)addvalue);
}
@@ -637,83 +587,12 @@ void Pet::LooseHappiness()
uint32 curValue = GetPower(POWER_HAPPINESS);
if (curValue <= 0)
return;
- int32 addvalue = (140 >> GetLoyaltyLevel()) * 125; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
+ int32 addvalue = 670; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
if(isInCombat()) //we know in combat happiness fades faster, multiplier guess
addvalue = int32(addvalue * 1.5);
ModifyPower(POWER_HAPPINESS, -addvalue);
}
-void Pet::ModifyLoyalty(int32 addvalue)
-{
- uint32 loyaltylevel = GetLoyaltyLevel();
-
- if(addvalue > 0) //only gain influenced, not loss
- addvalue = int32((float)addvalue * sWorld.getRate(RATE_LOYALTY));
-
- if(loyaltylevel >= BEST_FRIEND && (addvalue + m_loyaltyPoints) > int32(GetMaxLoyaltyPoints(loyaltylevel)))
- return;
-
- m_loyaltyPoints += addvalue;
-
- if(m_loyaltyPoints < 0)
- {
- if(loyaltylevel > REBELLIOUS)
- {
- //level down
- --loyaltylevel;
- SetLoyaltyLevel(LoyaltyLevel(loyaltylevel));
- m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel);
- SetTP(m_TrainingPoints - int32(getLevel()));
- }
- else
- {
- m_loyaltyPoints = 0;
- Unit* owner = GetOwner();
- if(owner && owner->GetTypeId() == TYPEID_PLAYER)
- {
- WorldPacket data(SMSG_PET_BROKEN, 0);
- ((Player*)owner)->GetSession()->SendPacket(&data);
-
- //run away
- ((Player*)owner)->RemovePet(this,PET_SAVE_AS_DELETED);
- }
- }
- }
- //level up
- else if(m_loyaltyPoints > int32(GetMaxLoyaltyPoints(loyaltylevel)))
- {
- ++loyaltylevel;
- SetLoyaltyLevel(LoyaltyLevel(loyaltylevel));
- m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel);
- SetTP(m_TrainingPoints + getLevel());
- }
-}
-
-void Pet::TickLoyaltyChange()
-{
- int32 addvalue;
-
- switch(GetHappinessState())
- {
- case HAPPY: addvalue = 20; break;
- case CONTENT: addvalue = 10; break;
- case UNHAPPY: addvalue = -20; break;
- default:
- return;
- }
- ModifyLoyalty(addvalue);
-}
-
-void Pet::KillLoyaltyBonus(uint32 level)
-{
- if(level > 100)
- return;
-
- //at lower levels gain is faster | the lower loyalty the more loyalty is gained
- uint32 bonus = uint32(((100 - level) / 10) + (6 - GetLoyaltyLevel()));
- ModifyLoyalty(bonus);
-}
-
HappinessState Pet::GetHappinessState()
{
if(GetPower(POWER_HAPPINESS) < HAPPINESS_LEVEL_SIZE)
@@ -724,11 +603,6 @@ HappinessState Pet::GetHappinessState()
return CONTENT;
}
-void Pet::SetLoyaltyLevel(LoyaltyLevel level)
-{
- SetByteValue(UNIT_FIELD_BYTES_1, 1, level);
-}
-
bool Pet::CanTakeMoreActiveSpells(uint32 spellid)
{
uint8 activecount = 1;
@@ -765,82 +639,6 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid)
return true;
}
-bool Pet::HasTPForSpell(uint32 spellid)
-{
- int32 neededtrainp = GetTPForSpell(spellid);
- if((m_TrainingPoints - neededtrainp < 0 || neededtrainp < 0) && neededtrainp != 0)
- return false;
- return true;
-}
-
-int32 Pet::GetTPForSpell(uint32 spellid)
-{
- uint32 basetrainp = 0;
-
- SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellid);
- SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellid);
- for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
- {
- if(!_spell_idx->second->reqtrainpoints)
- return 0;
-
- basetrainp = _spell_idx->second->reqtrainpoints;
- break;
- }
-
- uint32 spenttrainp = 0;
- uint32 chainstart = spellmgr.GetFirstSpellInChain(spellid);
-
- for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
- {
- if(itr->second->state == PETSPELL_REMOVED)
- continue;
-
- if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart)
- {
- SkillLineAbilityMap::const_iterator _lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first);
- SkillLineAbilityMap::const_iterator _upper = spellmgr.GetEndSkillLineAbilityMap(itr->first);
-
- for(SkillLineAbilityMap::const_iterator _spell_idx2 = _lower; _spell_idx2 != _upper; ++_spell_idx2)
- {
- if(_spell_idx2->second->reqtrainpoints > spenttrainp)
- {
- spenttrainp = _spell_idx2->second->reqtrainpoints;
- break;
- }
- }
- }
- }
-
- return int32(basetrainp) - int32(spenttrainp);
-}
-
-uint32 Pet::GetMaxLoyaltyPoints(uint32 level)
-{
- return LevelUpLoyalty[level - 1];
-}
-
-uint32 Pet::GetStartLoyaltyPoints(uint32 level)
-{
- return LevelStartLoyalty[level - 1];
-}
-
-void Pet::SetTP(int32 TP)
-{
- m_TrainingPoints = TP;
- SetUInt32Value(UNIT_TRAINING_POINTS, (uint32)GetDispTP());
-}
-
-int32 Pet::GetDispTP()
-{
- if(getPetType()!= HUNTER_PET)
- return(0);
- if(m_TrainingPoints < 0)
- return -m_TrainingPoints;
- else
- return -(m_TrainingPoints + 1);
-}
-
void Pet::Remove(PetSaveMode mode, bool returnreagent)
{
Unit* owner = GetOwner();
@@ -895,7 +693,7 @@ void Pet::GivePetXP(uint32 xp)
newXP -= nextLvlXP;
SetLevel( level + 1 );
- SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((Trinity::XP::xp_to_level(level+1))/4));
+ SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(level+1)/4);
level = getLevel();
nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP);
@@ -903,9 +701,6 @@ void Pet::GivePetXP(uint32 xp)
}
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP);
-
- if(getPetType() == HUNTER_PET)
- KillLoyaltyBonus(level);
}
void Pet::GivePetLevel(uint32 level)
@@ -913,9 +708,8 @@ void Pet::GivePetLevel(uint32 level)
if(!level)
return;
- InitStatsForLevel( level);
-
- SetTP(m_TrainingPoints + (GetLoyaltyLevel() - 1));
+ InitStatsForLevel(level);
+ InitTalentForLevel();
}
bool Pet::CreateBaseAtCreature(Creature* creature)
@@ -932,7 +726,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
sLog.outDebug("Create pet");
uint32 pet_number = objmgr.GeneratePetNumber();
- if(!Create(guid, creature->GetMap(), creature->GetEntry(), pet_number))
+ if(!Create(guid, creature->GetMap(), creature->GetPhaseMask(), creature->GetEntry(), pet_number))
return false;
Relocate(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation());
@@ -963,26 +757,20 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
setPowerType(POWER_FOCUS);
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
- SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((Trinity::XP::xp_to_level(creature->getLevel()))/4));
- SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
+ SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(creature->getLevel())/4);
SetUInt32Value(UNIT_NPC_FLAGS, 0);
- CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(creature->GetCreatureInfo()->family);
- if( char* familyname = cFamily->Name[sWorld.GetDefaultDbcLocale()] )
- SetName(familyname);
+ if(CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))
+ SetName(cFamily->Name[sWorld.GetDefaultDbcLocale()]);
else
- SetName(creature->GetName());
+ SetName(creature->GetNameForLocaleIdx(objmgr.GetDBCLocaleIndex()));
- m_loyaltyPoints = 1000;
if(cinfo->type == CREATURE_TYPE_BEAST)
{
SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100);
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
- SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
-
- SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED) );
- SetLoyaltyLevel(REBELLIOUS);
+ SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED));
}
return true;
}
@@ -1111,8 +899,8 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
}
case HUNTER_PET:
{
- SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((Trinity::XP::xp_to_level(petlevel))/4));
-
+ SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(petlevel)/4);
+ learnLevelupSpells();
//these formula may not be correct; however, it is designed to be close to what it should be
//this makes dps 0.5 of pets level
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) );
@@ -1304,7 +1092,7 @@ void Pet::_SaveSpellCooldowns()
void Pet::_LoadSpells()
{
- QueryResult *result = CharacterDatabase.PQuery("SELECT spell,slot,active FROM pet_spell WHERE guid = '%u'",m_charmInfo->GetPetNumber());
+ QueryResult *result = CharacterDatabase.PQuery("SELECT spell,active FROM pet_spell WHERE guid = '%u'",m_charmInfo->GetPetNumber());
if(result)
{
@@ -1312,7 +1100,7 @@ void Pet::_LoadSpells()
{
Field *fields = result->Fetch();
- addSpell(fields[0].GetUInt16(), fields[2].GetUInt16(), PETSPELL_UNCHANGED, fields[1].GetUInt16());
+ addSpell(fields[0].GetUInt32(), fields[1].GetUInt16(), PETSPELL_UNCHANGED);
}
while( result->NextRow() );
@@ -1329,7 +1117,7 @@ void Pet::_SaveSpells()
if (itr->second->state == PETSPELL_REMOVED || itr->second->state == PETSPELL_CHANGED)
CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first);
if (itr->second->state == PETSPELL_NEW || itr->second->state == PETSPELL_CHANGED)
- CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,slot,active) VALUES ('%u', '%u', '%u','%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second->slotId,itr->second->active);
+ CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second->active);
if (itr->second->state == PETSPELL_REMOVED)
_removeSpell(itr->first);
@@ -1344,10 +1132,6 @@ void Pet::_LoadAuras(uint32 timediff)
for (int i = 0; i < TOTAL_AURAS; i++)
m_modAuras[i].clear();
- // all aura related fields
- for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i)
- SetUInt32Value(i, 0);
-
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
if(result)
@@ -1451,7 +1235,7 @@ void Pet::_SaveAuras()
{
CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) "
"VALUES ('%u', '" I64FMTD "', '%u', '%u', '%u', '%d', '%d', '%d', '%d')",
- m_charmInfo->GetPetNumber(), itr2->second->GetCasterGUID(),(uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), (uint32)itr2->second->GetStackAmount(), itr2->second->GetModifier()->m_amount,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->m_procCharges));
+ m_charmInfo->GetPetNumber(), itr2->second->GetCasterGUID(),(uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), (uint32)itr2->second->GetStackAmount(), itr2->second->GetModifier()->m_amount ,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->GetAuraCharges()));
}
}
}
@@ -1469,7 +1253,7 @@ void Pet::_SaveAuras()
}
}
-bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 slot_id, PetSpellType type)
+bool Pet::addSpell(uint32 spell_id, uint16 active, PetSpellState state, PetSpellType type)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
if (!spellInfo)
@@ -1488,7 +1272,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
// same spells don't have autocast option
if (spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET)
- active = ACT_CAST;
+ active = ACT_ENABLED;
PetSpellMap::iterator itr = m_spells.find(spell_id);
if (itr != m_spells.end())
@@ -1525,40 +1309,45 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
else
newspell->active = active;
- uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id);
-
- for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
+ // talent: unlearn all other talent ranks (high and low)
+ if(TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id))
{
- if(itr->second->state == PETSPELL_REMOVED) continue;
-
- if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart)
+ if(TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id ))
{
- slot_id = itr->second->slotId;
- newspell->active = itr->second->active;
-
- if(newspell->active == ACT_ENABLED)
- ToggleAutocast(itr->first, false);
+ for(int i=0; i <5; ++i)
+ {
+ // skip learning spell and no rank spell case
+ uint32 rankSpellId = talentInfo->RankID[i];
+ if(!rankSpellId || rankSpellId==spell_id)
+ continue;
- oldspell_id = itr->first;
- removeSpell(itr->first);
+ // skip unknown ranks
+ if(!HasSpell(rankSpellId))
+ continue;
+ removeSpell(rankSpellId);
+ }
}
}
-
- uint16 tmpslot=slot_id;
-
- if (tmpslot == 0xffff)
+ else if(uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id))
{
- uint16 maxid = 0;
- PetSpellMap::iterator itr;
- for (itr = m_spells.begin(); itr != m_spells.end(); ++itr)
+ for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
{
if(itr->second->state == PETSPELL_REMOVED) continue;
- if (itr->second->slotId > maxid) maxid = itr->second->slotId;
+
+ if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart)
+ {
+ newspell->active = itr->second->active;
+
+ if(newspell->active == ACT_ENABLED)
+ ToggleAutocast(itr->first, false);
+
+ oldspell_id = itr->first;
+ unlearnSpell(itr->first);
+ break;
+ }
}
- tmpslot = maxid + 1;
}
- newspell->slotId = tmpslot;
m_spells[spell_id] = newspell;
if (IsPassiveSpell(spell_id))
@@ -1569,29 +1358,81 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
if(newspell->active == ACT_ENABLED)
ToggleAutocast(spell_id, true);
+ uint32 talentCost = GetTalentSpellCost(spell_id);
+ if (talentCost)
+ {
+ int32 free_points = GetMaxTalentPointsForLevel(getLevel());
+ m_usedTalentCount+=talentCost;
+ // update free talent points
+ free_points-=m_usedTalentCount;
+ SetFreeTalentPoints(free_points > 0 ? free_points : 0);
+ }
return true;
}
-bool Pet::learnSpell(uint16 spell_id)
+bool Pet::learnSpell(uint32 spell_id)
{
// prevent duplicated entires in spell book
if (!addSpell(spell_id))
return false;
Unit* owner = GetOwner();
- if(owner->GetTypeId()==TYPEID_PLAYER)
+ if(owner && owner->GetTypeId() == TYPEID_PLAYER)
+ {
+ if(!m_loading)
+ {
+ WorldPacket data(SMSG_PET_LEARNED_SPELL, 2);
+ data << uint16(spell_id);
+ ((Player*)owner)->GetSession()->SendPacket(&data);
+ }
((Player*)owner)->PetSpellInitialize();
+ }
return true;
}
-void Pet::removeSpell(uint16 spell_id)
+void Pet::learnLevelupSpells()
+{
+ PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family);
+ if(!levelupSpells)
+ return;
+
+ uint32 level = getLevel();
+
+ for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr)
+ {
+ if(itr->first <= level)
+ learnSpell(itr->second);
+ else
+ unlearnSpell(itr->second);
+ }
+}
+
+bool Pet::unlearnSpell(uint32 spell_id)
+{
+ if(removeSpell(spell_id))
+ {
+ if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
+ {
+ if(!m_loading)
+ {
+ WorldPacket data(SMSG_PET_REMOVED_SPELL, 2);
+ data << uint16(spell_id);
+ ((Player*)GetOwner())->GetSession()->SendPacket(&data);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool Pet::removeSpell(uint32 spell_id)
{
PetSpellMap::iterator itr = m_spells.find(spell_id);
if (itr == m_spells.end())
- return;
+ return false;
if(itr->second->state == PETSPELL_REMOVED)
- return;
+ return false;
if(itr->second->state == PETSPELL_NEW)
{
@@ -1602,9 +1443,23 @@ void Pet::removeSpell(uint16 spell_id)
itr->second->state = PETSPELL_REMOVED;
RemoveAurasDueToSpell(spell_id);
+
+ uint32 talentCost = GetTalentSpellCost(spell_id);
+ if (talentCost > 0)
+ {
+ if (m_usedTalentCount > talentCost)
+ m_usedTalentCount-=talentCost;
+ else
+ m_usedTalentCount = 0;
+ // update free talent points
+ int32 free_points = GetMaxTalentPointsForLevel(getLevel()) - m_usedTalentCount;
+ SetFreeTalentPoints(free_points > 0 ? free_points : 0);
+ }
+
+ return true;
}
-bool Pet::_removeSpell(uint16 spell_id)
+bool Pet::_removeSpell(uint32 spell_id)
{
PetSpellMap::iterator itr = m_spells.find(spell_id);
if (itr != m_spells.end())
@@ -1621,7 +1476,7 @@ void Pet::InitPetCreateSpells()
m_charmInfo->InitPetActionBar();
m_spells.clear();
- int32 usedtrainpoints = 0, petspellid;
+ uint32 petspellid;
PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry());
if(CreateSpells)
{
@@ -1641,7 +1496,7 @@ void Pet::InitPetCreateSpells()
if(owner->GetTypeId() == TYPEID_PLAYER && !((Player*)owner)->HasSpell(learn_spellproto->Id))
{
if(IsPassiveSpell(petspellid)) //learn passive skills when tamed, not sure if thats right
- ((Player*)owner)->learnSpell(learn_spellproto->Id);
+ ((Player*)owner)->learnSpell(learn_spellproto->Id,false);
else
AddTeachSpell(learn_spellproto->EffectTriggerSpell[0], learn_spellproto->Id);
}
@@ -1650,23 +1505,12 @@ void Pet::InitPetCreateSpells()
petspellid = learn_spellproto->Id;
addSpell(petspellid);
-
- SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]);
- SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]);
-
- for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
- {
- usedtrainpoints += _spell_idx->second->reqtrainpoints;
- break;
- }
}
}
LearnPetPassives();
CastPetAuras(false);
-
- SetTP(-usedtrainpoints);
}
void Pet::CheckLearning(uint32 spellid)
@@ -1686,11 +1530,115 @@ void Pet::CheckLearning(uint32 spellid)
if(urand(0, 100) < 10)
{
- ((Player*)owner)->learnSpell(itr->second);
+ ((Player*)owner)->learnSpell(itr->second,false);
m_teachspells.erase(itr);
}
}
+bool Pet::resetTalents(bool no_cost)
+{
+ Unit *owner = GetOwner();
+ if (!owner || owner->GetTypeId()!=TYPEID_PLAYER)
+ return false;
+
+ CreatureInfo const * ci = GetCreatureInfo();
+ if(!ci)
+ return false;
+ // Check pet talent type
+ CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
+ if(!pet_family || pet_family->petTalentType < 0)
+ return false;
+
+ Player *player = (Player *)owner;
+
+ uint32 level = getLevel();
+ uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level);
+
+ if (m_usedTalentCount == 0)
+ {
+ SetFreeTalentPoints(talentPointsForLevel);
+ return false;
+ }
+
+ uint32 cost = 0;
+
+ if(!no_cost)
+ {
+ cost = resetTalentsCost();
+
+ if (player->GetMoney() < cost)
+ {
+ player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
+ return false;
+ }
+ }
+
+ for (unsigned int i = 0; i < sTalentStore.GetNumRows(); i++)
+ {
+ TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
+
+ if (!talentInfo) continue;
+
+ TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab );
+
+ if(!talentTabInfo)
+ continue;
+
+ // unlearn only talents for pets family talent type
+ if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask))
+ continue;
+
+ for (int j = 0; j < 5; j++)
+ {
+ for(PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end();)
+ {
+ if(itr->second->state == PETSPELL_REMOVED)
+ {
+ ++itr;
+ continue;
+ }
+ // remove learned spells (all ranks)
+ uint32 itrFirstId = spellmgr.GetFirstSpellInChain(itr->first);
+
+ // unlearn if first rank is talent or learned by talent
+ if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId))
+ {
+ removeSpell(itr->first);
+ itr = m_spells.begin();
+ continue;
+ }
+ else
+ ++itr;
+ }
+ }
+ }
+
+ SetFreeTalentPoints(talentPointsForLevel);
+
+ if(!no_cost)
+ {
+ player->ModifyMoney(-(int32)cost);
+
+ m_resetTalentsCost = cost;
+ m_resetTalentsTime = time(NULL);
+ }
+ player->PetSpellInitialize();
+ return true;
+}
+
+void Pet::InitTalentForLevel()
+{
+ uint32 level = getLevel();
+ uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level);
+ // Reset talents in case low level (on level down) or wrong points for level (hunter can unlearn TP increase talent)
+ if(talentPointsForLevel == 0 || m_usedTalentCount > talentPointsForLevel)
+ {
+ // Remove all talent points
+ resetTalents(true);
+ }
+ SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount);
+}
+
uint32 Pet::resetTalentsCost() const
{
uint32 days = (sWorld.GetGameTime() - m_resetTalentsTime)/DAY;
@@ -1709,6 +1657,15 @@ uint32 Pet::resetTalentsCost() const
return (m_resetTalentsCost + 1*GOLD > 10*GOLD ? 10*GOLD : m_resetTalentsCost + 1*GOLD);
}
+uint8 Pet::GetMaxTalentPointsForLevel(uint32 level)
+{
+ uint8 points = (level >= 20) ? ((level - 16) / 4) : 0;
+ // Mod points from owner SPELL_AURA_MOD_PET_TALENT_POINTS
+ if (Unit *owner = GetOwner())
+ points+=owner->GetTotalAuraModifier(SPELL_AURA_MOD_PET_TALENT_POINTS);
+ return points;
+}
+
void Pet::ToggleAutocast(uint32 spellid, bool apply)
{
if(IsPassiveSpell(spellid))
@@ -1719,13 +1676,15 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply)
// && tempSpell->EffectImplicitTargetA[0] != TARGET_CHAIN_DAMAGE)
// return;
- PetSpellMap::const_iterator itr = m_spells.find((uint16)spellid);
+ PetSpellMap::const_iterator itr = m_spells.find(spellid);
int i;
if(apply)
{
- for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++);
+ for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++)
+ ; // just search
+
if (i == m_autospells.size())
{
m_autospells.push_back(spellid);
@@ -1736,7 +1695,9 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply)
else
{
AutoSpellList::iterator itr2 = m_autospells.begin();
- for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++);
+ for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++)
+ ; // just search
+
if (i < m_autospells.size())
{
m_autospells.erase(itr2);
@@ -1746,10 +1707,11 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply)
}
}
-bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number)
+bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number)
{
SetMapId(map->GetId());
SetInstanceId(map->GetInstanceId());
+ SetPhaseMask(phaseMask,false);
Object::_Create(guidlow, pet_number, HIGHGUID_PET);
@@ -1759,8 +1721,7 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number)
if(!InitEntry(Entry))
return false;
- SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
- SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
+ SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
if(getPetType() == MINI_PET) // always non-attackable
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
@@ -1770,7 +1731,8 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number)
bool Pet::HasSpell(uint32 spell) const
{
- return (m_spells.find(spell) != m_spells.end());
+ PetSpellMap::const_iterator itr = m_spells.find(spell);
+ return (itr != m_spells.end() && itr->second->state != PETSPELL_REMOVED );
}
// Get all passive spells in our skill line
@@ -1791,7 +1753,7 @@ void Pet::LearnPetPassives()
// Passive 01~10, Passive 00 (20782, not used), Ferocious Inspiration (34457)
// Scale 01~03 (34902~34904, bonus from owner, not used)
for(PetFamilySpellsSet::const_iterator petSet = petStore->second.begin(); petSet != petStore->second.end(); ++petSet)
- addSpell(*petSet, ACT_DECIDE, PETSPELL_NEW, 0xffff, PETSPELL_FAMILY);
+ addSpell(*petSet, ACT_DECIDE, PETSPELL_NEW, PETSPELL_FAMILY);
}
}
diff --git a/src/game/Pet.h b/src/game/Pet.h
index 9d187b24b45..aad154fe79e 100644
--- a/src/game/Pet.h
+++ b/src/game/Pet.h
@@ -52,16 +52,6 @@ enum HappinessState
HAPPY = 3
};
-enum LoyaltyLevel
-{
- REBELLIOUS = 1,
- UNRULY = 2,
- SUBMISSIVE = 3,
- DEPENDABLE = 4,
- FAITHFUL = 5,
- BEST_FRIEND = 6
-};
-
enum PetSpellState
{
PETSPELL_UNCHANGED = 0,
@@ -78,7 +68,6 @@ enum PetSpellType
struct PetSpell
{
- uint16 slotId;
uint16 active;
PetSpellState state : 16;
@@ -116,15 +105,12 @@ enum PetNameInvalidReason
PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 16
};
-typedef UNORDERED_MAP<uint16, PetSpell*> PetSpellMap;
+typedef UNORDERED_MAP<uint32, PetSpell*> PetSpellMap;
typedef std::map<uint32,uint32> TeachSpellMap;
typedef std::vector<uint32> AutoSpellList;
#define HAPPINESS_LEVEL_SIZE 333000
-extern const uint32 LevelUpLoyalty[6];
-extern const uint32 LevelStartLoyalty[6];
-
#define ACTIVE_SPELLS_MAX 4
#define OWNER_MAX_DISTANCE 100
@@ -146,9 +132,9 @@ class Pet : public Creature
bool isControlled() const { return getPetType()==SUMMON_PET || getPetType()==HUNTER_PET; }
bool isTemporarySummoned() const { return m_duration > 0; }
- bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number);
+ bool Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number);
bool CreateBaseAtCreature(Creature* creature);
- bool LoadPetFromDB( Unit* owner,uint32 petentry = 0,uint32 petnumber = 0, bool current = false );
+ bool LoadPetFromDB( Player* owner,uint32 petentry = 0,uint32 petnumber = 0, bool current = false );
void SavePetToDB(PetSaveMode mode);
void Remove(PetSaveMode mode, bool returnreagent = false);
static void DeleteFromDB(uint32 guidlow);
@@ -167,14 +153,7 @@ class Pet : public Creature
void RegenerateFocus();
void LooseHappiness();
- void TickLoyaltyChange();
- void ModifyLoyalty(int32 addvalue);
HappinessState GetHappinessState();
- uint32 GetMaxLoyaltyPoints(uint32 level);
- uint32 GetStartLoyaltyPoints(uint32 level);
- void KillLoyaltyBonus(uint32 level);
- uint32 GetLoyaltyLevel() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
- void SetLoyaltyLevel(LoyaltyLevel level);
void GivePetXP(uint32 xp);
void GivePetLevel(uint32 level);
bool InitStatsForLevel(uint32 level);
@@ -194,10 +173,8 @@ class Pet : public Creature
void UpdateAttackPowerAndDamage(bool ranged = false);
void UpdateDamagePhysical(WeaponAttackType attType);
- bool CanTakeMoreActiveSpells(uint32 SpellIconID);
- void ToggleAutocast(uint32 spellid, bool apply);
- bool HasTPForSpell(uint32 spellid);
- int32 GetTPForSpell(uint32 spellid);
+ bool CanTakeMoreActiveSpells(uint32 SpellIconID);
+ void ToggleAutocast(uint32 spellid, bool apply);
bool HasSpell(uint32 spell) const;
void AddTeachSpell(uint32 learned_id, uint32 source_id) { m_teachspells[learned_id] = source_id; }
@@ -213,10 +190,12 @@ class Pet : public Creature
void _LoadSpells();
void _SaveSpells();
- bool addSpell(uint16 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, uint16 slot_id=0xffff, PetSpellType type = PETSPELL_NORMAL);
- bool learnSpell(uint16 spell_id);
- void removeSpell(uint16 spell_id);
- bool _removeSpell(uint16 spell_id);
+ bool addSpell(uint32 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, PetSpellType type = PETSPELL_NORMAL);
+ bool learnSpell(uint32 spell_id);
+ void learnLevelupSpells();
+ bool unlearnSpell(uint32 spell_id);
+ bool removeSpell(uint32 spell_id);
+ bool _removeSpell(uint32 spell_id);
PetSpellMap m_spells;
TeachSpellMap m_teachspells;
@@ -224,16 +203,20 @@ class Pet : public Creature
void InitPetCreateSpells();
void CheckLearning(uint32 spellid);
+
+ bool resetTalents(bool no_cost = false);
uint32 resetTalentsCost() const;
+ void InitTalentForLevel();
- void SetTP(int32 TP);
- int32 GetDispTP();
+ uint8 GetMaxTalentPointsForLevel(uint32 level);
+ uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
+ void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); }
- int32 m_TrainingPoints;
uint32 m_resetTalentsCost;
time_t m_resetTalentsTime;
+ uint32 m_usedTalentCount;
- uint64 GetAuraUpdateMask() { return m_auraUpdateMask; }
+ const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; }
void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); }
void UnsetAuraUpdateMask(uint8 slot) { m_auraUpdateMask &= ~(uint64(1) << slot); }
void ResetAuraUpdateMask() { m_auraUpdateMask = 0; }
@@ -242,14 +225,12 @@ 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;
- uint32 m_loyaltyTimer;
PetType m_petType;
int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets)
- int32 m_loyaltyPoints;
int32 m_bonusdamage;
uint64 m_auraUpdateMask;
+ bool m_loading;
DeclinedName *m_declinedname;
diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp
index 67607defba0..398861d8d37 100644
--- a/src/game/PetAI.cpp
+++ b/src/game/PetAI.cpp
@@ -139,11 +139,11 @@ void PetAI::UpdateAI(const uint32 diff)
else
m_updateAlliesTimer -= diff;
- if (inCombat && i_pet.getVictim() == NULL)
+ if (inCombat && !i_pet.getVictim())
_stopAttack();
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
- if( i_pet.getVictim() != NULL )
+ if( i_pet.getVictim() )
{
if( _needToStop() )
{
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
index e4269ddafd6..e5ffd0235e5 100644
--- a/src/game/PetHandler.cpp
+++ b/src/game/PetHandler.cpp
@@ -106,7 +106,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
}
// only place where pet can be player
pet->clearUnitState(UNIT_STAT_FOLLOW);
- uint64 selguid = _player->GetSelection();
+ const uint64& selguid = _player->GetSelection();
Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, selguid);
if(!TargetUnit)
return;
@@ -118,27 +118,35 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
//if(!pet->IsWithinLOSInMap(TargetUnit))
// return;
- if(pet->GetTypeId() != TYPEID_PLAYER)
+ // This is true if pet has no target or has target but targets differs.
+ if(pet->getVictim() != TargetUnit)
{
- if (((Creature*)pet)->AI())
- ((Creature*)pet)->AI()->AttackStart(TargetUnit);
+ if (pet->getVictim())
+ pet->AttackStop();
- //10% chance to play special pet attack talk, else growl
- if(((Creature*)pet)->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10)
- pet->SendPetTalk((uint32)PET_TALK_ATTACK);
- else
+ if(pet->GetTypeId() != TYPEID_PLAYER)
{
- // 90% chance for pet and 100% chance for charmed creature
- pet->SendPetAIReaction(guid1);
+ pet->GetMotionMaster()->Clear();
+ if (((Creature*)pet)->AI())
+ ((Creature*)pet)->AI()->AttackStart(TargetUnit);
+
+ //10% chance to play special pet attack talk, else growl
+ if(((Creature*)pet)->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10)
+ pet->SendPetTalk((uint32)PET_TALK_ATTACK);
+ else
+ {
+ // 90% chance for pet and 100% chance for charmed creature
+ pet->SendPetAIReaction(guid1);
+ }
}
- }
- else // charmed player
- {
- if(pet->getVictim() && pet->getVictim() != TargetUnit)
- pet->AttackStop();
+ else // charmed player
+ {
+ if(pet->getVictim() && pet->getVictim() != TargetUnit)
+ pet->AttackStop();
- pet->Attack(TargetUnit,true);
- pet->SendPetAIReaction(guid1);
+ pet->Attack(TargetUnit,true);
+ pet->SendPetAIReaction(guid1);
+ }
}
break;
}
@@ -174,19 +182,17 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
break;
}
break;
- case ACT_DISABLED: //0x8100 spell (disabled), ignore
- case ACT_CAST: //0x0100
- case ACT_ENABLED: //0xc100 spell
+ case ACT_DISABLED: // 0x8100 spell (disabled), ignore
+ case ACT_PASSIVE: // 0x0100
+ case ACT_ENABLED: // 0xC100 spell
{
- Unit* unit_target;
- if(guid2)
- unit_target = ObjectAccessor::GetUnit(*_player,guid2);
- else
- unit_target = NULL;
-
+ Unit* unit_target = NULL;
if (((Creature*)pet)->GetGlobalCooldown() > 0)
return;
+ if(guid2)
+ unit_target = ObjectAccessor::GetUnit(*_player,guid2);
+
// do not cast unknown spells
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid );
if(!spellInfo)
@@ -211,7 +217,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
int16 result = spell->PetCanCast(unit_target);
- //auto turn to target unless possessed
+ //auto turn to target unless possessed
if(result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->isPossessed())
{
pet->SetInFront(unit_target);
@@ -242,12 +248,15 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
if( unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->isPossessed())
{
- pet->clearUnitState(UNIT_STAT_FOLLOW);
- if(pet->getVictim())
- pet->AttackStop();
- pet->GetMotionMaster()->Clear();
- if (((Creature*)pet)->AI())
- ((Creature*)pet)->AI()->AttackStart(unit_target);
+ // This is true if pet has no target or has target but targets differs.
+ if (pet->getVictim() != unit_target)
+ {
+ if (pet->getVictim())
+ pet->AttackStop();
+ pet->GetMotionMaster()->Clear();
+ if (((Creature*)pet)->AI())
+ ((Creature*)pet)->AI()->AttackStart(unit_target);
+ }
}
spell->prepare(&(spell->m_targets));
@@ -257,15 +266,12 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
if(pet->isPossessed())
{
WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
- data << uint32(spellid) << uint8(2) << uint8(result);
+ data << uint8(0) << uint32(spellid) << uint8(result);
switch (result)
{
case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
data << uint32(spellInfo->RequiresSpellFocus);
break;
- case SPELL_FAILED_REQUIRES_AREA:
- data << uint32(spellInfo->AreaId);
- break;
}
SendPacket(&data);
}
@@ -302,7 +308,7 @@ void WorldSession::HandlePetNameQuery( WorldPacket & recv_data )
void WorldSession::SendPetNameQuery( uint64 petguid, uint32 petnumber)
{
- Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, petguid);
+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid);
if(!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber)
return;
@@ -344,7 +350,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
if(ObjectAccessor::FindPlayer(petguid))
return;
- Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, petguid);
+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid);
if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm()))
{
@@ -369,7 +375,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X\n", _player->GetName(), position, spell_id, act_state);
//if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add
- if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_CAST) && spell_id && !pet->HasSpell(spell_id)))
+ if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id)))
{
//sign for autocast
if(act_state == ACT_ENABLED && spell_id)
@@ -481,7 +487,7 @@ void WorldSession::HandlePetAbandon( WorldPacket & recv_data )
sLog.outDetail( "HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid) );
// pet/charmed
- Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, guid);
+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid);
if(pet)
{
if(pet->isPet())
@@ -510,11 +516,11 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket)
sLog.outDetail("CMSG_PET_UNLEARN");
uint64 guid;
- recvPacket >> guid;
+ recvPacket >> guid; // Pet guid
Pet* pet = _player->GetPet();
- if(!pet || pet->getPetType() != HUNTER_PET || pet->m_spells.size() <= 1)
+ if(!pet || pet->getPetType() != HUNTER_PET || pet->m_usedTalentCount == 0)
return;
if(guid != pet->GetGUID())
@@ -529,38 +535,7 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket)
sLog.outError("WorldSession::HandlePetUnlearnOpcode: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID());
return;
}
-
- uint32 cost = pet->resetTalentsCost();
-
- if (GetPlayer()->GetMoney() < cost)
- {
- GetPlayer()->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
- return;
- }
-
- for(PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end();)
- {
- uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell
- ++itr;
- pet->removeSpell(spell_id);
- }
-
- pet->SetTP(pet->getLevel() * (pet->GetLoyaltyLevel() - 1));
-
- for(uint8 i = 0; i < 10; i++)
- {
- if(charmInfo->GetActionBarEntry(i)->SpellOrAction && charmInfo->GetActionBarEntry(i)->Type == ACT_ENABLED || charmInfo->GetActionBarEntry(i)->Type == ACT_DISABLED)
- charmInfo->GetActionBarEntry(i)->SpellOrAction = 0;
- }
-
- // relearn pet passives
- pet->LearnPetPassives();
-
- pet->m_resetTalentsTime = time(NULL);
- pet->m_resetTalentsCost = cost;
- GetPlayer()->ModifyMoney(-(int32)cost);
-
- GetPlayer()->PetSpellInitialize();
+ pet->resetTalents();
}
void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket )
@@ -580,7 +555,7 @@ void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket )
if(ObjectAccessor::FindPlayer(guid))
return;
- Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid);
+ Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid);
if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm()))
{
@@ -616,11 +591,15 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
{
sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL");
- CHECK_PACKET_SIZE(recvPacket,8+4);
+ CHECK_PACKET_SIZE(recvPacket,8+1+4+1);
uint64 guid;
uint32 spellid;
+ uint8 cast_count;
+ uint8 unk_flags; // flags (if 0x02 - some additional data are received)
+
+ recvPacket >> guid >> cast_count >> spellid >> unk_flags;
- recvPacket >> guid >> spellid;
+ sLog.outDebug("WORLD: CMSG_PET_CAST_SPELL, cast_count: %u, spellid %u, unk_flags %u", cast_count, spellid, unk_flags);
// This opcode is also sent from charmed and possessed units (players and creatures)
if(!_player->GetPet() && !_player->GetCharm())
@@ -655,6 +634,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
caster->clearUnitState(UNIT_STAT_FOLLOW);
Spell *spell = new Spell(caster, spellInfo, false);
+ spell->m_cast_count = cast_count; // probably pending spell cast
spell->m_targets = targets;
int16 result = spell->PetCanCast(NULL);
@@ -713,3 +693,129 @@ void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, Dec
data << uint8(0);
SendPacket(&data);
}
+
+void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data )
+{
+ sLog.outDebug("WORLD: CMSG_PET_LEARN_TALENT");
+ recv_data.hexlike();
+
+ CHECK_PACKET_SIZE(recv_data, 8+4+4);
+
+ uint64 guid;
+ uint32 talent_id, requested_rank;
+ recv_data >> guid >> talent_id >> requested_rank;
+
+ Pet *pet = _player->GetPet();
+
+ if(!pet)
+ return;
+
+ if(guid != pet->GetGUID())
+ return;
+
+ uint32 CurTalentPoints = pet->GetFreeTalentPoints();
+
+ if(CurTalentPoints == 0)
+ return;
+
+ if (requested_rank > 4)
+ return;
+
+ TalentEntry const *talentInfo = sTalentStore.LookupEntry(talent_id);
+
+ if(!talentInfo)
+ return;
+
+ TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
+
+ if(!talentTabInfo)
+ return;
+
+ CreatureInfo const *ci = pet->GetCreatureInfo();
+
+ if(!ci)
+ return;
+
+ CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
+
+ if(!pet_family)
+ return;
+
+ if(pet_family->petTalentType < 0) // not hunter pet
+ return;
+
+ // prevent learn talent for different family (cheating)
+ if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask))
+ return;
+
+ // prevent skip talent ranks (cheating)
+ if(requested_rank > 0 && !pet->HasSpell(talentInfo->RankID[requested_rank-1]))
+ return;
+
+ // Check if it requires another talent
+ if (talentInfo->DependsOn > 0)
+ {
+ if(TalentEntry const *depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn))
+ {
+ bool hasEnoughRank = false;
+ for (int i = talentInfo->DependsOnRank; i <= 4; i++)
+ {
+ if (depTalentInfo->RankID[i] != 0)
+ if (pet->HasSpell(depTalentInfo->RankID[i]))
+ hasEnoughRank = true;
+ }
+ if (!hasEnoughRank)
+ return;
+ }
+ }
+
+ // Find out how many points we have in this field
+ uint32 spentPoints = 0;
+
+ uint32 tTab = talentInfo->TalentTab;
+ if (talentInfo->Row > 0)
+ {
+ unsigned int numRows = sTalentStore.GetNumRows();
+ for (unsigned int i = 0; i < numRows; i++) // Loop through all talents.
+ {
+ // Someday, someone needs to revamp
+ const TalentEntry *tmpTalent = sTalentStore.LookupEntry(i);
+ if (tmpTalent) // the way talents are tracked
+ {
+ if (tmpTalent->TalentTab == tTab)
+ {
+ for (int j = 0; j <= 4; j++)
+ {
+ if (tmpTalent->RankID[j] != 0)
+ {
+ if (pet->HasSpell(tmpTalent->RankID[j]))
+ {
+ spentPoints += j + 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // not have required min points spent in talent tree
+ if(spentPoints < (talentInfo->Row * 3))
+ return;
+
+ // spell not set in talent.dbc
+ uint32 spellid = talentInfo->RankID[requested_rank];
+ if( spellid == 0 )
+ {
+ sLog.outError("Talent.dbc have for talent: %u Rank: %u spell id = 0", talent_id, requested_rank);
+ return;
+ }
+
+ // already known
+ if(pet->HasSpell(spellid))
+ return;
+
+ // learn! (other talent ranks will unlearned at learning)
+ pet->learnSpell(spellid);
+ sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid);
+}
diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp
index 8fc18b1c259..ad3893ce110 100644
--- a/src/game/PetitionsHandler.cpp
+++ b/src/game/PetitionsHandler.cpp
@@ -199,9 +199,9 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
if(!charter)
return;
- charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, charter->GetGUIDLow());
- // ITEM_FIELD_ENCHANTMENT is guild/arenateam id
- // ITEM_FIELD_ENCHANTMENT+1 is current signatures count (showed on item)
+ charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow());
+ // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id
+ // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item)
charter->SetState(ITEM_CHANGED, _player);
_player->SendNewItem(charter, 1, true, false);
@@ -565,7 +565,7 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
// update signs count on charter, required testing...
//Item *item = _player->GetItemByGuid(petitionguid));
//if(item)
- // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1, signs);
+ // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs);
// update for owner if online
if(Player *owner = objmgr.GetPlayer(ownerguid))
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index e7ae690c5be..bb8be628c54 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -64,6 +64,7 @@
#include "Spell.h"
#include "SocialMgr.h"
#include "GameEvent.h"
+#include "AchievementMgr.h"
#include <cmath>
@@ -132,7 +133,7 @@ PlayerTaxi::PlayerTaxi()
memset(m_taximask, 0, sizeof(m_taximask));
}
-void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 level)
+void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint32 level)
{
// capital and taxi hub masks
switch(race)
@@ -149,6 +150,13 @@ void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 level)
case RACE_BLOODELF: SetTaximaskNode(82); break; // Blood Elf
case RACE_DRAENEI: SetTaximaskNode(94); break; // Draenei
}
+
+ switch(chrClass)
+ {
+ case CLASS_DEATH_KNIGHT: // TODO: figure out initial known nodes
+ break;
+ }
+
// new continent starting masks (It will be accessible only at new map)
switch(Player::TeamForRace(race))
{
@@ -188,7 +196,7 @@ void PlayerTaxi::AppendTaximaskTo( ByteBuffer& data, bool all )
}
}
-bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values )
+bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values, uint32 team )
{
ClearTaxiDestinations();
@@ -216,6 +224,10 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values )
return false;
}
+ // can't load taxi path without mount set (quest taxi path?)
+ if(!objmgr.GetTaxiMount(GetTaxiSource(),team))
+ return false;
+
return true;
}
@@ -245,13 +257,22 @@ uint32 PlayerTaxi::GetCurrentTaxiPath() const
return path;
}
+std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
+{
+ ss << "'";
+ for(int i = 0; i < TaxiMaskSize; ++i)
+ ss << taxi.m_taximask[i] << " ";
+ ss << "'";
+ return ss;
+}
+
//== Player ====================================================
const int32 Player::ReputationRank_Length[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000};
UpdateMask Player::updateVisualBits;
-Player::Player (WorldSession *session): Unit()
+Player::Player (WorldSession *session): Unit(), m_achievementMgr(this)
{
m_transport = 0;
@@ -280,6 +301,7 @@ Player::Player (WorldSession *session): Unit()
m_comboPoints = 0;
m_usedTalentCount = 0;
+ m_questRewardTalentCount = 0;
m_regenTimer = 0;
m_weaponChangeTimer = 0;
@@ -335,7 +357,7 @@ Player::Player (WorldSession *session): Unit()
m_regenTimer = 0;
m_weaponChangeTimer = 0;
m_breathTimer = 0;
- m_isunderwater = 0;
+ m_isunderwater = UNDERWATER_NONE;
m_isInWater = false;
m_drunkTimer = 0;
m_drunk = 0;
@@ -362,6 +384,7 @@ Player::Player (WorldSession *session): Unit()
m_canParry = false;
m_canBlock = false;
m_canDualWield = false;
+ m_canTitanGrip = false;
m_ammoDPS = 0.0f;
m_temporaryUnsummonedPetNumber = 0;
@@ -406,6 +429,14 @@ Player::Player (WorldSession *session): Unit()
m_auraBaseMod[i][PCT_MOD] = 1.0f;
}
+ for (int i = 0; i < MAX_COMBAT_RATING; i++)
+ m_baseRatingValue[i] = 0;
+
+ m_baseSpellDamage = 0;
+ m_baseSpellHealing = 0;
+ m_baseFeralAP = 0;
+ m_baseManaRegen = 0;
+
// Honor System
m_lastHonorUpdateTime = time(NULL);
@@ -419,6 +450,8 @@ Player::Player (WorldSession *session): Unit()
//Default movement to run mode
m_unit_movement_flags = 0;
+ m_mover = NULL;
+
m_miniPet = 0;
m_bgAfkReportedTimer = 0;
m_contestedPvPTimer = 0;
@@ -428,6 +461,8 @@ Player::Player (WorldSession *session): Unit()
m_isActive = true;
m_farsightVision = false;
+
+ m_runes = NULL;
}
Player::~Player ()
@@ -475,6 +510,7 @@ Player::~Player ()
RemovePossess(false);
delete m_declinedname;
+ delete m_runes;
}
void Player::CleanupsBeforeDelete()
@@ -520,24 +556,8 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
uint8 powertype = cEntry->powerType;
- uint32 unitfield;
-
- switch(powertype)
- {
- case POWER_ENERGY:
- case POWER_MANA:
- unitfield = 0x00000000;
- break;
- case POWER_RAGE:
- unitfield = 0x00110000;
- break;
- default:
- sLog.outError("Invalid default powertype %u for player (class %u)",powertype,class_);
- return false;
- }
-
- SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE );
- SetFloatValue(UNIT_FIELD_COMBATREACH, DEFAULT_COMBAT_REACH );
+ SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE);
+ SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f);
switch(gender)
{
@@ -560,12 +580,13 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
uint32 RaceClassGender = ( race ) | ( class_ << 8 ) | ( gender << 16 );
SetUInt32Value(UNIT_FIELD_BYTES_0, ( RaceClassGender | ( powertype << 24 ) ) );
- SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield);
- SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_UNK5 );
- SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE );
+ SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP );
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE );
+ SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER);
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); // fix cast time showed in spell tooltip on client
+ SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); // default for players in 3.0.3
- //-1 is default value
+ // -1 is default value
SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1));
SetUInt32Value(PLAYER_BYTES, (skin | (face << 8) | (hairStyle << 16) | (hairColor << 24)));
@@ -577,6 +598,7 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
SetUInt32Value( PLAYER_GUILD_TIMESTAMP, 0 );
SetUInt64Value( PLAYER__FIELD_KNOWN_TITLES, 0 ); // 0=disabled
+ SetUInt64Value( PLAYER__FIELD_KNOWN_TITLES1, 0 ); // 0=disabled
SetUInt32Value( PLAYER_CHOSEN_TITLE, 0 );
SetUInt32Value( PLAYER_FIELD_KILLS, 0 );
SetUInt32Value( PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0 );
@@ -584,10 +606,20 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
SetUInt32Value( PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0 );
// set starting level
+ uint32 start_level = getClass() != CLASS_DEATH_KNIGHT
+ ? sWorld.getConfig(CONFIG_START_PLAYER_LEVEL)
+ : sWorld.getConfig(CONFIG_START_HEROIC_PLAYER_LEVEL);
+
if (GetSession()->GetSecurity() >= SEC_MODERATOR)
- SetUInt32Value (UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_GM_LEVEL));
- else
- SetUInt32Value (UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_PLAYER_LEVEL));
+ {
+ uint32 gm_level = sWorld.getConfig(CONFIG_START_GM_LEVEL);
+ if(gm_level > start_level)
+ start_level = gm_level;
+ }
+
+ SetUInt32Value(UNIT_FIELD_LEVEL, start_level);
+
+ InitRunes();
SetUInt32Value (PLAYER_FIELD_COINAGE, sWorld.getConfig(CONFIG_START_PLAYER_MONEY));
SetUInt32Value (PLAYER_FIELD_HONOR_CURRENCY, sWorld.getConfig(CONFIG_START_HONOR_POINTS));
@@ -651,6 +683,7 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
// base stats and related field values
InitStatsForLevel();
InitTaxiNodesForLevel();
+ InitGlyphsForLevel();
InitTalentForLevel();
InitPrimaryProffesions(); // to max set before any spell added
@@ -663,8 +696,16 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
SetPower(POWER_MANA,GetMaxPower(POWER_MANA));
}
+ if(getPowerType() == POWER_RUNIC_POWER)
+ {
+ SetPower(POWER_RUNE, 8);
+ SetMaxPower(POWER_RUNE, 8);
+ SetPower(POWER_RUNIC_POWER, 0);
+ SetMaxPower(POWER_RUNIC_POWER, 1000);
+ }
+
// original spells
- learnDefaultSpells(true);
+ learnDefaultSpells();
// original action bar
std::list<uint16>::const_iterator action_itr[4];
@@ -706,6 +747,11 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
uint32 item_id = oEntry->ItemId[j];
+
+ // Hack for not existed item id in dbc 3.0.3
+ if(item_id==40582)
+ continue;
+
ItemPrototype const* iProto = objmgr.GetItemPrototype(item_id);
if(!iProto)
{
@@ -713,7 +759,9 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
continue;
}
- uint32 count = iProto->Stackable; // max stack by default (mostly 1)
+ // max stack by default (mostly 1), 1 for infinity stackable
+ uint32 count = iProto->Stackable > 0 ? uint32(iProto->Stackable) : 1;
+
if(iProto->Class==ITEM_CLASS_CONSUMABLE && iProto->SubClass==ITEM_SUBCLASS_FOOD)
{
switch(iProto->Spells[0].SpellCategory)
@@ -872,14 +920,15 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da
void Player::HandleDrowning()
{
- if(!m_isunderwater)
+ if(!(m_isunderwater&~UNDERWATER_INLAVA))
return;
//if player is GM, have waterbreath, is dead or if breathing is disabled then return
- if(waterbreath || isGameMaster() || !isAlive() || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING))
+ if(isGameMaster() || !isAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING))
{
StopMirrorTimer(BREATH_TIMER);
- m_isunderwater = 0;
+ // drop every flag _except_ LAVA - otherwise waterbreathing will prevent lava damage
+ m_isunderwater &= UNDERWATER_INLAVA;
return;
}
@@ -887,24 +936,24 @@ void Player::HandleDrowning()
AuraList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING);
for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i)
- UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifierValue()) / 100.0f);
+ UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f);
- if ((m_isunderwater & 0x01) && !(m_isunderwater & 0x80) && isAlive())
+ if ((m_isunderwater & UNDERWATER_INWATER) && !(m_isunderwater & UNDERWATER_INLAVA) && isAlive())
{
//single trigger timer
- if (!(m_isunderwater & 0x02))
+ if (!(m_isunderwater & UNDERWATER_WATER_TRIGGER))
{
- m_isunderwater|= 0x02;
+ m_isunderwater|= UNDERWATER_WATER_TRIGGER;
m_breathTimer = UnderWaterTime + 1000;
}
- //single trigger "Breathbar"
- if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & 0x04))
+ //single trigger "show Breathbar"
+ if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & UNDERWATER_WATER_BREATHB))
{
- m_isunderwater|= 0x04;
+ m_isunderwater|= UNDERWATER_WATER_BREATHB;
StartMirrorTimer(BREATH_TIMER, UnderWaterTime);
}
//continuous trigger drowning "Damage"
- if ((m_breathTimer == 0) && (m_isunderwater & 0x01))
+ if ((m_breathTimer == 0) && (m_isunderwater & UNDERWATER_INWATER))
{
//TODO: Check this formula
uint64 guid = GetGUID();
@@ -915,74 +964,51 @@ void Player::HandleDrowning()
}
}
//single trigger retract bar
- else if (!(m_isunderwater & 0x01) && !(m_isunderwater & 0x08) && (m_isunderwater & 0x02) && (m_breathTimer > 0) && isAlive())
+ else if (!(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater & UNDERWATER_WATER_TRIGGER) && (m_breathTimer > 0) && isAlive())
{
- m_isunderwater = 0x08;
-
uint32 BreathRegen = 10;
+ // m_breathTimer will be reduced in ModifyMirrorTimer
ModifyMirrorTimer(BREATH_TIMER, UnderWaterTime, m_breathTimer,BreathRegen);
- m_isunderwater = 0x10;
+ m_isunderwater = UNDERWATER_WATER_BREATHB_RETRACTING;
}
//remove bar
- else if ((m_breathTimer < 50) && !(m_isunderwater & 0x01) && (m_isunderwater == 0x10))
+ else if ((m_breathTimer < 50) && !(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater == UNDERWATER_WATER_BREATHB_RETRACTING))
{
StopMirrorTimer(BREATH_TIMER);
- m_isunderwater = 0;
+ m_isunderwater = UNDERWATER_NONE;
}
}
void Player::HandleLava()
{
- bool ValidArea = false;
-
- if ((m_isunderwater & 0x80) && isAlive())
+ if ((m_isunderwater & UNDERWATER_INLAVA) && isAlive())
{
- //Single trigger Set BreathTimer
- if (!(m_isunderwater & 0x80))
+ /*
+ * arrai: how is this supposed to work? UNDERWATER_INLAVA is always set in this scope!
+ // Single trigger Set BreathTimer
+ if (!(m_isunderwater & UNDERWATER_INLAVA))
{
- m_isunderwater|= 0x04;
+ m_isunderwater|= UNDERWATER_WATER_BREATHB;
m_breathTimer = 1000;
}
- //Reset BreathTimer and still in the lava
+ */
+ // Reset BreathTimer and still in the lava
if (!m_breathTimer)
{
uint64 guid = GetGUID();
uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage
- uint32 dmgZone = GetZoneId(); // TODO: Find correct "lava dealing zone" flag in Area Table
- // Deal lava damage only in lava zones.
- switch(dmgZone)
- {
- case 0x8D:
- ValidArea = false;
- break;
- case 0x94:
- ValidArea = false;
- break;
- case 0x2CE:
- ValidArea = false;
- break;
- case 0x2CF:
- ValidArea = false;
- break;
- default:
- if (dmgZone / 5 & 0x408)
- ValidArea = true;
- }
-
- // if is valid area and is not gamemaster then deal damage
- if ( ValidArea && !isGameMaster() )
+ // if not gamemaster then deal damage
+ if ( !isGameMaster() )
EnvironmentalDamage(guid, DAMAGE_LAVA, damage);
m_breathTimer = 1000;
}
-
}
- //Death timer disabled and WaterFlags reset
- else if (m_deathState == DEAD)
+ else if (!isAlive()) // Disable breath timer and reset underwater flags
{
m_breathTimer = 0;
- m_isunderwater = 0;
+ m_isunderwater = UNDERWATER_NONE;
}
}
@@ -1314,6 +1340,7 @@ void Player::Update( uint32 p_time )
Pet* pet = GetPet();
if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE) && !pet->isPossessed())
+ //if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID())))
{
RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true);
return;
@@ -1363,6 +1390,7 @@ void Player::setDeathState(DeathState s)
// passive spell
if(!ressSpellId)
ressSpellId = GetResurrectionSpellId();
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1);
}
Unit::setDeathState(s);
@@ -1383,13 +1411,15 @@ void Player::setDeathState(DeathState s)
void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
{
- *p_data << GetGUID();
+ Field *fields = result->Fetch();
+
+ *p_data << uint64(GetGUID());
*p_data << m_name;
- *p_data << getRace();
+ *p_data << uint8(getRace());
uint8 pClass = getClass();
- *p_data << pClass;
- *p_data << getGender();
+ *p_data << uint8(pClass);
+ *p_data << uint8(getGender());
uint32 bytes = GetUInt32Value(PLAYER_BYTES);
*p_data << uint8(bytes);
@@ -1402,16 +1432,17 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
*p_data << uint8(getLevel()); // player level
// do not use GetMap! it will spawn a new instance since the bound instances are not loaded
- uint32 zoneId = MapManager::Instance().GetZoneId(GetMapId(), GetPositionX(),GetPositionY());
+ uint32 zoneId = MapManager::Instance().GetZoneId(GetMapId(), GetPositionX(),GetPositionY(),GetPositionZ());
sLog.outDebug("Player::BuildEnumData: m:%u, x:%f, y:%f, z:%f zone:%u", GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), zoneId);
- *p_data << zoneId;
- *p_data << GetMapId();
+ *p_data << uint32(zoneId);
+ *p_data << uint32(GetMapId());
*p_data << GetPositionX();
*p_data << GetPositionY();
*p_data << GetPositionZ();
- *p_data << (result ? result->Fetch()[13].GetUInt32() : 0);
+ // guild id
+ *p_data << (result ? fields[13].GetUInt32() : 0);
uint32 char_flags = 0;
if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM))
@@ -1422,14 +1453,13 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
char_flags |= CHARACTER_FLAG_GHOST;
if(HasAtLoginFlag(AT_LOGIN_RENAME))
char_flags |= CHARACTER_FLAG_RENAME;
- // always send the flag if declined names aren't used
- // to let the client select a default method of declining the name
- if(!sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) || (result && result->Fetch()[14].GetCppString() != ""))
+ if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) && (fields[14].GetCppString() != ""))
char_flags |= CHARACTER_FLAG_DECLINED;
- *p_data << (uint32)char_flags; // character flags
-
- *p_data << (uint8)1; // unknown
+ *p_data << uint32(char_flags); // character flags
+ // character customize (flags?)
+ *p_data << uint32(HasAtLoginFlag(AT_LOGIN_CUSTOMIZE) ? 1 : 0);
+ *p_data << uint8(1); // unknown
// Pets info
{
@@ -1440,8 +1470,6 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
// show pet at selection character in character list only for non-ghost character
if(result && isAlive() && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER))
{
- Field* fields = result->Fetch();
-
uint32 entry = fields[10].GetUInt32();
CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(entry);
if(cInfo)
@@ -1452,36 +1480,11 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
}
}
- *p_data << (uint32)petDisplayId;
- *p_data << (uint32)petLevel;
- *p_data << (uint32)petFamily;
+ *p_data << uint32(petDisplayId);
+ *p_data << uint32(petLevel);
+ *p_data << uint32(petFamily);
}
- /*ItemPrototype const *items[EQUIPMENT_SLOT_END];
- for (int i = 0; i < EQUIPMENT_SLOT_END; i++)
- items[i] = NULL;
-
- QueryResult *result = CharacterDatabase.PQuery("SELECT slot,item_template FROM character_inventory WHERE guid = '%u' AND bag = 0",GetGUIDLow());
- if (result)
- {
- do
- {
- Field *fields = result->Fetch();
- uint8 slot = fields[0].GetUInt8() & 255;
- uint32 item_id = fields[1].GetUInt32();
- if( slot >= EQUIPMENT_SLOT_END )
- continue;
-
- items[slot] = objmgr.GetItemPrototype(item_id);
- if(!items[slot])
- {
- sLog.outError( "Player::BuildEnumData: Player %s have unknown item (id: #%u) in inventory, skipped.", GetName(),item_id );
- continue;
- }
- } while (result->NextRow());
- delete result;
- }*/
-
for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; slot++)
{
uint32 visualbase = PLAYER_VISIBLE_ITEM_1_0 + (slot * MAX_VISIBLE_ITEM_OFFSET);
@@ -1498,20 +1501,20 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
if (proto != NULL)
{
- *p_data << (uint32)proto->DisplayInfoID;
- *p_data << (uint8)proto->InventoryType;
- *p_data << (uint32)(enchant?enchant->aura_id:0);
+ *p_data << uint32(proto->DisplayInfoID);
+ *p_data << uint8(proto->InventoryType);
+ *p_data << uint32(enchant ? enchant->aura_id : 0);
}
else
{
- *p_data << (uint32)0;
- *p_data << (uint8)0;
- *p_data << (uint32)0; // enchant?
+ *p_data << uint32(0);
+ *p_data << uint8(0);
+ *p_data << uint32(0); // enchant?
}
}
- *p_data << (uint32)0; // first bag display id
- *p_data << (uint8)0; // first bag inventory type
- *p_data << (uint32)0; // enchant?
+ *p_data << uint32(0); // first bag display id
+ *p_data << uint8(0); // first bag inventory type
+ *p_data << uint32(0); // enchant?
}
bool Player::ToggleAFK()
@@ -1596,7 +1599,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if(GetTransport())
RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :)
- SendTransferAborted(mapid, TRANSFER_ABORT_INSUF_EXPAN_LVL1);
+ SendTransferAborted(mapid, TRANSFER_ABORT_INSUF_EXPAN_LVL, mEntry->Expansion());
return false; // normal client can't teleport to this map...
}
@@ -1916,13 +1919,20 @@ void Player::RegenerateAll()
{
RegenerateHealth();
if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN))
+ {
Regenerate(POWER_RAGE);
+ if(getClass() == CLASS_DEATH_KNIGHT)
+ Regenerate(POWER_RUNIC_POWER);
+ }
}
Regenerate( POWER_ENERGY );
Regenerate( POWER_MANA );
+ if(getClass() == CLASS_DEATH_KNIGHT)
+ Regenerate( POWER_RUNE );
+
m_regenTimer = regenDelay;
}
@@ -1942,11 +1952,11 @@ void Player::Regenerate(Powers power)
if (recentCast)
{
// Trinity Updates Mana in intervals of 2s, which is correct
- addvalue = GetFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT) * ManaIncreaseRate * 2.00f;
+ addvalue = GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * 2.00f;
}
else
{
- addvalue = GetFloatValue(PLAYER_FIELD_MOD_MANA_REGEN) * ManaIncreaseRate * 2.00f;
+ addvalue = GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) * ManaIncreaseRate * 2.00f;
}
} break;
case POWER_RAGE: // Regenerate rage
@@ -1957,6 +1967,17 @@ void Player::Regenerate(Powers power)
case POWER_ENERGY: // Regenerate energy (rogue)
addvalue = 20;
break;
+ case POWER_RUNIC_POWER:
+ {
+ float RunicPowerDecreaseRate = sWorld.getRate(RATE_POWER_RUNICPOWER_LOSS);
+ addvalue = 30 * RunicPowerDecreaseRate; // 3 RunicPower by tick
+ } break;
+ case POWER_RUNE:
+ {
+ for(uint32 i = 0; i < MAX_RUNES; ++i)
+ if(uint8 cd = GetRuneCooldown(i)) // if we have cooldown, reduce it...
+ SetRuneCooldown(i, cd - 1); // ... by 2 sec (because update is every 2 sec)
+ } break;
case POWER_FOCUS:
case POWER_HAPPINESS:
break;
@@ -1969,10 +1990,10 @@ void Player::Regenerate(Powers power)
AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
for(AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i)
if ((*i)->GetModifier()->m_miscvalue == power)
- addvalue *= ((*i)->GetModifierValue() + 100) / 100.0f;
+ addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f;
}
- if (power != POWER_RAGE)
+ if (power != POWER_RAGE && power != POWER_RUNIC_POWER)
{
curValue += uint32(addvalue);
if (curValue > maxValue)
@@ -2010,7 +2031,7 @@ void Player::RegenerateHealth()
{
AuraList const& mModHealthRegenPct = GetAurasByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT);
for(AuraList::const_iterator i = mModHealthRegenPct.begin(); i != mModHealthRegenPct.end(); ++i)
- addvalue *= (100.0f + (*i)->GetModifierValue()) / 100.0f;
+ addvalue *= (100.0f + (*i)->GetModifier()->m_amount) / 100.0f;
}
else if(HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT))
addvalue *= GetTotalAuraModifier(SPELL_AURA_MOD_REGEN_DURING_COMBAT) / 100.0f;
@@ -2070,21 +2091,27 @@ void Player::SetGameMaster(bool on)
setFaction(35);
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM);
- RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);
+ RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
ResetContestedPvP();
getHostilRefManager().setOnlineOfflineState(false);
CombatStop();
+
+ SetPhaseMask(PHASEMASK_ANYWHERE,false); // see and visible in all phases
}
else
{
+ // restore phase
+ AuraList const& phases = GetAurasByType(SPELL_AURA_PHASE);
+ SetPhaseMask(!phases.empty() ? phases.front()->GetMiscValue() : PHASEMASK_NORMAL,false);
+
m_ExtraFlags &= ~ PLAYER_EXTRA_GM_ON;
setFactionForRace(getRace());
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM);
// restore FFA PvP Server state
if(sWorld.IsFFAPvPRealm())
- SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP);
+ SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
// restore FFA PvP area state, remove not allowed for GM mounts
UpdateArea(m_areaUpdateId);
@@ -2208,7 +2235,7 @@ void Player::GiveXP(uint32 xp, Unit* victim)
// handle SPELL_AURA_MOD_XP_PCT auras
Unit::AuraList const& ModXPPctAuras = GetAurasByType(SPELL_AURA_MOD_XP_PCT);
for(Unit::AuraList::const_iterator i = ModXPPctAuras.begin();i != ModXPPctAuras.end(); ++i)
- xp = uint32(xp*(1.0f + (*i)->GetModifierValue() / 100.0f));
+ xp = uint32(xp*(1.0f + (*i)->GetModifier()->m_amount / 100.0f));
// XP resting bonus for kill
uint32 rested_bonus_xp = victim ? GetXPRestBonus(xp) : 0;
@@ -2256,13 +2283,15 @@ void Player::GiveLevel(uint32 level)
data << uint32(0);
data << uint32(0);
data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
// end for
for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) // Stats loop (0-4)
data << uint32(int32(info.stats[i]) - GetCreateStat(Stats(i)));
GetSession()->SendPacket(&data);
- SetUInt32Value(PLAYER_NEXT_LEVEL_XP, Trinity::XP::xp_to_level(level));
+ SetUInt32Value(PLAYER_NEXT_LEVEL_XP, objmgr.GetXPForLevel(level));
//update level, max level of skills
if(getLevel()!= level)
@@ -2279,6 +2308,7 @@ void Player::GiveLevel(uint32 level)
InitTalentForLevel();
InitTaxiNodesForLevel();
+ InitGlyphsForLevel();
UpdateAllStats();
@@ -2298,6 +2328,7 @@ void Player::GiveLevel(uint32 level)
Pet* pet = GetPet();
if(pet && pet->getPetType()==SUMMON_PET)
pet->GivePetLevel(level);
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL);
}
void Player::InitTalentForLevel()
@@ -2315,7 +2346,8 @@ void Player::InitTalentForLevel()
}
else
{
- uint32 talentPointsForLevel = uint32((level-9)*sWorld.getRate(RATE_TALENT));
+ uint32 talentPointsForLevel = CalculateTalentsPoints();
+
// if used more that have then reset
if(m_usedTalentCount > talentPointsForLevel)
{
@@ -2342,7 +2374,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
objmgr.GetPlayerLevelInfo(getRace(),getClass(),getLevel(),&info);
SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) );
- SetUInt32Value(PLAYER_NEXT_LEVEL_XP, Trinity::XP::xp_to_level(getLevel()));
+ SetUInt32Value(PLAYER_NEXT_LEVEL_XP, objmgr.GetXPForLevel(getLevel()));
UpdateSkillsForLevel ();
@@ -2434,6 +2466,9 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetFloatValue(UNIT_FIELD_POWER_COST_MODIFIER+i,0.0f);
SetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,0.0f);
}
+ // Reset no reagent cost field
+ for(int i = 0; i < 3; i++)
+ SetUInt32Value(PLAYER_NO_REAGENT_COST_1 + i, 0);
// Init data for form but skip reapply item mods for form
InitDataForForm(reapplyMods);
@@ -2450,15 +2485,16 @@ void Player::InitStatsForLevel(bool reapplyMods)
RemoveFlag( UNIT_FIELD_FLAGS,
UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_ATTACKABLE_1 |
UNIT_FLAG_PET_IN_COMBAT | UNIT_FLAG_SILENCED | UNIT_FLAG_PACIFIED |
- UNIT_FLAG_DISABLE_ROTATE | UNIT_FLAG_IN_COMBAT | UNIT_FLAG_DISARMED |
+ UNIT_FLAG_STUNNED | UNIT_FLAG_IN_COMBAT | UNIT_FLAG_DISARMED |
UNIT_FLAG_CONFUSED | UNIT_FLAG_FLEEING | UNIT_FLAG_NOT_SELECTABLE |
UNIT_FLAG_SKINNABLE | UNIT_FLAG_MOUNT | UNIT_FLAG_TAXI_FLIGHT );
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); // must be set
// cleanup player flags (will be re-applied if need at aura load), to avoid have ghost flag without ghost aura, for example.
- RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK | PLAYER_FLAGS_DND | PLAYER_FLAGS_GM | PLAYER_FLAGS_GHOST | PLAYER_FLAGS_FFA_PVP);
+ RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK | PLAYER_FLAGS_DND | PLAYER_FLAGS_GM | PLAYER_FLAGS_GHOST);
- SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00); // one form stealth modified bytes
+ RemoveStandFlags(UNIT_STAND_FLAGS_ALL); // one form stealth modified bytes
+ RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP | UNIT_BYTE2_FLAG_SANCTUARY);
// restore if need some important flags
SetUInt32Value(PLAYER_FIELD_BYTES2, 0 ); // flags empty by default
@@ -2474,6 +2510,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE));
SetPower(POWER_FOCUS, 0);
SetPower(POWER_HAPPINESS, 0);
+ SetPower(POWER_RUNIC_POWER, 0);
}
void Player::SendInitialSpells()
@@ -2606,13 +2643,13 @@ void Player::AddNewMailDeliverTime(time_t deliver_time)
}
}
-bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, uint16 slot_id, bool disabled)
+bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
if (!spellInfo)
{
// do character spell book cleanup (all characters)
- if(loading && !learning) // spell load case
+ if(!IsInWorld() && !learning) // spell load case
{
sLog.outError("Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.",spell_id);
CharacterDatabase.PExecute("DELETE FROM character_spell WHERE spell = '%u'",spell_id);
@@ -2626,7 +2663,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
if(!SpellMgr::IsSpellValid(spellInfo,this,false))
{
// do character spell book cleanup (all characters)
- if(loading && !learning) // spell load case
+ if(!IsInWorld() && !learning) // spell load case
{
sLog.outError("Player::addSpell: Broken spell #%u learning not allowed, deleting for all characters in `character_spell`.",spell_id);
CharacterDatabase.PExecute("DELETE FROM character_spell WHERE spell = '%u'",spell_id);
@@ -2639,29 +2676,80 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
PlayerSpellState state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED;
+ bool dependent_set = false;
bool disabled_case = false;
bool superceded_old = false;
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
if (itr != m_spells.end())
{
+ uint32 next_active_spell_id = 0;
+ // fix activate state for non-stackable low rank (and find next spell for !active case)
+ if(!SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
+ {
+ if(uint32 next = spellmgr.GetNextSpellInChain(spell_id))
+ {
+ if(HasSpell(next))
+ {
+ // high rank already known so this must !active
+ active = false;
+ next_active_spell_id = next;
+ }
+ }
+ }
+
+ // not do anything if already known in expected state
+ if(itr->second->state != PLAYERSPELL_REMOVED && itr->second->active == active &&
+ itr->second->dependent == dependent && itr->second->disabled == disabled)
+ {
+ if(!IsInWorld() && !learning) // explicitly load from DB and then exist in it already and set correctly
+ itr->second->state = PLAYERSPELL_UNCHANGED;
+
+ return false;
+ }
+
+ // dependent spell known as not dependent, overwrite state
+ if (itr->second->state != PLAYERSPELL_REMOVED && !itr->second->dependent && dependent)
+ {
+ itr->second->dependent = dependent;
+ if (itr->second->state != PLAYERSPELL_NEW)
+ itr->second->state = PLAYERSPELL_CHANGED;
+ dependent_set = true;
+ }
+
// update active state for known spell
if(itr->second->active != active && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled)
{
itr->second->active = active;
- // loading && !learning == explicitly load from DB and then exist in it already and set correctly
- if(loading && !learning)
+ if(!IsInWorld() && !learning && !dependent_set) // explicitly load from DB and then exist in it already and set correctly
itr->second->state = PLAYERSPELL_UNCHANGED;
else if(itr->second->state != PLAYERSPELL_NEW)
itr->second->state = PLAYERSPELL_CHANGED;
- if(!active)
+ if(active)
{
- WorldPacket data(SMSG_REMOVED_SPELL, 4);
- data << uint16(spell_id);
- GetSession()->SendPacket(&data);
+ if (IsPassiveSpell(spell_id) && IsNeedCastPassiveSpellAtLearn(spellInfo))
+ CastSpell (this,spell_id,true);
}
+ else if(IsInWorld())
+ {
+ if(next_active_spell_id)
+ {
+ // update spell ranks in spellbook and action bar
+ WorldPacket data(SMSG_SUPERCEDED_SPELL, (4));
+ data << uint16(spell_id);
+ data << uint16(next_active_spell_id);
+ GetSession()->SendPacket( &data );
+ }
+ else
+ {
+ WorldPacket data(SMSG_REMOVED_SPELL, 4);
+ data << uint16(spell_id);
+ GetSession()->SendPacket(&data);
+ }
+ }
+
return active; // learn (show in spell book if active now)
}
@@ -2690,7 +2778,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
default: // known not saved yet spell (new or modified)
{
// can be in case spell loading but learned at some previous spell loading
- if(loading && !learning)
+ if(!IsInWorld() && !learning && !dependent_set)
itr->second->state = PLAYERSPELL_UNCHANGED;
return false;
@@ -2712,10 +2800,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
if(!rankSpellId || rankSpellId==spell_id)
continue;
- // skip unknown ranks
- if(!HasSpell(rankSpellId))
- continue;
-
removeSpell(rankSpellId);
}
}
@@ -2723,16 +2807,17 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
// non talent spell: learn low ranks (recursive call)
else if(uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id))
{
- if(loading) // at spells loading, no output, but allow save
- addSpell(prev_spell,active,true,loading,SPELL_WITHOUT_SLOT_ID,disabled);
+ if(!IsInWorld() || disabled) // at spells loading, no output, but allow save
+ addSpell(prev_spell,active,true,true,disabled);
else // at normal learning
- learnSpell(prev_spell);
+ learnSpell(prev_spell,true);
}
PlayerSpell *newspell = new PlayerSpell;
- newspell->active = active;
- newspell->state = state;
- newspell->disabled = disabled;
+ newspell->state = state;
+ newspell->active = active;
+ newspell->dependent = dependent;
+ newspell->disabled = disabled;
// replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible
if(newspell->active && !newspell->disabled && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
@@ -2749,7 +2834,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
{
if(spellmgr.IsHighRankOfSpell(spell_id,itr->first))
{
- if(!loading) // not send spell (re-/over-)learn packets at loading
+ if(IsInWorld()) // not send spell (re-/over-)learn packets at loading
{
WorldPacket data(SMSG_SUPERCEDED_SPELL, (4));
data << uint16(itr->first);
@@ -2759,12 +2844,13 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
// mark old spell as disable (SMSG_SUPERCEDED_SPELL replace it in client by new)
itr->second->active = false;
- itr->second->state = PLAYERSPELL_CHANGED;
+ if(itr->second->state != PLAYERSPELL_NEW)
+ itr->second->state = PLAYERSPELL_CHANGED;
superceded_old = true; // new spell replace old in action bars and spell book.
}
else if(spellmgr.IsHighRankOfSpell(itr->first,spell_id))
{
- if(!loading) // not send spell (re-/over-)learn packets at loading
+ if(IsInWorld()) // not send spell (re-/over-)learn packets at loading
{
WorldPacket data(SMSG_SUPERCEDED_SPELL, (4));
data << uint16(spell_id);
@@ -2782,23 +2868,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
}
}
- uint16 tmpslot=slot_id;
-
- if (tmpslot == SPELL_WITHOUT_SLOT_ID)
- {
- uint16 maxid = 0;
- PlayerSpellMap::iterator itr;
- for (itr = m_spells.begin(); itr != m_spells.end(); ++itr)
- {
- if(itr->second->state == PLAYERSPELL_REMOVED)
- continue;
- if (itr->second->slotId > maxid)
- maxid = itr->second->slotId;
- }
- tmpslot = maxid + 1;
- }
-
- newspell->slotId = tmpslot;
m_spells[spell_id] = newspell;
// return false if spell disabled
@@ -2818,23 +2887,8 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
// also cast passive spells (including all talents without SPELL_EFFECT_LEARN_SPELL) with additional checks
else if (IsPassiveSpell(spell_id))
{
- // if spell doesn't require a stance or the player is in the required stance
- if( ( !spellInfo->Stances &&
- spell_id != 5420 && spell_id != 5419 && spell_id != 7376 &&
- spell_id != 7381 && spell_id != 21156 && spell_id != 21009 &&
- spell_id != 21178 && spell_id != 33948 && spell_id != 40121 ) ||
- m_form != 0 && (spellInfo->Stances & (1<<(m_form-1))) ||
- (spell_id == 5420 && m_form == FORM_TREE) ||
- (spell_id == 5419 && m_form == FORM_TRAVEL) ||
- (spell_id == 7376 && m_form == FORM_DEFENSIVESTANCE) ||
- (spell_id == 7381 && m_form == FORM_BERSERKERSTANCE) ||
- (spell_id == 21156 && m_form == FORM_BATTLESTANCE)||
- (spell_id == 21178 && (m_form == FORM_BEAR || m_form == FORM_DIREBEAR) ) ||
- (spell_id == 33948 && m_form == FORM_FLIGHT) ||
- (spell_id == 40121 && m_form == FORM_FLIGHT_EPIC) )
- //Check CasterAuraStates
- if (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState)))
- CastSpell(this, spell_id, true);
+ if(IsNeedCastPassiveSpellAtLearn(spellInfo))
+ CastSpell(this, spell_id, true);
}
else if( IsSpellHaveEffect(spellInfo,SPELL_EFFECT_SKILL_STEP) )
{
@@ -2888,8 +2942,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
continue;
if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL ||
- // poison special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
- pSkill->id==SKILL_POISONS && _spell_idx->second->max_value==0 ||
// lockpicking special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
pSkill->id==SKILL_LOCKPICKING && _spell_idx->second->max_value==0 )
{
@@ -2919,37 +2971,71 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading,
{
if(!itr->second.autoLearned)
{
- if(loading) // at spells loading, no output, but allow save
- addSpell(itr->second.spell,true,true,loading);
+ if(!IsInWorld() || !itr->second.active) // at spells loading, no output, but allow save
+ addSpell(itr->second.spell,itr->second.active,true,true,false);
else // at normal learning
- learnSpell(itr->second.spell);
+ learnSpell(itr->second.spell,true);
}
}
+ if(IsInWorld())
+ {
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL);
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS);
+ }
+
// return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell
return active && !disabled && !superceded_old;
}
-void Player::learnSpell(uint32 spell_id)
+bool Player::IsNeedCastPassiveSpellAtLearn(SpellEntry const* spellInfo) const
+{
+ bool need_cast = false;
+
+ switch(spellInfo->Id)
+ {
+ // some spells not have stance data expacted cast at form change or present
+ case 5420: need_cast = (m_form == FORM_TREE); break;
+ case 5419: need_cast = (m_form == FORM_TRAVEL); break;
+ case 7376: need_cast = (m_form == FORM_DEFENSIVESTANCE); break;
+ case 7381: need_cast = (m_form == FORM_BERSERKERSTANCE); break;
+ case 21156: need_cast = (m_form == FORM_BATTLESTANCE); break;
+ case 21178: need_cast = (m_form == FORM_BEAR || m_form == FORM_DIREBEAR); break;
+ case 33948: need_cast = (m_form == FORM_FLIGHT); break;
+ case 34764: need_cast = (m_form == FORM_FLIGHT); break;
+ case 40121: need_cast = (m_form == FORM_FLIGHT_EPIC); break;
+ case 40122: need_cast = (m_form == FORM_FLIGHT_EPIC); break;
+ // another spells have proper stance data
+ default: need_cast = !spellInfo->Stances || m_form != 0 && (spellInfo->Stances & (1<<(m_form-1))); break;
+ }
+
+ //Check CasterAuraStates
+ return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState)));
+}
+
+void Player::learnSpell(uint32 spell_id, bool dependent)
{
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
bool disabled = (itr != m_spells.end()) ? itr->second->disabled : false;
bool active = disabled ? itr->second->active : true;
- bool learning = addSpell(spell_id,active);
+ bool learning = addSpell(spell_id,active,true,dependent,false);
// learn all disabled higher ranks (recursive)
- SpellChainNode const* node = spellmgr.GetSpellChainNode(spell_id);
- if (node)
+ if(disabled)
{
- PlayerSpellMap::iterator iter = m_spells.find(node->next);
- if (disabled && iter != m_spells.end() && iter->second->disabled )
- learnSpell(node->next);
+ SpellChainNode const* node = spellmgr.GetSpellChainNode(spell_id);
+ if(node)
+ {
+ PlayerSpellMap::iterator iter = m_spells.find(node->next);
+ if (iter != m_spells.end() && iter->second->disabled )
+ learnSpell(node->next,false);
+ }
}
- // prevent duplicated entires in spell book
- if(!learning)
+ // prevent duplicated entires in spell book, also not send if not in world (loading)
+ if(!learning || !IsInWorld ())
return;
WorldPacket data(SMSG_LEARNED_SPELL, 4);
@@ -2957,7 +3043,7 @@ void Player::learnSpell(uint32 spell_id)
GetSession()->SendPacket(&data);
}
-void Player::removeSpell(uint32 spell_id, bool disabled)
+void Player::removeSpell(uint32 spell_id, bool disabled, bool update_action_bar_for_low_rank)
{
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
if (itr == m_spells.end())
@@ -2979,10 +3065,8 @@ void Player::removeSpell(uint32 spell_id, bool disabled)
for (uint32 i=reqMap.count(spell_id);i>0;i--,itr2++)
removeSpell(itr2->second,disabled);
- // removing
- WorldPacket data(SMSG_REMOVED_SPELL, 4);
- data << uint16(spell_id);
- GetSession()->SendPacket(&data);
+ bool cur_active = itr->second->active;
+ bool cur_dependent = itr->second->dependent;
if (disabled)
{
@@ -3075,8 +3159,6 @@ void Player::removeSpell(uint32 spell_id, bool disabled)
continue;
if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL ||
- // poison special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
- pSkill->id==SKILL_POISONS && _spell_idx->second->max_value==0 ||
// lockpicking special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
pSkill->id==SKILL_LOCKPICKING && _spell_idx->second->max_value==0 )
{
@@ -3096,6 +3178,58 @@ void Player::removeSpell(uint32 spell_id, bool disabled)
for(SpellLearnSpellMap::const_iterator itr2 = spell_begin; itr2 != spell_end; ++itr2)
removeSpell(itr2->second.spell, disabled);
+
+ // activate lesser rank in spellbook/action bar, and cast it if need
+ bool prev_activate = false;
+
+ if(uint32 prev_id = spellmgr.GetPrevSpellInChain (spell_id))
+ {
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
+
+ // if talent then lesser rank also talent and need learn
+ if(talentCosts)
+ learnSpell (prev_id,false);
+ // if ranked non-stackable spell: need activate lesser rank and update dendence state
+ else if(cur_active && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
+ {
+ // need manually update dependence state (learn spell ignore like attempts)
+ PlayerSpellMap::iterator prev_itr = m_spells.find(prev_id);
+ if (prev_itr != m_spells.end())
+ {
+ if(prev_itr->second->dependent != cur_dependent)
+ {
+ prev_itr->second->dependent = cur_dependent;
+ if(prev_itr->second->state != PLAYERSPELL_NEW)
+ prev_itr->second->state = PLAYERSPELL_CHANGED;
+ }
+
+ // now re-learn if need re-activate
+ if(cur_active && !prev_itr->second->active)
+ {
+ if(addSpell(prev_id,true,false,prev_itr->second->dependent,prev_itr->second->disabled))
+ {
+ if(update_action_bar_for_low_rank)
+ {
+ // downgrade spell ranks in spellbook and action bar
+ WorldPacket data(SMSG_SUPERCEDED_SPELL, (4));
+ data << uint16(spell_id);
+ data << uint16(prev_id);
+ GetSession()->SendPacket( &data );
+ prev_activate = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // remove from spell book if not replaced by lesser rank
+ if(!prev_activate)
+ {
+ WorldPacket data(SMSG_REMOVED_SPELL, 4);
+ data << uint16(spell_id);
+ GetSession()->SendPacket(&data);
+ }
}
void Player::RemoveArenaSpellCooldowns()
@@ -3238,8 +3372,7 @@ bool Player::resetTalents(bool no_cost)
CharacterDatabase.PExecute("UPDATE characters set at_login = at_login & ~ %u WHERE guid ='%u'", uint32(AT_LOGIN_RESET_TALENTS), GetGUIDLow());
}
- uint32 level = getLevel();
- uint32 talentPointsForLevel = level < 10 ? 0 : uint32((level-9)*sWorld.getRate(RATE_TALENT));
+ uint32 talentPointsForLevel = CalculateTalentsPoints();
if (m_usedTalentCount == 0)
{
@@ -3319,18 +3452,6 @@ bool Player::resetTalents(bool no_cost)
return true;
}
-bool Player::_removeSpell(uint16 spell_id)
-{
- PlayerSpellMap::iterator itr = m_spells.find(spell_id);
- if (itr != m_spells.end())
- {
- delete itr->second;
- m_spells.erase(itr);
- return true;
- }
- return false;
-}
-
Mail* Player::GetMail(uint32 id)
{
for(PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr)
@@ -3376,50 +3497,46 @@ void Player::InitVisibleBits()
{
updateVisualBits.SetCount(PLAYER_END);
- // TODO: really implement OWNER_ONLY and GROUP_ONLY. Flags can be found in UpdateFields.h
-
updateVisualBits.SetBit(OBJECT_FIELD_GUID);
updateVisualBits.SetBit(OBJECT_FIELD_TYPE);
+ updateVisualBits.SetBit(OBJECT_FIELD_ENTRY);
updateVisualBits.SetBit(OBJECT_FIELD_SCALE_X);
-
- updateVisualBits.SetBit(UNIT_FIELD_CHARM);
- updateVisualBits.SetBit(UNIT_FIELD_CHARM+1);
-
- updateVisualBits.SetBit(UNIT_FIELD_SUMMON);
- updateVisualBits.SetBit(UNIT_FIELD_SUMMON+1);
-
- updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY);
- updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY+1);
-
- updateVisualBits.SetBit(UNIT_FIELD_TARGET);
- updateVisualBits.SetBit(UNIT_FIELD_TARGET+1);
-
- updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT);
- updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT+1);
-
+ updateVisualBits.SetBit(UNIT_FIELD_CHARM + 0);
+ updateVisualBits.SetBit(UNIT_FIELD_CHARM + 1);
+ updateVisualBits.SetBit(UNIT_FIELD_SUMMON + 0);
+ updateVisualBits.SetBit(UNIT_FIELD_SUMMON + 1);
+ updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY + 0);
+ updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY + 1);
+ updateVisualBits.SetBit(UNIT_FIELD_TARGET + 0);
+ updateVisualBits.SetBit(UNIT_FIELD_TARGET + 1);
+ updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT + 0);
+ updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT + 1);
+ updateVisualBits.SetBit(UNIT_FIELD_BYTES_0);
updateVisualBits.SetBit(UNIT_FIELD_HEALTH);
updateVisualBits.SetBit(UNIT_FIELD_POWER1);
updateVisualBits.SetBit(UNIT_FIELD_POWER2);
updateVisualBits.SetBit(UNIT_FIELD_POWER3);
updateVisualBits.SetBit(UNIT_FIELD_POWER4);
updateVisualBits.SetBit(UNIT_FIELD_POWER5);
-
+ updateVisualBits.SetBit(UNIT_FIELD_POWER6);
+ updateVisualBits.SetBit(UNIT_FIELD_POWER7);
updateVisualBits.SetBit(UNIT_FIELD_MAXHEALTH);
updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER1);
updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER2);
updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER3);
updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER4);
updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER5);
-
+ updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER6);
+ updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER7);
updateVisualBits.SetBit(UNIT_FIELD_LEVEL);
updateVisualBits.SetBit(UNIT_FIELD_FACTIONTEMPLATE);
- updateVisualBits.SetBit(UNIT_FIELD_BYTES_0);
+ updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 0);
+ updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 1);
+ updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 2);
updateVisualBits.SetBit(UNIT_FIELD_FLAGS);
updateVisualBits.SetBit(UNIT_FIELD_FLAGS_2);
- for(uint16 i = UNIT_FIELD_AURA; i < UNIT_FIELD_AURASTATE; ++i)
- updateVisualBits.SetBit(i);
updateVisualBits.SetBit(UNIT_FIELD_AURASTATE);
- updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME);
+ updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME + 0);
updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME + 1);
updateVisualBits.SetBit(UNIT_FIELD_BOUNDINGRADIUS);
updateVisualBits.SetBit(UNIT_FIELD_COMBATREACH);
@@ -3432,10 +3549,12 @@ void Player::InitVisibleBits()
updateVisualBits.SetBit(UNIT_DYNAMIC_FLAGS);
updateVisualBits.SetBit(UNIT_CHANNEL_SPELL);
updateVisualBits.SetBit(UNIT_MOD_CAST_SPEED);
+ updateVisualBits.SetBit(UNIT_FIELD_BASE_MANA);
updateVisualBits.SetBit(UNIT_FIELD_BYTES_2);
+ updateVisualBits.SetBit(UNIT_FIELD_HOVERHEIGHT);
- updateVisualBits.SetBit(PLAYER_DUEL_ARBITER);
- updateVisualBits.SetBit(PLAYER_DUEL_ARBITER+1);
+ updateVisualBits.SetBit(PLAYER_DUEL_ARBITER + 0);
+ updateVisualBits.SetBit(PLAYER_DUEL_ARBITER + 1);
updateVisualBits.SetBit(PLAYER_FLAGS);
updateVisualBits.SetBit(PLAYER_GUILDID);
updateVisualBits.SetBit(PLAYER_GUILDRANK);
@@ -3446,29 +3565,29 @@ void Player::InitVisibleBits()
updateVisualBits.SetBit(PLAYER_GUILD_TIMESTAMP);
// PLAYER_QUEST_LOG_x also visible bit on official (but only on party/raid)...
- for(uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i+=4)
+ for(uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i += 4)
updateVisualBits.SetBit(i);
- //Players visible items are not inventory stuff
- //431) = 884 (0x374) = main weapon
- for(uint16 i = 0; i < EQUIPMENT_SLOT_END; i++)
+ // Players visible items are not inventory stuff
+ for(uint16 i = 0; i < EQUIPMENT_SLOT_END; ++i)
{
- // item creator
- updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + (i*MAX_VISIBLE_ITEM_OFFSET) + 0);
- updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + (i*MAX_VISIBLE_ITEM_OFFSET) + 1);
+ uint32 offset = i * MAX_VISIBLE_ITEM_OFFSET;
- uint16 visual_base = PLAYER_VISIBLE_ITEM_1_0 + (i*MAX_VISIBLE_ITEM_OFFSET);
+ // item creator
+ updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + 0 + offset);
+ updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + 1 + offset);
// item entry
- updateVisualBits.SetBit(visual_base + 0);
+ updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_0 + 0 + offset);
- // item enchantment IDs
- for(uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j)
- updateVisualBits.SetBit(visual_base + 1 + j);
+ // item enchantments
+ for(uint8 j = 0; j < MAX_ENCHANTMENT_SLOT; ++j)
+ updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_0 + 1 + j + offset);
// random properties
- updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 0 + (i*MAX_VISIBLE_ITEM_OFFSET));
- updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 1 + (i*MAX_VISIBLE_ITEM_OFFSET));
+ updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + offset);
+ updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_SEED + offset);
+ updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PAD + offset);
}
updateVisualBits.SetBit(PLAYER_CHOSEN_TITLE);
@@ -3486,7 +3605,6 @@ void Player::BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target )
if(target == this)
{
-
for(int i = INVENTORY_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
{
if(m_items[i] == NULL)
@@ -3494,7 +3612,7 @@ void Player::BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target )
m_items[i]->BuildCreateUpdateBlockForPlayer( data, target );
}
- for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
+ for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++)
{
if(m_items[i] == NULL)
continue;
@@ -3527,7 +3645,7 @@ void Player::DestroyForPlayer( Player *target ) const
m_items[i]->DestroyForPlayer( target );
}
- for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
+ for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++)
{
if(m_items[i] == NULL)
continue;
@@ -3539,8 +3657,16 @@ void Player::DestroyForPlayer( Player *target ) const
bool Player::HasSpell(uint32 spell) const
{
- PlayerSpellMap::const_iterator itr = m_spells.find((uint16)spell);
- return (itr != m_spells.end() && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled);
+ PlayerSpellMap::const_iterator itr = m_spells.find(spell);
+ return (itr != m_spells.end() && itr->second->state != PLAYERSPELL_REMOVED &&
+ !itr->second->disabled);
+}
+
+bool Player::HasActiveSpell(uint32 spell) const
+{
+ PlayerSpellMap::const_iterator itr = m_spells.find(spell);
+ return (itr != m_spells.end() && itr->second->state != PLAYERSPELL_REMOVED &&
+ itr->second->active && !itr->second->disabled);
}
TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell) const
@@ -3548,22 +3674,22 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell
if (!trainer_spell)
return TRAINER_SPELL_RED;
- if (!trainer_spell->spell)
+ if (!trainer_spell->learned_spell)
return TRAINER_SPELL_RED;
// known spell
- if(HasSpell(trainer_spell->spell))
+ if(HasSpell(trainer_spell->learned_spell))
return TRAINER_SPELL_GRAY;
// check race/class requirement
- if(!IsSpellFitByClassAndRace(trainer_spell->spell))
+ if(!IsSpellFitByClassAndRace(trainer_spell->learned_spell))
return TRAINER_SPELL_RED;
// check level requirement
if(getLevel() < trainer_spell->reqlevel)
return TRAINER_SPELL_RED;
- if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->spell))
+ if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->learned_spell))
{
// check prev.rank requirement
if(spell_chain->prev && !HasSpell(spell_chain->prev))
@@ -3582,7 +3708,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell
return TRAINER_SPELL_RED;
// exist, already checked at loading
- SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->spell);
+ SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->learned_spell);
// secondary prof. or not prof. spell
uint32 skill = spell->EffectMiscValue[1];
@@ -3615,27 +3741,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
}
// remove from arena teams
- uint32 at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_2v2);
- if(at_id != 0)
- {
- ArenaTeam * at = objmgr.GetArenaTeamById(at_id);
- if(at)
- at->DelMember(playerguid);
- }
- at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_3v3);
- if(at_id != 0)
- {
- ArenaTeam * at = objmgr.GetArenaTeamById(at_id);
- if(at)
- at->DelMember(playerguid);
- }
- at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_5v5);
- if(at_id != 0)
- {
- ArenaTeam * at = objmgr.GetArenaTeamById(at_id);
- if(at)
- at->DelMember(playerguid);
- }
+ LeaveAllArenaTeams(playerguid);
// the player was uninvited already on logout so just remove from group
QueryResult *resultGroup = CharacterDatabase.PQuery("SELECT leaderGuid FROM group_member WHERE memberGuid='%u'", guid);
@@ -3676,15 +3782,16 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
MailItemsInfo mi;
if(has_items)
{
- QueryResult *resultItems = CharacterDatabase.PQuery("SELECT item_guid,item_template FROM mail_items WHERE mail_id='%u'", mail_id);
+ // data needs to be at first place for Item::LoadFromDB
+ QueryResult *resultItems = CharacterDatabase.PQuery("SELECT data,item_guid,item_template FROM mail_items JOIN item_instance ON item_guid = guid WHERE mail_id='%u'", mail_id);
if(resultItems)
{
do
{
Field *fields2 = resultItems->Fetch();
- uint32 item_guidlow = fields2[0].GetUInt32();
- uint32 item_template = fields2[1].GetUInt32();
+ uint32 item_guidlow = fields2[1].GetUInt32();
+ uint32 item_template = fields2[2].GetUInt32();
ItemPrototype const* itemProto = objmgr.GetItemPrototype(item_template);
if(!itemProto)
@@ -3694,7 +3801,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
}
Item *pItem = NewItemOrBag(itemProto);
- if(!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)))
+ if(!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),resultItems))
{
pItem->FSetState(ITEM_REMOVED);
pItem->SaveToDB(); // it also deletes item object !
@@ -3757,6 +3864,8 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
CharacterDatabase.PExecute("DELETE FROM mail_items WHERE receiver = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u'",guid);
+ CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = '%u'",guid);
+ CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = '%u'",guid);
CharacterDatabase.CommitTransaction();
//LoginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID);
@@ -3787,6 +3896,10 @@ void Player::SetMovement(PlayerMovementType pType)
*/
void Player::BuildPlayerRepop()
{
+ WorldPacket data(SMSG_PRE_RESURRECT, GetPackGUID().size());
+ data.append(GetPackGUID());
+ GetSession()->SendPacket(&data);
+
if(getRace() == RACE_NIGHTELF)
CastSpell(this, 20584, true); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form)
CastSpell(this, 8326, true); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?)
@@ -3831,7 +3944,8 @@ void Player::BuildPlayerRepop()
SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, (float)1.0); //see radius of death player?
- SetByteValue(UNIT_FIELD_BYTES_1, 3, PLAYER_STATE_FLAG_ALWAYS_STAND);
+ // set and clear other
+ SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND);
}
void Player::SendDelayResponse(const uint32 ml_seconds)
@@ -3907,7 +4021,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
if(Aura* Aur = GetAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,i))
{
Aur->SetAuraDuration(delta*1000);
- Aur->UpdateAuraDuration();
+ Aur->SendAuraUpdate(false);
}
}
}
@@ -3948,8 +4062,7 @@ void Player::CreateCorpse()
Corpse *corpse = new Corpse( (m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH) ? CORPSE_RESURRECTABLE_PVP : CORPSE_RESURRECTABLE_PVE );
SetPvPDeath(false);
- if(!corpse->Create(objmgr.GenerateLowGuid(HIGHGUID_CORPSE), this, GetMapId(), GetPositionX(),
- GetPositionY(), GetPositionZ(), GetOrientation()))
+ if(!corpse->Create(objmgr.GenerateLowGuid(HIGHGUID_CORPSE), this))
{
delete corpse;
return;
@@ -4445,7 +4558,7 @@ uint32 Player::GetShieldBlockValue() const
{
BaseModGroup modGroup = SHIELD_BLOCK_VALUE;
- float value = GetTotalBaseModValue(modGroup) + GetStat(STAT_STRENGTH)/20 - 1;
+ float value = GetTotalBaseModValue(modGroup) + GetStat(STAT_STRENGTH) * 0.5f - 10;
value = (value < 0) ? 0 : value;
@@ -4634,7 +4747,18 @@ float Player::OCTRegenMPPerSpirit()
void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply)
{
- ApplyModUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, value, apply);
+ m_baseRatingValue[cr]+=(apply ? value : -value);
+
+ int32 amount = uint32(m_baseRatingValue[cr]);
+ // Apply bonus from SPELL_AURA_MOD_RATING_FROM_STAT
+ // stat used stored in miscValueB for this aura
+ AuraList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT);
+ for(AuraList::const_iterator i = modRatingFromStat.begin();i != modRatingFromStat.end(); ++i)
+ if ((*i)->GetMiscValue() & (1<<cr))
+ amount += int32(GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetModifier()->m_amount / 100.0f);
+ if (amount < 0)
+ amount = 0;
+ SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, uint32(amount));
float RatingCoeffecient = GetRatingCoefficient(cr);
float RatingChange = 0.0f;
@@ -4657,16 +4781,13 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply)
UpdateBlockPercentage();
break;
case CR_HIT_MELEE:
- RatingChange = value / RatingCoeffecient;
- m_modMeleeHitChance += apply ? RatingChange : -RatingChange;
+ UpdateMeleeHitChances();
break;
case CR_HIT_RANGED:
- RatingChange = value / RatingCoeffecient;
- m_modRangedHitChance += apply ? RatingChange : -RatingChange;
+ UpdateRangedHitChances();
break;
case CR_HIT_SPELL:
- RatingChange = value / RatingCoeffecient;
- m_modSpellHitChance += apply ? RatingChange : -RatingChange;
+ UpdateSpellHitChances();
break;
case CR_CRIT_MELEE:
if(affectStats)
@@ -4764,6 +4885,7 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
new_value = max;
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,max));
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL);
return true;
}
@@ -4799,7 +4921,7 @@ bool Player::UpdateCraftSkill(uint32 spellid)
if(spellEntry && spellEntry->Mechanic==MECHANIC_DISCOVERY)
{
if(uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->skillId, spellid, this))
- learnSpell(discoveredSpell);
+ learnSpell(discoveredSpell,false);
}
uint32 craft_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_CRAFTING);
@@ -4826,6 +4948,7 @@ bool Player::UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 RedLeve
case SKILL_HERBALISM:
case SKILL_LOCKPICKING:
case SKILL_JEWELCRAFTING:
+ case SKILL_INSCRIPTION:
return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel+100, RedLevel+50, RedLevel+25)*Multiplicator,gathering_skill_gain);
case SKILL_SKINNING:
if( sWorld.getConfig(CONFIG_SKILL_CHANCE_SKINNING_STEPS)==0)
@@ -4854,6 +4977,11 @@ bool Player::UpdateFishingSkill()
return UpdateSkillPro(SKILL_FISHING,chance*10,gathering_skill_gain);
}
+// levels sync. with spell requirement for skill levels to learn
+// bonus abilities in sSkillLineAbilityStore
+// Used only to avoid scan DBC at each skill grow
+static uint32 bonusSkillLevels[] = {75,150,225,300,375,450};
+
bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
{
sLog.outDebug("UpdateSkillPro(SkillId %d, Chance %3.1f%%)", SkillId, Chance/10.0);
@@ -4888,6 +5016,15 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
new_value = MaxValue;
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,MaxValue));
+ for(uint32* bsl = &bonusSkillLevels[0]; *bsl; ++bsl)
+ {
+ if((SkillValue < *bsl && new_value >= *bsl))
+ {
+ learnSkillRewardedSpells( SkillId, new_value);
+ break;
+ }
+ }
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL);
sLog.outDebug("Player::UpdateSkillPro Chance=%3.1f%% taken", Chance/10.0);
return true;
}
@@ -4935,22 +5072,8 @@ void Player::UpdateWeaponSkill (WeaponAttackType attType)
UpdateAllCritPercentages();
}
-void Player::UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, MeleeHitOutcome outcome, bool defence)
+void Player::UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, bool defence)
{
-/* Not need, this checked on call this func from trigger system
- switch(outcome)
- {
- case MELEE_HIT_CRIT:
- case MELEE_HIT_DODGE:
- case MELEE_HIT_PARRY:
- case MELEE_HIT_BLOCK:
- case MELEE_HIT_BLOCK_CRIT:
- return;
-
- default:
- break;
- }
-*/
uint32 plevel = getLevel(); // if defense than pVictim == attacker
uint32 greylevel = Trinity::XP::GetGrayLevel(plevel);
uint32 moblevel = pVictim->getLevelForTarget(this);
@@ -5047,7 +5170,7 @@ void Player::UpdateSkillsToMaxSkillsForLevel()
if (GetUInt32Value(PLAYER_SKILL_INDEX(i)))
{
uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
- if( IsProfessionSkill(pskill) || pskill == SKILL_RIDING )
+ if( IsProfessionOrRidingSkill(pskill))
continue;
uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i));
@@ -5075,7 +5198,11 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
if(i<PLAYER_MAX_SKILLS) //has skill
{
if(currVal)
+ {
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(currVal,maxVal));
+ learnSkillRewardedSpells(id, currVal);
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL);
+ }
else //remove
{
// clear skill fields
@@ -5083,27 +5210,11 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),0);
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
- // remove spells that depend on this skill when removing the skill
- for (PlayerSpellMap::const_iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next)
- {
- ++next;
- if(itr->second->state == PLAYERSPELL_REMOVED)
- continue;
-
- SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first);
- SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(itr->first);
-
- for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
- {
- if (_spell_idx->second->skillId == id)
- {
- // this may remove more than one spell (dependents)
- removeSpell(itr->first);
- next = m_spells.begin();
- break;
- }
- }
- }
+ // remove all spells that related to this skill
+ for (uint32 j=0; j<sSkillLineAbilityStore.GetNumRows(); ++j)
+ if(SkillLineAbilityEntry const *pAbility = sSkillLineAbilityStore.LookupEntry(j))
+ if (pAbility->skillId==id)
+ removeSpell(spellmgr.GetFirstSpellInChain(pAbility->spellId));
}
}
else if(currVal) //add
@@ -5123,6 +5234,7 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
else
SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0));
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(currVal,maxVal));
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL);
// apply skill bonuses
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
@@ -5140,7 +5252,7 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
(*i)->ApplyModifier(true);
// Learn all spells for skill
- learnSkillRewardedSpells(id);
+ learnSkillRewardedSpells(id, currVal);
return;
}
}
@@ -5238,6 +5350,22 @@ uint16 Player::GetPureSkillValue(uint32 skill) const
return 0;
}
+int16 Player::GetSkillPermBonusValue(uint32 skill) const
+{
+ if(!skill)
+ return 0;
+
+ for (int i = 0; i < PLAYER_MAX_SKILLS; i++)
+ {
+ if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
+ {
+ return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)));
+ }
+ }
+
+ return 0;
+}
+
int16 Player::GetSkillTempBonusValue(uint32 skill) const
{
if(!skill)
@@ -5419,14 +5547,14 @@ void Player::CheckExploreSystem()
if (isInFlight())
return;
- uint16 areaFlag=MapManager::Instance().GetBaseMap(GetMapId())->GetAreaFlag(GetPositionX(),GetPositionY());
+ uint16 areaFlag=MapManager::Instance().GetBaseMap(GetMapId())->GetAreaFlag(GetPositionX(),GetPositionY(),GetPositionZ());
if(areaFlag==0xffff)
return;
int offset = areaFlag / 32;
if(offset >= 128)
{
- sLog.outError("ERROR: Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < 64 ).",areaFlag,GetPositionX(),GetPositionY(),offset,offset);
+ sLog.outError("ERROR: Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < 128 ).",areaFlag,GetPositionX(),GetPositionY(),offset,offset);
return;
}
@@ -5437,6 +5565,8 @@ void Player::CheckExploreSystem()
{
SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val));
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA);
+
AreaTableEntry const *p = GetAreaEntryByAreaFlagAndMap(areaFlag,GetMapId());
if(!p)
{
@@ -5533,6 +5663,7 @@ void Player::SendFactionState(FactionState const* faction) const
{
WorldPacket data(SMSG_SET_FACTION_STANDING, (16)); // last check 2.4.0
data << (float) 0; // unk 2.4.0
+ data << (uint8) 0; // wotlk 8634
data << (uint32) 1; // count
// for
data << (uint32) faction->ReputationListID;
@@ -5864,7 +5995,8 @@ bool Player::ModifyOneFactionReputation(FactionEntry const* factionEntry, int32
}
}
}
-
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION);
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION);
SendFactionState(&(itr->second));
return true;
@@ -5930,6 +6062,8 @@ bool Player::SetOneFactionReputation(FactionEntry const* factionEntry, int32 sta
SetFactionAtWar(&itr->second,true);
SendFactionState(&(itr->second));
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION);
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION);
return true;
}
return false;
@@ -6128,12 +6262,7 @@ bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor, bool pvpt
victim_guid = 0; // Don't show HK: <rank> message, only log.
}
- if(k_level <= 5)
- k_grey = 0;
- else if( k_level <= 39 )
- k_grey = k_level - 5 - k_level/10;
- else
- k_grey = k_level - 1 - k_level/5;
+ k_grey = Trinity::XP::GetGrayLevel(k_level);
if(v_level<=k_grey)
return false;
@@ -6169,6 +6298,8 @@ bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor, bool pvpt
if(groupsize > 1)
honor /= groupsize;
+ // apply honor multiplier from aura (not stacking-get highest)
+ honor *= (float(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HONOR_GAIN_PCT))+100.0f)/100.0f;
honor *= (((float)urand(8,12))/10); // approx honor: 80% - 120% of real honor
}
@@ -6198,8 +6329,8 @@ bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor, bool pvpt
{
// Check if allowed to receive it in current map
uint8 MapType = sWorld.getConfig(CONFIG_PVP_TOKEN_MAP_TYPE);
- if( (MapType == 1 && !InBattleGround() && !HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP))
- || (MapType == 2 && !HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP))
+ if( (MapType == 1 && !InBattleGround() && !HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
+ || (MapType == 2 && !HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
|| (MapType == 3 && !InBattleGround()) )
return true;
@@ -6257,24 +6388,18 @@ void Player::ModifyArenaPoints( int32 value )
uint32 Player::GetGuildIdFromDB(uint64 guid)
{
- std::ostringstream ss;
- ss<<"SELECT guildid FROM guild_member WHERE guid='"<<guid<<"'";
- QueryResult *result = CharacterDatabase.Query( ss.str().c_str() );
- if( result )
- {
- uint32 v = result->Fetch()[0].GetUInt32();
- delete result;
- return v;
- }
- else
+ QueryResult* result = CharacterDatabase.PQuery("SELECT guildid FROM guild_member WHERE guid='%u'", GUID_LOPART(guid));
+ if(!result)
return 0;
+
+ uint32 id = result->Fetch()[0].GetUInt32();
+ delete result;
+ return id;
}
uint32 Player::GetRankFromDB(uint64 guid)
{
- std::ostringstream ss;
- ss<<"SELECT rank FROM guild_member WHERE guid='"<<guid<<"'";
- QueryResult *result = CharacterDatabase.Query( ss.str().c_str() );
+ QueryResult *result = CharacterDatabase.PQuery( "SELECT rank FROM guild_member WHERE guid='%u'", GUID_LOPART(guid) );
if( result )
{
uint32 v = result->Fetch()[0].GetUInt32();
@@ -6298,10 +6423,8 @@ uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type)
uint32 Player::GetZoneIdFromDB(uint64 guid)
{
- std::ostringstream ss;
-
- ss<<"SELECT zone FROM characters WHERE guid='"<<GUID_LOPART(guid)<<"'";
- QueryResult *result = CharacterDatabase.Query( ss.str().c_str() );
+ uint32 guidLow = GUID_LOPART(guid);
+ QueryResult *result = CharacterDatabase.PQuery( "SELECT zone FROM characters WHERE guid='%u'", guidLow );
if (!result)
return 0;
Field* fields = result->Fetch();
@@ -6311,22 +6434,19 @@ uint32 Player::GetZoneIdFromDB(uint64 guid)
if (!zone)
{
// stored zone is zero, use generic and slow zone detection
- ss.str("");
- ss<<"SELECT map,position_x,position_y FROM characters WHERE guid='"<<GUID_LOPART(guid)<<"'";
- result = CharacterDatabase.Query(ss.str().c_str());
+ result = CharacterDatabase.PQuery("SELECT map,position_x,position_y,position_z FROM characters WHERE guid='%u'", guidLow);
if( !result )
return 0;
fields = result->Fetch();
- uint32 map = fields[0].GetUInt32();
+ uint32 map = fields[0].GetUInt32();
float posx = fields[1].GetFloat();
float posy = fields[2].GetFloat();
+ float posz = fields[3].GetFloat();
delete result;
- zone = MapManager::Instance().GetZoneId(map,posx,posy);
+ zone = MapManager::Instance().GetZoneId(map,posx,posy,posz);
- ss.str("");
- ss << "UPDATE characters SET zone='"<<zone<<"' WHERE guid='"<<GUID_LOPART(guid)<<"'";
- CharacterDatabase.Execute(ss.str().c_str());
+ CharacterDatabase.PExecute("UPDATE characters SET zone='%u' WHERE guid='%u'", zone, guidLow);
}
return zone;
@@ -6343,14 +6463,14 @@ void Player::UpdateArea(uint32 newArea)
if(area && (area->flags & AREA_FLAG_ARENA))
{
if(!isGameMaster())
- SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);
+ SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}
else
{
// remove ffa flag only if not ffapvp realm
// removal in sanctuaries and capitals is handled in zone update
- if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP) && !sWorld.IsFFAPvPRealm())
- RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);
+ if(HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && !sWorld.IsFFAPvPRealm())
+ RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}
UpdateAreaDependentAuras(newArea);
@@ -6412,13 +6532,13 @@ void Player::UpdateZone(uint32 newZone)
if(zone->flags & AREA_FLAG_SANCTUARY) // in sanctuary
{
- SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY);
+ SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
if(sWorld.IsFFAPvPRealm())
- RemoveFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP);
+ RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}
else
{
- RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY);
+ RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
}
if(zone->flags & AREA_FLAG_CAPITAL) // in capital city
@@ -6428,7 +6548,7 @@ void Player::UpdateZone(uint32 newZone)
InnEnter(time(0),GetMapId(),0,0,0);
if(sWorld.IsFFAPvPRealm())
- RemoveFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP);
+ RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}
else // anywhere else
{
@@ -6442,7 +6562,7 @@ void Player::UpdateZone(uint32 newZone)
SetRestType(REST_TYPE_NO);
if(sWorld.IsFFAPvPRealm())
- SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP);
+ SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}
}
else // not in tavern (leave city then)
@@ -6452,7 +6572,7 @@ void Player::UpdateZone(uint32 newZone)
// Set player to FFA PVP when not in rested environment.
if(sWorld.IsFFAPvPRealm())
- SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP);
+ SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}
}
}
@@ -6640,19 +6760,43 @@ void Player::_ApplyItemMods(Item *item, uint8 slot,bool apply)
sLog.outDebug("_ApplyItemMods complete.");
}
-void Player::_ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply)
+void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool apply)
{
if(slot >= INVENTORY_SLOT_BAG_END || !proto)
return;
for (int i = 0; i < 10; i++)
{
- float val = float (proto->ItemStat[i].ItemStatValue);
+ uint32 statType = 0;
+ int32 val = 0;
+
+ if(proto->ScalingStatDistribution)
+ {
+ if(ScalingStatDistributionEntry const *ssd = sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution))
+ {
+ statType = ssd->StatMod[i];
+
+ if(uint32 modifier = ssd->Modifier[i])
+ {
+ uint32 level = ((getLevel() > ssd->MaxLevel) ? ssd->MaxLevel : getLevel());
+ if(ScalingStatValuesEntry const *ssv = sScalingStatValuesStore.LookupEntry(level))
+ {
+ uint32 multiplier = ssv->Multiplier[proto->GetScalingStatValuesColumn()];
+ val = (multiplier * modifier) / 10000;
+ }
+ }
+ }
+ }
+ else
+ {
+ statType = proto->ItemStat[i].ItemStatType;
+ val = proto->ItemStat[i].ItemStatValue;
+ }
- if(val==0)
+ if(val == 0)
continue;
- switch (proto->ItemStat[i].ItemStatType)
+ switch (statType)
{
case ITEM_MOD_MANA:
HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply);
@@ -6770,6 +6914,31 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply)
case ITEM_MOD_EXPERTISE_RATING:
ApplyRatingMod(CR_EXPERTISE, int32(val), apply);
break;
+ case ITEM_MOD_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_RANGED_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_FERAL_ATTACK_POWER:
+ ApplyFeralAPBonus(int32(val), apply);
+ break;
+ case ITEM_MOD_SPELL_HEALING_DONE:
+ ApplySpellHealingBonus(int32(val), apply);
+ break;
+ case ITEM_MOD_SPELL_DAMAGE_DONE:
+ ApplySpellDamageBonus(int32(val), apply);
+ break;
+ case ITEM_MOD_MANA_REGENERATION:
+ ApplyManaRegenBonus(int32(val), apply);
+ break;
+ case ITEM_MOD_ARMOR_PENETRATION_RATING:
+ ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply);
+ break;
+ case ITEM_MOD_SPELL_POWER:
+ ApplySpellHealingBonus(int32(val), apply);
+ ApplySpellDamageBonus(int32(val), apply);
+ break;
}
}
@@ -6873,7 +7042,7 @@ void Player::_ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attac
if (item->IsFitToSpellRequirements(aura->GetSpellProto()))
{
- HandleBaseModValue(mod, FLAT_MOD, float (aura->GetModifierValue()), apply);
+ HandleBaseModValue(mod, FLAT_MOD, float (aura->GetModifier()->m_amount), apply);
}
}
@@ -6907,7 +7076,7 @@ void Player::_ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType att
if (item->IsFitToSpellRequirements(aura->GetSpellProto()))
{
- HandleStatModifier(unitMod, unitModType, float(aura->GetModifierValue()),apply);
+ HandleStatModifier(unitMod, unitModType, float(aura->GetModifier()->m_amount),apply);
}
}
@@ -7102,6 +7271,92 @@ void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attTy
}
}
+void Player::CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 cast_count, uint32 glyphIndex)
+{
+ ItemPrototype const* proto = item->GetProto();
+ // special learning case
+ if(proto->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN || proto->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN_PET)
+ {
+ uint32 learn_spell_id = proto->Spells[0].SpellId;
+ uint32 learning_spell_id = proto->Spells[1].SpellId;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(learn_spell_id);
+ if(!spellInfo)
+ {
+ sLog.outError("Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, learn_spell_id);
+ SendEquipError(EQUIP_ERR_NONE,item,NULL);
+ return;
+ }
+
+ Spell *spell = new Spell(this, spellInfo, false);
+ spell->m_CastItem = item;
+ spell->m_cast_count = cast_count; //set count of casts
+ spell->m_currentBasePoints[0] = learning_spell_id;
+ spell->prepare(&targets);
+ return;
+ }
+
+ // use triggered flag only for items with many spell casts and for not first cast
+ int count = 0;
+
+ // item spells casted at use
+ for(int i = 0; i < 5; ++i)
+ {
+ _Spell const& spellData = proto->Spells[i];
+
+ // no spell
+ if(!spellData.SpellId)
+ continue;
+
+ // wrong triggering type
+ if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE)
+ continue;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId);
+ if(!spellInfo)
+ {
+ sLog.outError("Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring",proto->ItemId, spellData.SpellId);
+ continue;
+ }
+
+ Spell *spell = new Spell(this, spellInfo, (count > 0));
+ spell->m_CastItem = item;
+ spell->m_cast_count = cast_count; // set count of casts
+ spell->m_glyphIndex = glyphIndex; // glyph index
+ spell->prepare(&targets);
+
+ ++count;
+ }
+
+ // Item enchantments spells casted at use
+ for(int e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot)
+ {
+ uint32 enchant_id = item->GetEnchantmentId(EnchantmentSlot(e_slot));
+ SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
+ if(!pEnchant) continue;
+ for (int s=0;s<3;s++)
+ {
+ if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_USE_SPELL)
+ continue;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(pEnchant->spellid[s]);
+ if (!spellInfo)
+ {
+ sLog.outError("Player::CastItemUseSpell Enchant %i, cast unknown spell %i", pEnchant->ID, pEnchant->spellid[s]);
+ continue;
+ }
+
+ Spell *spell = new Spell(this, spellInfo, (count > 0));
+ spell->m_CastItem = item;
+ spell->m_cast_count = cast_count; // set count of casts
+ spell->m_glyphIndex = glyphIndex; // glyph index
+ spell->prepare(&targets);
+
+ ++count;
+ }
+ }
+}
+
void Player::_RemoveAllItemMods()
{
sLog.outDebug("_RemoveAllItemMods start.");
@@ -7277,7 +7532,7 @@ void Player::RemovedInsignia(Player* looterPlr)
// We have to convert player corpse to bones, not to be able to resurrect there
// SpawnCorpseBones isn't handy, 'cos it saves player while he in BG
- Corpse *bones = ObjectAccessor::Instance().ConvertCorpseForPlayer(GetGUID());
+ Corpse *bones = ObjectAccessor::Instance().ConvertCorpseForPlayer(GetGUID(),true);
if (!bones)
return;
@@ -7385,6 +7640,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;
@@ -7580,8 +7846,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)
@@ -7658,46 +7924,46 @@ void Player::SendInitWorldStates(bool forceZone, uint32 forceZoneId)
case 1537:
case 2257:
case 2918:
- NumberOfFields = 6;
+ NumberOfFields = 8;
break;
case 139:
- NumberOfFields = 39;
+ NumberOfFields = 41;
break;
case 1377:
- NumberOfFields = 13;
+ NumberOfFields = 15;
break;
case 2597:
- NumberOfFields = 81;
+ NumberOfFields = 83;
break;
case 3277:
- NumberOfFields = 14;
+ NumberOfFields = 16;
break;
case 3358:
case 3820:
- NumberOfFields = 38;
+ NumberOfFields = 40;
break;
case 3483:
- NumberOfFields = 25;
+ NumberOfFields = 27;
break;
case 3518:
- NumberOfFields = 37;
+ NumberOfFields = 39;
break;
case 3519:
- NumberOfFields = 36;
+ NumberOfFields = 38;
break;
case 3521:
- NumberOfFields = 35;
+ NumberOfFields = 37;
break;
case 3698:
case 3702:
case 3968:
- NumberOfFields = 9;
+ NumberOfFields = 11;
break;
case 3703:
- NumberOfFields = 9;
+ NumberOfFields = 11;
break;
default:
- NumberOfFields = 10;
+ NumberOfFields = 12;
break;
}
@@ -7712,6 +7978,10 @@ void Player::SendInitWorldStates(bool forceZone, uint32 forceZoneId)
data << uint32(0x8d5) << uint32(0x0); // 4
data << uint32(0x8d4) << uint32(0x0); // 5
data << uint32(0x8d3) << uint32(0x0); // 6
+ // 7 1 - Arena season in progress, 0 - end of season
+ data << uint32(0xC77) << uint32(sWorld.getConfig(CONFIG_ARENA_SEASON_IN_PROGRESS));
+ // 8 Arena season id
+ data << uint32(0xF3D) << uint32(sWorld.getConfig(CONFIG_ARENA_SEASON_ID));
if(mapid == 530) // Outland
{
data << uint32(0x9bf) << uint32(0x0); // 7
@@ -8305,7 +8575,8 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap
// (this will be replace mainhand weapon at auto equip instead unwonted "you don't known dual wielding" ...
if(CanDualWield())
slots[1] = EQUIPMENT_SLOT_OFFHAND;
- };break;
+ break;
+ };
case INVTYPE_SHIELD:
slots[0] = EQUIPMENT_SLOT_OFFHAND;
break;
@@ -8314,6 +8585,8 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap
break;
case INVTYPE_2HWEAPON:
slots[0] = EQUIPMENT_SLOT_MAINHAND;
+ if (CanDualWield() && CanTitanGrip())
+ slots[1] = EQUIPMENT_SLOT_OFFHAND;
break;
case INVTYPE_TABARD:
slots[0] = EQUIPMENT_SLOT_TABARD;
@@ -8359,6 +8632,10 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap
if (pClass == CLASS_WARLOCK)
slots[0] = EQUIPMENT_SLOT_RANGED;
break;
+ case ITEM_SUBCLASS_ARMOR_SIGIL:
+ if (pClass == CLASS_DEATH_KNIGHT)
+ slots[0] = EQUIPMENT_SLOT_RANGED;
+ break;
}
break;
}
@@ -8384,14 +8661,8 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap
{
if ( slots[i] != NULL_SLOT && !GetItemByPos( INVENTORY_SLOT_BAG_0, slots[i] ) )
{
- // in case 2hand equipped weapon offhand slot empty but not free
- if(slots[i]==EQUIPMENT_SLOT_OFFHAND)
- {
- Item* mainItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND );
- if(!mainItem || mainItem->GetProto()->InventoryType != INVTYPE_2HWEAPON)
- return slots[i];
- }
- else
+ // in case 2hand equipped weapon (without titan grip) offhand slot empty but not free
+ if(slots[i]!=EQUIPMENT_SLOT_OFFHAND || !IsTwoHandUsed())
return slots[i];
}
}
@@ -8441,7 +8712,7 @@ uint8 Player::CanUnequipItems( uint32 item, uint32 count ) const
return EQUIP_ERR_OK;
}
}
- for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
+ for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++)
{
pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
if( pItem && pItem->GetEntry() == item )
@@ -8483,7 +8754,7 @@ uint32 Player::GetItemCount( uint32 item, bool inBankAlso, Item* skipItem ) cons
if( pItem && pItem != skipItem && pItem->GetEntry() == item )
count += pItem->GetCount();
}
- for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
+ for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++)
{
Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
if( pItem && pItem != skipItem && pItem->GetEntry() == item )
@@ -8543,7 +8814,7 @@ Item* Player::GetItemByGuid( uint64 guid ) const
if( pItem && pItem->GetGUID() == guid )
return pItem;
}
- for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
+ for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++)
{
Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
if( pItem && pItem->GetGUID() == guid )
@@ -8589,7 +8860,7 @@ Item* Player::GetItemByPos( uint16 pos ) const
Item* Player::GetItemByPos( uint8 bag, uint8 slot ) const
{
- if( bag == INVENTORY_SLOT_BAG_0 && ( slot < BANK_SLOT_BAG_END || slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END ) )
+ if( bag == INVENTORY_SLOT_BAG_0 && ( slot < BANK_SLOT_BAG_END || slot >= KEYRING_SLOT_START && slot < QUESTBAG_SLOT_END ) )
return m_items[slot];
else if(bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END
|| bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END )
@@ -8667,7 +8938,7 @@ bool Player::IsInventoryPos( uint8 bag, uint8 slot )
return true;
if( bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END )
return true;
- if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END ) )
+ if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= KEYRING_SLOT_START && slot < QUESTBAG_SLOT_END ) )
return true;
return false;
}
@@ -8788,7 +9059,7 @@ bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const
return true;
}
}
- for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
+ for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++)
{
Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
if( pItem && pItem->GetEntry() == item )
@@ -8886,12 +9157,12 @@ uint8 Player::_CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem,
}
// no maximum
- if(pProto->MaxCount == 0)
+ if(pProto->MaxCount <= 0)
return EQUIP_ERR_OK;
uint32 curcount = GetItemCount(pProto->ItemId,true,pItem);
- if( curcount + count > pProto->MaxCount )
+ if (curcount + count > uint32(pProto->MaxCount))
{
if(no_space_count)
*no_space_count = count +curcount - pProto->MaxCount;
@@ -8910,7 +9181,7 @@ bool Player::HasItemTotemCategory( uint32 TotemCategory ) const
if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory ))
return true;
}
- for(uint8 i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; ++i)
+ for(uint8 i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; ++i)
{
pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory ))
@@ -8950,6 +9221,18 @@ uint8 Player::_CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountV
if(slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_START+GetMaxKeyringSize() && !(pProto->BagFamily & BAG_FAMILY_MASK_KEYS))
return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ // vanitypet case (not use, vanity pets stored as spells)
+ if(slot >= VANITYPET_SLOT_START && slot < VANITYPET_SLOT_END)
+ return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+
+ // currencytoken case (disabled until proper implement)
+ if(slot >= CURRENCYTOKEN_SLOT_START && slot < CURRENCYTOKEN_SLOT_END && !(false /*pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS*/))
+ return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+
+ // guestbag case (disabled until proper implement)
+ if(slot >= QUESTBAG_SLOT_START && slot < QUESTBAG_SLOT_END && !(false /*pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS*/))
+ return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+
// prevent cheating
if(slot >= BUYBACK_SLOT_START && slot < BUYBACK_SLOT_END || slot >= PLAYER_SLOT_END)
return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
@@ -8969,7 +9252,7 @@ uint8 Player::_CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountV
}
// non empty stack with space
- need_space = pProto->Stackable;
+ need_space = pProto->GetMaxStackSize();
}
// non empty slot, check item type
else
@@ -8979,10 +9262,11 @@ uint8 Player::_CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountV
return EQUIP_ERR_ITEM_CANT_STACK;
// check free space
- if(pItem2->GetCount() >= pProto->Stackable)
+ if(pItem2->GetCount() >= pProto->GetMaxStackSize())
return EQUIP_ERR_ITEM_CANT_STACK;
- need_space = pProto->Stackable - pItem2->GetCount();
+ // free stack space or infinity
+ need_space = pProto->GetMaxStackSize() - pItem2->GetCount();
}
if(need_space > count)
@@ -9036,9 +9320,9 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy
if( pItem2 )
{
- if(pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->Stackable )
+ if(pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->GetMaxStackSize())
{
- uint32 need_space = pProto->Stackable - pItem2->GetCount();
+ uint32 need_space = pProto->GetMaxStackSize() - pItem2->GetCount();
if(need_space > count)
need_space = count;
@@ -9055,7 +9339,7 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy
}
else
{
- uint32 need_space = pProto->Stackable;
+ uint32 need_space = pProto->GetMaxStackSize();
if(need_space > count)
need_space = count;
@@ -9093,9 +9377,9 @@ uint8 Player::_CanStoreItem_InInventorySlots( uint8 slot_begin, uint8 slot_end,
if( pItem2 )
{
- if(pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->Stackable )
+ if(pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->GetMaxStackSize())
{
- uint32 need_space = pProto->Stackable - pItem2->GetCount();
+ uint32 need_space = pProto->GetMaxStackSize() - pItem2->GetCount();
if(need_space > count)
need_space = count;
ItemPosCount newPosition = ItemPosCount((INVENTORY_SLOT_BAG_0 << 8) | j, need_space);
@@ -9111,7 +9395,7 @@ uint8 Player::_CanStoreItem_InInventorySlots( uint8 slot_begin, uint8 slot_end,
}
else
{
- uint32 need_space = pProto->Stackable;
+ uint32 need_space = pProto->GetMaxStackSize();
if(need_space > count)
need_space = count;
@@ -9190,11 +9474,11 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3
if( bag != NULL_BAG )
{
// search stack in bag for merge to
- if( pProto->Stackable > 1 )
+ if( pProto->Stackable != 1 )
{
if( bag == INVENTORY_SLOT_BAG_0 ) // inventory
{
- res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,KEYRING_SLOT_END,dest,pProto,count,true,pItem,bag,slot);
+ res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,true,pItem,bag,slot);
if(res!=EQUIP_ERR_OK)
{
if(no_space_count)
@@ -9282,6 +9566,53 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3
}
}
+ // Vanity pet case skipped as not used
+
+ /* until proper implementation
+ else if(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS)
+ {
+ res = _CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START,CURRENCYTOKEN_SLOT_END,dest,pProto,count,false,pItem,bag,slot);
+ if(res!=EQUIP_ERR_OK)
+ {
+ if(no_space_count)
+ *no_space_count = count + no_similar_count;
+ return res;
+ }
+
+ if(count==0)
+ {
+ if(no_similar_count==0)
+ return EQUIP_ERR_OK;
+
+ if(no_space_count)
+ *no_space_count = count + no_similar_count;
+ return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ }
+ }
+ */
+ /* until proper implementation
+ else if(pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS)
+ {
+ res = _CanStoreItem_InInventorySlots(QUESTBAG_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,false,pItem,bag,slot);
+ if(res!=EQUIP_ERR_OK)
+ {
+ if(no_space_count)
+ *no_space_count = count + no_similar_count;
+ return res;
+ }
+
+ if(count==0)
+ {
+ if(no_similar_count==0)
+ return EQUIP_ERR_OK;
+
+ if(no_space_count)
+ *no_space_count = count + no_similar_count;
+ return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ }
+ }
+ */
+
res = _CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START,INVENTORY_SLOT_ITEM_END,dest,pProto,count,false,pItem,bag,slot);
if(res!=EQUIP_ERR_OK)
{
@@ -9328,9 +9659,9 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3
// not specific bag or have space for partly store only in specific bag
// search stack for merge to
- if( pProto->Stackable > 1 )
+ if( pProto->Stackable != 1 )
{
- res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,KEYRING_SLOT_END,dest,pProto,count,true,pItem,bag,slot);
+ res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,true,pItem,bag,slot);
if(res!=EQUIP_ERR_OK)
{
if(no_space_count)
@@ -9429,6 +9760,53 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3
}
}
+ // Vanity pet case skipped as not used
+
+ /* until proper implementation
+ else if(false pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS)
+ {
+ res = _CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START,CURRENCYTOKEN_SLOT_END,dest,pProto,count,false,pItem,bag,slot);
+ if(res!=EQUIP_ERR_OK)
+ {
+ if(no_space_count)
+ *no_space_count = count + no_similar_count;
+ return res;
+ }
+
+ if(count==0)
+ {
+ if(no_similar_count==0)
+ return EQUIP_ERR_OK;
+
+ if(no_space_count)
+ *no_space_count = count + no_similar_count;
+ return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ }
+ }
+ */
+ /* until proper implementation
+ else if(false pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS)
+ {
+ res = _CanStoreItem_InInventorySlots(QUESTBAG_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,false,pItem,bag,slot);
+ if(res!=EQUIP_ERR_OK)
+ {
+ if(no_space_count)
+ *no_space_count = count + no_similar_count;
+ return res;
+ }
+
+ if(count==0)
+ {
+ if(no_similar_count==0)
+ return EQUIP_ERR_OK;
+
+ if(no_space_count)
+ *no_space_count = count + no_similar_count;
+ return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ }
+ }
+ */
+
for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
res = _CanStoreItem_InBag(i,dest,pProto,count,false,false,pItem,bag,slot);
@@ -9498,10 +9876,14 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const
int inv_slot_items[INVENTORY_SLOT_ITEM_END-INVENTORY_SLOT_ITEM_START];
int inv_bags[INVENTORY_SLOT_BAG_END-INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE];
int inv_keys[KEYRING_SLOT_END-KEYRING_SLOT_START];
+ int inv_tokens[CURRENCYTOKEN_SLOT_END-CURRENCYTOKEN_SLOT_START];
+ int inv_quests[QUESTBAG_SLOT_END-QUESTBAG_SLOT_START];
memset(inv_slot_items,0,sizeof(int)*(INVENTORY_SLOT_ITEM_END-INVENTORY_SLOT_ITEM_START));
memset(inv_bags,0,sizeof(int)*(INVENTORY_SLOT_BAG_END-INVENTORY_SLOT_BAG_START)*MAX_BAG_SIZE);
memset(inv_keys,0,sizeof(int)*(KEYRING_SLOT_END-KEYRING_SLOT_START));
+ memset(inv_tokens,0,sizeof(int)*(CURRENCYTOKEN_SLOT_END-CURRENCYTOKEN_SLOT_START));
+ memset(inv_quests,0,sizeof(int)*(QUESTBAG_SLOT_END-QUESTBAG_SLOT_START));
for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
@@ -9523,6 +9905,28 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const
}
}
+ // Vanity pet case skipped as not used
+
+ for(int i = CURRENCYTOKEN_SLOT_START; i < CURRENCYTOKEN_SLOT_END; i++)
+ {
+ pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
+
+ if (pItem2 && !pItem2->IsInTrade())
+ {
+ inv_tokens[i-CURRENCYTOKEN_SLOT_START] = pItem2->GetCount();
+ }
+ }
+
+ for(int i = QUESTBAG_SLOT_START; i < QUESTBAG_SLOT_END; i++)
+ {
+ pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
+
+ if (pItem2 && !pItem2->IsInTrade())
+ {
+ inv_quests[i-QUESTBAG_SLOT_START] = pItem2->GetCount();
+ }
+ }
+
for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
@@ -9566,14 +9970,14 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const
return res;
// search stack for merge to
- if( pProto->Stackable > 1 )
+ if( pProto->Stackable != 1 )
{
bool b_found = false;
for(int t = KEYRING_SLOT_START; t < KEYRING_SLOT_END; t++)
{
pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t );
- if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_keys[t-KEYRING_SLOT_START] + pItem->GetCount() <= pProto->Stackable )
+ if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_keys[t-KEYRING_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize())
{
inv_keys[t-KEYRING_SLOT_START] += pItem->GetCount();
b_found = true;
@@ -9582,10 +9986,36 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const
}
if (b_found) continue;
+ // Vanity pet case skipped as not used
+
+ for(int t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; t++)
+ {
+ pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t );
+ if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_tokens[t-CURRENCYTOKEN_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize())
+ {
+ inv_tokens[t-CURRENCYTOKEN_SLOT_START] += pItem->GetCount();
+ b_found = true;
+ break;
+ }
+ }
+ if (b_found) continue;
+
+ for(int t = QUESTBAG_SLOT_START; t < QUESTBAG_SLOT_END; t++)
+ {
+ pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t );
+ if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_quests[t-QUESTBAG_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize())
+ {
+ inv_quests[t-QUESTBAG_SLOT_START] += pItem->GetCount();
+ b_found = true;
+ break;
+ }
+ }
+ if (b_found) continue;
+
for(int t = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; t++)
{
pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t );
- if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_slot_items[t-INVENTORY_SLOT_ITEM_START] + pItem->GetCount() <= pProto->Stackable )
+ if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_slot_items[t-INVENTORY_SLOT_ITEM_START] + pItem->GetCount() <= pProto->GetMaxStackSize())
{
inv_slot_items[t-INVENTORY_SLOT_ITEM_START] += pItem->GetCount();
b_found = true;
@@ -9602,7 +10032,7 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const
for(uint32 j = 0; j < pBag->GetBagSize(); j++)
{
pItem2 = GetItemByPos( t, j );
- if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->Stackable )
+ if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->GetMaxStackSize())
{
inv_bags[t-INVENTORY_SLOT_BAG_START][j] += pItem->GetCount();
b_found = true;
@@ -9634,6 +10064,41 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const
if (b_found) continue;
+ // Vanity pet case skipped as not used
+
+ /* until proper implementation
+ if(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS)
+ {
+ for(uint32 t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t)
+ {
+ if( inv_tokens[t-CURRENCYTOKEN_SLOT_START] == 0 )
+ {
+ inv_tokens[t-CURRENCYTOKEN_SLOT_START] = 1;
+ b_found = true;
+ break;
+ }
+ }
+ }
+
+ if (b_found) continue;
+ */
+ /* until proper implementation
+ if(pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS)
+ {
+ for(uint32 t = QUESTBAG_SLOT_START; t < QUESTBAG_SLOT_END; ++t)
+ {
+ if( inv_quests[t-QUESTBAG_SLOT_START] == 0 )
+ {
+ inv_quests[t-QUESTBAG_SLOT_START] = 1;
+ b_found = true;
+ break;
+ }
+ }
+ }
+
+ if (b_found) continue;
+ */
+
for(int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; t++)
{
pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t );
@@ -9819,33 +10284,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;
@@ -9963,7 +10437,7 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p
}
// search stack in bag for merge to
- if( pProto->Stackable > 1 )
+ if( pProto->Stackable != 1 )
{
if( bag == INVENTORY_SLOT_BAG_0 )
{
@@ -10015,7 +10489,7 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p
// not specific bag or have space for partly store only in specific bag
// search stack for merge to
- if( pProto->Stackable > 1 )
+ if( pProto->Stackable != 1 )
{
// in slots
res = _CanStoreItem_InInventorySlots(BANK_SLOT_ITEM_START,BANK_SLOT_ITEM_END,dest,pProto,count,true,pItem,bag,slot);
@@ -10765,7 +11239,7 @@ void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool uneq
}
}
}
- for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
+ for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++)
{
pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
if( pItem && pItem->GetEntry() == item )
@@ -10868,7 +11342,7 @@ void Player::DestroyZoneLimitedItem( bool update, uint32 new_zone )
if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) )
DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
}
- for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
+ for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++)
{
Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) )
@@ -11203,7 +11677,7 @@ void Player::SwapItem( uint16 src, uint16 dst )
// can be merge/fill
if(msg == EQUIP_ERR_OK)
{
- if( pSrcItem->GetCount() + pDstItem->GetCount() <= pSrcItem->GetProto()->Stackable )
+ if( pSrcItem->GetCount() + pDstItem->GetCount() <= pSrcItem->GetProto()->GetMaxStackSize())
{
RemoveItem(srcbag, srcslot, true);
@@ -11219,8 +11693,8 @@ void Player::SwapItem( uint16 src, uint16 dst )
}
else
{
- pSrcItem->SetCount( pSrcItem->GetCount() + pDstItem->GetCount() - pSrcItem->GetProto()->Stackable );
- pDstItem->SetCount( pSrcItem->GetProto()->Stackable );
+ pSrcItem->SetCount( pSrcItem->GetCount() + pDstItem->GetCount() - pSrcItem->GetProto()->GetMaxStackSize());
+ pDstItem->SetCount( pSrcItem->GetProto()->GetMaxStackSize());
pSrcItem->SetState(ITEM_CHANGED, this);
pDstItem->SetState(ITEM_CHANGED, this);
if( IsInWorld() )
@@ -11865,6 +12339,39 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a
((Player*)this)->ApplyRatingMod(CR_EXPERTISE, enchant_amount, apply);
sLog.outDebug("+ %u EXPERTISE", enchant_amount);
break;
+ case ITEM_MOD_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply);
+ sLog.outDebug("+ %u ATTACK_POWER", enchant_amount);
+ break;
+ case ITEM_MOD_RANGED_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
+ sLog.outDebug("+ %u RANGED_ATTACK_POWER", enchant_amount);
+ break;
+ case ITEM_MOD_FERAL_ATTACK_POWER:
+ ((Player*)this)->ApplyFeralAPBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u FERAL_ATTACK_POWER", enchant_amount);
+ break;
+ case ITEM_MOD_SPELL_HEALING_DONE:
+ ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u SPELL_HEALING_DONE", enchant_amount);
+ break;
+ case ITEM_MOD_SPELL_DAMAGE_DONE:
+ ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u SPELL_DAMAGE_DONE", enchant_amount);
+ break;
+ case ITEM_MOD_MANA_REGENERATION:
+ ((Player*)this)->ApplyManaRegenBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u MANA_REGENERATION", enchant_amount);
+ break;
+ case ITEM_MOD_ARMOR_PENETRATION_RATING:
+ ((Player*)this)->ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply);
+ sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount);
+ break;
+ case ITEM_MOD_SPELL_POWER:
+ ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply);
+ ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u SPELL_POWER", enchant_amount);
+ break;
default:
break;
}
@@ -11888,8 +12395,11 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a
}
break;
}
+ case ITEM_ENCHANTMENT_TYPE_USE_SPELL:
+ // processed in Player::CastItemUseSpell
+ break;
default:
- sLog.outError("Unknown item enchantment display type: %d",enchant_display_type);
+ sLog.outError("Unknown item enchantment (id = %d) display type: %d", enchant_id, enchant_display_type);
break;
} /*switch(enchant_display_type)*/
} /*for*/
@@ -12523,6 +13033,12 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
SetTitle(titleEntry);
}
+ if(pQuest->GetBonusTalents())
+ {
+ m_questRewardTalentCount+=pQuest->GetBonusTalents();
+ InitTalentForLevel();
+ }
+
// Send reward mail
if(pQuest->GetRewMailTemplateId())
{
@@ -12587,7 +13103,10 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
}
if(pQuest->IsDaily())
+ {
SetDailyQuestStatus(quest_id);
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, 1);
+ }
if ( !pQuest->IsRepeatable() )
SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE);
@@ -12600,6 +13119,8 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
SendQuestReward( pQuest, XP, questGiver );
if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED;
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST);
}
void Player::FailQuest( uint32 quest_id )
@@ -13225,6 +13746,7 @@ void Player::ItemAddedQuestCheck( uint32 entry, uint32 count )
}
}
UpdateForQuestsGO();
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, entry);
}
void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count )
@@ -13271,6 +13793,7 @@ void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count )
void Player::KilledMonster( uint32 entry, uint64 guid )
{
uint32 addkillcount = 1;
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, entry, addkillcount);
for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ )
{
uint32 questid = GetQuestSlotQuestId(i);
@@ -13549,13 +14072,12 @@ void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGive
uint32 questid = pQuest->GetQuestId();
sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questid );
gameeventmgr.HandleQuestComplete(questid);
- WorldPacket data( SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4+4+pQuest->GetRewItemsCount()*8) );
- data << questid;
- data << uint32(0x03);
+ WorldPacket data( SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4) );
+ data << uint32(questid);
if ( getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) )
{
- data << XP;
+ data << uint32(XP);
data << uint32(pQuest->GetRewOrReqMoney());
}
else
@@ -13563,16 +14085,9 @@ void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGive
data << uint32(0);
data << uint32(pQuest->GetRewOrReqMoney() + int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY)));
}
- data << uint32(0); // new 2.3.0, HonorPoints?
- data << uint32( pQuest->GetRewItemsCount() ); // max is 5
- for (uint32 i = 0; i < pQuest->GetRewItemsCount(); ++i)
- {
- if ( pQuest->RewItemId[i] > 0 )
- data << pQuest->RewItemId[i] << pQuest->RewItemCount[i];
- else
- data << uint32(0) << uint32(0);
- }
+ data << uint32(10*Trinity::Honor::hk_honor_at_level(getLevel(), pQuest->GetRewHonorableKills()));
+ data << uint32(pQuest->GetBonusTalents()); // bonus talents
GetSession()->SendPacket( &data );
if (pQuest->GetQuestCompleteScript() != 0)
@@ -13583,8 +14098,9 @@ void Player::SendQuestFailed( uint32 quest_id )
{
if( quest_id )
{
- WorldPacket data( SMSG_QUESTGIVER_QUEST_FAILED, 4 );
+ WorldPacket data( SMSG_QUESTGIVER_QUEST_FAILED, 4+4 );
data << quest_id;
+ data << uint32(0); // failed reason (4 for inventory is full)
GetSession()->SendPacket( &data );
sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_FAILED");
}
@@ -13623,10 +14139,10 @@ void Player::SendPushToPartyResponse( Player *pPlayer, uint32 msg )
void Player::SendQuestUpdateAddItem( Quest const* pQuest, uint32 item_idx, uint32 count )
{
- WorldPacket data( SMSG_QUESTUPDATE_ADD_ITEM, (4+4) );
+ WorldPacket data( SMSG_QUESTUPDATE_ADD_ITEM, 0 );
sLog.outDebug( "WORLD: Sent SMSG_QUESTUPDATE_ADD_ITEM" );
- data << pQuest->ReqItemId[item_idx];
- data << count;
+ //data << pQuest->ReqItemId[item_idx];
+ //data << count;
GetSession()->SendPacket( &data );
}
@@ -13672,7 +14188,7 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid )
if(!LoadValues( fields[1].GetString()))
{
- sLog.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded.",GUID_LOPART(guid));
+ sLog.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded for character list.",GUID_LOPART(guid));
if(delete_result) delete result;
return false;
}
@@ -13742,7 +14258,7 @@ void Player::_LoadArenaTeamInfo(QueryResult *result)
ArenaTeam* aTeam = objmgr.GetArenaTeamById(arenateamid);
if(!aTeam)
{
- sLog.outError("FATAL: couldn't load arenateam %u", arenateamid);
+ sLog.outError("Player::_LoadArenaTeamInfo: couldn't load arenateam %u, week %u, season %u, rating %u", arenateamid, played_week, played_season, personal_rating);
continue;
}
uint8 arenaSlot = aTeam->GetSlot();
@@ -13930,6 +14446,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
//Other way is to saves m_team into characters table.
setFactionForRace(m_race);
SetCharm(0);
+ SetMover(this);
m_class = fields[5].GetUInt8();
@@ -13945,7 +14462,6 @@ 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
@@ -14034,6 +14550,16 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
// getmap calls won't create new maps
SetInstanceId(map->GetInstanceId());
+ // if the player is in an instance and it has been reset in the meantime teleport him to the entrance
+ if(GetInstanceId() && !sInstanceSaveManager.GetInstanceSave(GetInstanceId()))
+ {
+ AreaTrigger const* at = objmgr.GetMapEntranceTrigger(GetMapId());
+ if(at)
+ Relocate(at->target_X, at->target_Y, at->target_Z, at->target_Orientation);
+ else
+ sLog.outError("Player %s(GUID: %u) logged in to a reset instance (map: %u) and there is no aretrigger leading to this map. Thus he can't be ported back to the entrance. This _might_ be an exploit attempt.", GetName(), GetGUIDLow(), GetMapId());
+ }
+
SaveRecallPosition();
if (transGUID != 0)
@@ -14144,10 +14670,10 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
uint32 extraflags = fields[25].GetUInt32();
m_stableSlots = fields[26].GetUInt32();
- if(m_stableSlots > 2)
+ if(m_stableSlots > 4)
{
- sLog.outError("Player can have not more 2 stable slots, but have in DB %u",uint32(m_stableSlots));
- m_stableSlots = 2;
+ sLog.outError("Player can have not more 4 stable slots, but have in DB %u",uint32(m_stableSlots));
+ m_stableSlots = 4;
}
m_atLoginFlags = fields[27].GetUInt32();
@@ -14171,34 +14697,18 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
// clear charm/summon related fields
SetCharm(NULL);
+ SetMover(NULL);
SetPet(NULL);
- SetCharmerGUID(NULL);
- SetOwnerGUID(NULL);
- SetCreatorGUID(NULL);
+ SetCharmerGUID(0);
+ SetOwnerGUID(0);
+ SetCreatorGUID(0);
// reset some aura modifiers before aura apply
- SetFarSight(NULL);
+ SetFarSightGUID(0);
SetUInt32Value(PLAYER_TRACK_CREATURES, 0 );
SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 );
- // reset skill modifiers and set correct unlearn flags
- for (uint32 i = 0; i < PLAYER_MAX_SKILLS; i++)
- {
- SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
-
- // set correct unlearn bit
- uint32 id = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
- if(!id) continue;
-
- SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id);
- if(!pSkill) continue;
-
- // enable unlearn button for primary professions only
- if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION)
- SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,1));
- else
- SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0));
- }
+ _LoadSkills();
// make sure the unit is considered out of combat for proper loading
ClearInCombat();
@@ -14216,6 +14726,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
// reset stats before loading any modifiers
InitStatsForLevel();
InitTaxiNodesForLevel();
+ InitGlyphsForLevel();
+ InitRunes();
// apply original stats mods before spell loading or item equipment that call before equip _RemoveStatsMods()
@@ -14223,6 +14735,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
//_LoadMail();
_LoadAuras(holder->GetResult(PLAYER_LOGIN_QUERY_LOADAURAS), time_diff);
+ _LoadGlyphAuras();
// add ghost flag (must be after aura load: PLAYER_FLAGS_GHOST set in aura)
if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) )
@@ -14230,14 +14743,14 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
_LoadSpells(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSPELLS));
- // after spell load
- InitTalentForLevel();
- learnSkillRewardedSpells();
-
// after spell load, learn rewarded spell if need also
_LoadQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS));
_LoadDailyQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS));
+ // after spell and quest load
+ InitTalentForLevel();
+ learnDefaultSpells();
+
_LoadTutorials(holder->GetResult(PLAYER_LOGIN_QUERY_LOADTUTORIALS));
// must be before inventory (some items required reputation check)
@@ -14267,7 +14780,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
}
// Not finish taxi flight path
- if(!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes))
+ if(!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes,GetTeam()))
{
// problems with taxi path loading
TaxiNodesEntry const* nodeEntry = NULL;
@@ -14303,6 +14816,9 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
// flight will started later
}
+ // has to be called after last Relocate() in Player::LoadFromDB
+ SetFallInformation(0, GetPositionZ());
+
_LoadSpellCooldowns(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS));
// Spell code allow apply any auras to dead character in load time in aura/spell/item loading
@@ -14336,6 +14852,28 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
break;
}
+ switch(sWorld.getConfig(CONFIG_GM_VISIBLE_STATE))
+ {
+ default:
+ case 0: SetGMVisible(false); break; // invisible
+ case 1: break; // visible
+ case 2: // save state
+ if(extraflags & PLAYER_EXTRA_GM_INVISIBLE)
+ SetGMVisible(false);
+ break;
+ }
+
+ /*switch(sWorld.getConfig(CONFIG_GM_ACCEPT_TICKETS))
+ {
+ default:
+ case 0: break; // disable
+ case 1: SetAcceptTicket(true); break; // enable
+ case 2: // save state
+ if(extraflags & PLAYER_EXTRA_GM_ACCEPT_TICKETS)
+ SetAcceptTicket(true);
+ break;
+ }*/
+
switch(sWorld.getConfig(CONFIG_GM_CHAT))
{
default:
@@ -14361,6 +14899,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
_LoadDeclinedNames(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES));
+ m_achievementMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS), holder->GetResult(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS));
+ m_achievementMgr.CheckAllAchievementCriteria();
return true;
}
@@ -14414,10 +14954,6 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
for (int i = 0; i < TOTAL_AURAS; i++)
m_modAuras[i].clear();
- // all aura related fields
- for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i)
- SetUInt32Value(i, 0);
-
//QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow());
if(result)
@@ -14463,7 +14999,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
remaincharges = spellproto->procCharges;
}
else
- remaincharges = -1;
+ remaincharges = 0;
//do not load single target auras (unless they were cast by the player)
if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto))
@@ -14488,6 +15024,36 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true);
}
+void Player::_LoadGlyphAuras()
+{
+ for (uint8 i = 0; i <= MAX_GLYPH_SLOT_INDEX; ++i)
+ {
+ if (uint32 glyph = GetGlyph(i))
+ {
+ if (GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
+ {
+ if (GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(GetGlyphSlot(i)))
+ {
+ if(gp->TypeFlags == gs->TypeFlags)
+ {
+ CastSpell(this, gp->SpellId, true);
+ continue;
+ }
+ else
+ sLog.outError("Player %s has glyph with typeflags %u in slot with typeflags %u, removing.", m_name.c_str(), gp->TypeFlags, gs->TypeFlags);
+ }
+ else
+ sLog.outError("Player %s has not existing glyph slot entry %u on index %u", m_name.c_str(), GetGlyphSlot(i), i);
+ }
+ else
+ sLog.outError("Player %s has not existing glyph entry %u on index %u", m_name.c_str(), glyph, i);
+
+ // On any error remove glyph
+ SetGlyph(i, 0);
+ }
+ }
+}
+
void Player::LoadCorpse()
{
if( isAlive() )
@@ -14663,15 +15229,16 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff)
// load mailed item which should receive current player
void Player::_LoadMailedItems(Mail *mail)
{
- QueryResult* result = CharacterDatabase.PQuery("SELECT item_guid, item_template FROM mail_items WHERE mail_id='%u'", mail->messageID);
+ // data needs to be at first place for Item::LoadFromDB
+ QueryResult* result = CharacterDatabase.PQuery("SELECT data, item_guid, item_template FROM mail_items JOIN item_instance ON item_guid = guid WHERE mail_id='%u'", mail->messageID);
if(!result)
return;
do
{
Field *fields = result->Fetch();
- uint32 item_guid_low = fields[0].GetUInt32();
- uint32 item_template = fields[1].GetUInt32();
+ uint32 item_guid_low = fields[1].GetUInt32();
+ uint32 item_template = fields[2].GetUInt32();
mail->AddItem(item_guid_low, item_template);
@@ -14687,7 +15254,7 @@ void Player::_LoadMailedItems(Mail *mail)
Item *item = NewItemOrBag(proto);
- if(!item->LoadFromDB(item_guid_low, 0))
+ if(!item->LoadFromDB(item_guid_low, 0, result))
{
sLog.outError( "Player::_LoadMailedItems - Item in mail (%u) doesn't exist !!!! - item guid: %u, deleted from mail", mail->messageID, item_guid_low);
CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low);
@@ -14868,6 +15435,9 @@ void Player::_LoadQuestStatus(QueryResult *result)
if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId()))
SetTitle(titleEntry);
}
+
+ if(pQuest->GetBonusTalents())
+ m_questRewardTalentCount+=pQuest->GetBonusTalents();
}
sLog.outDebug("Quest status is {%u} for quest {%u} for player (GUID: %u)", questStatusData.m_status, quest_id, GetGUIDLow());
@@ -14987,7 +15557,7 @@ void Player::_LoadSpells(QueryResult *result)
delete itr->second;
m_spells.clear();
- //QueryResult *result = CharacterDatabase.PQuery("SELECT spell,slot,active FROM character_spell WHERE guid = '%u'",GetGUIDLow());
+ //QueryResult *result = CharacterDatabase.PQuery("SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'",GetGUIDLow());
if(result)
{
@@ -14995,7 +15565,7 @@ void Player::_LoadSpells(QueryResult *result)
{
Field *fields = result->Fetch();
- addSpell(fields[0].GetUInt16(), fields[2].GetBool(), false, true, fields[1].GetUInt16(), fields[3].GetBool());
+ addSpell(fields[0].GetUInt16(), fields[1].GetBool(), false, false, fields[2].GetBool());
}
while( result->NextRow() );
@@ -15144,29 +15714,29 @@ InstancePlayerBind* Player::BindToInstance(InstanceSave *save, bool permanent, b
void Player::SendRaidInfo()
{
+ uint32 counter = 0;
+
WorldPacket data(SMSG_RAID_INSTANCE_INFO, 4);
- uint32 counter = 0, i;
- for(i = 0; i < TOTAL_DIFFICULTIES; i++)
- for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
- if(itr->second.perm) counter++;
+ size_t p_counter = data.wpos();
+ data << uint32(counter); // placeholder
- data << counter;
- for(i = 0; i < TOTAL_DIFFICULTIES; i++)
+ for(int i = 0; i < TOTAL_DIFFICULTIES; ++i)
{
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
{
if(itr->second.perm)
{
InstanceSave *save = itr->second.save;
- data << (save->GetMapId());
- data << (uint32)(save->GetResetTime() - time(NULL));
- data << save->GetInstanceId();
- data << uint32(counter);
- counter--;
+ data << uint32(save->GetMapId());
+ data << uint32(save->GetResetTime() - time(NULL));
+ data << uint32(save->GetInstanceId());
+ data << uint32(save->GetDifficulty());
+ ++counter;
}
}
}
+ data.put<uint32>(p_counter,counter);
GetSession()->SendPacket(&data);
}
@@ -15326,10 +15896,10 @@ void Player::SaveToDB()
uint32 tmp_displayid = GetDisplayId();
// Set player sit state to standing on save, also stealth and shifted form
- SetByteValue(UNIT_FIELD_BYTES_1, 0, 0); // stand state
+ SetStandState(UNIT_STAND_STATE_STAND); // stand state
+ RemoveStandFlags(UNIT_STAND_FLAGS_ALL); // stand flags?
SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift
- SetByteValue(UNIT_FIELD_BYTES_1, 3, 0); // stand flags?
- RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
SetDisplayId(GetNativeDisplayId());
bool inworld = IsInWorld();
@@ -15388,12 +15958,11 @@ void Player::SaveToDB()
ss << GetUInt32Value(i) << " ";
}
- ss << "', '";
+ ss << "', ";
- for( i = 0; i < 8; i++ )
- ss << m_taxi.GetTaximask(i) << " ";
+ ss << m_taxi; // string with TaxiMaskSize numbers
- ss << "', ";
+ ss << ", ";
ss << (inworld ? 1 : 0);
ss << ", ";
@@ -15480,7 +16049,7 @@ void Player::SaveToDB()
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
//to prevent access to DB we should cache some data, which is used very often
- CachePlayerInfoMap::iterator _iter = objmgr.m_mPlayerInfoMap.find(GetGUIDLow());
+ /*CachePlayerInfoMap::iterator _iter = objmgr.m_mPlayerInfoMap.find(GetGUIDLow());
if(_iter != objmgr.m_mPlayerInfoMap.end())//skip new players
{
_iter->second->unLevel = getLevel();
@@ -15494,7 +16063,8 @@ void Player::SaveToDB()
_iter->second->unArenaInfoId0 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (0 * 6));
_iter->second->unArenaInfoId1 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (1 * 6));
_iter->second->unArenaInfoId2 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (2 * 6));
- }
+ }*/
+ m_achievementMgr.SaveToDB();
}
// fast save function for item/money cheating preventing - save only inventory and money state
@@ -15572,7 +16142,7 @@ void Player::_SaveAuras()
{
CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) "
"VALUES ('%u', '" I64FMTD "' ,'%u', '%u', '%u', '%d', '%d', '%d', '%d')",
- GetGUIDLow(), itr2->second->GetCasterGUID(), (uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), (uint32)itr2->second->GetStackAmount(), itr2->second->GetModifier()->m_amount,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->m_procCharges));
+ GetGUIDLow(), itr2->second->GetCasterGUID(), (uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), (uint32)itr2->second->GetStackAmount(), itr2->second->GetModifier()->m_amount ,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->GetAuraCharges()));
}
}
}
@@ -15773,18 +16343,26 @@ void Player::_SaveReputation()
void Player::_SaveSpells()
{
- for (PlayerSpellMap::const_iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next)
+ for (PlayerSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end();)
{
- ++next;
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED)
CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u' and spell = '%u'", GetGUIDLow(), itr->first);
- if (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED)
- CharacterDatabase.PExecute("INSERT INTO character_spell (guid,spell,slot,active,disabled) VALUES ('%u', '%u', '%u','%u','%u')", GetGUIDLow(), itr->first, itr->second->slotId,itr->second->active ? 1 : 0,itr->second->disabled ? 1 : 0);
+
+ // add only changed/new not dependent spells
+ if (!itr->second->dependent && (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED))
+ CharacterDatabase.PExecute("INSERT INTO character_spell (guid,spell,active,disabled) VALUES ('%u', '%u', '%u', '%u')", GetGUIDLow(), itr->first, itr->second->active ? 1 : 0,itr->second->disabled ? 1 : 0);
if (itr->second->state == PLAYERSPELL_REMOVED)
- _removeSpell(itr->first);
+ {
+ delete itr->second;
+ m_spells.erase(itr++);
+ }
else
+ {
itr->second->state = PLAYERSPELL_UNCHANGED;
+ ++itr;
+ }
+
}
}
@@ -15956,6 +16534,42 @@ void Player::SetFloatValueInDB(uint16 index, float value, uint64 guid)
Player::SetUInt32ValueInDB(index, temp, guid);
}
+void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair)
+{
+ Tokens tokens;
+ if(!LoadValuesArrayFromDB(tokens, guid))
+ return;
+
+ uint32 unit_bytes0 = GetUInt32ValueFromArray(tokens, UNIT_FIELD_BYTES_0);
+ uint8 race = unit_bytes0 & 0xFF;
+ uint8 class_ = (unit_bytes0 >> 8) & 0xFF;
+
+ PlayerInfo const* info = objmgr.GetPlayerInfo(race, class_);
+ if(!info)
+ return;
+
+ unit_bytes0 &= ~(0xFF << 16);
+ unit_bytes0 |= (gender << 16);
+ SetUInt32ValueInArray(tokens, UNIT_FIELD_BYTES_0, unit_bytes0);
+
+ SetUInt32ValueInArray(tokens, UNIT_FIELD_DISPLAYID, gender ? info->displayId_f : info->displayId_m);
+ SetUInt32ValueInArray(tokens, UNIT_FIELD_NATIVEDISPLAYID, gender ? info->displayId_f : info->displayId_m);
+
+ SetUInt32ValueInArray(tokens, PLAYER_BYTES, (skin | (face << 8) | (hairStyle << 16) | (hairColor << 24)));
+
+ uint32 player_bytes2 = GetUInt32ValueFromArray(tokens, PLAYER_BYTES_2);
+ player_bytes2 &= ~0xFF;
+ player_bytes2 |= facialHair;
+ SetUInt32ValueInArray(tokens, PLAYER_BYTES_2, player_bytes2);
+
+ uint32 player_bytes3 = GetUInt32ValueFromArray(tokens, PLAYER_BYTES_3);
+ player_bytes3 &= ~0xFF;
+ player_bytes3 |= gender;
+ SetUInt32ValueInArray(tokens, PLAYER_BYTES_3, player_bytes3);
+
+ SaveValuesArrayInDB(tokens, guid);
+}
+
void Player::SendAttackSwingNotStanding()
{
WorldPacket data(SMSG_ATTACKSWING_NOTSTANDING, 0);
@@ -15988,7 +16602,8 @@ void Player::SendAttackSwingBadFacingAttack()
void Player::SendAutoRepeatCancel()
{
- WorldPacket data(SMSG_CANCEL_AUTO_REPEAT, 0);
+ WorldPacket data(SMSG_CANCEL_AUTO_REPEAT, GetPackGUID().size());
+ data.append(GetPackGUID()); // may be it's target guid
GetSession()->SendPacket( &data );
}
@@ -16217,6 +16832,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
{
WorldPacket data(SMSG_PET_SPELLS, 8);
data << uint64(0);
+ data << uint32(0);
GetSession()->SendPacket(&data);
if(GetGroup())
@@ -16348,65 +16964,79 @@ void Player::PetSpellInitialize()
{
Pet* pet = GetPet();
- if(pet)
- {
- uint8 addlist = 0;
+ if(!pet)
+ return;
- sLog.outDebug("Pet Spells Groups");
+ sLog.outDebug("Pet Spells Groups");
- CreatureInfo const *cinfo = pet->GetCreatureInfo();
+ CharmInfo *charmInfo = pet->GetCharmInfo();
- if(pet->isControlled() && (pet->getPetType() == HUNTER_PET || cinfo && cinfo->type == CREATURE_TYPE_DEMON && getClass() == CLASS_WARLOCK))
- {
- for(PetSpellMap::iterator itr = pet->m_spells.begin();itr != pet->m_spells.end();++itr)
- {
- if(itr->second->state == PETSPELL_REMOVED)
- continue;
- ++addlist;
- }
- }
+ WorldPacket data(SMSG_PET_SPELLS, 8+4+4+4+10*4);
+ data << uint64(pet->GetGUID());
+ data << uint32(pet->GetCreatureInfo()->family); // creature family (required for pet talents)
+ data << uint32(0);
+ data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0);
- // first line + actionbar + spellcount + spells + last adds
- WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);
+ // action bar loop
+ for(uint32 i = 0; i < 10; i++)
+ {
+ data << uint32(charmInfo->GetActionBarEntry(i)->Raw);
+ }
- CharmInfo *charmInfo = pet->GetCharmInfo();
+ size_t spellsCountPos = data.wpos();
- //16
- data << (uint64)pet->GetGUID() << uint32(0x00000000) << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0);
+ // spells count
+ uint8 addlist = 0;
+ data << uint8(addlist); // placeholder
- for(uint32 i = 0; i < 10; i++) //40
+ if(pet->isControlled() && ((pet->getPetType() == HUNTER_PET) || ((pet->GetCreatureInfo()->type == CREATURE_TYPE_DEMON) && (getClass() == CLASS_WARLOCK))))
+ {
+ // spells loop
+ for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr)
{
- data << uint16(charmInfo->GetActionBarEntry(i)->SpellOrAction) << uint16(charmInfo->GetActionBarEntry(i)->Type);
+ if(itr->second->state == PETSPELL_REMOVED)
+ continue;
+
+ data << uint16(itr->first);
+ data << uint16(itr->second->active); // pet spell active state isn't boolean
+ ++addlist;
}
+ }
- data << uint8(addlist); //1
+ data.put<uint8>(spellsCountPos, addlist);
- if(addlist && pet->isControlled())
- {
- for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr)
- {
- if(itr->second->state == PETSPELL_REMOVED)
- continue;
+ uint8 cooldownsCount = pet->m_CreatureSpellCooldowns.size() + pet->m_CreatureCategoryCooldowns.size();
+ data << uint8(cooldownsCount);
- data << uint16(itr->first);
- data << uint16(itr->second->active); // pet spell active state isn't boolean
- }
- }
+ time_t curTime = time(NULL);
- //data << uint8(0x01) << uint32(0x6010) << uint32(0x01) << uint32(0x05) << uint16(0x00); //15
- uint8 count = 3; //1+8+8+8=25
+ for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr)
+ {
+ time_t cooldown = 0;
- // if count = 0, then end of packet...
- data << count;
- // uint32 value is spell id...
- // uint64 value is constant 0, unknown...
- data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3
- //data << uint32(0x5fd1) << uint64(0); // if count = 2
- data << uint32(0x8e8c) << uint64(0); // if count = 3
- data << uint32(0x8e8b) << uint64(0); // if count = 3
+ if(itr->second > curTime)
+ cooldown = (itr->second - curTime) * 1000;
- GetSession()->SendPacket(&data);
+ data << uint16(itr->first); // spellid
+ data << uint16(0); // spell category?
+ data << uint32(itr->second); // cooldown
+ data << uint32(0); // category cooldown
}
+
+ for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureCategoryCooldowns.begin(); itr != pet->m_CreatureCategoryCooldowns.end(); ++itr)
+ {
+ time_t cooldown = 0;
+
+ if(itr->second > curTime)
+ cooldown = (itr->second - curTime) * 1000;
+
+ data << uint16(itr->first); // spellid
+ data << uint16(0); // spell category?
+ data << uint32(0); // cooldown
+ data << uint32(itr->second); // category cooldown
+ }
+
+ GetSession()->SendPacket(&data);
}
void Player::PossessSpellInitialize()
@@ -16428,7 +17058,10 @@ void Player::PossessSpellInitialize()
WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds
//16
- data << (uint64)charm->GetGUID() << uint32(0x00000000) << uint8(0) << uint8(0) << uint16(0);
+ data << uint64(charm->GetGUID());
+ data << uint32(0x00000000);
+ data << uint32(0);
+ data << uint8(0) << uint8(0) << uint16(0);
for(uint32 i = 0; i < 10; i++) //40
{
@@ -16437,11 +17070,8 @@ void Player::PossessSpellInitialize()
data << uint8(addlist); //1
- uint8 count = 3;
- data << count;
- data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3
- data << uint32(0x8e8c) << uint64(0); // if count = 3
- data << uint32(0x8e8b) << uint64(0); // if count = 3
+ uint8 count = 0;
+ data << uint8(count); // cooldowns count
GetSession()->SendPacket(&data);
}
@@ -16478,13 +17108,13 @@ void Player::CharmSpellInitialize()
WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds
- data << (uint64)charm->GetGUID() << uint32(0x00000000);
-
+ data << uint64(charm->GetGUID());
+ data << uint32(0x00000000);
+ data << uint32(0);
if(charm->GetTypeId() != TYPEID_PLAYER)
data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState());
else
data << uint8(0) << uint8(0);
-
data << uint16(0);
for(uint32 i = 0; i < 10; i++) //40
@@ -16507,51 +17137,12 @@ void Player::CharmSpellInitialize()
}
}
- uint8 count = 3;
- data << count;
- data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3
- data << uint32(0x8e8c) << uint64(0); // if count = 3
- data << uint32(0x8e8b) << uint64(0); // if count = 3
+ uint8 count = 0;
+ data << uint8(count); // cooldowns count
GetSession()->SendPacket(&data);
}
-int32 Player::GetTotalFlatMods(uint32 spellId, SpellModOp op)
-{
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
- if (!spellInfo) return 0;
- int32 total = 0;
- for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr)
- {
- SpellModifier *mod = *itr;
-
- if(!IsAffectedBySpellmod(spellInfo,mod))
- continue;
-
- if (mod->type == SPELLMOD_FLAT)
- total += mod->value;
- }
- return total;
-}
-
-int32 Player::GetTotalPctMods(uint32 spellId, SpellModOp op)
-{
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
- if (!spellInfo) return 0;
- int32 total = 0;
- for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr)
- {
- SpellModifier *mod = *itr;
-
- if(!IsAffectedBySpellmod(spellInfo,mod))
- continue;
-
- if (mod->type == SPELLMOD_PCT)
- total += mod->value;
- }
- return total;
-}
-
bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell)
{
if (!mod || !spellInfo)
@@ -16569,22 +17160,27 @@ bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mo
return false;
}
- return spellmgr.IsAffectedBySpell(spellInfo,mod->spellId,mod->effectId,mod->mask);
+ return spellmgr.IsAffectedByMod(spellInfo, mod);
}
void Player::AddSpellMod(SpellModifier* mod, bool apply)
{
uint16 Opcode= (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER;
- for(int eff=0;eff<64;++eff)
+ uint8 i=0;
+ flag96 _mask;
+ for(int eff=0;eff<96;++eff)
{
- uint64 _mask = uint64(1) << eff;
+ if ((eff!=0) && (eff%32==0))
+ i++;
+
+ _mask[i] = uint32(1) << (eff-(32*i));
if ( mod->mask & _mask)
{
int32 val = 0;
for (SpellModList::iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr)
{
- if ((*itr)->type == mod->type && (*itr)->mask & _mask)
+ if ((*itr)->type == mod->type && (*itr)->mask & _mask )
val += (*itr)->value;
}
val += apply ? mod->value : -(mod->value);
@@ -16683,6 +17279,27 @@ void Player::RemovePetitionsAndSigns(uint64 guid, uint32 type)
CharacterDatabase.CommitTransaction();
}
+void Player::LeaveAllArenaTeams(uint64 guid)
+{
+ QueryResult *result = CharacterDatabase.PQuery("SELECT arena_team_member.arenateamid FROM arena_team_member JOIN arena_team ON arena_team_member.arenateamid = arena_team.arenateamid WHERE guid='%u'", GUID_LOPART(guid));
+ if(!result)
+ return;
+
+ do
+ {
+ Field *fields = result->Fetch();
+ uint32 at_id = fields[0].GetUInt32();
+ if(at_id != 0)
+ {
+ ArenaTeam * at = objmgr.GetArenaTeamById(at_id);
+ if(at)
+ at->DelMember(guid);
+ }
+ } while (result->NextRow());
+
+ delete result;
+}
+
void Player::SetRestBonus (float rest_bonus_new)
{
// Prevent resting on max level
@@ -16713,7 +17330,7 @@ void Player::HandleStealthedUnitsDetection()
{
std::list<Unit*> stealthedUnits;
Trinity::AnyStealthedCheck u_check;
- Trinity::UnitListSearcher<Trinity::AnyStealthedCheck > searcher(stealthedUnits, u_check);
+ Trinity::UnitListSearcher<Trinity::AnyStealthedCheck > searcher(this, stealthedUnits, u_check);
VisitNearbyObject(World::GetMaxVisibleDistance(), searcher);
for (std::list<Unit*>::iterator i = stealthedUnits.begin(); i != stealthedUnits.end(); ++i)
@@ -16732,7 +17349,7 @@ void Player::HandleStealthedUnitsDetection()
// send data at target visibility change (adding to client)
if((*i)!=this && (*i)->isType(TYPEMASK_UNIT))
{
- SendAuraDurationsForTarget(*i);
+ SendAurasForTarget(*i);
//if(((Unit*)(*i))->isAlive()) //should be always alive
{
if((*i)->GetTypeId()==TYPEID_UNIT)
@@ -17528,6 +18145,10 @@ bool Player::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList, bool
if (u == this)
return true;
+ // phased visibility (both must phased in same way)
+ if(!InSamePhase(u))
+ return false;
+
// player visible for other player if not logout and at same transport
// including case when player is out of world
bool at_same_transport =
@@ -17726,7 +18347,7 @@ void Player::UpdateVisibilityOf(WorldObject* target)
// send data at target visibility change (adding to client)
if(target!=this && target->isType(TYPEMASK_UNIT))
{
- SendAuraDurationsForTarget((Unit*)target);
+ SendAurasForTarget((Unit*)target);
if(((Unit*)target)->isAlive())
{
if(target->GetTypeId()==TYPEID_UNIT)
@@ -17905,7 +18526,7 @@ void Player::SetGroup(Group *group, int8 subgroup)
void Player::SendInitialPacketsBeforeAddToMap()
{
- WorldPacket data(SMSG_SET_REST_START, 4);
+ WorldPacket data(SMSG_SET_REST_START_OBSOLETE, 4);
data << uint32(0); // unknown, may be rest state time or experience
GetSession()->SendPacket(&data);
@@ -17933,6 +18554,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
SendInitialActionButtons();
SendInitialReputations();
+ m_achievementMgr.SendAllAchievementData();
UpdateZone(GetZoneId());
SendInitWorldStates();
@@ -17943,13 +18565,23 @@ void Player::SendInitialPacketsBeforeAddToMap()
data << (float)0.01666667f; // game speed
GetSession()->SendPacket( &data );
+ data.Initialize(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement
+ data << uint32(0x00000000); // on blizz it increments periodically
+ GetSession()->SendPacket(&data);
+
// set fly flag if in fly form or taxi flight to prevent visually drop at ground in showup moment
if(HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || isInFlight())
AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
+
+ m_mover = this;
}
void Player::SendInitialPacketsAfterAddToMap()
{
+ WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement
+ data << uint32(0x00000000); // on blizz it increments periodically
+ GetSession()->SendPacket(&data);
+
CastSpell(this, 836, true); // LOGINEFFECT
// set some aura effects that send packet to player client after add player to map
@@ -17980,6 +18612,7 @@ void Player::SendInitialPacketsAfterAddToMap()
SendMessageToSet(&data,true);
}
+ SendAurasForTarget(this);
SendEnchantmentDurations(); // must be after add to map
SendItemDurations(); // must be after add to map
}
@@ -17997,11 +18630,19 @@ void Player::SendUpdateToOutOfRangeGroupMembers()
pet->ResetAuraUpdateMask();
}
-void Player::SendTransferAborted(uint32 mapid, uint16 reason)
+void Player::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg)
{
WorldPacket data(SMSG_TRANSFER_ABORTED, 4+2);
data << uint32(mapid);
- data << uint16(reason); // transfer abort reason
+ data << uint8(reason); // transfer abort reason
+ switch(reason)
+ {
+ case TRANSFER_ABORT_INSUF_EXPAN_LVL:
+ case TRANSFER_ABORT_DIFFICULTY:
+ case TRANSFER_ABORT_UNIQUE_MESSAGE:
+ data << uint8(arg);
+ break;
+ }
GetSession()->SendPacket(&data);
}
@@ -18067,22 +18708,18 @@ void Player::resetSpells()
learnQuestRewardedSpells();
}
-void Player::learnDefaultSpells(bool loading)
+void Player::learnDefaultSpells()
{
// learn default race/class spells
PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(),getClass());
- std::list<CreateSpellPair>::const_iterator spell_itr;
- for (spell_itr = info->spell.begin(); spell_itr!=info->spell.end(); ++spell_itr)
+ for (PlayerCreateInfoSpells::const_iterator itr = info->spell.begin(); itr!=info->spell.end(); ++itr)
{
- uint16 tspell = spell_itr->first;
- if (tspell)
- {
- sLog.outDebug("PLAYER: Adding initial spell, id = %u",tspell);
- if(loading || !spell_itr->second) // not care about passive spells or loading case
- addSpell(tspell,spell_itr->second);
- else // but send in normal spell in game learn case
- learnSpell(tspell);
- }
+ uint32 tspell = *itr;
+ sLog.outDebug("PLAYER (Class: %u Race: %u): Adding initial spell, id = %u",uint32(getClass()),uint32(getRace()), tspell);
+ if(!IsInWorld()) // will send in INITIAL_SPELLS in list anyway at map add
+ addSpell(tspell,true,true,true,false);
+ else // but send in normal spell in game learn case
+ learnSpell(tspell,true);
}
}
@@ -18174,7 +18811,7 @@ void Player::learnQuestRewardedSpells()
}
}
-void Player::learnSkillRewardedSpells(uint32 skill_id )
+void Player::learnSkillRewardedSpells(uint32 skill_id, uint32 skill_value )
{
uint32 raceMask = getRaceMask();
uint32 classMask = getClassMask();
@@ -18192,35 +18829,63 @@ void Player::learnSkillRewardedSpells(uint32 skill_id )
if (sSpellStore.LookupEntry(pAbility->spellId))
{
- // Ok need learn spell
- learnSpell(pAbility->spellId);
+ // need unlearn spell
+ if (skill_value < pAbility->req_skill_value)
+ removeSpell(pAbility->spellId);
+ // need learn
+ else if (!IsInWorld())
+ addSpell(pAbility->spellId,true,true,true,false);
+ else
+ learnSpell(pAbility->spellId,true);
}
}
}
-void Player::learnSkillRewardedSpells()
+void Player::SendAurasForTarget(Unit *target)
{
- for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++)
- {
- if(!GetUInt32Value(PLAYER_SKILL_INDEX(i)))
- continue;
-
- uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
+ if(target->GetVisibleAuras()->empty()) // speedup things
+ return;
- learnSkillRewardedSpells(pskill);
- }
-}
+ WorldPacket data(SMSG_AURA_UPDATE_ALL);
+ data.append(target->GetPackGUID());
-void Player::SendAuraDurationsForTarget(Unit* target)
-{
- for(Unit::AuraMap::const_iterator itr = target->GetAuras().begin(); itr != target->GetAuras().end(); ++itr)
+ Unit::VisibleAuraMap const *visibleAuras = target->GetVisibleAuras();
+ for(Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); itr != visibleAuras->end(); ++itr)
{
- Aura* aura = itr->second;
- if(aura->GetAuraSlot() >= MAX_AURAS || aura->IsPassive() || aura->GetCasterGUID()!=GetGUID())
- continue;
+ for(uint32 j = 0; j < 3; ++j)
+ {
+ if(Aura *aura = target->GetAura(itr->second, j))
+ {
+ data << uint8(aura->GetAuraSlot());
+ data << uint32(aura->GetId());
+
+ if(aura->GetId())
+ {
+ uint8 auraFlags = aura->GetAuraFlags();
+ // flags
+ data << uint8(auraFlags);
+ // level
+ data << uint8(aura->GetAuraLevel());
+ // charges
+ data << uint8(aura->GetAuraCharges());
+
+ if(!(auraFlags & AFLAG_NOT_CASTER))
+ {
+ data << uint8(0); // packed GUID of someone (caster?)
+ }
- aura->SendAuraDurationForCaster(this);
+ if(auraFlags & AFLAG_DURATION) // include aura duration
+ {
+ data << uint32(aura->GetAuraMaxDuration());
+ data << uint32(aura->GetAuraDuration());
+ }
+ }
+ break;
+ }
+ }
}
+
+ GetSession()->SendPacket(&data);
}
void Player::SetDailyQuestStatus( uint32 quest_id )
@@ -18282,15 +18947,15 @@ uint32 Player::GetMinLevelForBattleGroundQueueId(uint32 queue_id)
if(queue_id < 1)
return 0;
- if(queue_id >=6)
- queue_id = 6;
+ if(queue_id >=7)
+ queue_id = 7;
return 10*(queue_id+1);
}
uint32 Player::GetMaxLevelForBattleGroundQueueId(uint32 queue_id)
{
- if(queue_id >=6)
+ if(queue_id >=7)
return 255; // hardcoded max level
return 10*(queue_id+2)-1;
@@ -18302,8 +18967,8 @@ uint32 Player::GetBattleGroundQueueIdFromLevel() const
uint32 level = getLevel();
if(level <= 19)
return 0;
- else if (level > 69)
- return 6;
+ else if (level > 79)
+ return 7;
else
return level/10 - 1; // 20..29 -> 1, 30-39 -> 2, ...
/*
@@ -18333,18 +18998,23 @@ bool Player::IsSpellFitByClassAndRace( uint32 spell_id ) const
SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id);
SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spell_id);
+ if(lower==upper)
+ return true;
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
{
// skip wrong race skills
if( _spell_idx->second->racemask && (_spell_idx->second->racemask & racemask) == 0)
- return false;
+ continue;
// skip wrong class skills
if( _spell_idx->second->classmask && (_spell_idx->second->classmask & classmask) == 0)
- return false;
+ continue;
+
+ return true;
}
- return true;
+
+ return false;
}
bool Player::HasQuestForGO(int32 GOId)
@@ -18449,9 +19119,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;
@@ -18517,6 +19186,24 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons
return false;
}
+bool Player::CanNoReagentCast(SpellEntry const* spellInfo) const
+{
+ // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP
+ if (spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP &&
+ HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION))
+ return true;
+
+ // Check no reagent use mask
+ flag96 noReagentMask;
+ noReagentMask[0] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1);
+ noReagentMask[1] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1+1);
+ noReagentMask[2] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1+2);
+ if (spellInfo->SpellFamilyFlags & noReagentMask)
+ return true;
+
+ return false;
+}
+
void Player::RemoveItemDependentAurasAndCasts( Item * pItem )
{
AuraMap& auras = GetAuras();
@@ -18562,7 +19249,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())
{
@@ -18594,6 +19281,26 @@ uint32 Player::GetResurrectionSpellId()
return spell_id;
}
+// Used in triggers for check "Only to targets that grant experience or honor" req
+bool Player::isHonorOrXPTarget(Unit* pVictim)
+{
+ uint32 v_level = pVictim->getLevel();
+ uint32 k_grey = Trinity::XP::GetGrayLevel(getLevel());
+
+ // Victim level less gray level
+ if(v_level<=k_grey)
+ return false;
+
+ if(pVictim->GetTypeId() == TYPEID_UNIT)
+ {
+ if (((Creature*)pVictim)->isTotem() ||
+ ((Creature*)pVictim)->isPet() ||
+ ((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)
+ return false;
+ }
+ return true;
+}
+
bool Player::RewardPlayerAndGroupAtKill(Unit* pVictim)
{
bool PvP = pVictim->isCharmedOwnedByPlayerOrPlayer();
@@ -18721,6 +19428,9 @@ uint32 Player::GetBaseWeaponSkillValue (WeaponAttackType attType) const
void Player::ResurectUsingRequestData()
{
+ /// Teleport before resurrecting, otherwise the player might get attacked from creatures near his corpse
+ TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation());
+
ResurrectPlayer(0.0f,false);
if(GetMaxHealth() > m_resurrectHealth)
@@ -18738,8 +19448,6 @@ void Player::ResurectUsingRequestData()
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY) );
SpawnCorpseBones();
-
- TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation());
}
void Player::SetClientControl(Unit* target, uint8 allowMove)
@@ -18753,28 +19461,31 @@ void Player::SetClientControl(Unit* target, uint8 allowMove)
void Player::UpdateZoneDependentAuras( uint32 newZone )
{
// remove new continent flight forms
- if( !isGameMaster() &&
- GetVirtualMapForMapAndZone(GetMapId(),newZone) != 530)
+ if( !IsAllowUseFlyMountsHere() )
{
RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED);
RemoveSpellsCausingAura(SPELL_AURA_FLY);
}
// Some spells applied at enter into zone (with subzones)
- // Human Illusion
- // NOTE: these are removed by RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP);
- if ( newZone == 2367 ) // Old Hillsbrad Foothills
- {
- uint32 spellid = 0;
- // all horde races
- if( GetTeam() == HORDE )
- spellid = getGender() == GENDER_FEMALE ? 35481 : 35480;
- // and some alliance races
- else if( getRace() == RACE_NIGHTELF || getRace() == RACE_DRAENEI )
- spellid = getGender() == GENDER_FEMALE ? 35483 : 35482;
-
- if(spellid && !HasAura(spellid,0) )
- CastSpell(this,spellid,true);
+ switch(newZone)
+ {
+ case 2367: // Old Hillsbrad Foothills
+ {
+ // Human Illusion
+ // NOTE: these are removed by RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP);
+ uint32 spellid = 0;
+ // all horde races
+ if( GetTeam() == HORDE )
+ spellid = getGender() == GENDER_FEMALE ? 35481 : 35480;
+ // and some alliance races
+ else if( getRace() == RACE_NIGHTELF || getRace() == RACE_DRAENEI )
+ spellid = getGender() == GENDER_FEMALE ? 35483 : 35482;
+
+ if(spellid && !HasAura(spellid,0) )
+ CastSpell(this,spellid,true);
+ break;
+ }
}
}
@@ -18784,25 +19495,41 @@ void Player::UpdateAreaDependentAuras( uint32 newArea )
for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
{
// use m_zoneUpdateId for speed: UpdateArea called from UpdateZone or instead UpdateZone in both cases m_zoneUpdateId up-to-date
- if(!IsSpellAllowedInLocation(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea))
+ if(GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea)!=0)
RemoveAura(iter);
else
++iter;
}
- // unmount if enter in this subzone
- if( newArea == 35)
- RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
- // Dragonmaw Illusion
- else if( newArea == 3759 || newArea == 3966 || newArea == 3939 )
+ // some auras applied at subzone enter
+ switch(newArea)
{
- if( GetDummyAura(40214) )
- {
- if( !HasAura(40216,0) )
- CastSpell(this,40216,true);
- if( !HasAura(42016,0) )
- CastSpell(this,42016,true);
- }
+ // Dragonmaw Illusion
+ case 3759: // Netherwing Ledge
+ case 3939: // Dragonmaw Fortress
+ case 3966: // Dragonmaw Base Camp
+ if( GetDummyAura(40214) )
+ {
+ if( !HasAura(40216,0) )
+ CastSpell(this,40216,true);
+ if( !HasAura(42016,0) )
+ CastSpell(this,42016,true);
+ }
+ break;
+ // Dominion Over Acherus
+ case 4281: // Acherus: The Ebon Hold
+ case 4342: // Acherus: The Ebon Hold
+ if( HasSpell(51721) )
+ if( !HasAura(51721,0) )
+ CastSpell(this,51721,true);
+ break;
+ // Mist of the Kvaldir
+ case 4028: //Riplash Strand
+ case 4029: //Riplash Ruins
+ case 4106: //Garrosh's Landing
+ case 4031: //Pal'ea
+ CastSpell(this,54119,true);
+ break;
}
}
@@ -18933,18 +19660,20 @@ PartyResult Player::CanUninviteFromGroup() const
void Player::UpdateUnderwaterState( Map* m, float x, float y, float z )
{
float water_z = m->GetWaterLevel(x,y);
- float height_z = m->GetHeight(x,y,z, false); // use .map base surface height
+ float terrain_z = m->GetHeight(x,y,z, false); // use .map base surface height
uint8 flag1 = m->GetTerrainType(x,y);
- //!Underwater check, not in water if underground or above water level
- if (height_z <= INVALID_HEIGHT || z < (height_z-2) || z > (water_z - 2) )
- m_isunderwater &= 0x7A;
+ //!Underwater check, not in water if underground or above water level - take UC royal quater for example
+ if (terrain_z <= INVALID_HEIGHT || z < (terrain_z-2) || z > (water_z - 2) )
+ m_isunderwater &= ~UNDERWATER_INWATER;
else if ((z < (water_z - 2)) && (flag1 & 0x01))
- m_isunderwater |= 0x01;
+ m_isunderwater |= UNDERWATER_INWATER;
//!in lava check, anywhere under lava level
- if ((height_z <= INVALID_HEIGHT || z < (height_z - 0)) && (flag1 == 0x00) && IsInWater())
- m_isunderwater |= 0x80;
+ if ((terrain_z <= INVALID_HEIGHT || z < (terrain_z - 0)) && (flag1 == 0x00) && IsInWater())
+ m_isunderwater |= UNDERWATER_INLAVA;
+ else
+ m_isunderwater &= ~UNDERWATER_INLAVA;
}
void Player::SetCanParry( bool value )
@@ -18979,8 +19708,8 @@ bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const
void Player::HandleFallDamage(MovementInfo& movementInfo)
{
- if(movementInfo.fallTime < 1500)
- return;
+ //if(movementInfo.fallTime < 1500)
+ // return;
// calculate total z distance of the fall
float z_diff = m_lastFallZ - movementInfo.z;
@@ -18990,7 +19719,7 @@ void Player::HandleFallDamage(MovementInfo& movementInfo)
// 14.57 can be calculated by resolving damageperc formular below to 0
if (z_diff >= 14.57f && !isDead() && !isGameMaster() &&
!HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) &&
- !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) )
+ !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL) )
{
//Safe fall, fall height reduction
int32 safe_fall = GetTotalAuraModifier(SPELL_AURA_SAFE_FALL);
@@ -19085,38 +19814,46 @@ void Player::RemovePossess(bool attack)
}*/
}
-void Player::SetViewport(uint64 guid, bool moveable)
+/*void Player::SetViewport(uint64 guid, bool moveable)
{
WorldPacket data(SMSG_CLIENT_CONTROL_UPDATE, 8+1);
data.appendPackGUID(guid); // Packed guid of object to set client's view to
data << (moveable ? uint8(0x01) : uint8(0x00)); // 0 - can't move; 1 - can move
m_session->SendPacket(&data);
sLog.outDetail("Viewport for "I64FMT" (%s) changed to "I64FMT, GetGUID(), GetName(), guid);
+}*/
+
+void Player::SetBindSight(Unit *target)
+{
+ if(target)
+ target->AddPlayerToVision(this);
+ else
+ target->RemovePlayerFromVision(this);
}
WorldObject* Player::GetFarsightTarget() const
{
// Players can have in farsight field another player's guid, a creature's guid, or a dynamic object's guid
- if (uint64 guid = GetUInt64Value(PLAYER_FARSIGHT))
- return (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*this, guid, TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT);
+ if(uint64 guid = GetFarSight())
+ return (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*this, guid, TYPEMASK_FARSIGHTOBJ);
return NULL;
}
void Player::RemoveFarsightTarget()
{
- if (WorldObject* fTarget = GetFarsightTarget())
+ if (WorldObject* target = GetFarsightTarget())
{
- if (fTarget->isType(TYPEMASK_PLAYER | TYPEMASK_UNIT))
- ((Unit*)fTarget)->RemovePlayerFromVision(this);
+ if (target->isType(TYPEMASK_PLAYER | TYPEMASK_UNIT))
+ ((Unit*)target)->RemovePlayerFromVision(this);
}
ClearFarsight();
}
void Player::ClearFarsight()
{
- if (GetUInt64Value(PLAYER_FARSIGHT))
+ if(GetFarSight())
{
- SetUInt64Value(PLAYER_FARSIGHT, 0);
+ SetFarSightGUID(0);
WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
GetSession()->SendPacket(&data);
}
@@ -19130,7 +19867,7 @@ void Player::SetFarsightTarget(WorldObject* obj)
// Remove the current target if there is one
RemoveFarsightTarget();
- SetUInt64Value(PLAYER_FARSIGHT, obj->GetGUID());
+ SetFarSightGUID(obj->GetGUID());
}
bool Player::isAllowUseBattleGroundObject()
@@ -19145,6 +19882,159 @@ bool Player::isAllowUseBattleGroundObject()
);
}
+uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair)
+{
+ uint32 level = getLevel();
+
+ if(level > GT_MAX_LEVEL)
+ level = GT_MAX_LEVEL; // max level in this dbc
+
+ uint8 hairstyle = GetByteValue(PLAYER_BYTES, 2);
+ uint8 haircolor = GetByteValue(PLAYER_BYTES, 3);
+ uint8 facialhair = GetByteValue(PLAYER_BYTES_2, 0);
+
+ if((hairstyle == newhairstyle) && (haircolor == newhaircolor) && (facialhair == newfacialhair))
+ return 0;
+
+ GtBarberShopCostBaseEntry const *bsc = sGtBarberShopCostBaseStore.LookupEntry(level - 1);
+
+ if(!bsc) // shouldn't happen
+ return 0xFFFFFFFF;
+
+ float cost = 0;
+
+ if(hairstyle != newhairstyle)
+ cost += bsc->cost; // full price
+
+ if((haircolor != newhaircolor) && (hairstyle == newhairstyle))
+ cost += bsc->cost * 0.5f; // +1/2 of price
+
+ if(facialhair != newfacialhair)
+ cost += bsc->cost * 0.75f; // +3/4 of price
+
+ return uint32(cost);
+}
+
+void Player::InitGlyphsForLevel()
+{
+ for(uint32 i = 0; i < sGlyphSlotStore.GetNumRows(); ++i)
+ if(GlyphSlotEntry const * gs = sGlyphSlotStore.LookupEntry(i))
+ if(gs->Order)
+ SetGlyphSlot(gs->Order - 1, gs->Id);
+
+ uint32 level = getLevel();
+ uint32 value = 0;
+
+ // 0x3F = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 for 80 level
+ if(level >= 15)
+ value |= (0x01 | 0x02);
+ if(level >= 30)
+ value |= 0x08;
+ if(level >= 50)
+ value |= 0x04;
+ if(level >= 70)
+ value |= 0x10;
+ if(level >= 80)
+ value |= 0x20;
+
+ SetUInt32Value(PLAYER_GLYPHS_ENABLED, value);
+}
+
+void Player::EnterVehicle(Vehicle *vehicle)
+{
+ VehicleEntry const *ve = sVehicleStore.LookupEntry(vehicle->GetVehicleId());
+ if(!ve)
+ return;
+
+ VehicleSeatEntry const *veSeat = sVehicleSeatStore.LookupEntry(ve->m_seatID[0]);
+ if(!veSeat)
+ return;
+
+ vehicle->SetCharmerGUID(GetGUID());
+ vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
+ vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
+ vehicle->setFaction(getFaction());
+
+ SetCharm(vehicle); // charm
+ SetMover(vehicle);
+ SetFarSightGUID(vehicle->GetGUID()); // set view
+
+ SetClientControl(vehicle, 1); // redirect controls to vehicle
+
+ WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
+ GetSession()->SendPacket(&data);
+
+ data.Initialize(MSG_MOVE_TELEPORT_ACK, 30);
+ data.append(GetPackGUID());
+ data << uint32(0); // counter?
+ data << uint32(MOVEMENTFLAG_ONTRANSPORT); // transport
+ data << uint16(0); // special flags
+ data << uint32(getMSTime()); // time
+ data << vehicle->GetPositionX(); // x
+ data << vehicle->GetPositionY(); // y
+ data << vehicle->GetPositionZ(); // z
+ data << vehicle->GetOrientation(); // o
+ // transport part, TODO: load/calculate seat offsets
+ data << uint64(vehicle->GetGUID()); // transport guid
+ data << float(veSeat->m_attachmentOffsetX); // transport offsetX
+ data << float(veSeat->m_attachmentOffsetY); // transport offsetY
+ data << float(veSeat->m_attachmentOffsetZ); // transport offsetZ
+ data << float(0); // transport orientation
+ data << uint32(getMSTime()); // transport time
+ data << uint8(0); // seat
+ // end of transport part
+ data << uint32(0); // fall time
+ GetSession()->SendPacket(&data);
+
+ data.Initialize(SMSG_PET_SPELLS, 8+4+4+4+4*10+1+1);
+ data << uint64(vehicle->GetGUID());
+ data << uint32(0x00000000);
+ data << uint32(0x00000000);
+ data << uint32(0x00000101);
+
+ for(uint32 i = 0; i < 10; ++i)
+ data << uint16(0) << uint8(0) << uint8(i+8);
+
+ data << uint8(0);
+ data << uint8(0);
+ GetSession()->SendPacket(&data);
+}
+
+void Player::ExitVehicle(Vehicle *vehicle)
+{
+ vehicle->SetCharmerGUID(0);
+ vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
+ vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
+ vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H);
+
+ SetCharm(NULL);
+ SetMover(NULL);
+ SetFarSightGUID(0);
+
+ SetClientControl(vehicle, 0);
+
+ WorldPacket data(MSG_MOVE_TELEPORT_ACK, 30);
+ data.append(GetPackGUID());
+ data << uint32(0); // counter?
+ data << uint32(MOVEMENTFLAG_FLY_UNK1); // fly unk
+ data << uint16(0x40); // special flags
+ data << uint32(getMSTime()); // time
+ data << vehicle->GetPositionX(); // x
+ data << vehicle->GetPositionY(); // y
+ data << vehicle->GetPositionZ(); // z
+ data << vehicle->GetOrientation(); // o
+ data << uint32(0); // fall time
+ GetSession()->SendPacket(&data);
+
+ data.Initialize(SMSG_PET_SPELLS, 8+4);
+ data << uint64(0);
+ data << uint32(0);
+ GetSession()->SendPacket(&data);
+
+ // only for flyable vehicles?
+ CastSpell(this, 45472, true); // Parachute
+}
+
bool Player::HasTitle(uint32 bitIndex)
{
if (bitIndex > 128)
@@ -19162,7 +20052,6 @@ void Player::SetTitle(CharTitlesEntry const* title)
SetFlag(PLAYER__FIELD_KNOWN_TITLES+fieldIndexOffset, flag);
}
-
/*-----------------------TRINITY--------------------------*/
bool Player::isTotalImmunity()
{
@@ -19220,3 +20109,201 @@ void Player::UpdateCharmedAI()
}
}
+void Player::ConvertRune(uint8 index, uint8 newType)
+{
+ SetCurrentRune(index, newType);
+
+ WorldPacket data(SMSG_CONVERT_RUNE, 2);
+ data << uint8(index);
+ data << uint8(newType);
+ GetSession()->SendPacket(&data);
+}
+
+void Player::ResyncRunes(uint8 count)
+{
+ WorldPacket data(SMSG_RESYNC_RUNES, count * 2);
+ for(uint32 i = 0; i < count; ++i)
+ {
+ data << uint8(GetCurrentRune(i)); // rune type
+ data << uint8(255 - (GetRuneCooldown(i) * 51)); // passed cooldown time (0-255)
+ }
+ GetSession()->SendPacket(&data);
+}
+
+void Player::AddRunePower(uint8 index)
+{
+ WorldPacket data(SMSG_ADD_RUNE_POWER, 4);
+ data << uint32(1 << index); // mask (0x00-0x3F probably)
+ GetSession()->SendPacket(&data);
+}
+
+void Player::InitRunes()
+{
+ if(getClass() != CLASS_DEATH_KNIGHT)
+ return;
+
+ m_runes = new Runes;
+
+ m_runes->runeState = 0;
+
+ for(uint32 i = 0; i < MAX_RUNES; ++i)
+ {
+ SetBaseRune(i, i / 2); // init base types
+ SetCurrentRune(i, i / 2); // init current types
+ SetRuneCooldown(i, 0); // reset cooldowns
+ m_runes->SetRuneState(i);
+ }
+
+ for(uint32 i = 0; i < NUM_RUNE_TYPES; ++i)
+ SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f);
+}
+
+void Player::AutoStoreLootItem(uint8 bag, uint8 slot, uint32 loot_id, LootStore const& store)
+{
+ Loot loot;
+ loot.FillLoot (loot_id,store,this);
+ if(loot.items.empty ())
+ return;
+ LootItem const* lootItem = &loot.items[0];
+
+ ItemPosCountVec dest;
+ uint8 msg = CanStoreNewItem (bag,slot,dest,lootItem->itemid,lootItem->count);
+ if(msg != EQUIP_ERR_OK && slot != NULL_SLOT)
+ msg = CanStoreNewItem( bag, NULL_SLOT,dest,lootItem->itemid,lootItem->count);
+ if( msg != EQUIP_ERR_OK && bag != NULL_BAG)
+ msg = CanStoreNewItem( NULL_BAG, NULL_SLOT,dest,lootItem->itemid,lootItem->count);
+ if(msg != EQUIP_ERR_OK)
+ return;
+
+ StoreNewItem (dest,lootItem->itemid,true,lootItem->randomPropertyId);
+}
+
+uint32 Player::CalculateTalentsPoints() const
+{
+ uint32 base_talent = getLevel() < 10 ? 0 : uint32((getLevel()-9)*sWorld.getRate(RATE_TALENT));
+
+ if(getClass() != CLASS_DEATH_KNIGHT)
+ return base_talent;
+
+ uint32 talentPointsForLevel =
+ (getLevel() < 56 ? 0 : uint32((getLevel()-55)*sWorld.getRate(RATE_TALENT)))
+ + m_questRewardTalentCount;
+
+ if(talentPointsForLevel > base_talent)
+ talentPointsForLevel = base_talent;
+
+ return talentPointsForLevel;
+}
+
+bool Player::IsAllowUseFlyMountsHere() const
+{
+ if (isGameMaster())
+ return true;
+
+ switch(GetVirtualMapForMapAndZone(GetMapId(), GetZoneId()))
+ {
+ case 0:
+ case 1:
+ //if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_AZEROTH))
+ return false;
+ break;
+ case 530:
+ //if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_OUTLAND))
+ return false;
+ break;
+ case 571:
+ if(!HasSpell(54197))
+ return false;
+ break;
+ default:
+ //if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_OTHERS))
+ return false;
+ break;
+ }
+ return true;
+}
+
+void Player::learnSpellHighRank(uint32 spellid)
+{
+ learnSpell(spellid,false);
+
+ if(uint32 next = spellmgr.GetNextSpellInChain(spellid))
+ learnSpellHighRank(next);
+}
+
+void Player::_LoadSkills()
+{
+ // Note: skill data itself loaded from `data` field. This is only cleanup part of load
+
+ // reset skill modifiers and set correct unlearn flags
+ for (uint32 i = 0; i < PLAYER_MAX_SKILLS; i++)
+ {
+ SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
+
+ // set correct unlearn bit
+ uint32 id = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
+ if(!id) continue;
+
+ SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id);
+ if(!pSkill) continue;
+
+ // enable unlearn button for primary professions only
+ if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION)
+ SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,1));
+ else
+ SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0));
+
+ uint32 vskill = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)));
+
+ learnSkillRewardedSpells(id, vskill);
+ }
+
+ // special settings
+ if(getClass()==CLASS_DEATH_KNIGHT)
+ {
+ uint32 base_level = std::min(getLevel(),sWorld.getConfig (CONFIG_START_HEROIC_PLAYER_LEVEL));
+ if(base_level < 1)
+ base_level = 1;
+ uint32 base_skill = (base_level-1)*5; // 270 at starting level 55
+ if(base_skill < 1)
+ base_skill = 1; // skill mast be known and then > 0 in any case
+
+ if(GetPureSkillValue (SKILL_FIRST_AID) < base_skill)
+ SetSkill(SKILL_FIRST_AID,base_skill, base_skill);
+ if(GetPureSkillValue (SKILL_AXES) < base_skill)
+ SetSkill(SKILL_AXES, base_skill,base_skill);
+ if(GetPureSkillValue (SKILL_DEFENSE) < base_skill)
+ SetSkill(SKILL_DEFENSE, base_skill,base_skill);
+ if(GetPureSkillValue (SKILL_POLEARMS) < base_skill)
+ SetSkill(SKILL_POLEARMS, base_skill,base_skill);
+ if(GetPureSkillValue (SKILL_SWORDS) < base_skill)
+ SetSkill(SKILL_SWORDS, base_skill,base_skill);
+ if(GetPureSkillValue (SKILL_2H_AXES) < base_skill)
+ SetSkill(SKILL_2H_AXES, base_skill,base_skill);
+ if(GetPureSkillValue (SKILL_2H_SWORDS) < base_skill)
+ SetSkill(SKILL_2H_SWORDS, base_skill,base_skill);
+ if(GetPureSkillValue (SKILL_UNARMED) < base_skill)
+ SetSkill(SKILL_UNARMED, base_skill,base_skill);
+ }
+}
+
+uint32 Player::GetPhaseMaskForSpawn() const
+{
+ uint32 phase = PHASEMASK_NORMAL;
+ if(!isGameMaster())
+ phase = GetPhaseMask();
+ else
+ {
+ AuraList const& phases = GetAurasByType(SPELL_AURA_PHASE);
+ if(phases.empty())
+ phase = GetPhaseMask();
+ else
+ phase = phases.front()->GetMiscValue();
+ }
+
+ // some aura phases include 1 normal map in addition to phase itself
+ if(uint32 n_phase = phase & ~PHASEMASK_NORMAL)
+ return n_phase;
+
+ return PHASEMASK_NORMAL;
+} \ No newline at end of file
diff --git a/src/game/Player.h b/src/game/Player.h
index a5fd39a8908..dde519fdef4 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -35,6 +35,7 @@
#include "Pet.h"
#include "MapReference.h"
#include "Util.h" // for Tokens typedef
+#include "AchievementMgr.h"
#include<string>
#include<vector>
@@ -47,8 +48,11 @@ class Pet;
class PlayerMenu;
class Transport;
class UpdateMask;
+class SpellCastTargets;
class PlayerSocial;
class OutdoorPvP;
+class AchievementMgr;
+class Vehicle;
typedef std::deque<Mail*> PlayerMails;
@@ -62,6 +66,17 @@ enum SpellModType
SPELLMOD_PCT = 108 // SPELL_AURA_ADD_PCT_MODIFIER
};
+// 2^n values, Player::m_isunderwater is a bitmask. These are mangos internal values, they are never send to any client
+enum PlayerUnderwaterState
+{
+ UNDERWATER_NONE = 0x00,
+ UNDERWATER_INWATER = 0x01, // terrain type is water and player is afflicted by it
+ UNDERWATER_WATER_TRIGGER = 0x02, // m_breathTimer has been initialized
+ UNDERWATER_WATER_BREATHB = 0x04, // breathbar has been send to client
+ UNDERWATER_WATER_BREATHB_RETRACTING = 0x10, // breathbar is currently refilling - the player is above water level
+ UNDERWATER_INLAVA = 0x80 // terrain type is lava and player is afflicted by it
+};
+
enum PlayerSpellState
{
PLAYERSPELL_UNCHANGED = 0,
@@ -72,27 +87,26 @@ enum PlayerSpellState
struct PlayerSpell
{
- uint16 slotId : 16;
PlayerSpellState state : 8;
- bool active : 1;
- bool disabled : 1;
+ bool active : 1; // show in spellbook
+ bool dependent : 1; // learned as result another spell learn, skill grow, quest reward, etc
+ bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks
};
-#define SPELL_WITHOUT_SLOT_ID uint16(-1)
-
+// Spell modifier (used for modify other spells)
struct SpellModifier
{
+ SpellModifier() : charges(0), lastAffected(NULL) {}
SpellModOp op : 8;
SpellModType type : 8;
int16 charges : 16;
int32 value;
- uint64 mask;
+ flag96 mask;
uint32 spellId;
- uint32 effectId;
Spell const* lastAffected;
};
-typedef UNORDERED_MAP<uint16, PlayerSpell*> PlayerSpellMap;
+typedef UNORDERED_MAP<uint32, PlayerSpell*> PlayerSpellMap;
typedef std::list<SpellModifier*> SpellModList;
struct SpellCooldown
@@ -141,8 +155,6 @@ enum ActionButtonType
typedef std::map<uint8,ActionButton> ActionButtonList;
-typedef std::pair<uint16, uint8> CreateSpellPair;
-
struct PlayerCreateInfoItem
{
PlayerCreateInfoItem(uint32 id, uint32 amount) : item_id(id), item_amount(amount) {}
@@ -174,6 +186,8 @@ struct PlayerLevelInfo
uint8 stats[MAX_STATS];
};
+typedef std::list<uint32> PlayerCreateInfoSpells;
+
struct PlayerInfo
{
// existence checked by displayId != 0 // existence checked by displayId != 0
@@ -189,7 +203,7 @@ struct PlayerInfo
uint16 displayId_m;
uint16 displayId_f;
PlayerCreateInfoItems item;
- std::list<CreateSpellPair> spell;
+ PlayerCreateInfoSpells spell;
std::list<uint16> action[4];
PlayerLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1
@@ -224,6 +238,39 @@ struct Areas
float y2;
};
+#define MAX_RUNES 6
+#define RUNE_COOLDOWN 5 // 5*2=10 sec
+
+enum RuneType
+{
+ RUNE_BLOOD = 0,
+ RUNE_UNHOLY = 1,
+ RUNE_FROST = 2,
+ RUNE_DEATH = 3,
+ NUM_RUNE_TYPES = 4
+};
+
+struct RuneInfo
+{
+ uint8 BaseRune;
+ uint8 CurrentRune;
+ uint8 Cooldown;
+};
+
+struct Runes
+{
+ RuneInfo runes[MAX_RUNES];
+ uint8 runeState; // mask of available runes
+
+ void SetRuneState(uint8 index, bool set = true)
+ {
+ if(set)
+ runeState |= (1 << index); // usable
+ else
+ runeState &= ~(1 << index); // on cooldown
+ }
+};
+
enum FactionFlags
{
FACTION_FLAG_VISIBLE = 0x01, // makes visible in client (set or can be set at interaction with target of this faction)
@@ -328,52 +375,6 @@ enum DrunkenState
DRUNKEN_SMASHED = 3
};
-enum PlayerStateType
-{
- /*
- PLAYER_STATE_DANCE
- PLAYER_STATE_SLEEP
- PLAYER_STATE_SIT
- PLAYER_STATE_STAND
- PLAYER_STATE_READYUNARMED
- PLAYER_STATE_WORK
- PLAYER_STATE_POINT(DNR)
- PLAYER_STATE_NONE // not used or just no state, just standing there?
- PLAYER_STATE_STUN
- PLAYER_STATE_DEAD
- PLAYER_STATE_KNEEL
- PLAYER_STATE_USESTANDING
- PLAYER_STATE_STUN_NOSHEATHE
- PLAYER_STATE_USESTANDING_NOSHEATHE
- PLAYER_STATE_WORK_NOSHEATHE
- PLAYER_STATE_SPELLPRECAST
- PLAYER_STATE_READYRIFLE
- PLAYER_STATE_WORK_NOSHEATHE_MINING
- PLAYER_STATE_WORK_NOSHEATHE_CHOPWOOD
- PLAYER_STATE_AT_EASE
- PLAYER_STATE_READY1H
- PLAYER_STATE_SPELLKNEELSTART
- PLAYER_STATE_SUBMERGED
- */
-
- PLAYER_STATE_NONE = 0,
- PLAYER_STATE_SIT = 1,
- PLAYER_STATE_SIT_CHAIR = 2,
- PLAYER_STATE_SLEEP = 3,
- PLAYER_STATE_SIT_LOW_CHAIR = 4,
- PLAYER_STATE_SIT_MEDIUM_CHAIR = 5,
- PLAYER_STATE_SIT_HIGH_CHAIR = 6,
- PLAYER_STATE_DEAD = 7,
- PLAYER_STATE_KNEEL = 8,
-
- PLAYER_STATE_FORM_ALL = 0x00FF0000,
-
- PLAYER_STATE_FLAG_ALWAYS_STAND = 0x01, // byte 4
- PLAYER_STATE_FLAG_CREEP = 0x02000000,
- PLAYER_STATE_FLAG_UNTRACKABLE = 0x04000000,
- PLAYER_STATE_FLAG_ALL = 0xFF000000,
-};
-
enum PlayerFlags
{
PLAYER_FLAGS_GROUP_LEADER = 0x00000001,
@@ -382,17 +383,26 @@ enum PlayerFlags
PLAYER_FLAGS_GM = 0x00000008,
PLAYER_FLAGS_GHOST = 0x00000010,
PLAYER_FLAGS_RESTING = 0x00000020,
- PLAYER_FLAGS_FFA_PVP = 0x00000080,
+ PLAYER_FLAGS_UNK7 = 0x00000040,
+ PLAYER_FLAGS_UNK8 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state
PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards
PLAYER_FLAGS_IN_PVP = 0x00000200,
PLAYER_FLAGS_HIDE_HELM = 0x00000400,
PLAYER_FLAGS_HIDE_CLOAK = 0x00000800,
- PLAYER_FLAGS_UNK1 = 0x00001000, // played long time
- PLAYER_FLAGS_UNK2 = 0x00002000, // played too long time
- PLAYER_FLAGS_UNK3 = 0x00008000, // strange visual effect (2.0.1), looks like PLAYER_FLAGS_GHOST flag
- PLAYER_FLAGS_SANCTUARY = 0x00010000, // player entered sanctuary
- PLAYER_FLAGS_UNK4 = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
- PLAYER_UNK = 0x00040000, // 2.0.8...
+ PLAYER_FLAGS_UNK13 = 0x00001000, // played long time
+ PLAYER_FLAGS_UNK14 = 0x00002000, // played too long time
+ PLAYER_FLAGS_UNK15 = 0x00004000,
+ PLAYER_FLAGS_UNK16 = 0x00008000, // strange visual effect (2.0.1), looks like PLAYER_FLAGS_GHOST flag
+ PLAYER_FLAGS_UNK17 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary
+ PLAYER_FLAGS_UNK18 = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
+ PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually)
+ PLAYER_FLAGS_UNK20 = 0x00080000,
+ PLAYER_FLAGS_UNK21 = 0x00100000,
+ PLAYER_FLAGS_UNK22 = 0x00200000,
+ PLAYER_FLAGS_UNK23 = 0x00400000,
+ PLAYER_FLAGS_UNK24 = 0x00800000, // disabled all abilitys on tab except autoattack
+ PLAYER_FLAGS_UNK25 = 0x01000000, // disabled all melee ability on tab include autoattack
+
};
// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
@@ -481,7 +491,8 @@ enum LootType
LOOT_DISENCHANTING = 5, // unsupported by client, sending LOOT_SKINNING instead
LOOT_PROSPECTING = 6, // unsupported by client, sending LOOT_SKINNING instead
LOOT_INSIGNIA = 7, // unsupported by client, sending LOOT_SKINNING instead
- LOOT_FISHINGHOLE = 8 // unsupported by client, sending LOOT_FISHING instead
+ LOOT_FISHINGHOLE = 8, // unsupported by client, sending LOOT_FISHING instead
+ LOOT_MILLING = 9 // unsupported by client, sending LOOT_SKINNING instead
};
enum MirrorTimerType
@@ -511,7 +522,8 @@ enum AtLoginFlags
AT_LOGIN_NONE = 0,
AT_LOGIN_RENAME = 1,
AT_LOGIN_RESET_SPELLS = 2,
- AT_LOGIN_RESET_TALENTS = 4
+ AT_LOGIN_RESET_TALENTS = 4,
+ AT_LOGIN_CUSTOMIZE = 8
};
typedef std::map<uint32, QuestStatusData> QuestStatusMap;
@@ -543,7 +555,7 @@ enum PlayerSlots
// first slot for item stored (in any way in player m_items data)
PLAYER_SLOT_START = 0,
// last+1 slot for item stored (in any way in player m_items data)
- PLAYER_SLOT_END = 118,
+ PLAYER_SLOT_END = 200,
PLAYER_SLOTS_COUNT = (PLAYER_SLOT_END - PLAYER_SLOT_START)
};
@@ -671,12 +683,30 @@ enum KeyRingSlots
KEYRING_SLOT_END = 118
};
+enum VanityPetSlots
+{
+ VANITYPET_SLOT_START = 118, // not use, vanity pets stored as spells
+ VANITYPET_SLOT_END = 136 // not alloed any content in.
+};
+
+enum CurrencyTokenSlots
+{
+ CURRENCYTOKEN_SLOT_START = 136,
+ CURRENCYTOKEN_SLOT_END = 168
+};
+
+enum QuestBagSlots
+{
+ QUESTBAG_SLOT_START = 168,
+ QUESTBAG_SLOT_END = 200
+};
+
struct ItemPosCount
{
- ItemPosCount(uint16 _pos, uint8 _count) : pos(_pos), count(_count) {}
+ ItemPosCount(uint16 _pos, uint32 _count) : pos(_pos), count(_count) {}
bool isContainedIn(std::vector<ItemPosCount> const& vec) const;
uint16 pos;
- uint8 count;
+ uint32 count;
};
typedef std::vector<ItemPosCount> ItemPosCountVec;
@@ -689,14 +719,15 @@ enum TradeSlots
enum TransferAbortReason
{
- TRANSFER_ABORT_MAX_PLAYERS = 0x0001, // Transfer Aborted: instance is full
- TRANSFER_ABORT_NOT_FOUND = 0x0002, // Transfer Aborted: instance not found
- TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x0003, // You have entered too many instances recently.
- TRANSFER_ABORT_ZONE_IN_COMBAT = 0x0005, // Unable to zone in while an encounter is in progress.
- TRANSFER_ABORT_INSUF_EXPAN_LVL1 = 0x0106, // You must have TBC expansion installed to access this area.
- TRANSFER_ABORT_DIFFICULTY1 = 0x0007, // Normal difficulty mode is not available for %s.
- TRANSFER_ABORT_DIFFICULTY2 = 0x0107, // Heroic difficulty mode is not available for %s.
- TRANSFER_ABORT_DIFFICULTY3 = 0x0207 // Epic difficulty mode is not available for %s.
+ TRANSFER_ABORT_ERROR = 0x00,
+ TRANSFER_ABORT_MAX_PLAYERS = 0x01, // Transfer Aborted: instance is full
+ TRANSFER_ABORT_NOT_FOUND = 0x02, // Transfer Aborted: instance not found
+ TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x03, // You have entered too many instances recently.
+ TRANSFER_ABORT_ZONE_IN_COMBAT = 0x05, // Unable to zone in while an encounter is in progress.
+ TRANSFER_ABORT_INSUF_EXPAN_LVL = 0x06, // You must have <TBC,WotLK> expansion installed to access this area.
+ TRANSFER_ABORT_DIFFICULTY = 0x07, // <Normal,Heroic,Epic> difficulty mode is not available for %s.
+ TRANSFER_ABORT_UNIQUE_MESSAGE = 0x08, // Until you've escaped TLK's grasp, you cannot leave this place!
+ TRANSFER_ABORT_TOO_MANY_REALM_INSTANCES = 0x09 // Additional instances cannot be launched, please try again later.
};
enum InstanceResetWarningType
@@ -710,15 +741,16 @@ enum InstanceResetWarningType
struct MovementInfo
{
// common
- //uint32 flags;
- uint8 unk1;
+ uint32 flags;
+ uint16 unk1;
uint32 time;
float x, y, z, o;
// transport
uint64 t_guid;
float t_x, t_y, t_z, t_o;
uint32 t_time;
- // swimming and unk
+ int8 t_seat;
+ // swimming and unknown
float s_pitch;
// last fall time
uint32 fallTime;
@@ -729,17 +761,17 @@ struct MovementInfo
MovementInfo()
{
- //flags =
+ flags = 0;
time = t_time = fallTime = 0;
unk1 = 0;
x = y = z = o = t_x = t_y = t_z = t_o = s_pitch = j_unk = j_sinAngle = j_cosAngle = j_xyspeed = u_unk1 = 0.0f;
t_guid = 0;
}
- /*void SetMovementFlags(uint32 _flags)
+ void SetMovementFlags(uint32 _flags)
{
flags = _flags;
- }*/
+ }
};
// flags that use in movement check for example at spell casting
@@ -812,10 +844,12 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16,
PLAYER_LOGIN_QUERY_LOADGUILD = 17,
PLAYER_LOGIN_QUERY_LOADARENAINFO = 18,
-
- MAX_PLAYER_LOGIN_QUERY
+ PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS = 19,
+ PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS = 20,
+ MAX_PLAYER_LOGIN_QUERY = 21
};
+
// Player summoning auto-decline time (in secs)
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
#define MAX_MONEY_AMOUNT (0x7FFFFFFF-1)
@@ -836,11 +870,9 @@ class TRINITY_DLL_SPEC PlayerTaxi
PlayerTaxi();
~PlayerTaxi() {}
// Nodes
- void InitTaxiNodesForLevel(uint32 race, uint32 level);
+ void InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint32 level);
void LoadTaxiMask(const char* data);
- void SaveTaxiMask(const char* data);
- uint32 GetTaximask( uint8 index ) const { return m_taximask[index]; }
bool IsTaximaskNodeKnown(uint32 nodeidx) const
{
uint8 field = uint8((nodeidx - 1) / 32);
@@ -862,7 +894,7 @@ class TRINITY_DLL_SPEC PlayerTaxi
void AppendTaximaskTo(ByteBuffer& data,bool all);
// Destinations
- bool LoadTaxiDestinationsFromString(const std::string& values);
+ bool LoadTaxiDestinationsFromString(const std::string& values, uint32 team);
std::string SaveTaxiDestinationsToString();
void ClearTaxiDestinations() { m_TaxiDestinations.clear(); }
@@ -876,11 +908,15 @@ class TRINITY_DLL_SPEC PlayerTaxi
return GetTaxiDestination();
}
bool empty() const { return m_TaxiDestinations.empty(); }
+
+ friend std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi);
private:
TaxiMask m_taximask;
std::deque<uint32> m_TaxiDestinations;
};
+std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi);
+
class TRINITY_DLL_SPEC Player : public Unit
{
friend class WorldSession;
@@ -898,23 +934,6 @@ class TRINITY_DLL_SPEC Player : public Unit
void AddToWorld();
void RemoveFromWorld();
- void SetViewport(uint64 guid, bool movable);
- void RemovePossess(bool attack = true);
- void StopCharmOrPossess()
- {
- if(isPossessing())
- RemovePossess(true);
- else if(GetCharm())
- Uncharm();
- }
- WorldObject* GetFarsightTarget() const;
- void ClearFarsight();
- void RemoveFarsightTarget();
- void SetFarsightTarget(WorldObject* target);
- // Controls if vision is currently on farsight object, updated in FAR_SIGHT opcode
- void SetFarsightVision(bool apply) { m_farsightVision = apply; }
- bool HasFarsightVision() const { return m_farsightVision; }
-
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0);
bool TeleportTo(WorldLocation const &loc, uint32 options = 0)
@@ -945,7 +964,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void SendInitialPacketsBeforeAddToMap();
void SendInitialPacketsAfterAddToMap();
- void SendTransferAborted(uint32 mapid, uint16 reason);
+ void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0);
void SendInstanceResetWarning(uint32 mapid, uint32 time);
bool CanInteractWithNPCs(bool alive = true) const;
@@ -958,10 +977,12 @@ class TRINITY_DLL_SPEC Player : public Unit
std::string afkMsg;
std::string dndMsg;
+ uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair);
+
PlayerSocial *GetSocial() { return m_social; }
PlayerTaxi m_taxi;
- void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(),getLevel()); }
+ void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(), getClass(), getLevel()); }
bool ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_id = 0 , Creature* npc = NULL);
// mount_id can be used in scripting calls
bool isAcceptWhispers() const { return m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS; }
@@ -1021,6 +1042,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void AddGuardian(Pet* pet) { m_guardianPets.insert(pet->GetGUID()); }
GuardianPetList const& GetGuardians() const { return m_guardianPets; }
void Uncharm();
+ uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn
void Say(const std::string& text, const uint32 language);
void Yell(const std::string& text, const uint32 language);
@@ -1055,6 +1077,7 @@ class TRINITY_DLL_SPEC Player : public Unit
bool HasBankBagSlot( uint8 slot ) const;
bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const;
bool HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem = NULL);
+ bool CanNoReagentCast(SpellEntry const* spellInfo) const;
Item* GetItemOrItemWithGemEquipped( uint32 item ) const;
uint8 CanTakeMoreSimilarItems(Item* pItem) const { return _CanTakeMoreSimilarItems(pItem->GetEntry(),pItem->GetCount(),pItem); }
uint8 CanTakeMoreSimilarItems(uint32 entry, uint32 count) const { return _CanTakeMoreSimilarItems(entry,count,NULL); }
@@ -1086,6 +1109,8 @@ class TRINITY_DLL_SPEC Player : public Unit
Item* EquipItem( uint16 pos, Item *pItem, bool update );
void AutoUnequipOffhandIfNeed();
bool StoreNewItemInBestSlots(uint32 item_id, uint32 item_count);
+ void AutoStoreLootItem(uint8 bag, uint8 slot, uint32 loot_id, LootStore const& store);
+ void AutoStoreLootItem(uint32 loot_id, LootStore const& store) { AutoStoreLootItem(NULL_BAG,NULL_SLOT,loot_id,store); }
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;
@@ -1133,6 +1158,11 @@ class TRINITY_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);
@@ -1267,6 +1297,7 @@ class TRINITY_DLL_SPEC Player : public Unit
/*********************************************************/
bool LoadFromDB(uint32 guid, SqlQueryHolder *holder);
+
bool MinimalLoadFromDB(QueryResult *result, uint32 guid);
static bool LoadValuesArrayFromDB(Tokens& data,uint64 guid);
static uint32 GetUInt32ValueFromArray(Tokens const& data, uint16 index);
@@ -1288,6 +1319,7 @@ class TRINITY_DLL_SPEC Player : public Unit
static void SetFloatValueInArray(Tokens& data,uint16 index, float value);
static void SetUInt32ValueInDB(uint16 index, uint32 value, uint64 guid);
static void SetFloatValueInDB(uint16 index, float value, uint64 guid);
+ static void Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair);
static void SavePositionInDB(uint32 mapid, float x,float y,float z,float o,uint32 zone,uint64 guid);
bool m_mailsLoaded;
@@ -1344,7 +1376,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void SetSelection(const uint64 &guid) { m_curSelection = guid; SetUInt64Value(UNIT_FIELD_TARGET, guid); }
uint8 GetComboPoints() { return m_comboPoints; }
- uint64 GetComboTarget() { return m_comboTarget; }
+ const uint64& GetComboTarget() const { return m_comboTarget; }
void AddComboPoints(Unit* target, int8 count);
void ClearComboPoints();
@@ -1380,10 +1412,7 @@ class TRINITY_DLL_SPEC Player : public Unit
Item* GetMItem(uint32 id)
{
ItemMap::const_iterator itr = mMitems.find(id);
- if (itr != mMitems.end())
- return itr->second;
-
- return NULL;
+ return itr != mMitems.end() ? itr->second : NULL;
}
void AddMItem(Item* it)
@@ -1395,30 +1424,28 @@ class TRINITY_DLL_SPEC Player : public Unit
bool RemoveMItem(uint32 id)
{
- ItemMap::iterator i = mMitems.find(id);
- if (i == mMitems.end())
- return false;
-
- mMitems.erase(i);
- return true;
+ return mMitems.erase(id) ? true : false;
}
void PetSpellInitialize();
void CharmSpellInitialize();
void PossessSpellInitialize();
bool HasSpell(uint32 spell) const;
+ bool HasActiveSpell(uint32 spell) const; // show in spellbook
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const;
bool IsSpellFitByClassAndRace( uint32 spell_id ) const;
+ bool IsNeedCastPassiveSpellAtLearn(SpellEntry const* spellInfo) const;
void SendProficiency(uint8 pr1, uint32 pr2);
void SendInitialSpells();
- bool addSpell(uint32 spell_id, bool active, bool learning = true, bool loading = false, uint16 slot_id=SPELL_WITHOUT_SLOT_ID, bool disabled = false);
- void learnSpell(uint32 spell_id);
- void removeSpell(uint32 spell_id, bool disabled = false);
+ bool addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled);
+ void learnSpell(uint32 spell_id, bool dependent);
+ void removeSpell(uint32 spell_id, bool disabled = false, bool update_action_bar_for_low_rank = false);
void resetSpells();
- void learnDefaultSpells(bool loading = false);
+ void learnDefaultSpells();
void learnQuestRewardedSpells();
void learnQuestRewardedSpells(Quest const* quest);
+ void learnSpellHighRank(uint32 spellid);
uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); }
void SetFreeTalentPoints(uint32 points) { SetUInt32Value(PLAYER_CHARACTER_POINTS1,points); }
@@ -1426,6 +1453,14 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 resetTalentsCost() const;
void InitTalentForLevel();
+ uint32 CalculateTalentsPoints() const;
+
+ void InitGlyphsForLevel();
+ void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); }
+ uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
+ void SetGlyph(uint8 slot, uint32 glyph) { SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); }
+ uint32 GetGlyph(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot); }
+
uint32 GetFreePrimaryProffesionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); }
void SetFreePrimaryProffesions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2,profs); }
void InitPrimaryProffesions();
@@ -1434,8 +1469,6 @@ class TRINITY_DLL_SPEC Player : public Unit
PlayerSpellMap & GetSpellMap() { return m_spells; }
void AddSpellMod(SpellModifier* mod, bool apply);
- int32 GetTotalFlatMods(uint32 spellId, SpellModOp op);
- int32 GetTotalPctMods(uint32 spellId, SpellModOp op);
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL);
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL);
void RemoveSpellMods(Spell const* spell);
@@ -1540,6 +1573,7 @@ class TRINITY_DLL_SPEC Player : public Unit
static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot);
void SetArenaTeamIdInvited(uint32 ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; }
uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; }
+ static void LeaveAllArenaTeams(uint64 guid);
void SetDifficulty(uint32 dungeon_difficulty) { m_dungeonDifficulty = dungeon_difficulty; }
uint8 GetDifficulty() { return m_dungeonDifficulty; }
@@ -1565,9 +1599,12 @@ class TRINITY_DLL_SPEC Player : public Unit
void UpdateArmor();
void UpdateMaxHealth();
void UpdateMaxPower(Powers power);
+ void ApplyFeralAPBonus(int32 amount, bool apply);
void UpdateAttackPowerAndDamage(bool ranged = false);
void UpdateShieldBlockValue();
void UpdateDamagePhysical(WeaponAttackType attType);
+ void ApplySpellDamageBonus(int32 amount, bool apply);
+ void ApplySpellHealingBonus(int32 amount, bool apply);
void UpdateSpellDamageAndHealingBonus();
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage);
@@ -1585,6 +1622,8 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 GetRangedCritDamageReduction(uint32 damage) const;
uint32 GetSpellCritDamageReduction(uint32 damage) const;
uint32 GetDotDamageReduction(uint32 damage) const;
+ uint32 GetBaseSpellDamageBonus() { return m_baseSpellDamage;}
+ uint32 GetBaseSpellHealingBonus() { return m_baseSpellHealing;}
float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
void UpdateBlockPercentage();
@@ -1592,9 +1631,14 @@ class TRINITY_DLL_SPEC Player : public Unit
void UpdateAllCritPercentages();
void UpdateParryPercentage();
void UpdateDodgePercentage();
+ void UpdateMeleeHitChances();
+ void UpdateRangedHitChances();
+ void UpdateSpellHitChances();
+
void UpdateAllSpellCritChances();
void UpdateSpellCritChance(uint32 school);
void UpdateExpertise(WeaponAttackType attType);
+ void ApplyManaRegenBonus(int32 amount, bool apply);
void UpdateManaRegen();
const uint64& GetLootGUID() const { return m_lootGuid; }
@@ -1671,18 +1715,18 @@ class TRINITY_DLL_SPEC Player : public Unit
void UpdateDefense();
void UpdateWeaponSkill (WeaponAttackType attType);
- void UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, MeleeHitOutcome outcome, bool defence);
+ void UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, bool defence);
void SetSkill(uint32 id, uint16 currVal, uint16 maxVal);
- uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus
+ uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + temp bonus
uint16 GetPureMaxSkillValue(uint32 skill) const; // max
uint16 GetSkillValue(uint32 skill) const; // skill value + perm. bonus + temp bonus
uint16 GetBaseSkillValue(uint32 skill) const; // skill value + perm. bonus
uint16 GetPureSkillValue(uint32 skill) const; // skill value
+ int16 GetSkillPermBonusValue(uint32 skill) const;
int16 GetSkillTempBonusValue(uint32 skill) const;
bool HasSkill(uint32 skill) const;
- void learnSkillRewardedSpells( uint32 id );
- void learnSkillRewardedSpells();
+ void learnSkillRewardedSpells(uint32 id, uint32 value);
void SetDontMove(bool dontMove);
bool GetDontMove() const { return m_dontMove; }
@@ -1696,6 +1740,7 @@ class TRINITY_DLL_SPEC Player : public Unit
bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const;
bool RewardPlayerAndGroupAtKill(Unit* pVictim);
+ bool isHonorOrXPTarget(Unit* pVictim);
FactionStateList m_factions;
ForcedReactions m_forcedReactions;
@@ -1762,6 +1807,8 @@ class TRINITY_DLL_SPEC Player : public Unit
void SetCanParry(bool value);
bool CanBlock() const { return m_canBlock; }
void SetCanBlock(bool value);
+ bool CanTitanGrip() const { return m_canTitanGrip ; }
+ void SetCanTitanGrip(bool value) { m_canTitanGrip = value; }
void SetRegularAttackTime();
void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; }
@@ -1790,12 +1837,13 @@ class TRINITY_DLL_SPEC Player : public Unit
void ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply, bool form_change = false);
void UpdateEquipSpellsAtFormChange();
void CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType);
+ void CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 cast_count, uint32 glyphIndex);
void SendInitWorldStates(bool force = false, uint32 forceZoneId = 0);
void SendUpdateWorldState(uint32 Field, uint32 Value);
void SendDirectMessage(WorldPacket *data);
- void SendAuraDurationsForTarget(Unit* target);
+ void SendAurasForTarget(Unit *target);
PlayerMenu* PlayerTalkClass;
std::vector<ItemSetEffect *> ItemSetEff;
@@ -1956,6 +2004,7 @@ class TRINITY_DLL_SPEC Player : public Unit
MovementInfo m_movementInfo;
uint32 m_lastFallTime;
float m_lastFallZ;
+ Unit *m_mover;
void SetFallInformation(uint32 time, float z)
{
m_lastFallTime = time;
@@ -1966,6 +2015,7 @@ class TRINITY_DLL_SPEC Player : public Unit
bool CanFly() const { return HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); }
bool IsFlying() const { return HasUnitMovementFlag(MOVEMENTFLAG_FLYING); }
+ bool IsAllowUseFlyMountsHere() const;
void HandleDrowning();
void HandleFallDamage(MovementInfo& movementInfo);
@@ -1973,8 +2023,30 @@ class TRINITY_DLL_SPEC Player : public Unit
void SetClientControl(Unit* target, uint8 allowMove);
+ void EnterVehicle(Vehicle *vehicle);
+ void ExitVehicle(Vehicle *vehicle);
+
+ //void SetViewport(uint64 guid, bool movable);
+ void SetMover(Unit* target) { m_mover = target ? target : this; }
+ void RemovePossess(bool attack = true);
+ void StopCharmOrPossess()
+ {
+ if(isPossessing())
+ RemovePossess(true);
+ else if(GetCharm())
+ Uncharm();
+ }
+
uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); }
- void SetFarSight(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); }
+ void SetFarSightGUID(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); }
+ void SetBindSight(Unit *target);
+ WorldObject* GetFarsightTarget() const;
+ void ClearFarsight();
+ void RemoveFarsightTarget();
+ void SetFarsightTarget(WorldObject* target);
+ // Controls if vision is currently on farsight object, updated in FAR_SIGHT opcode
+ void SetFarsightVision(bool apply) { m_farsightVision = apply; }
+ bool HasFarsightVision() const { return m_farsightVision; }
// Transports
Transport * GetTransport() const { return m_transport; }
@@ -1985,6 +2057,7 @@ class TRINITY_DLL_SPEC Player : public Unit
float GetTransOffsetZ() const { return m_movementInfo.t_z; }
float GetTransOffsetO() const { return m_movementInfo.t_o; }
uint32 GetTransTime() const { return m_movementInfo.t_time; }
+ int8 GetTransSeat() const { return m_movementInfo.t_seat; }
uint32 GetSaveTimer() const { return m_nextSave; }
void SetSaveTimer(uint32 timer) { m_nextSave = timer; }
@@ -2036,7 +2109,6 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 GetOldPetSpell() const { return m_oldpetspell; }
void SetOldPetSpell(uint32 petspell) { m_oldpetspell = petspell; }
-
/*********************************************************/
/*** INSTANCE SYSTEM ***/
/*********************************************************/
@@ -2069,9 +2141,9 @@ class TRINITY_DLL_SPEC Player : public Unit
GroupReference& GetGroupRef() { return m_group; }
void SetGroup(Group *group, int8 subgroup = -1);
uint8 GetSubGroup() const { return m_group.getSubGroup(); }
- uint32 GetGroupUpdateFlag() { return m_groupUpdateMask; }
+ uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; }
void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; }
- uint64 GetAuraUpdateMask() { return m_auraUpdateMask; }
+ const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; }
void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); }
void UnsetAuraUpdateMask(uint8 slot) { m_auraUpdateMask &= ~(uint64(1) << slot); }
Player* GetNextRandomRaidMember(float radius);
@@ -2085,6 +2157,18 @@ class TRINITY_DLL_SPEC Player : public Unit
WorldLocation& GetTeleportDest() { return m_teleport_dest; }
DeclinedName const* GetDeclinedNames() const { return m_declinedname; }
+ uint8 GetRunesState() const { return m_runes->runeState; }
+ uint8 GetBaseRune(uint8 index) const { return m_runes->runes[index].BaseRune; }
+ uint8 GetCurrentRune(uint8 index) const { return m_runes->runes[index].CurrentRune; }
+ uint8 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; }
+ void SetBaseRune(uint8 index, uint8 baseRune) { m_runes->runes[index].BaseRune = baseRune; }
+ void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].CurrentRune = currentRune; }
+ void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); }
+ void ConvertRune(uint8 index, uint8 newType);
+ void ResyncRunes(uint8 count);
+ void AddRunePower(uint8 index);
+ void InitRunes();
+ AchievementMgr& GetAchievementMgr() { return m_achievementMgr; }
bool HasTitle(uint32 bitIndex);
bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); }
void SetTitle(CharTitlesEntry const* title);
@@ -2134,6 +2218,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void _LoadActions(QueryResult *result);
void _LoadAuras(QueryResult *result, uint32 timediff);
+ void _LoadGlyphAuras();
void _LoadBoundInstances(QueryResult *result);
void _LoadInventory(QueryResult *result, uint32 timediff);
void _LoadMailInit(QueryResult *resultUnread, QueryResult *resultDelivery);
@@ -2143,6 +2228,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void _LoadDailyQuestStatus(QueryResult *result);
void _LoadGroup(QueryResult *result);
void _LoadReputation(QueryResult *result);
+ void _LoadSkills();
void _LoadSpells(QueryResult *result);
void _LoadTutorials(QueryResult *result);
void _LoadFriendList(QueryResult *result);
@@ -2184,7 +2270,6 @@ class TRINITY_DLL_SPEC Player : public Unit
time_t m_lastHonorUpdateTime;
void outDebugValues() const;
- bool _removeSpell(uint16 spell_id);
uint64 m_lootGuid;
uint32 m_race;
@@ -2221,6 +2306,11 @@ class TRINITY_DLL_SPEC Player : public Unit
ActionButtonList m_actionButtons;
float m_auraBaseMod[BASEMOD_END][MOD_END];
+ int16 m_baseRatingValue[MAX_COMBAT_RATING];
+ uint16 m_baseSpellDamage;
+ uint16 m_baseSpellHealing;
+ uint16 m_baseFeralAP;
+ uint16 m_baseManaRegen;
SpellModList m_spellMods[MAX_SPELLMOD];
int32 m_SpellModRemoveCount;
@@ -2254,7 +2344,6 @@ class TRINITY_DLL_SPEC Player : public Unit
bool m_DailyQuestChanged;
time_t m_lastDailyQuestTime;
- uint32 m_regenTimer;
uint32 m_breathTimer;
uint32 m_drunkTimer;
uint16 m_drunk;
@@ -2273,8 +2362,10 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 m_ArmorProficiency;
bool m_canParry;
bool m_canBlock;
+ bool m_canTitanGrip;
uint8 m_swingErrorMsg;
float m_ammoDPS;
+
////////////////////Rest System/////////////////////
int time_inn_enter;
uint32 inn_pos_mapid;
@@ -2291,6 +2382,7 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 m_resetTalentsCost;
time_t m_resetTalentsTime;
uint32 m_usedTalentCount;
+ uint32 m_questRewardTalentCount;
// Social
PlayerSocial *m_social;
@@ -2321,6 +2413,8 @@ class TRINITY_DLL_SPEC Player : public Unit
bool m_farsightVision;
DeclinedName *m_declinedname;
+ Runes *m_runes;
+ AchievementMgr m_achievementMgr;
private:
// internal common parts for CanStore/StoreItem functions
uint8 _CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool swap, Item *pSrcItem ) const;
diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp
index 9f9eecc2234..983135fdc24 100644
--- a/src/game/QueryHandler.cpp
+++ b/src/game/QueryHandler.cpp
@@ -33,6 +33,7 @@
#include "NPCHandler.h"
#include "ObjectAccessor.h"
#include "Pet.h"
+#include "MapManager.h"
void WorldSession::SendNameQueryOpcode(Player *p)
{
@@ -185,7 +186,6 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data )
data << (uint32)ci->type;
data << (uint32)ci->family; // family wdbFeild9
data << (uint32)ci->rank; // rank wdbFeild10
- data << (uint32)0; // unknown wdbFeild11
data << (uint32)ci->PetSpellDataId; // Id from CreatureSpellData.dbc wdbField12
data << (uint32)ci->Modelid1; // Modelid1
data << (uint32)ci->Modelid2; // Modelid2
@@ -276,20 +276,43 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/)
Corpse *corpse = GetPlayer()->GetCorpse();
- uint8 found = 1;
if(!corpse)
- found = 0;
+ {
+ WorldPacket data(MSG_CORPSE_QUERY, 1);
+ data << uint8(0); // corpse not found
+ SendPacket(&data);
+ return;
+ }
- WorldPacket data(MSG_CORPSE_QUERY, (1+found*(5*4)));
- data << uint8(found);
- if(found)
+ int32 mapid = corpse->GetMapId();
+ float x = corpse->GetPositionX();
+ float y = corpse->GetPositionY();
+ float z = corpse->GetPositionZ();
+ int32 corpsemapid = _player->GetMapId();
+
+ if(Map *map = MapManager::Instance().FindMap(corpse->GetMapId(), corpse->GetInstanceId()))
{
- data << corpse->GetMapId();
- data << corpse->GetPositionX();
- data << corpse->GetPositionY();
- data << corpse->GetPositionZ();
- data << _player->GetMapId();
+ if(map->IsDungeon())
+ {
+ if(!map->GetEntrancePos(mapid, x, y))
+ return;
+
+ Map *entrance_map = MapManager::Instance().GetMap(mapid, _player);
+ if(!entrance_map)
+ return;
+
+ z = entrance_map->GetHeight(x, y, MAX_HEIGHT);
+ corpsemapid = corpse->GetMapId();
+ }
}
+
+ WorldPacket data(MSG_CORPSE_QUERY, 1+(5*4));
+ data << uint8(1); // corpse found
+ data << int32(mapid);
+ data << float(x);
+ data << float(y);
+ data << float(z);
+ data << int32(corpsemapid);
SendPacket(&data);
}
diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp
index 4dd202bc344..42ff15e1679 100644
--- a/src/game/QuestDef.cpp
+++ b/src/game/QuestDef.cpp
@@ -44,88 +44,90 @@ Quest::Quest(Field * questRecord)
QuestFlags = questRecord[17].GetUInt16();
uint32 SpecialFlags = questRecord[18].GetUInt16();
CharTitleId = questRecord[19].GetUInt32();
- PrevQuestId = questRecord[20].GetInt32();
- NextQuestId = questRecord[21].GetInt32();
- ExclusiveGroup = questRecord[22].GetInt32();
- NextQuestInChain = questRecord[23].GetUInt32();
- SrcItemId = questRecord[24].GetUInt32();
- SrcItemCount = questRecord[25].GetUInt32();
- SrcSpell = questRecord[26].GetUInt32();
- Title = questRecord[27].GetCppString();
- Details = questRecord[28].GetCppString();
- Objectives = questRecord[29].GetCppString();
- OfferRewardText = questRecord[30].GetCppString();
- RequestItemsText = questRecord[31].GetCppString();
- EndText = questRecord[32].GetCppString();
+ PlayersSlain = questRecord[20].GetUInt32();
+ BonusTalents = questRecord[21].GetUInt32();
+ PrevQuestId = questRecord[22].GetInt32();
+ NextQuestId = questRecord[23].GetInt32();
+ ExclusiveGroup = questRecord[24].GetInt32();
+ NextQuestInChain = questRecord[25].GetUInt32();
+ SrcItemId = questRecord[26].GetUInt32();
+ SrcItemCount = questRecord[27].GetUInt32();
+ SrcSpell = questRecord[28].GetUInt32();
+ Title = questRecord[29].GetCppString();
+ Details = questRecord[30].GetCppString();
+ Objectives = questRecord[31].GetCppString();
+ OfferRewardText = questRecord[32].GetCppString();
+ RequestItemsText = questRecord[33].GetCppString();
+ EndText = questRecord[34].GetCppString();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ObjectiveText[i] = questRecord[33+i].GetCppString();
+ ObjectiveText[i] = questRecord[35+i].GetCppString();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ReqItemId[i] = questRecord[37+i].GetUInt32();
+ ReqItemId[i] = questRecord[39+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ReqItemCount[i] = questRecord[41+i].GetUInt32();
+ ReqItemCount[i] = questRecord[43+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- ReqSourceId[i] = questRecord[45+i].GetUInt32();
+ ReqSourceId[i] = questRecord[47+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- ReqSourceCount[i] = questRecord[49+i].GetUInt32();
+ ReqSourceCount[i] = questRecord[51+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- ReqSourceRef[i] = questRecord[53+i].GetUInt32();
+ ReqSourceRef[i] = questRecord[55+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ReqCreatureOrGOId[i] = questRecord[57+i].GetInt32();
+ ReqCreatureOrGOId[i] = questRecord[59+i].GetInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ReqCreatureOrGOCount[i] = questRecord[61+i].GetUInt32();
+ ReqCreatureOrGOCount[i] = questRecord[63+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ReqSpell[i] = questRecord[65+i].GetUInt32();
+ ReqSpell[i] = questRecord[67+i].GetUInt32();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- RewChoiceItemId[i] = questRecord[69+i].GetUInt32();
+ RewChoiceItemId[i] = questRecord[71+i].GetUInt32();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- RewChoiceItemCount[i] = questRecord[75+i].GetUInt32();
+ RewChoiceItemCount[i] = questRecord[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();
-
- RewHonorableKills = questRecord[99].GetUInt32();
- RewOrReqMoney = questRecord[100].GetInt32();
- RewMoneyMaxLevel = questRecord[101].GetUInt32();
- RewSpell = questRecord[102].GetUInt32();
- RewSpellCast = questRecord[103].GetUInt32();
- RewMailTemplateId = questRecord[104].GetUInt32();
- RewMailDelaySecs = questRecord[105].GetUInt32();
- PointMapId = questRecord[106].GetUInt32();
- PointX = questRecord[107].GetFloat();
- PointY = questRecord[108].GetFloat();
- PointOpt = questRecord[109].GetUInt32();
+ RewRepValue[i] = questRecord[96+i].GetInt32();
+
+ 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;
@@ -164,18 +166,19 @@ uint32 Quest::XPValue( Player *pPlayer ) const
uint32 pLevel = pPlayer->getLevel();
uint32 qLevel = QuestLevel;
float fullxp = 0;
- if (qLevel >= 65)
+ if (qLevel >= 75)
fullxp = RewMoneyMaxLevel / 6.0f;
- else if (qLevel == 64)
+ else if (qLevel == 74)
fullxp = RewMoneyMaxLevel / 4.8f;
- else if (qLevel == 63)
+ else if (qLevel == 73)
fullxp = RewMoneyMaxLevel / 3.6f;
- else if (qLevel == 62)
+ else if (qLevel == 72)
fullxp = RewMoneyMaxLevel / 2.4f;
- else if (qLevel == 61)
+ else if (qLevel == 71)
fullxp = RewMoneyMaxLevel / 1.2f;
- else if (qLevel > 0 && qLevel <= 60)
+ else if (qLevel > 0 && qLevel <= 70)
fullxp = RewMoneyMaxLevel / 0.6f;
+ // FIXME: for <=65 need possible additional cases
if( pLevel <= qLevel + 5 )
return (uint32)fullxp;
diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h
index 52f58c2c87e..1904cbe08a8 100644
--- a/src/game/QuestDef.h
+++ b/src/game/QuestDef.h
@@ -44,30 +44,33 @@ class ObjectMgr;
enum QuestFailedReasons
{
INVALIDREASON_DONT_HAVE_REQ = 0,
- INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, //You are not high enough level for that quest.
- INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, //That quest is not available to your race.
- INVALIDREASON_QUEST_ALREADY_DONE = 7, //You have completed that quest.
- INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, //You can only be on one timed quest at a time.
- INVALIDREASON_QUEST_ALREADY_ON = 13, //You are already on that quest
- INVALIDREASON_QUEST_FAILED_EXPANSION = 16, //This quest requires an expansion enabled account.
- INVALIDREASON_QUEST_ALREADY_ON2 = 18, //You are already on that quest
- INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, //You don't have the required items with you. Check storage.
- INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, //You don't have enough money for that quest.
- INVALIDREASON_DAILY_QUESTS_REMAINING = 26, //You have already completed 10 daily quests today
- INVALIDREASON_QUEST_FAILED_CAIS = 27, //You cannot complete quests once you have reached tired time
+ INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, // You are not high enough level for that quest.
+ INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, // That quest is not available to your race.
+ INVALIDREASON_QUEST_ALREADY_DONE = 7, // You have completed that quest.
+ INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, // You can only be on one timed quest at a time.
+ INVALIDREASON_QUEST_ALREADY_ON = 13, // You are already on that quest.
+ INVALIDREASON_QUEST_FAILED_EXPANSION = 16, // This quest requires an expansion enabled account.
+ INVALIDREASON_QUEST_ALREADY_ON2 = 18, // You are already on that quest.
+ INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, // You don't have the required items with you. Check storage.
+ INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, // You don't have enough money for that quest.
+ INVALIDREASON_DAILY_QUESTS_REMAINING = 26, // You have already completed 25 daily quests today.
+ INVALIDREASON_QUEST_FAILED_CAIS = 27, // You cannot complete quests once you have reached tired time.
+ INVALIDREASON_DAILY_QUEST_COMPLETED_TODAY = 29 // You have completed that daily quest today.
};
enum QuestShareMessages
{
- QUEST_PARTY_MSG_SHARING_QUEST = 0,
- QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1,
- QUEST_PARTY_MSG_ACCEPT_QUEST = 2,
- QUEST_PARTY_MSG_REFUSE_QUEST = 3,
- QUEST_PARTY_MSG_TOO_FAR = 4,
- QUEST_PARTY_MSG_BUSY = 5,
- QUEST_PARTY_MSG_LOG_FULL = 6,
- QUEST_PARTY_MSG_HAVE_QUEST = 7,
- QUEST_PARTY_MSG_FINISH_QUEST = 8,
+ QUEST_PARTY_MSG_SHARING_QUEST = 0,
+ QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1,
+ QUEST_PARTY_MSG_ACCEPT_QUEST = 2,
+ QUEST_PARTY_MSG_DECLINE_QUEST = 3,
+ QUEST_PARTY_MSG_BUSY = 4,
+ QUEST_PARTY_MSG_LOG_FULL = 5,
+ QUEST_PARTY_MSG_HAVE_QUEST = 6,
+ QUEST_PARTY_MSG_FINISH_QUEST = 7,
+ QUEST_PARTY_MSG_CANT_BE_SHARED_TODAY = 8,
+ QUEST_PARTY_MSG_SHARING_TIMER_EXPIRED = 9,
+ QUEST_PARTY_MSG_NOT_IN_PARTY = 10
};
enum __QuestTradeSkill
@@ -190,6 +193,8 @@ class Quest
int32 GetExclusiveGroup() const { return ExclusiveGroup; }
uint32 GetNextQuestInChain() const { return NextQuestInChain; }
uint32 GetCharTitleId() const { return CharTitleId; }
+ uint32 GetPlayersSlain() const { return PlayersSlain; }
+ uint32 GetBonusTalents() const { return BonusTalents; }
uint32 GetSrcItemId() const { return SrcItemId; }
uint32 GetSrcItemCount() const { return SrcItemCount; }
uint32 GetSrcSpell() const { return SrcSpell; }
@@ -277,6 +282,8 @@ class Quest
uint32 LimitTime;
uint32 QuestFlags;
uint32 CharTitleId;
+ uint32 PlayersSlain;
+ uint32 BonusTalents;
int32 PrevQuestId;
int32 NextQuestId;
int32 ExclusiveGroup;
diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp
index abb285e6dbb..e88af8c5a67 100644
--- a/src/game/QuestHandler.cpp
+++ b/src/game/QuestHandler.cpp
@@ -180,7 +180,7 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode( WorldPacket & recv_data )
bool destroyItem = true;
for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
{
- if ((qInfo->ReqItemId[i] == ((Item*)pObject)->GetEntry()) && (((Item*)pObject)->GetProto()->MaxCount != 0))
+ if ((qInfo->ReqItemId[i] == ((Item*)pObject)->GetEntry()) && (((Item*)pObject)->GetProto()->MaxCount > 0))
{
destroyItem = false;
break;
@@ -451,12 +451,6 @@ void WorldSession::HandleQuestPushToParty(WorldPacket& recvPacket)
_player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_SHARING_QUEST);
- if( _player->GetDistance( pPlayer ) > 10 )
- {
- _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_TOO_FAR );
- continue;
- }
-
if( !pPlayer->SatisfyQuestStatus( pQuest, false ) )
{
_player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_HAVE_QUEST );
diff --git a/src/game/ScriptCalls.cpp b/src/game/ScriptCalls.cpp
index 8c763809f63..693f27b1fb0 100644
--- a/src/game/ScriptCalls.cpp
+++ b/src/game/ScriptCalls.cpp
@@ -86,7 +86,8 @@ bool LoadScriptingModule(char const* libName)
return false;
}
- printf("Scripts Library %s was successfully loaded.\n",name.c_str());
+ sLog.outString();
+ sLog.outString( ">>> Scripts Library %s was successfully loaded.\n", name.c_str() );
//heh we are still there :P we have a valid library
//we reload script
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index 03149d078ab..b08bb45e322 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -24,6 +24,9 @@
#include "Platform/Define.h"
#include <cassert>
+#define MaNGOS Trinity
+#define GetMangosString GetTrinityString
+
enum Gender
{
GENDER_MALE = 0,
@@ -88,7 +91,8 @@ enum Classes
#define CLASSMASK_ALL_PLAYABLE \
((1<<(CLASS_WARRIOR-1))|(1<<(CLASS_PALADIN-1))|(1<<(CLASS_HUNTER-1))| \
(1<<(CLASS_ROGUE-1)) |(1<<(CLASS_PRIEST-1)) |(1<<(CLASS_SHAMAN-1))| \
- (1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) )
+ (1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) | \
+ (1<<(CLASS_DEATH_KNIGHT-1)) )
#define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1)))
@@ -134,11 +138,12 @@ enum Powers
POWER_FOCUS = 2,
POWER_ENERGY = 3,
POWER_HAPPINESS = 4,
- POWER_RUNES = 5,
+ POWER_RUNE = 5,
+ POWER_RUNIC_POWER = 6,
POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value)
};
-#define MAX_POWERS 5 // not count POWER_RUNES for now
+#define MAX_POWERS 7
enum SpellSchools
{
@@ -199,10 +204,11 @@ enum ItemQualities
ITEM_QUALITY_RARE = 3, //BLUE
ITEM_QUALITY_EPIC = 4, //PURPLE
ITEM_QUALITY_LEGENDARY = 5, //ORANGE
- ITEM_QUALITY_ARTIFACT = 6 //LIGHT YELLOW
+ ITEM_QUALITY_ARTIFACT = 6, //LIGHT YELLOW
+ ITEM_QUALITY_HEIRLOOM = 7
};
-#define MAX_ITEM_QUALITY 7
+#define MAX_ITEM_QUALITY 8
enum SpellCategory
{
@@ -217,7 +223,7 @@ enum SpellCategory
#define SPELL_ATTR_UNK0 0x00000001 // 0
#define SPELL_ATTR_RANGED 0x00000002 // 1 All ranged abilities have this flag
#define SPELL_ATTR_ON_NEXT_SWING_1 0x00000004 // 2 on next swing
-#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 2.4.2
+#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 3.0.3
#define SPELL_ATTR_UNK4 0x00000010 // 4
#define SPELL_ATTR_UNK5 0x00000020 // 5 trade spells?
#define SPELL_ATTR_PASSIVE 0x00000040 // 6 Passive spell
@@ -257,7 +263,7 @@ enum SpellCategory
#define SPELL_ATTR_EX_NEGATIVE 0x00000080 // 7
#define SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET 0x00000100 // 8 Spell req target not to be in combat state
#define SPELL_ATTR_EX_UNK9 0x00000200 // 9
-#define SPELL_ATTR_EX_UNK10 0x00000400 // 10
+#define SPELL_ATTR_EX_NO_INITIAL_AGGRO 0x00000400 // 10 no generates threat on cast 100%
#define SPELL_ATTR_EX_UNK11 0x00000800 // 11
#define SPELL_ATTR_EX_UNK12 0x00001000 // 12
#define SPELL_ATTR_EX_UNK13 0x00002000 // 13
@@ -272,7 +278,7 @@ enum SpellCategory
#define SPELL_ATTR_EX_REQ_COMBO_POINTS2 0x00400000 // 22 Req combo points on target
#define SPELL_ATTR_EX_UNK23 0x00800000 // 23
#define SPELL_ATTR_EX_UNK24 0x01000000 // 24 Req fishing pole??
-#define SPELL_ATTR_EX_UNK25 0x02000000 // 25 not set in 2.4.2
+#define SPELL_ATTR_EX_UNK25 0x02000000 // 25
#define SPELL_ATTR_EX_UNK26 0x04000000 // 26
#define SPELL_ATTR_EX_UNK27 0x08000000 // 27
#define SPELL_ATTR_EX_UNK28 0x10000000 // 28
@@ -282,20 +288,20 @@ enum SpellCategory
#define SPELL_ATTR_EX2_UNK0 0x00000001 // 0
#define SPELL_ATTR_EX2_UNK1 0x00000002 // 1
-#define SPELL_ATTR_EX2_UNK2 0x00000004 // 2 boss spells?
+#define SPELL_ATTR_EX2_CANT_REFLECTED 0x00000004 // 2 ? used for detect can or not spell reflected
#define SPELL_ATTR_EX2_UNK3 0x00000008 // 3
#define SPELL_ATTR_EX2_UNK4 0x00000010 // 4
-#define SPELL_ATTR_EX2_UNK5 0x00000020 // 5
+#define SPELL_ATTR_EX2_AUTOREPEAT_FLAG 0x00000020 // 5
#define SPELL_ATTR_EX2_UNK6 0x00000040 // 6
#define SPELL_ATTR_EX2_UNK7 0x00000080 // 7
-#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 2.4.2
+#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 3.0.3
#define SPELL_ATTR_EX2_UNK9 0x00000200 // 9
#define SPELL_ATTR_EX2_UNK10 0x00000400 // 10
#define SPELL_ATTR_EX2_HEALTH_FUNNEL 0x00000800 // 11
#define SPELL_ATTR_EX2_UNK12 0x00001000 // 12
#define SPELL_ATTR_EX2_UNK13 0x00002000 // 13
#define SPELL_ATTR_EX2_UNK14 0x00004000 // 14
-#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 2.4.2
+#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 3.0.3
#define SPELL_ATTR_EX2_TAME_BEAST 0x00010000 // 16
#define SPELL_ATTR_EX2_NOT_RESET_AUTOSHOT 0x00020000 // 17 Hunters Shot and Stings only have this flag
#define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet
@@ -308,7 +314,7 @@ enum SpellCategory
#define SPELL_ATTR_EX2_UNK25 0x02000000 // 25
#define SPELL_ATTR_EX2_UNK26 0x04000000 // 26 unaffected by school immunity
#define SPELL_ATTR_EX2_UNK27 0x08000000 // 27
-#define SPELL_ATTR_EX2_UNK28 0x10000000 // 28
+#define SPELL_ATTR_EX2_UNK28 0x10000000 // 28 no breaks stealth if it fails??
#define SPELL_ATTR_EX2_CANT_CRIT 0x20000000 // 29 Spell can't crit
#define SPELL_ATTR_EX2_UNK30 0x40000000 // 30
#define SPELL_ATTR_EX2_FOOD 0x80000000 // 31 food, well-fed, and a few others
@@ -329,8 +335,8 @@ enum SpellCategory
#define SPELL_ATTR_EX3_UNK13 0x00002000 // 13
#define SPELL_ATTR_EX3_UNK14 0x00004000 // 14 "Honorless Target" only this spells have this flag
#define SPELL_ATTR_EX3_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag
-#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16
-#define SPELL_ATTR_EX3_NO_INITIAL_AGGRO 0x00020000 // 17 no initial aggro
+#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 no triggers effects that trigger on casting a spell??
+#define SPELL_ATTR_EX3_UNK17 0x00020000 // 17 no triggers effects that trigger on casting a spell??
#define SPELL_ATTR_EX3_UNK18 0x00040000 // 18
#define SPELL_ATTR_EX3_UNK19 0x00080000 // 19
#define SPELL_ATTR_EX3_DEATH_PERSISTENT 0x00100000 // 20 Death persistent spells
@@ -338,7 +344,7 @@ enum SpellCategory
#define SPELL_ATTR_EX3_REQ_WAND 0x00400000 // 22 Req wand
#define SPELL_ATTR_EX3_UNK23 0x00800000 // 23
#define SPELL_ATTR_EX3_REQ_OFFHAND 0x01000000 // 24 Req offhand weapon
-#define SPELL_ATTR_EX3_UNK25 0x02000000 // 25
+#define SPELL_ATTR_EX3_UNK25 0x02000000 // 25 no cause spell pushback ?
#define SPELL_ATTR_EX3_UNK26 0x04000000 // 26
#define SPELL_ATTR_EX3_UNK27 0x08000000 // 27
#define SPELL_ATTR_EX3_UNK28 0x10000000 // 28
@@ -350,7 +356,7 @@ enum SpellCategory
#define SPELL_ATTR_EX4_UNK1 0x00000002 // 1 proc on finishing move?
#define SPELL_ATTR_EX4_UNK2 0x00000004 // 2
#define SPELL_ATTR_EX4_UNK3 0x00000008 // 3
-#define SPELL_ATTR_EX4_UNK4 0x00000010 // 4
+#define SPELL_ATTR_EX4_UNK4 0x00000010 // 4 This will no longer cause guards to attack on use??
#define SPELL_ATTR_EX4_UNK5 0x00000020 // 5
#define SPELL_ATTR_EX4_UNK6 0x00000040 // 6
#define SPELL_ATTR_EX4_UNK7 0x00000080 // 7
@@ -388,7 +394,7 @@ enum SpellCategory
#define SPELL_ATTR_EX5_UNK6 0x00000040 // 6
#define SPELL_ATTR_EX5_UNK7 0x00000080 // 7
#define SPELL_ATTR_EX5_UNK8 0x00000100 // 8
-#define SPELL_ATTR_EX5_UNK9 0x00000200 // 9
+#define SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY 0x00000200 // 9 begin periodic tick at aura apply
#define SPELL_ATTR_EX5_UNK10 0x00000400 // 10
#define SPELL_ATTR_EX5_UNK11 0x00000800 // 11
#define SPELL_ATTR_EX5_UNK12 0x00001000 // 12
@@ -413,37 +419,39 @@ enum SpellCategory
#define SPELL_ATTR_EX5_UNK31 0x80000000 // 31 Forces all nearby enemies to focus attacks caster
#define SPELL_ATTR_EX6_UNK0 0x00000001 // 0 Only Move spell have this flag
-#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 2.4.2
+#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 3.0.3
#define SPELL_ATTR_EX6_UNK2 0x00000004 // 2
#define SPELL_ATTR_EX6_UNK3 0x00000008 // 3
-#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 not set in 2.4.2
+#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4
#define SPELL_ATTR_EX6_UNK5 0x00000020 // 5
#define SPELL_ATTR_EX6_UNK6 0x00000040 // 6
#define SPELL_ATTR_EX6_UNK7 0x00000080 // 7
#define SPELL_ATTR_EX6_UNK8 0x00000100 // 8
-#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9 not set in 2.4.2
+#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9
#define SPELL_ATTR_EX6_UNK10 0x00000400 // 10
#define SPELL_ATTR_EX6_UNK11 0x00000800 // 11
-#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK21 0x00200000 // 21 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 2.4.2
-#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 2.4.2
+#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12
+#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13
+#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14
+#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 3.0.3
+#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16
+#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17
+#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18
+#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19
+#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20
+#define SPELL_ATTR_EX6_UNK21 0x00200000 // 21
+#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22
+#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 3.0.3
+#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 3.0.3
+#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 3.0.3
+#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 3.0.3
+#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 3.0.3
+#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 3.0.3
+#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 3.0.3
+#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 3.0.3
+#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 3.0.3
+
+#define MAX_GLYPH_SLOT_INDEX 5
enum SheathTypes
{
@@ -562,11 +570,11 @@ enum SpellEffects
SPELL_EFFECT_DISPEL = 38,
SPELL_EFFECT_LANGUAGE = 39,
SPELL_EFFECT_DUAL_WIELD = 40,
- SPELL_EFFECT_SUMMON_WILD = 41,
- SPELL_EFFECT_SUMMON_GUARDIAN = 42,
+ SPELL_EFFECT_JUMP = 41,
+ SPELL_EFFECT_JUMP2 = 42,
SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER= 43,
SPELL_EFFECT_SKILL_STEP = 44,
- SPELL_EFFECT_UNDEFINED_45 = 45,
+ SPELL_EFFECT_ADD_HONOR = 45,
SPELL_EFFECT_SPAWN = 46,
SPELL_EFFECT_TRADE_SKILL = 47,
SPELL_EFFECT_STEALTH = 48,
@@ -586,16 +594,16 @@ enum SpellEffects
SPELL_EFFECT_POWER_BURN = 62,
SPELL_EFFECT_THREAT = 63,
SPELL_EFFECT_TRIGGER_SPELL = 64,
- SPELL_EFFECT_HEALTH_FUNNEL = 65,
- SPELL_EFFECT_POWER_FUNNEL = 66,
+ SPELL_EFFECT_APPLY_AREA_AURA_RAID = 65,
+ SPELL_EFFECT_CREATE_MANA_GEM = 66,
SPELL_EFFECT_HEAL_MAX_HEALTH = 67,
SPELL_EFFECT_INTERRUPT_CAST = 68,
SPELL_EFFECT_DISTRACT = 69,
SPELL_EFFECT_PULL = 70,
SPELL_EFFECT_PICKPOCKET = 71,
SPELL_EFFECT_ADD_FARSIGHT = 72,
- SPELL_EFFECT_SUMMON_POSSESSED = 73,
- SPELL_EFFECT_SUMMON_TOTEM = 74,
+ SPELL_EFFECT_UNTRAIN_TALENTS = 73,
+ SPELL_EFFECT_APPLY_GLYPH = 74,
SPELL_EFFECT_HEAL_MECHANICAL = 75,
SPELL_EFFECT_SUMMON_OBJECT_WILD = 76,
SPELL_EFFECT_SCRIPT_EFFECT = 77,
@@ -608,17 +616,17 @@ enum SpellEffects
SPELL_EFFECT_STUCK = 84,
SPELL_EFFECT_SUMMON_PLAYER = 85,
SPELL_EFFECT_ACTIVATE_OBJECT = 86,
- SPELL_EFFECT_SUMMON_TOTEM_SLOT1 = 87,
- SPELL_EFFECT_SUMMON_TOTEM_SLOT2 = 88,
- SPELL_EFFECT_SUMMON_TOTEM_SLOT3 = 89,
- SPELL_EFFECT_SUMMON_TOTEM_SLOT4 = 90,
+ SPELL_EFFECT_WMO_DAMAGE = 87,
+ SPELL_EFFECT_WMO_REPAIR = 88,
+ SPELL_EFFECT_WMO_CHANGE = 89,
+ SPELL_EFFECT_KILL_CREDIT = 90,
SPELL_EFFECT_THREAT_ALL = 91,
SPELL_EFFECT_ENCHANT_HELD_ITEM = 92,
SPELL_EFFECT_SUMMON_PHANTASM = 93, //unused
SPELL_EFFECT_SELF_RESURRECT = 94,
SPELL_EFFECT_SKINNING = 95,
SPELL_EFFECT_CHARGE = 96,
- SPELL_EFFECT_SUMMON_CRITTER = 97,
+ SPELL_EFFECT_97 = 97,
SPELL_EFFECT_KNOCK_BACK = 98,
SPELL_EFFECT_DISENCHANT = 99,
SPELL_EFFECT_INEBRIATE = 100,
@@ -633,7 +641,7 @@ enum SpellEffects
SPELL_EFFECT_SUMMON_DEAD_PET = 109,
SPELL_EFFECT_DESTROY_ALL_TOTEMS = 110,
SPELL_EFFECT_DURABILITY_DAMAGE = 111,
- SPELL_EFFECT_SUMMON_DEMON = 112,
+ SPELL_EFFECT_112 = 112,
SPELL_EFFECT_RESURRECT_NEW = 113,
SPELL_EFFECT_ATTACK_ME = 114,
SPELL_EFFECT_DURABILITY_DAMAGE_PCT = 115,
@@ -655,19 +663,19 @@ enum SpellEffects
SPELL_EFFECT_131 = 131,
SPELL_EFFECT_132 = 132,
SPELL_EFFECT_UNLEARN_SPECIALIZATION = 133,
- SPELL_EFFECT_KILL_CREDIT = 134,
+ SPELL_EFFECT_KILL_CREDIT2 = 134,
SPELL_EFFECT_135 = 135,
SPELL_EFFECT_HEAL_PCT = 136,
SPELL_EFFECT_ENERGIZE_PCT = 137,
SPELL_EFFECT_138 = 138,
- SPELL_EFFECT_139 = 139,
+ SPELL_EFFECT_CLEAR_QUEST = 139,
SPELL_EFFECT_FORCE_CAST = 140,
SPELL_EFFECT_141 = 141,
SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE = 142,
SPELL_EFFECT_APPLY_AREA_AURA_OWNER = 143,
SPELL_EFFECT_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,
@@ -675,7 +683,13 @@ enum SpellEffects
SPELL_EFFECT_TRIGGER_SPELL_2 = 151,
SPELL_EFFECT_152 = 152,
SPELL_EFFECT_153 = 153,
- TOTAL_SPELL_EFFECTS = 154
+ SPELL_EFFECT_154 = 154,
+ SPELL_EFFECT_TITAN_GRIP = 155,
+ SPELL_EFFECT_ADD_SOCKET = 156,
+ SPELL_EFFECT_CREATE_ITEM_2 = 157,
+ SPELL_EFFECT_MILLING = 158,
+ SPELL_EFFECT_ALLOW_RENAME_PET = 159,
+ TOTAL_SPELL_EFFECTS = 160
};
// Spell aura states
@@ -685,25 +699,28 @@ enum AuraState
AURA_STATE_DEFENSE = 1, // C |
AURA_STATE_HEALTHLESS_20_PERCENT = 2, // CcT |
AURA_STATE_BERSERKING = 3, // C T |
- //AURA_STATE_UNKNOWN4 = 4, // c t| some limitation to charge spells (?) and target test spells
+ AURA_STATE_FROZEN = 4, // c t| frozen target
AURA_STATE_JUDGEMENT = 5, // C |
//AURA_STATE_UNKNOWN6 = 6, // | not used
AURA_STATE_HUNTER_PARRY = 7, // C |
AURA_STATE_ROGUE_ATTACK_FROM_STEALTH = 7, // C | FIX ME: not implemented yet!
- //AURA_STATE_UNKNOWN7c = 7, // c | random/focused bursts spells (?)
+ //AURA_STATE_UNKNOWN7 = 7, // c | random/focused bursts spells (?)
//AURA_STATE_UNKNOWN8 = 8, // | not used
//AURA_STATE_UNKNOWN9 = 9, // | not used
AURA_STATE_WARRIOR_VICTORY_RUSH = 10, // C | warrior victory rush
- AURA_STATE_HUNTER_CRIT_STRIKE = 10, // C | hunter crit strike
- AURA_STATE_CRIT = 11, // C |
+ //AURA_STATE_UNKNOWN11 = 11, // t|
AURA_STATE_FAERIE_FIRE = 12, // c t|
AURA_STATE_HEALTHLESS_35_PERCENT = 13, // C T |
AURA_STATE_IMMOLATE = 14, // T |
AURA_STATE_SWIFTMEND = 15, // T |
AURA_STATE_DEADLY_POISON = 16, // T |
- AURA_STATE_FORBEARANCE = 17, // c t|
- AURA_STATE_WEAKENED_SOUL = 18, // t|
- AURA_STATE_HYPOTHERMIA = 19 // c |
+ AURA_STATE_ENRAGE = 17, // C |
+ //AURA_STATE_UNKNOWN18 = 18, // C t|
+ //AURA_STATE_UNKNOWN19 = 19, // | not used
+ //AURA_STATE_UNKNOWN20 = 20, // c | only (45317 Suicide)
+ //AURA_STATE_UNKNOWN21 = 21, // | not used
+ //AURA_STATE_UNKNOWN22 = 22, // C | not implemented yet (Requires Evasive Charges to use)
+ AURA_STATE_HEALTH_ABOVE_75_PERCENT = 23, // C |
};
// Spell mechanics
@@ -711,11 +728,11 @@ enum Mechanics
{
MECHANIC_NONE = 0,
MECHANIC_CHARM = 1,
- MECHANIC_CONFUSED = 2,
+ MECHANIC_DISORIENTED = 2,
MECHANIC_DISARM = 3,
MECHANIC_DISTRACT = 4,
MECHANIC_FEAR = 5,
- MECHANIC_FUMBLE = 6,
+ MECHANIC_GRIP = 6,
MECHANIC_ROOT = 7,
MECHANIC_PACIFY = 8, //0 spells use this mechanic
MECHANIC_SILENCE = 9,
@@ -731,7 +748,7 @@ enum Mechanics
MECHANIC_SHIELD = 19,
MECHANIC_SHACKLE = 20,
MECHANIC_MOUNT = 21,
- MECHANIC_PERSUADE = 22, //0 spells use this mechanic
+ MECHANIC_INFECTED = 22,
MECHANIC_TURN = 23,
MECHANIC_HORROR = 24,
MECHANIC_INVULNERABILITY = 25,
@@ -739,12 +756,13 @@ enum Mechanics
MECHANIC_DAZE = 27,
MECHANIC_DISCOVERY = 28,
MECHANIC_IMMUNE_SHIELD = 29, // Divine (Blessing) Shield/Protection and Ice Block
- MECHANIC_SAPPED = 30
+ MECHANIC_SAPPED = 30,
+ MECHANIC_ENRAGED = 31
};
// Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967da6)
#define IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK ( \
- (1<<MECHANIC_CHARM )|(1<<MECHANIC_CONFUSED )|(1<<MECHANIC_FEAR )| \
+ (1<<MECHANIC_CHARM )|(1<<MECHANIC_DISORIENTED )|(1<<MECHANIC_FEAR )| \
(1<<MECHANIC_ROOT )|(1<<MECHANIC_PACIFY )|(1<<MECHANIC_SLEEP )| \
(1<<MECHANIC_SNARE )|(1<<MECHANIC_STUN )|(1<<MECHANIC_FREEZE)| \
(1<<MECHANIC_KNOCKOUT)|(1<<MECHANIC_POLYMORPH)|(1<<MECHANIC_BANISH)| \
@@ -764,7 +782,8 @@ enum DispelType
DISPEL_ALL = 7,
DISPEL_SPE_NPC_ONLY = 8,
DISPEL_ENRAGE = 9,
- DISPEL_ZG_TICKET = 10
+ DISPEL_ZG_TICKET = 10,
+ DESPEL_OLD_UNUSED = 11
};
#define DISPEL_ALL_MASK ( (1<<DISPEL_MAGIC) | (1<<DISPEL_CURSE) | (1<<DISPEL_DISEASE) | (1<<DISPEL_POISON) )
@@ -790,10 +809,9 @@ enum Targets
{
TARGET_SELF = 1,
TARGET_UNIT_CASTER = 1,
- TARGET_RANDOM_ENEMY_CHAIN_IN_AREA = 2, // only one spell has that, but regardless, it's a target type after all
- //TARGET_UNIT_NEARBY_ENEMY
- TARGET_UNIT_SINGLE_UNKNOWN = 3,
- TARGET_UNIT_NEARBY_ALLY = 4,
+ TARGET_UNIT_NEARBY_ENEMY = 2,
+ TARGET_UNIT_NEARBY_ALLY = 3,
+ TARGET_UNIT_NEARBY_ALLY_UNK = 4,
TARGET_PET = 5,
TARGET_UNIT_PET = 5,
TARGET_CHAIN_DAMAGE = 6,
@@ -816,7 +834,6 @@ enum Targets
TARGET_UNIT_PARTY_CASTER = 20,
TARGET_SINGLE_FRIEND = 21,
TARGET_UNIT_TARGET_ALLY = 21,
- TARGET_ALL_AROUND_CASTER = 22, // used only in TargetA, target selection dependent from TargetB
TARGET_DEST_CASTER = 22,
TARGET_GAMEOBJECT = 23,
//TARGET_OBJECT_OPEN
@@ -986,9 +1003,10 @@ enum GameobjectTypes
GAMEOBJECT_TYPE_BARBER_CHAIR = 32,
GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING = 33,
GAMEOBJECT_TYPE_GUILD_BANK = 34,
+ GAMEOBJECT_TYPE_TRAPDOOR = 35
};
-#define MAX_GAMEOBJECT_TYPE 35 // sending to client this or greater value can crash client.
+#define MAX_GAMEOBJECT_TYPE 36 // sending to client this or greater value can crash client.
#define GAMEOBJECT_FISHINGNODE_ENTRY 35591 // Better to define it somewhere instead of hardcoding everywhere
@@ -1555,7 +1573,9 @@ enum LockType
LOCKTYPE_BLASTING = 16,
LOCKTYPE_SLOW_OPEN = 17,
LOCKTYPE_SLOW_CLOSE = 18,
- LOCKTYPE_FISHING = 19
+ LOCKTYPE_FISHING = 19,
+ LOCKTYPE_INSCRIPTION = 20,
+ LOCKTYPE_OPEN_FROM_VEHICLE = 21
};
enum TrainerType // this is important type for npcs!
@@ -1568,6 +1588,7 @@ enum TrainerType // this is important
#define MAX_TRAINER_TYPE 4
+// CreatureType.dbc
enum CreatureType
{
CREATURE_TYPE_BEAST = 1,
@@ -1587,6 +1608,7 @@ enum CreatureType
uint32 const CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD = (1 << (CREATURE_TYPE_HUMANOID-1)) | (1 << (CREATURE_TYPE_UNDEAD-1));
+// CreatureFamily.dbc
enum CreatureFamily
{
CREATURE_FAMILY_WOLF = 1,
@@ -1598,6 +1620,7 @@ enum CreatureFamily
CREATURE_FAMILY_CARRION_BIRD = 7,
CREATURE_FAMILY_CRAB = 8,
CREATURE_FAMILY_GORILLA = 9,
+ CREATURE_FAMILY_HORSE_CUSTOM = 10, // not exist in DBC but used for horse like beasts in DB
CREATURE_FAMILY_RAPTOR = 11,
CREATURE_FAMILY_TALLSTRIDER = 12,
CREATURE_FAMILY_FELHUNTER = 15,
@@ -1609,7 +1632,7 @@ enum CreatureFamily
CREATURE_FAMILY_IMP = 23,
CREATURE_FAMILY_BAT = 24,
CREATURE_FAMILY_HYENA = 25,
- CREATURE_FAMILY_OWL = 26,
+ CREATURE_FAMILY_BIRD_OF_PREY = 26,
CREATURE_FAMILY_WIND_SERPENT = 27,
CREATURE_FAMILY_REMOTE_CONTROL = 28,
CREATURE_FAMILY_FELGUARD = 29,
@@ -1619,14 +1642,24 @@ enum CreatureFamily
CREATURE_FAMILY_SPOREBAT = 33,
CREATURE_FAMILY_NETHER_RAY = 34,
CREATURE_FAMILY_SERPENT = 35,
- CREATURE_FAMILY_SEA_LION = 36
+ CREATURE_FAMILY_MOTH = 37,
+ CREATURE_FAMILY_CHIMAERA = 38,
+ CREATURE_FAMILY_DEVILSAUR = 39,
+ CREATURE_FAMILY_GHOUL = 40,
+ CREATURE_FAMILY_SILITHID = 41,
+ CREATURE_FAMILY_WORM = 42,
+ CREATURE_FAMILY_RHINO = 43,
+ CREATURE_FAMILY_WASP = 44,
+ CREATURE_FAMILY_CORE_HOUND = 45,
+ CREATURE_FAMILY_SPIRIT_BEAST = 46
};
enum CreatureTypeFlags
{
- CREATURE_TYPEFLAGS_TAMEABLE = 0x0001,
- CREATURE_TYPEFLAGS_HERBLOOT = 0x0100,
- CREATURE_TYPEFLAGS_MININGLOOT = 0x0200
+ CREATURE_TYPEFLAGS_TAMEABLE = 0x0001,
+ CREATURE_TYPEFLAGS_HERBLOOT = 0x0100,
+ CREATURE_TYPEFLAGS_MININGLOOT = 0x0200,
+ CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x8000
};
enum CreatureEliteType
@@ -1651,6 +1684,8 @@ enum QuestTypes
QUEST_TYPE_LEGENDARY = 83,
QUEST_TYPE_ESCORT = 84,
QUEST_TYPE_HEROIC = 85,
+ QUEST_TYPE_RAID_10 = 88,
+ QUEST_TYPE_RAID_25 = 89
};
// values based at QuestSort.dbc
@@ -1661,7 +1696,7 @@ enum QuestSort
QUEST_SORT_SEASONAL = 22,
QUEST_SORT_UNDERCITY_OLD = 23,
QUEST_SORT_HERBALISM = 24,
- QUEST_SORT_SCARLET_MONASTERY_OLD= 25,
+ QUEST_SORT_BATTLEGROUNDS = 25,
QUEST_SORT_ULDAMN_OLD = 41,
QUEST_SORT_WARLOCK = 61,
QUEST_SORT_WARRIOR = 81,
@@ -1690,22 +1725,26 @@ enum QuestSort
QUEST_SORT_REPUTATION = 367,
QUEST_SORT_INVASION = 368,
QUEST_SORT_MIDSUMMER = 369,
- QUEST_SORT_BREWFEST = 370
+ QUEST_SORT_BREWFEST = 370,
+ QUEST_SORT_INSCRIPTION = 371,
+ QUEST_SORT_DEATH_KNIGHT = 372,
+ QUEST_SORT_JEWELCRAFTING = 373
};
inline uint8 ClassByQuestSort(int32 QuestSort)
{
switch(QuestSort)
{
- case QUEST_SORT_WARLOCK: return CLASS_WARLOCK;
- case QUEST_SORT_WARRIOR: return CLASS_WARRIOR;
- case QUEST_SORT_SHAMAN: return CLASS_SHAMAN;
- case QUEST_SORT_PALADIN: return CLASS_PALADIN;
- case QUEST_SORT_MAGE: return CLASS_MAGE;
- case QUEST_SORT_ROGUE: return CLASS_ROGUE;
- case QUEST_SORT_HUNTER: return CLASS_HUNTER;
- case QUEST_SORT_PRIEST: return CLASS_PRIEST;
- case QUEST_SORT_DRUID: return CLASS_DRUID;
+ case QUEST_SORT_WARLOCK: return CLASS_WARLOCK;
+ case QUEST_SORT_WARRIOR: return CLASS_WARRIOR;
+ case QUEST_SORT_SHAMAN: return CLASS_SHAMAN;
+ case QUEST_SORT_PALADIN: return CLASS_PALADIN;
+ case QUEST_SORT_MAGE: return CLASS_MAGE;
+ case QUEST_SORT_ROGUE: return CLASS_ROGUE;
+ case QUEST_SORT_HUNTER: return CLASS_HUNTER;
+ case QUEST_SORT_PRIEST: return CLASS_PRIEST;
+ case QUEST_SORT_DRUID: return CLASS_DRUID;
+ case QUEST_SORT_DEATH_KNIGHT: return CLASS_DEATH_KNIGHT;
}
return 0;
}
@@ -1717,7 +1756,6 @@ enum SkillType
SKILL_ARMS = 26,
SKILL_COMBAT = 38,
SKILL_SUBTLETY = 39,
- SKILL_POISONS = 40,
SKILL_SWORDS = 43,
SKILL_AXES = 44,
SKILL_BOWS = 45,
@@ -1725,8 +1763,8 @@ enum SkillType
SKILL_BEAST_MASTERY = 50,
SKILL_SURVIVAL = 51,
SKILL_MACES = 54,
- SKILL_HOLY = 56,
SKILL_2H_SWORDS = 55,
+ SKILL_HOLY = 56,
SKILL_SHADOW = 78,
SKILL_DEFENSE = 95,
SKILL_LANG_COMMON = 98,
@@ -1782,24 +1820,20 @@ enum SkillType
SKILL_PET_BOAR = 211,
SKILL_PET_CROCILISK = 212,
SKILL_PET_CARRION_BIRD = 213,
- SKILL_PET_GORILLA = 215,
SKILL_PET_CRAB = 214,
+ SKILL_PET_GORILLA = 215,
SKILL_PET_RAPTOR = 217,
SKILL_PET_TALLSTRIDER = 218,
SKILL_RACIAL_UNDED = 220,
- SKILL_WEAPON_TALENTS = 222,
SKILL_CROSSBOWS = 226,
- SKILL_SPEARS = 227,
SKILL_WANDS = 228,
SKILL_POLEARMS = 229,
SKILL_PET_SCORPID = 236,
SKILL_ARCANE = 237,
- SKILL_OPEN_LOCK = 242,
SKILL_PET_TURTLE = 251,
SKILL_ASSASSINATION = 253,
SKILL_FURY = 256,
SKILL_PROTECTION = 257,
- SKILL_BEAST_TRAINING = 261,
SKILL_PROTECTION2 = 267,
SKILL_PET_TALENTS = 270,
SKILL_PLATE_MAIL = 293,
@@ -1829,7 +1863,7 @@ enum SkillType
SKILL_LOCKPICKING = 633,
SKILL_PET_BAT = 653,
SKILL_PET_HYENA = 654,
- SKILL_PET_OWL = 655,
+ SKILL_PET_BIRD_OF_PREY = 655,
SKILL_PET_WIND_SERPENT = 656,
SKILL_LANG_GUTTERSPEAK = 673,
SKILL_RIDING_KODO = 713,
@@ -1849,10 +1883,27 @@ enum SkillType
SKILL_PET_WARP_STALKER = 766,
SKILL_PET_RAVAGER = 767,
SKILL_PET_SERPENT = 768,
- SKILL_INTERNAL = 769
+ SKILL_INTERNAL = 769,
+ SKILL_DK_BLOOD = 770,
+ SKILL_DK_FROST = 771,
+ SKILL_DK_UNHOLY = 772,
+ SKILL_INSCRIPTION = 773,
+ SKILL_PET_MOTH = 775,
+ SKILL_RUNEFORGING = 776,
+ SKILL_MOUNTS = 777,
+ SKILL_COMPANIONS = 778,
+ SKILL_PET_EXOTIC_CHIMAERA = 780,
+ SKILL_PET_EXOTIC_DEVILSAUR = 781,
+ SKILL_PET_GHOUL = 782,
+ SKILL_PET_EXOTIC_SILITHID = 783,
+ SKILL_PET_EXOTIC_WORM = 784,
+ SKILL_PET_WASP = 785,
+ SKILL_PET_EXOTIC_RHINO = 786,
+ SKILL_PET_EXOTIC_CORE_HOUND = 787,
+ SKILL_PET_EXOTIC_SPIRIT_BEAST = 788
};
-#define MAX_SKILL_TYPE 770
+#define MAX_SKILL_TYPE 789
inline uint32 SkillByQuestSort(int32 QuestSort)
{
@@ -1867,25 +1918,27 @@ inline uint32 SkillByQuestSort(int32 QuestSort)
case QUEST_SORT_TAILORING: return SKILL_TAILORING;
case QUEST_SORT_COOKING: return SKILL_COOKING;
case QUEST_SORT_FIRST_AID: return SKILL_FIRST_AID;
+ case QUEST_SORT_JEWELCRAFTING: return SKILL_JEWELCRAFTING;
+ case QUEST_SORT_INSCRIPTION: return SKILL_INSCRIPTION;
}
return 0;
}
enum SkillCategory
{
- SKILL_CATEGORY_ATTRIBUTES = 5,
- SKILL_CATEGORY_WEAPON = 6,
- SKILL_CATEGORY_CLASS = 7,
- SKILL_CATEGORY_ARMOR = 8,
- SKILL_CATEGORY_SECONDARY = 9, // secondary professions
+ SKILL_CATEGORY_ATTRIBUTES = 5,
+ SKILL_CATEGORY_WEAPON = 6,
+ SKILL_CATEGORY_CLASS = 7,
+ SKILL_CATEGORY_ARMOR = 8,
+ SKILL_CATEGORY_SECONDARY = 9, // secondary professions
SKILL_CATEGORY_LANGUAGES = 10,
SKILL_CATEGORY_PROFESSION = 11, // primary professions
- SKILL_CATEGORY_NOT_DISPLAYED = 12
+ SKILL_CATEGORY_GENERIC = 12
};
enum TotemCategory
{
- TC_SKINNING_SKIFE = 1,
+ TC_SKINNING_SKIFE_OLD = 1,
TC_EARTH_TOTEM = 2,
TC_AIR_TOTEM = 3,
TC_FIRE_TOTEM = 4,
@@ -1895,15 +1948,28 @@ enum TotemCategory
TC_GOLDEN_ROD = 8,
TC_TRUESILVER_ROD = 9,
TC_ARCANITE_ROD = 10,
- TC_MINING_PICK = 11,
+ TC_MINING_PICK_OLD = 11,
TC_PHILOSOPHERS_STONE = 12,
- TC_BLACKSMITH_HAMMER = 13,
+ TC_BLACKSMITH_HAMMER_OLD = 13,
TC_ARCLIGHT_SPANNER = 14,
TC_GYROMATIC_MA = 15,
TC_MASTER_TOTEM = 21,
TC_FEL_IRON_ROD = 41,
TC_ADAMANTITE_ROD = 62,
- TC_ETERNIUM_ROD = 63
+ TC_ETERNIUM_ROD = 63,
+ TC_HOLLOW_QUILL = 81,
+ TC_RUNED_AZURITE_ROD = 101,
+ TC_VIRTUOSO_INKING_SET = 121,
+ TC_DRUMS = 141,
+ TC_GNOMISH_ARMY_KNIFE = 161,
+ TC_BLACKSMITH_HAMMER = 162,
+ TC_MINING_PICK = 165,
+ TC_SKINNING_KNIFE = 166,
+ TC_HAMMER_PICK = 167,
+ TC_BLADED_PICKAXE = 168,
+ TC_FLINT_AND_TINDER = 169,
+ TC_RUNED_COBALT_ROD = 189,
+ TC_RUNED_TITANIUM_ROD = 190
};
enum UnitDynFlags
@@ -1913,7 +1979,8 @@ enum UnitDynFlags
UNIT_DYNFLAG_OTHER_TAGGER = 0x0004,
UNIT_DYNFLAG_ROOTED = 0x0008,
UNIT_DYNFLAG_SPECIALINFO = 0x0010,
- UNIT_DYNFLAG_DEAD = 0x0020
+ UNIT_DYNFLAG_DEAD = 0x0020,
+ UNIT_DYNFLAG_REFER_A_FRIEND = 0x0040
};
enum CorpseDynFlags
@@ -1922,11 +1989,14 @@ enum CorpseDynFlags
};
// Passive Spell codes explicit used in code
-#define SPELL_ID_GENERIC_LEARN 483
-#define SPELL_ID_PASSIVE_BATTLE_STANCE 2457
-#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007
-#define SPELL_ID_WEAPON_SWITCH_COOLDOWN_1_5s 6119
-#define SPELL_ID_WEAPON_SWITCH_COOLDOWN_1_0s 6123
+#define SPELL_ID_GENERIC_LEARN 483
+#define SPELL_ID_GENERIC_LEARN_PET 55884 // used for learning mounts and companions
+#define SPELL_ID_PASSIVE_BATTLE_STANCE 2457
+#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007
+#define SPELL_ID_WEAPON_SWITCH_COOLDOWN_1_5s 6119
+#define SPELL_ID_WEAPON_SWITCH_COOLDOWN_1_0s 6123
+#define SPELL_ID_AUTOSHOT 75 // used for checks in other spells interruption
+#define SPELL_ID_SHADOWMELD 58984 // used for check ignore stealth stance state
enum WeatherType
{
@@ -1990,9 +2060,12 @@ enum ChatMsg
CHAT_MSG_BATTLEGROUND = 0x2C,
CHAT_MSG_BATTLEGROUND_LEADER = 0x2D,
CHAT_MSG_RESTRICTED = 0x2E,
+ CHAT_MSG_BN = 0x2F,
+ CHAT_MSG_ACHIEVEMENT = 0x30,
+ CHAT_MSG_GUILD_ACHIEVEMENT = 0x31
};
-#define MAX_CHAT_MSG_TYPE 0x2F
+#define MAX_CHAT_MSG_TYPE 0x32
// Values from ItemPetFood (power of (value-1) used for compare with CreatureFamilyEntry.petDietMask
enum PetDiet
@@ -2092,7 +2165,9 @@ enum SummonType
SUMMON_TYPE_CRITTER3 = 307,
SUMMON_TYPE_UNKNOWN5 = 409,
SUMMON_TYPE_POSESSED3 = 427,
- SUMMON_TYPE_POSESSED2 = 428
+ SUMMON_TYPE_POSESSED2 = 428,
+ SUMMON_TYPE_FORCE_OF_NATURE = 669,
+ SUMMON_TYPE_GUARDIAN2 = 1161
};
enum ResponseCodes
@@ -2161,42 +2236,45 @@ enum ResponseCodes
CHAR_CREATE_SERVER_QUEUE = 0x37,
CHAR_CREATE_ONLY_EXISTING = 0x38,
CHAR_CREATE_EXPANSION = 0x39,
-
- CHAR_DELETE_IN_PROGRESS = 0x3A,
- CHAR_DELETE_SUCCESS = 0x3B,
- CHAR_DELETE_FAILED = 0x3C,
- CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x3D,
- CHAR_DELETE_FAILED_GUILD_LEADER = 0x3E,
- CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x3F,
-
- CHAR_LOGIN_IN_PROGRESS = 0x40,
- CHAR_LOGIN_SUCCESS = 0x41,
- CHAR_LOGIN_NO_WORLD = 0x42,
- CHAR_LOGIN_DUPLICATE_CHARACTER = 0x43,
- CHAR_LOGIN_NO_INSTANCES = 0x44,
- CHAR_LOGIN_FAILED = 0x45,
- CHAR_LOGIN_DISABLED = 0x46,
- CHAR_LOGIN_NO_CHARACTER = 0x47,
- CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x48,
- CHAR_LOGIN_LOCKED_BY_BILLING = 0x49,
-
- CHAR_NAME_SUCCESS = 0x4A,
- CHAR_NAME_FAILURE = 0x4B,
- CHAR_NAME_NO_NAME = 0x4C,
- CHAR_NAME_TOO_SHORT = 0x4D,
- CHAR_NAME_TOO_LONG = 0x4E,
- CHAR_NAME_INVALID_CHARACTER = 0x4F,
- CHAR_NAME_MIXED_LANGUAGES = 0x50,
- CHAR_NAME_PROFANE = 0x51,
- CHAR_NAME_RESERVED = 0x52,
- CHAR_NAME_INVALID_APOSTROPHE = 0x53,
- CHAR_NAME_MULTIPLE_APOSTROPHES = 0x54,
- CHAR_NAME_THREE_CONSECUTIVE = 0x55,
- CHAR_NAME_INVALID_SPACE = 0x56,
- CHAR_NAME_CONSECUTIVE_SPACES = 0x57,
- CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x58,
- CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x59,
- CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5A,
+ CHAR_CREATE_EXPANSION_CLASS = 0x3A,
+ CHAR_CREATE_LEVEL_REQUIREMENT = 0x3B,
+ CHAR_CREATE_UNIQUE_CLASS_LIMIT = 0x3C,
+
+ CHAR_DELETE_IN_PROGRESS = 0x3D,
+ CHAR_DELETE_SUCCESS = 0x3E,
+ CHAR_DELETE_FAILED = 0x3F,
+ CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x40,
+ CHAR_DELETE_FAILED_GUILD_LEADER = 0x41,
+ CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x42,
+
+ CHAR_LOGIN_IN_PROGRESS = 0x43,
+ CHAR_LOGIN_SUCCESS = 0x44,
+ CHAR_LOGIN_NO_WORLD = 0x45,
+ CHAR_LOGIN_DUPLICATE_CHARACTER = 0x46,
+ CHAR_LOGIN_NO_INSTANCES = 0x47,
+ CHAR_LOGIN_FAILED = 0x48,
+ CHAR_LOGIN_DISABLED = 0x49,
+ CHAR_LOGIN_NO_CHARACTER = 0x4A,
+ CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x4B,
+ CHAR_LOGIN_LOCKED_BY_BILLING = 0x4C,
+
+ CHAR_NAME_SUCCESS = 0x4D,
+ CHAR_NAME_FAILURE = 0x4E,
+ CHAR_NAME_NO_NAME = 0x4F,
+ CHAR_NAME_TOO_SHORT = 0x50,
+ CHAR_NAME_TOO_LONG = 0x51,
+ CHAR_NAME_INVALID_CHARACTER = 0x52,
+ CHAR_NAME_MIXED_LANGUAGES = 0x53,
+ CHAR_NAME_PROFANE = 0x54,
+ CHAR_NAME_RESERVED = 0x55,
+ CHAR_NAME_INVALID_APOSTROPHE = 0x56,
+ CHAR_NAME_MULTIPLE_APOSTROPHES = 0x57,
+ CHAR_NAME_THREE_CONSECUTIVE = 0x58,
+ CHAR_NAME_INVALID_SPACE = 0x59,
+ CHAR_NAME_CONSECUTIVE_SPACES = 0x5A,
+ CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x5B,
+ CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x5C,
+ CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5D
};
/// Ban function modes
diff --git a/src/game/SkillDiscovery.cpp b/src/game/SkillDiscovery.cpp
index 2a1c6ec9d82..6758f3db9fd 100644
--- a/src/game/SkillDiscovery.cpp
+++ b/src/game/SkillDiscovery.cpp
@@ -31,14 +31,15 @@
struct SkillDiscoveryEntry
{
- uint32 spellId;
- float chance;
+ uint32 spellId; // discavered spell
+ uint32 reqSkillValue; // skill level limitation
+ float chance; // chance
SkillDiscoveryEntry()
- : spellId(0), chance(0) {}
+ : spellId(0), reqSkillValue(0), chance(0) {}
- SkillDiscoveryEntry(uint16 _spellId, float _chance)
- : spellId(_spellId), chance(_chance) {}
+ SkillDiscoveryEntry(uint16 _spellId, uint32 req_skill_val, float _chance)
+ : spellId(_spellId), reqSkillValue(req_skill_val), chance(_chance) {}
};
typedef std::list<SkillDiscoveryEntry> SkillDiscoveryList;
@@ -53,8 +54,8 @@ void LoadSkillDiscoveryTable()
uint32 count = 0;
- // 0 1 2
- QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, chance FROM skill_discovery_template");
+ // 0 1 2 3
+ QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, reqSkillValue, chance FROM skill_discovery_template");
if (result)
{
@@ -69,11 +70,13 @@ void LoadSkillDiscoveryTable()
uint32 spellId = fields[0].GetUInt32();
int32 reqSkillOrSpell = fields[1].GetInt32();
- float chance = fields[2].GetFloat();
+ uint32 reqSkillValue = fields[2].GetInt32();
+ float chance = fields[3].GetFloat();
if( chance <= 0 ) // chance
{
- ssNonDiscoverableEntries << "spellId = " << spellId << " reqSkillOrSpell = " << reqSkillOrSpell << " chance = " << chance << "\n";
+ ssNonDiscoverableEntries << "spellId = " << spellId << " reqSkillOrSpell = " << reqSkillOrSpell
+ << " reqSkillValue = " << reqSkillValue << " chance = " << chance << "(chance problem)\n";
continue;
}
@@ -86,13 +89,16 @@ void LoadSkillDiscoveryTable()
continue;
}
- if( spellEntry->Mechanic != MECHANIC_DISCOVERY )
+ // mechanic discovery
+ if (spellEntry->Mechanic != MECHANIC_DISCOVERY &&
+ // explicit discovery ability
+ !IsExplicitDiscoverySpell(spellEntry))
{
- sLog.outErrorDb("Spell (ID: %u) not have have MECHANIC_DISCOVERY (28) value in Mechanic field in spell.dbc but listed in `skill_discovery_template` table",spellId);
+ sLog.outErrorDb("Spell (ID: %u) not have have MECHANIC_DISCOVERY (28) value in Mechanic field in spell.dbc and not 100% chance random discovery ability but listed in `skill_discovery_template` table",spellId);
continue;
}
- SkillDiscoveryStore[reqSkillOrSpell].push_back( SkillDiscoveryEntry(spellId, chance) );
+ SkillDiscoveryStore[reqSkillOrSpell].push_back( SkillDiscoveryEntry(spellId, reqSkillValue, chance) );
}
else if( reqSkillOrSpell == 0 ) // skill case
{
@@ -107,7 +113,7 @@ void LoadSkillDiscoveryTable()
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
{
- SkillDiscoveryStore[-int32(_spell_idx->second->skillId)].push_back( SkillDiscoveryEntry(spellId, chance) );
+ SkillDiscoveryStore[-int32(_spell_idx->second->skillId)].push_back( SkillDiscoveryEntry(spellId, reqSkillValue, chance) );
}
}
else
@@ -115,6 +121,7 @@ void LoadSkillDiscoveryTable()
sLog.outErrorDb("Spell (ID: %u) have negative value in `reqSpell` field in `skill_discovery_template` table",spellId);
continue;
}
+
++count;
} while (result->NextRow());
@@ -132,8 +139,48 @@ void LoadSkillDiscoveryTable()
}
}
+uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player)
+{
+ // explicit discovery spell chances (always success if case exist)
+ // in this case we have both skill and spell
+ SkillDiscoveryMap::iterator tab = SkillDiscoveryStore.find(spellId);
+ if(tab == SkillDiscoveryStore.end())
+ return 0;
+
+ SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellId);
+ SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellId);
+ uint32 skillvalue = lower != upper ? player->GetSkillValue(lower->second->skillId) : 0;
+
+ float full_chance = 0;
+ for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter)
+ if(item_iter->reqSkillValue <= skillvalue)
+ if(!player->HasSpell(item_iter->spellId))
+ full_chance += item_iter->chance;
+
+ float rate = full_chance / 100.0f;
+ float roll = rand_chance() * rate; // roll now in range 0..full_chance
+
+ for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter)
+ {
+ if(item_iter->reqSkillValue > skillvalue)
+ continue;
+
+ if(player->HasSpell(item_iter->spellId))
+ continue;
+
+ if(item_iter->chance > roll)
+ return item_iter->spellId;
+
+ roll -= item_iter->chance;
+ }
+
+ return 0;
+}
+
uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player)
{
+ uint32 skillvalue = skillId ? player->GetSkillValue(skillId) : 0;
+
// check spell case
SkillDiscoveryMap::iterator tab = SkillDiscoveryStore.find(spellId);
@@ -142,6 +189,7 @@ uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player)
for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter)
{
if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY))
+ && item_iter->reqSkillValue <= skillvalue
&& !player->HasSpell(item_iter->spellId) )
return item_iter->spellId;
}
@@ -149,6 +197,9 @@ uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player)
return 0;
}
+ if(!skillId)
+ return 0;
+
// check skill line case
tab = SkillDiscoveryStore.find(-(int32)skillId);
if(tab != SkillDiscoveryStore.end())
@@ -156,6 +207,7 @@ uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player)
for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter)
{
if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY))
+ && item_iter->reqSkillValue <= skillvalue
&& !player->HasSpell(item_iter->spellId) )
return item_iter->spellId;
}
diff --git a/src/game/SkillDiscovery.h b/src/game/SkillDiscovery.h
index bdd126e0cb3..e64fa826940 100644
--- a/src/game/SkillDiscovery.h
+++ b/src/game/SkillDiscovery.h
@@ -27,4 +27,5 @@ class Player;
void LoadSkillDiscoveryTable();
uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player);
+uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player);
#endif
diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp
index 56e48bf75c4..e909842dc86 100644
--- a/src/game/SkillHandler.cpp
+++ b/src/game/SkillHandler.cpp
@@ -82,10 +82,6 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data )
}
}
- // Check if it requires spell
- if( talentInfo->DependsOnSpell && !player->HasSpell(talentInfo->DependsOnSpell) )
- return;
-
// Find out how many points we have in this field
uint32 spentPoints = 0;
@@ -133,7 +129,7 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data )
return;
// learn! (other talent ranks will unlearned at learning)
- GetPlayer( )->learnSpell(spellid);
+ GetPlayer( )->learnSpell(spellid,false);
sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid);
// update free talent points
diff --git a/src/game/SocialMgr.cpp b/src/game/SocialMgr.cpp
index baabe9b043f..ce9d6cbd8df 100644
--- a/src/game/SocialMgr.cpp
+++ b/src/game/SocialMgr.cpp
@@ -182,13 +182,6 @@ SocialMgr::~SocialMgr()
}
-void SocialMgr::RemovePlayerSocial(uint32 guid)
-{
- SocialMap::iterator itr = m_socialMap.find(guid);
- if(itr != m_socialMap.end())
- m_socialMap.erase(itr);
-}
-
void SocialMgr::GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo)
{
if(!player)
diff --git a/src/game/SocialMgr.h b/src/game/SocialMgr.h
index 1cc14589e51..27280992173 100644
--- a/src/game/SocialMgr.h
+++ b/src/game/SocialMgr.h
@@ -143,7 +143,8 @@ class SocialMgr
SocialMgr();
~SocialMgr();
// Misc
- void RemovePlayerSocial(uint32 guid);
+ void RemovePlayerSocial(uint32 guid) { m_socialMap.erase(guid); }
+
void GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo);
// Packet management
void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket *data);
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 648d73a8f6f..ddac7d5c970 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -43,7 +43,6 @@
#include "CellImpl.h"
#include "Policies/SingletonImp.h"
#include "SharedDefines.h"
-#include "Tools.h"
#include "LootMgr.h"
#include "VMapFactory.h"
#include "BattleGround.h"
@@ -120,6 +119,14 @@ void SpellCastTargets::setDestination(Unit *target, bool send)
m_targetMask |= TARGET_FLAG_DEST_LOCATION;
}
+void SpellCastTargets::setSource(float x, float y, float z)
+{
+ m_srcX = x;
+ m_srcY = y;
+ m_srcZ = z;
+ m_targetMask |= TARGET_FLAG_SOURCE_LOCATION;
+}
+
void SpellCastTargets::setGOTarget(GameObject *target)
{
m_GOTarget = target;
@@ -178,16 +185,20 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster )
return true;
// TARGET_FLAG_UNK2 is used for non-combat pets, maybe other?
- if( m_targetMask & (TARGET_FLAG_UNIT|TARGET_FLAG_UNK2) )
- if(!readGUID(*data, m_unitTargetGUID))
+ if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_UNK2 ))
+ if(!data->readPackGUID(m_unitTargetGUID))
return false;
- if( m_targetMask & ( TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK ))
- if(!readGUID(*data, m_GOTargetGUID))
+ if( m_targetMask & ( TARGET_FLAG_OBJECT ))
+ if(!data->readPackGUID(m_GOTargetGUID))
return false;
if(( m_targetMask & ( TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM )) && caster->GetTypeId() == TYPEID_PLAYER)
- if(!readGUID(*data, m_itemTargetGUID))
+ if(!data->readPackGUID(m_itemTargetGUID))
+ return false;
+
+ if( m_targetMask & (TARGET_FLAG_CORPSE | TARGET_FLAG_PVP_CORPSE ) )
+ if(!data->readPackGUID(m_CorpseTargetGUID))
return false;
/*if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION )
@@ -202,7 +213,10 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster )
if( m_targetMask & (TARGET_FLAG_SOURCE_LOCATION | TARGET_FLAG_DEST_LOCATION) )
{
- if(data->rpos()+4+4+4 > data->size())
+ if(data->rpos()+1+4+4+4 > data->size())
+ return false;
+
+ if(!data->readPackGUID(m_unitTargetGUID))
return false;
*data >> m_destX >> m_destY >> m_destZ;
@@ -219,10 +233,6 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster )
*data >> m_strTarget;
}
- if( m_targetMask & (TARGET_FLAG_CORPSE | TARGET_FLAG_PVP_CORPSE ) )
- if(!readGUID(*data, m_CorpseTargetGUID))
- return false;
-
// find real units/GOs
Update(caster);
return true;
@@ -242,7 +252,7 @@ void SpellCastTargets::write ( WorldPacket * data )
else
*data << uint8(0);
}
- else if( m_targetMask & ( TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK ) )
+ else if( m_targetMask & TARGET_FLAG_OBJECT )
{
if(m_GOTarget)
data->append(m_GOTarget->GetPackGUID());
@@ -267,7 +277,14 @@ void SpellCastTargets::write ( WorldPacket * data )
*data << m_srcX << m_srcY << m_srcZ;
if( m_targetMask & TARGET_FLAG_DEST_LOCATION )
+ {
+ if(m_unitTarget)
+ data->append(m_unitTarget->GetPackGUID());
+ else
+ *data << uint8(0);
+
*data << m_destX << m_destY << m_destZ;
+ }
if( m_targetMask & TARGET_FLAG_STRING )
*data << m_strTarget;
@@ -305,7 +322,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
break;
default:
// Wands
- if (m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_WAND)
+ if (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG)
m_attackType = RANGED_ATTACK;
else
m_attackType = BASE_ATTACK;
@@ -355,14 +372,14 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
gameObjTarget = NULL;
focusObject = NULL;
m_cast_count = 0;
+ m_glyphIndex = 0;
+ m_preCastSpell = 0;
m_triggeredByAuraSpell = NULL;
- //Auto Shot & Shoot
- if( m_spellInfo->AttributesEx2 == 0x000020 && !triggered )
- m_autoRepeat = true;
- else
- m_autoRepeat = false;
+ //Auto Shot & Shoot (wand)
+ m_autoRepeat = IsAutoRepeatRangedSpell(m_spellInfo);
+ m_runesState = 0;
m_powerCost = 0; // setup to correct value in Spell::prepare, don't must be used before.
m_casttime = 0; // setup to correct value in Spell::prepare, don't must be used before.
m_timer = 0; // will set to castime in prepare
@@ -372,7 +389,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
// determine reflection
m_canReflect = false;
- if(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && (m_spellInfo->AttributesEx2 & 0x4)==0)
+ if(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_CANT_REFLECTED))
{
for(int j=0;j<3;j++)
{
@@ -461,7 +478,7 @@ void Spell::FillTargetMap()
WorldObject* result = NULL;
Trinity::CannibalizeObjectCheck u_check(m_caster, max_range);
- Trinity::WorldObjectSearcher<Trinity::CannibalizeObjectCheck > searcher(result, u_check);
+ Trinity::WorldObjectSearcher<Trinity::CannibalizeObjectCheck > searcher(m_caster, result, u_check);
m_caster->VisitNearbyGridObject(max_range, searcher);
if(!result)
m_caster->VisitNearbyWorldObject(max_range, searcher);
@@ -511,6 +528,8 @@ void Spell::FillTargetMap()
case SPELL_EFFECT_CREATE_ITEM:
case SPELL_EFFECT_TRIGGER_SPELL:
case SPELL_EFFECT_SKILL_STEP:
+ case SPELL_EFFECT_PROFICIENCY:
+ case SPELL_EFFECT_SUMMON_OBJECT_WILD:
case SPELL_EFFECT_SELF_RESURRECT:
case SPELL_EFFECT_REPUTATION:
case SPELL_EFFECT_LEARN_SPELL:
@@ -543,7 +562,9 @@ void Spell::FillTargetMap()
break;
case SPELL_EFFECT_SUMMON_CHANGE_ITEM:
case SPELL_EFFECT_ADD_FARSIGHT:
+ case SPELL_EFFECT_APPLY_GLYPH:
case SPELL_EFFECT_STUCK:
+ case SPELL_EFFECT_FEED_PET:
case SPELL_EFFECT_DESTROY_ALL_TOTEMS:
tmpUnitMap.push_back(m_caster);
break;
@@ -554,8 +575,8 @@ void Spell::FillTargetMap()
/*case SPELL_EFFECT_ENCHANT_ITEM:
case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY:
case SPELL_EFFECT_DISENCHANT:
- case SPELL_EFFECT_FEED_PET:
case SPELL_EFFECT_PROSPECTING:
+ case SPELL_EFFECT_MILLING:
if(m_targets.getItemTarget())
AddItemTarget(m_targets.getItemTarget(), i);
break;*/
@@ -596,7 +617,6 @@ void Spell::FillTargetMap()
}
}
-
if(IsChanneledSpell(m_spellInfo) && !tmpUnitMap.empty())
m_needAliveTargetMask |= (1<<i);
@@ -633,34 +653,43 @@ void Spell::prepareDataForTriggerSystem()
// Ñan spell trigger another or not ( m_canTrigger )
// Create base triggers flags for Attacker and Victim ( m_procAttacker and m_procVictim)
//==========================================================================================
-
// Fill flag can spell trigger or not
- if (!m_IsTriggeredSpell)
+ // TODO: possible exist spell attribute for this
+ m_canTrigger = false;
+
+ if (m_CastItem)
+ m_canTrigger = false; // Do not trigger from item cast spell
+ else if (!m_IsTriggeredSpell)
m_canTrigger = true; // Normal cast - can trigger
else if (!m_triggeredByAuraSpell)
m_canTrigger = true; // Triggered from SPELL_EFFECT_TRIGGER_SPELL - can trigger
- else // Exceptions (some periodic triggers)
+
+ if (!m_canTrigger) // Exceptions (some periodic triggers)
{
- m_canTrigger = false; // Triggered spells can`t trigger another
switch (m_spellInfo->SpellFamilyName)
{
case SPELLFAMILY_MAGE: // Arcane Missles / Blizzard triggers need do it
- if (m_spellInfo->SpellFamilyFlags & 0x0000000000200080LL) m_canTrigger = true;
+ if (m_spellInfo->SpellFamilyFlags[0] & 0x200080) m_canTrigger = true;
break;
case SPELLFAMILY_WARLOCK: // For Hellfire Effect / Rain of Fire / Seed of Corruption triggers need do it
- if (m_spellInfo->SpellFamilyFlags & 0x0000800000000060LL) m_canTrigger = true;
+ if (m_spellInfo->SpellFamilyFlags[1] & 0x00008000 || m_spellInfo->SpellFamilyFlags[0] & 0x00000060) m_canTrigger = true;
+ break;
+ case SPELLFAMILY_PRIEST: // For Penance heal/damage triggers need do it
+ if (m_spellInfo->SpellFamilyFlags[1] & 0x00018000) m_canTrigger = true;
+ break;
+ case SPELLFAMILY_ROGUE: // For poisons need do it
+ if (m_spellInfo->SpellFamilyFlags[1] & 0x00000010 || m_spellInfo->SpellFamilyFlags[0] & 0x1001E000) m_canTrigger = true;
break;
- case SPELLFAMILY_HUNTER: // Hunter Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect
- if (m_spellInfo->SpellFamilyFlags & 0x0000200000000014LL) m_canTrigger = true;
+ case SPELLFAMILY_HUNTER: // Hunter Rapid Killing/Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect/Explosive Shot
+ if (m_spellInfo->SpellFamilyFlags[1] & 0x01002000
+ || m_spellInfo->SpellFamilyFlags[0] & 0x00000214 ||
+ m_spellInfo->SpellFamilyFlags[2] & 0x200) m_canTrigger = true;
break;
- case SPELLFAMILY_PALADIN: // For Holy Shock triggers need do it
- if (m_spellInfo->SpellFamilyFlags & 0x0001000000200000LL) m_canTrigger = true;
+ case SPELLFAMILY_PALADIN: // For Judgements (all) / Holy Shock triggers need do it
+ if (m_spellInfo->SpellFamilyFlags[1] & 0x00010009 || m_spellInfo->SpellFamilyFlags[0] & 0x00B80400) m_canTrigger = true;
break;
}
}
- // Do not trigger from item cast spell
- if (m_CastItem)
- m_canTrigger = false;
// Get data for type of attack and fill base info for trigger
switch (m_spellInfo->DmgClass)
@@ -670,21 +699,30 @@ void Spell::prepareDataForTriggerSystem()
m_procVictim = PROC_FLAG_TAKEN_MELEE_SPELL_HIT;
break;
case SPELL_DAMAGE_CLASS_RANGED:
- m_procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_SPELL_HIT;
- m_procVictim = PROC_FLAG_TAKEN_RANGED_SPELL_HIT;
+ // Auto attack
+ if (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG)
+ {
+ m_procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_HIT;
+ m_procVictim = PROC_FLAG_TAKEN_RANGED_HIT;
+ }
+ else // Ranged spell attack
+ {
+ m_procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_SPELL_HIT;
+ m_procVictim = PROC_FLAG_TAKEN_RANGED_SPELL_HIT;
+ }
break;
default:
- if (IsPositiveSpell(m_spellInfo->Id)) // Check for positive spell
+ if (IsPositiveSpell(m_spellInfo->Id)) // Check for positive spell
{
m_procAttacker = PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL;
m_procVictim = PROC_FLAG_TAKEN_POSITIVE_SPELL;
}
- else if (m_spellInfo->Id == 5019) // Wands
+ else if (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG) // Wands auto attack
{
- m_procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_SPELL_HIT;
- m_procVictim = PROC_FLAG_TAKEN_RANGED_SPELL_HIT;
+ m_procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_HIT;
+ m_procVictim = PROC_FLAG_TAKEN_RANGED_HIT;
}
- else
+ else // Negative spell
{
m_procAttacker = PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT;
m_procVictim = PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT;
@@ -693,7 +731,7 @@ void Spell::prepareDataForTriggerSystem()
}
// Hunter traps spells (for Entrapment trigger)
// Gives your Immolation Trap, Frost Trap, Explosive Trap, and Snake Trap ....
- if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellInfo->SpellFamilyFlags & 0x0000200000000014LL)
+ if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && (m_spellInfo->SpellFamilyFlags[1] & 0x00002000 || m_spellInfo->SpellFamilyFlags[0] & 0x1C))
m_procAttacker |= PROC_FLAG_ON_TRAP_ACTIVATION;
}
@@ -702,8 +740,6 @@ void Spell::CleanupTargetList()
m_UniqueTargetInfo.clear();
m_UniqueGOTargetInfo.clear();
m_UniqueItemInfo.clear();
- m_countOfHit = 0;
- m_countOfMiss = 0;
m_delayMoment = 0;
}
@@ -712,6 +748,9 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
if( m_spellInfo->Effect[effIndex]==0 )
return;
+ // Check for effect immune skip if immuned
+ bool immuned = pVictim->IsImmunedToSpellEffect(m_spellInfo, effIndex);
+
uint64 targetGUID = pVictim->GetGUID();
// Lookup target in already in list
@@ -719,7 +758,8 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
{
if (targetGUID == ihit->targetGUID) // Found in list
{
- ihit->effectMask |= 1<<effIndex; // Add only effect mask
+ if (!immuned)
+ ihit->effectMask |= 1<<effIndex; // Add only effect mask if not immuned
return;
}
}
@@ -729,7 +769,7 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
// Get spell hit result on target
TargetInfo target;
target.targetGUID = targetGUID; // Store target GUID
- target.effectMask = 1<<effIndex; // Store index of effect
+ target.effectMask = immuned ? 0 : 1<<effIndex; // Store index of effect if not immuned
target.processed = false; // Effects not apply on target
target.damage = 0;
@@ -743,11 +783,6 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
else
target.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE;
- if (target.missCondition == SPELL_MISS_NONE)
- ++m_countOfHit;
- else
- ++m_countOfMiss;
-
// Spell have speed - need calculate incoming time
if (m_spellInfo->speed > 0.0f)
{
@@ -828,8 +863,6 @@ void Spell::AddGOTarget(GameObject* pVictim, uint32 effIndex)
else
target.timeDelay = 0LL;
- ++m_countOfHit;
-
// Add target to list
m_UniqueGOTargetInfo.push_back(target);
}
@@ -863,83 +896,6 @@ void Spell::AddItemTarget(Item* pitem, uint32 effIndex)
target.effectMask = 1<<effIndex;
m_UniqueItemInfo.push_back(target);
}
-/*
-void Spell::doTriggers(SpellMissInfo missInfo, uint32 damage, SpellSchoolMask damageSchoolMask, uint32 block, uint32 absorb, bool crit)
-{
- // Do triggers depends from hit result (triggers on hit do in effects)
- // Set aura states depends from hit result
- if (missInfo!=SPELL_MISS_NONE)
- {
- // Miss/dodge/parry/block only for melee based spells
- // Resist only for magic based spells
- switch (missInfo)
- {
- case SPELL_MISS_MISS:
- if(m_caster->GetTypeId()== TYPEID_PLAYER)
- ((Player*)m_caster)->UpdateWeaponSkill(BASE_ATTACK);
-
- m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_MISS, m_spellInfo, m_IsTriggeredSpell);
- break;
- case SPELL_MISS_RESIST:
- m_caster->ProcDamageAndSpell(unitTarget, PROC_FLAG_TARGET_RESISTS, PROC_FLAG_RESIST_SPELL, 0, damageSchoolMask, m_spellInfo, m_IsTriggeredSpell);
- break;
- case SPELL_MISS_DODGE:
- if(unitTarget->GetTypeId() == TYPEID_PLAYER)
- ((Player*)unitTarget)->UpdateDefense();
-
- // Overpower
- if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_WARRIOR)
- {
- ((Player*) m_caster)->AddComboPoints(unitTarget, 1);
- m_caster->StartReactiveTimer( REACTIVE_OVERPOWER );
- }
-
- // Riposte
- if (unitTarget->getClass() != CLASS_ROGUE)
- {
- unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true);
- unitTarget->StartReactiveTimer( REACTIVE_DEFENSE );
- }
-
- m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_DODGE, m_spellInfo, m_IsTriggeredSpell);
- break;
- case SPELL_MISS_PARRY:
- // Update victim defense ?
- if(unitTarget->GetTypeId() == TYPEID_PLAYER)
- ((Player*)unitTarget)->UpdateDefense();
- // Mongoose bite - set only Counterattack here
- if (unitTarget->getClass() == CLASS_HUNTER)
- {
- unitTarget->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true);
- unitTarget->StartReactiveTimer( REACTIVE_HUNTER_PARRY );
- }
- else
- {
- unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true);
- unitTarget->StartReactiveTimer( REACTIVE_DEFENSE );
- }
- m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_PARRY, m_spellInfo, m_IsTriggeredSpell);
- break;
- case SPELL_MISS_BLOCK:
- unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true);
- unitTarget->StartReactiveTimer( REACTIVE_DEFENSE );
-
- m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_BLOCK, m_spellInfo, m_IsTriggeredSpell);
- break;
- // Trigger from this events not supported
- case SPELL_MISS_EVADE:
- case SPELL_MISS_IMMUNE:
- case SPELL_MISS_IMMUNE2:
- case SPELL_MISS_DEFLECT:
- case SPELL_MISS_ABSORB:
- // Trigger from reflects need do after get reflect result
- case SPELL_MISS_REFLECT:
- break;
- default:
- break;
- }
- }
-}*/
void Spell::DoAllEffectOnTarget(TargetInfo *target)
{
@@ -949,15 +905,13 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
// Get mask of effects for target
uint32 mask = target->effectMask;
- if (mask == 0) // No effects
- return;
Unit* unit = m_caster->GetGUID()==target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster,target->targetGUID);
if (!unit)
return;
// Get original caster (if exist) and calculate damage/healing from him data
- Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
+ Unit *caster = m_originalCaster ? m_originalCaster : m_caster;
// Skip if m_originalCaster not avaiable
if (!caster)
@@ -1005,7 +959,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
if (crit)
{
procEx |= PROC_EX_CRITICAL_HIT;
- addhealth = caster->SpellCriticalBonus(m_spellInfo, addhealth, NULL);
+ addhealth = caster->SpellCriticalHealingBonus(m_spellInfo, addhealth, NULL);
}
else
procEx |= PROC_EX_NORMAL_HIT;
@@ -1044,44 +998,12 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
caster->DealSpellDamage(&damageInfo, true);
- // Shadow Word: Death - deals damage equal to damage done to caster if victim is not killed
- if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && m_spellInfo->SpellFamilyFlags&0x0000000200000000LL &&
- caster != unitTarget && unitTarget->isAlive())
- {
- // Redirect damage to caster if victim Alive
- damageInfo.target = caster;
- damageInfo.absorb = 0;
- damageInfo.resist = 0;
- damageInfo.blocked = 0;
- // Send log damage message to client
- caster->SendSpellNonMeleeDamageLog(&damageInfo);
- caster->DealSpellDamage(&damageInfo, true);
- }
// Judgement of Blood
- else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && m_spellInfo->SpellFamilyFlags & 0x0000000800000000LL && m_spellInfo->SpellIconID==153)
+ if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && m_spellInfo->SpellFamilyFlags[1] & 0x00000008 && m_spellInfo->SpellIconID==153)
{
int32 damagePoint = damageInfo.damage * 33 / 100;
m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true);
}
- // Bloodthirst
- else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
- {
- uint32 BTAura = 0;
- switch(m_spellInfo->Id)
- {
- case 23881: BTAura = 23885; break;
- case 23892: BTAura = 23886; break;
- case 23893: BTAura = 23887; break;
- case 23894: BTAura = 23888; break;
- case 25251: BTAura = 25252; break;
- case 30335: BTAura = 30339; break;
- default:
- sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo->Id);
- break;
- }
- if (BTAura)
- m_caster->CastSpell(m_caster,BTAura,true);
- }
}
// Passive spell hits/misses or active spells only misses (only triggers)
else
@@ -1105,14 +1027,14 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
if( !m_caster->IsFriendlyTo(unit) && !IsPositiveSpell(m_spellInfo->Id))
{
- if( !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) )
+ if( !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) )
{
m_caster->CombatStart(unit);
}
else if(m_customAttr & SPELL_ATTR_CU_AURA_CC)
{
if(!unit->IsStandState())
- unit->SetStandState(PLAYER_STATE_NONE);
+ unit->SetStandState(UNIT_STAND_STATE_STAND);
}
}
}
@@ -1125,25 +1047,37 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
// Recheck immune (only for delayed spells)
if( m_spellInfo->speed &&
!(m_spellInfo->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY)
- && (unit->IsImmunedToDamage(GetSpellSchoolMask(m_spellInfo),true) ||
- unit->IsImmunedToSpell(m_spellInfo,true) ))
+ && (unit->IsImmunedToDamage(GetSpellSchoolMask(m_spellInfo)) ||
+ unit->IsImmunedToSpell(m_spellInfo)))
{
m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_IMMUNE);
m_damage = 0;
return;
}
+ if (unit->GetTypeId() == TYPEID_PLAYER)
+ {
+ ((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id);
+ ((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id);
+ }
+
+ if(m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit);
+ }
+
if( m_caster != unit )
{
- if (unit->GetCharmerOrOwnerGUID() != m_caster->GetGUID())
+ // Recheck UNIT_FLAG_NON_ATTACKABLE for delayed spells
+ if (m_spellInfo->speed > 0.0f &&
+ unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) &&
+ unit->GetCharmerOrOwnerGUID() != m_caster->GetGUID())
{
- if (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- {
- m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
+ m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
m_damage = 0;
- return;
- }
+ return;
}
+
if( !m_caster->IsFriendlyTo(unit) )
{
// for delayed spells ignore not visible explicit target
@@ -1172,7 +1106,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
// assisting case, healing and resurrection
if(unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER))
m_caster->SetContestedPvP();
- if( unit->isInCombat() && !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) )
+ if( unit->isInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) )
{
m_caster->SetInCombatState(unit->GetCombatTimer() > 0);
unit->getHostilRefManager().threatAssist(m_caster, 0.0f);
@@ -1190,6 +1124,10 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
unit->IncrDiminishing(m_diminishGroup);
}
+ // Apply additional spell effects to target
+ if (m_preCastSpell)
+ m_caster->CastSpell(unit,m_preCastSpell, true, m_CastItem);
+
for(uint32 effectNumber=0;effectNumber<3;effectNumber++)
{
if (effectMask & (1<<effectNumber))
@@ -1344,6 +1282,16 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin
if(!cur)
return;
+ // Get spell max affected targets
+ /*uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets;
+ Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
+ for(Unit::AuraList::const_iterator m = mod.begin(); m != mod.end(); ++m)
+ {
+ if (!(*m)->isAffectedOnSpell(m_spellInfo))
+ continue;
+ unMaxTargets+=(*m)->GetModifier()->m_amount;
+ }*/
+
//FIXME: This very like horrible hack and wrong for most spells
if(m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE)
max_range += num * CHAIN_SPELL_JUMP_RADIUS;
@@ -1455,7 +1403,7 @@ Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 en
{
Creature* target = NULL;
Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster, entry, true, radius);
- Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(target, u_check);
+ Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster, target, u_check);
m_caster->VisitNearbyObject(radius, searcher);
return target;
}
@@ -1469,13 +1417,13 @@ Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 en
case SPELL_TARGETS_ENEMY:
{
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius);
- Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, u_check);
+ Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check);
m_caster->VisitNearbyObject(radius, searcher);
}break;
case SPELL_TARGETS_ALLY:
{
Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius);
- Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(target, u_check);
+ Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check);
m_caster->VisitNearbyObject(radius, searcher);
}break;
}
@@ -1559,7 +1507,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
case TARGET_UNIT_TARGET_RAID:
case TARGET_UNIT_TARGET_ANY: // SelectMagnetTarget()?
case TARGET_UNIT_TARGET_PARTY:
- case TARGET_UNIT_SINGLE_UNKNOWN:
TagUnitMap.push_back(target);
break;
case TARGET_UNIT_PARTY_TARGET:
@@ -1698,7 +1645,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, true, ((Player*)m_caster)->m_homebindMapId);
break;
-
case TARGET_IN_FRONT_OF_CASTER:
case TARGET_UNIT_CONE_ENEMY_UNKNOWN:
if(m_customAttr & SPELL_ATTR_CU_CONE_BACK)
@@ -1714,6 +1660,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
// nearby target
case TARGET_UNIT_NEARBY_ALLY:
+ case TARGET_UNIT_NEARBY_ALLY_UNK:
if(!m_targets.getUnitTarget())
m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ALLY));
if(m_targets.getUnitTarget())
@@ -1724,7 +1671,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ALLY);
}
break;
- case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA:
+ case TARGET_UNIT_NEARBY_ENEMY:
if(!m_targets.getUnitTarget())
m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ENEMY));
if(m_targets.getUnitTarget())
@@ -1765,7 +1712,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
if(i_spellST->second.targetEntry)
{
Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range);
- Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(p_GameObject,go_check);
+ Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(m_caster, p_GameObject,go_check);
m_caster->VisitNearbyGridObject(range, checker);
if(p_GameObject)
@@ -1795,7 +1742,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
Creature *p_Creature = NULL;
Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range);
- Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(p_Creature, u_check);
+ Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster, p_Creature, u_check);
m_caster->VisitNearbyObject(range, searcher);
if(p_Creature )
@@ -2011,7 +1958,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
}
}
-void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura)
+void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)
{
if(m_CastItem)
m_castItemGUID = m_CastItem->GetGUID();
@@ -2033,7 +1980,7 @@ void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura)
m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1));
//Prevent casting at cast another spell (ServerSide check)
- if(m_caster->IsNonMeleeSpellCasted(false, true) && m_cast_count)
+ if(m_caster->IsNonMeleeSpellCasted(false, true, true) && m_cast_count)
{
SendCastResult(SPELL_FAILED_SPELL_IN_PROGRESS);
finish(false);
@@ -2128,11 +2075,11 @@ void Spell::cancel(bool report)
{
Unit* unit = m_caster->GetGUID()==(*ihit).targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
if( unit && unit->isAlive() )
- unit->RemoveAurasDueToCasterSpell(m_spellInfo->Id, m_caster->GetGUID());
+ unit->RemoveAurasByCasterSpell(m_spellInfo->Id, m_caster->GetGUID());
}
}
- m_caster->RemoveAurasDueToCasterSpell(m_spellInfo->Id, m_caster->GetGUID());
+ m_caster->RemoveAurasByCasterSpell(m_spellInfo->Id, m_caster->GetGUID());
SendChannelUpdate(0);
SendInterrupted(0);
SendCastResult(report ? SPELL_FAILED_INTERRUPTED : SPELL_FAILED_DONT_REPORT);
@@ -2206,10 +2153,43 @@ void Spell::cast(bool skipCheck)
FillTargetMap();
+ if(m_spellInfo->SpellFamilyName)
+ {
+ if (m_spellInfo->excludeCasterAuraSpell)
+ m_preCastSpell = m_spellInfo->excludeCasterAuraSpell;
+ else if (m_spellInfo->excludeTargetAuraSpell)
+ m_preCastSpell = m_spellInfo->excludeTargetAuraSpell;
+ }
+ switch (m_spellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ {
+ if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
+ m_preCastSpell = 11196; // Recently Bandaged
+ else if(m_spellInfo->SpellIconID == 1662 && m_spellInfo->AttributesEx & 0x20)
+ m_preCastSpell = 23230; // Blood Fury - Healing Reduction
+ break;
+ }
+
+ case SPELLFAMILY_PRIEST:
+ {
+ if (m_spellInfo->Id == 47585) // Dispersion (transform)
+ m_preCastSpell = 60069; // Dispersion (mana regen)
+ break;
+ }
+ }
// traded items have trade slot instead of guid in m_itemTargetGUID
// set to real guid to be sent later to the client
m_targets.updateTradeSlotItem();
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (m_CastItem)
+ ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry());
+
+ ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id);
+ }
+
// CAST SPELL
SendSpellCooldown();
@@ -2252,31 +2232,29 @@ void Spell::cast(bool skipCheck)
handle_immediate();
}
- //handle SPELL_AURA_ADD_TARGET_TRIGGER auras
//are there any spells need to be triggered after hit?
+ // handle SPELL_AURA_ADD_TARGET_TRIGGER auras
Unit::AuraList const& targetTriggers = m_caster->GetAurasByType(SPELL_AURA_ADD_TARGET_TRIGGER);
for(Unit::AuraList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i)
{
- SpellEntry const *auraSpellInfo = (*i)->GetSpellProto();
- uint32 auraSpellIdx = (*i)->GetEffIndex();
- if (IsAffectedBy(auraSpellInfo, auraSpellIdx))
- {
- for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
- if( ihit->effectMask & (1<<auraSpellIdx) )
+ if (!(*i)->isAffectedOnSpell(m_spellInfo))
+ continue;
+ for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
+ if( ihit->missCondition == SPELL_MISS_NONE )
{
// check m_caster->GetGUID() let load auras at login and speedup most often case
Unit *unit = m_caster->GetGUID()== ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
if (unit && unit->isAlive())
{
+ SpellEntry const *auraSpellInfo = (*i)->GetSpellProto();
+ uint32 auraSpellIdx = (*i)->GetEffIndex();
// Calculate chance at that moment (can be depend for example from combo points)
int32 chance = m_caster->CalculateSpellDamage(auraSpellInfo, auraSpellIdx, (*i)->GetBasePoints(),unit);
-
if(roll_chance_i(chance))
for (int j=0; j != (*i)->GetStackAmount(); ++j)
m_caster->CastSpell(unit, auraSpellInfo->EffectTriggerSpell[auraSpellIdx], true, NULL, (*i));
}
}
- }
}
// combo points should not be taken before SPELL_AURA_ADD_TARGET_TRIGGER auras are handled
@@ -2304,9 +2282,16 @@ void Spell::handle_immediate()
// start channeling if applicable
if(IsChanneledSpell(m_spellInfo))
{
- m_spellState = SPELL_STATE_CASTING;
- m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags);
- SendChannelStart(GetSpellDuration(m_spellInfo));
+ int32 duration = GetSpellDuration(m_spellInfo);
+ if (duration)
+ {
+ // Apply duration mod
+ if(Player* modOwner = m_caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
+ m_spellState = SPELL_STATE_CASTING;
+ m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags);
+ SendChannelStart(duration);
+ }
}
// process immediate effects (items, ground, etc.) also initialize some variables
@@ -2487,7 +2472,7 @@ void Spell::SendSpellCooldown()
// shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK)
// prevent 0 cooldowns set by another way
- if (rec <= 0 && catrec <= 0 && (cat == 76 || cat == 351))
+ if (rec <= 0 && catrec <= 0 && (cat == 76 || IsAutoRepeatRangedSpell(m_spellInfo) && m_spellInfo->Id != SPELL_ID_AUTOSHOT))
rec = _player->GetAttackTime(RANGED_ATTACK);
// Now we have cooldown data (if found any), time to apply mods
@@ -2525,7 +2510,7 @@ void Spell::SendSpellCooldown()
if(*i_scset == m_spellInfo->Id) // skip main spell, already handled above
continue;
- _player->AddSpellCooldown(m_spellInfo->Id, m_CastItem ? m_CastItem->GetEntry() : 0, catrecTime);
+ _player->AddSpellCooldown(*i_scset, m_CastItem ? m_CastItem->GetEntry() : 0, catrecTime);
}
}
}
@@ -2703,9 +2688,9 @@ void Spell::SendCastResult(uint8 result)
if(result != 0)
{
WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
+ data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
data << uint32(m_spellInfo->Id);
data << uint8(result); // problem
- data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
switch (result)
{
case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
@@ -2726,8 +2711,8 @@ void Spell::SendCastResult(uint8 result)
case 45373: // Bloodberry Elixir
data << uint32(4075);
break;
- default: // default case
- data << uint32(m_spellInfo->AreaId);
+ default: // default case (don't must be)
+ data << uint32(0);
break;
}
break;
@@ -2746,18 +2731,11 @@ void Spell::SendCastResult(uint8 result)
case SPELL_FAILED_EQUIPPED_ITEM_CLASS:
data << uint32(m_spellInfo->EquippedItemClass);
data << uint32(m_spellInfo->EquippedItemSubClassMask);
- data << uint32(m_spellInfo->EquippedItemInventoryTypeMask);
+ //data << uint32(m_spellInfo->EquippedItemInventoryTypeMask);
break;
}
((Player*)m_caster)->GetSession()->SendPacket(&data);
}
- else
- {
- WorldPacket data(SMSG_CLEAR_EXTRA_AURA_INFO, (8+4));
- data.append(m_caster->GetPackGUID());
- data << uint32(m_spellInfo->Id);
- ((Player*)m_caster)->GetSession()->SendPacket(&data);
- }
}
void Spell::SendSpellStart()
@@ -2771,6 +2749,9 @@ void Spell::SendSpellStart()
if(IsRangedSpell())
castFlags |= CAST_FLAG_AMMO;
+ if(m_spellInfo->runeCostID)
+ castFlags |= CAST_FLAG_UNKNOWN10;
+
Unit *target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster;
WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2));
@@ -2780,14 +2761,32 @@ void Spell::SendSpellStart()
data.append(m_caster->GetPackGUID());
data.append(m_caster->GetPackGUID());
- data << uint32(m_spellInfo->Id);
- data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
- data << uint16(castFlags);
- data << uint32(m_timer);
+ data << uint8(m_cast_count); // pending spell cast?
+ data << uint32(m_spellInfo->Id); // spellId
+ data << uint32(castFlags); // cast flags
+ data << uint32(m_timer); // delay?
m_targets.write(&data);
- if( castFlags & CAST_FLAG_AMMO )
+ if ( castFlags & CAST_FLAG_UNKNOWN6 ) // predicted power?
+ data << uint32(0);
+
+ if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list
+ {
+ uint8 v1 = 0;//m_runesState;
+ uint8 v2 = 0;//((Player*)m_caster)->GetRunesState();
+ data << uint8(v1); // runes state before
+ data << uint8(v2); // runes state after
+ for(uint8 i = 0; i < MAX_RUNES; ++i)
+ {
+ uint8 m = (1 << i);
+ if(m & v1) // usable before...
+ if(!(m & v2)) // ...but on cooldown now...
+ data << uint8(0); // some unknown byte (time?)
+ }
+ }
+
+ if ( castFlags & CAST_FLAG_AMMO )
WriteAmmoToPacket(&data);
m_caster->SendMessageToSet(&data, true);
@@ -2807,24 +2806,68 @@ void Spell::SendSpellGo()
if(IsRangedSpell())
castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
+ if((m_caster->GetTypeId() == TYPEID_PLAYER) && (m_caster->getClass() == CLASS_DEATH_KNIGHT) && m_spellInfo->runeCostID)
+ {
+ castFlags |= CAST_FLAG_UNKNOWN10; // same as in SMSG_SPELL_START
+ castFlags |= CAST_FLAG_UNKNOWN6; // makes cooldowns visible
+ castFlags |= CAST_FLAG_UNKNOWN7; // rune cooldowns list
+ }
+
WorldPacket data(SMSG_SPELL_GO, 50); // guess size
+
if(m_CastItem)
data.append(m_CastItem->GetPackGUID());
else
data.append(m_caster->GetPackGUID());
data.append(m_caster->GetPackGUID());
- data << uint32(m_spellInfo->Id);
- data << uint16(castFlags);
+ data << uint8(m_cast_count); // pending spell cast?
+ data << uint32(m_spellInfo->Id); // spellId
+ data << uint32(castFlags); // cast flags
data << uint32(getMSTime()); // timestamp
WriteSpellGoTargets(&data);
m_targets.write(&data);
- if( castFlags & CAST_FLAG_AMMO )
+ if ( castFlags & CAST_FLAG_UNKNOWN6 ) // unknown wotlk, predicted power?
+ data << uint32(0);
+
+ if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list
+ {
+ uint8 v1 = m_runesState;
+ uint8 v2 = ((Player*)m_caster)->GetRunesState();
+ data << uint8(v1); // runes state before
+ data << uint8(v2); // runes state after
+ for(uint8 i = 0; i < MAX_RUNES; ++i)
+ {
+ uint8 m = (1 << i);
+ if(m & v1) // usable before...
+ if(!(m & v2)) // ...but on cooldown now...
+ data << uint8(0); // some unknown byte (time?)
+ }
+ }
+
+ if ( castFlags & CAST_FLAG_UNKNOWN4 ) // unknown wotlk
+ {
+ data << float(0);
+ data << uint32(0);
+ }
+
+ if ( castFlags & CAST_FLAG_AMMO )
WriteAmmoToPacket(&data);
+ if ( castFlags & CAST_FLAG_UNKNOWN5 ) // unknown wotlk
+ {
+ data << uint32(0);
+ data << uint32(0);
+ }
+
+ if ( m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION )
+ {
+ data << uint8(0);
+ }
+
m_caster->SendMessageToSet(&data, true);
}
@@ -2869,15 +2912,36 @@ void Spell::WriteAmmoToPacket( WorldPacket * data )
void Spell::WriteSpellGoTargets( WorldPacket * data )
{
- *data << (uint8)m_countOfHit;
+ // This function also fill data for channeled spells:
+ // m_needAliveTargetMask req for stop channelig if one target die
+ uint32 hit = m_UniqueGOTargetInfo.size(); // Always hits on GO
+ uint32 miss = 0;
+ for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
+ {
+ if ((*ihit).effectMask == 0) // No effect apply - all immuned add state
+ {
+ // possibly SPELL_MISS_IMMUNE2 for this??
+ ihit->missCondition = SPELL_MISS_IMMUNE2;
+ miss++;
+ }
+ else if ((*ihit).missCondition == SPELL_MISS_NONE)
+ hit++;
+ else
+ miss++;
+ }
+
+ *data << (uint8)hit;
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits
+ {
*data << uint64(ihit->targetGUID);
+ m_needAliveTargetMask |=ihit->effectMask;
+ }
for(std::list<GOTargetInfo>::iterator ighit= m_UniqueGOTargetInfo.begin();ighit != m_UniqueGOTargetInfo.end();++ighit)
*data << uint64(ighit->targetGUID); // Always hits
- *data << (uint8)m_countOfMiss;
+ *data << (uint8)miss;
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
{
if( ihit->missCondition != SPELL_MISS_NONE ) // Add only miss
@@ -2888,6 +2952,9 @@ void Spell::WriteSpellGoTargets( WorldPacket * data )
*data << uint8(ihit->reflectResult);
}
}
+ // Reset m_needAliveTargetMask for non channeled spell
+ if(!IsChanneledSpell(m_spellInfo))
+ m_needAliveTargetMask = 0;
}
void Spell::SendLogExecute()
@@ -2952,30 +3019,19 @@ void Spell::SendLogExecute()
data << uint8(0);
break;
case SPELL_EFFECT_CREATE_ITEM:
+ case SPELL_EFFECT_CREATE_ITEM_2:
data << uint32(m_spellInfo->EffectItemType[0]);
break;
case SPELL_EFFECT_SUMMON:
- case SPELL_EFFECT_SUMMON_WILD:
- case SPELL_EFFECT_SUMMON_GUARDIAN:
case SPELL_EFFECT_TRANS_DOOR:
case SPELL_EFFECT_SUMMON_PET:
- case SPELL_EFFECT_SUMMON_POSSESSED:
- case SPELL_EFFECT_SUMMON_TOTEM:
case SPELL_EFFECT_SUMMON_OBJECT_WILD:
case SPELL_EFFECT_CREATE_HOUSE:
case SPELL_EFFECT_DUEL:
- case SPELL_EFFECT_SUMMON_TOTEM_SLOT1:
- case SPELL_EFFECT_SUMMON_TOTEM_SLOT2:
- case SPELL_EFFECT_SUMMON_TOTEM_SLOT3:
- case SPELL_EFFECT_SUMMON_TOTEM_SLOT4:
- case SPELL_EFFECT_SUMMON_PHANTASM:
- case SPELL_EFFECT_SUMMON_CRITTER:
case SPELL_EFFECT_SUMMON_OBJECT_SLOT1:
case SPELL_EFFECT_SUMMON_OBJECT_SLOT2:
case SPELL_EFFECT_SUMMON_OBJECT_SLOT3:
case SPELL_EFFECT_SUMMON_OBJECT_SLOT4:
- case SPELL_EFFECT_SUMMON_DEMON:
- case SPELL_EFFECT_150:
if(Unit *unit = m_targets.getUnitTarget())
data.append(unit->GetPackGUID());
else if(m_targets.getItemTargetGUID())
@@ -2994,6 +3050,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;
}
@@ -3007,13 +3070,16 @@ void Spell::SendInterrupted(uint8 result)
{
WorldPacket data(SMSG_SPELL_FAILURE, (8+4+1));
data.append(m_caster->GetPackGUID());
- data << m_spellInfo->Id;
- data << result;
+ data << uint8(m_cast_count);
+ data << uint32(m_spellInfo->Id);
+ data << uint8(result);
m_caster->SendMessageToSet(&data, true);
data.Initialize(SMSG_SPELL_FAILED_OTHER, (8+4));
data.append(m_caster->GetPackGUID());
- data << m_spellInfo->Id;
+ data << uint8(m_cast_count);
+ data << uint32(m_spellInfo->Id);
+ data << uint8(result);
m_caster->SendMessageToSet(&data, true);
}
@@ -3081,10 +3147,19 @@ void Spell::SendChannelStart(uint32 duration)
void Spell::SendResurrectRequest(Player* target)
{
- WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+2+4));
- data << m_caster->GetGUID();
- data << uint32(1) << uint16(0) << uint32(1);
+ // Both players and NPCs can resurrect using spells - have a look at creature 28487 for example
+ // However, the packet structure differs slightly
+
+ const char* sentName = m_caster->GetTypeId()==TYPEID_PLAYER ?"":m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex());
+ WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+strlen(sentName)+1+1+1));
+ data << uint64(m_caster->GetGUID());
+ data << uint32(strlen(sentName)+1);
+
+ data << sentName;
+ data << uint8(0);
+
+ data << uint8(m_caster->GetTypeId()==TYPEID_PLAYER ?0:1);
target->GetSession()->SendPacket(&data);
}
@@ -3137,7 +3212,7 @@ void Spell::TakeCastItem()
if (charges)
{
(charges > 0) ? --charges : ++charges; // abs(charges) less at 1 after use
- if (proto->Stackable < 2)
+ if (proto->Stackable == 1)
m_CastItem->SetSpellCharges(i, charges);
m_CastItem->SetState(ITEM_CHANGED, (Player*)m_caster);
}
@@ -3176,6 +3251,12 @@ void Spell::TakePower()
{
if(ihit->missCondition != SPELL_MISS_NONE && ihit->missCondition != SPELL_MISS_MISS/* && ihit->targetGUID!=m_caster->GetGUID()*/)
hit = false;
+ if (ihit->missCondition != SPELL_MISS_NONE)
+ {
+ //lower spell cost on fail (by talent aura)
+ if(Player *modOwner = ((Player*)m_caster)->GetSpellModOwner())
+ modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_SPELL_COST_REFUND_ON_FAIL, m_powerCost);
+ }
break;
}
if(hit && NeedsComboPoints(m_spellInfo))
@@ -3197,6 +3278,12 @@ void Spell::TakePower()
Powers powerType = Powers(m_spellInfo->powerType);
+ if(powerType == POWER_RUNE)
+ {
+ TakeRunePower();
+ return;
+ }
+
if(hit)
m_caster->ModifyPower(powerType, -m_powerCost);
else
@@ -3207,6 +3294,116 @@ 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_RUNE_TYPES]; // blood, frost, unholy, death
+
+ for(uint32 i = 0; i < RUNE_DEATH; ++i)
+ {
+ runeCost[i] = src->RuneCost[i];
+ }
+
+ runeCost[RUNE_DEATH] = 0; // calculated later
+
+ for(uint32 i = 0; i < MAX_RUNES; ++i)
+ {
+ uint8 rune = plr->GetCurrentRune(i);
+ if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0))
+ {
+ runeCost[rune]--;
+ }
+ }
+
+ for(uint32 i = 0; i < RUNE_DEATH; ++i)
+ {
+ if(runeCost[i] > 0)
+ {
+ runeCost[RUNE_DEATH] += runeCost[i];
+ }
+ }
+
+ if(runeCost[RUNE_DEATH] > 0)
+ return SPELL_FAILED_NO_POWER; // not sure if result code is correct
+
+ return 0;
+}
+
+void Spell::TakeRunePower()
+{
+ if(m_caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ Player *plr = (Player*)m_caster;
+
+ if(plr->getClass() != CLASS_DEATH_KNIGHT)
+ return;
+
+ SpellRuneCostEntry const *src = sSpellRuneCostStore.LookupEntry(m_spellInfo->runeCostID);
+
+ if(!src || (src->NoRuneCost() && src->NoRunicPowerGain()))
+ return;
+
+ m_runesState = plr->GetRunesState(); // store previous state
+
+ int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death
+
+ for(uint32 i = 0; i < RUNE_DEATH; ++i)
+ {
+ runeCost[i] = src->RuneCost[i];
+ }
+
+ runeCost[RUNE_DEATH] = 0; // calculated later
+
+ for(uint32 i = 0; i < MAX_RUNES; ++i)
+ {
+ uint8 rune = plr->GetCurrentRune(i);
+ if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0))
+ {
+ plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec
+ runeCost[rune]--;
+ }
+ }
+
+ runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_UNHOLY] + runeCost[RUNE_FROST];
+
+ if(runeCost[RUNE_DEATH] > 0)
+ {
+ for(uint32 i = 0; i < MAX_RUNES; ++i)
+ {
+ uint8 rune = plr->GetCurrentRune(i);
+ if((plr->GetRuneCooldown(i) == 0) && (rune == RUNE_DEATH))
+ {
+ plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec
+ runeCost[rune]--;
+ plr->ConvertRune(i, plr->GetBaseRune(i));
+ if(runeCost[RUNE_DEATH] == 0)
+ break;
+ }
+ }
+ }
+
+ // you can gain some runic power when use runes
+ float rp = src->runePowerGain;;
+ rp *= sWorld.getRate(RATE_POWER_RUNICPOWER_INCOME);
+ plr->ModifyPower(POWER_RUNIC_POWER, (int32)rp);
+}
+
void Spell::TakeReagents()
{
if(m_IsTriggeredSpell) // reagents used in triggered spell removed by original spell or don't must be removed.
@@ -3215,11 +3412,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++)
{
@@ -3282,14 +3477,9 @@ void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTar
gameObjTarget = pGOTarget;
uint8 eff = m_spellInfo->Effect[i];
- uint32 mechanic = m_spellInfo->EffectMechanic[i];
sLog.outDebug( "Spell: Effect : %u", eff);
- //Simply return. Do not display "immune" in red text on client
- if(unitTarget && unitTarget->IsImmunedToSpellEffect(eff, mechanic))
- return;
-
//we do not need DamageMultiplier here.
damage = CalculateDamage(i, NULL);
@@ -3343,12 +3533,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
@@ -3357,6 +3560,12 @@ uint8 Spell::CanCast(bool strict)
if(m_spellInfo->CasterAuraStateNot && m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraStateNot)))
return SPELL_FAILED_CASTER_AURASTATE;
+ // Caster aura req check if need
+ if(m_spellInfo->casterAuraSpell && !m_caster->HasAura(m_spellInfo->casterAuraSpell))
+ return SPELL_FAILED_CASTER_AURASTATE;
+ if(m_spellInfo->excludeCasterAuraSpell && m_caster->HasAura(m_spellInfo->excludeCasterAuraSpell))
+ return SPELL_FAILED_CASTER_AURASTATE;
+
// cancel autorepeat spells if cast start when moving
// (not wand currently autorepeat cast delayed to moving stop anyway in spell update code)
if( m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->isMoving() )
@@ -3375,6 +3584,12 @@ uint8 Spell::CanCast(bool strict)
if(m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot)))
return SPELL_FAILED_TARGET_AURASTATE;
+ // Target aura req check if need
+ if(m_spellInfo->targetAuraSpell && !target->HasAura(m_spellInfo->targetAuraSpell))
+ return SPELL_FAILED_CASTER_AURASTATE;
+ if(m_spellInfo->excludeTargetAuraSpell && target->HasAura(m_spellInfo->excludeTargetAuraSpell))
+ return SPELL_FAILED_CASTER_AURASTATE;
+
if(target != m_caster)
{
// target state requirements (apply to non-self only), to allow cast affects to self like Dirty Deeds
@@ -3400,6 +3615,20 @@ uint8 Spell::CanCast(bool strict)
}
}
}
+ else if (m_caster->GetTypeId()==TYPEID_PLAYER) // Target - is player caster
+ {
+ // Additional check for some spells
+ // If 0 spell effect empty - client not send target data (need use selection)
+ // TODO: check it on next client version
+ if (m_targets.m_targetMask == TARGET_FLAG_SELF &&
+ m_spellInfo->EffectImplicitTargetA[1] == TARGET_CHAIN_DAMAGE)
+ {
+ if (target = m_caster->GetUnit(*m_caster, ((Player *)m_caster)->GetSelection()))
+ m_targets.setUnitTarget(target);
+ else
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+ }
// check pet presents
for(int j=0;j<3;j++)
@@ -3451,13 +3680,14 @@ uint8 Spell::CanCast(bool strict)
if(IsPositiveSpell(m_spellInfo->Id))
{
- if(target->IsImmunedToSpell(m_spellInfo,false))
+ if(target->IsImmunedToSpell(m_spellInfo))
return SPELL_FAILED_TARGET_AURASTATE;
}
//Must be behind the target.
if( m_spellInfo->AttributesEx2 == 0x100000 && (m_spellInfo->AttributesEx & 0x200) == 0x200 && target->HasInArc(M_PI, m_caster)
- && (m_spellInfo->SpellFamilyName != SPELLFAMILY_DRUID || m_spellInfo->SpellFamilyFlags != 0x0000000000020000LL))
+ //Exclusion for Pounce: Facing Limitation was removed in 2.0.1, but it still uses the same, old Ex-Flags
+ && (m_spellInfo->SpellFamilyName != SPELLFAMILY_DRUID || !m_spellInfo->SpellFamilyFlags.IsEqual(0x20000,0,0)))
{
SendInterrupted(2);
return SPELL_FAILED_NOT_BEHIND;
@@ -3491,8 +3721,8 @@ uint8 Spell::CanCast(bool strict)
return SPELL_FAILED_NOT_IN_ARENA;
// zone check
- if(!IsSpellAllowedInLocation(m_spellInfo,m_caster->GetMapId(),m_caster->GetZoneId(),m_caster->GetAreaId()))
- return SPELL_FAILED_REQUIRES_AREA;
+ if(uint8 res= GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),m_caster->GetZoneId(),m_caster->GetAreaId()))
+ return res;
// not let players cast spells at mount (and let do it to creatures)
if( m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell &&
@@ -3545,7 +3775,7 @@ uint8 Spell::CanCast(bool strict)
cell.data.Part.reserved = ALL_DISTRICT;
MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range);
- MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck> checker(p_GameObject,go_check);
+ MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck> checker(m_caster, p_GameObject,go_check);
TypeContainerVisitor<MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -3583,7 +3813,7 @@ uint8 Spell::CanCast(bool strict)
cell.SetNoCreate(); // Really don't know what is that???
MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range);
- MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(p_Creature, u_check);
+ MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster, p_Creature, u_check);
TypeContainerVisitor<MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher);
@@ -3644,16 +3874,14 @@ uint8 Spell::CanCast(bool strict)
}
}*/
- if(!m_skipCheck && !m_triggeredByAuraSpell)
+ if(!m_IsTriggeredSpell)
+ {
if(uint8 castResult = CheckRange(strict))
return castResult;
- if(!m_IsTriggeredSpell)
- {
if(uint8 castResult = CheckPower())
return castResult;
- //if(!m_triggeredByAuraSpell) // triggered spell not affected by stun/etc
if(uint8 castResult = CheckCasterAuras())
return castResult;
}
@@ -3693,7 +3921,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;
@@ -3718,15 +3946,9 @@ uint8 Spell::CanCast(bool strict)
if(!learn_spellproto)
return SPELL_FAILED_NOT_KNOWN;
- if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id))
- return SPELL_FAILED_TOO_MANY_SKILLS;
-
if(m_spellInfo->spellLevel > pet->getLevel())
return SPELL_FAILED_LOWLEVEL;
- if(!pet->HasTPForSpell(learn_spellproto->Id))
- return SPELL_FAILED_TRAINING_POINTS;
-
break;
}
case SPELL_EFFECT_LEARN_PET_SPELL:
@@ -3741,20 +3963,18 @@ uint8 Spell::CanCast(bool strict)
if(!learn_spellproto)
return SPELL_FAILED_NOT_KNOWN;
- if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id))
- return SPELL_FAILED_TOO_MANY_SKILLS;
-
if(m_spellInfo->spellLevel > pet->getLevel())
return SPELL_FAILED_LOWLEVEL;
- if(!pet->HasTPForSpell(learn_spellproto->Id))
- return SPELL_FAILED_TRAINING_POINTS;
-
break;
}
case SPELL_EFFECT_FEED_PET:
{
- if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_targets.getItemTarget() )
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ return SPELL_FAILED_BAD_TARGETS;
+
+ Item* foodItem = m_targets.getItemTarget();
+ if(!foodItem)
return SPELL_FAILED_BAD_TARGETS;
Pet* pet = m_caster->GetPet();
@@ -3762,10 +3982,10 @@ uint8 Spell::CanCast(bool strict)
if(!pet)
return SPELL_FAILED_NO_PET;
- if(!pet->HaveInDiet(m_targets.getItemTarget()->GetProto()))
+ if(!pet->HaveInDiet(foodItem->GetProto()))
return SPELL_FAILED_WRONG_PET_FOOD;
- if(!pet->GetCurrentFoodBenefitLevel(m_targets.getItemTarget()->GetProto()->ItemLevel))
+ if(!pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel))
return SPELL_FAILED_FOOD_LOWLEVEL;
if(m_caster->isInCombat() || pet->isInCombat())
@@ -3852,27 +4072,27 @@ uint8 Spell::CanCast(bool strict)
{
// check for lock - key pair (checked by client also, just prevent cheating
bool ok_key = false;
- for(int it = 0; it < 5; ++it)
+ for(int it = 0; it < 8; ++it)
{
- switch(lockInfo->keytype[it])
+ switch(lockInfo->Type[it])
{
case LOCK_KEY_NONE:
break;
case LOCK_KEY_ITEM:
{
- if(lockInfo->key[it])
+ if(lockInfo->Index[it])
{
- if(m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it])
+ if(m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[it])
ok_key =true;
break;
}
}
case LOCK_KEY_SKILL:
{
- if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->key[it])
+ if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->Index[it])
break;
- switch(lockInfo->key[it])
+ switch(lockInfo->Index[it])
{
case LOCKTYPE_HERBALISM:
if(((Player*)m_caster)->HasSkill(SKILL_HERBALISM))
@@ -3930,9 +4150,9 @@ uint8 Spell::CanCast(bool strict)
{
// check for lock - key pair
bool ok = false;
- for(int it = 0; it < 5; ++it)
+ for(int it = 0; it < 8; ++it)
{
- if(lockInfo->keytype[it]==LOCK_KEY_ITEM && lockInfo->key[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it])
+ if(lockInfo->Type[it]==LOCK_KEY_ITEM && lockInfo->Index[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[it])
{
// if so, we're good to go
ok = true;
@@ -3943,9 +4163,9 @@ uint8 Spell::CanCast(bool strict)
break;
if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_PICKLOCK)
- ReqValue = lockInfo->requiredlockskill;
+ ReqValue = lockInfo->Skill[1];
else
- ReqValue = lockInfo->requiredminingskill;
+ ReqValue = lockInfo->Skill[0];
}
// skill doesn't meet the required value
@@ -3969,9 +4189,7 @@ uint8 Spell::CanCast(bool strict)
break;
}
- // This is generic summon effect now and don't make this check for summon types similar
- // SPELL_EFFECT_SUMMON_CRITTER, SPELL_EFFECT_SUMMON_WILD or SPELL_EFFECT_SUMMON_GUARDIAN.
- // These won't show up in m_caster->GetPetGUID()
+ // This is generic summon effect
case SPELL_EFFECT_SUMMON:
{
switch(m_spellInfo->EffectMiscValueB[i])
@@ -3992,11 +4210,8 @@ uint8 Spell::CanCast(bool strict)
}
break;
}
- // Don't make this check for SPELL_EFFECT_SUMMON_CRITTER, SPELL_EFFECT_SUMMON_WILD or SPELL_EFFECT_SUMMON_GUARDIAN.
- // These won't show up in m_caster->GetPetGUID()
- case SPELL_EFFECT_SUMMON_POSSESSED:
+ // Not used for summon?
case SPELL_EFFECT_SUMMON_PHANTASM:
- case SPELL_EFFECT_SUMMON_DEMON:
{
if(m_caster->GetPetGUID())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
@@ -4141,17 +4356,14 @@ uint8 Spell::CanCast(bool strict)
return SPELL_FAILED_NO_MOUNTS_ALLOWED;
// Ignore map check if spell have AreaId. AreaId already checked and this prevent special mount spells
- if (m_caster->GetTypeId()==TYPEID_PLAYER && !sMapStore.LookupEntry(m_caster->GetMapId())->IsMountAllowed() && !m_IsTriggeredSpell && !m_spellInfo->AreaId)
- return SPELL_FAILED_NO_MOUNTS_ALLOWED;
-
- if (m_caster->GetAreaId()==35)
+ if (m_caster->GetTypeId()==TYPEID_PLAYER && !sMapStore.LookupEntry(m_caster->GetMapId())->IsMountAllowed() && !m_IsTriggeredSpell && !m_spellInfo->AreaGroupId)
return SPELL_FAILED_NO_MOUNTS_ALLOWED;
ShapeshiftForm form = m_caster->m_form;
if( form == FORM_CAT || form == FORM_TREE || form == FORM_TRAVEL ||
form == FORM_AQUA || form == FORM_BEAR || form == FORM_DIREBEAR ||
form == FORM_CREATUREBEAR || form == FORM_GHOSTWOLF || form == FORM_FLIGHT ||
- form == FORM_FLIGHT_EPIC || form == FORM_MOONKIN )
+ form == FORM_FLIGHT_EPIC || form == FORM_MOONKIN || form == FORM_METAMORPHOSIS )
return SPELL_FAILED_NOT_SHAPESHIFT;
break;
@@ -4170,11 +4382,10 @@ uint8 Spell::CanCast(bool strict)
case SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED:
case SPELL_AURA_FLY:
{
- // not allow cast fly spells at old maps by players (all spells is self target)
+ // not allow cast fly spells at old maps by players (all spells is self target)
if(m_caster->GetTypeId()==TYPEID_PLAYER)
{
- if( !((Player*)m_caster)->isGameMaster() &&
- GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) != 530)
+ if( !((Player*)m_caster)->IsAllowUseFlyMountsHere() )
return SPELL_FAILED_NOT_HERE;
}
break;
@@ -4289,15 +4500,16 @@ uint8 Spell::CheckCasterAuras() const
//Check whether the cast should be prevented by any state you might have.
uint8 prevented_reason = 0;
// Have to check if there is a stun aura. Otherwise will have problems with ghost aura apply while logging out
- if(!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED) && m_caster->HasAuraType(SPELL_AURA_MOD_STUN))
+ uint32 unitflag = m_caster->GetUInt32Value(UNIT_FIELD_FLAGS); // Get unit state
+ if(unitflag & UNIT_FLAG_STUNNED && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED))
prevented_reason = SPELL_FAILED_STUNNED;
- else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED) && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED))
+ else if(unitflag & UNIT_FLAG_CONFUSED && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED))
prevented_reason = SPELL_FAILED_CONFUSED;
- else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING) && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED))
+ else if(unitflag & UNIT_FLAG_FLEEING && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED))
prevented_reason = SPELL_FAILED_FLEEING;
- else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE)
+ else if(unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE)
prevented_reason = SPELL_FAILED_SILENCED;
- else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY)
+ else if(unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY)
prevented_reason = SPELL_FAILED_PACIFIED;
// Attr must make flag drop spell totally immune from all effects
@@ -4488,9 +4700,12 @@ int32 Spell::CalculatePowerCost()
case POWER_FOCUS:
case POWER_ENERGY:
case POWER_HAPPINESS:
- // case POWER_RUNES:
powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetMaxPower(Powers(m_spellInfo->powerType)) / 100;
break;
+ case POWER_RUNE:
+ case POWER_RUNIC_POWER:
+ sLog.outDebug("Spell::CalculateManaCost: Not implemented yet!");
+ break;
default:
sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", m_spellInfo->powerType, m_spellInfo->Id);
return 0;
@@ -4535,6 +4750,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)
@@ -4654,8 +4874,8 @@ uint8 Spell::CheckItems()
cell.data.Part.reserved = ALL_DISTRICT;
GameObject* ok = NULL;
- Trinity::GameObjectFocusCheck go_check(m_caster,m_spellInfo->RequiresSpellFocus);
- Trinity::GameObjectSearcher<Trinity::GameObjectFocusCheck> checker(ok,go_check);
+ MaNGOS::GameObjectFocusCheck go_check(m_caster,m_spellInfo->RequiresSpellFocus);
+ MaNGOS::GameObjectSearcher<MaNGOS::GameObjectFocusCheck> checker(m_caster,ok,go_check);
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectFocusCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -4667,8 +4887,7 @@ uint8 Spell::CheckItems()
focusObject = ok; // game object found in range
}
- if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP &&
- m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION)))
+ if (!p_caster->CanNoReagentCast(m_spellInfo))
{
for(uint32 i=0;i<8;i++)
{
@@ -4836,13 +5055,36 @@ uint8 Spell::CheckItems()
return SPELL_FAILED_LOW_CASTLEVEL;
//make sure the player has the required ores in inventory
if(m_targets.getItemTarget()->GetCount() < 5)
- return SPELL_FAILED_PROSPECT_NEED_MORE;
+ return SPELL_FAILED_NEED_MORE_ITEMS;
if(!LootTemplates_Prospecting.HaveLootFor(m_targets.getItemTargetEntry()))
return SPELL_FAILED_CANT_BE_PROSPECTED;
break;
}
+ case SPELL_EFFECT_MILLING:
+ {
+ if(!m_targets.getItemTarget())
+ return SPELL_FAILED_CANT_BE_MILLED;
+ //ensure item is a millable herb
+ if(!(m_targets.getItemTarget()->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS) || m_targets.getItemTarget()->GetProto()->Class != ITEM_CLASS_TRADE_GOODS)
+ return SPELL_FAILED_CANT_BE_MILLED;
+ //prevent milling in trade slot
+ if( m_targets.getItemTarget()->GetOwnerGUID() != m_caster->GetGUID() )
+ return SPELL_FAILED_CANT_BE_MILLED;
+ //Check for enough skill in inscription
+ uint32 item_millingskilllevel = m_targets.getItemTarget()->GetProto()->RequiredSkillRank;
+ if(item_millingskilllevel >p_caster->GetSkillValue(SKILL_INSCRIPTION))
+ return SPELL_FAILED_LOW_CASTLEVEL;
+ //make sure the player has the required herbs in inventory
+ if(m_targets.getItemTarget()->GetCount() < 5)
+ return SPELL_FAILED_NEED_MORE_ITEMS;
+
+ if(!LootTemplates_Milling.HaveLootFor(m_targets.getItemTargetEntry()))
+ return SPELL_FAILED_CANT_BE_MILLED;
+
+ break;
+ }
case SPELL_EFFECT_WEAPON_DAMAGE:
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
{
@@ -4922,18 +5164,22 @@ void Spell::Delayed() // only called in DealDamage()
//if (m_spellState == SPELL_STATE_DELAYED)
// return; // spell is active and can't be time-backed
+ if(isDelayableNoMore()) // Spells may only be delayed twice
+ return;
+
// spells not loosing casting time ( slam, dynamites, bombs.. )
//if(!(m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE))
// return;
- //check resist chance
- int32 resistChance = 100; //must be initialized to 100 for percent modifiers
- ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this);
- resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100;
- if (roll_chance_i(resistChance))
+ //check pushback reduce
+ int32 delaytime = 500; // spellcasting delay is normally 500ms
+ int32 delayReduce = 100; // must be initialized to 100 for percent modifiers
+ ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME, delayReduce, this);
+ delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100;
+ if(delayReduce >= 100)
return;
- int32 delaytime = GetNextDelayAtDamageMsTime();
+ delaytime = delaytime * (100 - delayReduce) / 100;
if(int32(m_timer) + delaytime > m_casttime)
{
@@ -4957,14 +5203,18 @@ void Spell::DelayedChannel()
if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER || getState() != SPELL_STATE_CASTING)
return;
- //check resist chance
- int32 resistChance = 100; //must be initialized to 100 for percent modifiers
- ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this);
- resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100;
- if (roll_chance_i(resistChance))
+ if(isDelayableNoMore()) // Spells may only be delayed twice
+ return;
+
+ //check pushback reduce
+ int32 delaytime = GetSpellDuration(m_spellInfo) * 25 / 100; // channeling delay is normally 25% of its time per hit
+ int32 delayReduce = 100; // must be initialized to 100 for percent modifiers
+ ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,delayReduce, this);
+ delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100;
+ if(delayReduce >= 100)
return;
- int32 delaytime = GetNextDelayAtDamageMsTime();
+ delaytime = delaytime * (100 - delayReduce) / 100;
if(int32(m_timer) < delaytime)
{
@@ -5018,9 +5268,9 @@ void Spell::UpdatePointers()
m_targets.Update(m_caster);
}
-bool Spell::IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId)
+bool Spell::IsAffectedByAura(Aura *aura)
{
- return spellmgr.IsAffectedBySpell(m_spellInfo,spellInfo->Id,effectId,spellInfo->EffectItemType[effectId]);
+ return spellmgr.IsAffectedByMod(m_spellInfo, aura->getAuraSpellMod());
}
bool Spell::CheckTargetCreatureType(Unit* target) const
@@ -5028,7 +5278,7 @@ bool Spell::CheckTargetCreatureType(Unit* target) const
uint32 spellCreatureTargetMask = m_spellInfo->TargetCreatureType;
// Curse of Doom : not find another way to fix spell target check :/
- if(m_spellInfo->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags == 0x0200000000LL)
+ if(m_spellInfo->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags.IsEqual(0,0x02,0))
{
// not allow cast at player
if(target->GetTypeId()==TYPEID_PLAYER)
@@ -5071,6 +5321,12 @@ bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase )
return false;
}
+ // Check Aura spell req (need for AoE spells)
+ if(m_spellInfo->targetAuraSpell && !target->HasAura(m_spellInfo->targetAuraSpell))
+ return false;
+ if (m_spellInfo->excludeTargetAuraSpell && target->HasAura(m_spellInfo->excludeTargetAuraSpell))
+ return false;
+
// Check targets for not_selectable unit flag and remove
// A player can cast spells on his pet (or other controlled unit) though in any state
if (target != m_caster && target->GetCharmerOrOwnerGUID() != m_caster->GetGUID())
@@ -5131,7 +5387,13 @@ bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase )
// all ok by some way or another, skip normal check
break;
default: // normal case
- if(target!=m_caster && !target->IsWithinLOSInMap(m_caster))
+ // Get GO cast coordinates if original caster -> GO
+ WorldObject *caster = NULL;
+ if (m_originalCasterGUID)
+ caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID);
+ if (!caster)
+ caster = m_caster;
+ if(target!=m_caster && !target->IsWithinLOSInMap(caster))
return false;
break;
}
@@ -5150,9 +5412,8 @@ Unit* Spell::SelectMagnetTarget()
{
if(Unit* magnet = (*itr)->GetCaster())
{
- if((*itr)->m_procCharges>0)
+ if((*itr)->DropAuraCharge())
{
- (*itr)->SetAuraProcCharges((*itr)->m_procCharges-1);
target = magnet;
m_targets.setUnitTarget(target);
AddUnitTarget(target, 0);
@@ -5176,7 +5437,7 @@ Unit* Spell::SelectMagnetTarget()
bool Spell::IsNeedSendToClient() const
{
- return m_spellInfo->SpellVisual!=0 || IsChanneledSpell(m_spellInfo) ||
+ return m_spellInfo->SpellVisual[0] || m_spellInfo->SpellVisual[1] || IsChanneledSpell(m_spellInfo) ||
m_spellInfo->speed > 0.0f || !m_triggeredByAuraSpell && !m_IsTriggeredSpell;
}
diff --git a/src/game/Spell.h b/src/game/Spell.h
index cc4cfc8f64a..ac7f8c8c7ea 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -47,26 +47,51 @@ enum SpellCastTargetFlags
TARGET_FLAG_RESURRECTABLE = 0x8000*/
TARGET_FLAG_SELF = 0x00000000,
+ TARGET_FLAG_UNUSED1 = 0x00000001, // not used in any spells as of 3.0.3 (can be set dynamically)
TARGET_FLAG_UNIT = 0x00000002, // pguid
+ TARGET_FLAG_UNUSED2 = 0x00000004, // not used in any spells as of 3.0.3 (can be set dynamically)
+ TARGET_FLAG_UNUSED3 = 0x00000008, // not used in any spells as of 3.0.3 (can be set dynamically)
TARGET_FLAG_ITEM = 0x00000010, // pguid
TARGET_FLAG_SOURCE_LOCATION = 0x00000020, // 3 float
TARGET_FLAG_DEST_LOCATION = 0x00000040, // 3 float
- TARGET_FLAG_OBJECT_UNK = 0x00000080, // ?
+ TARGET_FLAG_OBJECT_UNK = 0x00000080, // used in 7 spells only
+ TARGET_FLAG_UNIT_UNK = 0x00000100, // looks like self target (480 spells)
TARGET_FLAG_PVP_CORPSE = 0x00000200, // pguid
- TARGET_FLAG_OBJECT = 0x00000800, // pguid
- TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid
- TARGET_FLAG_STRING = 0x00002000, // string
- TARGET_FLAG_UNK1 = 0x00004000, // ?
- TARGET_FLAG_CORPSE = 0x00008000, // pguid
- TARGET_FLAG_UNK2 = 0x00010000 // pguid
+ TARGET_FLAG_UNIT_CORPSE = 0x00000400, // 10 spells (gathering professions)
+ TARGET_FLAG_OBJECT = 0x00000800, // pguid, 2 spells
+ TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid, 0 spells
+ TARGET_FLAG_STRING = 0x00002000, // string, 0 spells
+ TARGET_FLAG_UNK1 = 0x00004000, // 199 spells, opening object/lock
+ TARGET_FLAG_CORPSE = 0x00008000, // pguid, resurrection spells
+ TARGET_FLAG_UNK2 = 0x00010000, // pguid, not used in any spells as of 3.0.3 (can be set dynamically)
+ TARGET_FLAG_GLYPH = 0x00020000 // used in glyph spells
};
enum SpellCastFlags
{
+ CAST_FLAG_NONE = 0x00000000,
+ CAST_FLAG_UNKNOWN0 = 0x00000001, // may be pending spell cast
CAST_FLAG_UNKNOWN1 = 0x00000002,
+ CAST_FLAG_UNKNOWN11 = 0x00000004,
+ CAST_FLAG_UNKNOWN12 = 0x00000008,
CAST_FLAG_UNKNOWN2 = 0x00000010,
- CAST_FLAG_AMMO = 0x00000020,
- CAST_FLAG_UNKNOWN3 = 0x00000100
+ CAST_FLAG_AMMO = 0x00000020, // Projectiles visual
+ CAST_FLAG_UNKNOWN8 = 0x00000040,
+ CAST_FLAG_UNKNOWN9 = 0x00000080,
+ CAST_FLAG_UNKNOWN3 = 0x00000100,
+ CAST_FLAG_UNKNOWN13 = 0x00000200,
+ CAST_FLAG_UNKNOWN14 = 0x00000400,
+ CAST_FLAG_UNKNOWN6 = 0x00000800, // wotlk, trigger rune cooldown
+ CAST_FLAG_UNKNOWN15 = 0x00001000,
+ CAST_FLAG_UNKNOWN16 = 0x00002000,
+ CAST_FLAG_UNKNOWN17 = 0x00004000,
+ CAST_FLAG_UNKNOWN18 = 0x00008000,
+ CAST_FLAG_UNKNOWN19 = 0x00010000,
+ CAST_FLAG_UNKNOWN4 = 0x00020000, // wotlk
+ CAST_FLAG_UNKNOWN10 = 0x00040000,
+ CAST_FLAG_UNKNOWN5 = 0x00080000, // wotlk
+ CAST_FLAG_UNKNOWN20 = 0x00100000,
+ CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk, rune cooldown list
};
enum SpellRangeFlag
@@ -136,6 +161,7 @@ class SpellCastTargets
void setUnitTarget(Unit *target);
void setDestination(float x, float y, float z, bool send = true, int32 mapId = -1);
void setDestination(Unit *target, bool send = true);
+ void setSource(float x, float y, float z);
uint64 getGOTargetGUID() const { return m_GOTargetGUID; }
GameObject *getGOTarget() const { return m_GOTarget; }
@@ -276,6 +302,7 @@ class Spell
void EffectStuck(uint32 i);
void EffectSummonPlayer(uint32 i);
void EffectActivateObject(uint32 i);
+ void EffectApplyGlyph(uint32 i);
void EffectSummonTotem(uint32 i);
void EffectEnchantHeldItem(uint32 i);
void EffectSummonObject(uint32 i);
@@ -293,6 +320,8 @@ class Spell
void EffectSkinning(uint32 i);
void EffectCharge(uint32 i);
void EffectProspecting(uint32 i);
+ void EffectMilling(uint32 i);
+ void EffectRenamePet(uint32 i);
void EffectSendTaxi(uint32 i);
void EffectSummonCritter(uint32 i);
void EffectKnockBack(uint32 i);
@@ -319,16 +348,20 @@ class Spell
void EffectKillCredit(uint32 i);
void EffectQuestFail(uint32 i);
void EffectRedirectThreat(uint32 i);
+ void EffectActivateRune(uint32 i);
+ void EffectTitanGrip(uint32 i);
Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL, bool skipCheck = false );
~Spell();
- void prepare(SpellCastTargets * targets, Aura* triggeredByAura = NULL);
+ void prepare(SpellCastTargets const* targets, Aura* triggeredByAura = NULL);
void cancel(bool report = true);
void update(uint32 difftime);
void cast(bool skipCheck = false);
void finish(bool ok = true);
void TakePower();
+ uint8 CheckRuneCost(uint32 runeCostID);
+ void TakeRunePower();
void TakeReagents();
void TakeCastItem();
void TriggerSpell();
@@ -354,11 +387,10 @@ class Spell
bool HaveTargetsForEffect(uint8 effect) const;
void Delayed();
void DelayedChannel();
- inline uint32 getState() const { return m_spellState; }
+ uint32 getState() const { return m_spellState; }
void setState(uint32 state) { m_spellState = state; }
void DoCreateItem(uint32 i, uint32 itemtype);
-
void WriteSpellGoTargets( WorldPacket * data );
void WriteAmmoToPacket( WorldPacket * data );
void FillTargetMap();
@@ -388,6 +420,8 @@ class Spell
Item* m_CastItem;
uint64 m_castItemGUID;
uint8 m_cast_count;
+ uint32 m_glyphIndex;
+ uint32 m_preCastSpell;
SpellCastTargets m_targets;
int32 GetCastTime() const { return m_casttime; }
@@ -424,7 +458,7 @@ class Spell
void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc)
- bool IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId);
+ bool IsAffectedByAura(Aura *aura);
bool CheckTargetCreatureType(Unit* target) const;
@@ -451,9 +485,17 @@ class Spell
int32 m_casttime; // Calculated spell cast time initialized only in Spell::prepare
bool m_canReflect; // can reflect this spell?
bool m_autoRepeat;
+ uint8 m_runesState;
uint8 m_delayAtDamageCount;
- int32 GetNextDelayAtDamageMsTime() { return m_delayAtDamageCount < 5 ? 1000 - (m_delayAtDamageCount++)* 200 : 200; }
+ bool isDelayableNoMore()
+ {
+ if(m_delayAtDamageCount >= 2)
+ return true;
+
+ m_delayAtDamageCount++;
+ return false;
+ }
// Delayed spells system
uint64 m_delayStart; // time of spell delay start, filled by event handler, zero = just started
@@ -497,8 +539,6 @@ class Spell
// Spell target subsystem
//*****************************************
// Targets store structures and data
- uint32 m_countOfHit;
- uint32 m_countOfMiss;
struct TargetInfo
{
uint64 targetGUID;
diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h
index cf628515925..abe3438aa43 100644
--- a/src/game/SpellAuraDefines.h
+++ b/src/game/SpellAuraDefines.h
@@ -20,14 +20,19 @@
#ifndef TRINITY_SPELLAURADEFINES_H
#define TRINITY_SPELLAURADEFINES_H
-#define MAX_AURAS 56
-#define MAX_POSITIVE_AURAS 40
+#define MAX_AURAS 64 // client support up to 255, but it will cause problems with group auras updating
enum AURA_FLAGS
{
- AFLAG_NEGATIVE = 0x09,
- AFLAG_POSITIVE = 0x1F,
- AFLAG_MASK = 0xFF
+ AFLAG_NONE = 0x00,
+ AFLAG_EFF_INDEX_0 = 0x01,
+ AFLAG_EFF_INDEX_1 = 0x02,
+ AFLAG_EFF_INDEX_2 = 0x04,
+ AFLAG_NOT_CASTER = 0x08,
+ AFLAG_POSITIVE = 0x10,
+ AFLAG_DURATION = 0x20,
+ AFLAG_UNK2 = 0x40,
+ AFLAG_NEGATIVE = 0x80
};
//m_schoolAbsorb
@@ -85,11 +90,11 @@ enum AuraType
SPELL_AURA_PROC_TRIGGER_DAMAGE = 43,
SPELL_AURA_TRACK_CREATURES = 44,
SPELL_AURA_TRACK_RESOURCES = 45,
- SPELL_AURA_MOD_PARRY_SKILL = 46,
+ SPELL_AURA_46 = 46, // Ignore all Gear test spells
SPELL_AURA_MOD_PARRY_PERCENT = 47,
- SPELL_AURA_MOD_DODGE_SKILL = 48,
+ SPELL_AURA_48 = 48, // One periodic spell
SPELL_AURA_MOD_DODGE_PERCENT = 49,
- SPELL_AURA_MOD_BLOCK_SKILL = 50,
+ SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT = 50,
SPELL_AURA_MOD_BLOCK_PERCENT = 51,
SPELL_AURA_MOD_CRIT_PERCENT = 52,
SPELL_AURA_PERIODIC_LEECH = 53,
@@ -104,7 +109,7 @@ enum AuraType
SPELL_AURA_PERIODIC_HEALTH_FUNNEL = 62,
SPELL_AURA_PERIODIC_MANA_FUNNEL = 63,
SPELL_AURA_PERIODIC_MANA_LEECH = 64,
- SPELL_AURA_MOD_CASTING_SPEED = 65,
+ SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK = 65,
SPELL_AURA_FEIGN_DEATH = 66,
SPELL_AURA_MOD_DISARM = 67,
SPELL_AURA_MOD_STALKED = 68,
@@ -184,11 +189,11 @@ enum AuraType
SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142,
SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143,
SPELL_AURA_SAFE_FALL = 144,
- SPELL_AURA_CHARISMA = 145,
- SPELL_AURA_PERSUADED = 146,
+ SPELL_AURA_MOD_PET_TALENT_POINTS = 145,
+ SPELL_AURA_ALLOW_TAME_PET_TYPE = 146,
SPELL_AURA_ADD_CREATURE_IMMUNITY = 147,
SPELL_AURA_RETAIN_COMBO_POINTS = 148,
- SPELL_AURA_RESIST_PUSHBACK = 149, // Resist Pushback
+ SPELL_AURA_REDUCE_PUSHBACK = 149, // Reduce Pushback
SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT = 150,
SPELL_AURA_TRACK_STEALTHED = 151, // Track Stealthed
SPELL_AURA_MOD_DETECTED_RANGE = 152, // Mod Detected Range
@@ -233,8 +238,8 @@ enum AuraType
SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED = 191,
SPELL_AURA_HASTE_MELEE = 192,
SPELL_AURA_MELEE_SLOW = 193,
- SPELL_AURA_MOD_DEPRICATED_1 = 194, // not used now, old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT
- SPELL_AURA_MOD_DEPRICATED_2 = 195, // not used now, old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT
+ SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL = 194,
+ SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL = 195,
SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath
SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197,
SPELL_AURA_MOD_ALL_WEAPON_SKILLS = 198,
@@ -266,16 +271,16 @@ enum AuraType
SPELL_AURA_224 = 224,
SPELL_AURA_PRAYER_OF_MENDING = 225,
SPELL_AURA_PERIODIC_DUMMY = 226,
- SPELL_AURA_227 = 227,
+ SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE = 227,
SPELL_AURA_DETECT_STEALTH = 228,
SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE = 229,
SPELL_AURA_230 = 230,
- SPELL_AURA_231 = 231,
+ SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE = 231,
SPELL_AURA_MECHANIC_DURATION_MOD = 232,
SPELL_AURA_233 = 233,
SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK = 234,
SPELL_AURA_MOD_DISPEL_RESIST = 235,
- SPELL_AURA_236 = 236,
+ SPELL_AURA_CONTROL_VEHICLE = 236,
SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER = 237,
SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER = 238,
SPELL_AURA_MOD_SCALE_2 = 239,
@@ -285,28 +290,51 @@ 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_249 = 249,
+ SPELL_AURA_CONVERT_RUNE = 249,
SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250,
SPELL_AURA_MOD_ENEMY_DODGE = 251,
SPELL_AURA_252 = 252,
- SPELL_AURA_253 = 253,
- SPELL_AURA_254 = 254,
- SPELL_AURA_255 = 255,
- SPELL_AURA_256 = 256,
- SPELL_AURA_257 = 257,
+ SPELL_AURA_MOD_BLOCK_CRIT_CHANCE = 253,
+ SPELL_AURA_MOD_DISARM_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,
- TOTAL_AURAS=262
+ SPELL_AURA_SCREEN_EFFECT = 260,
+ SPELL_AURA_PHASE = 261,
+ SPELL_AURA_262 = 262,
+ SPELL_AURA_ALLOW_ONLY_ABILITY = 263,
+ SPELL_AURA_264 = 264,
+ SPELL_AURA_265 = 265,
+ SPELL_AURA_266 = 266,
+ SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267,
+ SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268,
+ SPELL_AURA_269 = 269,
+ SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive
+ SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271,
+ SPELL_AURA_272 = 272,
+ SPELL_AURA_273 = 273,
+ SPELL_AURA_274 = 274,
+ SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275,
+ SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done
+ SPELL_AURA_MOD_MAX_AFFECTED_TARGETS = 277,
+ SPELL_AURA_MOD_DISARM_RANGED = 278,
+ SPELL_AURA_279 = 279,
+ SPELL_AURA_MOD_WEAPONTYPE_IGNORE_TARGET_RESISTANCE = 280,
+ SPELL_AURA_MOD_HONOR_GAIN_PCT = 281,
+ SPELL_AURA_MOD_BASE_HEALTH_PCT = 282,
+ SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells
+ TOTAL_AURAS = 284
};
enum AreaAuraType
{
AREA_AURA_PARTY,
+ AREA_AURA_RAID,
AREA_AURA_FRIEND,
AREA_AURA_ENEMY,
AREA_AURA_PET,
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index cd9e41f2c5e..f831dc2d045 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -100,11 +100,11 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor
&Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES
&Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES
- &Aura::HandleUnused, // 46 SPELL_AURA_MOD_PARRY_SKILL obsolete?
+ &Aura::HandleUnused, // 46 SPELL_AURA_46
&Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT
- &Aura::HandleUnused, // 48 SPELL_AURA_MOD_DODGE_SKILL obsolete?
+ &Aura::HandleUnused, // 48 SPELL_AURA_48
&Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT
- &Aura::HandleUnused, // 50 SPELL_AURA_MOD_BLOCK_SKILL obsolete?
+ &Aura::HandleNoImmediateEffect, // 50 SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT implemented in Unit::SpellCriticalHealingBonus
&Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT
&Aura::HandleAuraModCritPercent, // 52 SPELL_AURA_MOD_CRIT_PERCENT
&Aura::HandlePeriodicLeech, // 53 SPELL_AURA_PERIODIC_LEECH
@@ -116,10 +116,10 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
&Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE
&Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE
- &Aura::HandleNULL, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL
+ &Aura::HandlePeriodicHealthFunnel, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL
&Aura::HandleUnused, // 63 SPELL_AURA_PERIODIC_MANA_FUNNEL obsolete?
&Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH
- &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED
+ &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK
&Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH
&Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM
&Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED
@@ -163,7 +163,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleAuraHover, //106 SPELL_AURA_HOVER
&Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER
&Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER
- &Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER
+ &Aura::HandleAddTargetTrigger, //109 SPELL_AURA_ADD_TARGET_TRIGGER
&Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT
&Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER
&Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
@@ -199,11 +199,11 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
&Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
&Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
- &Aura::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete?
- &Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete?
+ &Aura::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS
+ &Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE
&Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY
&Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
- &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK
+ &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK
&Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
&Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
&Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
@@ -228,7 +228,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK
&Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
&Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
- &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus (by default intellect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT)
+ &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus
&Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus
&Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end
&Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM
@@ -248,8 +248,8 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
&Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE
&Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
- &Aura::HandleUnused, //194 SPELL_AURA_MOD_DEPRICATED_1 not used now (old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT)
- &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT)
+ &Aura::HandleUnused, //194 SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL
+ &Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL implement in Unit::CalculateSpellDamage
&Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN
&Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
&Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS
@@ -274,23 +274,23 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleUnused, //217 unused
&Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
&Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
- &Aura::HandleNULL, //220 SPELL_AURA_MOD_RATING_FROM_STAT
+ &Aura::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT
&Aura::HandleNULL, //221 ignored
&Aura::HandleUnused, //222 unused
&Aura::HandleNULL, //223 Cold Stare
&Aura::HandleUnused, //224 unused
&Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING
&Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY
- &Aura::HandleNULL, //227 periodic trigger spell
+ &Aura::HandlePeriodicTriggerSpellWithValue, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE
&Aura::HandleNoImmediateEffect, //228 stealth detection
&Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
&Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout
- &Aura::HandleNULL, //231
+ &Aura::HandleNoImmediateEffect, //231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE
&Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration
&Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue
&Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration
&Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult
- &Aura::HandleUnused, //236 unused
+ &Aura::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE
&Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus
&Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus
&Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61
@@ -300,30 +300,52 @@ 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::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::HandleNULL, //249
+ &Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE
&Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
&Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE
- &Aura::HandleUnused, //252 unused
- &Aura::HandleUnused, //253 unused
- &Aura::HandleUnused, //254 unused
- &Aura::HandleUnused, //255 unused
- &Aura::HandleUnused, //256 unused
- &Aura::HandleUnused, //257 unused
- &Aura::HandleUnused, //258 unused
- &Aura::HandleUnused, //259 unused
- &Aura::HandleUnused, //260 unused
- &Aura::HandleNULL //261 SPELL_AURA_261 some phased state (44856 spell)
+ &Aura::HandleNULL, //252 haste all?
+ &Aura::HandleNULL, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE
+ &Aura::HandleNULL, //254 SPELL_AURA_MOD_DISARM_SHIELD disarm Shield
+ &Aura::HandleNoImmediateEffect, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT implemented in Unit::SpellDamageBonus
+ &Aura::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select
+ &Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select
+ &Aura::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL
+ &Aura::HandleNULL, //259 corrupt healing over time spell
+ &Aura::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code
+ &Aura::HandlePhase, //261 SPELL_AURA_PHASE undetactable invisibility? implemented in Unit::isVisibleForOrDetect
+ &Aura::HandleNULL, //262
+ &Aura::HandleNULL, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask
+ &Aura::HandleNULL, //264 unused
+ &Aura::HandleNULL, //265 unused
+ &Aura::HandleNULL, //266 unused
+ &Aura::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect
+ &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT
+ &Aura::HandleNULL, //269 ignore DR effects?
+ &Aura::HandleNULL, //270 SPELL_AURA_MOD_IGNORE_TARGET_RESIST
+ &Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus
+ &Aura::HandleNULL, //272 reduce spell cast time?
+ &Aura::HandleNULL, //273
+ &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::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
+ &Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor
+ &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
+ &Aura::HandleNoImmediateEffect //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
};
Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) :
-m_procCharges(0), m_stackAmount(1), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target),
-m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS),
-m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false),
-m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false),
-m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE)
+m_spellmod(NULL), m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target),
+m_timeCla(1000), m_periodicTimer(0), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE),
+m_effIndex(eff), m_auraSlot(MAX_AURAS), m_auraFlags(AFLAG_NONE), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),
+m_positive(false), m_permanent(false), m_isPeriodic(false), m_isAreaAura(false), m_isPersistent(false),
+m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false)
{
assert(target);
@@ -399,28 +421,29 @@ m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE)
m_duration = m_maxduration;
- if(modOwner)
- modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer);
-
sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage);
m_effIndex = eff;
SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]);
- m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
+ // Apply periodic time mod
+ if(modOwner && m_modifier.periodictime)
+ modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_modifier.periodictime);
- if(m_spellProto->procCharges)
- {
- m_procCharges = m_spellProto->procCharges;
+ // Start periodic on next tick or at aura apply
+ if (!(m_spellProto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY))
+ m_periodicTimer += m_modifier.periodictime;
- if(modOwner)
- modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges);
- }
- else
- m_procCharges = -1;
+ m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
+
+ m_procCharges = m_spellProto->procCharges;
+ if(modOwner)
+ modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges);
- m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances &&
- !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000));
+ m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() &&
+ m_spellProto->Stances &&
+ !(m_spellProto->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) &&
+ !(m_spellProto->Attributes & SPELL_ATTR_NOT_SHAPESHIFT));
}
Aura::~Aura()
@@ -446,6 +469,11 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target,
if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
m_modifier.m_auraname = SPELL_AURA_NONE;
break;
+ case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
+ m_areaAuraType = AREA_AURA_RAID;
+ if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
+ m_modifier.m_auraname = SPELL_AURA_NONE;
+ break;
case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
m_areaAuraType = AREA_AURA_FRIEND;
break;
@@ -576,28 +604,13 @@ void Aura::Update(uint32 diff)
if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent))
{
m_periodicTimer -= diff;
- if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
+ if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
{
- if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN ||
- m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN ||
- // Cannibalize, eating items and other spells
- m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH ||
- // Eating items and other spells
- m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA )
- {
- ApplyModifier(true);
- return;
- }
// update before applying (aura can be removed in TriggerSpell or PeriodicTick calls)
m_periodicTimer += m_modifier.periodictime;
if(!m_target->hasUnitState(UNIT_STAT_ISOLATED))
- {
- if(m_isTrigger)
- TriggerSpell();
- else
- PeriodicTick();
- }
+ PeriodicTick();
}
}
}
@@ -616,19 +629,22 @@ void AreaAura::Update(uint32 diff)
switch(m_areaAuraType)
{
case AREA_AURA_PARTY:
- caster->GetPartyMember(targets, m_radius);
+ caster->GetPartyMember(targets, m_radius);
+ break;
+ case AREA_AURA_RAID:
+ caster->GetRaidMember(targets, m_radius);
break;
case AREA_AURA_FRIEND:
{
Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(caster, caster, m_radius);
- Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
+ Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(caster, targets, u_check);
caster->VisitNearbyObject(m_radius, searcher);
break;
}
case AREA_AURA_ENEMY:
{
Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(caster, caster, m_radius); // No GetCharmer in searcher
- Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check);
+ Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(caster, targets, u_check);
caster->VisitNearbyObject(m_radius, searcher);
break;
}
@@ -657,6 +673,7 @@ void AreaAura::Update(uint32 diff)
aur = new AreaAura(actualSpellInfo, m_effIndex, &m_modifier.m_amount, (*tIter), caster, NULL);
else
aur = new AreaAura(actualSpellInfo, m_effIndex, NULL, (*tIter), caster, NULL);
+ aur->SetAuraDuration(GetAuraDuration());
(*tIter)->AddAura(aur);
}
}
@@ -690,6 +707,11 @@ void AreaAura::Update(uint32 diff)
if(!tmp_target->IsInPartyWith(caster))
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
+ else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me!
+ {
+ if(!tmp_target->IsInRaidWith(caster))
+ tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
+ }
else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
{
if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
@@ -740,47 +762,6 @@ void Aura::ApplyModifier(bool apply, bool Real)
m_in_use = false;
}
-void Aura::UpdateAuraDuration()
-{
- if(m_auraSlot >= MAX_AURAS || m_isPassive)
- return;
-
- if( m_target->GetTypeId() == TYPEID_PLAYER)
- {
- WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5);
- data << (uint8)m_auraSlot << (uint32)m_duration;
- ((Player*)m_target)->SendDirectMessage(&data);
-
- data.Initialize(SMSG_SET_EXTRA_AURA_INFO, (8+1+4+4+4));
- data.append(m_target->GetPackGUID());
- data << uint8(m_auraSlot);
- data << uint32(GetId());
- data << uint32(GetAuraMaxDuration());
- data << uint32(GetAuraDuration());
- ((Player*)m_target)->SendDirectMessage(&data);
- }
-
- // not send in case player loading (will not work anyway until player not added to map), sent in visibility change code
- if(m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading())
- return;
-
- Unit* caster = GetCaster();
-
- if(caster && caster->GetTypeId() == TYPEID_PLAYER && caster != m_target)
- SendAuraDurationForCaster((Player*)caster);
-}
-
-void Aura::SendAuraDurationForCaster(Player* caster)
-{
- WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8+1+4+4+4));
- data.append(m_target->GetPackGUID());
- data << uint8(m_auraSlot);
- data << uint32(GetId());
- data << uint32(GetAuraMaxDuration()); // full
- data << uint32(GetAuraDuration()); // remain
- caster->GetSession()->SendPacket(&data);
-}
-
void Aura::_AddAura()
{
if (!GetId())
@@ -788,11 +769,12 @@ void Aura::_AddAura()
if(!m_target)
return;
- // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT
+ // Second aura if some spell
bool secondaura = false;
+ // Try find slot for aura
uint8 slot = NULL_AURA_SLOT;
-
- for(uint8 i = 0; i < 3; i++)
+ // Lookup for some spell auras (and get slot from it)
+ for(uint8 i = 0; i < m_effIndex; i++)
{
Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
@@ -800,108 +782,88 @@ void Aura::_AddAura()
// allow use single slot only by auras from same caster
if(itr->second->GetCasterGUID()==GetCasterGUID())
{
- secondaura = true;
slot = itr->second->GetAuraSlot();
+ secondaura = true;
break;
}
}
-
- if(secondaura)
+ if (secondaura)
break;
}
-
- Unit* caster = GetCaster();
-
- // not call total regen auras at adding
- switch (m_modifier.m_auraname)
+ // Lookup free slot
+ if (!secondaura && m_target->GetVisibleAurasCount() < MAX_AURAS)
{
- /*case SPELL_AURA_PERIODIC_DAMAGE:
- case SPELL_AURA_PERIODIC_LEECH:
- if(caster)
- m_modifier.m_amount = caster->SpellDamageBonus(m_target, m_spellProto, m_modifier.m_amount, DOT);
- break;
- case SPELL_AURA_PERIODIC_HEAL:
- if(caster)
- m_modifier.m_amount = caster->SpellHealingBonus(m_spellProto, m_modifier.m_amount, DOT, m_target);
- break;*/
- case SPELL_AURA_OBS_MOD_HEALTH:
- case SPELL_AURA_OBS_MOD_MANA:
- m_periodicTimer = m_modifier.periodictime;
- break;
- case SPELL_AURA_MOD_REGEN:
- case SPELL_AURA_MOD_POWER_REGEN:
- case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT:
- m_periodicTimer = 5000;
- break;
+ Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras();
+ for(uint8 i = 0; i < MAX_AURAS; ++i)
+ {
+ Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(i);
+ if(itr == visibleAuras->end())
+ {
+ slot = i;
+ // update for out of range group members (on 1 slot use)
+ m_target->UpdateAuraForGroup(slot);
+ break;
+ }
+ }
}
- // register aura
- if (getDiminishGroup() != DIMINISHING_NONE )
- m_target->ApplyDiminishingAura(getDiminishGroup(),true);
+ Unit* caster = GetCaster();
// passive auras (except totem auras) do not get placed in the slots
// area auras with SPELL_AURA_NONE are not shown on target
if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) &&
(m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))
{
- if(!secondaura) // new slot need
+ SetAuraSlot( slot );
+ if(slot < MAX_AURAS) // slot found send data to client
{
- if (IsPositive()) // empty positive slot
- {
- for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++)
- {
- if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0)
- {
- slot = i;
- break;
- }
- }
- }
- else // empty negative slot
- {
- for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++)
- {
- if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0)
- {
- slot = i;
- break;
- }
- }
- }
-
- SetAuraSlot( slot );
-
- // Not update fields for not first spell's aura, all data already in fields
- if(slot < MAX_AURAS) // slot found
- {
- SetAura(slot, false);
- SetAuraFlag(slot, true);
- SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
- UpdateAuraCharges();
-
- // update for out of range group members
- m_target->UpdateAuraForGroup(slot);
- }
+ SetAura(false);
+ 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));
+ SendAuraUpdate(false);
}
- else // use found slot
+
+ //*****************************************************
+ // Update target aura state flag (at 1 aura apply)
+ // TODO: Make it easer
+ //*****************************************************
+ if (!secondaura)
{
- SetAuraSlot( slot );
- }
-
- UpdateSlotCounterAndDuration();
+ // Sitdown on apply aura req seated
+ if (m_spellProto->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !m_target->IsSitState())
+ m_target->SetStandState(UNIT_STAND_STATE_SIT);
- // Update Seals information
- if( IsSealSpell(GetSpellProto()) )
- m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
+ // register aura diminishing on apply
+ if (getDiminishGroup() != DIMINISHING_NONE )
+ m_target->ApplyDiminishingAura(getDiminishGroup(),true);
- // Conflagrate aura state
- if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
- m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
+ // Update Seals information
+ if (IsSealSpell(m_spellProto))
+ m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
- if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
- && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
- {
- m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true);
+ // Conflagrate aura state on Immolate
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags[0] & 4)
+ m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
+
+ // Faerie Fire (druid versions)
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x400)
+ m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true);
+
+ // Victorious
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[1] & 0x00040000)
+ m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, true);
+
+ // Swiftmend state on Regrowth & Rejuvenation
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x50 )
+ m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true);
+
+ // Deadly poison aura state
+ if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags[0] & 0x10000)
+ m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON, true);
+
+ // Enrage aura state
+ if(m_spellProto->Dispel == DISPEL_ENRAGE)
+ m_target->ModifyAuraState(AURA_STATE_ENRAGE, true);
}
}
}
@@ -922,10 +884,6 @@ void Aura::_RemoveAura()
dynObj->RemoveAffected(m_target);
}
- // unregister aura
- if (getDiminishGroup() != DIMINISHING_NONE )
- m_target->ApplyDiminishingAura(getDiminishGroup(),false);
-
//passive auras do not get put in slots
// Note: but totem can be not accessible for aura target in time remove (to far for find in grid)
//if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem()))
@@ -936,10 +894,10 @@ void Aura::_RemoveAura()
if(slot >= MAX_AURAS) // slot not set
return;
- if(m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + slot)) == 0)
+ if(m_target->GetVisibleAura(slot) == 0)
return;
- bool samespell = false;
+ bool lastaura = true;
// find other aura in same slot (current already removed from list)
for(uint8 i = 0; i < 3; i++)
@@ -949,50 +907,84 @@ void Aura::_RemoveAura()
{
if(itr->second->GetAuraSlot()==slot)
{
- samespell = true;
-
+ lastaura = false;
break;
}
}
- if(samespell)
+ if(!lastaura)
break;
}
// only remove icon when the last aura of the spell is removed (current aura already removed from list)
- if (!samespell)
+ if (lastaura)
{
- SetAura(slot, true);
- SetAuraFlag(slot, false);
- SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
+ // unregister aura diminishing (and store last time)
+ if (getDiminishGroup() != DIMINISHING_NONE )
+ m_target->ApplyDiminishingAura(getDiminishGroup(),false);
+
+ SetAura(true);
+ SetAuraFlags(AFLAG_NONE);
+ SetAuraLevel(0);
+ SendAuraUpdate(true);
- SetAuraApplication(slot, 0);
// update for out of range group members
m_target->UpdateAuraForGroup(slot);
- if( IsSealSpell(GetSpellProto()) )
- m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false);
+ //*****************************************************
+ // Update target aura state flag (at last aura remove)
+ //*****************************************************
+ // Enrage aura state
+ if(m_spellProto->Dispel == DISPEL_ENRAGE)
+ m_target->ModifyAuraState(AURA_STATE_ENRAGE, false);
- // Conflagrate aura state
- if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
- m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false);
+ uint32 removeState = 0;
+ switch(m_spellProto->SpellFamilyName)
+ {
+ case SPELLFAMILY_PALADIN:
+ if (IsSealSpell(m_spellProto))
+ removeState = AURA_STATE_JUDGEMENT; // Update Seals information
+ break;
+ case SPELLFAMILY_WARLOCK:
+ if(m_spellProto->SpellFamilyFlags[0] & 4)
+ removeState = AURA_STATE_IMMOLATE; // Conflagrate aura state
+ break;
+ case SPELLFAMILY_DRUID:
+ if(m_spellProto->SpellFamilyFlags[0] & 0x400)
+ removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
+ else if(m_spellProto->SpellFamilyFlags[0] & 0x50)
+ removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
+ break;
+ case SPELLFAMILY_WARRIOR:
+ if(m_spellProto->SpellFamilyFlags[1] & 0x00040000)
+ removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious
+ break;
+ case SPELLFAMILY_ROGUE:
+ if(m_spellProto->SpellFamilyFlags[0] & 0x10000)
+ removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state
+ break;
+ case SPELLFAMILY_HUNTER:
+ if(m_spellProto->SpellFamilyFlags[1] & 0x10000000)
+ removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions)
- // Swiftmend aura state
- if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
- && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
+ }
+ // Remove state (but need check other auras for it)
+ if (removeState)
{
bool found = false;
- Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
- for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
+ Unit::AuraMap& Auras = m_target->GetAuras();
+ for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
- if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
- && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
+ SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
+ if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
+ auraSpellInfo->SpellFamilyFlags == m_spellProto->SpellFamilyFlags )
{
found = true;
break;
}
}
+ // this has been last aura
if(!found)
- m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false);
+ m_target->ModifyAuraState(AuraState(removeState), false);
}
// reset cooldown state for spells
@@ -1004,56 +996,95 @@ void Aura::_RemoveAura()
}
}
-void Aura::SetAuraFlag(uint32 slot, bool add)
+void Aura::SendAuraUpdate(bool remove)
{
- uint32 index = slot / 4;
- uint32 byte = (slot % 4) * 8;
- uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAFLAGS + index);
- val &= ~((uint32)AFLAG_MASK << byte);
- if(add)
+ WorldPacket data(SMSG_AURA_UPDATE);
+ data.append(m_target->GetPackGUID());
+ data << uint8(GetAuraSlot());
+ data << uint32(remove ? 0 : GetId());
+
+ if(remove)
{
- if (IsPositive())
- val |= ((uint32)AFLAG_POSITIVE << byte);
- else
- val |= ((uint32)AFLAG_NEGATIVE << byte);
+ m_target->SendMessageToSet(&data, true);
+ return;
}
- m_target->SetUInt32Value(UNIT_FIELD_AURAFLAGS + index, val);
+
+ uint8 auraFlags = GetAuraFlags();
+ data << uint8(auraFlags);
+ data << uint8(GetAuraLevel());
+ data << uint8(m_procCharges ? m_procCharges : m_stackAmount);
+
+ if(!(auraFlags & AFLAG_NOT_CASTER))
+ {
+ data << uint8(0); // pguid
+ }
+
+ if(auraFlags & AFLAG_DURATION)
+ {
+ data << uint32(GetAuraMaxDuration());
+ data << uint32(GetAuraDuration());
+ }
+
+ m_target->SendMessageToSet(&data, true);
}
-void Aura::SetAuraLevel(uint32 slot,uint32 level)
+void Aura::SetStackAmount(uint8 stackAmount)
{
- uint32 index = slot / 4;
- uint32 byte = (slot % 4) * 8;
- uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURALEVELS + index);
- val &= ~(0xFF << byte);
- val |= (level << byte);
- m_target->SetUInt32Value(UNIT_FIELD_AURALEVELS + index, val);
+ if (stackAmount != m_stackAmount)
+ {
+ Unit *target = GetTarget();
+ Unit *caster = GetCaster();
+ if (!target || !caster)
+ return;
+ m_stackAmount = stackAmount;
+ int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target);
+ // Reapply if amount change
+ if (amount!=m_modifier.m_amount)
+ {
+ ApplyModifier(false, true);
+ m_modifier.m_amount = amount;
+ ApplyModifier(true, true);
+ }
+ }
+ RefreshAura();
}
-void Aura::SetAuraApplication(uint32 slot, int8 count)
+bool Aura::modStackAmount(int32 num)
{
- uint32 index = slot / 4;
- uint32 byte = (slot % 4) * 8;
- uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index);
- val &= ~(0xFF << byte);
- val |= ((uint8(count)) << byte);
- m_target->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index, val);
+ // Can`t mod
+ if (!m_spellProto->StackAmount)
+ return true;
+
+ // Modify stack but limit it
+ int32 stackAmount = m_stackAmount + num;
+ if (stackAmount > m_spellProto->StackAmount)
+ stackAmount = m_spellProto->StackAmount;
+ else if (stackAmount <=0) // Last aura from stack removed
+ {
+ m_stackAmount = 0;
+ return true; // need remove aura
+ }
+
+ // Update stack amount
+ SetStackAmount(stackAmount);
+ return false;
}
-void Aura::UpdateSlotCounterAndDuration()
+void Aura::RefreshAura()
{
- uint8 slot = GetAuraSlot();
- if(slot >= MAX_AURAS)
- return;
-
- // Three possibilities:
- // Charge = 0; Stack >= 0
- // Charge = 1; Stack >= 0
- // Charge > 1; Stack = 0
- if(m_procCharges < 2)
- SetAuraApplication(slot, m_stackAmount-1);
+ m_duration = m_maxduration;
+ SendAuraUpdate(false);
+}
- UpdateAuraDuration();
+bool Aura::isAffectedOnSpell(SpellEntry const *spell) const
+{
+ // Check family name
+ if (spell->SpellFamilyName != m_spellProto->SpellFamilyName)
+ return false;
+ // Check EffectClassMask
+ if (m_spellProto->EffectSpellClassMask[m_effIndex] & spell->SpellFamilyFlags)
+ return true;
+ return false;
}
/*********************************************************/
@@ -1064,10 +1095,6 @@ void Aura::HandleAddModifier(bool apply, bool Real)
if(m_target->GetTypeId() != TYPEID_PLAYER || !Real)
return;
- SpellEntry const *spellInfo = GetSpellProto();
- if(!spellInfo)
- return;
-
if(m_modifier.m_miscvalue >= MAX_SPELLMOD)
return;
@@ -1078,40 +1105,35 @@ void Aura::HandleAddModifier(bool apply, bool Real)
{
case 17941: // Shadow Trance
case 22008: // Netherwind Focus
+ case 31834: // Light's Grace
+ case 34754: // Clearcasting
case 34936: // Backlash
- m_procCharges = 1;
+ case 48108: // Hot Streak
+ case 54741: // Firestarter
+ case 57761: // Fireball!
+ SetAuraCharges(1);
break;
}
SpellModifier *mod = new SpellModifier;
mod->op = SpellModOp(m_modifier.m_miscvalue);
- mod->value = GetModifierValue();
+ mod->value = m_modifier.m_amount;
mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types
mod->spellId = GetId();
- mod->effectId = m_effIndex;
- mod->lastAffected = NULL;
- uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex);
-
- if (spellAffectMask)
- mod->mask = spellAffectMask;
- else
- mod->mask = spellInfo->EffectItemType[m_effIndex];
-
- if (m_procCharges > 0)
- mod->charges = m_procCharges;
- else
- mod->charges = 0;
+ flag96 const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex);
+ if (!spellAffect)
+ spellAffect = &m_spellProto->EffectSpellClassMask[m_effIndex];
+ mod->mask = *spellAffect;
+ mod->charges = m_procCharges;
m_spellmod = mod;
}
- uint64 spellFamilyMask = m_spellmod->mask;
-
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
// reapply some passive spells after add/remove related spellmods
- if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL))
+ if(m_spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && (m_spellmod->mask[1] & 0x00001000))
{
m_target->RemoveAurasDueToSpell(45471);
@@ -1119,6 +1141,29 @@ void Aura::HandleAddModifier(bool apply, bool Real)
m_target->CastSpell(m_target,45471,true);
}
}
+void Aura::HandleAddTargetTrigger(bool apply, bool Real)
+{
+ // Use SpellModifier structure for check
+ // used only fields:
+ // spellId, mask, mask2
+ if (apply)
+ {
+ SpellModifier *mod = new SpellModifier;
+ mod->spellId = GetId();
+
+ flag96 const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex);
+ if (!spellAffect)
+ spellAffect = &m_spellProto->EffectSpellClassMask[m_effIndex];
+
+ mod->mask = *spellAffect;
+ m_spellmod = mod;
+ }
+ else
+ {
+ delete m_spellmod;
+ m_spellmod = NULL;
+ }
+}
void Aura::TriggerSpell()
{
@@ -1131,8 +1176,6 @@ void Aura::TriggerSpell()
// generic casting code with custom spells and target/caster customs
uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
- uint64 originalCasterGUID = GetCasterGUID();
-
SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
SpellEntry const *auraSpellInfo = GetSpellProto();
uint32 auraId = auraSpellInfo->Id;
@@ -1729,7 +1772,7 @@ void Aura::TriggerSpell()
{
SpellEntry const* spell = itr->second->GetSpellProto();
if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN &&
- spell->SpellFamilyFlags & 0x0000000000000400L)
+ spell->SpellFamilyFlags[0] & 0x400)
return;
}
target->RemoveAurasDueToSpell(28820);
@@ -1799,8 +1842,8 @@ void Aura::TriggerSpell()
{
switch((*i)->GetModifier()->m_miscvalue)
{
- case STAT_INTELLECT: intellectLoss += (*i)->GetModifierValue(); break;
- case STAT_SPIRIT: spiritLoss += (*i)->GetModifierValue(); break;
+ case STAT_INTELLECT: intellectLoss += (*i)->GetModifier()->m_amount; break;
+ case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break;
default: break;
}
}
@@ -1810,20 +1853,19 @@ void Aura::TriggerSpell()
return;
caster = target;
- originalCasterGUID = 0;
break;
}
// Mana Tide
case 16191:
{
- caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID);
+ caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this);
return;
}
}
}
if(!GetSpellMaxRange(sSpellRangeStore.LookupEntry(triggeredSpellInfo->rangeIndex)))
target = m_target; //for druid dispel poison
- m_target->CastSpell(target, triggeredSpellInfo, true, 0, this, originalCasterGUID);
+ m_target->CastSpell(target, triggeredSpellInfo, true, 0, this, GetCasterGUID());
}
Unit* Aura::GetTriggerTarget() const
@@ -1835,6 +1877,21 @@ Unit* Aura::GetTriggerTarget() const
return target ? target : m_target;
}
+void Aura::TriggerSpellWithValue()
+{
+ Unit* caster = GetCaster();
+ Unit* target = GetTriggerTarget();
+
+ if(!caster || !target)
+ return;
+
+ // generic casting code with custom spells and target/caster customs
+ uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
+ int32 basepoints0 = this->GetModifier()->m_amount;
+
+ caster->CastCustomSpell(target, trigger_spell_id, &basepoints0, 0, 0, true, 0, this);
+}
+
/*********************************************************/
/*** AURA EFFECTS ***/
/*********************************************************/
@@ -1868,7 +1925,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
return;
case 43873: // Headless Horseman Laugh
if(caster->GetTypeId() == TYPEID_PLAYER)
- ((Player*)caster)->SendPlaySound(11965, false);
+ ((Player*)caster)->PlaySound(11965, false);
return;
case 46354: // Blood Elf Illusion
if(caster)
@@ -1893,11 +1950,11 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
}
// Earth Shield
- if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL))
+ if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags[1] & 0x400))
{
// prevent double apply bonuses
if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
- m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
+ m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE);
return;
}
}
@@ -1964,6 +2021,25 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
m_target->SetReducedThreatPercent(0, 0);
return;
}
+
+ if (caster && m_removeMode == AURA_REMOVE_BY_DEATH)
+ {
+ // Stop caster Arcane Missle chanelling on death
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE &&
+ m_spellProto->SpellFamilyFlags[0] & 0x800)
+ {
+ caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ return;
+ }
+ // Stop caster Penance chanelling on death
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST &&
+ m_spellProto->SpellFamilyFlags[2] & 0x00000080)
+ {
+ caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ return;
+ }
+
+ }
}
// AT APPLY & REMOVE
@@ -2004,12 +2080,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
m_target->RemoveAurasDueToSpell(spellId);
return;
}
- // Victorious
- if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR)
- {
- m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply);
- return;
- }
//Summon Fire Elemental
if (GetId() == 40133 && caster)
{
@@ -2048,10 +2118,25 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
}
case SPELLFAMILY_MAGE:
{
- // Hypothermia
- if( GetId()==41425 )
+ break;
+ }
+ case SPELLFAMILY_PRIEST:
+ {
+ // Pain and Suffering
+ if( m_spellProto->SpellIconID == 2874 && m_target->GetTypeId()==TYPEID_PLAYER )
{
- m_target->ModifyAuraState(AURA_STATE_HYPOTHERMIA,apply);
+ if(apply)
+ {
+ // Reduce backfire damage (dot damage) from Shadow Word: Death
+ SpellModifier *mod = new SpellModifier;
+ mod->op = SPELLMOD_DOT;
+ mod->value = m_modifier.m_amount;
+ mod->type = SPELLMOD_PCT;
+ mod->spellId = GetId();
+ mod->mask[1] = 0x00000002;
+ m_spellmod = mod;
+ }
+ ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
return;
}
break;
@@ -2059,24 +2144,38 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
case SPELLFAMILY_DRUID:
{
// Lifebloom
- if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL )
+ if ( GetSpellProto()->SpellFamilyFlags[1] & 0x10 )
{
if ( apply )
{
if ( caster )
// prevent double apply bonuses
if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
- m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
+ m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE);
}
- // Do final heal for real !apply
- else if (Real)
+ else
{
- if (GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL)
+ // Final heal only on dispelled or duration end
+ if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) )
+ return;
+
+ // final heal
+ if(m_target->IsInWorld())
+ m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID());
+
+ /*// have a look if there is still some other Lifebloom dummy aura
+ Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); ++itr)
+ if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
+ (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL)
+ return;
+
+ // final heal
+ if(m_target->IsInWorld() && m_stackAmount > 0)
{
- // final heal
- if(m_target->IsInWorld())
- m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID());
- }
+ int32 amount = m_modifier.m_amount / m_stackAmount;
+ m_target->CastCustomSpell(m_target,33778,&amount,NULL,NULL,true,NULL,this,GetCasterGUID());
+ }*/
}
return;
}
@@ -2097,10 +2196,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
mod->value = m_modifier.m_amount/7;
mod->type = SPELLMOD_FLAT;
mod->spellId = GetId();
- mod->effectId = m_effIndex;
- mod->lastAffected = NULL;
- mod->mask = 0x001000000000LL;
- mod->charges = 0;
+ mod->mask[1] = 0x0010;
m_spellmod = mod;
}
@@ -2123,10 +2219,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
mod->value = m_modifier.m_amount;
mod->type = SPELLMOD_FLAT;
mod->spellId = GetId();
- mod->effectId = m_effIndex;
- mod->lastAffected = NULL;
- mod->mask = 0x4000000000000LL;
- mod->charges = 0;
+ mod->mask[1] = 0x40000;
m_spellmod = mod;
}
@@ -2148,18 +2241,15 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
mod->value = m_modifier.m_amount;
mod->type = SPELLMOD_PCT;
mod->spellId = GetId();
- mod->effectId = m_effIndex;
- mod->lastAffected = NULL;
switch (m_effIndex)
{
case 0:
- mod->mask = 0x00200000000LL; // Windfury Totem
+ mod->mask[1] = 0x002; // Windfury Totem
break;
case 1:
- mod->mask = 0x00400000000LL; // Flametongue Totem
+ mod->mask[1] = 0x004; // Flametongue Totem
break;
}
- mod->charges = 0;
m_spellmod = mod;
}
@@ -2200,42 +2290,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
}
}
-void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
-{
- // spells required only Real aura add/remove
- if(!Real)
- return;
-
- SpellEntry const*spell = GetSpellProto();
- switch( spell->SpellFamilyName)
- {
- case SPELLFAMILY_ROGUE:
- {
- // Master of Subtlety
- if (spell->Id==31666 && !apply && Real)
- {
- m_target->RemoveAurasDueToSpell(31665);
- break;
- }
- break;
- }
- case SPELLFAMILY_HUNTER:
- {
- // Aspect of the Viper
- if (spell->SpellFamilyFlags&0x0004000000000000LL)
- {
- // Update regen on remove
- if (!apply && m_target->GetTypeId() == TYPEID_PLAYER)
- ((Player*)m_target)->UpdateManaRegen();
- break;
- }
- break;
- }
- }
-
- m_isPeriodic = apply;
-}
-
void Aura::HandleAuraMounted(bool apply, bool Real)
{
// only at real add/remove aura
@@ -2318,12 +2372,8 @@ void Aura::HandleAuraHover(bool apply, bool Real)
void Aura::HandleWaterBreathing(bool apply, bool Real)
{
- if(apply)
- m_target->waterbreath = true;
- else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty())
+ if(!apply && !m_target->HasAuraType(SPELL_AURA_WATER_BREATHING))
{
- m_target->waterbreath = false;
-
// update for enable timer in case not moving target
if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld())
{
@@ -2401,6 +2451,9 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real)
else
modelid = 21244;
break;
+ case FORM_METAMORPHOSIS:
+ modelid = 25277;
+ break;
case FORM_AMBIENT:
case FORM_SHADOW:
case FORM_STEALTH:
@@ -2748,7 +2801,7 @@ void Aura::HandleAuraModSkill(bool apply, bool Real)
return;
uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex];
- int32 points = GetModifierValue();
+ int32 points = m_modifier.m_amount;
((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT);
if(prot == SKILL_DEFENSE)
@@ -2768,6 +2821,9 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real)
//talent will remove the caster's aura->interrupt channel->remove victim aura
if(victim->GetHealth() > 0)
return;
+ // Item amount
+ if (m_modifier.m_amount <= 0)
+ return;
SpellEntry const *spellInfo = GetSpellProto();
if(spellInfo->EffectItemType[m_effIndex] == 0)
@@ -2778,16 +2834,22 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real)
(victim->getLevel() <= Trinity::XP::GetGrayLevel(caster->getLevel()) ||
victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) )
return;
+ //Adding items
+ uint32 noSpaceForCount = 0;
+ uint32 count = m_modifier.m_amount;
+
ItemPosCountVec dest;
- uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 );
+ uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], count, &noSpaceForCount);
if( msg != EQUIP_ERR_OK )
{
+ count-=noSpaceForCount;
((Player*)caster)->SendEquipError( msg, NULL, NULL );
- return;
+ if (count==0)
+ return;
}
Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true);
- ((Player*)caster)->SendNewItem(newitem, 1, true, false);
+ ((Player*)caster)->SendNewItem(newitem, count, true, false);
}
}
@@ -2797,10 +2859,7 @@ void Aura::HandleBindSight(bool apply, bool Real)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
- if (apply)
- m_target->AddPlayerToVision((Player*)caster);
- else
- m_target->RemovePlayerFromVision((Player*)caster);
+ ((Player*)caster)->SetBindSight(apply ? m_target : NULL);
}
void Aura::HandleFarSight(bool apply, bool Real)
@@ -2809,7 +2868,7 @@ void Aura::HandleFarSight(bool apply, bool Real)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
- ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
+ ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0);
}
void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
@@ -2845,30 +2904,78 @@ void Aura::HandleAuraTrackStealthed(bool apply, bool Real)
void Aura::HandleAuraModScale(bool apply, bool Real)
{
- m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,GetModifierValue(),apply);
+ m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
}
-void Aura::HandleModPossess(bool apply, bool Real)
+/*void Aura::HandleModPossess(bool apply, bool Real)
{
if(!Real)
return;
+ if(m_target->getLevel() > m_modifier.m_amount)
+ return;
+
+ // not possess yourself
+ if(GetCasterGUID() == m_target->GetGUID())
+ return;
+
Unit* caster = GetCaster();
- if(caster && caster->GetTypeId() == TYPEID_UNIT)
- {
- HandleModCharm(apply, Real);
+ if(!caster)
return;
- }
- if(apply)
+ if( apply )
{
- if(m_target->getLevel() > m_modifier.m_amount)
- return;
+ m_target->SetCharmerGUID(GetCasterGUID());
+ m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
+ caster->SetCharm(m_target);
- m_target->SetCharmedOrPossessedBy(caster, true);
+ m_target->CombatStop();
+ m_target->DeleteThreatList();
+ if(m_target->GetTypeId() == TYPEID_UNIT)
+ {
+ m_target->StopMoving();
+ m_target->GetMotionMaster()->Clear();
+ m_target->GetMotionMaster()->MoveIdle();
+ CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
+ charmInfo->InitPossessCreateSpells();
+ }
+
+ if(caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ ((Player*)caster)->PossessSpellInitialize();
+ }
}
else
- m_target->RemoveCharmedOrPossessedBy(caster);
+ {
+ m_target->SetCharmerGUID(0);
+
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)m_target)->setFactionForRace(m_target->getRace());
+ else if(m_target->GetTypeId() == TYPEID_UNIT)
+ {
+ CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
+ m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
+ }
+
+ caster->SetCharm(0);
+
+ if(caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data(SMSG_PET_SPELLS, 8);
+ data << uint64(0);
+ data << uint32(0);
+ ((Player*)caster)->GetSession()->SendPacket(&data);
+ }
+ if(m_target->GetTypeId() == TYPEID_UNIT)
+ {
+ ((Creature*)m_target)->AIM_Initialize();
+
+ if (((Creature*)m_target)->AI())
+ ((Creature*)m_target)->AI()->AttackStart(caster);
+ }
+ }
+ if(caster->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0);
}
void Aura::HandleModPossessPet(bool apply, bool Real)
@@ -2879,42 +2986,151 @@ void Aura::HandleModPossessPet(bool apply, bool Real)
Unit* caster = GetCaster();
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
- if(caster->GetPet() != m_target)
+
+ Pet *pet = caster->GetPet();
+ if(!pet || pet != m_target)
return;
if(apply)
- m_target->SetCharmedOrPossessedBy(caster, true);
+ pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
else
- {
- m_target->RemoveCharmedOrPossessedBy(caster);
+ pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
- // Reinitialize the pet bar and make the pet come back to the owner
- ((Player*)caster)->PetSpellInitialize();
- if(!m_target->getVictim())
- {
- m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
- m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
- }
+ ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : NULL);
+ ((Player*)caster)->SetCharm(apply ? pet : NULL);
+ ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0);
+
+ if(apply)
+ {
+ pet->StopMoving();
+ pet->GetMotionMaster()->Clear();
+ pet->GetMotionMaster()->MoveIdle();
}
+ else
+ {
+ pet->AttackStop();
+ pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ pet->SetUnitMovementFlags(MOVEMENTFLAG_NONE);
+ }
+}*/
+
+void Aura::HandleAuraModPetTalentsPoints(bool Apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ // Recalculate pet tlaent points
+ if (Pet *pet=m_target->GetPet())
+ pet->InitTalentForLevel();
}
-void Aura::HandleModCharm(bool apply, bool Real)
+/*void Aura::HandleModCharm(bool apply, bool Real)
{
if(!Real)
return;
+ // not charm yourself
+ if(GetCasterGUID() == m_target->GetGUID())
+ return;
+
Unit* caster = GetCaster();
+ if(!caster)
+ return;
- if(apply)
+ if(int32(m_target->getLevel()) <= m_modifier.m_amount)
{
- if(int32(m_target->getLevel()) > m_modifier.m_amount)
- return;
-
- m_target->SetCharmedOrPossessedBy(caster, false);
+ if( apply )
+ {
+ m_target->SetCharmerGUID(GetCasterGUID());
+ m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
+ m_target->CastStop(m_target==caster ? GetId() : 0);
+ caster->SetCharm(m_target);
+
+ m_target->CombatStop();
+ m_target->DeleteThreatList();
+
+ if(m_target->GetTypeId() == TYPEID_UNIT)
+ {
+ ((Creature*)m_target)->AIM_Initialize();
+ CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
+ charmInfo->InitCharmCreateSpells();
+ charmInfo->SetReactState( REACT_DEFENSIVE );
+
+ if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
+ {
+ CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
+ if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
+ {
+ //to prevent client crash
+ m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
+ //just to enable stat window
+ charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
+ //if charmed two demons the same session, the 2nd gets the 1st one's name
+ m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
+ }
+ }
+ }
+
+ if(caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ ((Player*)caster)->CharmSpellInitialize();
+ }
+ }
+ else
+ {
+ m_target->SetCharmerGUID(0);
+
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)m_target)->setFactionForRace(m_target->getRace());
+ else
+ {
+ CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
+
+ // restore faction
+ if(((Creature*)m_target)->isPet())
+ {
+ if(Unit* owner = m_target->GetOwner())
+ m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
+ else if(cinfo)
+ m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
+ }
+ else if(cinfo) // normal creature
+ m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
+
+ // restore UNIT_FIELD_BYTES_0
+ if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
+ {
+ CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
+ if(cainfo && cainfo->bytes0 != 0)
+ m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
+ else
+ m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
+
+ if(m_target->GetCharmInfo())
+ m_target->GetCharmInfo()->SetPetNumber(0, true);
+ else
+ sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
+ }
+ }
+
+ caster->SetCharm(0);
+
+ if(caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data(SMSG_PET_SPELLS, 8);
+ data << uint64(0);
+ data << uint32(0);
+ ((Player*)caster)->GetSession()->SendPacket(&data);
+ }
+ if(m_target->GetTypeId() == TYPEID_UNIT)
+ {
+ ((Creature*)m_target)->AIM_Initialize();
+ if (((Creature*)m_target)->AI())
+ ((Creature*)m_target)->AI()->AttackStart(caster);
+ }
+ }
}
- else
- m_target->RemoveCharmedOrPossessedBy(caster);
-}
+}*/
void Aura::HandleModConfuse(bool apply, bool Real)
{
@@ -2953,7 +3169,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real)
std::list<Unit*> targets;
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_target, m_target, World::GetMaxVisibleDistance());
- Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
+ Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_target, targets, u_check);
m_target->VisitNearbyObject(World::GetMaxVisibleDistance(), searcher);
for(std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter)
{
@@ -2970,7 +3186,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real)
}
}
// blizz like 2.0.x
- m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
+ m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29);
// blizz like 2.0.x
m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
// blizz like 2.0.x
@@ -2995,7 +3211,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real)
m_target->SendMessageToSet(&data,true);
*/
// blizz like 2.0.x
- m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29);
// blizz like 2.0.x
m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
// blizz like 2.0.x
@@ -3065,7 +3281,7 @@ void Aura::HandleModStealth(bool apply, bool Real)
// only at real aura add
if(Real)
{
- m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02);
+ m_target->SetStandFlags(UNIT_STAND_FLAGS_CREEP);
if(m_target->GetTypeId()==TYPEID_PLAYER)
m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
@@ -3076,10 +3292,6 @@ void Aura::HandleModStealth(bool apply, bool Real)
//m_target->SetVisibility(VISIBILITY_OFF);
m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
}
-
- // for RACE_NIGHTELF stealth
- if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
- m_target->CastSpell(m_target, 21009, true, NULL, this);
}
}
else
@@ -3087,14 +3299,10 @@ void Aura::HandleModStealth(bool apply, bool Real)
// only at real aura remove
if(Real)
{
- // for RACE_NIGHTELF stealth
- if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
- m_target->RemoveAurasDueToSpell(21009);
-
// if last SPELL_AURA_MOD_STEALTH and no GM invisibility
if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
{
- m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00);
+ m_target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP);
if(m_target->GetTypeId()==TYPEID_PLAYER)
m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
@@ -3216,6 +3424,10 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
if(!Real)
return;
+ // Frost root aura -> freeze/unfreeze target
+ if (GetSpellSchoolMask(m_spellProto) & SPELL_SCHOOL_MASK_FROST)
+ m_target->ModifyAuraState(AURA_STATE_FROZEN, apply);
+
m_target->SetControlled(apply, UNIT_STAT_ROOT);
}
@@ -3255,7 +3467,7 @@ void Aura::HandleAuraModSilence(bool apply, bool Real)
return;
// Search Mana Tap auras on caster
- Aura * dummy = m_target->GetDummyAura(28734);
+ Aura * dummy = caster->GetDummyAura(28734);
if (dummy)
{
int32 bp = dummy->GetStackAmount() * 10;
@@ -3312,7 +3524,7 @@ void Aura::HandleModThreat(bool apply, bool Real)
if(m_modifier.m_miscvalue & int32(1<<x))
{
if(m_target->GetTypeId() == TYPEID_PLAYER)
- ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? GetModifierValue() : -GetModifierValue(), apply);
+ ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply);
}
}
}
@@ -3333,9 +3545,9 @@ void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
float threatMod = 0.0f;
if(apply)
- threatMod = float(GetModifierValue());
+ threatMod = float(m_modifier.m_amount);
else
- threatMod = float(-GetModifierValue());
+ threatMod = float(-m_modifier.m_amount);
m_target->getHostilRefManager().threatAssist(caster, threatMod);
}
@@ -3465,9 +3677,8 @@ void Aura::HandleModMechanicImmunity(bool apply, bool Real)
next = iter;
++next;
SpellEntry const *spell = iter->second->GetSpellProto();
- if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability
- && !iter->second->IsPositive() // only remove negative spells
- && spell->Id != GetId())
+ if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) && // spells unaffected by invulnerability
+ spell->Id != GetId())
{
//check for mechanic mask
if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
@@ -3484,17 +3695,6 @@ void Aura::HandleModMechanicImmunity(bool apply, bool Real)
m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply);
- // special cases
- switch(m_modifier.m_miscvalue)
- {
- case MECHANIC_INVULNERABILITY:
- m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply);
- break;
- case MECHANIC_SHIELD:
- m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply);
- break;
- }
-
// Bestial Wrath
if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->Id == 19574)
{
@@ -3668,8 +3868,7 @@ void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real)
switch (GetId())
{
case 28200: // Ascendance (Talisman of Ascendance trinket)
- m_procCharges = 6;
- UpdateAuraCharges();
+ SetAuraCharges(6);
break;
default: break;
}
@@ -3691,75 +3890,72 @@ void Aura::HandleAuraModStalked(bool apply, bool Real)
void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
{
- if (m_periodicTimer <= 0)
- m_periodicTimer += m_modifier.periodictime;
-
m_isPeriodic = apply;
- m_isTrigger = apply;
+}
- // Curse of the Plaguebringer
- if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL)
- {
- // Cast Wrath of the Plaguebringer if not dispelled
- m_target->CastSpell(m_target, 29214, true, 0, this);
- }
+void Aura::HandlePeriodicTriggerSpellWithValue(bool apply, bool Real)
+{
+ m_isPeriodic = apply;
}
void Aura::HandlePeriodicEnergize(bool apply, bool Real)
{
- if (m_periodicTimer <= 0)
- m_periodicTimer += m_modifier.periodictime;
+ if (!Real)
+ return;
m_isPeriodic = apply;
+
+ // Replenishment (0.25% from max)
+ // Infinite Replenishment
+ if (GetId() == 57669 ||
+ GetId() == 61782)
+ m_modifier.m_amount = m_target->GetMaxPower(POWER_MANA) * 25 / 10000;
}
-void Aura::HandlePeriodicHeal(bool apply, bool Real)
+void Aura::HandleAuraPowerBurn(bool apply, bool Real)
{
- if (m_periodicTimer <= 0)
- m_periodicTimer += m_modifier.periodictime;
-
m_isPeriodic = apply;
+}
- // only at real apply
- if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE)
- {
- // provided m_target as original caster to prevent apply aura caster selection for this negative buff
- m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID());
- }
+void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
// For prevent double apply bonuses
bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
- if(!loading && apply)
+ Unit* caster = GetCaster();
+
+ SpellEntry const*spell = GetSpellProto();
+ switch( spell->SpellFamilyName)
{
- switch (m_spellProto->SpellFamilyName)
+ case SPELLFAMILY_ROGUE:
{
- case SPELLFAMILY_DRUID:
+ // Master of Subtlety
+ if (spell->Id==31666 && !apply)
{
- // Rejuvenation
- if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL)
- {
- if(Unit* caster = GetCaster())
- {
- Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
- {
- int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
- switch((*k)->GetModifier()->m_miscvalue)
- {
- case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura
- case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura
- {
- m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
- break;
- }
- }
- }
- }
- }
+ m_target->RemoveAurasDueToSpell(31665);
+ break;
}
+ break;
+ }
+ case SPELLFAMILY_HUNTER:
+ {
+ // Explosive Shot
+ if (apply && !loading && caster)
+ m_modifier.m_amount +=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;
+ break;
}
}
+
+ m_isPeriodic = apply;
+}
+
+void Aura::HandlePeriodicHeal(bool apply, bool Real)
+{
+ m_isPeriodic = apply;
}
void Aura::HandlePeriodicDamage(bool apply, bool Real)
@@ -3768,26 +3964,28 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
if(!Real)
return;
- if (m_periodicTimer <= 0)
- m_periodicTimer += m_modifier.periodictime;
-
m_isPeriodic = apply;
// For prevent double apply bonuses
bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
+ // Custom damage calculation after
+ if (!apply || loading)
+ return;
+
Unit *caster = GetCaster();
+ if (!caster)
+ return;
switch (m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
{
// Pounce Bleed
- if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 )
+ if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual[0] == 0 )
{
// $AP*0.18/6 bonus per tick
- if (apply && !loading && caster)
- m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
return;
}
break;
@@ -3795,18 +3993,14 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
case SPELLFAMILY_WARRIOR:
{
// Rend
- if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
+ if (m_spellProto->SpellFamilyFlags[0] & 0x20)
{
- // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
- if (apply && !loading && caster)
- {
- float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
- int32 mws = caster->GetAttackTime(BASE_ATTACK);
- float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
- float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
- // WARNING! in 3.0 multiplier 0.00743f change to 0.6
- m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f);
- }
+ // $0.2*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
+ float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
+ int32 mws = caster->GetAttackTime(BASE_ATTACK);
+ float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
+ float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
+ m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.2f);
return;
}
break;
@@ -3814,92 +4008,80 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
case SPELLFAMILY_DRUID:
{
// Rake
- if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
+ if (m_spellProto->SpellFamilyFlags[0] & 0x1000)
{
- // $AP*0.06/3 bonus per tick
- if (apply && !loading && caster)
- m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100);
+ // $AP*0.06 bonus per tick
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 6 / 100);
return;
}
// Lacerate
- if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
+ if (m_spellProto->SpellFamilyFlags[1] & 0x0000000100)
{
// $AP*0.05/5 bonus per tick
- if (apply && !loading && caster)
- m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
return;
}
// Rip
- if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL)
+ if (m_spellProto->SpellFamilyFlags[1] & 0x800000)
{
- // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used]
- if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
- {
- uint8 cp = ((Player*)caster)->GetComboPoints();
+ // 0.01*$AP*cp
+ if (caster->GetTypeId() != TYPEID_PLAYER)
+ return;
- // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
- Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
- for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
+ uint8 cp = ((Player*)caster)->GetComboPoints();
+
+ // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
+ Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
+ {
+ if((*itr)->GetId()==34241)
{
- if((*itr)->GetId()==34241)
- {
- m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
- break;
- }
+ m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
+ break;
}
-
- if (cp > 4) cp = 4;
- m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
}
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
+ return;
+ }
+ // Lock Jaw
+ if (m_spellProto->SpellFamilyFlags[1] & 0x10000000)
+ {
+ // 0.15*$AP
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 15 / 100);
return;
}
break;
}
case SPELLFAMILY_ROGUE:
{
- // Deadly poison aura state
- if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100)
+ // Rupture
+ if (m_spellProto->SpellFamilyFlags[0] & 0x100000)
{
- if(apply)
- m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true);
- else
- {
- // current aura already removed, search present of another
- bool found = false;
- Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
- for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
- {
- SpellEntry const* itr_spell = (*itr)->GetSpellProto();
- if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual==5100)
- {
- found = true;
- break;
- }
- }
- // this has been last deadly poison aura
- if(!found)
- m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false);
- }
+ if (caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+ //1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs
+ //2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs
+ //3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs
+ //4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs
+ //5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs
+ float AP_per_combo[] = {0, 0.015f, 0.024, 0.03, 0.03428571, 0.0375};
+ uint8 cp = ((Player*)caster)->GetComboPoints();
+ if (cp > 5) cp = 5;
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]);
return;
}
- // Rupture
- if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL)
+ // Garrote
+ if (m_spellProto->SpellFamilyFlags[0] & 0x100)
{
- // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP]
- if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
- {
- uint8 cp = ((Player*)caster)->GetComboPoints();
- if (cp > 3) cp = 3;
- m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
- }
+ // $AP*0.07 bonus per tick
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 7 / 100);
return;
}
- // Garrote
- if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
+ // Deadly Poison
+ if (m_spellProto->SpellFamilyFlags[0] & 0x10000)
{
- // $AP*0.18/6 bonus per tick
- if (apply && !loading && caster)
- m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
+ // 0.08*$AP / 4 * amount of stack
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 * GetStackAmount() / 100);
return;
}
break;
@@ -3907,47 +4089,17 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
case SPELLFAMILY_HUNTER:
{
// Serpent Sting
- if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
+ if (m_spellProto->SpellFamilyFlags[0] & 0x4000)
{
// $RAP*0.1/5 bonus per tick
- if (apply && !loading && caster)
- m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
return;
}
// Immolation Trap
- if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
+ if (m_spellProto->SpellFamilyFlags[0] & 0x4 && m_spellProto->SpellIconID == 678)
{
// $RAP*0.1/5 bonus per tick
- if (apply && !loading && caster)
- m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
- return;
- }
- break;
- }
- case SPELLFAMILY_PALADIN:
- {
- // Consecration
- if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
- {
- if (apply && !loading)
- {
- if(Unit* caster = GetCaster())
- {
- Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
- {
- int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
- switch((*k)->GetModifier()->m_miscvalue)
- {
- case 5147: // Improved Consecration - Libram of the Eternal Rest
- {
- m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
- break;
- }
- }
- }
- }
- }
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
return;
}
break;
@@ -3959,25 +4111,21 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
{
- if (m_periodicTimer <= 0)
- m_periodicTimer += m_modifier.periodictime;
-
m_isPeriodic = apply;
}
void Aura::HandlePeriodicLeech(bool apply, bool Real)
{
- if (m_periodicTimer <= 0)
- m_periodicTimer += m_modifier.periodictime;
-
m_isPeriodic = apply;
}
void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
{
- if (m_periodicTimer <= 0)
- m_periodicTimer += m_modifier.periodictime;
+ m_isPeriodic = apply;
+}
+void Aura::HandlePeriodicHealthFunnel(bool apply, bool Real)
+{
m_isPeriodic = apply;
}
@@ -3995,9 +4143,9 @@ void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real)
{
if(m_modifier.m_miscvalue & int32(1<<x))
{
- m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply);
if(m_target->GetTypeId() == TYPEID_PLAYER)
- m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,GetModifierValue(), apply);
+ m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
}
}
}
@@ -4008,19 +4156,11 @@ void Aura::HandleAuraModResistance(bool apply, bool Real)
{
if(m_modifier.m_miscvalue & int32(1<<x))
{
- m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
- m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,GetModifierValue(), apply);
+ m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
}
}
-
- // Faerie Fire (druid versions)
- if( m_spellProto->SpellIconID == 109 &&
- m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID &&
- m_spellProto->SpellFamilyFlags & 0x0000000000000400LL )
- {
- m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply);
- }
}
void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
@@ -4030,14 +4170,14 @@ void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
{
//pets only have base armor
if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
- m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply);
}
else
{
for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
{
if(m_modifier.m_miscvalue & int32(1<<x))
- m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply);
}
}
}
@@ -4048,11 +4188,11 @@ void Aura::HandleModResistancePercent(bool apply, bool Real)
{
if(m_modifier.m_miscvalue & int32(1<<i))
{
- m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
{
- m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,GetModifierValue(), apply);
- m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,GetModifierValue(), apply);
+ m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply);
+ m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply);
}
}
}
@@ -4065,13 +4205,13 @@ void Aura::HandleModBaseResistance(bool apply, bool Real)
{
//only pets have base stats
if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
- m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
else
{
for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
if(m_modifier.m_miscvalue & (1<<i))
- m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
}
@@ -4093,9 +4233,9 @@ void Aura::HandleAuraModStat(bool apply, bool Real)
if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
{
//m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
- m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
- m_target->ApplyStatBuffMod(Stats(i),GetModifierValue(),apply);
+ m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply);
}
}
}
@@ -4115,7 +4255,7 @@ void Aura::HandleModPercentStat(bool apply, bool Real)
for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
- m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply);
}
}
@@ -4193,9 +4333,9 @@ void Aura::HandleModTotalPercentStat(bool apply, bool Real)
{
if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
{
- m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
- m_target->ApplyStatPercentBuffMod(Stats(i), GetModifierValue(), apply );
+ m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply );
}
}
@@ -4230,117 +4370,47 @@ void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real)
/********************************/
void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
{
- /*
- Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic,
- so this aura not fully working.
- */
- if(apply)
- {
- if(!m_target->isAlive())
- return;
-
- if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
- m_target->SetStandState(PLAYER_STATE_SIT);
-
- if(m_periodicTimer <= 0)
- {
- m_periodicTimer += m_modifier.periodictime;
-
- if(m_target->GetHealth() < m_target->GetMaxHealth())
- {
- // PeriodicTick can cast triggered spells with stats changes
- PeriodicTick();
- }
- }
- }
-
m_isPeriodic = apply;
}
void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
{
- if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
- m_target->SetStandState(PLAYER_STATE_SIT);
- if(apply)
- {
- if(m_modifier.periodictime == 0)
- m_modifier.periodictime = 1000;
- if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA)
- {
- m_periodicTimer += m_modifier.periodictime;
-
- if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA))
- {
- // PeriodicTick can cast triggered spells with stats changes
- PeriodicTick();
- }
- }
- }
+ if(m_modifier.periodictime == 0)
+ m_modifier.periodictime = 1000;
+ m_periodicTimer = m_modifier.periodictime;
m_isPeriodic = apply;
}
void Aura::HandleModRegen(bool apply, bool Real) // eating
{
- if(apply)
- {
- if(!m_target->isAlive())
- return;
-
- if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
- m_target->SetStandState(PLAYER_STATE_SIT);
-
- if(m_periodicTimer <= 0)
- {
- m_periodicTimer += 5000;
- int32 gain = m_target->ModifyHealth(GetModifierValue());
- Unit *caster = GetCaster();
- if (caster)
- {
- SpellEntry const *spellProto = GetSpellProto();
- if (spellProto)
- m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto);
- }
- }
- }
+ if(m_modifier.periodictime == 0)
+ m_modifier.periodictime = 5000;
+ m_periodicTimer = 5000;
m_isPeriodic = apply;
}
void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
{
- if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
- m_target->SetStandState(PLAYER_STATE_SIT);
+ if (!Real)
+ return;
- if(apply && m_periodicTimer <= 0)
+ Powers pt = m_target->getPowerType();
+ if(m_modifier.periodictime == 0)
{
- m_periodicTimer += 2000;
+ if (pt == POWER_RAGE)
+ m_modifier.periodictime = 1000;
+ else
+ m_modifier.periodictime = 2000;
+ }
- Powers pt = m_target->getPowerType();
- if(int32(pt) != m_modifier.m_miscvalue)
- return;
+ m_periodicTimer = 5000;
- if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
- {
- // eating anim
- m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
- }
- else if( GetId() == 20577 )
- {
- // cannibalize anim
- m_target->HandleEmoteCommand(398);
- }
+ if (m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
+ ((Player*)m_target)->UpdateManaRegen();
- // Warrior talent, gain 1 rage every 3 seconds while in combat
- if(pt == POWER_RAGE && m_target->isInCombat())
- {
- m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
- m_periodicTimer += 1000;
- }
- }
m_isPeriodic = apply;
- if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
- ((Player*)m_target)->UpdateManaRegen();
}
void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real)
@@ -4384,7 +4454,7 @@ void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
{
if(apply)
{
- m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
m_target->ModifyHealth(m_modifier.m_amount);
}
else
@@ -4393,7 +4463,7 @@ void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
m_target->ModifyHealth(-m_modifier.m_amount);
else
m_target->SetHealth(1);
- m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
}
}
@@ -4424,7 +4494,7 @@ void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real)
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
- m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/)
@@ -4435,12 +4505,17 @@ void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/)
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
- m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/)
{
- m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply);
+}
+
+void Aura::HandleAuraIncreaseBaseHealthPercent(bool apply, bool /*Real*/)
+{
+ m_target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(m_modifier.m_amount), apply);
}
/********************************/
@@ -4504,9 +4579,9 @@ void Aura::HandleAuraModCritPercent(bool apply, bool Real)
if (GetSpellProto()->EquippedItemClass == -1)
{
- ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetModifierValue()), apply);
- ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetModifierValue()), apply);
- ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetModifierValue()), apply);
+ ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
+ ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
+ ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
}
else
{
@@ -4516,13 +4591,28 @@ void Aura::HandleAuraModCritPercent(bool apply, bool Real)
void Aura::HandleModHitChance(bool apply, bool Real)
{
- m_target->m_modMeleeHitChance += apply ? GetModifierValue() : -GetModifierValue();
- m_target->m_modRangedHitChance += apply ? GetModifierValue() : -GetModifierValue();
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ ((Player*)m_target)->UpdateMeleeHitChances();
+ ((Player*)m_target)->UpdateRangedHitChances();
+ }
+ else
+ {
+ m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
+ m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
+ }
}
void Aura::HandleModSpellHitChance(bool apply, bool Real)
{
- m_target->m_modSpellHitChance += apply ? GetModifierValue(): -GetModifierValue();
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ ((Player*)m_target)->UpdateSpellHitChances();
+ }
+ else
+ {
+ m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount);
+ }
}
void Aura::HandleModSpellCritChance(bool apply, bool Real)
@@ -4537,7 +4627,7 @@ void Aura::HandleModSpellCritChance(bool apply, bool Real)
}
else
{
- m_target->m_baseSpellCritChance += apply ? GetModifierValue():-GetModifierValue();
+ m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:-m_modifier.m_amount;
}
}
@@ -4561,22 +4651,22 @@ void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real)
void Aura::HandleModCastingSpeed(bool apply, bool Real)
{
- m_target->ApplyCastTimePercentMod(GetModifierValue(),apply);
+ m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
}
void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real)
{
- m_target->ApplyAttackTimePercentMod(BASE_ATTACK,GetModifierValue(),apply);
- m_target->ApplyAttackTimePercentMod(OFF_ATTACK,GetModifierValue(),apply);
- m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetModifierValue(), apply);
+ m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
}
void Aura::HandleModCombatSpeedPct(bool apply, bool Real)
{
- m_target->ApplyCastTimePercentMod(GetModifierValue(),apply);
- m_target->ApplyAttackTimePercentMod(BASE_ATTACK,GetModifierValue(),apply);
- m_target->ApplyAttackTimePercentMod(OFF_ATTACK,GetModifierValue(),apply);
- m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetModifierValue(), apply);
+ m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
}
void Aura::HandleModAttackSpeed(bool apply, bool Real)
@@ -4584,26 +4674,26 @@ void Aura::HandleModAttackSpeed(bool apply, bool Real)
if(!m_target->isAlive() )
return;
- m_target->ApplyAttackTimePercentMod(BASE_ATTACK,GetModifierValue(),apply);
+ m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
}
void Aura::HandleHaste(bool apply, bool Real)
{
- m_target->ApplyAttackTimePercentMod(BASE_ATTACK, GetModifierValue(),apply);
- m_target->ApplyAttackTimePercentMod(OFF_ATTACK, GetModifierValue(),apply);
- m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,GetModifierValue(),apply);
+ m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply);
}
void Aura::HandleAuraModRangedHaste(bool apply, bool Real)
{
- m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetModifierValue(), apply);
+ m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
}
void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
- m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,GetModifierValue(), apply);
+ m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply);
}
/********************************/
@@ -4612,7 +4702,7 @@ void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
void Aura::HandleAuraModAttackPower(bool apply, bool Real)
{
- m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
@@ -4620,13 +4710,13 @@ void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
return;
- m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real)
{
//UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
- m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
@@ -4635,7 +4725,7 @@ void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
return;
//UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
- m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
@@ -4644,18 +4734,20 @@ void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
if(!Real)
return;
- if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
- return;
+ // Recalculate bonus
+ if(m_target->GetTypeId() == TYPEID_PLAYER && !(m_target->getClassMask() & CLASSMASK_WAND_USERS))
+ ((Player*)m_target)->UpdateAttackPowerAndDamage(true);
+}
- if(m_modifier.m_miscvalue != STAT_INTELLECT)
- {
- // support required adding UpdateAttackPowerAndDamage calls at stat update
- sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intellect stats!");
+void Aura::HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
return;
- }
// Recalculate bonus
- ((Player*)m_target)->UpdateAttackPowerAndDamage(true);
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)m_target)->UpdateAttackPowerAndDamage(false);
}
/********************************/
@@ -4685,9 +4777,9 @@ void Aura::HandleModDamageDone(bool apply, bool Real)
// apply generic physical damage bonuses including wand case
if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
{
- m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetModifierValue()), apply);
- m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetModifierValue()), apply);
- m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
else
{
@@ -4697,9 +4789,9 @@ void Aura::HandleModDamageDone(bool apply, bool Real)
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
if(m_positive)
- m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,GetModifierValue(),apply);
+ m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply);
else
- m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,GetModifierValue(),apply);
+ m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply);
}
}
@@ -4725,7 +4817,7 @@ void Aura::HandleModDamageDone(bool apply, bool Real)
for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
{
if((m_modifier.m_miscvalue & (1<<i)) != 0)
- m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,GetModifierValue(),apply);
+ m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply);
}
}
else
@@ -4733,7 +4825,7 @@ void Aura::HandleModDamageDone(bool apply, bool Real)
for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
{
if((m_modifier.m_miscvalue & (1<<i)) != 0)
- m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,GetModifierValue(),apply);
+ m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply);
}
}
Pet* pet = m_target->GetPet();
@@ -4768,9 +4860,9 @@ void Aura::HandleModDamagePercentDone(bool apply, bool Real)
// apply generic physical damage bonuses including wand case
if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
{
- m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetModifierValue()), apply);
- m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetModifierValue()), apply);
- m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
else
{
@@ -4809,7 +4901,7 @@ void Aura::HandleModOffhandDamagePercent(bool apply, bool Real)
sLog.outDebug("AURA MOD OFFHAND DAMAGE");
- m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetModifierValue()), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
/********************************/
@@ -4822,7 +4914,7 @@ void Aura::HandleModPowerCostPCT(bool apply, bool Real)
if(!Real)
return;
- float amount = GetModifierValue() /100.0f;
+ float amount = m_modifier.m_amount /100.0f;
for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
if(m_modifier.m_miscvalue & (1<<i))
m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
@@ -4836,7 +4928,24 @@ void Aura::HandleModPowerCost(bool apply, bool Real)
for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
if(m_modifier.m_miscvalue & (1<<i))
- m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,GetModifierValue(),apply);
+ m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply);
+}
+
+void Aura::HandleNoReagentUseAura(bool Apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+ flag96 mask;
+ Unit::AuraList const& noReagent = m_target->GetAurasByType(SPELL_AURA_NO_REAGENT_USE);
+ for(Unit::AuraList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i)
+ mask |= (*i)->m_spellProto->EffectSpellClassMask[(*i)->m_effIndex];
+
+ m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]);
+ m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]);
+ m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]);
}
/*********************************************************/
@@ -4857,6 +4966,7 @@ void Aura::HandleShapeshiftBoosts(bool apply)
break;
case FORM_TREE:
spellId = 5420;
+ spellId2 = 34123;
break;
case FORM_TRAVEL:
spellId = 5419;
@@ -4890,11 +5000,16 @@ void Aura::HandleShapeshiftBoosts(bool apply)
break;
case FORM_FLIGHT:
spellId = 33948;
+ spellId2 = 34764;
break;
case FORM_FLIGHT_EPIC:
spellId = 40122;
spellId2 = 40121;
break;
+ case FORM_METAMORPHOSIS:
+ spellId = 54817;
+ spellId2 = 54879;
+ break;
case FORM_SPIRITOFREDEMPTION:
spellId = 27792;
spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
@@ -4925,7 +5040,7 @@ void Aura::HandleShapeshiftBoosts(bool apply)
if(itr->second->state == PLAYERSPELL_REMOVED) continue;
if(itr->first==spellId || itr->first==spellId2) continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
- if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue;
+ if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7)))) continue;
if (spellInfo->Stances & (1<<form))
m_target->CastSpell(m_target, itr->first, true, NULL, this);
}
@@ -4992,9 +5107,9 @@ void Aura::HandleAuraEmpathy(bool apply, bool Real)
void Aura::HandleAuraUntrackable(bool apply, bool Real)
{
if(apply)
- m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
+ m_target->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE);
else
- m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
+ m_target->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE);
}
void Aura::HandleAuraModPacify(bool apply, bool Real)
@@ -5057,7 +5172,21 @@ void Aura::HandleModRating(bool apply, bool Real)
for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
if (m_modifier.m_miscvalue & (1 << rating))
- ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), GetModifierValue(), apply);
+ ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply);
+}
+
+void Aura::HandleModRatingFromStat(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+ // Just recalculate ratings
+ for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
+ if (m_modifier.m_miscvalue & (1 << rating))
+ ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), 0, apply);
}
void Aura::HandleForceMoveForward(bool apply, bool Real)
@@ -5088,11 +5217,11 @@ void Aura::HandleModTargetResistance(bool apply, bool Real)
// show armor penetration
if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
- m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,GetModifierValue(), apply);
+ m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply);
// show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL)
- m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,GetModifierValue(), apply);
+ m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply);
}
void Aura::HandleShieldBlockValue(bool apply, bool Real)
@@ -5102,7 +5231,7 @@ void Aura::HandleShieldBlockValue(bool apply, bool Real)
modType = PCT_MOD;
if(m_target->GetTypeId() == TYPEID_PLAYER)
- ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(GetModifierValue()), apply);
+ ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
@@ -5120,7 +5249,7 @@ void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
// remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
if( !apply && m_duration==0 && target->GetComboTarget())
if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget()))
- target->AddComboPoints(unit, -GetModifierValue());
+ target->AddComboPoints(unit, -m_modifier.m_amount);
}
void Aura::HandleModUnattackable( bool Apply, bool Real )
@@ -5150,7 +5279,7 @@ void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
// set stand state (expected in this form)
if(!m_target->IsStandState())
- m_target->SetStandState(PLAYER_STATE_NONE);
+ m_target->SetStandState(UNIT_STAND_STATE_STAND);
}
m_target->SetHealth(1);
@@ -5162,6 +5291,14 @@ void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
void Aura::CleanupTriggeredSpells()
{
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[1] & 0x00000010 || m_spellProto->SpellFamilyFlags[0] & 0x00000020)
+ {
+ // Blood Frenzy remove
+ m_target->RemoveAurasDueToSpell(30069);
+ m_target->RemoveAurasDueToSpell(30070);
+ return;
+ }
+
uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
if(!tSpellId)
return;
@@ -5181,14 +5318,6 @@ void Aura::CleanupTriggeredSpells()
m_target->RemoveAurasDueToSpell(tSpellId);
}
-void Aura::HandleAuraPowerBurn(bool apply, bool Real)
-{
- if (m_periodicTimer <= 0)
- m_periodicTimer += m_modifier.periodictime;
-
- m_isPeriodic = apply;
-}
-
void Aura::HandleSchoolAbsorb(bool apply, bool Real)
{
if(!Real)
@@ -5211,7 +5340,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real)
}
break;
case SPELLFAMILY_MAGE:
- if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL)
+ if(m_spellProto->SpellFamilyFlags.IsEqual(0x80100) || m_spellProto->SpellFamilyFlags.IsEqual(0x8) || m_spellProto->SpellFamilyFlags.IsEqual(0,0x1))
{
//frost ward, fire ward, ice barrier
//+10% from +spd bonus
@@ -5220,7 +5349,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real)
}
break;
case SPELLFAMILY_WARLOCK:
- if(m_spellProto->SpellFamilyFlags == 0x00)
+ if(m_spellProto->SpellFamilyFlags.IsEqual(0,0,0x40))
{
//shadow ward
//+10% from +spd bonus
@@ -5312,28 +5441,25 @@ void Aura::PeriodicTick()
CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
// ignore non positive values (can be result apply spellmods to aura damage
- uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0;
-
- uint32 pdamage;
+ //uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0;
+ uint32 pdamage = GetModifier()->m_amount > 0 ? GetModifier()->m_amount : 0;
if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE)
{
- pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),amount,DOT);
+ pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount());
// Calculate armor mitigation if it is a physical spell
// But not for bleed mechanic spells
if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
{
- uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
+ uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage, GetSpellProto());
cleanDamage.damage += pdamage - pdamageReductedArmor;
pdamage = pdamageReductedArmor;
}
- //pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
-
// Curse of Agony damage-per-tick calculation
- if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544)
+ if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x400) && GetSpellProto()->SpellIconID==544)
{
// 1..4 ticks, 1/2 from normal tick damage
if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3))
@@ -5345,15 +5471,13 @@ void Aura::PeriodicTick()
}
}
else
- pdamage = uint32(m_target->GetMaxHealth()*amount/100);
+ pdamage = uint32(m_target->GetMaxHealth()*pdamage/100);
//As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
// Reduce dot damage from resilience for players
if (m_target->GetTypeId()==TYPEID_PLAYER)
pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
- pdamage *= GetStackAmount();
-
pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
@@ -5366,6 +5490,7 @@ void Aura::PeriodicTick()
data << uint32(1);
data << uint32(m_modifier.m_auraname);
data << (uint32)pdamage;
+ data << uint32(0); // overkill
data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x
data << (uint32)absorb;
data << (uint32)resist;
@@ -5386,6 +5511,7 @@ void Aura::PeriodicTick()
break;
}
case SPELL_AURA_PERIODIC_LEECH:
+ case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
{
Unit *pCaster = GetCaster();
if(!pCaster)
@@ -5398,7 +5524,7 @@ void Aura::PeriodicTick()
pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
return;
- // Check for immune (not use charges)
+ // Check for immune
if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
return;
@@ -5406,79 +5532,23 @@ void Aura::PeriodicTick()
uint32 resist=0;
CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
- uint32 pdamage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0;
- pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
+ //uint32 pdamage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0;
+ uint32 pdamage = GetModifier()->m_amount > 0 ? GetModifier()->m_amount : 0;
+ pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount());
//Calculate armor mitigation if it is a physical spell
if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
{
- uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
+ uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage, GetSpellProto());
cleanDamage.damage += pdamage - pdamageReductedArmor;
pdamage = pdamageReductedArmor;
}
- //pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
-
- // talent Soul Siphon add bonus to Drain Life spells
- if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) )
- {
- // find talent max bonus percentage
- Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i)
- {
- if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993)
- {
- if((*i)->GetEffIndex()!=1)
- {
- sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId());
- break;
- }
-
- // effect 1 m_amount
- int32 maxPercent = (*i)->GetModifier()->m_amount;
- // effect 0 m_amount
- int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster);
-
- // count affliction effects and calc additional damage in percentage
- int32 modPercent = 0;
- Unit::AuraMap const& victimAuras = m_target->GetAuras();
- for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
- {
- Aura* aura = itr->second;
- if (aura->IsPositive())continue;
- SpellEntry const* m_spell = aura->GetSpellProto();
- if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK)
- continue;
-
- SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id);
- SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id);
-
- for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
- {
- if(_spell_idx->second->skillId == SKILL_AFFLICTION)
- {
- modPercent += stepPercent;
- if (modPercent >= maxPercent)
- {
- modPercent = maxPercent;
- break;
- }
- }
- }
- }
- pdamage += (pdamage*modPercent/100);
- break;
- }
- }
- }
-
//As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
// Reduce dot damage from resilience for players
if (m_target->GetTypeId()==TYPEID_PLAYER)
pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
- pdamage *= GetStackAmount();
-
pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
if(m_target->GetHealth() < pdamage)
@@ -5516,7 +5586,7 @@ void Aura::PeriodicTick()
if(Player *modOwner = pCaster->GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
- uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster);
+ uint32 heal = pCaster->SpellHealingBonus(pCaster, spellProto, uint32(new_damage * multiplier), DOT, GetStackAmount());
int32 gain = pCaster->ModifyHealth(heal);
pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
@@ -5532,22 +5602,17 @@ void Aura::PeriodicTick()
return;
// heal for caster damage (must be alive)
- if(m_target != pCaster && GetSpellProto()->SpellVisual==163 && !pCaster->isAlive())
+ if(m_target != pCaster && GetSpellProto()->SpellVisual[0]==163 && !pCaster->isAlive())
return;
// ignore non positive values (can be result apply spellmods to aura damage
- uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0;
-
- uint32 pdamage;
+ //uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0;
+ uint32 pdamage = GetModifier()->m_amount > 0 ? GetModifier()->m_amount : 0;
if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH)
- pdamage = uint32(m_target->GetMaxHealth() * amount/100);
+ pdamage = uint32(m_target->GetMaxHealth() * pdamage * GetStackAmount() / 100);
else
- pdamage = pCaster->SpellHealingBonus(GetSpellProto(), amount, DOT, m_target);
-
- pdamage *= GetStackAmount();
-
- //pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target);
+ pdamage = pCaster->SpellHealingBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount());
sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
@@ -5559,6 +5624,7 @@ void Aura::PeriodicTick()
data << uint32(1);
data << uint32(m_modifier.m_auraname);
data << (uint32)pdamage;
+ data << uint32(0); // wotlk
m_target->SendMessageToSet(&data,true);
int32 gain = m_target->ModifyHealth(pdamage);
@@ -5578,7 +5644,7 @@ void Aura::PeriodicTick()
bool haveCastItem = GetCastItemGUID()!=0;
// heal for caster damage
- if(m_target!=pCaster && spellProto->SpellVisual==163)
+ if(m_target!=pCaster && spellProto->SpellVisual[0]==163)
{
uint32 dmg = spellProto->manaPerSecond;
if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER)
@@ -5630,12 +5696,12 @@ void Aura::PeriodicTick()
return;
// ignore non positive values (can be result apply spellmods to aura damage
- uint32 pdamage = GetModifierValue() > 0 ? GetModifierValue() : 0;
+ uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
- if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
+ if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
break;
Powers power = Powers(m_modifier.m_miscvalue);
@@ -5692,12 +5758,12 @@ void Aura::PeriodicTick()
case SPELL_AURA_PERIODIC_ENERGIZE:
{
// ignore non positive values (can be result apply spellmods to aura damage
- uint32 pdamage = GetModifierValue() > 0 ? GetModifierValue() : 0;
+ uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
- if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
+ if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
break;
Powers power = Powers(m_modifier.m_miscvalue);
@@ -5724,7 +5790,7 @@ void Aura::PeriodicTick()
case SPELL_AURA_OBS_MOD_MANA:
{
// ignore non positive values (can be result apply spellmods to aura damage
- uint32 amount = GetModifierValue() > 0 ? GetModifierValue() : 0;
+ uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100);
@@ -5760,7 +5826,7 @@ void Aura::PeriodicTick()
if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
return;
- int32 pdamage = GetModifierValue() > 0 ? GetModifierValue() : 0;
+ int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
Powers powerType = Powers(m_modifier.m_miscvalue);
@@ -5794,12 +5860,51 @@ void Aura::PeriodicTick()
pCaster->DealSpellDamage(&damageInfo, true);
break;
}
+ case SPELL_AURA_MOD_REGEN:
+ {
+ int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
+ if (Unit *caster = GetCaster())
+ m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
+ break;
+ }
+ case SPELL_AURA_MOD_POWER_REGEN:
+ {
+ Powers pt = m_target->getPowerType();
+ if(int32(pt) != m_modifier.m_miscvalue)
+ return;
+
+ if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
+ {
+ // eating anim
+ m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
+ }
+ else if( GetId() == 20577 )
+ {
+ // cannibalize anim
+ m_target->HandleEmoteCommand(EMOTE_STATE_CANNIBALIZE);
+ }
+
+ // Warrior talent, gain 1 rage every 3 seconds while in combat
+ if(pt == POWER_RAGE && m_target->isInCombat())
+ m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
+ break;
+ }
// Here tick dummy auras
case SPELL_AURA_PERIODIC_DUMMY:
{
PeriodicDummyTick();
break;
}
+ case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
+ {
+ TriggerSpell();
+ break;
+ }
+ case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
+ {
+ TriggerSpellWithValue();
+ break;
+ }
default:
break;
}
@@ -5807,114 +5912,77 @@ void Aura::PeriodicTick()
void Aura::PeriodicDummyTick()
{
+ Unit *caster = GetCaster();
SpellEntry const* spell = GetSpellProto();
- switch (spell->Id)
- {
- // Drink
- case 430:
- case 431:
- case 432:
- case 1133:
- case 1135:
- case 1137:
- case 10250:
- case 22734:
- case 27089:
- case 34291:
- case 43706:
- case 46755:
+ switch (spell->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ switch (spell->Id)
{
- if (m_target->GetTypeId() != TYPEID_PLAYER)
- return;
- // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
- Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
- for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
+ // Drink
+ case 430:
+ case 431:
+ case 432:
+ case 1133:
+ case 1135:
+ case 1137:
+ case 10250:
+ case 22734:
+ case 27089:
+ case 34291:
+ case 43706:
+ case 46755:
+ case 49472: // Drink Coffee
+ case 61830:
{
- if ((*i)->GetId() == GetId())
+ if (m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+ // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
+ Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
+ for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
{
- // Get tick number
- int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime;
- // Default case (not on arenas)
- if (tick == 0)
+ if ((*i)->GetId() == GetId())
{
(*i)->GetModifier()->m_amount = m_modifier.m_amount;
((Player*)m_target)->UpdateManaRegen();
// Disable continue
m_isPeriodic = false;
- }
- return;
- //**********************************************
- // Code commended since arena patch not added
- // This feature uses only in arenas
- //**********************************************
- // Here need increase mana regen per tick (6 second rule)
- // on 0 tick - 0 (handled in 2 second)
- // on 1 tick - 166% (handled in 4 second)
- // on 2 tick - 133% (handled in 6 second)
- // Not need update after 3 tick
- /*
- if (tick > 3)
return;
- // Apply bonus for 0 - 3 tick
- switch (tick)
- {
- case 0: // 0%
- (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0;
- break;
- case 1: // 166%
- (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3;
- break;
- case 2: // 133%
- (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3;
- break;
- default: // 100% - normal regen
- (*i)->GetModifier()->m_amount = m_modifier.m_amount;
- break;
}
- ((Player*)m_target)->UpdateManaRegen();
- return;*/
}
+ return;
+ }
+ // Forsaken Skills
+ case 7054:
+ {
+ // Possibly need cast one of them (but
+ // 7038 Forsaken Skill: Swords
+ // 7039 Forsaken Skill: Axes
+ // 7040 Forsaken Skill: Daggers
+ // 7041 Forsaken Skill: Maces
+ // 7042 Forsaken Skill: Staves
+ // 7043 Forsaken Skill: Bows
+ // 7044 Forsaken Skill: Guns
+ // 7045 Forsaken Skill: 2H Axes
+ // 7046 Forsaken Skill: 2H Maces
+ // 7047 Forsaken Skill: 2H Swords
+ // 7048 Forsaken Skill: Defense
+ // 7049 Forsaken Skill: Fire
+ // 7050 Forsaken Skill: Frost
+ // 7051 Forsaken Skill: Holy
+ // 7053 Forsaken Skill: Shadow
+ return;
}
- return;
- }
// // Panda
// case 19230: break;
-// // Master of Subtlety
-// case 31666: break;
// // Gossip NPC Periodic - Talk
// case 33208: break;
// // Gossip NPC Periodic - Despawn
// case 33209: break;
-// // Force of Nature
-// case 33831: break;
- // Aspect of the Viper
- case 34074:
- {
- if (m_target->GetTypeId() != TYPEID_PLAYER)
- return;
- // Should be manauser
- if (m_target->getPowerType()!=POWER_MANA)
- return;
- Unit *caster = GetCaster();
- if (!caster)
- return;
- // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell)
- int mana = m_target->GetPower(POWER_MANA);
- int max_mana = m_target->GetMaxPower(POWER_MANA);
- int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
- float regen_pct = 1.20f - 1.1f * mana / max_mana;
- if (regen_pct > 1.0f) regen_pct = 1.0f;
- else if (regen_pct < 0.2f) regen_pct = 0.2f;
- m_modifier.m_amount = int32 (base_regen * regen_pct);
- ((Player*)m_target)->UpdateManaRegen();
- return;
- }
// // Steal Weapon
// case 36207: break;
// // Simon Game START timer, (DND)
// case 39993: break;
-// // Harpooner's Mark
-// case 40084: break;
// // Knockdown Fel Cannon: break; The Aggro Burst
// case 40119: break;
// // Old Mount Spell
@@ -5927,6 +5995,8 @@ void Aura::PeriodicDummyTick()
// case 40846: break;
// // Copy Weapon
// case 41054: break;
+// // Dementia
+// case 41404: break;
// // Ethereal Ring Visual, Lightning Aura
// case 41477: break;
// // Ethereal Ring Visual, Lightning Aura (Fork)
@@ -5975,6 +6045,8 @@ void Aura::PeriodicDummyTick()
// case 43310: break;
// // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
// case 43884: break;
+// // Wretched!
+// case 43963: break;
// // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
// case 44000: break;
// // Energy Feedback
@@ -6041,14 +6113,190 @@ void Aura::PeriodicDummyTick()
// case 47407: break;
// // Mole Machine Port Schedule
// case 47489: break;
+// case 47941: break; // Crystal Spike
+// case 48200: break; // Healer Aura
+// case 48630: break; // Summon Gauntlet Mobs Periodic
+// case 49313: break; // Proximity Mine Area Aura
// // Mole Machine Portal Schedule
// case 49466: break;
-// // Drink Coffee
-// case 49472: break;
+// case 49555: break; // Corpse Explode
+// case 49592: break; // Temporal Rift
+// case 49957: break; // Cutting Laser
+// case 50085: break; // Slow Fall
// // Listening to Music
// case 50493: break;
// // Love Rocket Barrage
// case 50530: break;
+// Exist more after, need add later
+ default:
+ break;
+ }
+ break;
+ case SPELLFAMILY_MAGE:
+ {
+ // Mirror Image
+// if (spell->Id == 55342)
+// return;
+ break;
+ }
+ case SPELLFAMILY_WARRIOR:
+ {
+ // Armored to the Teeth
+ if (spell->SpellIconID == 3516)
+ {
+ // Increases your attack power by $s1 for every $s2 armor value you have.
+ // Calculate AP bonus (from 1 efect of this spell)
+ int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
+ m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this);
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_DRUID:
+ {
+ switch (spell->Id)
+ {
+ // Frenzied Regeneration
+ case 22842:
+ {
+ // Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health.
+ // Should be manauser
+ if (m_target->getPowerType()!=POWER_RAGE)
+ return;
+ uint32 rage = m_target->GetPower(POWER_RAGE);
+ // Nothing todo
+ if (rage == 0)
+ return;
+ int32 mod = (rage < 100) ? rage : 100;
+ int32 points = m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
+ int32 regen = m_target->GetMaxHealth() * (mod * points / 10) / 1000;
+ m_target->CastCustomSpell(m_target, 22845, &regen, 0, 0, true, 0, this);
+ m_target->SetPower(POWER_RAGE, rage-mod);
+ return;
+ }
+ // Force of Nature
+ case 33831:
+ return;
+ default:
+ break;
+ }
+ break;
+ }
+ case SPELLFAMILY_ROGUE:
+ {
+// switch (spell->Id)
+// {
+ // Master of Subtlety
+// case 31666: break;
+ // Killing Spree
+// case 51690: break;
+ // Overkill
+// case 58428: break;
+// default:
+// break;
+// }
+ break;
+ }
+ case SPELLFAMILY_HUNTER:
+ {
+ // Explosive Shot
+ if (spell->SpellFamilyFlags[1] & 0x80000000)
+ {
+ if (!caster)
+ return;
+ int32 damage = m_modifier.m_amount;
+ // Full damage to target at 0 tick
+ if (m_duration > m_modifier.periodictime)
+ {
+ caster->CastCustomSpell(m_target, 53352, &damage, 0, 0, true, 0, this);
+ return;
+ }
+ damage/=4;
+ caster->CastCustomSpell(m_target, 56298, &damage, 0, 0, true, 0, this);
+ return;
+ }
+ switch (spell->Id)
+ {
+ // Harpooner's Mark
+ // case 40084:
+ // return;
+ // Feeding Frenzy Rank 1
+ case 53511:
+ if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 )
+ m_target->CastSpell(m_target, 60096, true, 0, this);
+ return;
+ // Feeding Frenzy Rank 2
+ case 53512:
+ if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 )
+ m_target->CastSpell(m_target, 60097, true, 0, this);
+ return;
+ default:
+ break;
+ }
+ break;
+ }
+ case SPELLFAMILY_SHAMAN:
+ {
+ // Astral Shift
+ if (spell->Id == 52179)
+ {
+ // Periodic need for remove visual on stun/fear/silence lost
+ if (!(m_target->GetUInt32Value(UNIT_FIELD_FLAGS)&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED)))
+ m_target->RemoveAurasDueToSpell(52179);
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_DEATHKNIGHT:
+ {
+ // Death and Decay
+ if (spell->SpellFamilyFlags[0] & 0x20)
+ {
+ if (caster)
+ caster->CastCustomSpell(m_target, 52212, &m_modifier.m_amount, NULL, NULL, true, 0, this);
+ return;
+ }
+ // Raise Dead
+// if (spell->SpellFamilyFlags & 0x0000000000001000LL)
+// return;
+ // Chains of Ice
+ if (spell->SpellFamilyFlags[1] & 0x00004000)
+ {
+ // Get 0 effect aura
+ Aura *slow = m_target->GetAura(GetId(), 0);
+ if (slow)
+ {
+ slow->ApplyModifier(false, true);
+ Modifier *mod = slow->GetModifier();
+ mod->m_amount+= m_modifier.m_amount;
+ if (mod->m_amount > 0) mod->m_amount = 0;
+ slow->ApplyModifier(true, true);
+ }
+ return;
+ }
+ // Summon Gargoyle
+// if (spell->SpellFamilyFlags & 0x0000008000000000LL)
+// return;
+ // Death Rune Mastery
+// if (spell->SpellFamilyFlags & 0x0000000000004000LL)
+// return;
+ // Bladed Armor
+ if (spell->SpellIconID == 2653)
+ {
+ // Increases your attack power by $s1 for every $s2 armor value you have.
+ // Calculate AP bonus (from 1 efect of this spell)
+ int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
+ m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this);
+ return;
+ }
+ // Reaping
+// if (spell->SpellIconID == 22)
+// return;
+ // Blood of the North
+// if (spell->SpellIconID == 30412)
+// return;
+ break;
+ }
default:
break;
}
@@ -6084,7 +6332,7 @@ void Aura::HandleManaShield(bool apply, bool Real)
switch(m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_MAGE:
- if(m_spellProto->SpellFamilyFlags & 0x8000)
+ if(m_spellProto->SpellFamilyFlags[0] & 0x8000)
{
// Mana Shield
// +50% from +spd bonus
@@ -6114,14 +6362,164 @@ void Aura::HandleArenaPreparation(bool apply, bool Real)
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
}
-void Aura::HandleModAttackerSpellHitChance(bool apply, bool Real)
+void Aura::HandleAuraControlVehicle(bool apply, bool Real)
{
if(!Real)
return;
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if(Pet *pet = m_target->GetPet())
+ pet->Remove(PET_SAVE_AS_CURRENT);
+
+ WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
+ ((Player*)m_target)->GetSession()->SendPacket(&data);
+}
+
+void Aura::HandleAuraConvertRune(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ Player *plr = (Player*)m_target;
+
+ if(plr->getClass() != CLASS_DEATH_KNIGHT)
+ return;
+
+ // how to determine what rune need to be converted?
+ for(uint32 i = 0; i < MAX_RUNES; ++i)
+ {
+ if(apply)
+ {
+ if(!plr->GetRuneCooldown(i))
+ {
+ plr->ConvertRune(i, GetSpellProto()->EffectMiscValueB[m_effIndex]);
+ break;
+ }
+ }
+ else
+ {
+ if(plr->GetCurrentRune(i) == GetSpellProto()->EffectMiscValueB[m_effIndex])
+ {
+ plr->ConvertRune(i, plr->GetBaseRune(i));
+ break;
+ }
+ }
+ }
+}
+
+void Aura::HandleModAttackerSpellHitChance(bool apply, bool Real)
+{
if(GetId() != 31224)
return;
//cloak of shadows : flare
m_target->ApplySpellImmune(31224, IMMUNITY_ID, 1543, apply);
-} \ No newline at end of file
+}
+
+void Aura::HandleModPossess(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ Unit* caster = GetCaster();
+ if(caster && caster->GetTypeId() == TYPEID_UNIT)
+ {
+ HandleModCharm(apply, Real);
+ return;
+ }
+
+ if(apply)
+ {
+ if(m_target->getLevel() > m_modifier.m_amount)
+ return;
+
+ m_target->SetCharmedOrPossessedBy(caster, true);
+ }
+ else
+ m_target->RemoveCharmedOrPossessedBy(caster);
+}
+
+void Aura::HandleModPossessPet(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ Unit* caster = GetCaster();
+ if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+ if(caster->GetPet() != m_target)
+ return;
+
+ if(apply)
+ m_target->SetCharmedOrPossessedBy(caster, true);
+ else
+ {
+ m_target->RemoveCharmedOrPossessedBy(caster);
+
+ // Reinitialize the pet bar and make the pet come back to the owner
+ ((Player*)caster)->PetSpellInitialize();
+ if(!m_target->getVictim())
+ {
+ m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
+ }
+ }
+}
+
+void Aura::HandleModCharm(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ Unit* caster = GetCaster();
+
+ if(apply)
+ {
+ if(int32(m_target->getLevel()) > m_modifier.m_amount)
+ return;
+
+ m_target->SetCharmedOrPossessedBy(caster, false);
+ }
+ else
+ m_target->RemoveCharmedOrPossessedBy(caster);
+}
+
+void Aura::HandlePhase(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ // always non stackable
+ if(apply)
+ {
+ Unit::AuraList const& phases = m_target->GetAurasByType(SPELL_AURA_PHASE);
+ if(!phases.empty())
+ m_target->RemoveAurasDueToSpell(phases.front()->GetId(),this);
+ }
+
+ // no-phase is also phase state so same code for apply and remove
+
+ // phase auras normally not expected at BG but anyway better check
+ if(m_target->GetTypeId()==TYPEID_PLAYER)
+ {
+ // drop flag at invisible in bg
+ if(((Player*)m_target)->InBattleGround())
+ if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
+ bg->EventPlayerDroppedFlag((Player*)m_target);
+
+ // GM-mode have mask 0xFFFFFFFF
+ if(!((Player*)m_target)->isGameMaster())
+ m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false);
+ }
+ else
+ m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false);
+
+ // need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases)
+ if(m_target->GetVisibility()!=VISIBILITY_OFF)
+ m_target->SetVisibility(m_target->GetVisibility());
+}
diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h
index 1e9a8bd8c63..7a4130d97d7 100644
--- a/src/game/SpellAuras.h
+++ b/src/game/SpellAuras.h
@@ -22,15 +22,6 @@
#include "SpellAuraDefines.h"
-struct DamageManaShield
-{
- uint32 m_spellId;
- uint32 m_modType;
- int32 m_schoolType;
- uint32 m_totalAbsorb;
- uint32 m_currAbsorb;
-};
-
struct Modifier
{
AuraType m_auraname;
@@ -100,6 +91,7 @@ class TRINITY_DLL_SPEC Aura
void HandleAuraFeatherFall(bool Apply, bool Real);
void HandleAuraHover(bool Apply, bool Real);
void HandleAddModifier(bool Apply, bool Real);
+ void HandleAddTargetTrigger(bool Apply, bool Real);
void HandleAuraModStun(bool Apply, bool Real);
void HandleModDamageDone(bool Apply, bool Real);
void HandleAuraUntrackable(bool Apply, bool Real);
@@ -111,8 +103,10 @@ class TRINITY_DLL_SPEC Aura
void HandleAuraModRegenInterrupt(bool Apply, bool Real);
void HandleHaste(bool Apply, bool Real);
void HandlePeriodicTriggerSpell(bool Apply, bool Real);
+ void HandlePeriodicTriggerSpellWithValue(bool apply, bool Real);
void HandlePeriodicEnergize(bool Apply, bool Real);
void HandleAuraModResistanceExclusive(bool Apply, bool Real);
+ void HandleAuraModPetTalentsPoints(bool Apply, bool Real);
void HandleModStealth(bool Apply, bool Real);
void HandleInvisibility(bool Apply, bool Real);
void HandleInvisibilityDetect(bool Apply, bool Real);
@@ -147,6 +141,7 @@ class TRINITY_DLL_SPEC Aura
void HandleModSpellHitChance(bool Apply, bool Real);
void HandleAuraModScale(bool Apply, bool Real);
void HandlePeriodicManaLeech(bool Apply, bool Real);
+ void HandlePeriodicHealthFunnel(bool apply, bool Real);
void HandleModCastingSpeed(bool Apply, bool Real);
void HandleAuraMounted(bool Apply, bool Real);
void HandleWaterBreathing(bool Apply, bool Real);
@@ -184,10 +179,12 @@ class TRINITY_DLL_SPEC Aura
void HandleAuraGhost(bool Apply, bool Real);
void HandleAuraAllowFlight(bool Apply, bool Real);
void HandleModRating(bool apply, bool Real);
+ void HandleModRatingFromStat(bool apply, bool Real);
void HandleModTargetResistance(bool apply, bool Real);
void HandleAuraModAttackPowerPercent(bool apply, bool Real);
void HandleAuraModRangedAttackPowerPercent(bool apply, bool Real);
void HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real);
+ void HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real);
void HandleSpiritOfRedemption(bool apply, bool Real);
void HandleModManaRegen(bool apply, bool Real);
void HandleComprehendLanguage(bool apply, bool Real);
@@ -197,6 +194,7 @@ class TRINITY_DLL_SPEC Aura
void HandleModSpellDamagePercentFromStat(bool apply, bool Real);
void HandleModSpellHealingPercentFromStat(bool apply, bool Real);
void HandleAuraModDispelResist(bool apply, bool Real);
+ void HandleAuraControlVehicle(bool apply, bool Real);
void HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real);
void HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real);
void HandleAuraModPacifyAndSilence(bool Apply, bool Real);
@@ -209,14 +207,16 @@ class TRINITY_DLL_SPEC Aura
void HandlePreventFleeing(bool apply, bool Real);
void HandleManaShield(bool apply, bool Real);
void HandleArenaPreparation(bool apply, bool Real);
+ void HandleAuraConvertRune(bool apply, bool Real);
+ void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real);
+ void HandleNoReagentUseAura(bool Apply, bool Real);
void HandleModAttackerSpellHitChance(bool apply, bool Real);
+ void HandlePhase(bool Apply, bool Real);
virtual ~Aura();
void SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue);
Modifier* GetModifier() {return &m_modifier;}
- int32 GetModifierValuePerStack() {return m_modifier.m_amount;}
- int32 GetModifierValue() {return m_modifier.m_amount * m_stackAmount;}
int32 GetMiscValue() {return m_spellProto->EffectMiscValue[m_effIndex];}
int32 GetMiscBValue() {return m_spellProto->EffectMiscValueB[m_effIndex];}
@@ -231,9 +231,8 @@ class TRINITY_DLL_SPEC Aura
int32 GetAuraDuration() const { return m_duration; }
void SetAuraDuration(int32 duration) { m_duration = duration; }
time_t GetAuraApplyTime() { return m_applyTime; }
- void UpdateAuraDuration();
- void SendAuraDurationForCaster(Player* caster);
- void UpdateSlotCounterAndDuration();
+
+ SpellModifier *getAuraSpellMod() {return m_spellmod; }
uint64 const& GetCasterGUID() const { return m_caster_guid; }
Unit* GetCaster() const;
@@ -250,14 +249,35 @@ class TRINITY_DLL_SPEC Aura
uint8 GetAuraSlot() const { return m_auraSlot; }
void SetAuraSlot(uint8 slot) { m_auraSlot = slot; }
- void UpdateAuraCharges()
+ uint8 GetAuraFlags() const { return m_auraFlags; }
+ void SetAuraFlags(uint8 flags) { m_auraFlags = flags; }
+ uint8 GetAuraLevel() const { return m_auraLevel; }
+ void SetAuraLevel(uint8 level) { m_auraLevel = level; }
+ uint8 GetAuraCharges() const { return m_procCharges; }
+ void SetAuraCharges(uint8 charges)
{
- uint8 slot = GetAuraSlot();
-
- // only aura in slot with charges and without stack limitation
- if (slot < MAX_AURAS && m_procCharges >= 1 && GetSpellProto()->StackAmount==0)
- SetAuraApplication(slot, m_procCharges - 1);
+ if (m_procCharges == charges)
+ return;
+ m_procCharges = charges;
+ SendAuraUpdate(false);
}
+ bool DropAuraCharge() // return true if last charge dropped
+ {
+ if (m_procCharges == 0)
+ return false;
+ m_procCharges--;
+ SendAuraUpdate(false);
+ return m_procCharges == 0;
+ }
+
+ void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); }
+ void SendAuraUpdate(bool remove);
+
+ int8 GetStackAmount() {return m_stackAmount;}
+ //int32 GetModifierValuePerStack() {return m_modifier.m_amount / m_stackAmount;}
+ void SetStackAmount(uint8 num);
+ bool modStackAmount(int32 num); // return true if last charge dropped
+ void RefreshAura();
bool IsPositive() { return m_positive; }
void SetNegative() { m_positive = false; }
@@ -266,7 +286,6 @@ class TRINITY_DLL_SPEC Aura
bool IsPermanent() const { return m_permanent; }
bool IsAreaAura() const { return m_isAreaAura; }
bool IsPeriodic() const { return m_isPeriodic; }
- bool IsTrigger() const { return m_isTrigger; }
bool IsPassive() const { return m_isPassive; }
bool IsPersistent() const { return m_isPersistent; }
bool IsDeathPersistent() const { return m_isDeathPersist; }
@@ -279,15 +298,10 @@ class TRINITY_DLL_SPEC Aura
void _AddAura();
void _RemoveAura();
- void TriggerSpell();
-
bool IsUpdated() { return m_updated; }
void SetUpdated(bool val) { m_updated = val; }
void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; }
- int32 m_procCharges;
- void SetAuraProcCharges(int32 charges) { m_procCharges = charges; }
-
Unit* GetTriggerTarget() const;
// add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras
@@ -297,54 +311,53 @@ class TRINITY_DLL_SPEC Aura
void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; }
DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; }
+ void TriggerSpell();
+ void TriggerSpellWithValue();
void PeriodicTick();
void PeriodicDummyTick();
- int32 GetStackAmount() {return m_stackAmount;}
- void SetStackAmount(int32 amount) {m_stackAmount=amount;}
+ bool isAffectedOnSpell(SpellEntry const *spell) const;
protected:
Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
Modifier m_modifier;
SpellModifier *m_spellmod;
- uint32 m_effIndex;
+
SpellEntry const *m_spellProto;
- int32 m_currentBasePoints; // cache SpellEntry::EffectBasePoints and use for set custom base points
- uint64 m_caster_guid;
Unit* m_target;
- int32 m_maxduration;
- int32 m_duration;
- int32 m_timeCla;
+ uint64 m_caster_guid;
uint64 m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted
time_t m_applyTime;
- AuraRemoveMode m_removeMode;
+ int32 m_currentBasePoints; // cache SpellEntry::EffectBasePoints and use for set custom base points
+ int32 m_maxduration; // Max aura duration
+ int32 m_duration; // Current time
+ int32 m_timeCla; // Timer for power per sec calcultion
+ int32 m_periodicTimer; // Timer for periodic auras
- uint8 m_auraSlot;
+ AuraRemoveMode m_removeMode:8; // Store info for know remove aura reason
+ DiminishingGroup m_AuraDRGroup:8; // Diminishing
+
+ uint8 m_effIndex; // Aura effect index in spell
+ uint8 m_auraSlot; // Aura slot on unit (for show in client)
+ uint8 m_auraFlags; // Aura info flag (for send data to client)
+ uint8 m_auraLevel; // Aura level (store caster level for correct show level dep amount)
+ uint8 m_procCharges; // Aura charges (0 for infinite)
+ uint8 m_stackAmount; // Aura stack amount
bool m_positive:1;
bool m_permanent:1;
bool m_isPeriodic:1;
- bool m_isTrigger:1;
bool m_isAreaAura:1;
bool m_isPassive:1;
bool m_isPersistent:1;
bool m_isDeathPersist:1;
bool m_isRemovedOnShapeLost:1;
- bool m_updated:1;
+ bool m_updated:1; // Prevent remove aura by stack if set
bool m_in_use:1; // true while in Aura::ApplyModifier call
- int32 m_periodicTimer;
- uint32 m_PeriodicEventId;
- DiminishingGroup m_AuraDRGroup;
-
- int32 m_stackAmount;
private:
void CleanupTriggeredSpells();
- void SetAura(uint32 slot, bool remove) { m_target->SetUInt32Value(UNIT_FIELD_AURA + slot, remove ? 0 : GetId()); }
- void SetAuraFlag(uint32 slot, bool add);
- void SetAuraLevel(uint32 slot, uint32 level);
- void SetAuraApplication(uint32 slot, int8 count);
};
class TRINITY_DLL_SPEC AreaAura : public Aura
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 438b9cd2290..2ef4a3827c4 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -60,6 +60,7 @@
#include "CellImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
+#include "SkillDiscovery.h"
pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
{
@@ -104,8 +105,8 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
&Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
&Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
- &Spell::EffectSummonWild, // 41 SPELL_EFFECT_SUMMON_WILD
- &Spell::EffectSummonGuardian, // 42 SPELL_EFFECT_SUMMON_GUARDIAN
+ &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP
+ &Spell::EffectUnused, // 42 SPELL_EFFECT_JUMP2
&Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
&Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
&Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
@@ -128,16 +129,16 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
&Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
&Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
- &Spell::EffectUnused, // 65 SPELL_EFFECT_HEALTH_FUNNEL unused
- &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused
+ &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
+ &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
&Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
&Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
&Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
&Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
&Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
&Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
- &Spell::EffectSummonPossessed, // 73 SPELL_EFFECT_SUMMON_POSSESSED
- &Spell::EffectSummonTotem, // 74 SPELL_EFFECT_SUMMON_TOTEM
+ &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
+ &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
&Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
&Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
&Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
@@ -150,17 +151,17 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
&Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
&Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
- &Spell::EffectSummonTotem, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1
- &Spell::EffectSummonTotem, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2
- &Spell::EffectSummonTotem, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3
- &Spell::EffectSummonTotem, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4
+ &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
+ &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
+ &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
+ &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT
&Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
&Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
&Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
&Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
&Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
&Spell::EffectUnused, // 96 SPELL_EFFECT_CHARGE
- &Spell::EffectSummonCritter, // 97 SPELL_EFFECT_SUMMON_CRITTER
+ &Spell::EffectUnused, // 97 SPELL_EFFECT_97
&Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
&Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
&Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
@@ -175,7 +176,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
&Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
&Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
- &Spell::EffectSummonDemon, //112 SPELL_EFFECT_SUMMON_DEMON
+ &Spell::EffectUnused, //112 SPELL_EFFECT_112
&Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
&Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
&Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
@@ -195,21 +196,21 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
&Spell::EffectRedirectThreat, //130 SPELL_EFFECT_REDIRECT_THREAT
&Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
- &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value
+ &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
&Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
&Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
&Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
&Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
&Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
&Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
- &Spell::EffectUnused, //139 SPELL_EFFECT_139 unused
+ &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
&Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
&Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
&Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
&Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
&Spell::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
@@ -217,6 +218,12 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
&Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
&Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
+ &Spell::EffectNULL, //154 unused
+ &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
+ &Spell::EffectNULL, //156 Add Socket
+ &Spell::EffectCreateItem, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
+ &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
+ &Spell::EffectRenamePet //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
};
void Spell::EffectNULL(uint32 /*i*/)
@@ -339,6 +346,13 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
damage = 200;
break;
}
+ // Intercept (warrior spell trigger)
+ case 20253:
+ case 61491:
+ {
+ damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
+ break;
+ }
// arcane charge. must only affect demons (also undead?)
case 45072:
{
@@ -366,7 +380,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
case SPELLFAMILY_MAGE:
{
// Arcane Blast
- if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
+ if(m_spellInfo->SpellFamilyFlags[0] & 0x20000000)
{
m_caster->CastSpell(m_caster,36032,true);
}
@@ -375,29 +389,43 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
case SPELLFAMILY_WARRIOR:
{
// Bloodthirst
- if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
+ if(m_spellInfo->SpellFamilyFlags[1] & 0x400)
{
damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
}
// Shield Slam
- else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
+ else if(m_spellInfo->SpellFamilyFlags[1] & 0x1)
damage += int32(m_caster->GetShieldBlockValue());
// Victory Rush
- else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
+ else if(m_spellInfo->SpellFamilyFlags[1] & 0x100)
{
damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
}
+ // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
+ else if(m_spellInfo->SpellFamilyFlags[0] & 0x400)
+ damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
+ // Heroic Throw ${$m1+$AP*.50}
+ else if(m_spellInfo->SpellFamilyFlags[1] & 0x00000001)
+ damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
+ // Shockwave ${$m3/100*$AP}
+ else if(m_spellInfo->SpellFamilyFlags[1] & 0x00008000)
+ {
+ int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
+ if (pct > 0)
+ damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
+ break;
+ }
break;
}
case SPELLFAMILY_WARLOCK:
{
// Incinerate Rank 1 & 2
- if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
+ if((m_spellInfo->SpellFamilyFlags[1] & 0x000040) && m_spellInfo->SpellIconID==2128)
{
// Incinerate does more dmg (dmg*0.25) if the target is Immolated.
if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
- damage += int32(damage*0.25);
+ damage += int32(damage*0.25f);
}
// Conflagrate - consumes immolate
@@ -407,75 +435,52 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
{
- if( (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && ((*i)->GetSpellProto()->SpellFamilyFlags & 4) &&
+ if( (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && ((*i)->GetSpellProto()->SpellFamilyFlags[0] & 4) &&
(*i)->GetCasterGUID()==m_caster->GetGUID() )
{
- unitTarget->RemoveAurasDueToCasterSpell((*i)->GetId(), m_caster->GetGUID());
+ unitTarget->RemoveAurasByCasterSpell((*i)->GetId(), m_caster->GetGUID());
break;
}
}
}
break;
}
+ case SPELLFAMILY_PRIEST:
+ {
+ // Shadow Word: Death - deals damage equal to damage done to caster
+ if (m_spellInfo->SpellFamilyFlags[1] & 0x2)
+ m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
+ break;
+ }
case SPELLFAMILY_DRUID:
{
// Ferocious Bite
- if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual==6587)
+ if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags[0] & 0x000800000) && m_spellInfo->SpellVisual[0]==6587)
{
- // converts each extra point of energy into ($f1+$AP/630) additional damage
- float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx];
+ // converts each extra point of energy into ($f1+$AP/410) additional damage
+ float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
+ float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
+ damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
m_caster->SetPower(POWER_ENERGY,0);
}
// Rake
- else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
+ else if(m_spellInfo->SpellFamilyFlags[0] & 0x1000)
{
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
}
// Swipe
- else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
+ else if(m_spellInfo->SpellFamilyFlags[1] & 0x00100000)
{
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
}
- // Starfire
- else if ( m_spellInfo->SpellFamilyFlags & 0x0004LL )
- {
- Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
- {
- // Starfire Bonus (caster)
- switch((*i)->GetModifier()->m_miscvalue)
- {
- case 5481: // Nordrassil Regalia - bonus
- {
- Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
- for(Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr)
- {
- // Moonfire or Insect Swarm (target debuff from any casters)
- if ( (*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL )
- {
- int32 mod = (*i)->GetModifier()->m_amount;
- damage += damage*mod/100;
- break;
- }
- }
- break;
- }
- case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura
- {
- damage += (*i)->GetModifier()->m_amount;
- break;
- }
- }
- }
- }
//Mangle Bonus for the initial damage of Lacerate and Rake
- if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
- (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
+ if((m_spellInfo->SpellFamilyFlags.IsEqual(0x1000,0,0) && m_spellInfo->SpellIconID==494) ||
+ (m_spellInfo->SpellFamilyFlags.IsEqual(0,0x100,0) && m_spellInfo->SpellIconID==2246))
{
Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
- if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
+ if((*i)->GetSpellProto()->SpellFamilyFlags[1] & 0x00000440 && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
{
damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
break;
@@ -486,69 +491,88 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
case SPELLFAMILY_ROGUE:
{
// Envenom
- if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
+ if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags[1] & 0x8))
{
// consume from stack dozes not more that have combo-points
if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
{
- // count consumed deadly poison doses at target
- uint32 doses = 0;
-
- // remove consumed poison doses
+ Aura *poison = 0;
+ // Lookup for Deadly poison (only attacker applied)
Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
- for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;)
- {
- // Deadly poison (only attacker applied)
- if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) &&
- (*itr)->GetSpellProto()->SpellVisual==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() )
+ for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
+ if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
+ (*itr)->GetSpellProto()->SpellFamilyFlags[0] & 0x10000 &&
+ (*itr)->GetCasterGUID()==m_caster->GetGUID() )
{
- --combo;
- ++doses;
-
- unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex());
-
- itr = auras.begin();
+ poison = *itr;
+ break;
}
- else
- ++itr;
+ // count consumed deadly poison doses at target
+ if (poison)
+ {
+ uint32 spellId = poison->GetId();
+ uint32 doses = poison->GetStackAmount();
+ if (doses > combo)
+ doses = combo;
+ for (int i=0; i< doses; i++)
+ unitTarget->RemoveSingleSpellAurasFromStack(spellId);
+ damage *= doses;
+ damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
}
-
- damage *= doses;
- damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
-
// Eviscerate and Envenom Bonus Damage (item set effect)
if(m_caster->GetDummyAura(37169))
damage += ((Player*)m_caster)->GetComboPoints()*40;
}
}
// Eviscerate
- else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
+ else if((m_spellInfo->SpellFamilyFlags[0] & 0x00020000) && m_caster->GetTypeId()==TYPEID_PLAYER)
{
if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
{
- damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f);
+ float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
+ damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
// Eviscerate and Envenom Bonus Damage (item set effect)
if(m_caster->GetDummyAura(37169))
damage += combo*40;
}
}
+ // Gouge
+ else if(m_spellInfo->SpellFamilyFlags[0] & 0x8)
+ {
+ damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f);
+ }
+ // Instant Poison
+ else if(m_spellInfo->SpellFamilyFlags[0] & 0x2000)
+ {
+ damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
+ }
+ // Wound Poison
+ else if(m_spellInfo->SpellFamilyFlags[0] & 0x10000000)
+ {
+ damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
+ }
break;
}
case SPELLFAMILY_HUNTER:
{
// Mongoose Bite
- if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual==342)
+ if((m_spellInfo->SpellFamilyFlags[0] & 0x2) && m_spellInfo->SpellVisual[0]==342)
+ {
+ damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
+ }
+ // Counterattack
+ else if(m_spellInfo->SpellFamilyFlags[1] & 0x00080000)
{
- damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2);
+ damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
}
// Arcane Shot
- else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
+ else if((m_spellInfo->SpellFamilyFlags[0] & 0x00000800) && m_spellInfo->maxLevel > 0)
{
- damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15);
+ damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
}
// Steady Shot
- else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
+ else if(m_spellInfo->SpellFamilyFlags[1] & 0x1)
{
int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
@@ -570,28 +594,58 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
if(found)
damage += m_spellInfo->EffectBasePoints[1];
}
- //Explosive Trap Effect
- else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
+ // Explosive Trap Effect
+ else if(m_spellInfo->SpellFamilyFlags[0] & 0x00000004)
{
- damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1);
+ damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
}
break;
}
case SPELLFAMILY_PALADIN:
{
- //Judgement of Vengeance
- if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
+ // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
+ if((m_spellInfo->SpellFamilyFlags[1] & 0x8) && m_spellInfo->SpellIconID==2292)
{
+ float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
+ int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
+ m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
+ damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
+ // Get stack of Holy Vengeance on the target added by caster
uint32 stacks = 0;
Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
- ++stacks;
- if(!stacks)
- //No damage if the target isn't affected by this
- damage = -1;
- else
- damage *= stacks;
+ {
+ stacks = (*itr)->GetStackAmount();
+ break;
+ }
+ // + 10% for each application of Holy Vengeance on the target
+ if(stacks)
+ damage += damage * stacks * 10 /100;
+ }
+ // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
+ else if(m_spellInfo->SpellFamilyFlags[0] & 0x4000)
+ {
+ float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
+ int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
+ m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
+ damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
+ }
+ // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
+ else if(m_spellInfo->SpellFamilyFlags[1] & 0x00000080)
+ {
+ float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
+ int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
+ m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
+ damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
+ }
+ // Hammer of the Righteous
+ else if(m_spellInfo->SpellFamilyFlags[1]&0x00040000)
+ {
+ // Add main hand dps * effect[2] amount
+ float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
+ int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
+ damage += count * int32(averange * 1000) / m_caster->GetAttackTime(BASE_ATTACK);
}
break;
}
@@ -629,7 +683,7 @@ void Spell::EffectDummy(uint32 i)
if (!creatureTarget || !pGameObj) return;
- if (!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 181574, creatureTarget->GetMap(),
+ if (!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 181574, creatureTarget->GetMap(), creatureTarget->GetPhaseMask(),
creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1))
{
@@ -737,12 +791,6 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
return;
}
- case 12975: //Last Stand
- {
- int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
- m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
- return;
- }
case 13120: // net-o-matic
{
if(!unitTarget)
@@ -779,30 +827,6 @@ void Spell::EffectDummy(uint32 i)
}
return;
}
- case 14185: // Preparation Rogue
- {
- if(m_caster->GetTypeId()!=TYPEID_PLAYER)
- return;
-
- //immediately finishes the cooldown on certain Rogue abilities
- const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
- {
- uint32 classspell = itr->first;
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
-
- if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL))
- {
- ((Player*)m_caster)->RemoveSpellCooldown(classspell);
-
- WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
- data << uint32(classspell);
- data << uint64(m_caster->GetGUID());
- ((Player*)m_caster)->GetSession()->SendPacket(&data);
- }
- }
- return;
- }
case 15998: // Capture Worg Pup
case 29435: // Capture Female Kaliri Hatchling
{
@@ -867,19 +891,20 @@ void Spell::EffectDummy(uint32 i)
if(creatureTarget->isPet())
return;
+ GameObject* Crystal_Prison = m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, creatureTarget->GetRespawnTime()-time(NULL));
+ sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019\n");
+
creatureTarget->setDeathState(JUST_DIED);
creatureTarget->RemoveCorpse();
creatureTarget->SetHealth(0); // just for nice GM-mode view
- GameObject* Crystal_Prison = m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, creatureTarget->GetRespawnTime()-time(NULL));
- sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019\n");
WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
data << uint64(Crystal_Prison->GetGUID());
m_caster->SendMessageToSet(&data,true);
return;
}
- case 23074: // Arc. Dragonling
+ case 23074: // Arcanite Dragonling
if (!m_CastItem) return;
m_caster->CastSpell(m_caster,19804,true,m_CastItem);
return;
@@ -955,7 +980,7 @@ void Spell::EffectDummy(uint32 i)
{
Aura * dummy = m_caster->GetDummyAura(28734);
if (dummy)
- {
+ {
int32 bp = damage * dummy->GetStackAmount();
m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
m_caster->RemoveAurasDueToSpell(28734);
@@ -1197,6 +1222,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
@@ -1270,65 +1301,113 @@ void Spell::EffectDummy(uint32 i)
break;
case SPELLFAMILY_WARRIOR:
// Charge
- if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual == 867)
+ if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867)
{
int32 chargeBasePoints0 = damage;
m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
return;
}
// Execute
- if(m_spellInfo->SpellFamilyFlags & 0x20000000)
+ if(m_spellInfo->SpellFamilyFlags[0] & 0x20000000)
{
if(!unitTarget)
return;
+ uint32 rage = m_caster->GetPower(POWER_RAGE);
+ // Glyph of Execution bonus
+ if (Aura *aura = m_caster->GetDummyAura(58367))
+ rage+=aura->GetModifier()->m_amount;
+
spell_id = 20647;
- bp = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]);
+ int32 bp = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
+ m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
m_caster->SetPower(POWER_RAGE,0);
break;
}
- if(m_spellInfo->Id==21977) //Warrior's Wrath
+ // Slam
+ if(m_spellInfo->SpellFamilyFlags[0] & 0x200000)
{
if(!unitTarget)
return;
-
- m_caster->CastSpell(unitTarget,21887,true); // spell mod
+ m_damage+=m_caster->CalculateDamage(m_attackType, false);
+ m_damage+=damage;
return;
}
+ switch(m_spellInfo->Id)
+ {
+ // Warrior's Wrath
+ case 21977:
+ {
+ if(!unitTarget)
+ return;
+ m_caster->CastSpell(unitTarget,21887,true); // spell mod
+ return;
+ }
+ // Last Stand
+ case 12975:
+ {
+ int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
+ m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
+ return;
+ }
+ // Bloodthirst
+ case 23881:
+ {
+ m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
+ return;
+ }
+ }
break;
case SPELLFAMILY_WARLOCK:
- //Life Tap (only it have this with dummy effect)
- if (m_spellInfo->SpellFamilyFlags == 0x40000)
+ // Life Tap
+ if (m_spellInfo->SpellFamilyFlags[0] & 0x40000)
{
- float cost = damage;
-
- if(Player* modOwner = m_caster->GetSpellModOwner())
- modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost,this);
-
- int32 dmg = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(cost > 0 ? cost : 0), SPELL_DIRECT_DAMAGE);
-
- if(int32(m_caster->GetHealth()) > dmg)
+ // In 303 exist spirit depend
+ uint32 spirit = m_caster->GetStat(STAT_SPIRIT);
+ switch (m_spellInfo->Id)
+ {
+ case 1454: damage+=spirit; break;
+ case 1455: damage+=spirit*15/10; break;
+ case 1456: damage+=spirit*2; break;
+ case 11687: damage+=spirit*25/10; break;
+ case 11688:
+ case 11689:
+ case 27222:
+ case 57946: damage+=spirit*3; break;
+ default:
+ sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
+ return;
+ }
+// Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
+// damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
+ if(int32(unitTarget->GetHealth()) > damage)
{
// Shouldn't Appear in Combat Log
- m_caster->ModifyHealth(-dmg);
-
- int32 mana = dmg;
+ unitTarget->ModifyHealth(-damage);
+ int32 mana = damage;
+ // Improved Life Tap mod
Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
{
- // only Imp. Life Tap have this in combination with dummy aura
if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
}
-
- m_caster->CastCustomSpell(m_caster,31818,&mana,NULL,NULL,true,NULL);
+ m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
// Mana Feed
- int32 manaFeedVal = m_caster->CalculateSpellDamage(m_spellInfo,1, m_spellInfo->EffectBasePoints[1],m_caster);
- manaFeedVal = manaFeedVal * mana / 100;
+ int32 manaFeedVal = 0;
+ Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
+ for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
+ {
+ if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
+ manaFeedVal+= (*itr)->GetModifier()->m_amount;
+ }
if(manaFeedVal > 0)
- m_caster->CastCustomSpell(m_caster,32553,&manaFeedVal,NULL,NULL,true,NULL);
+ {
+ manaFeedVal = manaFeedVal * mana / 100;
+ m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
+ }
}
else
SendCastResult(SPELL_FAILED_FIZZLE);
@@ -1336,6 +1415,30 @@ void Spell::EffectDummy(uint32 i)
}
break;
case SPELLFAMILY_PRIEST:
+ // Penance
+ if (m_spellInfo->SpellFamilyFlags[1] & 0x00800000)
+ {
+ if (!unitTarget)
+ return;
+
+ int hurt = 0;
+ int heal = 0;
+ switch(m_spellInfo->Id)
+ {
+ case 47540: hurt = 47758; heal = 47757; break;
+ case 53005: hurt = 53001; heal = 52986; break;
+ case 53006: hurt = 53002; heal = 52987; break;
+ case 53007: hurt = 53003; heal = 52988; break;
+ default:
+ sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
+ return;
+ }
+ if (m_caster->IsFriendlyTo(unitTarget))
+ m_caster->CastSpell(unitTarget, heal, true, 0);
+ else
+ m_caster->CastSpell(unitTarget, hurt, true, 0);
+ return;
+ }
switch(m_spellInfo->Id )
{
case 28598: // Touch of Weakness triggered spell
@@ -1363,25 +1466,10 @@ void Spell::EffectDummy(uint32 i)
}
break;
case SPELLFAMILY_DRUID:
- switch(m_spellInfo->Id )
- {
- case 5420: // Tree of Life passive
- {
- // Tree of Life area effect
- int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT)/4);
- m_caster->CastCustomSpell(m_caster,34123,&health_mod,NULL,NULL,true,NULL);
- return;
- }
- }
break;
case SPELLFAMILY_ROGUE:
switch(m_spellInfo->Id )
{
- case 31231: // Cheat Death
- {
- m_caster->CastSpell(m_caster,45182,true);
- return;
- }
case 5938: // Shiv
{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
@@ -1417,36 +1505,38 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(unitTarget, 5940, true);
return;
}
- }
- break;
- case SPELLFAMILY_HUNTER:
- // Kill command
- if(m_spellInfo->SpellFamilyFlags & 0x00080000000000LL)
- {
- if(m_caster->getClass()!=CLASS_HUNTER)
- return;
+ case 14185: // Preparation Rogue
+ {
+ if(m_caster->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ //immediately finishes the cooldown on certain Rogue abilities
+ const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
+ for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
+ {
+ uint32 classspell = itr->first;
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
- // clear hunter crit aura state
- m_caster->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE,false);
+ if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags[1] & 0x00000240 || spellInfo->SpellFamilyFlags[0] & 0x00000860))
+ {
+ ((Player*)m_caster)->RemoveSpellCooldown(classspell);
- // additional damage from pet to pet target
- Pet* pet = m_caster->GetPet();
- if(!pet || !pet->getVictim())
+ WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
+ data << uint32(classspell);
+ data << uint64(m_caster->GetGUID());
+ ((Player*)m_caster)->GetSession()->SendPacket(&data);
+ }
+ }
return;
-
- uint32 spell_id = 0;
- switch (m_spellInfo->Id)
+ }
+ case 31231: // Cheat Death
{
- case 34026: spell_id = 34027; break; // rank 1
- default:
- sLog.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo->Id);
+ m_caster->CastSpell(m_caster,45182,true);
return;
}
-
- pet->CastSpell(pet->getVictim(), spell_id, true);
- return;
}
-
+ break;
+ case SPELLFAMILY_HUNTER:
switch(m_spellInfo->Id)
{
case 23989: //Readiness talent
@@ -1504,6 +1594,8 @@ void Spell::EffectDummy(uint32 i)
case 20930: hurt = 25902; heal = 25903; break;
case 27174: hurt = 27176; heal = 27175; break;
case 33072: hurt = 33073; heal = 33074; break;
+ case 48824: hurt = 48822; heal = 48820; break;
+ case 48825: hurt = 48823; heal = 48821; break;
default:
sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
return;
@@ -1534,10 +1626,7 @@ void Spell::EffectDummy(uint32 i)
mod->value = -50;
mod->type = SPELLMOD_PCT;
mod->spellId = m_spellInfo->Id;
- mod->effectId = i;
- mod->lastAffected = NULL;
- mod->mask = 0x0000020000000000LL;
- mod->charges = 0;
+ mod->mask[1] = 0x00000200;
((Player*)m_caster)->AddSpellMod(mod, true);
m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
@@ -1553,6 +1642,14 @@ void Spell::EffectDummy(uint32 i)
switch(m_spellInfo->Id)
{
+ // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
+ case 20187:
+ {
+ if (!unitTarget)
+ return;
+ m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
+ return;
+ }
case 31789: // Righteous Defense (step 1)
{
// 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
@@ -1619,8 +1716,10 @@ void Spell::EffectDummy(uint32 i)
break;
case SPELLFAMILY_SHAMAN:
//Shaman Rockbiter Weapon
- if (m_spellInfo->SpellFamilyFlags == 0x400000)
+ if (m_spellInfo->SpellFamilyFlags.IsEqual(0x400000))
{
+ // TODO: use expect spell for enchant (if exist talent)
+ // In 3.0.3 no mods present for rockbiter
uint32 spell_id = 0;
switch(m_spellInfo->Id)
{
@@ -1628,11 +1727,6 @@ void Spell::EffectDummy(uint32 i)
case 8018: spell_id = 36750; break; // Rank 2
case 8019: spell_id = 36755; break; // Rank 3
case 10399: spell_id = 36759; break; // Rank 4
- case 16314: spell_id = 36763; break; // Rank 5
- case 16315: spell_id = 36766; break; // Rank 6
- case 16316: spell_id = 36771; break; // Rank 7
- case 25479: spell_id = 36775; break; // Rank 8
- case 25485: spell_id = 36499; break; // Rank 9
default:
sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
return;
@@ -1670,18 +1764,57 @@ void Spell::EffectDummy(uint32 i)
}
return;
}
-
- if(m_spellInfo->Id == 39610) // Mana-Tide Totem effect
+ // Healing Stream Totem
+ if(m_spellInfo->SpellFamilyFlags[0] & 0x2000)
+ {
+ m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
+ return;
+ }
+ // Mana Spring Totem
+ if(m_spellInfo->SpellFamilyFlags[0] & 0x4000)
+ {
+ if(unitTarget->getPowerType()!=POWER_MANA)
+ return;
+ m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
+ return;
+ }
+ if(m_spellInfo->Id == 39610) // Mana Tide Totem effect
{
if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
return;
-
+ // Glyph of Mana Tide
+ Unit *owner = m_caster->GetOwner();
+ if (owner)
+ if (Aura *dummy = owner->GetDummyAura(55441))
+ damage+=dummy->GetModifier()->m_amount;
// Regenerate 6% of Total Mana Every 3 secs
int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
return;
}
-
+ // Lava Lash
+ if (m_spellInfo->SpellFamilyFlags[2] & 0x00000004)
+ {
+ if (m_caster->GetTypeId()!=TYPEID_PLAYER)
+ return;
+ Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
+ if (item)
+ {
+ // Damage is increased if your off-hand weapon is enchanted with Flametongue.
+ Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
+ {
+ if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
+ (*itr)->GetSpellProto()->SpellFamilyFlags[0] & 0x200000 &&
+ (*itr)->GetCastItemGUID() == item->GetGUID())
+ {
+ m_damage += m_damage * damage / 100;
+ return;
+ }
+ }
+ }
+ return;
+ }
break;
}
@@ -1695,7 +1828,7 @@ void Spell::EffectDummy(uint32 i)
sLog.outError("EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id);
return;
}
-
+
Spell* spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID, NULL, true);
if(bp) spell->m_currentBasePoints[0] = bp;
SpellCastTargets targets;
@@ -1801,7 +1934,7 @@ void Spell::EffectTriggerSpell(uint32 i)
if (!spellInfo)
continue;
- if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
+ if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_STEALTH)
{
spellId = spellInfo->Id;
break;
@@ -1958,12 +2091,7 @@ void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
if (m_CastItem)
DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
- Spell *spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID );
-
- SpellCastTargets targets;
- targets.setDestination(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ);
- spell->m_CastItem = m_CastItem;
- spell->prepare(&targets, NULL);
+ m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo->Id, true, m_CastItem, 0, m_originalCasterGUID);
}
void Spell::EffectTeleportUnits(uint32 i)
@@ -2098,17 +2226,12 @@ void Spell::EffectApplyAura(uint32 i)
if(!unitTarget)
return;
- SpellImmuneList const& list = unitTarget->m_spellImmune[IMMUNITY_STATE];
- for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
- if(itr->type == m_spellInfo->EffectApplyAuraName[i])
- return;
-
// ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
(unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
return;
- Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster;
+ Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
if(!caster)
return;
@@ -2145,33 +2268,8 @@ void Spell::EffectApplyAura(uint32 i)
if(!Aur)
return;
- // TODO Make a way so it works for every related spell!
- if(unitTarget->GetTypeId()==TYPEID_PLAYER) // Negative buff should only be applied on players
- {
- uint32 spellId = 0;
- if(m_spellInfo->CasterAuraStateNot==AURA_STATE_WEAKENED_SOUL || m_spellInfo->TargetAuraStateNot==AURA_STATE_WEAKENED_SOUL)
- spellId = 6788; // Weakened Soul
- else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_FORBEARANCE || m_spellInfo->TargetAuraStateNot==AURA_STATE_FORBEARANCE)
- spellId = 25771; // Forbearance
- else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_HYPOTHERMIA)
- spellId = 41425; // Hypothermia
- else if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
- spellId = 11196; // Recently Bandaged
- else if( (m_spellInfo->AttributesEx & 0x20) && (m_spellInfo->AttributesEx2 & 0x20000) )
- spellId = 23230; // Blood Fury - Healing Reduction
-
- SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId);
- if (AdditionalSpellInfo)
- {
- // applied at target by target
- Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, NULL, unitTarget,unitTarget, 0);
- unitTarget->AddAura(AdditionalAura);
- sLog.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo->EffectApplyAuraName[0]);
- }
- }
-
// Prayer of Mending (jump animation), we need formal caster instead original for correct animation
- if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
+ if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags[1] & 0x000020))
m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
}
@@ -2222,7 +2320,8 @@ void Spell::EffectPowerDrain(uint32 i)
unitTarget->ModifyPower(drain_power,-new_damage);
- if(drain_power == POWER_MANA)
+ // Don`t restore from self drain
+ if(drain_power == POWER_MANA && m_caster != unitTarget)
{
float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
if(manaMultiplier==0)
@@ -2363,7 +2462,7 @@ void Spell::SpellDamageHeal(uint32 /*i*/)
Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
if((*i)->GetId() == 45062)
- damageAmount+=(*i)->GetModifierValue();
+ damageAmount+=(*i)->GetModifier()->m_amount;
if (damageAmount)
m_caster->RemoveAurasDueToSpell(45062);
@@ -2378,7 +2477,7 @@ void Spell::SpellDamageHeal(uint32 /*i*/)
for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
{
if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
- && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
+ && ((*i)->GetSpellProto()->SpellFamilyFlags.IsEqual(0x40) || (*i)->GetSpellProto()->SpellFamilyFlags.IsEqual(0x10)) )
{
if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
targetAura = *i;
@@ -2398,21 +2497,21 @@ void Spell::SpellDamageHeal(uint32 /*i*/)
idx++;
}
- int32 tickheal = targetAura->GetModifierValuePerStack();
+ int32 tickheal = targetAura->GetModifier()->m_amount;
if(Unit* auraCaster = targetAura->GetCaster())
- tickheal = auraCaster->SpellHealingBonus(targetAura->GetSpellProto(), tickheal, DOT, unitTarget);
+ tickheal = auraCaster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), tickheal, DOT);
//int32 tickheal = targetAura->GetSpellProto()->EffectBasePoints[idx] + 1;
//It is said that talent bonus should not be included
- //int32 tickheal = targetAura->GetModifierValue();
+
int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
addhealth += tickheal * tickcount;
- unitTarget->RemoveAurasDueToCasterSpell(targetAura->GetId(), targetAura->GetCasterGUID());
+ unitTarget->RemoveAurasByCasterSpell(targetAura->GetId(), targetAura->GetCasterGUID());
//addhealth += tickheal * tickcount;
//addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget);
}
else
- addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget);
+ addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
m_damage -= addhealth;
}
@@ -2453,7 +2552,7 @@ void Spell::EffectHealMechanical( uint32 /*i*/ )
if (!caster)
return;
- uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget);
+ uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL);
caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
unitTarget->ModifyHealth( int32(damage) );
}
@@ -2484,7 +2583,7 @@ void Spell::EffectHealthLeech(uint32 i)
if(m_caster->isAlive())
{
- new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster);
+ new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL);
m_caster->ModifyHealth(new_damage);
@@ -2537,8 +2636,8 @@ void Spell::DoCreateItem(uint32 i, uint32 itemtype)
if (num_to_add < 1)
num_to_add = 1;
- if (num_to_add > pProto->Stackable)
- num_to_add = pProto->Stackable;
+ if (num_to_add > pProto->GetMaxStackSize())
+ num_to_add = pProto->GetMaxStackSize();
// init items_count to 1, since 1 item will be created regardless of specialization
int items_count=1;
@@ -2660,6 +2759,8 @@ void Spell::EffectEnergize(uint32 i)
if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
return;
+ Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
+
// Some level depends spells
int multiplier = 0;
int level_diff = 0;
@@ -2690,8 +2791,6 @@ void Spell::EffectEnergize(uint32 i)
if(damage < 0)
return;
- Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
-
if(unitTarget->GetMaxPower(power) == 0)
return;
@@ -2759,7 +2858,7 @@ void Spell::EffectEnergisePct(uint32 i)
uint32 gain = damage * maxPower / 100;
unitTarget->ModifyPower(power, gain);
- m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
+ m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power);
}
void Spell::SendLoot(uint64 guid, LootType loottype)
@@ -2922,10 +3021,10 @@ void Spell::EffectOpenLock(uint32 /*i*/)
}
// check key
- for(int i = 0; i < 5; ++i)
+ for(int i = 0; i < 8; ++i)
{
- // type==1 This means lockInfo->key[i] is an item
- if(lockInfo->keytype[i]==LOCK_KEY_ITEM && lockInfo->key[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[i])
+ // Type==1 This means lockInfo->Index[i] is an item
+ if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i])
{
SendLoot(guid, loottype);
return;
@@ -2943,9 +3042,9 @@ void Spell::EffectOpenLock(uint32 /*i*/)
// skill bonus provided by casting spell (mostly item spells)
uint32 spellSkillBonus = uint32(damage/*m_currentBasePoints[0]+1*/);
- uint32 reqSkillValue = lockInfo->requiredminingskill;
+ uint32 reqSkillValue = lockInfo->Skill[0];
- if(lockInfo->requiredlockskill) // required pick lock skill applying
+ if(lockInfo->Skill[1]) // required pick lock skill applying
{
if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?)
{
@@ -2953,7 +3052,7 @@ void Spell::EffectOpenLock(uint32 /*i*/)
return;
}
- reqSkillValue = lockInfo->requiredlockskill;
+ reqSkillValue = lockInfo->Skill[1];
}
else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target
{
@@ -3136,6 +3235,9 @@ void Spell::EffectSummonType(uint32 i)
case SUMMON_TYPE_POSESSED2:
case SUMMON_TYPE_POSESSED3:
EffectSummonPossessed(i);
+ case SUMMON_TYPE_FORCE_OF_NATURE:
+ case SUMMON_TYPE_GUARDIAN2:
+ EffectSummonGuardian(i);
break;
case SUMMON_TYPE_WILD:
EffectSummonWild(i);
@@ -3183,7 +3285,7 @@ void Spell::EffectSummon(uint32 i)
Pet* spawnCreature = new Pet(SUMMON_PET);
spawnCreature->setActive(m_caster->isActive());
- if(spawnCreature->LoadPetFromDB(m_caster,pet_entry))
+ if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
{
// set timer for unsummon
int32 duration = GetSpellDuration(m_spellInfo);
@@ -3195,7 +3297,8 @@ void Spell::EffectSummon(uint32 i)
Map *map = m_caster->GetMap();
uint32 pet_number = objmgr.GeneratePetNumber();
- if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_spellInfo->EffectMiscValue[i], pet_number))
+ if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_caster->GetPhaseMask(),
+ m_spellInfo->EffectMiscValue[i], pet_number))
{
sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
delete spawnCreature;
@@ -3280,8 +3383,8 @@ void Spell::EffectLearnSpell(uint32 i)
Player *player = (Player*)unitTarget;
- uint32 spellToLearn = (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) ? damage : m_spellInfo->EffectTriggerSpell[i];
- player->learnSpell(spellToLearn);
+ uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
+ player->learnSpell(spellToLearn,false);
sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
}
@@ -3377,12 +3480,7 @@ void Spell::EffectDispel(uint32 i)
SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
data << uint32(spellInfo->Id); // Spell Id
data << uint8(0); // 0 - dispelled !=0 cleansed
- if(spellInfo->StackAmount!= 0)
- {
- //Why are Aura's Removed by EffIndex? Auras should be removed as a whole.....
- unitTarget->RemoveSingleAuraFromStackByDispel(spellInfo->Id);
- }
- else
+ //Why are Aura's Removed by EffIndex? Auras should be removed as a whole.....
unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
}
m_caster->SendMessageToSet(&data, true);
@@ -3650,7 +3748,8 @@ void Spell::EffectSummonGuardian(uint32 i)
Map *map = m_caster->GetMap();
uint32 pet_number = objmgr.GeneratePetNumber();
- if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_spellInfo->EffectMiscValue[i], pet_number))
+ if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
+ m_spellInfo->EffectMiscValue[i], pet_number))
{
sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
delete spawnCreature;
@@ -3800,35 +3899,34 @@ void Spell::EffectEnchantItemPerm(uint32 i)
p_caster->UpdateCraftSkill(m_spellInfo->Id);
- if (m_spellInfo->EffectMiscValue[i])
- {
- uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
+ uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
+ if (!enchant_id)
+ return;
- SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
- if(!pEnchant)
- return;
+ SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
+ if(!pEnchant)
+ return;
- // item can be in trade slot and have owner diff. from caster
- Player* item_owner = itemTarget->GetOwner();
- if(!item_owner)
- return;
+ // item can be in trade slot and have owner diff. from caster
+ Player* item_owner = itemTarget->GetOwner();
+ if(!item_owner)
+ return;
- if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
- {
- sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
- p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
- itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
- item_owner->GetName(),item_owner->GetSession()->GetAccountId());
- }
+ if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
+ {
+ sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
+ p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
+ itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
+ item_owner->GetName(),item_owner->GetSession()->GetAccountId());
+ }
- // remove old enchanting before applying new if equipped
- item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
+ // remove old enchanting before applying new if equipped
+ item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
- itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
+ itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
- // add new enchanting if equipped
- item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
- }
+ // add new enchanting if equipped
+ item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
}
void Spell::EffectEnchantItemTmp(uint32 i)
@@ -3923,13 +4021,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
@@ -3992,14 +4090,16 @@ void Spell::EffectTameCreature(uint32 /*i*/)
creatureTarget->RemoveCorpse();
creatureTarget->SetHealth(0); // just for nice GM-mode view
+ uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
+
// prepare visual effect for levelup
- pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1);
+ pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
// add to world
pet->GetMap()->Add((Creature*)pet);
// visual effect for levelup
- pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel());
+ pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
// caster have pet now
m_caster->SetPet(pet);
@@ -4058,7 +4158,7 @@ void Spell::EffectSummonPet(uint32 i)
NewSummon->setActive(m_caster->isActive());
// petentry==0 for hunter "call pet" (current pet summoned if any)
- if(NewSummon->LoadPetFromDB(m_caster,petentry))
+ if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry))
{
if(NewSummon->getPetType()==SUMMON_PET)
{
@@ -4097,7 +4197,8 @@ void Spell::EffectSummonPet(uint32 i)
Map *map = m_caster->GetMap();
uint32 pet_number = objmgr.GeneratePetNumber();
- if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number))
+ if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
+ petentry, pet_number))
{
delete NewSummon;
return;
@@ -4143,10 +4244,12 @@ void Spell::EffectSummonPet(uint32 i)
// this enables pet details window (Shift+P)
// this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
- NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
+ if(m_caster->GetTypeId() == TYPEID_PLAYER)
+ NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
NewSummon->InitStatsForLevel(petlevel);
NewSummon->InitPetCreateSpells();
+ NewSummon->InitTalentForLevel();
if(NewSummon->getPetType()==SUMMON_PET)
{
@@ -4204,7 +4307,6 @@ void Spell::EffectLearnPetSpell(uint32 i)
if(!learn_spellproto)
return;
- pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id));
pet->learnSpell(learn_spellproto->Id);
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
@@ -4268,20 +4370,18 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
case SPELLFAMILY_WARRIOR:
{
// Devastate bonus and sunder armor refresh
- if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508)
+ if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
{
uint32 stack = 0;
-
Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE);
for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr)
{
SpellEntry const *proto = (*itr)->GetSpellProto();
if(proto->SpellFamilyName == SPELLFAMILY_WARRIOR
- && proto->SpellFamilyFlags == SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR)
+ && proto->SpellFamilyFlags.IsEqual(SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR)
+ && (*itr)->GetCasterGUID() == m_caster->GetGUID())
{
- int32 duration = GetSpellDuration(proto);
- (*itr)->SetAuraDuration(duration);
- (*itr)->UpdateAuraDuration();
+ (*itr)->RefreshAura();
stack = (*itr)->GetStackAmount();
break;
}
@@ -4310,7 +4410,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
if (!spellInfo)
continue;
- if (spellInfo->SpellFamilyFlags == SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR
+ if (spellInfo->SpellFamilyFlags.IsEqual(SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR)
&& spellInfo->Id != m_spellInfo->Id
&& spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR)
{
@@ -4319,19 +4419,21 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
}
}
}
+ if (stack)
+ spell_bonus += stack * CalculateDamage(2, unitTarget);
}
break;
}
case SPELLFAMILY_ROGUE:
{
// Hemorrhage
- if(m_spellInfo->SpellFamilyFlags & 0x2000000)
+ if(m_spellInfo->SpellFamilyFlags[0] & 0x2000000)
{
if(m_caster->GetTypeId()==TYPEID_PLAYER)
((Player*)m_caster)->AddComboPoints(unitTarget, 1);
}
// Mutilate (for each hand)
- else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
+ else if(m_spellInfo->SpellFamilyFlags[1] & 0x6)
{
bool found = false;
// fast check
@@ -4359,7 +4461,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
case SPELLFAMILY_PALADIN:
{
// Seal of Command - receive benefit from Spell Damage and Healing
- if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
+ if(m_spellInfo->SpellFamilyFlags[0] & 0x2000000)
{
spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
@@ -4370,7 +4472,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
{
// Skyshatter Harness item set bonus
// Stormstrike
- if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
+ if(m_spellInfo->SpellFamilyFlags[1] & 0x0010)
{
Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
@@ -4388,7 +4490,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
case SPELLFAMILY_DRUID:
{
// Mangle (Cat): CP
- if(m_spellInfo->SpellFamilyFlags==0x0000040000000000LL)
+ if(m_spellInfo->SpellFamilyFlags.IsEqual(0,0x00000400))
{
if(m_caster->GetTypeId()==TYPEID_PLAYER)
((Player*)m_caster)->AddComboPoints(unitTarget,1);
@@ -4576,7 +4678,7 @@ void Spell::EffectSummonObjectWild(uint32 i)
Map *map = target->GetMap();
if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
- x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
+ m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
{
delete pGameObj;
return;
@@ -4624,7 +4726,7 @@ void Spell::EffectSummonObjectWild(uint32 i)
{
GameObject* linkedGO = new GameObject;
if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
- x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
+ m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
{
linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
linkedGO->SetSpellId(m_spellInfo->Id);
@@ -4645,408 +4747,556 @@ void Spell::EffectScriptEffect(uint32 effIndex)
{
// TODO: we must implement hunter pet summon at login there (spell 6962)
- // by spell id
- switch(m_spellInfo->Id)
+ switch(m_spellInfo->SpellFamilyName)
{
- // PX-238 Winter Wondervolt TRAP
- case 26275:
+ case SPELLFAMILY_GENERIC:
{
- if( unitTarget->HasAura(26272,0)
- || unitTarget->HasAura(26157,0)
- || unitTarget->HasAura(26273,0)
- || unitTarget->HasAura(26274,0))
- return;
+ switch(m_spellInfo->Id)
+ {
+ // PX-238 Winter Wondervolt TRAP
+ case 26275:
+ {
+ uint32 spells[4] = { 26272, 26157, 26273, 26274 };
- uint32 iTmpSpellId;
+ // check presence
+ for(int j = 0; j < 4; ++j)
+ if(unitTarget->HasAura(spells[j],0))
+ return;
- switch(urand(0,3))
- {
- case 0:
- iTmpSpellId = 26272;
- break;
- case 1:
- iTmpSpellId = 26157;
- break;
- case 2:
- iTmpSpellId = 26273;
- break;
- case 3:
- iTmpSpellId = 26274;
- break;
- }
+ // select spell
+ uint32 iTmpSpellId = spells[urand(0,3)];
+
+ // cast
+ unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
+ return;
+ }
+ // Bending Shinbone
+ case 8856:
+ {
+ if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
+ return;
- unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
+ uint32 spell_id = 0;
+ switch(urand(1,5))
+ {
+ case 1: spell_id = 8854; break;
+ default: spell_id = 8855; break;
+ }
- return;
- }
+ m_caster->CastSpell(m_caster,spell_id,true,NULL);
+ return;
+ }
+ // Brittle Armor - need remove one 24575 Brittle Armor aura
+ case 24590:
+ unitTarget->RemoveSingleSpellAurasFromStack(24575);
+ return;
+ // Mercurial Shield - need remove one 26464 Mercurial Shield aura
+ case 26465:
+ unitTarget->RemoveSingleSpellAurasFromStack(26464);
+ return;
+ // Orb teleport spells
+ case 25140:
+ case 25143:
+ case 25650:
+ case 25652:
+ case 29128:
+ case 29129:
+ case 35376:
+ case 35727:
+ {
+ if(!unitTarget)
+ return;
- // Bending Shinbone
- case 8856:
- {
- if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
- return;
+ uint32 spellid;
+ switch(m_spellInfo->Id)
+ {
+ case 25140: spellid = 32571; break;
+ case 25143: spellid = 32572; break;
+ case 25650: spellid = 30140; break;
+ case 25652: spellid = 30141; break;
+ case 29128: spellid = 32568; break;
+ case 29129: spellid = 32569; break;
+ case 35376: spellid = 25649; break;
+ case 35727: spellid = 35730; break;
+ default:
+ return;
+ }
- uint32 spell_id = 0;
- switch(urand(1,5))
- {
- case 1: spell_id = 8854; break;
- default: spell_id = 8855; break;
- }
+ unitTarget->CastSpell(unitTarget,spellid,false);
+ return;
+ }
+ // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
+ case 22539:
+ case 22972:
+ case 22975:
+ case 22976:
+ case 22977:
+ case 22978:
+ case 22979:
+ case 22980:
+ case 22981:
+ case 22982:
+ case 22983:
+ case 22984:
+ case 22985:
+ {
+ if(!unitTarget || !unitTarget->isAlive())
+ return;
- m_caster->CastSpell(m_caster,spell_id,true,NULL);
- return;
- }
+ // Onyxia Scale Cloak
+ if(unitTarget->GetDummyAura(22683))
+ return;
- // Healthstone creating spells
- case 6201:
- case 6202:
- case 5699:
- case 11729:
- case 11730:
- case 27230:
- {
- uint32 itemtype;
- uint32 rank = 0;
- Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
- for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
- {
- if((*i)->GetId() == 18692)
+ // Shadow Flame
+ m_caster->CastSpell(unitTarget, 22682, true);
+ return;
+ }
+ // Summon Black Qiraji Battle Tank
+ case 26656:
{
- rank = 1;
+ if(!unitTarget)
+ return;
+
+ // Prevent stacking of mounts
+ unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
+
+ // Two separate mounts depending on area id (allows use both in and out of specific instance)
+ if (unitTarget->GetAreaId() == 3428)
+ unitTarget->CastSpell(unitTarget, 25863, false);
+ else
+ unitTarget->CastSpell(unitTarget, 26655, false);
break;
}
- else if((*i)->GetId() == 18693)
+ // Piccolo of the Flaming Fire
+ case 17512:
{
- rank = 2;
+ if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
+ return;
+ unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
break;
}
- }
+ // Mirren's Drinking Hat
+ case 29830:
+ {
+ uint32 item = 0;
+ switch ( urand(1,6) )
+ {
+ case 1:case 2:case 3:
+ item = 23584;break; // Loch Modan Lager
+ case 4:case 5:
+ item = 23585;break; // Stouthammer Lite
+ case 6:
+ item = 23586;break; // Aerie Peak Pale Ale
+ }
+ if (item)
+ DoCreateItem(effIndex,item);
+ break;
+ }
+ // Improved Sprint
+ case 30918:
+ {
+ // Removes snares and roots.
+ uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
+ Unit::AuraMap& Auras = unitTarget->GetAuras();
+ for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
+ {
+ next = iter;
+ ++next;
+ Aura *aur = iter->second;
+ if (!aur->IsPositive()) //only remove negative spells
+ {
+ // check for mechanic mask
+ if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
+ {
+ unitTarget->RemoveAurasDueToSpell(aur->GetId());
+ if(Auras.empty())
+ break;
+ else
+ next = Auras.begin();
+ }
+ }
+ }
+ break;
+ }
+ /*// Flame Crash
+ case 41126:
+ {
+ if(!unitTarget)
+ return;
- static uint32 const itypes[6][3] = {
- { 5512,19004,19005}, // Minor Healthstone
- { 5511,19006,19007}, // Lesser Healthstone
- { 5509,19008,19009}, // Healthstone
- { 5510,19010,19011}, // Greater Healthstone
- { 9421,19012,19013}, // Major Healthstone
- {22103,22104,22105} // Master Healthstone
- };
+ unitTarget->CastSpell(unitTarget, 41131, true);
+ break;
+ }*/
+ // Draw Soul
+ case 40904:
+ {
+ if(!unitTarget)
+ return;
- switch(m_spellInfo->Id)
- {
- case 6201: itemtype=itypes[0][rank];break; // Minor Healthstone
- case 6202: itemtype=itypes[1][rank];break; // Lesser Healthstone
- case 5699: itemtype=itypes[2][rank];break; // Healthstone
- case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone
- case 11730: itemtype=itypes[4][rank];break; // Major Healthstone
- case 27230: itemtype=itypes[5][rank];break; // Master Healthstone
- default:
- return;
- }
- DoCreateItem( effIndex, itemtype );
- return;
- }
- // Brittle Armor - need remove one 24575 Brittle Armor aura
- case 24590:
- unitTarget->RemoveSingleAuraFromStack(24575, 0);
- unitTarget->RemoveSingleAuraFromStack(24575, 1);
- return;
- // Mercurial Shield - need remove one 26464 Mercurial Shield aura
- case 26465:
- unitTarget->RemoveSingleAuraFromStack(26464, 0);
- return;
- // Orb teleport spells
- case 25140:
- case 25143:
- case 25650:
- case 25652:
- case 29128:
- case 29129:
- case 35376:
- case 35727:
- {
- if(!unitTarget)
- return;
+ unitTarget->CastSpell(m_caster, 40903, true);
+ break;
+ }
+ case 41931:
+ {
+ if(m_caster->GetTypeId() != TYPEID_PLAYER)
+ return;
- uint32 spellid;
- switch(m_spellInfo->Id)
- {
- case 25140: spellid = 32571; break;
- case 25143: spellid = 32572; break;
- case 25650: spellid = 30140; break;
- case 25652: spellid = 30141; break;
- case 29128: spellid = 32568; break;
- case 29129: spellid = 32569; break;
- case 35376: spellid = 25649; break;
- case 35727: spellid = 35730; break;
- default:
- return;
- }
+ int bag=19;
+ int slot=0;
+ Item* item = NULL;
+
+ while (bag < 256)
+ {
+ item = ((Player*)m_caster)->GetItemByPos(bag,slot);
+ if (item && item->GetEntry() == 38587) break;
+ slot++;
+ if (slot == 39)
+ {
+ slot = 0;
+ bag++;
+ }
+ }
+ if (bag < 256)
+ {
+ if (((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount() == 1) ((Player*)m_caster)->RemoveItem(bag,slot,true);
+ else ((Player*)m_caster)->GetItemByPos(bag,slot)->SetCount(((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount()-1);
+ // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen)
+ m_caster->CastSpell(m_caster,42518,true);
+ return;
+ }
+ break;
+ }
+ // Force Cast - Portal Effect: Sunwell Isle
+ case 44876:
+ {
+ if(!unitTarget)
+ return;
- unitTarget->CastSpell(unitTarget,spellid,false);
- return;
- }
+ unitTarget->CastSpell(unitTarget, 44870, true);
+ break;
+ }
+ // Goblin Weather Machine
+ case 46203:
+ {
+ if(!unitTarget)
+ return;
- // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
- case 22539:
- case 22972:
- case 22975:
- case 22976:
- case 22977:
- case 22978:
- case 22979:
- case 22980:
- case 22981:
- case 22982:
- case 22983:
- case 22984:
- case 22985:
- {
- if(!unitTarget || !unitTarget->isAlive())
- return;
+ uint32 spellId;
+ switch(rand()%4)
+ {
+ case 0: spellId = 46740; break;
+ case 1: spellId = 46739; break;
+ case 2: spellId = 46738; break;
+ case 3: spellId = 46736; break;
+ }
+ unitTarget->CastSpell(unitTarget, spellId, true);
+ break;
+ }
+ //5,000 Gold
+ case 46642:
+ {
+ if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
+ return;
- // Onyxia Scale Cloak
- if(unitTarget->GetDummyAura(22683))
- return;
+ ((Player*)unitTarget)->ModifyMoney(50000000);
- // Shadow Flame
- m_caster->CastSpell(unitTarget, 22682, true);
- return;
- }
- break;
+ break;
+ }
+ // Emblazon Runeblade
+ case 51770:
+ {
+ if(!unitTarget)
+ return;
- // Summon Black Qiraji Battle Tank
- case 26656:
- {
- if(!unitTarget)
- return;
+ unitTarget->CastSpell(unitTarget,51771,false);
+ break;
+ }
+ // Death Gate
+ case 52751:
+ {
+ if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
+ return;
+ // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
+ unitTarget->CastSpell(unitTarget, damage, false);
+ break;
+ }
+ // random spell learn instead placeholder
+ case 60893: // Northrend Alchemy Research
+ case 61177: // Northrend Inscription Research
+ case 61288: // Minor Inscription Research
+ case 61756: // Northrend Inscription Research (FAST QA VERSION)
+ {
+ if(!IsExplicitDiscoverySpell(m_spellInfo))
+ {
+ sLog.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo->Id);
+ return;
+ }
- // Prevent stacking of mounts
- unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
+ if(m_caster->GetTypeId()!=TYPEID_PLAYER)
+ return;
+ Player* player = (Player*)m_caster;
- // Two separate mounts depending on area id (allows use both in and out of specific instance)
- if (unitTarget->GetAreaId() == 3428)
- unitTarget->CastSpell(unitTarget, 25863, false);
- else
- unitTarget->CastSpell(unitTarget, 26655, false);
- break;
- }
- // Piccolo of the Flaming Fire
- case 17512:
- {
- if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
- return;
- unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
- break;
- }
- // Netherbloom
- case 28702:
- {
- if(!unitTarget)
- return;
- // 25% chance of casting a random buff
- if(roll_chance_i(75))
- return;
+ // need replace effect 0 item by loot
+ uint32 reagent_id = m_spellInfo->EffectItemType[0];
- // triggered spells are 28703 to 28707
- // Note: some sources say, that there was the possibility of
- // receiving a debuff. However, this seems to be removed by a patch.
- const uint32 spellid = 28703;
+ if(!player->HasItemCount(reagent_id,1))
+ return;
- // don't overwrite an existing aura
- for(uint8 i=0; i<5; i++)
- if(unitTarget->HasAura(spellid+i, 0))
- return;
- unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
- break;
- }
+ // remove reagent
+ uint32 count = 1;
+ player->DestroyItemCount (reagent_id,count,true);
- // Nightmare Vine
- case 28720:
- {
- if(!unitTarget)
- return;
- // 25% chance of casting Nightmare Pollen
- if(roll_chance_i(75))
- return;
- unitTarget->CastSpell(unitTarget, 28721, true);
- break;
- }
+ // create some random items
+ player->AutoStoreLootItem(m_spellInfo->Id,LootTemplates_Spell);
- // Mirren's Drinking Hat
- case 29830:
- {
- uint32 item = 0;
- switch ( urand(1,6) )
- {
- case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager
- case 4: case 5: item = 23585; break;// Stouthammer Lite
- case 6: item = 23586; break;// Aerie Peak Pale Ale
+ // learn random explicit discovery recipe (if any)
+ if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player))
+ player->learnSpell(discoveredSpell,false);
+ return;
+ }
}
- if (item)
- DoCreateItem(effIndex,item);
break;
}
- // Improved Sprint
- case 30918:
+ case SPELLFAMILY_WARLOCK:
{
- // Removes snares and roots.
- uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
- Unit::AuraMap& Auras = unitTarget->GetAuras();
- for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
+ switch(m_spellInfo->Id)
{
- next = iter;
- ++next;
- Aura *aur = iter->second;
- if (!aur->IsPositive()) //only remove negative spells
+ // Healthstone creating spells
+ case 6201:
+ case 6202:
+ case 5699:
+ case 11729:
+ case 11730:
+ case 27230:
+ case 47871:
+ case 47878:
{
- // check for mechanic mask
- if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
+ uint32 itemtype;
+ uint32 rank = 0;
+ Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
{
- unitTarget->RemoveAurasDueToSpell(aur->GetId());
- if(Auras.empty())
+ if((*i)->GetId() == 18692)
+ {
+ rank = 1;
break;
- else
- next = Auras.begin();
+ }
+ else if((*i)->GetId() == 18693)
+ {
+ rank = 2;
+ break;
+ }
+ }
+
+ static uint32 const itypes[8][3] = {
+ { 5512,19004,19005}, // Minor Healthstone
+ { 5511,19006,19007}, // Lesser Healthstone
+ { 5509,19008,19009}, // Healthstone
+ { 5510,19010,19011}, // Greater Healthstone
+ { 9421,19012,19013}, // Major Healthstone
+ {22103,22104,22105}, // Master Healthstone
+ {36889,36890,36891}, // Demonic Healthstone
+ {36892,36893,36894} // Fel Healthstone
+ };
+
+ switch(m_spellInfo->Id)
+ {
+ case 6201:
+ itemtype=itypes[0][rank];break; // Minor Healthstone
+ case 6202:
+ itemtype=itypes[1][rank];break; // Lesser Healthstone
+ case 5699:
+ itemtype=itypes[2][rank];break; // Healthstone
+ case 11729:
+ itemtype=itypes[3][rank];break; // Greater Healthstone
+ case 11730:
+ itemtype=itypes[4][rank];break; // Major Healthstone
+ case 27230:
+ itemtype=itypes[5][rank];break; // Master Healthstone
+ case 47871:
+ itemtype=itypes[6][rank];break; // Demonic Healthstone
+ case 47878:
+ itemtype=itypes[7][rank];break; // Fel Healthstone
+ default:
+ return;
}
+ DoCreateItem( effIndex, itemtype );
+ return;
}
}
break;
}
-
- // Goblin Weather Machine
- case 46203:
+ case SPELLFAMILY_PRIEST:
{
- if(!unitTarget)
- return;
-
- uint32 spellId;
- switch(rand()%4)
+ switch(m_spellInfo->Id)
{
- case 0:
- spellId=46740;
- break;
- case 1:
- spellId=46739;
- break;
- case 2:
- spellId=46738;
- break;
- case 3:
- spellId=46736;
+ // Pain and Suffering
+ case 47948:
+ {
+ if (!unitTarget)
+ return;
+ // Refresh Shadow Word: Pain on target
+ Unit::AuraMap& auras = unitTarget->GetAuras();
+ for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
+ {
+ SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
+ if( spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
+ spellInfo->SpellFamilyFlags[0] & 0x8000 &&
+ (*itr).second->GetCasterGUID() == m_caster->GetGUID())
+ {
+ (*itr).second->RefreshAura();
+ return;
+ }
+ }
+ return;
+ }
+ default:
break;
}
- unitTarget->CastSpell(unitTarget, spellId, true);
break;
}
-
- }
-
- if(!unitTarget || !unitTarget->isAlive()) // can we remove this check?
- {
- sLog.outError("Spell %u in EffectScriptEffect does not have unitTarget", m_spellInfo->Id);
- return;
- }
-
- switch(m_spellInfo->Id)
- {
- // Dreaming Glory
- case 28698: unitTarget->CastSpell(unitTarget, 28694, true); break;
- // Needle Spine
- //case 39835: unitTarget->CastSpell(unitTarget, 39968, true); break;
- // Draw Soul
- case 40904: unitTarget->CastSpell(m_caster, 40903, true); break;
- // Flame Crash
- //case 41126: unitTarget->CastSpell(unitTarget, 41131, true); break;
- case 41931:
+ case SPELLFAMILY_HUNTER:
{
- int bag=19;
- int slot=0;
- Item* item = NULL;
-
- while (bag < 256)
+ switch(m_spellInfo->Id)
{
- item = ((Player*)m_caster)->GetItemByPos(bag,slot);
- if (item && item->GetEntry() == 38587) break;
- slot++;
- if (slot == 39)
+ // Chimera Shot
+ case 53209:
{
- slot = 0;
- bag++;
+ uint32 spellId = 0;
+ int32 basePoint = 0;
+ Unit::AuraMap& Auras = unitTarget->GetAuras();
+ for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
+ {
+ Aura *aura = (*i).second;
+ if (aura->GetCasterGUID() != m_caster->GetGUID())
+ continue;
+ // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
+ uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
+ if (!(familyFlag & 0x000000800000C000LL))
+ continue;
+ // Refresh aura duration
+ aura->RefreshAura();
+
+ // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
+ if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0)
+ {
+ spellId = 53353; // 53353 Chimera Shot - Serpent
+ basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
+ }
+ // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
+ if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0)
+ {
+ spellId = 53358; // 53358 Chimera Shot - Viper
+ basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
+ }
+ // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
+ if (familyFlag & 0x0000000000008000LL)
+ spellId = 53359; // 53359 Chimera Shot - Scorpid
+ // ?? nothing say in spell desc (possibly need addition check)
+ //if (familyFlag & 0x0000010000000000LL || // dot
+ // familyFlag & 0x0000100000000000LL) // stun
+ //{
+ // spellId = 53366; // 53366 Chimera Shot - Wyvern
+ //}
+ }
+ if (spellId)
+ m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
+ return;
}
+ default:
+ break;
}
- if (bag < 256)
- {
- if (((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount() == 1) ((Player*)m_caster)->RemoveItem(bag,slot,true);
- else ((Player*)m_caster)->GetItemByPos(bag,slot)->SetCount(((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount()-1);
- // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen)
- m_caster->CastSpell(m_caster,42518,true);
- return;
- }
- }
- // Force Cast - Portal Effect: Sunwell Isle
- case 44876: unitTarget->CastSpell(unitTarget, 44870, true); break;
- //5,000 Gold
- case 46642:
- {
- if(unitTarget->GetTypeId() == TYPEID_PLAYER)
- ((Player*)unitTarget)->ModifyMoney(50000000);
break;
}
- }
-
- if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
- {
- switch(m_spellInfo->SpellFamilyFlags)
+ case SPELLFAMILY_PALADIN:
{
// Judgement
- case 0x800000:
+ if (m_spellInfo->SpellFamilyFlags[0] & 0x800000)
{
+ if(!unitTarget || !unitTarget->isAlive())
+ return;
+ uint32 spellId1 = 0;
uint32 spellId2 = 0;
- // all seals have aura dummy
+ // Judgement self add switch
+ switch (m_spellInfo->Id)
+ {
+ case 41467: break; // Judgement
+ case 53407: spellId1 = 20184; break; // Judgement of Justice
+ case 20271: // Judgement of Light
+ case 57774: spellId1 = 20185; break; // Judgement of Light
+ case 53408: spellId1 = 20186; break; // Judgement of Wisdom
+ default:
+ return;
+ }
+ // all seals have aura dummy in 2 effect
Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
{
SpellEntry const *spellInfo = (*itr)->GetSpellProto();
-
// search seal (all seals have judgement's aura dummy spell id in 2 effect
- if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 )
+ if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
continue;
-
- // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
- spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1;
-
- if(spellId2 <= 1)
+ spellId2 = (*itr)->GetModifier()->m_amount;
+ SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
+ if (!judge)
continue;
+ break;
+ }
+ if (spellId1)
+ m_caster->CastSpell(unitTarget, spellId1, true);
+ if (spellId2)
+ m_caster->CastSpell(unitTarget, spellId2, true);
+ return;
+ }
+ }
+ case SPELLFAMILY_POTION:
+ {
+ switch(m_spellInfo->Id)
+ {
+ // Dreaming Glory
+ case 28698:
+ {
+ if(!unitTarget)
+ return;
+ unitTarget->CastSpell(unitTarget, 28694, true);
+ break;
+ }
+ // Netherbloom
+ case 28702:
+ {
+ if(!unitTarget)
+ return;
+ // 25% chance of casting a random buff
+ if(roll_chance_i(75))
+ return;
- // found, remove seal
- m_caster->RemoveAurasDueToSpell((*itr)->GetId());
-
- // Sanctified Judgement
- Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
- for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i)
- {
- if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL)
- {
- int32 chance = (*i)->GetModifier()->m_amount;
- if ( roll_chance_i(chance) )
- {
- int32 mana = spellInfo->manaCost;
- if ( Player* modOwner = m_caster->GetSpellModOwner() )
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana);
- mana = int32(mana* 0.8f);
- m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i);
- }
- break;
- }
- }
+ // triggered spells are 28703 to 28707
+ // Note: some sources say, that there was the possibility of
+ // receiving a debuff. However, this seems to be removed by a patch.
+ const uint32 spellid = 28703;
+ // don't overwrite an existing aura
+ for(uint8 i=0; i<5; i++)
+ if(unitTarget->HasAura(spellid+i, 0))
+ return;
+ unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
break;
}
- m_caster->CastSpell(unitTarget,spellId2,true);
- return;
+ // Nightmare Vine
+ case 28720:
+ {
+ if(!unitTarget)
+ return;
+ // 25% chance of casting Nightmare Pollen
+ if(roll_chance_i(75))
+ return;
+ unitTarget->CastSpell(unitTarget, 28721, true);
+ break;
+ }
}
+ break;
}
}
@@ -5062,7 +5312,7 @@ void Spell::EffectSanctuary(uint32 /*i*/)
std::list<Unit*> targets;
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(unitTarget, unitTarget, World::GetMaxVisibleDistance());
- Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
+ Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(unitTarget, targets, u_check);
unitTarget->VisitNearbyObject(World::GetMaxVisibleDistance(), searcher);
for(std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter)
{
@@ -5082,7 +5332,7 @@ void Spell::EffectSanctuary(uint32 /*i*/)
unitTarget->CombatStop();
unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
// Vanish allows to remove all threat and cast regular stealth so other spells can be used
- if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
+ if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_VANISH))
{
((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
}
@@ -5117,6 +5367,7 @@ void Spell::EffectDuel(uint32 i)
// Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
// Don't have to check the target's map since you cannot challenge someone across maps
if(caster->GetMap()->Instanceable())
+ //if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
{
SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
return;
@@ -5142,7 +5393,8 @@ void Spell::EffectDuel(uint32 i)
uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
Map *map = m_caster->GetMap();
- if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
+ if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
+ map, m_caster->GetPhaseMask(),
m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
m_caster->GetPositionZ(),
@@ -5255,6 +5507,43 @@ void Spell::EffectActivateObject(uint32 effect_idx)
sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
}
+void Spell::EffectApplyGlyph(uint32 i)
+{
+ if(m_caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ Player *player = (Player*)m_caster;
+
+ // remove old glyph
+ if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
+ {
+ if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
+ {
+ player->RemoveAurasDueToSpell(old_gp->SpellId);
+ player->SetGlyph(m_glyphIndex, 0);
+ }
+ }
+
+ // apply new one
+ if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
+ {
+ if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
+ {
+ if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
+ {
+ if(gp->TypeFlags != gs->TypeFlags)
+ {
+ SendCastResult(SPELL_FAILED_INVALID_GLYPH);
+ return; // glyph slot missmatch
+ }
+ }
+
+ player->CastSpell(m_caster, gp->SpellId, true);
+ player->SetGlyph(m_glyphIndex, glyph);
+ }
+ }
+}
+
void Spell::EffectSummonTotem(uint32 i)
{
uint8 slot = 0;
@@ -5288,7 +5577,8 @@ void Spell::EffectSummonTotem(uint32 i)
Totem* pTotem = new Totem;
- if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team ))
+ if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
+ m_spellInfo->EffectMiscValue[i], team ))
{
delete pTotem;
return;
@@ -5323,10 +5613,9 @@ void Spell::EffectSummonTotem(uint32 i)
}
pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
- pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
- pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true);
- pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true);
+ if(m_caster->GetTypeId() == TYPEID_PLAYER)
+ pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
pTotem->Summon(m_caster);
@@ -5421,7 +5710,8 @@ void Spell::EffectFeedPet(uint32 i)
Player *_player = (Player*)m_caster;
- if(!itemTarget)
+ Item* foodItem = m_targets.getItemTarget();
+ if(!foodItem)
return;
Pet *pet = _player->GetPet();
@@ -5431,15 +5721,15 @@ void Spell::EffectFeedPet(uint32 i)
if(!pet->isAlive())
return;
- int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel);
+ int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
if(benefit <= 0)
return;
uint32 count = 1;
- _player->DestroyItemCount(itemTarget,count,true);
+ _player->DestroyItemCount(foodItem,count,true);
// TODO: fix crash when a spell has two effects, both pointed at the same item target
- m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
+ m_caster->CastCustomSpell(pet,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
}
void Spell::EffectDismissPet(uint32 /*i*/)
@@ -5499,7 +5789,8 @@ void Spell::EffectSummonObject(uint32 i)
m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
Map *map = m_caster->GetMap();
- if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
+ if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
+ m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
{
delete pGameObj;
return;
@@ -5578,18 +5869,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)
@@ -5800,8 +6087,8 @@ void Spell::EffectSummonCritter(uint32 i)
Map *map = m_caster->GetMap();
uint32 pet_number = objmgr.GeneratePetNumber();
- if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),
- map, pet_entry, pet_number))
+ if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
+ pet_entry, pet_number))
{
sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
delete critter;
@@ -5865,14 +6152,16 @@ void Spell::EffectKnockBack(uint32 i)
float vsin = sin(m_caster->GetAngle(unitTarget));
float vcos = cos(m_caster->GetAngle(unitTarget));
+ float speedxy = float(m_spellInfo->EffectMiscValue[i])/10;
+ float speedz = float(damage/-10);
WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
data.append(unitTarget->GetPackGUID());
data << uint32(0); // Sequence
data << float(vcos); // x direction
data << float(vsin); // y direction
- data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed
- data << float(damage/-10); // Z Movement speed (vertical)
+ data << float(speedxy); // Horizontal speed
+ data << float(speedz); // Z Movement speed (vertical)
((Player*)unitTarget)->GetSession()->SendPacket(&data);
}
@@ -5895,17 +6184,26 @@ void Spell::EffectSendTaxi(uint32 i)
uint32 mountid = 0;
switch(m_spellInfo->Id)
{
- case 31606: //Stormcrow Amulet
+ case 31606: //Stormcrow Amulet
mountid = 17447;
break;
- case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
- case 45113: //Quest - Sunwell Daily - Ship Bombing Run
- case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
+ case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
+ case 45113: //Quest - Sunwell Daily - Ship Bombing Run
+ case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
mountid = 22840;
break;
- case 34905: //Stealth Flight
+ case 34905: //Stealth Flight
mountid = 6851;
break;
+ case 45883: //Amber Ledge to Beryl Point
+ mountid = 23524;
+ break;
+ case 46064: //Amber Ledge to Coldarra
+ mountid = 6371;
+ break;
+ case 53335: //Stormwind Harbor Flight - Peaceful
+ mountid = 6852;
+ break;
case 41533: //Fly of the Netherwing
case 41540: //Fly of the Netherwing
mountid = 23468;
@@ -6127,7 +6425,7 @@ void Spell::EffectTransmitted(uint32 effIndex)
GameObject* pGameObj = new GameObject;
if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
- fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
+ m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
{
delete pGameObj;
return;
@@ -6141,9 +6439,9 @@ void Spell::EffectTransmitted(uint32 effIndex)
{
m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
// Orientation3
- pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 );
+ pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 );
// Orientation4
- pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 );
+ pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 );
m_caster->AddGameObject(pGameObj); // will removed at spell cancel
// end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
@@ -6198,7 +6496,7 @@ void Spell::EffectTransmitted(uint32 effIndex)
{
GameObject* linkedGO = new GameObject;
if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
- fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
+ m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
{
linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
@@ -6238,6 +6536,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");
@@ -6385,8 +6705,42 @@ void Spell::EffectQuestFail(uint32 i)
((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
}
+void Spell::EffectActivateRune(uint32 eff_idx)
+{
+ if(m_caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ Player *plr = (Player*)m_caster;
+
+ if(plr->getClass() != CLASS_DEATH_KNIGHT)
+ return;
+
+ for(uint32 j = 0; j < MAX_RUNES; ++j)
+ {
+ if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
+ {
+ plr->SetRuneCooldown(j, 0);
+ }
+ }
+}
+
+void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
+{
+ if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)unitTarget)->SetCanTitanGrip(true);
+}
+
void Spell::EffectRedirectThreat(uint32 /*i*/)
{
if(unitTarget)
m_caster->SetReducedThreatPercent((uint32)damage, unitTarget->GetGUID());
}
+
+void Spell::EffectRenamePet(uint32 /*eff_idx*/)
+{
+ if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
+ !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
+ return;
+
+ unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
+}
diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp
index 9b77e19b30b..4186336fe18 100644
--- a/src/game/SpellHandler.cpp
+++ b/src/game/SpellHandler.cpp
@@ -38,15 +38,17 @@
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{
// TODO: add targets.read() check
- CHECK_PACKET_SIZE(recvPacket,1+1+1+1+8);
+ CHECK_PACKET_SIZE(recvPacket,1+1+1+4+8+4+1);
Player* pUser = _player;
uint8 bagIndex, slot;
- uint8 spell_count; // number of spells at item, not used
+ uint8 unk_flags; // flags (if 0x02 - some additional data are received)
uint8 cast_count; // next cast if exists (single or not)
uint64 item_guid;
+ uint32 glyphIndex; // something to do with glyphs?
+ uint32 spellid; // casted spell id
- recvPacket >> bagIndex >> slot >> spell_count >> cast_count >> item_guid;
+ recvPacket >> bagIndex >> slot >> cast_count >> spellid >> item_guid >> glyphIndex >> unk_flags;
Item *pItem = pUser->GetItemByPos(bagIndex, slot);
if(!pItem)
@@ -61,7 +63,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
return;
}
- sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, spell_count: %u , cast_count: %u, Item: %u, data length = %i", bagIndex, slot, spell_count, cast_count, pItem->GetEntry(), recvPacket.size());
+ sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, cast_count: %u, spellid: %u, Item: %u, glyphIndex: %u, unk_flags: %u, data length = %i", bagIndex, slot, cast_count, spellid, pItem->GetEntry(), glyphIndex, unk_flags, recvPacket.size());
ItemPrototype const *proto = pItem->GetProto();
if(!proto)
@@ -126,57 +128,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
if(!Script->ItemUse(pUser,pItem,targets))
{
// no script or script not process request by self
-
- // special learning case
- if(pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN)
- {
- uint32 learning_spell_id = pItem->GetProto()->Spells[1].SpellId;
-
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(SPELL_ID_GENERIC_LEARN);
- if(!spellInfo)
- {
- sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, SPELL_ID_GENERIC_LEARN);
- pUser->SendEquipError(EQUIP_ERR_NONE,pItem,NULL);
- return;
- }
-
- Spell *spell = new Spell(pUser, spellInfo, false);
- spell->m_CastItem = pItem;
- spell->m_cast_count = cast_count; //set count of casts
- spell->m_currentBasePoints[0] = learning_spell_id;
- spell->prepare(&targets);
- return;
- }
-
- // use triggered flag only for items with many spell casts and for not first cast
- int count = 0;
-
- for(int i = 0; i < 5; ++i)
- {
- _Spell const& spellData = pItem->GetProto()->Spells[i];
-
- // no spell
- if(!spellData.SpellId)
- continue;
-
- // wrong triggering type
- if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE)
- continue;
-
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId);
- if(!spellInfo)
- {
- sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, spellData.SpellId);
- continue;
- }
-
- Spell *spell = new Spell(pUser, spellInfo, (count > 0));
- spell->m_CastItem = pItem;
- spell->m_cast_count = cast_count; //set count of casts
- spell->prepare(&targets);
-
- ++count;
- }
+ pUser->CastItemUseSpell(pItem,targets,cast_count,glyphIndex);
}
}
@@ -227,7 +179,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
}
// required picklocking
- if(lockInfo->requiredlockskill || lockInfo->requiredminingskill)
+ if(lockInfo->Skill[1] || lockInfo->Skill[0])
{
pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL );
return;
@@ -281,17 +233,28 @@ void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data )
obj->Use(_player);
}
+void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket)
+{
+ CHECK_PACKET_SIZE(recvPacket,8);
+
+ uint64 guid;
+ recvPacket >> guid;
+
+ sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_REPORT_USE Message [in game guid: %u]", GUID_LOPART(guid));
+}
+
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
- CHECK_PACKET_SIZE(recvPacket,4+1+2);
+ CHECK_PACKET_SIZE(recvPacket,1+4+1);
uint32 spellId;
- uint8 cast_count;
- recvPacket >> spellId;
+ uint8 cast_count, unk_flags;
recvPacket >> cast_count;
+ recvPacket >> spellId;
+ recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received)
- sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i",
- spellId, cast_count, recvPacket.size());
+ sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i",
+ spellId, cast_count, unk_flags, recvPacket.size());
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
@@ -301,8 +264,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
return;
}
- // not have spell or spell passive and not casted by client
- if ( !_player->HasSpell (spellId) || IsPassiveSpell(spellId) )
+ // not have spell in spellbook or spell passive and not casted by client
+ if ( !_player->HasActiveSpell (spellId) || IsPassiveSpell(spellId) )
{
//cheater? kick? ban?
return;
@@ -334,9 +297,12 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket)
{
- CHECK_PACKET_SIZE(recvPacket,4);
+ CHECK_PACKET_SIZE(recvPacket,5);
+ // increments with every CANCEL packet, don't use for now
+ uint8 counter;
uint32 spellId;
+ recvPacket >> counter;
recvPacket >> spellId;
//FIXME: hack, ignore unexpected client cancel Deadly Throw cast
@@ -363,7 +329,7 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
return;
// lifebloom must delete final heal effect
- if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && (spellInfo->SpellFamilyFlags & 0x1000000000LL) )
+ if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && (spellInfo->SpellFamilyFlags[1] & 0x10) )
{
Unit::AuraMap::iterator iter;
while((iter = _player->m_Auras.find(Unit::spellEffectPair(spellId, 1))) != _player->m_Auras.end())
@@ -420,7 +386,7 @@ void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket)
return;
}
- Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid);
+ Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid);
if(!pet)
{
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 208f31540dc..433ebe80cc9 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -38,25 +38,25 @@ SpellMgr::SpellMgr()
case SPELL_EFFECT_PERSISTENT_AREA_AURA: //27
case SPELL_EFFECT_SUMMON: //28
case SPELL_EFFECT_TRIGGER_MISSILE: //32
- case SPELL_EFFECT_SUMMON_WILD: //41
- case SPELL_EFFECT_SUMMON_GUARDIAN: //42
+ //case SPELL_EFFECT_SUMMON_WILD: //41 not 303
+ //case SPELL_EFFECT_SUMMON_GUARDIAN: //42 not 303
case SPELL_EFFECT_TRANS_DOOR: //50 summon object
case SPELL_EFFECT_SUMMON_PET: //56
case SPELL_EFFECT_ADD_FARSIGHT: //72
- case SPELL_EFFECT_SUMMON_POSSESSED: //73
- case SPELL_EFFECT_SUMMON_TOTEM: //74
+ //case SPELL_EFFECT_SUMMON_POSSESSED: //73
+ //case SPELL_EFFECT_SUMMON_TOTEM: //74
case SPELL_EFFECT_SUMMON_OBJECT_WILD: //76
- case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: //87
- case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: //88
- case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: //89
- case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: //90
- case SPELL_EFFECT_SUMMON_CRITTER: //97
+ //case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: //87
+ //case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: //88
+ //case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: //89
+ //case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: //90
+ //case SPELL_EFFECT_SUMMON_CRITTER: //97 not 303
case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: //104
case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: //105
case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: //106
case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: //107
case SPELL_EFFECT_SUMMON_DEAD_PET: //109
- case SPELL_EFFECT_SUMMON_DEMON: //112
+ //case SPELL_EFFECT_SUMMON_DEMON: //112 not 303
case SPELL_EFFECT_TRIGGER_SPELL_2: //151 ritual of summon
EffectTargetType[i] = SPELL_REQUIRE_DEST;
break;
@@ -105,7 +105,6 @@ SpellMgr::SpellMgr()
case TARGET_UNIT_TARGET_ALLY:
case TARGET_UNIT_TARGET_RAID:
case TARGET_UNIT_TARGET_ANY:
- case TARGET_UNIT_SINGLE_UNKNOWN:
case TARGET_UNIT_TARGET_ENEMY:
case TARGET_UNIT_TARGET_PARTY:
case TARGET_UNIT_PARTY_TARGET:
@@ -328,17 +327,17 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
case SPELLFAMILY_MAGE:
{
// family flags 18(Molten), 25(Frost/Ice), 28(Mage)
- if (spellInfo->SpellFamilyFlags & 0x12040000)
+ if (spellInfo->SpellFamilyFlags[0] & 0x12040000)
return SPELL_MAGE_ARMOR;
- if ((spellInfo->SpellFamilyFlags & 0x1000000) && spellInfo->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE)
+ if ((spellInfo->SpellFamilyFlags[0] & 0x1000000) && spellInfo->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE)
return SPELL_MAGE_POLYMORPH;
break;
}
case SPELLFAMILY_WARRIOR:
{
- if (spellInfo->SpellFamilyFlags & 0x00008000010000LL)
+ if (spellInfo->SpellFamilyFlags[1] & 0x000080 || spellInfo->SpellFamilyFlags[0] & 0x10000LL)
return SPELL_POSITIVE_SHOUT;
break;
@@ -349,12 +348,12 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
if (spellInfo->Dispel == DISPEL_CURSE)
return SPELL_CURSE;
- // family flag 37 (only part spells have family name)
- if (spellInfo->SpellFamilyFlags & 0x2000000000LL)
+ // Warlock (Demon Armor | Demon Skin | Fel Armor)
+ if (spellInfo->SpellFamilyFlags[1] & 0x20000020 || spellInfo->SpellFamilyFlags[2] & 0x00000010)
return SPELL_WARLOCK_ARMOR;
//seed of corruption and corruption
- if (spellInfo->SpellFamilyFlags & 0x1000000002LL)
+ if (spellInfo->SpellFamilyFlags[1] & 0x10 || spellInfo->SpellFamilyFlags[0] & 0x2)
return SPELL_WARLOCK_CORRUPTION;
break;
}
@@ -364,6 +363,13 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
if (spellInfo->Dispel == DISPEL_POISON)
return SPELL_STING;
+ // only hunter aspects have this
+ if( spellInfo->SpellFamilyFlags[1] & 0x00440000 || spellInfo->SpellFamilyFlags[0] & 0x00380000 || spellInfo->SpellFamilyFlags[2] & 0x00003010)
+ return SPELL_ASPECT;
+
+ if( spellInfo->SpellFamilyFlags[2] & 0x00000002 )
+ return SPELL_TRACKER;
+
break;
}
case SPELLFAMILY_PALADIN:
@@ -371,16 +377,16 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
if (IsSealSpell(spellInfo))
return SPELL_SEAL;
- if (spellInfo->SpellFamilyFlags & 0x10000100LL)
+ if (spellInfo->SpellFamilyFlags[0] & 0x11010002)
return SPELL_BLESSING;
- if ((spellInfo->SpellFamilyFlags & 0x00000820180400LL) && (spellInfo->AttributesEx3 & 0x200))
+ if ((spellInfo->SpellFamilyFlags[1] & 0x000008 || spellInfo->SpellFamilyFlags[0] & 20180400) && (spellInfo->AttributesEx3 & 0x200))
return SPELL_JUDGEMENT;
for (int i = 0; i < 3; i++)
{
- // only paladin auras have this
- if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
+ // only paladin auras have this (for palaldin class family)
+ if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID)
return SPELL_AURA;
}
break;
@@ -395,28 +401,13 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
case SPELLFAMILY_POTION:
return spellmgr.GetSpellElixirSpecific(spellInfo->Id);
- }
-
- // only warlock armor/skin have this (in additional to family cases)
- if( spellInfo->SpellVisual == 130 && spellInfo->SpellIconID == 89)
- {
- return SPELL_WARLOCK_ARMOR;
- }
- // only hunter aspects have this (but not all aspects in hunter family)
- if( spellInfo->activeIconID == 122 && (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_NATURE) &&
- (spellInfo->Attributes & 0x50000) != 0 && (spellInfo->Attributes & 0x9000010) == 0)
- {
- return SPELL_ASPECT;
+ case SPELLFAMILY_DEATHKNIGHT:
+ if ((spellInfo->Attributes & 0x10) && (spellInfo->AttributesEx2 & 0x10) && (spellInfo->AttributesEx4 & 0x200000))
+ return SPELL_PRESENCE;
+ break;
}
- for(int i = 0; i < 3; i++)
- if( spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA && (
- spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_CREATURES ||
- spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_RESOURCES ||
- spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_STEALTHED ) )
- return SPELL_TRACKER;
-
// elixirs can have different families, but potion most ofc.
if(SpellSpecific sp = spellmgr.GetSpellElixirSpecific(spellInfo->Id))
return sp;
@@ -452,6 +443,7 @@ bool IsSingleFromSpellSpecificPerTarget(uint32 spellSpec1,uint32 spellSpec2)
case SPELL_MAGE_ARMOR:
case SPELL_ELEMENTAL_SHIELD:
case SPELL_MAGE_POLYMORPH:
+ case SPELL_PRESENCE:
case SPELL_WELL_FED:
case SPELL_DRINK:
case SPELL_FOOD:
@@ -484,8 +476,6 @@ bool IsPositiveTarget(uint32 targetA, uint32 targetB)
case TARGET_CURRENT_ENEMY_COORDINATES:
case TARGET_UNIT_CHANNEL:
return false;
- case TARGET_ALL_AROUND_CASTER:
- return (targetB == TARGET_ALL_PARTY || targetB == TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER);
default:
break;
}
@@ -890,8 +880,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 )
{
@@ -938,26 +928,22 @@ void SpellMgr::LoadSpellAffects()
continue;
}
- uint64 spellAffectMask = fields[2].GetUInt64();
+ flag96 affect(fields[2].GetUInt32(), fields[3].GetUInt32(), fields[4].GetUInt32());
- // Spell.dbc have own data for low part of SpellFamilyMask
- if( spellInfo->EffectItemType[effectId])
- {
- if(spellInfo->EffectItemType[effectId] == spellAffectMask)
- {
- sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectItemType%d) data for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId);
- continue;
- }
+ // Spell.dbc have own data
+ if (effectId>3)
+ continue;
- // 24429 have wrong data in EffectItemType and overwrites by DB, possible bug in client
- if(spellInfo->Id!=24429 && spellInfo->EffectItemType[effectId] != spellAffectMask)
- {
- sLog.outErrorDb("Spell %u listed in `spell_affect` have different low part from EffectItemType%d for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId);
- continue;
- }
+ flag96 dbc_affect;
+ dbc_affect = spellInfo->EffectSpellClassMask[effectId];
+ if(dbc_affect[0] == affect[0] || dbc_affect[1] == affect[1] || dbc_affect[2] == affect[2])
+ {
+ char text[]="ABC";
+ sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectSpellClassMask%c) data for effect index (%u) and not needed, skipped.", entry, text[effectId], effectId);
+ continue;
}
- mSpellAffectMap.insert(SpellAffectMap::value_type((entry<<8) + effectId,spellAffectMask));
+ mSpellAffectMap[(entry<<8) + effectId] = affect;
++count;
} while( result->NextRow() );
@@ -965,7 +951,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)
{
@@ -981,7 +967,9 @@ void SpellMgr::LoadSpellAffects()
spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER) )
continue;
- if(spellInfo->EffectItemType[effectId] != 0)
+ flag96 dbc_affect;
+ dbc_affect = spellInfo->EffectSpellClassMask[effectId];
+ if(dbc_affect)
continue;
if(mSpellAffectMap.find((id<<8) + effectId) != mSpellAffectMap.end())
@@ -992,33 +980,19 @@ void SpellMgr::LoadSpellAffects()
}
}
-bool SpellMgr::IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const
+bool SpellMgr::IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const
{
// false for spellInfo == NULL
- if (!spellInfo)
+ if (!spellInfo || !mod)
return false;
- SpellEntry const *affect_spell = sSpellStore.LookupEntry(spellId);
- // false for affect_spell == NULL
- if (!affect_spell)
+ SpellEntry const *affect_spell = sSpellStore.LookupEntry(mod->spellId);
+ // False if affect_spell == NULL or spellFamily not equal
+ if (!affect_spell || affect_spell->SpellFamilyName != spellInfo->SpellFamilyName)
return false;
- // False if spellFamily not equal
- if (affect_spell->SpellFamilyName != spellInfo->SpellFamilyName)
- return false;
-
- // If familyFlags == 0
- if (!familyFlags)
- {
- // Get it from spellAffect table
- familyFlags = GetSpellAffectMask(spellId,effectId);
- // false if familyFlags == 0
- if (!familyFlags)
- return false;
- }
-
// true
- if (familyFlags & spellInfo->SpellFamilyFlags)
+ if (mod->mask & spellInfo->SpellFamilyFlags)
return true;
return false;
@@ -1030,15 +1004,12 @@ void SpellMgr::LoadSpellProcEvents()
uint32 count = 0;
- // 0 1 2 3 4 5 6 7 8
- QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMask, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event");
+ // 0 1 2 3 4 5 6 7 8 9 10
+ QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event");
if( !result )
{
-
barGoLink bar( 1 );
-
bar.step();
-
sLog.outString();
sLog.outString( ">> Loaded %u spell proc event conditions", count );
return;
@@ -1052,7 +1023,7 @@ void SpellMgr::LoadSpellProcEvents()
bar.step();
- uint16 entry = fields[0].GetUInt16();
+ uint32 entry = fields[0].GetUInt32();
const SpellEntry *spell = sSpellStore.LookupEntry(entry);
if (!spell)
@@ -1065,12 +1036,13 @@ void SpellMgr::LoadSpellProcEvents()
spe.schoolMask = fields[1].GetUInt32();
spe.spellFamilyName = fields[2].GetUInt32();
- spe.spellFamilyMask = fields[3].GetUInt64();
- spe.procFlags = fields[4].GetUInt32();
- spe.procEx = fields[5].GetUInt32();
- spe.ppmRate = fields[6].GetFloat();
- spe.customChance = fields[7].GetFloat();
- spe.cooldown = fields[8].GetUInt32();
+ spe.spellFamilyMask = (uint64)fields[3].GetUInt32()|((uint64)fields[4].GetUInt32()<<32);
+ spe.spellFamilyMask2= fields[5].GetUInt32();
+ spe.procFlags = fields[6].GetUInt32();
+ spe.procEx = fields[7].GetUInt32();
+ spe.ppmRate = fields[8].GetFloat();
+ spe.customChance = fields[9].GetFloat();
+ spe.cooldown = fields[10].GetUInt32();
mSpellProcEventMap[entry] = spe;
@@ -1090,80 +1062,54 @@ void SpellMgr::LoadSpellProcEvents()
sLog.outString();
if (customProc)
- sLog.outString( ">> Loaded %u custom spell proc event conditions +%u custom", count, customProc );
+ sLog.outString( ">> Loaded %u extra spell proc event conditions +%u custom", count, customProc );
else
- sLog.outString( ">> Loaded %u spell proc event conditions", count );
+ sLog.outString( ">> Loaded %u extra spell proc event conditions", count );
+}
- /*
- // Commented for now, as it still produces many errors (still quite many spells miss spell_proc_event)
- for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id)
+void SpellMgr::LoadSpellBonusess()
+{
+ mSpellBonusMap.clear(); // need for reload case
+ uint32 count = 0;
+ // 0 1 2 3
+ QueryResult *result = WorldDatabase.Query("SELECT entry, direct_bonus, dot_bonus, ap_bonus FROM spell_bonus_data");
+ if( !result )
{
- SpellEntry const* spellInfo = sSpellStore.LookupEntry(id);
- if (!spellInfo)
- continue;
-
- bool found = false;
- for (int effectId = 0; effectId < 3; ++effectId)
- {
- // at this moment check only SPELL_AURA_PROC_TRIGGER_SPELL
- if( spellInfo->EffectApplyAuraName[effectId] == SPELL_AURA_PROC_TRIGGER_SPELL )
- {
- found = true;
- break;
- }
- }
+ barGoLink bar( 1 );
+ bar.step();
+ sLog.outString();
+ sLog.outString( ">> Loaded %u spell bonus data", count);
+ return;
+ }
- if(!found)
- continue;
+ barGoLink bar( result->GetRowCount() );
+ do
+ {
+ Field *fields = result->Fetch();
+ bar.step();
+ uint32 entry = fields[0].GetUInt32();
- if(GetSpellProcEvent(id))
+ const SpellEntry *spell = sSpellStore.LookupEntry(entry);
+ if (!spell)
+ {
+ sLog.outErrorDb("Spell %u listed in `spell_bonus_data` does not exist", entry);
continue;
+ }
- sLog.outErrorDb("Spell %u (%s) misses spell_proc_event",id,spellInfo->SpellName[sWorld.GetDBClang()]);
- }
- */
-}
-
-/*
-bool SpellMgr::IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, SpellEntry const * procSpell, uint32 procFlags )
-{
- if((procFlags & spellProcEvent->procFlags) == 0)
- return false;
+ SpellBonusEntry sbe;
- // Additional checks in case spell cast/hit/crit is the event
- // Check (if set) school, category, skill line, spell talent mask
- if(spellProcEvent->schoolMask && (!procSpell || (GetSpellSchoolMask(procSpell) & spellProcEvent->schoolMask) == 0))
- return false;
- if(spellProcEvent->category && (!procSpell || procSpell->Category != spellProcEvent->category))
- return false;
- if(spellProcEvent->skillId)
- {
- if (!procSpell)
- return false;
+ sbe.direct_damage = fields[1].GetFloat();
+ sbe.dot_damage = fields[2].GetFloat();
+ sbe.ap_bonus = fields[3].GetFloat();
- SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(procSpell->Id);
- SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(procSpell->Id);
+ mSpellBonusMap[entry] = sbe;
+ } while( result->NextRow() );
- bool found = false;
- for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
- {
- if(_spell_idx->second->skillId == spellProcEvent->skillId)
- {
- found = true;
- break;
- }
- }
- if (!found)
- return false;
- }
- if(spellProcEvent->spellFamilyName && (!procSpell || spellProcEvent->spellFamilyName != procSpell->SpellFamilyName))
- return false;
- if(spellProcEvent->spellFamilyMask && (!procSpell || (spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags) == 0))
- return false;
+ delete result;
- return true;
+ sLog.outString();
+ sLog.outString( ">> Loaded %u extra spell bonus data", count);
}
-*/
bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active)
{
@@ -1175,7 +1121,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellP
return false;
// Always trigger for this
- if (EventProcFlag & (PROC_FLAG_KILLED | PROC_FLAG_KILL_AND_GET_XP))
+ if (EventProcFlag & (PROC_FLAG_KILLED | PROC_FLAG_KILL | PROC_FLAG_ON_TRAP_ACTIVATION))
return true;
if (spellProcEvent) // Exist event data
@@ -1201,9 +1147,9 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellP
return false;
// spellFamilyName is Ok need check for spellFamilyMask if present
- if(spellProcEvent->spellFamilyMask)
+ if(spellProcEvent->spellFamilyMask || spellProcEvent->spellFamilyMask2)
{
- if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags) == 0)
+ if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags ) == 0)
return false;
active = true; // Spell added manualy -> so its active spell
}
@@ -1302,28 +1248,38 @@ bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellI
bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
{
+ if(IsPassiveSpell(spellInfo->Id)) // ranked passive spell
+ return false;
if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH)
return false;
- if(IsProfessionSpell(spellInfo->Id))
+ if(IsProfessionOrRidingSpell(spellInfo->Id))
+ return false;
+
+ if(spellmgr.IsSkillBonusSpell(spellInfo->Id))
return false;
// All stance spells. if any better way, change it.
for (int i = 0; i < 3; i++)
{
- // Paladin aura Spell
- if(spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN
- && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
- return false;
- // Druid form Spell
- if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID
- && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA
- && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
- return false;
- // Rogue Stealth
- if(spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE
- && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA
- && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
- return false;
+ switch(spellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_PALADIN:
+ // Paladin aura Spell
+ if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_RAID)
+ return false;
+ break;
+ case SPELLFAMILY_DRUID:
+ // Druid form Spell
+ if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA &&
+ spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
+ return false;
+ break;
+ case SPELLFAMILY_ROGUE:
+ // Rogue Stealth
+ if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA &&
+ spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
+ return false;
+ }
}
return true;
}
@@ -1352,6 +1308,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool
if(spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName)
return false;
+ // TODO: Is this needed?
+ // Allow stack passive and not passive spells
+ if ((spellInfo_1->Attributes & SPELL_ATTR_PASSIVE)!=(spellInfo_2->Attributes & SPELL_ATTR_PASSIVE))
+ return false;
+
// generic spells
if(!spellInfo_1->SpellFamilyName)
{
@@ -1406,6 +1367,21 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool
return true;
}
+
+bool SpellMgr::IsProfessionOrRidingSpell(uint32 spellId)
+{
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
+ if(!spellInfo)
+ return false;
+
+ if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL)
+ return false;
+
+ uint32 skill = spellInfo->EffectMiscValue[1];
+
+ return IsProfessionOrRidingSkill(skill);
+}
+
bool SpellMgr::IsProfessionSpell(uint32 spellId)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
@@ -1439,6 +1415,24 @@ bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId) const
return IsPrimaryProfessionSpell(spellId) && GetSpellRank(spellId)==1;
}
+bool SpellMgr::IsSkillBonusSpell(uint32 spellId) const
+{
+ SkillLineAbilityMap::const_iterator lower = GetBeginSkillLineAbilityMap(spellId);
+ SkillLineAbilityMap::const_iterator upper = GetEndSkillLineAbilityMap(spellId);
+
+ for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
+ {
+ SkillLineAbilityEntry const *pAbility = _spell_idx->second;
+ if (!pAbility || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL)
+ continue;
+
+ if(pAbility->req_skill_value > 0)
+ return true;
+ }
+
+ return false;
+}
+
SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const
{
// ignore passive spells
@@ -1450,7 +1444,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;
@@ -1525,21 +1520,31 @@ struct SpellRankEntry
uint32 RangeIndex;
uint32 SpellVisual;
uint32 ProcFlags;
- uint64 SpellFamilyFlags;
+ flag96 SpellFamilyFlags;
uint32 TargetAuraState;
uint32 ManaCost;
-
- bool operator()(const SpellRankEntry & _Left,const SpellRankEntry & _Right)const
- {
- return (_Left.SkillId != _Right.SkillId ? _Left.SkillId < _Right.SkillId
- : _Left.SpellName!=_Right.SpellName ? _Left.SpellName < _Right.SpellName
- : _Left.ProcFlags!=_Right.ProcFlags ? _Left.ProcFlags < _Right.ProcFlags
- : _Left.SpellFamilyFlags!=_Right.SpellFamilyFlags ? _Left.SpellFamilyFlags < _Right.SpellFamilyFlags
- : (_Left.SpellVisual!=_Right.SpellVisual) && (!_Left.SpellVisual || !_Right.SpellVisual) ? _Left.SpellVisual < _Right.SpellVisual
- : (_Left.ManaCost!=_Right.ManaCost) && (!_Left.ManaCost || !_Right.ManaCost) ? _Left.ManaCost < _Right.ManaCost
- : (_Left.DurationIndex!=_Right.DurationIndex) && (!_Left.DurationIndex || !_Right.DurationIndex)? _Left.DurationIndex < _Right.DurationIndex
- : (_Left.RangeIndex!=_Right.RangeIndex) && (!_Left.RangeIndex || !_Right.RangeIndex || _Left.RangeIndex==1 || !_Right.RangeIndex==1) ? _Left.RangeIndex < _Right.RangeIndex
- : _Left.TargetAuraState < _Right.TargetAuraState
+ uint32 CastingTimeIndex;
+ flag96 Effect;
+ flag96 Aura;
+ uint16 TalentID;
+
+ bool operator < (const SpellRankEntry & _Right) const
+ {
+ return (SkillId != _Right.SkillId ? SkillId < _Right.SkillId
+ : SpellName!=_Right.SpellName ? SpellName < _Right.SpellName
+ : ProcFlags!=_Right.ProcFlags ? ProcFlags < _Right.ProcFlags
+
+ : Effect!=_Right.Effect ? Effect < _Right.Effect
+ : Aura!=_Right.Aura ? Aura < _Right.Aura
+ : TalentID!=_Right.TalentID ? TalentID < _Right.TalentID
+ : (CastingTimeIndex!=_Right.CastingTimeIndex) && (!CastingTimeIndex || !_Right.CastingTimeIndex || CastingTimeIndex==1 || !_Right.CastingTimeIndex==1) ? CastingTimeIndex < _Right.CastingTimeIndex
+
+ : SpellFamilyFlags!=_Right.SpellFamilyFlags ? SpellFamilyFlags < _Right.SpellFamilyFlags
+ : (SpellVisual!=_Right.SpellVisual) && (!SpellVisual || !_Right.SpellVisual) ? SpellVisual < _Right.SpellVisual
+ : (ManaCost!=_Right.ManaCost) && (!ManaCost || !_Right.ManaCost) ? ManaCost < _Right.ManaCost
+ : (DurationIndex!=_Right.DurationIndex) && (!DurationIndex || !_Right.DurationIndex)? DurationIndex < _Right.DurationIndex
+ : (RangeIndex!=_Right.RangeIndex) && (!RangeIndex || !_Right.RangeIndex || RangeIndex==1 || !_Right.RangeIndex==1) ? RangeIndex < _Right.RangeIndex
+ : TargetAuraState < _Right.TargetAuraState
);
}
};
@@ -1548,6 +1553,7 @@ struct SpellRankValue
{
uint32 Id;
char const *Rank;
+ bool strict;
};
void SpellMgr::LoadSpellChains()
@@ -1560,14 +1566,12 @@ void SpellMgr::LoadSpellChains()
SkillLineAbilityEntry const *AbilityInfo=sSkillLineAbilityStore.LookupEntry(ability_id);
if (!AbilityInfo)
continue;
- if (AbilityInfo->spellId==20154) //exception to these rules (not needed in 3.0.3)
- continue;
if (!AbilityInfo->forward_spellid)
continue;
ChainedSpells.push_back(AbilityInfo->forward_spellid);
}
- std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry> RankMap;
+ std::multimap<SpellRankEntry, SpellRankValue> RankMap;
for (uint32 ability_id=0;ability_id<sSkillLineAbilityStore.GetNumRows();ability_id++)
{
@@ -1577,8 +1581,6 @@ void SpellMgr::LoadSpellChains()
//get only spell with lowest ability_id to prevent doubles
uint32 spell_id=AbilityInfo->spellId;
- if (spell_id==20154) //exception to these rules (not needed in 3.0.3)
- continue;
bool found=false;
for (uint32 i=0; i<ChainedSpells.size(); i++)
{
@@ -1597,7 +1599,7 @@ void SpellMgr::LoadSpellChains()
if(sRank.empty())
continue;
//exception to polymorph spells-make pig and turtle other chain than sheep
- if ((SpellInfo->SpellFamilyName==SPELLFAMILY_MAGE) && (SpellInfo->SpellFamilyFlags & 0x1000000) && (SpellInfo->SpellIconID!=82))
+ if ((SpellInfo->SpellFamilyName==SPELLFAMILY_MAGE) && (SpellInfo->SpellFamilyFlags[0] & 0x1000000) && (SpellInfo->SpellIconID!=82))
continue;
SpellRankEntry entry;
@@ -1609,14 +1611,16 @@ void SpellMgr::LoadSpellChains()
entry.ProcFlags=SpellInfo->procFlags;
entry.SpellFamilyFlags=SpellInfo->SpellFamilyFlags;
entry.TargetAuraState=SpellInfo->TargetAuraState;
- entry.SpellVisual=SpellInfo->SpellVisual;
+ entry.SpellVisual=SpellInfo->SpellVisual[0];
entry.ManaCost=SpellInfo->manaCost;
-
+ entry.CastingTimeIndex=0;
+ entry.TalentID=0;
for (;;)
{
AbilityInfo=mSkillLineAbilityMap.lower_bound(spell_id)->second;
value.Id=spell_id;
value.Rank=SpellInfo->Rank[sWorld.GetDefaultDbcLocale()];
+ value.strict=false;
RankMap.insert(std::pair<SpellRankEntry, SpellRankValue>(entry,value));
spell_id=AbilityInfo->forward_spellid;
SpellInfo=sSpellStore.LookupEntry(spell_id);
@@ -1629,48 +1633,109 @@ void SpellMgr::LoadSpellChains()
uint32 count=0;
- for (std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator itr = RankMap.begin();itr!=RankMap.end();)
+ for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr = RankMap.begin();itr!=RankMap.end();)
{
SpellRankEntry entry=itr->first;
//trac errors in extracted data
- std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator> RankErrorMap;
- for (std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2++)
+ std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator> RankErrorMap;
+ for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2++)
{
bar.step();
- RankErrorMap.insert(std::pair<char const *, std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator>(itr2->second.Rank,itr2));
- }
- for (std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator>::iterator itr2 = RankErrorMap.begin();itr2!=RankErrorMap.end();)
- {
- char const * err_entry=itr2->first;
- uint32 rank_count=RankErrorMap.count(itr2->first);
- if (rank_count>1)
- for (itr2 = RankErrorMap.lower_bound(err_entry);itr2!=RankErrorMap.upper_bound(err_entry);itr2++)
+ RankErrorMap.insert(std::pair<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator>(itr2->second.Rank,itr2));
+ }
+
+ bool error=false;
+ //if strict == true strict check is not needed
+ if (!itr->second.strict)
+ //check for rank duplicates, if there are any do strict check
+ for (std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator>::iterator itr2 = RankErrorMap.begin();itr2!=RankErrorMap.end();)
{
- sLog.outDebug("There is a duplicate rank entry (%s) for spell: %u",itr2->first,itr2->second->second.Id);
- sLog.outDebug("Spell %u removed from chain data.",itr2->second->second.Id);
- RankMap.erase(itr2->second);
- itr=RankMap.lower_bound(entry);
+ char const * err_entry=itr2->first;
+ uint32 rank_count=RankErrorMap.count(itr2->first);
+ if (rank_count>1)
+ {
+ error=true;
+ break;
+ }
+ else
+ itr2++;
}
- else
- itr2++;
- }
- //do not proceed for spells with less than 2 ranks
- uint32 spell_max_rank=RankMap.count(entry);
- if (spell_max_rank<2)
+ bool allHaveTalents=true;
+ if (error)
{
- itr=RankMap.upper_bound(entry);
+ std::list<uint32> ConflictedSpells;
+ for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2=RankMap.lower_bound(entry))
+ {
+ ConflictedSpells.push_back(itr2->second.Id);
+ if (!GetTalentSpellPos(itr2->second.Id))
+ allHaveTalents=false;
+ RankMap.erase(itr2);
+ }
+ SpellRankEntry nextEntry, currEntry;
+ for (;!ConflictedSpells.empty();ConflictedSpells.pop_front())
+ {
+ SpellEntry const *SpellInfo=sSpellStore.LookupEntry(ConflictedSpells.front());
+ currEntry.SkillId=entry.SkillId;
+ currEntry.SpellName=SpellInfo->SpellName[sWorld.GetDefaultDbcLocale()];
+ currEntry.DurationIndex=SpellInfo->DurationIndex;
+ currEntry.RangeIndex=SpellInfo->rangeIndex;
+ currEntry.ProcFlags=SpellInfo->procFlags;
+ currEntry.SpellFamilyFlags=SpellInfo->SpellFamilyFlags;
+ //compare talents only when all spells from chain have entry
+ //to prevent wrong results with spells which have first rank talented and other not
+ if (allHaveTalents)
+ currEntry.TalentID=GetTalentSpellPos(ConflictedSpells.front())->talent_id;
+ else
+ currEntry.TalentID=0;
+ currEntry.TargetAuraState=SpellInfo->TargetAuraState;
+ currEntry.SpellVisual=SpellInfo->SpellVisual[0];
+ currEntry.ManaCost=SpellInfo->manaCost;
+
+ //compare effects and casting time
+ currEntry.CastingTimeIndex=SpellInfo->CastingTimeIndex;
+ currEntry.Effect[0]=SpellInfo->Effect[0];
+ currEntry.Effect[1]=SpellInfo->Effect[1];
+ currEntry.Effect[2]=SpellInfo->Effect[2];
+
+ currEntry.Aura[0]=SpellInfo->EffectApplyAuraName[0];
+ currEntry.Aura[1]=SpellInfo->EffectApplyAuraName[1];
+ currEntry.Aura[2]=SpellInfo->EffectApplyAuraName[2];
+
+ SpellRankValue currValue;
+ currValue.Id=ConflictedSpells.front();
+ currValue.Rank=SpellInfo->Rank[sWorld.GetDefaultDbcLocale()];
+ currValue.strict=true;
+ RankMap.insert(std::pair<SpellRankEntry, SpellRankValue>(currEntry,currValue));
+ }
+ itr=RankMap.begin();
continue;
}
+ else
+ for (std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator>::iterator itr2 = RankErrorMap.begin();itr2!=RankErrorMap.end();)
+ {
+ char const * err_entry=itr2->first;
+ uint32 rank_count=RankErrorMap.count(itr2->first);
+ if (rank_count>1)
+ for (itr2 = RankErrorMap.lower_bound(err_entry);itr2!=RankErrorMap.upper_bound(err_entry);itr2++)
+ {
+ sLog.outDebug("There is a duplicate rank entry (%s) for spell: %u",itr2->first,itr2->second->second.Id);
+ if (!(itr2->second->second.Id==52375 || itr2->second->second.Id==45902))
+ {
+ sLog.outDebug("Spell %u removed from chain data.",itr2->second->second.Id);
+ RankMap.erase(itr2->second);
+ }
+ }
+ else
+ itr2++;
+ }
- itr=RankMap.upper_bound(entry);
-
- //order spells by spells by spellLevel
+ //order spells by spellLevel
std::list<uint32> RankedSpells;
uint32 min_spell_lvl=0;
- std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator min_itr;
+ std::multimap<SpellRankEntry, SpellRankValue>::iterator min_itr;
for (;RankMap.count(entry);)
{
- for (std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2++)
+ for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2++)
{
SpellEntry const *SpellInfo=sSpellStore.LookupEntry(itr2->second.Id);
if (SpellInfo->spellLevel<min_spell_lvl || itr2==RankMap.lower_bound(entry))
@@ -1706,9 +1771,13 @@ void SpellMgr::LoadSpellChains()
}
}
+ //do not proceed for spells with less than 2 ranks
+ itr=RankMap.begin();
+ if (RankedSpells.size()<2)
+ continue;
+
count++;
- itr=RankMap.upper_bound(entry);
uint32 spell_rank=1;
for(std::list<uint32>::iterator itr2 = RankedSpells.begin();itr2!=RankedSpells.end();spell_rank++)
{
@@ -1732,8 +1801,8 @@ void SpellMgr::LoadSpellChains()
}
//uncomment these two lines to print yourself list of spell_chains on startup
-// for (UNORDERED_MAP<uint32, SpellChainNode>::iterator itr=mSpellChains.begin();itr!=mSpellChains.end();itr++)
-// sLog.outString( "Id: %u, Rank: %d , %s",itr->first,itr->second.rank, sSpellStore.LookupEntry(itr->first)->Rank[sWorld.GetDefaultDbcLocale()]);
+ //for (UNORDERED_MAP<uint32, SpellChainNode>::iterator itr=mSpellChains.begin();itr!=mSpellChains.end();itr++)
+ //sLog.outString( "Id: %u, Rank: %d , %s, %u, %u, %u, %u",itr->first,itr->second.rank, sSpellStore.LookupEntry(itr->first)->Rank[sWorld.GetDefaultDbcLocale()], itr->second.first, itr->second.last,itr->second.next ,itr->second.prev);
sLog.outString();
sLog.outString( ">> Loaded %u spell chains",count);
@@ -1745,8 +1814,10 @@ void SpellMgr::LoadSpellLearnSkills()
// search auto-learned skills and add its to map also for use in unlearn spells/talents
uint32 dbc_count = 0;
+ barGoLink bar( sSpellStore.GetNumRows() );
for(uint32 spell = 0; spell < sSpellStore.GetNumRows(); ++spell)
{
+ bar.step();
SpellEntry const* entry = sSpellStore.LookupEntry(spell);
if(!entry)
@@ -1781,7 +1852,8 @@ void SpellMgr::LoadSpellLearnSpells()
{
mSpellLearnSpells.clear(); // need for reload case
- QueryResult *result = WorldDatabase.Query("SELECT entry, SpellID FROM spell_learn_spell");
+ // 0 1 2
+ QueryResult *result = WorldDatabase.Query("SELECT entry, SpellID, Active FROM spell_learn_spell");
if(!result)
{
barGoLink bar( 1 );
@@ -1805,6 +1877,7 @@ void SpellMgr::LoadSpellLearnSpells()
SpellLearnSpellNode node;
node.spell = fields[1].GetUInt32();
+ node.active = fields[2].GetBool();
node.autoLearned= false;
if(!sSpellStore.LookupEntry(spell_id))
@@ -1841,7 +1914,16 @@ void SpellMgr::LoadSpellLearnSpells()
{
SpellLearnSpellNode dbc_node;
dbc_node.spell = entry->EffectTriggerSpell[i];
- dbc_node.autoLearned = true;
+ dbc_node.active = true; // all dbc based learned spells is active (show in spell book or hide by client itself)
+
+ // ignore learning not existed spells (broken/outdated/or generic learnig spell 483
+ if(!sSpellStore.LookupEntry(dbc_node.spell))
+ continue;
+
+ // talent or passive spells or skill-step spells auto-casted and not need dependent learning,
+ // pet teaching spells don't must be dependent learning (casted)
+ // other required explicit dependent learning
+ dbc_node.autoLearned = entry->EffectImplicitTargetA[i]==TARGET_PET || GetTalentSpellCost(spell) > 0 || IsPassiveSpell(spell) || IsSpellHaveEffect(entry,SPELL_EFFECT_SKILL_STEP);
SpellLearnSpellMap::const_iterator db_node_begin = GetBeginSpellLearnSpell(spell);
SpellLearnSpellMap::const_iterator db_node_end = GetEndSpellLearnSpell(spell);
@@ -2160,7 +2242,7 @@ void SpellMgr::LoadSpellCustomAttr()
}
}
- if(spellInfo->SpellVisual == 3879)
+ if(spellInfo->SpellVisual[0] == 3879)
mSpellCustomAttr[i] |= SPELL_ATTR_CU_CONE_BACK;
switch(i)
@@ -2279,6 +2361,187 @@ void SpellMgr::LoadSpellLinked()
}
/// Some checks for spells, to prevent adding depricated/broken spells for trainers, spell book, etc
+void SpellMgr::LoadPetLevelupSpellMap()
+{
+ CreatureFamilyEntry const *creatureFamily;
+ SpellEntry const *spell;
+ uint32 count = 0;
+
+ for (uint32 i = 0; i < sCreatureFamilyStore.GetNumRows(); ++i)
+ {
+ creatureFamily = sCreatureFamilyStore.LookupEntry(i);
+
+ if(!creatureFamily) // not exist
+ continue;
+
+ if(creatureFamily->petTalentType < 0) // not hunter pet family
+ continue;
+
+ for(uint32 j = 0; j < sSpellStore.GetNumRows(); ++j)
+ {
+ spell = sSpellStore.LookupEntry(j);
+
+ // not exist
+ if(!spell)
+ continue;
+
+ // not hunter spell
+ if(spell->SpellFamilyName != SPELLFAMILY_HUNTER)
+ continue;
+
+ // not pet spell
+ if(!(spell->SpellFamilyFlags[1] & 0x10000000))
+ continue;
+
+ // not Growl or Cower (generics)
+ if(spell->SpellIconID != 201 && spell->SpellIconID != 958)
+ {
+ switch(creatureFamily->ID)
+ {
+ case CREATURE_FAMILY_BAT: // Bite and Sonic Blast
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 1577)
+ continue;
+ break;
+ case CREATURE_FAMILY_BEAR: // Claw and Swipe
+ if(spell->SpellIconID != 262 && spell->SpellIconID != 1562)
+ continue;
+ break;
+ case CREATURE_FAMILY_BIRD_OF_PREY: // Claw and Snatch
+ if(spell->SpellIconID != 262 && spell->SpellIconID != 168)
+ continue;
+ break;
+ case CREATURE_FAMILY_BOAR: // Bite and Gore
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 1578)
+ continue;
+ break;
+ case CREATURE_FAMILY_CARRION_BIRD: // Bite and Demoralizing Screech
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 1579)
+ continue;
+ break;
+ case CREATURE_FAMILY_CAT: // Claw and Prowl and Rake
+ if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 494)
+ continue;
+ break;
+ case CREATURE_FAMILY_CHIMAERA: // Bite and Froststorm Breath
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 62)
+ continue;
+ break;
+ case CREATURE_FAMILY_CORE_HOUND: // Bite and Lava Breath
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 1197)
+ continue;
+ break;
+ case CREATURE_FAMILY_CRAB: // Claw and Pin
+ if(spell->SpellIconID != 262 && spell->SpellIconID != 2679)
+ continue;
+ break;
+ case CREATURE_FAMILY_CROCOLISK: // Bite and Bad Attitude
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 1581)
+ continue;
+ break;
+ case CREATURE_FAMILY_DEVILSAUR: // Bite and Monstrous Bite
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 599)
+ continue;
+ break;
+ case CREATURE_FAMILY_DRAGONHAWK: // Bite and Fire Breath
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 2128)
+ continue;
+ break;
+ case CREATURE_FAMILY_GORILLA: // Smack and Thunderstomp
+ if(spell->SpellIconID != 473 && spell->SpellIconID != 148)
+ continue;
+ break;
+ case CREATURE_FAMILY_HYENA: // Bite and Tendon Rip
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 138)
+ continue;
+ break;
+ case CREATURE_FAMILY_MOTH: // Serenity Dust and Smack
+ if(spell->SpellIconID != 1714 && spell->SpellIconID != 473)
+ continue;
+ break;
+ case CREATURE_FAMILY_NETHER_RAY: // Bite and Nether Shock
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 2027)
+ continue;
+ break;
+ case CREATURE_FAMILY_RAPTOR: // Claw and Savage Rend
+ if(spell->SpellIconID != 262 && spell->SpellIconID != 245)
+ continue;
+ break;
+ case CREATURE_FAMILY_RAVAGER: // Bite and Ravage
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 2253)
+ continue;
+ break;
+ case CREATURE_FAMILY_RHINO: // Smack and Stampede
+ if(spell->SpellIconID != 473 && spell->SpellIconID != 3066)
+ continue;
+ break;
+ case CREATURE_FAMILY_SCORPID: // Claw and Scorpid Poison
+ if(spell->SpellIconID != 262 && spell->SpellIconID != 163)
+ continue;
+ break;
+ case CREATURE_FAMILY_SERPENT: // Bite and Poison Spit
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 68)
+ continue;
+ break;
+ case CREATURE_FAMILY_SILITHID: // Claw and Venom Web Spray
+ if(spell->SpellIconID != 262 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 12013))
+ continue;
+ break;
+ case CREATURE_FAMILY_SPIDER: // Bite and Web
+ if(spell->SpellIconID != 1680 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 684))
+ continue;
+ break;
+ case CREATURE_FAMILY_SPIRIT_BEAST: // Claw and Prowl and Spirit Strike
+ if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 255)
+ continue;
+ break;
+ case CREATURE_FAMILY_SPOREBAT: // Smack and Spore Cloud
+ if(spell->SpellIconID != 473 && spell->SpellIconID != 2681)
+ continue;
+ break;
+ case CREATURE_FAMILY_TALLSTRIDER: // Claw and Dust Cloud
+ if(spell->SpellIconID != 262 && (spell->SpellIconID != 157 && !(spell->Attributes & 0x4000000)))
+ continue;
+ break;
+ case CREATURE_FAMILY_TURTLE: // Bite and Shell Shield
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 1588)
+ continue;
+ break;
+ case CREATURE_FAMILY_WARP_STALKER: // Bite and Warp
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 1952)
+ continue;
+ break;
+ case CREATURE_FAMILY_WASP: // Smack and Sting
+ if(spell->SpellIconID != 473 && spell->SpellIconID != 110)
+ continue;
+ break;
+ case CREATURE_FAMILY_WIND_SERPENT: // Bite and Lightning Breath
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 62)
+ continue;
+ break;
+ case CREATURE_FAMILY_WOLF: // Bite and Furious Howl
+ if(spell->SpellIconID != 1680 && spell->SpellIconID != 1573)
+ continue;
+ break;
+ case CREATURE_FAMILY_WORM: // Acid Spit and Bite
+ if(spell->SpellIconID != 636 && spell->SpellIconID != 1680)
+ continue;
+ break;
+ default:
+ sLog.outError("LoadPetLevelupSpellMap: Unhandled creature family %u", creatureFamily->ID);
+ continue;
+ }
+ }
+
+ mPetLevelupSpellMap[creatureFamily->ID][spell->spellLevel] = spell->Id;
+ count++;
+ }
+ }
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u pet levelup spells", count );
+}
+
+/// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc
bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg)
{
// not exist
@@ -2353,11 +2616,24 @@ bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg)
return true;
}
-bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id)
+uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id)
{
// normal case
- if( spellInfo->AreaId && spellInfo->AreaId != zone_id && spellInfo->AreaId != area_id )
- return false;
+ if( spellInfo->AreaGroupId > 0)
+ {
+ bool found = false;
+
+ AreaGroupEntry const* groupEntry = sAreaGroupStore.LookupEntry(spellInfo->AreaGroupId);
+ if(groupEntry)
+ {
+ for (uint8 i=0; i<7; i++)
+ if( groupEntry->AreaId[i] == zone_id || groupEntry->AreaId[i] == area_id )
+ found = true;
+ }
+
+ if(!found)
+ return SPELL_FAILED_INCORRECT_AREA;
+ }
// elixirs (all area dependent elixirs have family SPELLFAMILY_POTION, use this for speedup)
if(spellInfo->SpellFamilyName==SPELLFAMILY_POTION)
@@ -2367,28 +2643,28 @@ bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 z
if(mask & ELIXIR_BATTLE_MASK)
{
if(spellInfo->Id==45373) // Bloodberry Elixir
- return zone_id==4075;
+ return zone_id==4075 ? 0 : SPELL_FAILED_REQUIRES_AREA;
}
if(mask & ELIXIR_UNSTABLE_MASK)
{
// in the Blade's Edge Mountains Plateaus and Gruul's Lair.
- return zone_id ==3522 || map_id==565;
+ return zone_id ==3522 || map_id==565 ? 0 : SPELL_FAILED_INCORRECT_AREA;
}
if(mask & ELIXIR_SHATTRATH_MASK)
{
// in Tempest Keep, Serpentshrine Cavern, Caverns of Time: Mount Hyjal, Black Temple, Sunwell Plateau
if(zone_id ==3607 || map_id==534 || map_id==564 || zone_id==4075)
- return true;
+ return 0;
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
if(!mapEntry)
- return false;
+ return SPELL_FAILED_INCORRECT_AREA;
- return mapEntry->multimap_id==206;
+ return mapEntry->multimap_id==206 ? 0 : SPELL_FAILED_INCORRECT_AREA;
}
// elixirs not have another limitations
- return true;
+ return 0;
}
}
@@ -2400,35 +2676,46 @@ bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 z
{
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
if(!mapEntry)
- return false;
+ return SPELL_FAILED_INCORRECT_AREA;
- return mapEntry->multimap_id==206;
+ return mapEntry->multimap_id==206 ? 0 : SPELL_FAILED_REQUIRES_AREA;
}
case 41617: // Cenarion Mana Salve
case 41619: // Cenarion Healing Salve
{
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
if(!mapEntry)
- return false;
+ return SPELL_FAILED_INCORRECT_AREA;
- return mapEntry->multimap_id==207;
+ return mapEntry->multimap_id==207 ? 0 : SPELL_FAILED_REQUIRES_AREA;
}
case 40216: // Dragonmaw Illusion
case 42016: // Dragonmaw Illusion
- return area_id == 3759 || area_id == 3966 || area_id == 3939;
+ return area_id == 3759 || area_id == 3966 || area_id == 3939 ? 0 : SPELL_FAILED_INCORRECT_AREA;
+ case 51721: // Dominion Over Acherus
+ case 54055: // Dominion Over Acherus
+ return area_id == 4281 || area_id == 4342 ? 0 : SPELL_FAILED_INCORRECT_AREA;
+ case 51852: // The Eye of Acherus
+ {
+ return map_id == 609 ? 0 : SPELL_FAILED_REQUIRES_AREA;
+ }
+ case 54119: // Mist of the Kvaldir
+ return area_id == 4028 || area_id == 4029 || area_id == 4106 || area_id == 4031 ? 0 : SPELL_FAILED_INCORRECT_AREA;
}
- return true;
+ return 0;
}
void SpellMgr::LoadSkillLineAbilityMap()
{
mSkillLineAbilityMap.clear();
+ barGoLink bar( sSkillLineAbilityStore.GetNumRows() );
uint32 count = 0;
for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); i++)
{
+ bar.step();
SkillLineAbilityEntry const *SkillInfo = sSkillLineAbilityStore.LookupEntry(i);
if(!SkillInfo)
continue;
@@ -2438,7 +2725,7 @@ void SpellMgr::LoadSkillLineAbilityMap()
}
sLog.outString();
- sLog.outString(">> Loaded %u SkillLineAbility MultiMap", count);
+ sLog.outString(">> Loaded %u SkillLineAbility MultiMap Data", count);
}
DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto, bool triggered)
@@ -2446,56 +2733,49 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto
// Explicit Diminishing Groups
switch(spellproto->SpellFamilyName)
{
- case SPELLFAMILY_MAGE:
- {
- // Polymorph
- if ((spellproto->SpellFamilyFlags & 0x00001000000LL) && spellproto->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE)
- return DIMINISHING_POLYMORPH;
- break;
- }
case SPELLFAMILY_ROGUE:
{
// Kidney Shot
- if (spellproto->SpellFamilyFlags & 0x00000200000LL)
+ if (spellproto->SpellFamilyFlags[0] & 0x200000)
return DIMINISHING_KIDNEYSHOT;
// Sap
- else if (spellproto->SpellFamilyFlags & 0x00000000080LL)
+ else if (spellproto->SpellFamilyFlags[0] & 0x80)
return DIMINISHING_POLYMORPH;
// Gouge
- else if (spellproto->SpellFamilyFlags & 0x00000000008LL)
+ else if (spellproto->SpellFamilyFlags[0] & 0x8)
return DIMINISHING_POLYMORPH;
// Blind
- else if (spellproto->SpellFamilyFlags & 0x00001000000LL)
+ else if (spellproto->SpellFamilyFlags[0] & 0x00001000000)
return DIMINISHING_BLIND_CYCLONE;
break;
}
case SPELLFAMILY_WARLOCK:
{
// Death Coil
- if (spellproto->SpellFamilyFlags & 0x00000080000LL)
+ if (spellproto->SpellFamilyFlags[0] & 0x00000080000)
return DIMINISHING_DEATHCOIL;
// Seduction
- if (spellproto->SpellFamilyFlags & 0x00040000000LL)
+ if (spellproto->SpellFamilyFlags[0] & 0x00040000000)
return DIMINISHING_FEAR;
// Fear
//else if (spellproto->SpellFamilyFlags & 0x40840000000LL)
// return DIMINISHING_WARLOCK_FEAR;
// Curses/etc
- else if (spellproto->SpellFamilyFlags & 0x00080000000LL)
+ else if (spellproto->SpellFamilyFlags[0] & 0x80000000)
return DIMINISHING_LIMITONLY;
break;
}
case SPELLFAMILY_DRUID:
{
// Cyclone
- if (spellproto->SpellFamilyFlags & 0x02000000000LL)
+ if (spellproto->SpellFamilyFlags[1] & 0x020)
return DIMINISHING_BLIND_CYCLONE;
break;
}
case SPELLFAMILY_WARRIOR:
{
// Hamstring - limit duration to 10s in PvP
- if (spellproto->SpellFamilyFlags & 0x00000000002LL)
+ if (spellproto->SpellFamilyFlags[0] & 0x00000000002)
return DIMINISHING_LIMITONLY;
break;
}
@@ -2504,30 +2784,21 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto
}
// Get by mechanic
- for (uint8 i=0;i<3;++i)
- {
- if (spellproto->Mechanic == MECHANIC_STUN || spellproto->EffectMechanic[i] == MECHANIC_STUN)
- return triggered ? DIMINISHING_TRIGGER_STUN : DIMINISHING_CONTROL_STUN;
- else if (spellproto->Mechanic == MECHANIC_SLEEP || spellproto->EffectMechanic[i] == MECHANIC_SLEEP)
- return DIMINISHING_SLEEP;
- else if (spellproto->Mechanic == MECHANIC_ROOT || spellproto->EffectMechanic[i] == MECHANIC_ROOT)
- return triggered ? DIMINISHING_TRIGGER_ROOT : DIMINISHING_CONTROL_ROOT;
- else if (spellproto->Mechanic == MECHANIC_FEAR || spellproto->EffectMechanic[i] == MECHANIC_FEAR)
- return DIMINISHING_FEAR;
- else if (spellproto->Mechanic == MECHANIC_CHARM || spellproto->EffectMechanic[i] == MECHANIC_CHARM)
- return DIMINISHING_CHARM;
- else if (spellproto->Mechanic == MECHANIC_SILENCE || spellproto->EffectMechanic[i] == MECHANIC_SILENCE)
- return DIMINISHING_SILENCE;
- else if (spellproto->Mechanic == MECHANIC_DISARM || spellproto->EffectMechanic[i] == MECHANIC_DISARM)
- return DIMINISHING_DISARM;
- else if (spellproto->Mechanic == MECHANIC_FREEZE || spellproto->EffectMechanic[i] == MECHANIC_FREEZE)
- return DIMINISHING_FREEZE;
- else if (spellproto->Mechanic == MECHANIC_KNOCKOUT|| spellproto->EffectMechanic[i] == MECHANIC_KNOCKOUT ||
- spellproto->Mechanic == MECHANIC_SAPPED || spellproto->EffectMechanic[i] == MECHANIC_SAPPED)
- return DIMINISHING_KNOCKOUT;
- else if (spellproto->Mechanic == MECHANIC_BANISH || spellproto->EffectMechanic[i] == MECHANIC_BANISH)
- return DIMINISHING_BANISH;
- }
+ uint32 mechanic = GetAllSpellMechanicMask(spellproto);
+ if (mechanic == MECHANIC_NONE) return DIMINISHING_NONE;
+ if (mechanic & (1<<MECHANIC_STUN)) return triggered ? DIMINISHING_TRIGGER_STUN : DIMINISHING_CONTROL_STUN;
+ if (mechanic & (1<<MECHANIC_SLEEP)) return DIMINISHING_SLEEP;
+ if (mechanic & (1<<MECHANIC_POLYMORPH)) return DIMINISHING_POLYMORPH;
+ if (mechanic & (1<<MECHANIC_ROOT)) return triggered ? DIMINISHING_TRIGGER_ROOT : DIMINISHING_CONTROL_ROOT;
+ if (mechanic & (1<<MECHANIC_FEAR)) return DIMINISHING_FEAR;
+ if (mechanic & (1<<MECHANIC_CHARM)) return DIMINISHING_CHARM;
+ if (mechanic & (1<<MECHANIC_SILENCE)) return DIMINISHING_SILENCE;
+ if (mechanic & (1<<DIMINISHING_DISARM)) return DIMINISHING_DISARM;
+ if (mechanic & (1<<MECHANIC_FREEZE)) return DIMINISHING_FREEZE;
+ if (mechanic & ((1<<MECHANIC_KNOCKOUT) | (1<<MECHANIC_SAPPED))) return DIMINISHING_KNOCKOUT;
+ if (mechanic & (1<<MECHANIC_BANISH)) return DIMINISHING_BANISH;
+ if (mechanic & (1<<MECHANIC_HORROR)) return DIMINISHING_DEATHCOIL;
+
return DIMINISHING_NONE;
}
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index babad470d5f..0e48871c8fd 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -10,12 +10,12 @@
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _SPELLMGR_H
@@ -29,6 +29,9 @@
#include "Database/SQLStorage.h"
#include "Utilities/UnorderedMap.h"
+
+#include "Player.h"
+
#include <map>
class Player;
@@ -38,175 +41,188 @@ extern SQLStorage sSpellThreatStore;
enum SpellFailedReason
{
- SPELL_FAILED_AFFECTING_COMBAT = 0x00,
- SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 0x01,
- SPELL_FAILED_ALREADY_AT_FULL_MANA = 0x02,
- SPELL_FAILED_ALREADY_AT_FULL_POWER = 0x03,
- SPELL_FAILED_ALREADY_BEING_TAMED = 0x04,
- SPELL_FAILED_ALREADY_HAVE_CHARM = 0x05,
- SPELL_FAILED_ALREADY_HAVE_SUMMON = 0x06,
- SPELL_FAILED_ALREADY_OPEN = 0x07,
- SPELL_FAILED_AURA_BOUNCED = 0x08,
- SPELL_FAILED_AUTOTRACK_INTERRUPTED = 0x09,
- SPELL_FAILED_BAD_IMPLICIT_TARGETS = 0x0A,
- SPELL_FAILED_BAD_TARGETS = 0x0B,
- SPELL_FAILED_CANT_BE_CHARMED = 0x0C,
- SPELL_FAILED_CANT_BE_DISENCHANTED = 0x0D,
- SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 0x0E,
- SPELL_FAILED_CANT_BE_PROSPECTED = 0x0F,
- SPELL_FAILED_CANT_CAST_ON_TAPPED = 0x10,
- SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 0x11,
- SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 0x12,
- SPELL_FAILED_CANT_STEALTH = 0x13,
- SPELL_FAILED_CASTER_AURASTATE = 0x14,
- SPELL_FAILED_CASTER_DEAD = 0x15,
- SPELL_FAILED_CHARMED = 0x16,
- SPELL_FAILED_CHEST_IN_USE = 0x17,
- SPELL_FAILED_CONFUSED = 0x18,
- SPELL_FAILED_DONT_REPORT = 0x19,
- SPELL_FAILED_EQUIPPED_ITEM = 0x1A,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS = 0x1B,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 0x1C,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 0x1D,
- SPELL_FAILED_ERROR = 0x1E,
- SPELL_FAILED_FIZZLE = 0x1F,
- SPELL_FAILED_FLEEING = 0x20,
- SPELL_FAILED_FOOD_LOWLEVEL = 0x21,
- SPELL_FAILED_HIGHLEVEL = 0x22,
- SPELL_FAILED_HUNGER_SATIATED = 0x23,
- SPELL_FAILED_IMMUNE = 0x24,
- SPELL_FAILED_INTERRUPTED = 0x25,
- SPELL_FAILED_INTERRUPTED_COMBAT = 0x26,
- SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 0x27,
- SPELL_FAILED_ITEM_GONE = 0x28,
- SPELL_FAILED_ITEM_NOT_FOUND = 0x29,
- SPELL_FAILED_ITEM_NOT_READY = 0x2A,
- SPELL_FAILED_LEVEL_REQUIREMENT = 0x2B,
- SPELL_FAILED_LINE_OF_SIGHT = 0x2C,
- SPELL_FAILED_LOWLEVEL = 0x2D,
- SPELL_FAILED_LOW_CASTLEVEL = 0x2E,
- SPELL_FAILED_MAINHAND_EMPTY = 0x2F,
- SPELL_FAILED_MOVING = 0x30,
- SPELL_FAILED_NEED_AMMO = 0x31,
- SPELL_FAILED_NEED_AMMO_POUCH = 0x32,
- SPELL_FAILED_NEED_EXOTIC_AMMO = 0x33,
- SPELL_FAILED_NOPATH = 0x34,
- SPELL_FAILED_NOT_BEHIND = 0x35,
- SPELL_FAILED_NOT_FISHABLE = 0x36,
- SPELL_FAILED_NOT_FLYING = 0x37,
- SPELL_FAILED_NOT_HERE = 0x38,
- SPELL_FAILED_NOT_INFRONT = 0x39,
- SPELL_FAILED_NOT_IN_CONTROL = 0x3A,
- SPELL_FAILED_NOT_KNOWN = 0x3B,
- SPELL_FAILED_NOT_MOUNTED = 0x3C,
- SPELL_FAILED_NOT_ON_TAXI = 0x3D,
- SPELL_FAILED_NOT_ON_TRANSPORT = 0x3E,
- SPELL_FAILED_NOT_READY = 0x3F,
- SPELL_FAILED_NOT_SHAPESHIFT = 0x40,
- SPELL_FAILED_NOT_STANDING = 0x41,
- SPELL_FAILED_NOT_TRADEABLE = 0x42,
- SPELL_FAILED_NOT_TRADING = 0x43,
- SPELL_FAILED_NOT_UNSHEATHED = 0x44,
- SPELL_FAILED_NOT_WHILE_GHOST = 0x45,
- SPELL_FAILED_NO_AMMO = 0x46,
- SPELL_FAILED_NO_CHARGES_REMAIN = 0x47,
- SPELL_FAILED_NO_CHAMPION = 0x48,
- SPELL_FAILED_NO_COMBO_POINTS = 0x49,
- SPELL_FAILED_NO_DUELING = 0x4A,
- SPELL_FAILED_NO_ENDURANCE = 0x4B,
- SPELL_FAILED_NO_FISH = 0x4C,
- SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 0x4D,
- SPELL_FAILED_NO_MOUNTS_ALLOWED = 0x4E,
- SPELL_FAILED_NO_PET = 0x4F,
- SPELL_FAILED_NO_POWER = 0x50,
- SPELL_FAILED_NOTHING_TO_DISPEL = 0x51,
- SPELL_FAILED_NOTHING_TO_STEAL = 0x52,
- SPELL_FAILED_ONLY_ABOVEWATER = 0x53,
- SPELL_FAILED_ONLY_DAYTIME = 0x54,
- SPELL_FAILED_ONLY_INDOORS = 0x55,
- SPELL_FAILED_ONLY_MOUNTED = 0x56,
- SPELL_FAILED_ONLY_NIGHTTIME = 0x57,
- SPELL_FAILED_ONLY_OUTDOORS = 0x58,
- SPELL_FAILED_ONLY_SHAPESHIFT = 0x59,
- SPELL_FAILED_ONLY_STEALTHED = 0x5A,
- SPELL_FAILED_ONLY_UNDERWATER = 0x5B,
- SPELL_FAILED_OUT_OF_RANGE = 0x5C,
- SPELL_FAILED_PACIFIED = 0x5D,
- SPELL_FAILED_POSSESSED = 0x5E,
- SPELL_FAILED_REAGENTS = 0x5F,
- SPELL_FAILED_REQUIRES_AREA = 0x60,
- SPELL_FAILED_REQUIRES_SPELL_FOCUS = 0x61,
- SPELL_FAILED_ROOTED = 0x62,
- SPELL_FAILED_SILENCED = 0x63,
- SPELL_FAILED_SPELL_IN_PROGRESS = 0x64,
- SPELL_FAILED_SPELL_LEARNED = 0x65,
- SPELL_FAILED_SPELL_UNAVAILABLE = 0x66,
- SPELL_FAILED_STUNNED = 0x67,
- SPELL_FAILED_TARGETS_DEAD = 0x68,
- SPELL_FAILED_TARGET_AFFECTING_COMBAT = 0x69,
- SPELL_FAILED_TARGET_AURASTATE = 0x6A,
- SPELL_FAILED_TARGET_DUELING = 0x6B,
- SPELL_FAILED_TARGET_ENEMY = 0x6C,
- SPELL_FAILED_TARGET_ENRAGED = 0x6D,
- SPELL_FAILED_TARGET_FRIENDLY = 0x6E,
- SPELL_FAILED_TARGET_IN_COMBAT = 0x6F,
- SPELL_FAILED_TARGET_IS_PLAYER = 0x70,
- SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 0x71,
- SPELL_FAILED_TARGET_NOT_DEAD = 0x72,
- SPELL_FAILED_TARGET_NOT_IN_PARTY = 0x73,
- SPELL_FAILED_TARGET_NOT_LOOTED = 0x74,
- SPELL_FAILED_TARGET_NOT_PLAYER = 0x75,
- SPELL_FAILED_TARGET_NO_POCKETS = 0x76,
- SPELL_FAILED_TARGET_NO_WEAPONS = 0x77,
- SPELL_FAILED_TARGET_UNSKINNABLE = 0x78,
- SPELL_FAILED_THIRST_SATIATED = 0x79,
- SPELL_FAILED_TOO_CLOSE = 0x7A,
- SPELL_FAILED_TOO_MANY_OF_ITEM = 0x7B,
- SPELL_FAILED_TOTEM_CATEGORY = 0x7C,
- SPELL_FAILED_TOTEMS = 0x7D,
- SPELL_FAILED_TRAINING_POINTS = 0x7E,
- SPELL_FAILED_TRY_AGAIN = 0x7F,
- SPELL_FAILED_UNIT_NOT_BEHIND = 0x80,
- SPELL_FAILED_UNIT_NOT_INFRONT = 0x81,
- SPELL_FAILED_WRONG_PET_FOOD = 0x82,
- SPELL_FAILED_NOT_WHILE_FATIGUED = 0x83,
- SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 0x84,
- SPELL_FAILED_NOT_WHILE_TRADING = 0x85,
- SPELL_FAILED_TARGET_NOT_IN_RAID = 0x86,
- SPELL_FAILED_DISENCHANT_WHILE_LOOTING = 0x87,
- SPELL_FAILED_PROSPECT_WHILE_LOOTING = 0x88,
- SPELL_FAILED_PROSPECT_NEED_MORE = 0x89,
- SPELL_FAILED_TARGET_FREEFORALL = 0x8A,
- SPELL_FAILED_NO_EDIBLE_CORPSES = 0x8B,
- SPELL_FAILED_ONLY_BATTLEGROUNDS = 0x8C,
- SPELL_FAILED_TARGET_NOT_GHOST = 0x8D,
- SPELL_FAILED_TOO_MANY_SKILLS = 0x8E,
- SPELL_FAILED_TRANSFORM_UNUSABLE = 0x8F,
- SPELL_FAILED_WRONG_WEATHER = 0x90,
- SPELL_FAILED_DAMAGE_IMMUNE = 0x91,
- SPELL_FAILED_PREVENTED_BY_MECHANIC = 0x92,
- SPELL_FAILED_PLAY_TIME = 0x93,
- SPELL_FAILED_REPUTATION = 0x94,
- SPELL_FAILED_MIN_SKILL = 0x95,
- SPELL_FAILED_NOT_IN_ARENA = 0x96,
- SPELL_FAILED_NOT_ON_SHAPESHIFT = 0x97,
- SPELL_FAILED_NOT_ON_STEALTHED = 0x98,
- SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 0x99,
- SPELL_FAILED_NOT_ON_MOUNTED = 0x9A,
- SPELL_FAILED_TOO_SHALLOW = 0x9B,
- SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 0x9C,
- SPELL_FAILED_TARGET_IS_TRIVIAL = 0x9D,
- SPELL_FAILED_BM_OR_INVISGOD = 0x9E,
- SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 0x9F,
- SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 0xA0,
- SPELL_FAILED_NOT_IDLE = 0xA1,
- SPELL_FAILED_NOT_INACTIVE = 0xA2,
- SPELL_FAILED_PARTIAL_PLAYTIME = 0xA3,
- SPELL_FAILED_NO_PLAYTIME = 0xA4,
- SPELL_FAILED_NOT_IN_BATTLEGROUND = 0xA5,
- SPELL_FAILED_ONLY_IN_ARENA = 0xA6,
- SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 0xA7,
- SPELL_FAILED_UNKNOWN = 0xA8,
+ SPELL_FAILED_AFFECTING_COMBAT = 0,
+ SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 1,
+ SPELL_FAILED_ALREADY_AT_FULL_MANA = 2,
+ SPELL_FAILED_ALREADY_AT_FULL_POWER = 3,
+ SPELL_FAILED_ALREADY_BEING_TAMED = 4,
+ SPELL_FAILED_ALREADY_HAVE_CHARM = 5,
+ SPELL_FAILED_ALREADY_HAVE_SUMMON = 6,
+ SPELL_FAILED_ALREADY_OPEN = 7,
+ SPELL_FAILED_AURA_BOUNCED = 8,
+ SPELL_FAILED_AUTOTRACK_INTERRUPTED = 9,
+ SPELL_FAILED_BAD_IMPLICIT_TARGETS = 10,
+ SPELL_FAILED_BAD_TARGETS = 11,
+ SPELL_FAILED_CANT_BE_CHARMED = 12,
+ SPELL_FAILED_CANT_BE_DISENCHANTED = 13,
+ SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 14,
+ SPELL_FAILED_CANT_BE_MILLED = 15,
+ SPELL_FAILED_CANT_BE_PROSPECTED = 16,
+ SPELL_FAILED_CANT_CAST_ON_TAPPED = 17,
+ SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 18,
+ SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 19,
+ SPELL_FAILED_CANT_STEALTH = 20,
+ SPELL_FAILED_CASTER_AURASTATE = 21,
+ SPELL_FAILED_CASTER_DEAD = 22,
+ SPELL_FAILED_CHARMED = 23,
+ SPELL_FAILED_CHEST_IN_USE = 24,
+ SPELL_FAILED_CONFUSED = 25,
+ SPELL_FAILED_DONT_REPORT = 26,
+ SPELL_FAILED_EQUIPPED_ITEM = 27,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS = 28,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 29,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 30,
+ SPELL_FAILED_ERROR = 31,
+ SPELL_FAILED_FIZZLE = 32,
+ SPELL_FAILED_FLEEING = 33,
+ SPELL_FAILED_FOOD_LOWLEVEL = 34,
+ SPELL_FAILED_HIGHLEVEL = 35,
+ SPELL_FAILED_HUNGER_SATIATED = 36,
+ SPELL_FAILED_IMMUNE = 37,
+ SPELL_FAILED_INCORRECT_AREA = 38,
+ SPELL_FAILED_INTERRUPTED = 39,
+ SPELL_FAILED_INTERRUPTED_COMBAT = 40,
+ SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 41,
+ SPELL_FAILED_ITEM_GONE = 42,
+ SPELL_FAILED_ITEM_NOT_FOUND = 43,
+ SPELL_FAILED_ITEM_NOT_READY = 44,
+ SPELL_FAILED_LEVEL_REQUIREMENT = 45,
+ SPELL_FAILED_LINE_OF_SIGHT = 46,
+ SPELL_FAILED_LOWLEVEL = 47,
+ SPELL_FAILED_LOW_CASTLEVEL = 48,
+ SPELL_FAILED_MAINHAND_EMPTY = 49,
+ SPELL_FAILED_MOVING = 50,
+ SPELL_FAILED_NEED_AMMO = 51,
+ SPELL_FAILED_NEED_AMMO_POUCH = 52,
+ SPELL_FAILED_NEED_EXOTIC_AMMO = 53,
+ SPELL_FAILED_NEED_MORE_ITEMS = 54,
+ SPELL_FAILED_NOPATH = 55,
+ SPELL_FAILED_NOT_BEHIND = 56,
+ SPELL_FAILED_NOT_FISHABLE = 57,
+ SPELL_FAILED_NOT_FLYING = 58,
+ SPELL_FAILED_NOT_HERE = 59,
+ SPELL_FAILED_NOT_INFRONT = 60,
+ SPELL_FAILED_NOT_IN_CONTROL = 61,
+ SPELL_FAILED_NOT_KNOWN = 62,
+ SPELL_FAILED_NOT_MOUNTED = 63,
+ SPELL_FAILED_NOT_ON_TAXI = 64,
+ SPELL_FAILED_NOT_ON_TRANSPORT = 65,
+ SPELL_FAILED_NOT_READY = 66,
+ SPELL_FAILED_NOT_SHAPESHIFT = 67,
+ SPELL_FAILED_NOT_STANDING = 68,
+ SPELL_FAILED_NOT_TRADEABLE = 69,
+ SPELL_FAILED_NOT_TRADING = 70,
+ SPELL_FAILED_NOT_UNSHEATHED = 71,
+ SPELL_FAILED_NOT_WHILE_GHOST = 72,
+ SPELL_FAILED_NOT_WHILE_LOOTING = 73,
+ SPELL_FAILED_NO_AMMO = 74,
+ SPELL_FAILED_NO_CHARGES_REMAIN = 75,
+ SPELL_FAILED_NO_CHAMPION = 76,
+ SPELL_FAILED_NO_COMBO_POINTS = 77,
+ SPELL_FAILED_NO_DUELING = 78,
+ SPELL_FAILED_NO_ENDURANCE = 79,
+ SPELL_FAILED_NO_FISH = 80,
+ SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 81,
+ SPELL_FAILED_NO_MOUNTS_ALLOWED = 82,
+ SPELL_FAILED_NO_PET = 83,
+ SPELL_FAILED_NO_POWER = 84,
+ SPELL_FAILED_NOTHING_TO_DISPEL = 85,
+ SPELL_FAILED_NOTHING_TO_STEAL = 86,
+ SPELL_FAILED_ONLY_ABOVEWATER = 87,
+ SPELL_FAILED_ONLY_DAYTIME = 88,
+ SPELL_FAILED_ONLY_INDOORS = 89,
+ SPELL_FAILED_ONLY_MOUNTED = 90,
+ SPELL_FAILED_ONLY_NIGHTTIME = 91,
+ SPELL_FAILED_ONLY_OUTDOORS = 92,
+ SPELL_FAILED_ONLY_SHAPESHIFT = 93,
+ SPELL_FAILED_ONLY_STEALTHED = 94,
+ SPELL_FAILED_ONLY_UNDERWATER = 95,
+ SPELL_FAILED_OUT_OF_RANGE = 96,
+ SPELL_FAILED_PACIFIED = 97,
+ SPELL_FAILED_POSSESSED = 98,
+ SPELL_FAILED_REAGENTS = 99,
+ SPELL_FAILED_REQUIRES_AREA = 100,
+ SPELL_FAILED_REQUIRES_SPELL_FOCUS = 101,
+ SPELL_FAILED_ROOTED = 102,
+ SPELL_FAILED_SILENCED = 103,
+ SPELL_FAILED_SPELL_IN_PROGRESS = 104,
+ SPELL_FAILED_SPELL_LEARNED = 105,
+ SPELL_FAILED_SPELL_UNAVAILABLE = 106,
+ SPELL_FAILED_STUNNED = 107,
+ SPELL_FAILED_TARGETS_DEAD = 108,
+ SPELL_FAILED_TARGET_AFFECTING_COMBAT = 109,
+ SPELL_FAILED_TARGET_AURASTATE = 110,
+ SPELL_FAILED_TARGET_DUELING = 111,
+ SPELL_FAILED_TARGET_ENEMY = 112,
+ SPELL_FAILED_TARGET_ENRAGED = 113,
+ SPELL_FAILED_TARGET_FRIENDLY = 114,
+ SPELL_FAILED_TARGET_IN_COMBAT = 115,
+ SPELL_FAILED_TARGET_IS_PLAYER = 116,
+ SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 117,
+ SPELL_FAILED_TARGET_NOT_DEAD = 118,
+ SPELL_FAILED_TARGET_NOT_IN_PARTY = 119,
+ SPELL_FAILED_TARGET_NOT_LOOTED = 120,
+ SPELL_FAILED_TARGET_NOT_PLAYER = 121,
+ SPELL_FAILED_TARGET_NO_POCKETS = 122,
+ SPELL_FAILED_TARGET_NO_WEAPONS = 123,
+ SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 124,
+ SPELL_FAILED_TARGET_UNSKINNABLE = 125,
+ SPELL_FAILED_THIRST_SATIATED = 126,
+ SPELL_FAILED_TOO_CLOSE = 127,
+ SPELL_FAILED_TOO_MANY_OF_ITEM = 128,
+ SPELL_FAILED_TOTEM_CATEGORY = 129,
+ SPELL_FAILED_TOTEMS = 130,
+ SPELL_FAILED_TRY_AGAIN = 131,
+ SPELL_FAILED_UNIT_NOT_BEHIND = 132,
+ SPELL_FAILED_UNIT_NOT_INFRONT = 133,
+ SPELL_FAILED_WRONG_PET_FOOD = 134,
+ SPELL_FAILED_NOT_WHILE_FATIGUED = 135,
+ SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 136,
+ SPELL_FAILED_NOT_WHILE_TRADING = 137,
+ SPELL_FAILED_TARGET_NOT_IN_RAID = 138,
+ SPELL_FAILED_TARGET_FREEFORALL = 139,
+ SPELL_FAILED_NO_EDIBLE_CORPSES = 140,
+ SPELL_FAILED_ONLY_BATTLEGROUNDS = 141,
+ SPELL_FAILED_TARGET_NOT_GHOST = 142,
+ SPELL_FAILED_TRANSFORM_UNUSABLE = 143,
+ SPELL_FAILED_WRONG_WEATHER = 144,
+ SPELL_FAILED_DAMAGE_IMMUNE = 145,
+ SPELL_FAILED_PREVENTED_BY_MECHANIC = 146,
+ SPELL_FAILED_PLAY_TIME = 147,
+ SPELL_FAILED_REPUTATION = 148,
+ SPELL_FAILED_MIN_SKILL = 149,
+ SPELL_FAILED_NOT_IN_ARENA = 150,
+ SPELL_FAILED_NOT_ON_SHAPESHIFT = 151,
+ SPELL_FAILED_NOT_ON_STEALTHED = 152,
+ SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 153,
+ SPELL_FAILED_NOT_ON_MOUNTED = 154,
+ SPELL_FAILED_TOO_SHALLOW = 155,
+ SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 156,
+ SPELL_FAILED_TARGET_IS_TRIVIAL = 157,
+ SPELL_FAILED_BM_OR_INVISGOD = 158,
+ SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 159,
+ SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 160,
+ SPELL_FAILED_NOT_IDLE = 161,
+ SPELL_FAILED_NOT_INACTIVE = 162,
+ SPELL_FAILED_PARTIAL_PLAYTIME = 163,
+ SPELL_FAILED_NO_PLAYTIME = 164,
+ SPELL_FAILED_NOT_IN_BATTLEGROUND = 165,
+ SPELL_FAILED_NOT_IN_RAID_INSTANCE = 166,
+ SPELL_FAILED_ONLY_IN_ARENA = 167,
+ SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 168,
+ SPELL_FAILED_ON_USE_ENCHANT = 169,
+ SPELL_FAILED_NOT_ON_GROUND = 170,
+ SPELL_FAILED_CUSTOM_ERROR = 171,
+ SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 172,
+ SPELL_FAILED_TOO_MANY_SOCKETS = 173,
+ SPELL_FAILED_INVALID_GLYPH = 174,
+ SPELL_FAILED_UNIQUE_GLYPH = 175,
+ SPELL_FAILED_GLYPH_SOCKET_LOCKED = 176,
+ SPELL_FAILED_NO_VALID_TARGETS = 177,
+ SPELL_FAILED_ITEM_AT_MAX_CHARGES = 178,
+ SPELL_FAILED_NOT_IN_BARBERSHOP = 179,
+ SPELL_FAILED_FISHING_TOO_LOW = 180,
+ SPELL_FAILED_UNKNOWN = 181
};
enum SpellFamilyNames
@@ -223,8 +239,12 @@ enum SpellFamilyNames
SPELLFAMILY_HUNTER = 9,
SPELLFAMILY_PALADIN = 10,
SPELLFAMILY_SHAMAN = 11,
- SPELLFAMILY_UNK2 = 12,
- SPELLFAMILY_POTION = 13
+ SPELLFAMILY_UNK2 = 12, // 2 spells (silence resistance)
+ SPELLFAMILY_POTION = 13,
+ // 14 - unused
+ SPELLFAMILY_DEATHKNIGHT = 15,
+ // 16 - unused
+ SPELLFAMILY_PET = 17
};
enum SpellDisableTypes
@@ -255,15 +275,15 @@ enum SpellSelectTargetTypes
};
//Some SpellFamilyFlags
-#define SPELLFAMILYFLAG_ROGUE_VANISH 0x000000800LL
-#define SPELLFAMILYFLAG_ROGUE_STEALTH 0x000400000LL
-#define SPELLFAMILYFLAG_ROGUE_BACKSTAB 0x000800004LL
-#define SPELLFAMILYFLAG_ROGUE_SAP 0x000000080LL
-#define SPELLFAMILYFLAG_ROGUE_FEINT 0x008000000LL
-#define SPELLFAMILYFLAG_ROGUE_KIDNEYSHOT 0x000200000LL
-#define SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE 0x9003E0000LL
-#define SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR 0x000004000LL
-#define SPELLFAMILYFLAG_SHAMAN_FROST_SHOCK 0x080000000LL
+#define SPELLFAMILYFLAG_ROGUE_VANISH 0x00000800
+#define SPELLFAMILYFLAG_ROGUE_STEALTH 0x00400000
+#define SPELLFAMILYFLAG_ROGUE_BACKSTAB 0x00800004
+#define SPELLFAMILYFLAG_ROGUE_SAP 0x00000080
+#define SPELLFAMILYFLAG_ROGUE_FEINT 0x08000000
+#define SPELLFAMILYFLAG_ROGUE_KIDNEYSHOT 0x00200000
+//#define SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE 0x9003E0000LL
+#define SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR 0x00004000
+#define SPELLFAMILYFLAG_SHAMAN_FROST_SHOCK 0x80000000
// Spell clasification
enum SpellSpecific
@@ -288,7 +308,8 @@ enum SpellSpecific
SPELL_WARLOCK_CORRUPTION= 17,
SPELL_WELL_FED = 18,
SPELL_DRINK = 19,
- SPELL_FOOD = 20
+ SPELL_FOOD = 20,
+ SPELL_PRESENCE = 21,
};
SpellSpecific GetSpellSpecific(uint32 spellId);
@@ -317,13 +338,21 @@ inline bool IsSealSpell(SpellEntry const *spellInfo)
{
//Collection of all the seal family flags. No other paladin spell has any of those.
return spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN &&
- ( spellInfo->SpellFamilyFlags & 0x4000A000200LL );
+ ( spellInfo->SpellFamilyFlags[1] & 0x26000C00
+ || spellInfo->SpellFamilyFlags[0] & 0x0A000000 );
}
inline bool IsElementalShield(SpellEntry const *spellInfo)
{
// family flags 10 (Lightning), 42 (Earth), 37 (Water), proc shield from T2 8 pieces bonus
- return (spellInfo->SpellFamilyFlags & 0x42000000400LL) || spellInfo->Id == 23552;
+ return (spellInfo->SpellFamilyFlags[1] & 0x420
+ || spellInfo->SpellFamilyFlags[0] & 0x00000400)
+ || spellInfo->Id == 23552;
+}
+
+inline bool IsExplicitDiscoverySpell(SpellEntry const *spellInfo)
+{
+ return spellInfo->Effect[0]==SPELL_EFFECT_CREATE_ITEM_2 && spellInfo->Effect[1]==SPELL_EFFECT_SCRIPT_EFFECT;
}
int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
@@ -331,6 +360,15 @@ bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1, uint32 spellSpec2);
bool IsSingleFromSpellSpecificPerTarget(uint32 spellSpec1, uint32 spellSpec2);
bool IsPassiveSpell(uint32 spellId);
+inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto)
+{
+ if(!IsPassiveSpell(spellProto->Id))
+ return false;
+
+ return !IsSpellHaveEffect(spellProto,SPELL_EFFECT_APPLY_AURA);
+}
+
+
inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo)
{
switch(spellInfo->Id)
@@ -358,9 +396,10 @@ bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellI
bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId);
-bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id);
+uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id);
extern bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS];
+
inline bool IsAreaOfEffectSpell(SpellEntry const *spellInfo)
{
if(IsAreaEffectTarget[spellInfo->EffectImplicitTargetA[0]] || IsAreaEffectTarget[spellInfo->EffectImplicitTargetB[0]])
@@ -375,6 +414,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 ||
@@ -407,6 +447,11 @@ inline bool isSpellBreakStealth(SpellEntry const* spellInfo)
return !(spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH);
}
+inline bool IsAutoRepeatRangedSpell(SpellEntry const* spellInfo)
+{
+ return (spellInfo->Attributes & SPELL_ATTR_RANGED) && (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG);
+}
+
uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form);
inline bool IsChanneledSpell(SpellEntry const* spellInfo)
@@ -434,6 +479,17 @@ inline uint32 GetSpellMechanicMask(SpellEntry const* spellInfo, int32 effect)
return mask;
}
+inline uint32 GetAllSpellMechanicMask(SpellEntry const* spellInfo)
+{
+ uint32 mask = 0;
+ if (spellInfo->Mechanic)
+ mask |= 1<<spellInfo->Mechanic;
+ for (int i=0; i< 3; ++i)
+ if (spellInfo->EffectMechanic[i])
+ mask |= 1<<spellInfo->EffectMechanic[i];
+ return mask;
+}
+
inline Mechanics GetEffectMechanic(SpellEntry const* spellInfo, int32 effect)
{
if (spellInfo->EffectMechanic[effect])
@@ -458,7 +514,7 @@ bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group);
DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group);
// Spell affects related declarations (accessed using SpellMgr functions)
-typedef std::map<uint32, uint64> SpellAffectMap;
+typedef UNORDERED_MAP<uint32, flag96> SpellAffectMap;
// Spell proc event related declarations (accessed using SpellMgr functions)
enum ProcFlags
@@ -466,16 +522,16 @@ enum ProcFlags
PROC_FLAG_NONE = 0x00000000,
PROC_FLAG_KILLED = 0x00000001, // 00 Killed by agressor
- PROC_FLAG_KILL_AND_GET_XP = 0x00000002, // 01 Kill that yields experience or honor
+ PROC_FLAG_KILL = 0x00000002, // 01 Kill target (in most cases need XP/Honor reward)
- PROC_FLAG_SUCCESSFUL_MILEE_HIT = 0x00000004, // 02 Successful melee attack
- PROC_FLAG_TAKEN_MELEE_HIT = 0x00000008, // 03 Taken damage from melee strike hit
+ PROC_FLAG_SUCCESSFUL_MILEE_HIT = 0x00000004, // 02 Successful melee auto attack
+ PROC_FLAG_TAKEN_MELEE_HIT = 0x00000008, // 03 Taken damage from melee auto attack hit
PROC_FLAG_SUCCESSFUL_MELEE_SPELL_HIT = 0x00000010, // 04 Successful attack by Spell that use melee weapon
PROC_FLAG_TAKEN_MELEE_SPELL_HIT = 0x00000020, // 05 Taken damage by Spell that use melee weapon
- PROC_FLAG_SUCCESSFUL_RANGED_HIT = 0x00000040, // 06 Successful Ranged attack (all ranged attack deal as spell so newer set :( )
- PROC_FLAG_TAKEN_RANGED_HIT = 0x00000080, // 07 Taken damage from ranged attack (all ranged attack deal as spell so newer set :( )
+ PROC_FLAG_SUCCESSFUL_RANGED_HIT = 0x00000040, // 06 Successful Ranged auto attack
+ PROC_FLAG_TAKEN_RANGED_HIT = 0x00000080, // 07 Taken damage from ranged auto attack
PROC_FLAG_SUCCESSFUL_RANGED_SPELL_HIT = 0x00000100, // 08 Successful Ranged attack by Spell that use ranged weapon
PROC_FLAG_TAKEN_RANGED_SPELL_HIT = 0x00000200, // 09 Taken damage by Spell that use ranged weapon
@@ -526,19 +582,20 @@ enum ProcFlagsEx
PROC_EX_DEFLECT = 0x0000200,
PROC_EX_ABSORB = 0x0000400,
PROC_EX_REFLECT = 0x0000800,
- PROC_EX_INTERRUPT = 0x0001000, // Melle hit result can be Interrupt (not used)
+ PROC_EX_INTERRUPT = 0x0001000, // Melee hit result can be Interrupt (not used)
PROC_EX_RESERVED1 = 0x0002000,
PROC_EX_RESERVED2 = 0x0004000,
PROC_EX_RESERVED3 = 0x0008000,
PROC_EX_EX_TRIGGER_ALWAYS = 0x0010000, // If set trigger always ( no matter another flags) used for drop charges
- PROC_EX_EX_ONE_TIME_TRIGGER = 0x0020000 // If set trigger always but only one time
+ PROC_EX_EX_ONE_TIME_TRIGGER = 0x0020000 // If set trigger always but only one time (not used)
};
struct SpellProcEventEntry
{
uint32 schoolMask; // if nonzero - bit mask for matching proc condition based on spell candidate's school: Fire=2, Mask=1<<(2-1)=2
uint32 spellFamilyName; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyNamer value
- uint64 spellFamilyMask; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags (like auras 107 and 108 do)
+ flag96 spellFamilyMask; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags (like auras 107 and 108 do)
+ uint32 spellFamilyMask2; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags2 (like auras 107 and 108 do)
uint32 procFlags; // bitmask for matching proc event
uint32 procEx; // proc Extend info (see ProcFlagsEx)
float ppmRate; // for melee (ranged?) damage spells - proc rate per minute. if zero, falls back to flat chance from Spell.dbc
@@ -546,7 +603,15 @@ struct SpellProcEventEntry
uint32 cooldown; // hidden cooldown used for some spell proc events, applied to _triggered_spell_
};
+struct SpellBonusEntry
+{
+ float direct_damage;
+ float dot_damage;
+ float ap_bonus;
+};
+
typedef UNORDERED_MAP<uint32, SpellProcEventEntry> SpellProcEventMap;
+typedef UNORDERED_MAP<uint32, SpellBonusEntry> SpellBonusMap;
#define ELIXIR_BATTLE_MASK 0x1
#define ELIXIR_GUARDIAN_MASK 0x2
@@ -669,6 +734,7 @@ typedef std::map<uint32, SpellLearnSkillNode> SpellLearnSkillMap;
struct SpellLearnSpellNode
{
uint32 spell;
+ bool active; // show in spellbook or not
bool autoLearned;
};
@@ -676,6 +742,9 @@ typedef std::multimap<uint32, SpellLearnSpellNode> SpellLearnSpellMap;
typedef std::multimap<uint32, SkillLineAbilityEntry const*> SkillLineAbilityMap;
+typedef std::map<uint32, uint32> PetLevelupSpellSet;
+typedef std::map<uint32, PetLevelupSpellSet> PetLevelupSpellMap;
+
inline bool IsPrimaryProfessionSkill(uint32 skill)
{
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(skill);
@@ -708,6 +777,11 @@ typedef std::vector<uint32> SpellCustomAttribute;
typedef std::map<int32, std::vector<int32> > SpellLinkedMap;
+inline bool IsProfessionOrRidingSkill(uint32 skill)
+{
+ return IsProfessionSkill(skill) || skill == SKILL_RIDING;
+}
+
class SpellMgr
{
// Constructors
@@ -718,15 +792,15 @@ class SpellMgr
// Accessors (const or static functions)
public:
// Spell affects
- uint64 GetSpellAffectMask(uint16 spellId, uint8 effectId) const
+ flag96 const*GetSpellAffect(uint16 spellId, uint8 effectId) const
{
SpellAffectMap::const_iterator itr = mSpellAffectMap.find((spellId<<8) + effectId);
if( itr != mSpellAffectMap.end( ) )
- return itr->second;
+ return &itr->second;
return 0;
}
- bool IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const;
+ bool IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const;
SpellElixirMap const& GetSpellElixirMap() const { return mSpellElixirs; }
@@ -763,6 +837,23 @@ class SpellMgr
static bool IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active);
+ // Spell bonus data
+ SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const
+ {
+ // Lookup data
+ SpellBonusMap::const_iterator itr = mSpellBonusMap.find(spellId);
+ if( itr != mSpellBonusMap.end( ) )
+ return &itr->second;
+ // Not found, try lookup for 1 spell rank if exist
+ if (uint32 rank_1 = GetFirstSpellInChain(spellId))
+ {
+ SpellBonusMap::const_iterator itr = mSpellBonusMap.find(rank_1);
+ if( itr != mSpellBonusMap.end( ) )
+ return &itr->second;
+ }
+ return NULL;
+ }
+
// Spell target coordinates
SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id) const
{
@@ -807,6 +898,14 @@ class SpellMgr
return 0;
}
+ uint32 GetNextSpellInChain(uint32 spell_id) const
+ {
+ if(SpellChainNode const* node = GetSpellChainNode(spell_id))
+ return node->next;
+
+ return 0;
+ }
+
SpellsRequiringSpellMap const& GetSpellsRequiringSpell() const { return mSpellsReqSpell; }
// Note: not use rank for compare to spell ranks: spell chains isn't linear order
@@ -886,10 +985,14 @@ class SpellMgr
return false;
}
+ static bool IsProfessionOrRidingSpell(uint32 spellId);
static bool IsProfessionSpell(uint32 spellId);
static bool IsPrimaryProfessionSpell(uint32 spellId);
bool IsPrimaryProfessionFirstRankSpell(uint32 spellId) const;
+ bool IsSkillBonusSpell(uint32 spellId) const;
+
+
// Spell script targets
SpellScriptTarget::const_iterator GetBeginSpellScriptTarget(uint32 spell_id) const
{
@@ -929,11 +1032,6 @@ class SpellMgr
return 0;
else
return mSpellCustomAttr[spell_id];
- /*SpellCustomAttrMap::const_iterator itr = mSpellCustomAttrMap.find(spell_id);
- if(itr != mSpellCustomAttrMap.end())
- return itr->second;
- else
- return 0;*/
}
const std::vector<int32> *GetSpellLinked(int32 spell_id) const
@@ -945,6 +1043,15 @@ class SpellMgr
SpellEffectTargetTypes EffectTargetType[TOTAL_SPELL_EFFECTS];
SpellSelectTargetTypes SpellTargetType[TOTAL_SPELL_TARGETS];
+ PetLevelupSpellSet const* GetPetLevelupSpellList(uint32 petFamily) const
+ {
+ PetLevelupSpellMap::const_iterator itr = mPetLevelupSpellMap.find(petFamily);
+ if(itr != mPetLevelupSpellMap.end())
+ return &itr->second;
+ else
+ return NULL;
+ }
+
// Modifiers
public:
static SpellMgr& Instance();
@@ -958,12 +1065,14 @@ class SpellMgr
void LoadSpellAffects();
void LoadSpellElixirs();
void LoadSpellProcEvents();
+ void LoadSpellBonusess();
void LoadSpellTargetPositions();
void LoadSpellThreats();
void LoadSkillLineAbilityMap();
void LoadSpellPetAuras();
void LoadSpellCustomAttr();
void LoadSpellLinked();
+ void LoadPetLevelupSpellMap();
private:
SpellScriptTarget mSpellScriptTarget;
@@ -976,10 +1085,12 @@ class SpellMgr
SpellAffectMap mSpellAffectMap;
SpellElixirMap mSpellElixirs;
SpellProcEventMap mSpellProcEventMap;
+ SpellBonusMap mSpellBonusMap;
SkillLineAbilityMap mSkillLineAbilityMap;
SpellPetAuraMap mSpellPetAuraMap;
SpellCustomAttribute mSpellCustomAttr;
SpellLinkedMap mSpellLinkedMap;
+ PetLevelupSpellMap mPetLevelupSpellMap;
};
#define spellmgr SpellMgr::Instance()
diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp
index bd5ab61eeff..5473206e8bd 100644
--- a/src/game/StatSystem.cpp
+++ b/src/game/StatSystem.cpp
@@ -51,24 +51,17 @@ bool Player::UpdateStats(Stats stat)
switch(stat)
{
case STAT_STRENGTH:
- UpdateAttackPowerAndDamage();
UpdateShieldBlockValue();
break;
case STAT_AGILITY:
UpdateArmor();
- UpdateAttackPowerAndDamage(true);
- if(getClass() == CLASS_ROGUE || getClass() == CLASS_HUNTER || getClass() == CLASS_DRUID && m_form==FORM_CAT)
- UpdateAttackPowerAndDamage();
-
UpdateAllCritPercentages();
UpdateDodgePercentage();
break;
-
case STAT_STAMINA: UpdateMaxHealth(); break;
case STAT_INTELLECT:
UpdateMaxPower(POWER_MANA);
UpdateAllSpellCritChances();
- UpdateAttackPowerAndDamage(true); //SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, only intellect currently
UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently
break;
@@ -78,11 +71,43 @@ 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;
}
+void Player::ApplySpellDamageBonus(int32 amount, bool apply)
+{
+ m_baseSpellDamage+=apply?amount:-amount;
+ // For speed just update for client
+ ApplyModUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, amount, apply);
+}
+
+void Player::ApplySpellHealingBonus(int32 amount, bool apply)
+{
+ m_baseSpellHealing+=apply?amount:-amount;
+ // For speed just update for client
+ for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
+ ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, amount, apply);;
+}
+
void Player::UpdateSpellDamageAndHealingBonus()
{
// Magic damage modifiers implemented in Unit::SpellDamageBonus
@@ -155,7 +180,7 @@ void Player::UpdateArmor()
{
Modifier* mod = (*i)->GetModifier();
if(mod->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)
- value += int32(GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetModifierValue() / 100.0f);
+ value += int32(GetStat(Stats((*i)->GetMiscBValue())) * mod->m_amount / 100.0f);
}
value *= GetModifierValue(unitMod, TOTAL_PCT);
@@ -213,6 +238,12 @@ void Player::UpdateMaxPower(Powers power)
SetMaxPower(power, uint32(value));
}
+void Player::ApplyFeralAPBonus(int32 amount, bool apply)
+{
+ m_baseFeralAP+= apply ? amount:-amount;
+ UpdateAttackPowerAndDamage();
+}
+
void Player::UpdateAttackPowerAndDamage(bool ranged )
{
float val2 = 0.0f;
@@ -253,11 +284,12 @@ void Player::UpdateAttackPowerAndDamage(bool ranged )
{
switch(getClass())
{
- case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
- case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
- case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break;
- case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break;
- case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ case CLASS_DEATH_KNIGHT: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break;
+ case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break;
+ case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break;
case CLASS_DRUID:
{
//Check if Predatory Strikes is skilled
@@ -286,12 +318,12 @@ void Player::UpdateAttackPowerAndDamage(bool ranged )
switch(m_form)
{
case FORM_CAT:
- val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f; break;
+ val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f + m_baseFeralAP; break;
case FORM_BEAR:
case FORM_DIREBEAR:
- val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break;
case FORM_MOONKIN:
- val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break;
default:
val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
}
@@ -309,11 +341,20 @@ void Player::UpdateAttackPowerAndDamage(bool ranged )
float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
- if( ranged && (getClassMask() & CLASSMASK_WAND_USERS)==0)
+ 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)->GetModifierValue() / 100.0f);
+ if ((getClassMask() & CLASSMASK_WAND_USERS)==0)
+ {
+ AuraList const& mRAPbyStat = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT);
+ for(AuraList::const_iterator i = mRAPbyStat.begin();i != mRAPbyStat.end(); ++i)
+ attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f);
+ }
+ }
+ else
+ {
+ AuraList const& mAPbyStat = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT);
+ for(AuraList::const_iterator i = mAPbyStat.begin();i != mAPbyStat.end(); ++i)
+ attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f);
}
float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
@@ -554,6 +595,24 @@ void Player::UpdateSpellCritChance(uint32 school)
SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1 + school, crit);
}
+void Player::UpdateMeleeHitChances()
+{
+ m_modMeleeHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
+ m_modMeleeHitChance+= GetRatingBonusValue(CR_HIT_MELEE);
+}
+
+void Player::UpdateRangedHitChances()
+{
+ m_modRangedHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
+ m_modRangedHitChance+= GetRatingBonusValue(CR_HIT_RANGED);
+}
+
+void Player::UpdateSpellHitChances()
+{
+ m_modSpellHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE);
+ m_modSpellHitChance+= GetRatingBonusValue(CR_HIT_SPELL);
+}
+
void Player::UpdateAllSpellCritChances()
{
for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
@@ -574,10 +633,10 @@ void Player::UpdateExpertise(WeaponAttackType attack)
{
// item neutral spell
if((*itr)->GetSpellProto()->EquippedItemClass == -1)
- expertise += (*itr)->GetModifierValue();
+ expertise += (*itr)->GetModifier()->m_amount;
// item dependent spell
else if(weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto()))
- expertise += (*itr)->GetModifierValue();
+ expertise += (*itr)->GetModifier()->m_amount;
}
if(expertise < 0)
@@ -591,6 +650,12 @@ void Player::UpdateExpertise(WeaponAttackType attack)
}
}
+void Player::ApplyManaRegenBonus(int32 amount, bool apply)
+{
+ m_baseManaRegen+= apply ? amount : -amount;
+ UpdateManaRegen();
+}
+
void Player::UpdateManaRegen()
{
float Intellect = GetStat(STAT_INTELLECT);
@@ -600,14 +665,14 @@ void Player::UpdateManaRegen()
power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA);
// Mana regen from SPELL_AURA_MOD_POWER_REGEN aura
- float power_regen_mp5 = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f;
+ float power_regen_mp5 = (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) + m_baseManaRegen) / 5.0f;
// Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura
AuraList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT);
for(AuraList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
- power_regen_mp5 += GetStat(Stats(mod->m_miscvalue)) * (*i)->GetModifierValue() / 500.0f;
+ power_regen_mp5 += GetStat(Stats(mod->m_miscvalue)) * mod->m_amount / 500.0f;
}
// Bonus from some dummy auras
@@ -624,9 +689,9 @@ void Player::UpdateManaRegen()
int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT);
if (modManaRegenInterrupt > 100)
modManaRegenInterrupt = 100;
- SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f);
+ SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f);
- SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN, power_regen_mp5 + power_regen);
+ SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, power_regen_mp5 + power_regen);
}
void Player::_ApplyAllStatBonuses()
@@ -923,7 +988,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/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp
index 640618eaebb..c3b9dce4c05 100644
--- a/src/game/TaxiHandler.cpp
+++ b/src/game/TaxiHandler.cpp
@@ -56,7 +56,7 @@ void WorldSession::SendTaxiStatus( uint64 guid )
return;
}
- uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId());
+ uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer( )->GetTeam());
// not found nearest
if(curloc == 0)
@@ -71,7 +71,7 @@ void WorldSession::SendTaxiStatus( uint64 guid )
sLog.outDebug( "WORLD: Sent SMSG_TAXINODE_STATUS" );
}
-void WorldSession::HandleTaxiQueryAvailableNodesOpcode( WorldPacket & recv_data )
+void WorldSession::HandleTaxiQueryAvailableNodes( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data,8);
@@ -103,7 +103,7 @@ void WorldSession::HandleTaxiQueryAvailableNodesOpcode( WorldPacket & recv_data
void WorldSession::SendTaxiMenu( Creature* unit )
{
// find current node
- uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId());
+ uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer( )->GetTeam());
if ( curloc == 0 )
return;
@@ -136,7 +136,7 @@ void WorldSession::SendDoFlight( uint16 MountId, uint32 path, uint32 pathNode )
bool WorldSession::SendLearnNewTaxiNode( Creature* unit )
{
// find current node
- uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId());
+ uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer( )->GetTeam());
if ( curloc == 0 )
return true; // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result.
diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp
index 0e902c05864..a78dfc09373 100644
--- a/src/game/ThreatManager.cpp
+++ b/src/game/ThreatManager.cpp
@@ -267,26 +267,36 @@ HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilRe
{
HostilReference* currentRef = NULL;
bool found = false;
-
+ bool noPriorityTargetFound = false;
+
std::list<HostilReference*>::iterator lastRef = iThreatList.end();
lastRef--;
-
- for(std::list<HostilReference*>::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found; ++iter)
+
+ for(std::list<HostilReference*>::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found;)
{
currentRef = (*iter);
Unit* target = currentRef->getTarget();
assert(target); // if the ref has status online the target must be there !
-
- // some units are preferred in comparison to others
- if(iter != lastRef && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask(), false) ||
- target->hasUnitState(UNIT_STAT_CONFUSED)
- ) )
+
+ // some units are prefered in comparison to others
+ if(!noPriorityTargetFound && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask()) || target->hasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_DAMAGE)) )
{
- // current victim is a second choice target, so don't compare threat with it below
- if(currentRef == pCurrentVictim)
- pCurrentVictim = NULL;
- continue;
+ if(iter != lastRef)
+ {
+ // current victim is a second choice target, so don't compare threat with it below
+ if(currentRef == pCurrentVictim)
+ pCurrentVictim = NULL;
+ ++iter;
+ continue;
+ }
+ else
+ {
+ // if we reached to this point, everyone in the threatlist is a second choice target. In such a situation the target with the highest threat should be attacked.
+ noPriorityTargetFound = true;
+ iter = iThreatList.begin();
+ continue;
+ }
}
if(!pAttacker->IsOutOfThreatArea(target)) // skip non attackable currently targets
@@ -314,6 +324,7 @@ HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilRe
break;
}
}
+ ++iter;
}
if(!found)
currentRef = NULL;
diff --git a/src/game/ThreatManager.h b/src/game/ThreatManager.h
index d4a3910e91e..018c66d4b43 100644
--- a/src/game/ThreatManager.h
+++ b/src/game/ThreatManager.h
@@ -208,10 +208,10 @@ class TRINITY_DLL_SPEC ThreatManager
// methods to access the lists from the outside to do sume dirty manipulation (scriping and such)
// I hope they are used as little as possible.
- inline std::list<HostilReference*>& getThreatList() { return iThreatContainer.getThreatList(); }
- inline std::list<HostilReference*>& getOfflieThreatList() { return iThreatOfflineContainer.getThreatList(); }
- inline ThreatContainer& getOnlineContainer() { return iThreatContainer; }
- inline ThreatContainer& getOfflineContainer() { return iThreatOfflineContainer; }
+ std::list<HostilReference*>& getThreatList() { return iThreatContainer.getThreatList(); }
+ std::list<HostilReference*>& getOfflieThreatList() { return iThreatOfflineContainer.getThreatList(); }
+ ThreatContainer& getOnlineContainer() { return iThreatContainer; }
+ ThreatContainer& getOfflineContainer() { return iThreatOfflineContainer; }
};
//=================================================
diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp
index 2ac26f823d6..7be3ffbd635 100644
--- a/src/game/Totem.cpp
+++ b/src/game/Totem.cpp
@@ -178,18 +178,18 @@ void Totem::SetTypeBySummonSpell(SpellEntry const * spellProto)
m_type = TOTEM_STATUE; //Jewelery statue
}
-bool Totem::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges)
+bool Totem::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const
{
-/* for (int i=0;i<3;i++)
+ // TODO: possibly all negative auras immuned?
+ switch(spellInfo->EffectApplyAuraName[index])
{
- switch(spellInfo->EffectApplyAuraName[i])
- {
- case SPELL_AURA_PERIODIC_DAMAGE:
- case SPELL_AURA_PERIODIC_LEECH:
- return true;
- default:
- continue;
- }
- }*/
- return Creature::IsImmunedToSpell(spellInfo, useCharges);
+ case SPELL_AURA_PERIODIC_DAMAGE:
+ case SPELL_AURA_PERIODIC_LEECH:
+ case SPELL_AURA_MOD_FEAR:
+ case SPELL_AURA_TRANSFORM:
+ return true;
+ default:
+ break;
+ }
+ return Creature::IsImmunedToSpellEffect(spellInfo, index);
}
diff --git a/src/game/Totem.h b/src/game/Totem.h
index 717499ff850..84d1d1f00f3 100644
--- a/src/game/Totem.h
+++ b/src/game/Totem.h
@@ -56,8 +56,8 @@ class Totem : public Creature
void UpdateMaxPower(Powers /*power*/) {}
void UpdateAttackPowerAndDamage(bool /*ranged*/ ) {}
void UpdateDamagePhysical(WeaponAttackType /*attType*/) {}
-
- bool IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges = false);
+
+ bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const;
protected:
TotemType m_type;
diff --git a/src/game/TotemAI.cpp b/src/game/TotemAI.cpp
index 4d7b45eba8e..fe6ad9e3674 100644
--- a/src/game/TotemAI.cpp
+++ b/src/game/TotemAI.cpp
@@ -82,21 +82,10 @@ TotemAI::UpdateAI(const uint32 /*diff*/)
!victim->isTargetableForAttack() || !i_totem.IsWithinDistInMap(victim, max_range) ||
i_totem.IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(&i_totem,false) )
{
- CellPair p(Trinity::ComputeCellPair(i_totem.GetPositionX(),i_totem.GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
-
victim = NULL;
-
Trinity::NearestAttackableUnitInObjectRangeCheck u_check(&i_totem, &i_totem, max_range);
- Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check);
-
- TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
- TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
-
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, grid_object_checker, *MapManager::Instance().GetMap(i_totem.GetMapId(), &i_totem));
- cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(i_totem.GetMapId(), &i_totem));
+ Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(&i_totem, victim, u_check);
+ i_totem.VisitNearbyObject(max_range, checker);
}
// If have target
diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp
index cccf50ad0fb..92f4f7a54cc 100644
--- a/src/game/Transports.cpp
+++ b/src/game/Transports.cpp
@@ -139,7 +139,7 @@ void MapManager::LoadTransports()
Transport::Transport() : GameObject()
{
// 2.3.2 - 0x5A
- m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION);
+ m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION);
}
bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags)
@@ -147,6 +147,7 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z,
Relocate(x,y,z,ang);
SetMapId(mapid);
+ // instance id and phaseMask isn't set to values different from std.
if(!IsPositionValid())
{
@@ -170,9 +171,10 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z,
SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size);
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
- SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
-
- SetUInt32Value(OBJECT_FIELD_ENTRY, goinfo->id);
+ //SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
+ SetUInt32Value(GAMEOBJECT_FLAGS, MAKE_PAIR32(0x28, 0x64));
+ SetUInt32Value(GAMEOBJECT_LEVEL, m_period);
+ SetEntry(goinfo->id);
SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId);
@@ -181,7 +183,7 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z,
SetGoAnimProgress(animprogress);
if(dynflags)
- SetUInt32Value(GAMEOBJECT_DYN_FLAGS, dynflags);
+ SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags));
return true;
}
@@ -479,11 +481,8 @@ bool Transport::AddPassenger(Player* passenger)
bool Transport::RemovePassenger(Player* passenger)
{
- if (m_passengers.find(passenger) != m_passengers.end())
- {
- sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), this->m_name.c_str());
- m_passengers.erase(passenger);
- }
+ if (m_passengers.erase(passenger))
+ sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), m_name.c_str());
return true;
}
diff --git a/src/game/Transports.h b/src/game/Transports.h
index 5fb15dbe98f..9093c0d21d0 100644
--- a/src/game/Transports.h
+++ b/src/game/Transports.h
@@ -38,16 +38,16 @@ class TransportPath
uint32 delay;
};
- inline void SetLength(const unsigned int sz)
+ void SetLength(const unsigned int sz)
{
i_nodes.resize( sz );
}
- inline unsigned int Size(void) const { return i_nodes.size(); }
- inline bool Empty(void) const { return i_nodes.empty(); }
- inline void Resize(unsigned int sz) { i_nodes.resize(sz); }
- inline void Clear(void) { i_nodes.clear(); }
- inline PathNode* GetNodes(void) { return static_cast<PathNode *>(&i_nodes[0]); }
+ unsigned int Size(void) const { return i_nodes.size(); }
+ bool Empty(void) const { return i_nodes.empty(); }
+ void Resize(unsigned int sz) { i_nodes.resize(sz); }
+ void Clear(void) { i_nodes.clear(); }
+ PathNode* GetNodes(void) { return static_cast<PathNode *>(&i_nodes[0]); }
PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; }
const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; }
diff --git a/src/game/Traveller.h b/src/game/Traveller.h
index 0ac136ff677..2e0bdaf0584 100644
--- a/src/game/Traveller.h
+++ b/src/game/Traveller.h
@@ -47,10 +47,10 @@ struct TRINITY_DLL_DECL Traveller
operator T&(void) { return i_traveller; }
operator const T&(void) { return i_traveller; }
- inline float GetPositionX() const { return i_traveller.GetPositionX(); }
- inline float GetPositionY() const { return i_traveller.GetPositionY(); }
- inline float GetPositionZ() const { return i_traveller.GetPositionZ(); }
- inline T& GetTraveller(void) { return i_traveller; }
+ float GetPositionX() const { return i_traveller.GetPositionX(); }
+ float GetPositionY() const { return i_traveller.GetPositionY(); }
+ float GetPositionZ() const { return i_traveller.GetPositionZ(); }
+ T& GetTraveller(void) { return i_traveller; }
float Speed(void) { assert(false); return 0.0f; }
void Relocation(float x, float y, float z, float orientation) {}
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index db777fe757f..0c79a7d2bd3 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -60,92 +60,17 @@ float baseMoveSpeed[MAX_MOVE_TYPE] =
3.141594f, // MOVE_TURN_RATE
7.0f, // MOVE_FLIGHT
4.5f, // MOVE_FLIGHT_BACK
+ 3.14f // MOVE_PITCH_RATE
};
-void InitTriggerAuraData();
-
-// auraTypes contains attacker auras capable of proc'ing cast auras
-static Unit::AuraTypeSet GenerateAttakerProcCastAuraTypes()
-{
- static Unit::AuraTypeSet auraTypes;
- auraTypes.insert(SPELL_AURA_DUMMY);
- auraTypes.insert(SPELL_AURA_PROC_TRIGGER_SPELL);
- auraTypes.insert(SPELL_AURA_MOD_HASTE);
- auraTypes.insert(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- return auraTypes;
-}
-
-// auraTypes contains victim auras capable of proc'ing cast auras
-static Unit::AuraTypeSet GenerateVictimProcCastAuraTypes()
-{
- static Unit::AuraTypeSet auraTypes;
- auraTypes.insert(SPELL_AURA_DUMMY);
- auraTypes.insert(SPELL_AURA_PRAYER_OF_MENDING);
- auraTypes.insert(SPELL_AURA_PROC_TRIGGER_SPELL);
- return auraTypes;
-}
-
-// auraTypes contains auras capable of proc effect/damage (but not cast) for attacker
-static Unit::AuraTypeSet GenerateAttakerProcEffectAuraTypes()
-{
- static Unit::AuraTypeSet auraTypes;
- auraTypes.insert(SPELL_AURA_MOD_DAMAGE_DONE);
- auraTypes.insert(SPELL_AURA_PROC_TRIGGER_DAMAGE);
- auraTypes.insert(SPELL_AURA_MOD_CASTING_SPEED);
- auraTypes.insert(SPELL_AURA_MOD_RATING);
- return auraTypes;
-}
-
-// auraTypes contains auras capable of proc effect/damage (but not cast) for victim
-static Unit::AuraTypeSet GenerateVictimProcEffectAuraTypes()
-{
- static Unit::AuraTypeSet auraTypes;
- auraTypes.insert(SPELL_AURA_MOD_RESISTANCE);
- auraTypes.insert(SPELL_AURA_PROC_TRIGGER_DAMAGE);
- auraTypes.insert(SPELL_AURA_MOD_PARRY_PERCENT);
- auraTypes.insert(SPELL_AURA_MOD_BLOCK_PERCENT);
- auraTypes.insert(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
- return auraTypes;
-}
-
-static Unit::AuraTypeSet attackerProcCastAuraTypes = GenerateAttakerProcCastAuraTypes();
-static Unit::AuraTypeSet attackerProcEffectAuraTypes = GenerateAttakerProcEffectAuraTypes();
-
-static Unit::AuraTypeSet victimProcCastAuraTypes = GenerateVictimProcCastAuraTypes();
-static Unit::AuraTypeSet victimProcEffectAuraTypes = GenerateVictimProcEffectAuraTypes();
-
-// auraTypes contains auras capable of proc'ing for attacker and victim
-static Unit::AuraTypeSet GenerateProcAuraTypes()
-{
- InitTriggerAuraData();
-
- Unit::AuraTypeSet auraTypes;
- auraTypes.insert(attackerProcCastAuraTypes.begin(),attackerProcCastAuraTypes.end());
- auraTypes.insert(attackerProcEffectAuraTypes.begin(),attackerProcEffectAuraTypes.end());
- auraTypes.insert(victimProcCastAuraTypes.begin(),victimProcCastAuraTypes.end());
- auraTypes.insert(victimProcEffectAuraTypes.begin(),victimProcEffectAuraTypes.end());
- return auraTypes;
-}
-
-static Unit::AuraTypeSet procAuraTypes = GenerateProcAuraTypes();
-
-bool IsPassiveStackableSpell( uint32 spellId )
-{
- if(!IsPassiveSpell(spellId))
- return false;
-
- SpellEntry const* spellProto = sSpellStore.LookupEntry(spellId);
- if(!spellProto)
- return false;
-
- for(int j = 0; j < 3; ++j)
- {
- if(std::find(procAuraTypes.begin(),procAuraTypes.end(),spellProto->EffectApplyAuraName[j])!=procAuraTypes.end())
- return false;
- }
-
- return true;
-}
+// Used for prepare can/can`t triggr aura
+static bool InitTriggerAuraData();
+// Define can trigger auras
+static bool isTriggerAura[TOTAL_AURAS];
+// Define can`t trigger auras (need for disable second trigger)
+static bool isNonTriggerAura[TOTAL_AURAS];
+// Prepare lists
+static bool procPrepared = InitTriggerAuraData();
Unit::Unit()
: WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostilRefManager(this)
@@ -154,7 +79,7 @@ Unit::Unit()
m_objectType |= TYPEMASK_UNIT;
m_objectTypeId = TYPEID_UNIT;
// 2.3.2 - 0x70
- m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HASPOSITION);
+ m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION);
m_attackTimer[BASE_ATTACK] = 0;
m_attackTimer[OFF_ATTACK] = 0;
@@ -183,7 +108,6 @@ Unit::Unit()
//m_AurasCheck = 2000;
//m_removeAuraTimer = 4;
//tmpAura = NULL;
- waterbreath = false;
m_Visibility = VISIBILITY_ON;
@@ -322,6 +246,7 @@ void Unit::Update( uint32 p_time )
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, GetHealth() < GetMaxHealth()*0.20f);
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth()*0.35f);
+ ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetHealth() > GetMaxHealth()*0.75f);
i_motionMaster.UpdateMotion(p_time);
}
@@ -385,6 +310,11 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 ty
case 1: // stop packet
SendMessageToSet( &data, true );
return;
+ case 2: // not used currently
+ data << float(0); // orientation
+ data << float(0);
+ data << float(0);
+ break;
case 3: // not used currently
data << uint64(0); // probably target guid
break;
@@ -738,6 +668,167 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
{
DEBUG_LOG("DealDamage: victim just died");
Kill(pVictim, durabilityLoss);
+
+ /*// find player: owner of controlled `this` or `this` itself maybe
+ Player *player = GetCharmerOrOwnerPlayerOrPlayerItself();
+
+ if(pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->GetLootRecipient())
+ player = ((Creature*)pVictim)->GetLootRecipient();
+ // Reward player, his pets, and group/raid members
+ // call kill spell proc event (before real die and combat stop to triggering auras removed at death/combat stop)
+ if(player && player!=pVictim)
+ {
+ player->RewardPlayerAndGroupAtKill(pVictim);
+ player->ProcDamageAndSpell(pVictim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_EX_NONE, 0);
+ }
+
+ DEBUG_LOG("DealDamageAttackStop");
+
+ // stop combat
+ pVictim->CombatStop();
+ pVictim->getHostilRefManager().deleteReferences();
+
+ bool damageFromSpiritOfRedemtionTalent = spellProto && spellProto->Id == 27795;
+
+ // if talent known but not triggered (check priest class for speedup check)
+ Aura* spiritOfRedemtionTalentReady = NULL;
+ if( !damageFromSpiritOfRedemtionTalent && // not called from SPELL_AURA_SPIRIT_OF_REDEMPTION
+ pVictim->GetTypeId()==TYPEID_PLAYER && pVictim->getClass()==CLASS_PRIEST )
+ {
+ AuraList const& vDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
+ for(AuraList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr)
+ {
+ if((*itr)->GetSpellProto()->SpellIconID==1654)
+ {
+ spiritOfRedemtionTalentReady = *itr;
+ break;
+ }
+ }
+ }
+
+ DEBUG_LOG("SET JUST_DIED");
+ if(!spiritOfRedemtionTalentReady)
+ pVictim->setDeathState(JUST_DIED);
+
+ DEBUG_LOG("DealDamageHealth1");
+
+ if(spiritOfRedemtionTalentReady)
+ {
+ // save value before aura remove
+ uint32 ressSpellId = pVictim->GetUInt32Value(PLAYER_SELF_RES_SPELL);
+ if(!ressSpellId)
+ ressSpellId = ((Player*)pVictim)->GetResurrectionSpellId();
+
+ //Remove all expected to remove at death auras (most important negative case like DoT or periodic triggers)
+ pVictim->RemoveAllAurasOnDeath();
+
+ // restore for use at real death
+ pVictim->SetUInt32Value(PLAYER_SELF_RES_SPELL,ressSpellId);
+
+ // FORM_SPIRITOFREDEMPTION and related auras
+ pVictim->CastSpell(pVictim,27827,true,NULL,spiritOfRedemtionTalentReady);
+ }
+ else
+ pVictim->SetHealth(0);
+
+ // remember victim PvP death for corpse type and corpse reclaim delay
+ // at original death (not at SpiritOfRedemtionTalent timeout)
+ if( pVictim->GetTypeId()==TYPEID_PLAYER && !damageFromSpiritOfRedemtionTalent )
+ ((Player*)pVictim)->SetPvPDeath(player!=NULL);
+
+ // Call KilledUnit for creatures
+ if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->AI())
+ ((Creature*)this)->AI()->KilledUnit(pVictim);
+
+ // achievement stuff
+ if ( pVictim->GetTypeId() == TYPEID_PLAYER)
+ {
+ if(GetTypeId() == TYPEID_UNIT)
+ ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry());
+ else if(GetTypeId() == TYPEID_PLAYER)
+ ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1);
+ }
+
+ // 10% durability loss on death
+ // clean InHateListOf
+ if (pVictim->GetTypeId() == TYPEID_PLAYER)
+ {
+ // only if not player and not controlled by player pet. And not at BG
+ if (durabilityLoss && !player && !((Player*)pVictim)->InBattleGround())
+ {
+ DEBUG_LOG("We are dead, loosing 10 percents durability");
+ ((Player*)pVictim)->DurabilityLossAll(0.10f,false);
+ // durability lost message
+ WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0);
+ ((Player*)pVictim)->GetSession()->SendPacket(&data);
+ }
+ }
+ else // creature died
+ {
+ DEBUG_LOG("DealDamageNotPlayer");
+ Creature *cVictim = (Creature*)pVictim;
+
+ if(!cVictim->isPet())
+ {
+ cVictim->DeleteThreatList();
+ cVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ }
+ // Call creature just died function
+ if (cVictim->AI())
+ cVictim->AI()->JustDied(this);
+
+ // Dungeon specific stuff, only applies to players killing creatures
+ if(cVictim->GetInstanceId())
+ {
+ Map *m = cVictim->GetMap();
+ Player *creditedPlayer = GetCharmerOrOwnerPlayerOrPlayerItself();
+ // TODO: do instance binding anyway if the charmer/owner is offline
+
+ if(m->IsDungeon() && creditedPlayer)
+ {
+ if(m->IsRaid() || m->IsHeroic())
+ {
+ if(cVictim->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
+ ((InstanceMap *)m)->PermBindAllPlayers(creditedPlayer);
+ }
+ else
+ {
+ // the reset time is set but not added to the scheduler
+ // until the players leave the instance
+ time_t resettime = cVictim->GetRespawnTimeEx() + 2 * HOUR;
+ if(InstanceSave *save = sInstanceSaveManager.GetInstanceSave(cVictim->GetInstanceId()))
+ if(save->GetResetTime() < resettime) save->SetResetTime(resettime);
+ }
+ }
+ }
+ }
+
+ // last damage from non duel opponent or opponent controlled creature
+ if(duel_hasEnded)
+ {
+ assert(pVictim->GetTypeId()==TYPEID_PLAYER);
+ Player *he = (Player*)pVictim;
+
+ assert(he->duel);
+
+ he->duel->opponent->CombatStopWithPets(true);
+ he->CombatStopWithPets(true);
+
+ he->DuelComplete(DUEL_INTERUPTED);
+ }
+
+ // battleground things (do this at the end, so the death state flag will be properly set to handle in the bg->handlekill)
+ if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->InBattleGround())
+ {
+ Player *killed = ((Player*)pVictim);
+ if(BattleGround *bg = killed->GetBattleGround())
+ if(player)
+ bg->HandleKillPlayer(killed, player);
+ //later we can add support for creature->player kills here i'm
+ //not sure, but i guess those kills also get counted in av
+ //else if(GetTypeId() == TYPEID_UNIT)
+ // bg->HandleKillPlayer(killed,(Creature*)this);
+ }*/
}
else // if (health <= damage)
{
@@ -768,7 +859,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
//if (!spellProto || !(spellProto->AuraInterruptFlags&AURA_INTERRUPT_FLAG_DIRECT_DAMAGE))
pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE, spellProto ? spellProto->Id : 0);
}
-
if (pVictim->GetTypeId() != TYPEID_PLAYER)
{
if(spellProto && IsDamageToThreatSpell(spellProto))
@@ -835,7 +925,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if(spell->getState() == SPELL_STATE_PREPARING)
{
uint32 interruptFlags = spell->m_spellInfo->InterruptFlags;
- if(interruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE)
+ if(interruptFlags & SPELL_INTERRUPT_FLAG_ABORT_ON_DMG)
pVictim->InterruptNonMeleeSpells(false);
else if(interruptFlags & SPELL_INTERRUPT_FLAG_PUSH_BACK)
spell->Delayed();
@@ -1074,419 +1164,6 @@ void Unit::CastSpell(GameObject *go, uint32 spellId, bool triggered, Item *castI
spell->prepare(&targets, triggeredByAura);
}
-/*
-void Unit::DealFlatDamage(Unit *pVictim, SpellEntry const *spellInfo, uint32 *damage, CleanDamage *cleanDamage, bool *crit, bool isTriggeredSpell)
-{
- // TODO this in only generic way, check for exceptions
- DEBUG_LOG("DealFlatDamage (BEFORE) >> DMG:%u", *damage);
-
- // Per-damage class calculation
- switch (spellInfo->DmgClass)
- {
- // Melee and Ranged Spells
- case SPELL_DAMAGE_CLASS_RANGED:
- case SPELL_DAMAGE_CLASS_MELEE:
- {
- // Calculate physical outcome
- MeleeHitOutcome outcome = RollPhysicalOutcomeAgainst(pVictim, BASE_ATTACK, spellInfo);
-
- //Used to store the Hit Outcome
- cleanDamage->hitOutCome = outcome;
-
- // Return miss/evade first (sends miss message)
- switch(outcome)
- {
- case MELEE_HIT_EVADE:
- {
- SendAttackStateUpdate(HITINFO_MISS, pVictim, 1, GetSpellSchoolMask(spellInfo), 0, 0,0,VICTIMSTATE_EVADES,0);
- *damage = 0;
- return;
- }
- case MELEE_HIT_MISS:
- {
- SendAttackStateUpdate(HITINFO_MISS, pVictim, 1, GetSpellSchoolMask(spellInfo), 0, 0,0,VICTIMSTATE_NORMAL,0);
- *damage = 0;
-
- if(GetTypeId()== TYPEID_PLAYER)
- ((Player*)this)->UpdateWeaponSkill(BASE_ATTACK);
-
- CastMeleeProcDamageAndSpell(pVictim,0,GetSpellSchoolMask(spellInfo),BASE_ATTACK,MELEE_HIT_MISS,spellInfo,isTriggeredSpell);
- return;
- }
- }
-
- // Hitinfo, Victimstate
- uint32 hitInfo = HITINFO_NORMALSWING;
- VictimState victimState = VICTIMSTATE_NORMAL;
-
- // Physical Damage
- if ( GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_NORMAL )
- {
- // apply spellmod to Done damage
- if(Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_DAMAGE, *damage);
-
- //Calculate armor mitigation
- uint32 damageAfterArmor = CalcArmorReducedDamage(pVictim, *damage);
-
- // random durability for main hand weapon (ABSORB)
- if(damageAfterArmor < *damage)
- if(pVictim->GetTypeId() == TYPEID_PLAYER)
- if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_ABSORB)))
- ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EquipmentSlots(urand(EQUIPMENT_SLOT_START,EQUIPMENT_SLOT_BACK)));
-
- cleanDamage->damage += *damage - damageAfterArmor;
- *damage = damageAfterArmor;
- }
- // Magical Damage
- else
- {
- // Calculate damage bonus
- *damage = SpellDamageBonus(pVictim, spellInfo, *damage, SPELL_DIRECT_DAMAGE);
- }
-
- // Classify outcome
- switch (outcome)
- {
- case MELEE_HIT_BLOCK_CRIT:
- case MELEE_HIT_CRIT:
- {
- uint32 bonusDmg = *damage;
-
- // Apply crit_damage bonus
- if(Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, bonusDmg);
-
- uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
- AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS);
- for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i)
- if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
- bonusDmg = uint32(bonusDmg * ((*i)->GetModifierValue()+100.0f)/100.0f);
-
- *damage += bonusDmg;
-
- // Resilience - reduce crit damage
- if (pVictim->GetTypeId()==TYPEID_PLAYER)
- {
- uint32 resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(*damage);
- cleanDamage->damage += resilienceReduction;
- *damage -= resilienceReduction;
- }
-
- *crit = true;
- hitInfo |= HITINFO_CRITICALHIT;
-
- ModifyAuraState(AURA_STATE_CRIT, true);
- StartReactiveTimer( REACTIVE_CRIT );
-
- if(getClass()==CLASS_HUNTER)
- {
- ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true);
- StartReactiveTimer( REACTIVE_HUNTER_CRIT );
- }
-
- if ( outcome == MELEE_HIT_BLOCK_CRIT )
- {
- uint32 blocked_amount = uint32(pVictim->GetShieldBlockValue());
- if (blocked_amount >= *damage)
- {
- hitInfo |= HITINFO_SWINGNOHITSOUND;
- victimState = VICTIMSTATE_BLOCKS;
- cleanDamage->damage += *damage; // To Help Calculate Rage
- *damage = 0;
- }
- else
- {
- // To Help Calculate Rage
- cleanDamage->damage += blocked_amount;
- *damage = *damage - blocked_amount;
- }
-
- pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true);
- pVictim->StartReactiveTimer( REACTIVE_DEFENSE );
-
- if(pVictim->GetTypeId() == TYPEID_PLAYER)
- {
- // Update defense
- ((Player*)pVictim)->UpdateDefense();
-
- // random durability for main hand weapon (BLOCK)
- if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK)))
- ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND);
- }
- }
- break;
- }
- case MELEE_HIT_PARRY:
- {
- cleanDamage->damage += *damage; // To Help Calculate Rage
- *damage = 0;
- victimState = VICTIMSTATE_PARRY;
-
- // Counter-attack ( explained in Unit::DoAttackDamage() )
- if(pVictim->GetTypeId()==TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN) )
- {
- // Get attack timers
- float offtime = float(pVictim->getAttackTimer(OFF_ATTACK));
- float basetime = float(pVictim->getAttackTimer(BASE_ATTACK));
-
- // Reduce attack time
- if (pVictim->haveOffhandWeapon() && offtime < basetime)
- {
- float percent20 = pVictim->GetAttackTime(OFF_ATTACK) * 0.20;
- float percent60 = 3 * percent20;
- if(offtime > percent20 && offtime <= percent60)
- {
- pVictim->setAttackTimer(OFF_ATTACK, uint32(percent20));
- }
- else if(offtime > percent60)
- {
- offtime -= 2 * percent20;
- pVictim->setAttackTimer(OFF_ATTACK, uint32(offtime));
- }
- }
- else
- {
- float percent20 = pVictim->GetAttackTime(BASE_ATTACK) * 0.20;
- float percent60 = 3 * percent20;
- if(basetime > percent20 && basetime <= percent60)
- {
- pVictim->setAttackTimer(BASE_ATTACK, uint32(percent20));
- }
- else if(basetime > percent60)
- {
- basetime -= 2 * percent20;
- pVictim->setAttackTimer(BASE_ATTACK, uint32(basetime));
- }
- }
- }
-
- if(pVictim->GetTypeId() == TYPEID_PLAYER)
- {
- // Update victim defense ?
- ((Player*)pVictim)->UpdateDefense();
-
- // random durability for main hand weapon (PARRY)
- if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_PARRY)))
- ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_MAINHAND);
- }
-
- // Set parry flags
- pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED);
-
- // Mongoose bite - set only Counterattack here
- if (pVictim->getClass() == CLASS_HUNTER)
- {
- pVictim->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true);
- pVictim->StartReactiveTimer( REACTIVE_HUNTER_PARRY );
- }
- else
- {
- pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true);
- pVictim->StartReactiveTimer( REACTIVE_DEFENSE );
- }
- break;
- }
- case MELEE_HIT_DODGE:
- {
- if(pVictim->GetTypeId() == TYPEID_PLAYER)
- ((Player*)pVictim)->UpdateDefense();
-
- cleanDamage->damage += *damage; // To Help Calculate Rage
- *damage = 0;
- hitInfo |= HITINFO_SWINGNOHITSOUND;
- victimState = VICTIMSTATE_DODGE;
-
- // Set dodge flags
- pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED);
-
- // Overpower
- if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR)
- {
- ((Player*)this)->AddComboPoints(pVictim, 1);
- StartReactiveTimer( REACTIVE_OVERPOWER );
- }
-
- // Riposte
- if (pVictim->getClass() != CLASS_ROGUE)
- {
- pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true);
- pVictim->StartReactiveTimer( REACTIVE_DEFENSE );
- }
- break;
- }
- case MELEE_HIT_BLOCK:
- {
- uint32 blocked_amount = uint32(pVictim->GetShieldBlockValue());
- if (blocked_amount >= *damage)
- {
- hitInfo |= HITINFO_SWINGNOHITSOUND;
- victimState = VICTIMSTATE_BLOCKS;
- cleanDamage->damage += *damage; // To Help Calculate Rage
- *damage = 0;
- }
- else
- {
- // To Help Calculate Rage
- cleanDamage->damage += blocked_amount;
- *damage = *damage - blocked_amount;
- }
-
- pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true);
- pVictim->StartReactiveTimer( REACTIVE_DEFENSE );
-
- if(pVictim->GetTypeId() == TYPEID_PLAYER)
- {
- // Update defense
- ((Player*)pVictim)->UpdateDefense();
-
- // random durability for main hand weapon (BLOCK)
- if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK)))
- ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND);
- }
- break;
- }
- case MELEE_HIT_EVADE: // already processed early
- case MELEE_HIT_MISS: // already processed early
- case MELEE_HIT_GLANCING:
- case MELEE_HIT_CRUSHING:
- case MELEE_HIT_NORMAL:
- break;
- }
-
- // do all damage=0 cases here
- if(*damage == 0)
- CastMeleeProcDamageAndSpell(pVictim,0,GetSpellSchoolMask(spellInfo),BASE_ATTACK,outcome,spellInfo,isTriggeredSpell);
-
- break;
- }
- // Magical Attacks
- case SPELL_DAMAGE_CLASS_NONE:
- case SPELL_DAMAGE_CLASS_MAGIC:
- {
- // Calculate damage bonus
- *damage = SpellDamageBonus(pVictim, spellInfo, *damage, SPELL_DIRECT_DAMAGE);
-
- *crit = isSpellCrit(pVictim, spellInfo, GetSpellSchoolMask(spellInfo), BASE_ATTACK);
- if (*crit)
- {
- *damage = SpellCriticalBonus(spellInfo, *damage, pVictim);
-
- // Resilience - reduce crit damage
- if (pVictim && pVictim->GetTypeId()==TYPEID_PLAYER)
- {
- uint32 damage_reduction = ((Player *)pVictim)->GetSpellCritDamageReduction(*damage);
- if(*damage > damage_reduction)
- *damage -= damage_reduction;
- else
- *damage = 0;
- }
-
- cleanDamage->hitOutCome = MELEE_HIT_CRIT;
- }
- // spell proc all magic damage==0 case in this function
- if(*damage == 0)
- {
- // Procflags
- uint32 procAttacker = PROC_FLAG_HIT_SPELL;
- uint32 procVictim = (PROC_FLAG_STRUCK_SPELL|PROC_FLAG_TAKE_DAMAGE);
-
- ProcDamageAndSpell(pVictim, procAttacker, procVictim, 0, GetSpellSchoolMask(spellInfo), spellInfo, isTriggeredSpell);
- }
-
- break;
- }
- }
-
- // TODO this in only generic way, check for exceptions
- DEBUG_LOG("DealFlatDamage (AFTER) >> DMG:%u", *damage);
-}
-
-uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool isTriggeredSpell, bool useSpellDamage)
-{
- if(!this || !pVictim)
- return 0;
- if(!isAlive() || !pVictim->isAlive())
- return 0;
-
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID);
- if(!spellInfo)
- return 0;
-
- CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL);
- bool crit = false;
-
- if (useSpellDamage)
- DealFlatDamage(pVictim, spellInfo, &damage, &cleanDamage, &crit, isTriggeredSpell);
-
- // If we actually dealt some damage (spell proc's for 0 damage (normal and magic) called in DealFlatDamage)
- if(damage > 0)
- {
- // Calculate absorb & resists
- uint32 absorb = 0;
- uint32 resist = 0;
-
- CalcAbsorbResist(pVictim,GetSpellSchoolMask(spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
-
- //No more damage left, target absorbed and/or resisted all damage
- if (damage > absorb + resist)
- damage -= absorb + resist; //Remove Absorbed and Resisted from damage actually dealt
- else
- {
- uint32 HitInfo = HITINFO_SWINGNOHITSOUND;
-
- if (absorb)
- HitInfo |= HITINFO_ABSORB;
- if (resist)
- {
- HitInfo |= HITINFO_RESIST;
- ProcDamageAndSpell(pVictim, PROC_FLAG_TARGET_RESISTS, PROC_FLAG_RESIST_SPELL, 0, GetSpellSchoolMask(spellInfo), spellInfo,isTriggeredSpell);
- }
-
- //Send resist
- SendAttackStateUpdate(HitInfo, pVictim, 1, GetSpellSchoolMask(spellInfo), damage, absorb,resist,VICTIMSTATE_NORMAL,0);
- return 0;
- }
-
- // Deal damage done
- damage = DealDamage(pVictim, damage, &cleanDamage, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellInfo), spellInfo, true);
-
- // Send damage log
- sLog.outDetail("SpellNonMeleeDamageLog: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u,absorb is %u,resist is %u",
- GetGUIDLow(), GetTypeId(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damage, spellID, absorb,resist);
-
- // Actual log sent to client
- SendSpellNonMeleeDamageLog(pVictim, spellID, damage + resist, GetSpellSchoolMask(spellInfo), absorb, resist, false, 0, crit);
-
- // Procflags
- uint32 procAttacker = PROC_FLAG_HIT_SPELL;
- uint32 procVictim = (PROC_FLAG_STRUCK_SPELL|PROC_FLAG_TAKE_DAMAGE);
-
- if (crit)
- {
- procAttacker |= PROC_FLAG_CRIT_SPELL;
- procVictim |= PROC_FLAG_STRUCK_CRIT_SPELL;
- }
-
- ProcDamageAndSpell(pVictim, procAttacker, procVictim, damage, GetSpellSchoolMask(spellInfo), spellInfo, isTriggeredSpell);
-
- return damage;
- }
- else
- {
- // all spell proc for 0 normal and magic damage called in DealFlatDamage
-
- //Check for rage
- if(cleanDamage.damage)
- // Rage from damage received.
- if(pVictim->GetTypeId() == TYPEID_PLAYER && (pVictim->getPowerType() == POWER_RAGE))
- ((Player*)pVictim)->RewardRage(cleanDamage.damage, 0, false);
-
- return 0;
- }
-}
-*/
-
// Obsolete func need remove, here only for comotability vs another patches
uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool isTriggeredSpell, bool useSpellDamage)
{
@@ -1575,7 +1252,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 dama
if (crit)
{
damageInfo->HitInfo|= SPELL_HIT_TYPE_CRIT;
- damage = SpellCriticalBonus(spellInfo, damage, pVictim);
+ damage = SpellCriticalDamageBonus(spellInfo, damage, pVictim);
// Resilience - reduce crit damage
if (pVictim->GetTypeId()==TYPEID_PLAYER)
damage -= ((Player*)pVictim)->GetSpellCritDamageReduction(damage);
@@ -1585,19 +1262,63 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 dama
}
if( damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL )
- damage = CalcArmorReducedDamage(pVictim, damage);
+ damage = CalcArmorReducedDamage(pVictim, damage, spellInfo, attackType);
// Calculate absorb resist
if(damage > 0)
{
- CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist);
- damage-= damageInfo->absorb + damageInfo->resist;
+ // lookup absorb/resist ignore auras on caster for spell
+ bool ignore = false;
+ Unit::AuraList const& ignoreAbsorb = GetAurasByType(SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL);
+ for(Unit::AuraList::const_iterator i = ignoreAbsorb.begin(); i != ignoreAbsorb.end(); ++i)
+ if ((*i)->isAffectedOnSpell(spellInfo))
+ {
+ ignore = true;
+ break;
+ }
+
+ if (!ignore)
+ {
+ CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist);
+ damage-= damageInfo->absorb + damageInfo->resist;
+ }
}
else
damage = 0;
damageInfo->damage = damage;
}
+int32 Unit::GetIgnoredArmorMultiplier(SpellEntry const *spellInfo, WeaponAttackType attackType)
+{
+ if (GetTypeId() != TYPEID_PLAYER)
+ return 0;
+ //check if spell uses weapon
+ if (spellInfo && spellInfo->EquippedItemClass!=ITEM_CLASS_WEAPON)
+ return 0;
+ Item *item = NULL;
+ if(attackType == BASE_ATTACK)
+ item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
+ else if (attackType == OFF_ATTACK)
+ item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
+ else if (attackType == RANGED_ATTACK)
+ item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
+ if (!item)
+ return 0;
+
+ AuraList const& armAuras = GetAurasByType(SPELL_AURA_MOD_WEAPONTYPE_IGNORE_TARGET_RESISTANCE);
+ int32 armorIgnored = 0;
+ for(AuraList::const_iterator i = armAuras.begin();i != armAuras.end(); ++i)
+ {
+ if (!((*i)->GetSpellProto()->EquippedItemClass==item->GetProto()->Class
+ && (*i)->GetSpellProto()->EquippedItemSubClassMask & (1<<item->GetProto()->SubClass)))
+ continue;
+
+ if((*i)->GetModifier()->m_amount)
+ armorIgnored += (*i)->GetModifier()->m_amount;
+ }
+ return (-armorIgnored);
+}
+
void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
{
if (damageInfo==0)
@@ -1627,20 +1348,6 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
return;
}
- // update at damage Judgement aura duration that applied by attacker at victim
- if(damageInfo->damage && spellProto->Id == 35395)
- {
- AuraMap& vAuras = pVictim->GetAuras();
- for(AuraMap::iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr)
- {
- SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
- if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID()))
- {
- (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
- (*itr).second->UpdateAuraDuration();
- }
- }
- }
// Call default DealDamage
CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, MELEE_HIT_NORMAL);
DealDamage(pVictim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss);
@@ -1694,7 +1401,7 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da
}
// Physical Immune check
- if(damageInfo->target->IsImmunedToDamage(SpellSchoolMask(damageInfo->damageSchoolMask),true))
+ if(damageInfo->target->IsImmunedToDamage(SpellSchoolMask(damageInfo->damageSchoolMask)))
{
damageInfo->HitInfo |= HITINFO_NORMALSWING;
damageInfo->TargetState = VICTIMSTATE_IS_IMMUNE;
@@ -1708,7 +1415,7 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da
// Add melee damage bonus
MeleeDamageBonus(damageInfo->target, &damage, damageInfo->attackType);
// Calculate armor reduction
- damageInfo->damage = CalcArmorReducedDamage(damageInfo->target, damage);
+ damageInfo->damage = CalcArmorReducedDamage(damageInfo->target, damage, NULL , damageInfo->attackType);
damageInfo->cleanDamage += damage - damageInfo->damage;
damageInfo->hitOutCome = RollMeleeOutcomeAgainst(damageInfo->target, damageInfo->attackType);
@@ -1796,6 +1503,7 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da
case MELEE_HIT_BLOCK:
{
damageInfo->TargetState = VICTIMSTATE_NORMAL;
+ damageInfo->HitInfo |= HITINFO_BLOCK;
damageInfo->procEx|=PROC_EX_BLOCK;
damageInfo->blocked_amount = damageInfo->target->GetShieldBlockValue();
if (damageInfo->blocked_amount >= damageInfo->damage)
@@ -1943,21 +1651,6 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
CastSpell(pVictim, 1604, true);
}
- // update at damage Judgement aura duration that applied by attacker at victim
- if(damageInfo->damage)
- {
- AuraMap& vAuras = pVictim->GetAuras();
- for(AuraMap::iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr)
- {
- SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
- if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID()))
- {
- (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
- (*itr).second->UpdateAuraDuration();
- }
- }
- }
-
// If not miss
if (!(damageInfo->HitInfo & HITINFO_MISS))
{
@@ -1987,11 +1680,13 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
//CalcAbsorbResist(pVictim, SpellSchools(spellProto->School), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
//damage-=absorb + resist;
- WorldPacket data(SMSG_SPELLDAMAGESHIELD,(8+8+4+4));
+ WorldPacket data(SMSG_SPELLDAMAGESHIELD,(8+8+4+4+4+4));
data << uint64(pVictim->GetGUID());
data << uint64(GetGUID());
+ data << uint32(spellProto->Id);
+ data << uint32(damage); // Damage
+ data << uint32(0); // Overkill
data << uint32(spellProto->SchoolMask);
- data << uint32(damage);
pVictim->SendMessageToSet(&data, true );
pVictim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellProto), spellProto, true);
@@ -2010,28 +1705,35 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
void Unit::HandleEmoteCommand(uint32 anim_id)
{
WorldPacket data( SMSG_EMOTE, 12 );
- data << anim_id << GetGUID();
- WPAssert(data.size() == 12);
-
+ data << uint32(anim_id);
+ data << uint64(GetGUID());
SendMessageToSet(&data, true);
}
-uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage)
+uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType)
{
uint32 newdamage = 0;
float armor = pVictim->GetArmor();
// Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
armor += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL);
- if (armor<0.0f) armor=0.0f;
+ armor *= float((GetIgnoredArmorMultiplier(spellInfo, attackType)+100.0f)/100.0f);
+ if(spellInfo)
+ if(Player *modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor);
+
+ // Apply Player CR_ARMOR_PENETRATION rating
+ if (GetTypeId()==TYPEID_PLAYER)
+ armor *= 1.0f - ((Player*)this)->GetRatingBonusValue(CR_ARMOR_PENETRATION) / 100.0f;
+
+ if (armor < 0.0f) armor=0.0f;
+
+ float levelModifier = getLevel();
+ if ( levelModifier > 59 )
+ levelModifier = levelModifier + (4.5f * (levelModifier-59));
- float tmpvalue = 0.0f;
- if(getLevel() <= 59) //Level 1-59
- tmpvalue = armor / (armor + 400.0f + 85.0f * getLevel());
- else if(getLevel() < 70) //Level 60-69
- tmpvalue = armor / (armor - 22167.5f + 467.5f * getLevel());
- else //Level 70+
- tmpvalue = armor / (armor + 10557.5f);
+ float tmpvalue = 0.1f * armor / (8.5f * levelModifier + 40);
+ tmpvalue = tmpvalue/(1.0f + tmpvalue);
if(tmpvalue < 0.0f)
tmpvalue = 0.0f;
@@ -2084,89 +1786,236 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
int32 RemainingDamage = damage - *resist;
+ // Get unit state (need for some absorb check)
+ uint32 unitflag = pVictim->GetUInt32Value(UNIT_FIELD_FLAGS);
+ // Reflect damage spells (not cast any damage spell in aura lookup)
+ uint32 reflectSpell = 0;
+ int32 reflectDamage = 0;
+ // Need remove expired auras after
+ bool existExpired = false;
// absorb without mana cost
- int32 reflectDamage = 0;
- Aura* reflectAura = NULL;
AuraList const& vSchoolAbsorb = pVictim->GetAurasByType(SPELL_AURA_SCHOOL_ABSORB);
- for(AuraList::const_iterator i = vSchoolAbsorb.begin(), next; i != vSchoolAbsorb.end() && RemainingDamage > 0; i = next)
+ for(AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end() && RemainingDamage > 0; ++i)
{
- next = i; ++next;
-
- if (((*i)->GetModifier()->m_miscvalue & schoolMask)==0)
+ Modifier* mod = (*i)->GetModifier();
+ if (!(mod->m_miscvalue & schoolMask))
continue;
- // Cheat Death
- if((*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && (*i)->GetSpellProto()->SpellIconID == 2109)
+ SpellEntry const* spellProto = (*i)->GetSpellProto();
+
+ // Max Amount can be absorbed by this aura
+ int32 currentAbsorb = mod->m_amount;
+
+ // Found empty aura (umpossible but..)
+ if (currentAbsorb <=0)
{
- if (((Player*)pVictim)->HasSpellCooldown(31231))
- continue;
- if (pVictim->GetHealth() <= RemainingDamage)
+ existExpired = true;
+ continue;
+ }
+ // Handle custom absorb auras
+ // TODO: try find better way
+ switch(spellProto->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
{
- int32 chance = (*i)->GetModifier()->m_amount;
- if (roll_chance_i(chance))
+ // Astral Shift
+ if (spellProto->SpellIconID == 3066)
{
- pVictim->CastSpell(pVictim,31231,true);
- ((Player*)pVictim)->AddSpellCooldown(31231,0,time(NULL)+60);
-
- // with health > 10% lost health until health==10%, in other case no losses
- uint32 health10 = pVictim->GetMaxHealth()/10;
- RemainingDamage = pVictim->GetHealth() > health10 ? pVictim->GetHealth() - health10 : 0;
+ //reduces all damage taken while stun, fear or silence
+ if (unitflag & (UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED))
+ RemainingDamage -= RemainingDamage * currentAbsorb / 100;
+ continue;
+ }
+ // Nerves of Steel
+ if (spellProto->SpellIconID == 2115)
+ {
+ // while affected by Stun and Fear
+ if (unitflag&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING))
+ RemainingDamage -= RemainingDamage * currentAbsorb / 100;
+ continue;
+ }
+ // Spell Deflection
+ if (spellProto->SpellIconID == 3006)
+ {
+ // You have a chance equal to your Parry chance
+ if (damagetype == DIRECT_DAMAGE && // Only for direct damage
+ roll_chance_f(pVictim->GetUnitParryChance())) // Roll chance
+ RemainingDamage -= RemainingDamage * currentAbsorb / 100;
+ continue;
+ }
+ // Reflective Shield (Lady Malande boss)
+ if (spellProto->Id == 41475)
+ {
+ if(RemainingDamage < currentAbsorb)
+ reflectDamage = RemainingDamage / 2;
+ else
+ reflectDamage = currentAbsorb / 2;
+ reflectSpell = 33619;
+ break;
+ }
+ if (spellProto->Id == 39228 || // Argussian Compass
+ spellProto->Id == 60218) // Essence of Gossamer
+ {
+ // Max absorb stored in 1 dummy effect
+ if (spellProto->EffectBasePoints[1] < currentAbsorb)
+ currentAbsorb = spellProto->EffectBasePoints[1];
+ break;
}
+ break;
}
- continue;
- }
-
- int32 currentAbsorb;
-
- //Reflective Shield
- if ((pVictim != this) && (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && (*i)->GetSpellProto()->SpellFamilyFlags == 0x1)
- {
- if(Unit* caster = (*i)->GetCaster())
+ case SPELLFAMILY_DRUID:
{
- AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for(AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k)
+ // Primal Tenacity
+ if (spellProto->SpellIconID == 2253)
{
- switch((*k)->GetModifier()->m_miscvalue)
+ //reduces all damage taken while Stunned
+ if (unitflag & UNIT_FLAG_STUNNED)
+ RemainingDamage -= RemainingDamage * currentAbsorb / 100;
+ continue;
+ }
+ break;
+ }
+ case SPELLFAMILY_ROGUE:
+ {
+ // Cheat Death
+ if(spellProto->SpellIconID == 2109)
+ {
+ if (pVictim->GetTypeId()==TYPEID_PLAYER && // Only players
+ pVictim->GetHealth() <= RemainingDamage && // Only if damage kill
+ !((Player*)pVictim)->HasSpellCooldown(31231) && // Only if no cooldown
+ roll_chance_i(currentAbsorb)) // Only if roll
{
- case 5065: // Rank 1
- case 5064: // Rank 2
- case 5063: // Rank 3
- case 5062: // Rank 4
- case 5061: // Rank 5
- {
- if(RemainingDamage >= (*i)->GetModifier()->m_amount)
- reflectDamage = (*i)->GetModifier()->m_amount * (*k)->GetModifier()->m_amount/100;
- else
- reflectDamage = (*k)->GetModifier()->m_amount * RemainingDamage/100;
- reflectAura = *i;
-
- } break;
- default: break;
+ pVictim->CastSpell(pVictim,31231,true);
+ ((Player*)pVictim)->AddSpellCooldown(31231,0,time(NULL)+60);
+ // with health > 10% lost health until health==10%, in other case no losses
+ uint32 health10 = pVictim->GetMaxHealth()/10;
+ RemainingDamage = pVictim->GetHealth() > health10 ? pVictim->GetHealth() - health10 : 0;
}
-
- if(reflectDamage)
+ continue;
+ }
+ break;
+ }
+ case SPELLFAMILY_PRIEST:
+ {
+ // Reflective Shield
+ if (spellProto->SpellFamilyFlags == 0x1)
+ {
+ if (pVictim == this)
+ break;
+ Unit* caster = (*i)->GetCaster();
+ if (!caster)
break;
+ int32 reflectDamage = 0;
+ AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_DUMMY);
+ for(AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k)
+ {
+ switch((*k)->GetModifier()->m_miscvalue)
+ {
+ case 5065: // Rank 1
+ case 5064: // Rank 2
+ case 5063: // Rank 3
+ {
+ if(RemainingDamage >= currentAbsorb)
+ reflectDamage = (*k)->GetModifier()->m_amount * currentAbsorb/100;
+ else
+ reflectDamage = (*k)->GetModifier()->m_amount * RemainingDamage/100;
+ reflectSpell = 33619;
+ } break;
+ default: break;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ case SPELLFAMILY_SHAMAN:
+ {
+ // Astral Shift
+ if (spellProto->SpellIconID == 3066)
+ {
+ //reduces all damage taken while stun, fear or silence
+ if (unitflag & (UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED))
+ RemainingDamage -= RemainingDamage * currentAbsorb / 100;
+ continue;
+ }
+ break;
+ }
+ case SPELLFAMILY_DEATHKNIGHT:
+ {
+ // Shadow of Death
+ if (spellProto->SpellIconID == 1958)
+ {
+ // TODO: absorb only while transform
+ continue;
+ }
+ // Anti-Magic Shell (on self)
+ if (spellProto->Id == 48707)
+ {
+ // damage absorbed by Anti-Magic Shell energizes the DK with additional runic power.
+ // This, if I'm not mistaken, shows that we get back ~2% of the absorbed damage as runic power.
+ int32 absorbed = RemainingDamage * currentAbsorb / 100;
+ int32 regen = absorbed * 2 / 10;
+ pVictim->CastCustomSpell(pVictim, 49088, &regen, 0, 0, true, 0, *i);
+ RemainingDamage -= absorbed;
+ continue;
}
+ // Anti-Magic Shell (on single party/raid member)
+ if (spellProto->Id == 50462)
+ {
+ RemainingDamage -= RemainingDamage * currentAbsorb / 100;
+ continue;
+ }
+ // Anti-Magic Zone
+ if (spellProto->Id == 50461)
+ {
+ Unit* caster = (*i)->GetCaster();
+ if (!caster)
+ continue;
+ int32 absorbed = RemainingDamage * currentAbsorb / 100;
+ int32 canabsorb = caster->GetHealth();
+ if (canabsorb < absorbed)
+ absorbed = canabsorb;
+ DealDamage(caster, absorbed, NULL, damagetype, schoolMask, 0, false);
+ RemainingDamage -= absorbed;
+ continue;
+ }
+ break;
}
+ default:
+ break;
}
- if (RemainingDamage >= (*i)->GetModifier()->m_amount)
- {
- currentAbsorb = (*i)->GetModifier()->m_amount;
- pVictim->RemoveAurasDueToSpell((*i)->GetId());
- next = vSchoolAbsorb.begin();
- }
- else
- {
+ // currentAbsorb - damage can be absorbed by shield
+ // If need absorb less damage
+ if (RemainingDamage < currentAbsorb)
currentAbsorb = RemainingDamage;
- (*i)->GetModifier()->m_amount -= RemainingDamage;
- }
RemainingDamage -= currentAbsorb;
+
+ // Reduce shield amount
+ mod->m_amount-=currentAbsorb;
+ // Need remove it later
+ if (mod->m_amount<=0)
+ existExpired = true;
+ }
+
+ // Remove all expired absorb auras
+ if (existExpired)
+ {
+ for(AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end();)
+ {
+ if ((*i)->GetModifier()->m_amount<=0)
+ {
+ pVictim->RemoveAurasDueToSpell((*i)->GetId());
+ i = vSchoolAbsorb.begin();
+ }
+ else
+ ++i;
+ }
}
- // do not cast spells while looping auras; auras can get invalid otherwise
- if (reflectDamage)
- pVictim->CastCustomSpell(this, 33619, &reflectDamage, NULL, NULL, true, NULL, reflectAura);
+ // Cast back reflect damage spell
+ if (reflectSpell)
+ pVictim->CastCustomSpell(this, reflectSpell, &reflectDamage, NULL, NULL, true);
// absorb by mana cost
AuraList const& vManaShield = pVictim->GetAurasByType(SPELL_AURA_MANA_SHIELD);
@@ -2264,407 +2113,6 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
*absorb = damage - RemainingDamage - *resist;
}
-/*
-void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchoolMask damageSchoolMask, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted, bool isTriggeredSpell)
-{
- MeleeHitOutcome outcome;
-
- // If is casted Melee spell, calculate like physical
- if(!spellCasted)
- outcome = RollMeleeOutcomeAgainst (pVictim, attType);
- else
- outcome = RollPhysicalOutcomeAgainst (pVictim, attType, spellCasted);
-
- if(outcome == MELEE_HIT_MISS ||outcome == MELEE_HIT_DODGE ||outcome == MELEE_HIT_BLOCK ||outcome == MELEE_HIT_PARRY)
- pVictim->AddThreat(this, 0.0f);
- switch(outcome)
- {
- case MELEE_HIT_EVADE:
- {
- *hitInfo |= HITINFO_MISS;
- *damage = 0;
- cleanDamage->damage = 0;
- return;
- }
- case MELEE_HIT_MISS:
- {
- *hitInfo |= HITINFO_MISS;
- *damage = 0;
- cleanDamage->damage = 0;
- if(GetTypeId()== TYPEID_PLAYER)
- ((Player*)this)->UpdateWeaponSkill(attType);
- return;
- }
- }
-
- /// If this is a creature and it attacks from behind it has a probability to daze it's victim
- if( (outcome==MELEE_HIT_CRIT || outcome==MELEE_HIT_CRUSHING || outcome==MELEE_HIT_NORMAL || outcome==MELEE_HIT_GLANCING) &&
- GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->GetCharmerOrOwnerGUID() && !pVictim->HasInArc(M_PI, this)
- && pVictim->GetTypeId() == TYPEID_PLAYER)
- {
- // -probability is between 0% and 40%
- // 20% base chance
- float Probability = 20;
-
- //there is a newbie protection, at level 10 just 7% base chance; assuming linear function
- if( pVictim->getLevel() < 30 )
- Probability = 0.65f*pVictim->getLevel()+0.5;
-
- uint32 VictimDefense=pVictim->GetDefenseSkillValue(this);
- uint32 AttackerMeleeSkill=GetUnitMeleeSkill(pVictim);
-
- Probability *= AttackerMeleeSkill/(float)VictimDefense;
-
- if(Probability > 40.0f)
- Probability = 40.0f;
-
- if(roll_chance_f(Probability))
- CastSpell(pVictim, 1604, true);
- }
-
- //Calculate the damage after armor mitigation if SPELL_SCHOOL_NORMAL
- if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL)
- {
- uint32 damageAfterArmor = CalcArmorReducedDamage(pVictim, *damage);
-
- // random durability for main hand weapon (ABSORB)
- if(damageAfterArmor < *damage)
- if(pVictim->GetTypeId() == TYPEID_PLAYER)
- if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_ABSORB)))
- ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EquipmentSlots(urand(EQUIPMENT_SLOT_START,EQUIPMENT_SLOT_BACK)));
-
- cleanDamage->damage += *damage - damageAfterArmor;
- *damage = damageAfterArmor;
- }
-
- if(GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() != CREATURE_TYPE_CRITTER )
- ((Player*)this)->UpdateCombatSkills(pVictim, attType, outcome, false);
-
- if(GetTypeId() != TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
- ((Player*)pVictim)->UpdateCombatSkills(this, attType, outcome, true);
-
- switch (outcome)
- {
- case MELEE_HIT_BLOCK_CRIT:
- case MELEE_HIT_CRIT:
- {
- //*hitInfo = 0xEA;
- // 0xEA
- *hitInfo = HITINFO_CRITICALHIT | HITINFO_NORMALSWING2 | 0x8;
-
- // Crit bonus calc
- uint32 crit_bonus;
- crit_bonus = *damage;
-
- // Apply crit_damage bonus for melee spells
- if (spellCasted)
- {
- if(Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellCasted->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
-
- uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
- AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS);
- for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i)
- if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
- crit_bonus = uint32(crit_bonus * ((*i)->GetModifierValue()+100.0f)/100.0f);
- }
-
- *damage += crit_bonus;
-
- uint32 resilienceReduction = 0;
-
- if(attType == RANGED_ATTACK)
- {
- int32 mod = pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
- *damage = int32((*damage) * float((100.0f + mod)/100.0f));
- // Resilience - reduce crit damage
- if (pVictim->GetTypeId()==TYPEID_PLAYER)
- resilienceReduction = ((Player*)pVictim)->GetRangedCritDamageReduction(*damage);
- }
- else
- {
- int32 mod = pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
- mod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE);
- *damage = int32((*damage) * float((100.0f + mod)/100.0f));
- // Resilience - reduce crit damage
- if (pVictim->GetTypeId()==TYPEID_PLAYER)
- resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(*damage);
- }
-
- *damage -= resilienceReduction;
- cleanDamage->damage += resilienceReduction;
-
- if(GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() != CREATURE_TYPE_CRITTER )
- ((Player*)this)->UpdateWeaponSkill(attType);
-
- ModifyAuraState(AURA_STATE_CRIT, true);
- StartReactiveTimer( REACTIVE_CRIT );
-
- if(getClass()==CLASS_HUNTER)
- {
- ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true);
- StartReactiveTimer( REACTIVE_HUNTER_CRIT );
- }
-
- if ( outcome == MELEE_HIT_BLOCK_CRIT )
- {
- *blocked_amount = pVictim->GetShieldBlockValue();
-
- if (pVictim->GetUnitBlockChance())
- pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYSHIELD);
- else
- pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED);
-
- //Only set VICTIMSTATE_BLOCK on a full block
- if (*blocked_amount >= uint32(*damage))
- {
- *victimState = VICTIMSTATE_BLOCKS;
- *blocked_amount = uint32(*damage);
- }
-
- if(pVictim->GetTypeId() == TYPEID_PLAYER)
- {
- // Update defense
- ((Player*)pVictim)->UpdateDefense();
-
- // random durability for main hand weapon (BLOCK)
- if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK)))
- ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND);
- }
-
- pVictim->ModifyAuraState(AURA_STATE_DEFENSE,true);
- pVictim->StartReactiveTimer( REACTIVE_DEFENSE );
- break;
- }
-
- pVictim->HandleEmoteCommand(EMOTE_ONESHOT_WOUNDCRITICAL);
- break;
- }
- case MELEE_HIT_PARRY:
- {
- if(attType == RANGED_ATTACK) //range attack - no parry
- {
- outcome = MELEE_HIT_NORMAL;
- break;
- }
-
- cleanDamage->damage += *damage;
- *damage = 0;
- *victimState = VICTIMSTATE_PARRY;
-
- // instant (maybe with small delay) counter attack
- {
- float offtime = float(pVictim->getAttackTimer(OFF_ATTACK));
- float basetime = float(pVictim->getAttackTimer(BASE_ATTACK));
-
- // after parry nearest next attack time will reduced at %40 from full attack time.
- // The delay cannot be reduced to less than 20% of your weapon base swing delay.
- if (pVictim->haveOffhandWeapon() && offtime < basetime)
- {
- float percent20 = pVictim->GetAttackTime(OFF_ATTACK)*0.20;
- float percent60 = 3*percent20;
- // set to 20% if in range 20%...20+40% of full time
- if(offtime > percent20 && offtime <= percent60)
- {
- pVictim->setAttackTimer(OFF_ATTACK,uint32(percent20));
- }
- // decrease at %40 from full time
- else if(offtime > percent60)
- {
- offtime -= 2*percent20;
- pVictim->setAttackTimer(OFF_ATTACK,uint32(offtime));
- }
- // ELSE not changed
- }
- else
- {
- float percent20 = pVictim->GetAttackTime(BASE_ATTACK)*0.20;
- float percent60 = 3*percent20;
- // set to 20% if in range 20%...20+40% of full time
- if(basetime > percent20 && basetime <= percent60)
- {
- pVictim->setAttackTimer(BASE_ATTACK,uint32(percent20));
- }
- // decrease at %40 from full time
- else if(basetime > percent60)
- {
- basetime -= 2*percent20;
- pVictim->setAttackTimer(BASE_ATTACK,uint32(basetime));
- }
- // ELSE not changed
- }
- }
-
- if(pVictim->GetTypeId() == TYPEID_PLAYER)
- {
- // Update victim defense ?
- ((Player*)pVictim)->UpdateDefense();
-
- // random durability for main hand weapon (PARRY)
- if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_PARRY)))
- ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_MAINHAND);
- }
-
- pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED);
-
- if (pVictim->getClass() == CLASS_HUNTER)
- {
- pVictim->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true);
- pVictim->StartReactiveTimer( REACTIVE_HUNTER_PARRY );
- }
- else
- {
- pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true);
- pVictim->StartReactiveTimer( REACTIVE_DEFENSE );
- }
-
- CastMeleeProcDamageAndSpell(pVictim, 0, damageSchoolMask, attType, outcome, spellCasted, isTriggeredSpell);
- return;
- }
- case MELEE_HIT_DODGE:
- {
- if(attType == RANGED_ATTACK) //range attack - no dodge
- {
- outcome = MELEE_HIT_NORMAL;
- break;
- }
-
- cleanDamage->damage += *damage;
- *damage = 0;
- *victimState = VICTIMSTATE_DODGE;
-
- if(pVictim->GetTypeId() == TYPEID_PLAYER)
- ((Player*)pVictim)->UpdateDefense();
-
- pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED);
-
- if (pVictim->getClass() != CLASS_ROGUE) // Riposte
- {
- pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true);
- pVictim->StartReactiveTimer( REACTIVE_DEFENSE );
- }
-
- // Overpower
- if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR)
- {
- ((Player*)this)->AddComboPoints(pVictim, 1);
- StartReactiveTimer( REACTIVE_OVERPOWER );
- }
-
- CastMeleeProcDamageAndSpell(pVictim, 0, damageSchoolMask, attType, outcome, spellCasted, isTriggeredSpell);
- return;
- }
- case MELEE_HIT_BLOCK:
- {
- *blocked_amount = pVictim->GetShieldBlockValue();
-
- if (pVictim->GetUnitBlockChance())
- pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYSHIELD);
- else
- pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED);
-
- //Only set VICTIMSTATE_BLOCK on a full block
- if (*blocked_amount >= uint32(*damage))
- {
- *victimState = VICTIMSTATE_BLOCKS;
- *blocked_amount = uint32(*damage);
- }
-
- if(pVictim->GetTypeId() == TYPEID_PLAYER)
- {
- // Update defense
- ((Player*)pVictim)->UpdateDefense();
-
- // random durability for main hand weapon (BLOCK)
- if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK)))
- ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND);
- }
-
- pVictim->ModifyAuraState(AURA_STATE_DEFENSE,true);
- pVictim->StartReactiveTimer( REACTIVE_DEFENSE );
-
- break;
- }
- case MELEE_HIT_GLANCING:
- {
- int32 leveldif = int32(pVictim->getLevel()) - int32(getLevel());
- if (leveldif > 3) leveldif = 3;
- *damage *= (1 - leveldif * 0.1f);
- cleanDamage->damage = *damage;
- *hitInfo |= HITINFO_GLANCING;
- break;
- }
- case MELEE_HIT_CRUSHING:
- {
- // 150% normal damage
- *damage += (*damage / 2);
- cleanDamage->damage = *damage;
- *hitInfo |= HITINFO_CRUSHING;
- // TODO: victimState, victim animation?
- break;
- }
- default:
- break;
- }
-
- // apply melee damage bonus and absorb only if base damage not fully blocked to prevent negative damage or damage with full block
- if(*victimState != VICTIMSTATE_BLOCKS)
- {
- MeleeDamageBonus(pVictim, damage,attType,spellCasted);
- CalcAbsorbResist(pVictim, damageSchoolMask, DIRECT_DAMAGE, *damage-*blocked_amount, absorbDamage, resistDamage);
- }
-
- if (*absorbDamage) *hitInfo |= HITINFO_ABSORB;
- if (*resistDamage) *hitInfo |= HITINFO_RESIST;
-
- cleanDamage->damage += *blocked_amount;
-
- if (*damage <= *absorbDamage + *resistDamage + *blocked_amount)
- {
- //*hitInfo = 0x00010020;
- //*hitInfo |= HITINFO_SWINGNOHITSOUND;
- //*damageType = 0;
- CastMeleeProcDamageAndSpell(pVictim, 0, damageSchoolMask, attType, outcome, spellCasted, isTriggeredSpell);
- return;
- }
-
- // update at damage Judgement aura duration that applied by attacker at victim
- if(*damage)
- {
- AuraMap const& vAuras = pVictim->GetAuras();
- for(AuraMap::const_iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr)
- {
- SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
- if( (spellInfo->AttributesEx3 & 0x40000) && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN &&
- ((*itr).second->GetCasterGUID() == GetGUID() && (!spellCasted || spellCasted->Id == 35395)) )
- {
- (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
- (*itr).second->UpdateAuraDuration();
- }
- }
- }
-
- CastMeleeProcDamageAndSpell(pVictim, (*damage - *absorbDamage pVictim->SpellNonMeleeDamageLog(this, (*i)->GetId(), (*i)->GetModifier()->m_amount, false, false);eld
- // yet another hack to fix crashes related to the aura getting removed during iteration
- std::set<Aura*> alreadyDone;
- uint32 removedAuras = pVictim->m_removedAuras;
- AuraList const& vDamageShields = pVictim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD);
- for(AuraList::const_iterator i = vDamageShields.begin(), next = vDamageShields.begin(); i != vDamageShields.end(); i = next)
- {
- ++next;
- if (alreadyDone.find(*i) == alreadyDone.end())
- {
- alreadyDone.insert(*i);
- pVictim->SpellNonMeleeDamageLog(this, (*i)->GetId(), (*i)->GetModifierValue(), false, false);
- if (pVictim->m_removedAuras > removedAuras)
- {
- removedAuras = pVictim->m_removedAuras;
- next = vDamageShields.begin();
- }
- }
- }
-}*/
-
void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool extra )
{
if(hasUnitState(UNIT_STAT_CANNOT_AUTOATTACK) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) )
@@ -2731,67 +2179,6 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex
}
}
-/*
-MeleeHitOutcome Unit::RollPhysicalOutcomeAgainst (Unit const *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo)
-{
- // Miss chance based on melee
- float miss_chance = MeleeMissChanceCalc(pVictim, attType);
-
- // Critical hit chance
- float crit_chance = GetUnitCriticalChance(attType, pVictim);
- // this is to avoid compiler issue when declaring variables inside if
- float block_chance, parry_chance, dodge_chance;
-
- // cannot be dodged/parried/blocked
- if(spellInfo->Attributes & SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK)
- {
- block_chance = 0.0f;
- parry_chance = 0.0f;
- dodge_chance = 0.0f;
- }
- else
- {
- // parry can be avoided only by some abilities
- parry_chance = pVictim->GetUnitParryChance();
- // block might be bypassed by it as well
- block_chance = pVictim->GetUnitBlockChance();
- // stunned target cannot dodge and this is check in GetUnitDodgeChance()
- dodge_chance = pVictim->GetUnitDodgeChance();
- }
-
- // Only players can have Talent&Spell bonuses
- if (GetTypeId() == TYPEID_PLAYER)
- {
- // Increase from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL aura
- crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, spellInfo->SchoolMask);
-
- if( dodge_chance != 0.0f ) // if dodge chance is already 0, ignore talents for speed
- {
- AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
- for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i)
- {
- // can't be dodged rogue finishing move
- if((*i)->GetModifier()->m_miscvalue == VICTIMSTATE_DODGE)
- {
- if(spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE))
- {
- dodge_chance = 0.0f;
- break;
- }
- }
- }
- }
- }
-
- // Spellmods
- if(Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance);
-
- DEBUG_LOG("PHYSICAL OUTCOME: miss %f crit %f dodge %f parry %f block %f",miss_chance,crit_chance,dodge_chance,parry_chance, block_chance);
-
- return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100),int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100), true);
-}*/
-
MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackType attType) const
{
// This is only wrapper
@@ -2811,10 +2198,10 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackT
// Useful if want to specify crit & miss chances for melee, else it could be removed
DEBUG_LOG("MELEE OUTCOME: miss %f crit %f dodge %f parry %f block %f", miss_chance,crit_chance,dodge_chance,parry_chance,block_chance);
- return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100), false);
+ return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100));
}
-MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted ) const
+MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const
{
if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
return MELEE_HIT_EVADE;
@@ -2827,7 +2214,6 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack
// bonus from skills is 0.04%
int32 skillBonus = 4 * ( attackerWeaponSkill - victimMaxSkillValueForLevel );
- int32 skillBonus2 = 4 * ( attackerMaxSkillValueForLevel - victimDefenseSkill );
int32 sum = 0, tmp = 0;
int32 roll = urand (0, 10000);
@@ -2908,16 +2294,6 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack
&& ((tmp -= skillBonus) > 0)
&& (roll < (sum += tmp)))
{
- // Critical chance
- tmp = crit_chance + skillBonus2;
- if ( GetTypeId() == TYPEID_PLAYER && SpellCasted && tmp > 0 )
- {
- if ( roll_chance_i(tmp/100))
- {
- DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCKED CRIT");
- return MELEE_HIT_BLOCK_CRIT;
- }
- }
DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCK <%d, %d)", sum-tmp, sum);
return MELEE_HIT_BLOCK;
}
@@ -2925,7 +2301,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack
}
// Critical chance
- tmp = crit_chance + skillBonus2;
+ tmp = crit_chance;
if (tmp > 0 && roll < (sum += tmp))
{
@@ -2934,7 +2310,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack
}
// Max 40% chance to score a glancing blow against mobs that are higher level (can do only players and pets and not with ranged weapon)
- if( attType != RANGED_ATTACK && !SpellCasted &&
+ if( attType != RANGED_ATTACK &&
(GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet()) &&
pVictim->GetTypeId() != TYPEID_PLAYER && !((Creature*)pVictim)->isPet() &&
getLevel() < pVictim->getLevelForTarget(this) )
@@ -2953,10 +2329,14 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack
}
}
- if(GetTypeId()!=TYPEID_PLAYER && !(((Creature*)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRUSH) && !((Creature*)this)->isPet() && !SpellCasted /*Only autoattack can be crushing blow*/ )
+ // mobs can score crushing blows if they're 4 or more levels above victim
+ if (getLevelForTarget(pVictim) >= pVictim->getLevelForTarget(this) + 4 &&
+ // can be from by creature (if can) or from controlled player that considered as creature
+ (GetTypeId()!=TYPEID_PLAYER && !((Creature*)this)->isPet() &&
+ !(((Creature*)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRUSH) ||
+ GetTypeId()==TYPEID_PLAYER && GetCharmerOrOwnerGUID()))
{
- // mobs can score crushing blows if they're 3 or more levels above victim
- // or when their weapon skill is 15 or more above victim's defense skill
+ // when their weapon skill is 15 or more above victim's defense skill
tmp = victimDefenseSkill;
int32 tmpmax = victimMaxSkillValueForLevel;
// having defense above your maximum (from items, talents etc.) has no effect
@@ -3066,6 +2446,23 @@ bool Unit::isSpellBlocked(Unit *pVictim, SpellEntry const *spellProto, WeaponAtt
{
if (pVictim->HasInArc(M_PI,this))
{
+ /* Currently not exist spells with ignore block
+ // Ignore combat result aura (parry/dodge check on prepare)
+ AuraList const& ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
+ for(AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
+ {
+ if (!(*i)->isAffectedOnSpell(spellProto))
+ continue;
+ if ((*i)->GetModifier()->m_miscvalue == )
+ return false;
+ }
+ */
+
+ // Check creatures flags_extra for disable block
+ if(pVictim->GetTypeId()==TYPEID_UNIT &&
+ ((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_BLOCK )
+ return false;
+
float blockChance = GetUnitBlockChance();
blockChance += (GetWeaponSkillValue(attackType) - pVictim->GetMaxSkillValueForLevel() )*0.04;
if (roll_chance_f(blockChance))
@@ -3076,22 +2473,18 @@ bool Unit::isSpellBlocked(Unit *pVictim, SpellEntry const *spellProto, WeaponAtt
// Melee based spells can be miss, parry or dodge on this step
// Crit or block - determined on damage calculation phase! (and can be both in some time)
-float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const
+/*float Unit::MeleeSpellMissChance(Unit *pVictim, WeaponAttackType attType, int32 skillDiff, SpellEntry const *spell)
{
// Calculate hit chance (more correct for chance mod)
int32 HitChance;
// PvP - PvE melee chances
- /*int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 5 : 7;
+ int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 5 : 7;
int32 leveldif = pVictim->getLevelForTarget(this) - getLevelForTarget(pVictim);
if(leveldif < 3)
HitChance = 95 - leveldif;
else
- HitChance = 93 - (leveldif - 2) * lchance;*/
- if (spellId || attType == RANGED_ATTACK || !haveOffhandWeapon())
- HitChance = 95.0f;
- else
- HitChance = 76.0f;
+ HitChance = 93 - (leveldif - 2) * lchance;
// Hit chance depends from victim auras
if(attType == RANGED_ATTACK)
@@ -3100,11 +2493,8 @@ float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType,
HitChance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE);
// Spellmod from SPELLMOD_RESIST_MISS_CHANCE
- if(spellId)
- {
- if(Player *modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_MISS_CHANCE, HitChance);
- }
+ if(Player *modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spell->Id, SPELLMOD_RESIST_MISS_CHANCE, HitChance);
// Miss = 100 - hit
float miss_chance= 100.0f - HitChance;
@@ -3116,12 +2506,7 @@ float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType,
miss_chance -= m_modMeleeHitChance;
// bonus from skills is 0.04%
- //miss_chance -= skillDiff * 0.04f;
- int32 diff = -skillDiff;
- if(pVictim->GetTypeId()==TYPEID_PLAYER)
- miss_chance += diff > 0 ? diff * 0.04 : diff * 0.02;
- else
- miss_chance += diff > 10 ? 2 + (diff - 10) * 0.4 : diff * 0.1;
+ miss_chance -= skillDiff * 0.04f;
// Limit miss chance from 0 to 60%
if (miss_chance < 0.0f)
@@ -3129,7 +2514,7 @@ float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType,
if (miss_chance > 60.0f)
return 60.0f;
return miss_chance;
-}
+}*/
// Melee based spells hit result calculations
SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell)
@@ -3145,68 +2530,106 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell)
int32 fullSkillDiff = attackerWeaponSkill - int32(pVictim->GetDefenseSkillValue(this));
uint32 roll = urand (0, 10000);
- uint32 missChance = uint32(MeleeSpellMissChance(pVictim, attType, fullSkillDiff, spell->Id)*100.0f);
+ uint32 missChance = uint32(MeleeSpellMissChance(pVictim, attType, fullSkillDiff, spell->Id)*100.0f);
// Roll miss
uint32 tmp = missChance;
if (roll < tmp)
return SPELL_MISS_MISS;
+ // Chance resist mechanic (select max value from every mechanic spell effect)
+ int32 resist_mech = 0;
+ // Get effects mechanic and chance
+ for(int eff = 0; eff < 3; ++eff)
+ {
+ int32 effect_mech = GetEffectMechanic(spell, eff);
+ if (effect_mech)
+ {
+ int32 temp = pVictim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effect_mech);
+ if (resist_mech < temp*100)
+ resist_mech = temp*100;
+ }
+ }
+ // Roll chance
+ tmp += resist_mech;
+ if (roll < tmp)
+ return SPELL_MISS_RESIST;
+
+ bool canDodge = true;
+ bool canParry = true;
+
// Same spells cannot be parry/dodge
if (spell->Attributes & SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK)
return SPELL_MISS_NONE;
- // Ranged attack can`t miss too
+ // Ranged attack cannot be parry/dodge
if (attType == RANGED_ATTACK)
return SPELL_MISS_NONE;
- bool attackFromBehind = !pVictim->HasInArc(M_PI,this);
-
- // Roll dodge
- int32 dodgeChance = int32(pVictim->GetUnitDodgeChance()*100.0f) - skillDiff * 4;
- // Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
- dodgeChance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE);
-
- // Reduce dodge chance by attacker expertise rating
- if (GetTypeId() == TYPEID_PLAYER)
- dodgeChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
- if (dodgeChance < 0)
- dodgeChance = 0;
-
- // Can`t dodge from behind in PvP (but its possible in PvE)
- if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER && attackFromBehind)
- dodgeChance = 0;
-
- // Rogue talent`s cant be dodged
- AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
- for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i)
+ // Check for attack from behind
+ if (!pVictim->HasInArc(M_PI,this))
+ {
+ // Can`t dodge from behind in PvP (but its possible in PvE)
+ if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
+ canDodge = false;
+ // Can`t parry
+ canParry = false;
+ }
+ // Check creatures flags_extra for disable parry
+ if(pVictim->GetTypeId()==TYPEID_UNIT)
{
- if((*i)->GetModifier()->m_miscvalue == VICTIMSTATE_DODGE) // can't be dodged rogue finishing move
+ uint32 flagEx = ((Creature*)pVictim)->GetCreatureInfo()->flags_extra;
+ if( flagEx & CREATURE_FLAG_EXTRA_NO_PARRY )
+ canParry = false;
+ }
+ // Ignore combat result aura
+ AuraList const& ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
+ for(AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
+ {
+ if (!(*i)->isAffectedOnSpell(spell))
+ continue;
+ switch((*i)->GetModifier()->m_miscvalue)
{
- if(spell->SpellFamilyName==SPELLFAMILY_ROGUE && (spell->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE))
- {
- dodgeChance = 0;
+ case MELEE_HIT_DODGE: canDodge = false; break;
+ case MELEE_HIT_BLOCK: break; // Block check in hit step
+ case MELEE_HIT_PARRY: canParry = false; break;
+ default:
+ DEBUG_LOG("Spell %u SPELL_AURA_IGNORE_COMBAT_RESULT have unhandled state %d", (*i)->GetId(), (*i)->GetModifier()->m_miscvalue);
break;
- }
}
}
- tmp += dodgeChance;
- if (roll < tmp)
- return SPELL_MISS_DODGE;
+ if (canDodge)
+ {
+ // Roll dodge
+ int32 dodgeChance = int32(pVictim->GetUnitDodgeChance()*100.0f) - skillDiff * 4;
+ // Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
+ dodgeChance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE);
+ // Reduce dodge chance by attacker expertise rating
+ if (GetTypeId() == TYPEID_PLAYER)
+ dodgeChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
+ if (dodgeChance < 0)
+ dodgeChance = 0;
- // Roll parry
- int32 parryChance = int32(pVictim->GetUnitParryChance()*100.0f) - skillDiff * 4;
- // Reduce parry chance by attacker expertise rating
- if (GetTypeId() == TYPEID_PLAYER)
- parryChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
- // Can`t parry from behind
- if (parryChance < 0 || attackFromBehind)
- parryChance = 0;
+ tmp += dodgeChance;
+ if (roll < tmp)
+ return SPELL_MISS_DODGE;
+ }
- tmp += parryChance;
- if (roll < tmp)
- return SPELL_MISS_PARRY;
+ if (canParry)
+ {
+ // Roll parry
+ int32 parryChance = int32(pVictim->GetUnitParryChance()*100.0f) - skillDiff * 4;
+ // Reduce parry chance by attacker expertise rating
+ if (GetTypeId() == TYPEID_PLAYER)
+ parryChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
+ if (parryChance < 0)
+ parryChance = 0;
+
+ tmp += parryChance;
+ if (roll < tmp)
+ return SPELL_MISS_PARRY;
+ }
return SPELL_MISS_NONE;
}
@@ -3297,8 +2720,8 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool
if (spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY)
return SPELL_MISS_NONE;
- // Check for immune (use charges)
- if (pVictim->IsImmunedToSpell(spell,true))
+ // Check for immune
+ if (pVictim->IsImmunedToSpell(spell))
return SPELL_MISS_IMMUNE;
// All positive spells can`t miss
@@ -3307,8 +2730,8 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool
&&(!IsHostileTo(pVictim))) //prevent from affecting enemy by "positive" spell
return SPELL_MISS_NONE;
- // Check for immune (use charges)
- if (pVictim->IsImmunedToDamage(GetSpellSchoolMask(spell),true))
+ // Check for immune
+ if (pVictim->IsImmunedToDamage(GetSpellSchoolMask(spell)))
return SPELL_MISS_IMMUNE;
if(this == pVictim)
@@ -3321,7 +2744,7 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool
Unit::AuraList const& mReflectSpellsSchool = pVictim->GetAurasByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL);
for(Unit::AuraList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i)
if((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spell))
- reflectchance = (*i)->GetModifierValue();
+ reflectchance += (*i)->GetModifier()->m_amount;
if (reflectchance > 0 && roll_chance_i(reflectchance))
{
// Start triggers for remove charges if need (trigger only for victim, and mark as active spell)
@@ -3562,6 +2985,9 @@ float Unit::GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVict
crit -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE);
}
+ // Apply crit chance from defence skill
+ crit += (int32(GetMaxSkillValueForLevel(pVictim)) - int32(pVictim->GetDefenseSkillValue(this))) * 0.04f;
+
if (crit < 0.0f)
crit = 0.0f;
return crit;
@@ -3689,7 +3115,7 @@ void Unit::_UpdateAutoRepeatSpell()
if ( (GetTypeId() == TYPEID_PLAYER && ((Player*)this)->isMoving()) || IsNonMeleeSpellCasted(false,false,true) )
{
// cancel wand shoot
- if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351)
+ if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != SPELL_ID_AUTOSHOT)
InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
m_AutoRepeatFirstCast = true;
return;
@@ -3742,7 +3168,7 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell )
if ( m_currentSpells[CURRENT_AUTOREPEAT_SPELL] )
{
// break autorepeat if not Auto Shot
- if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351)
+ if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != SPELL_ID_AUTOSHOT)
InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
m_AutoRepeatFirstCast = true;
}
@@ -3757,7 +3183,7 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell )
// it also does break autorepeat if not Auto Shot
if ( m_currentSpells[CURRENT_AUTOREPEAT_SPELL] &&
- m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351 )
+ m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != SPELL_ID_AUTOSHOT )
InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
addUnitState(UNIT_STAT_CASTING);
} break;
@@ -3765,7 +3191,7 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell )
case CURRENT_AUTOREPEAT_SPELL:
{
// only Auto Shoot does not break anything
- if (pSpell->m_spellInfo->Category == 351)
+ if (pSpell->m_spellInfo->Id != SPELL_ID_AUTOSHOT)
{
// generic autorepeats break generic non-delayed and channeled non-delayed spells
InterruptSpell(CURRENT_GENERIC_SPELL,false);
@@ -3934,7 +3360,7 @@ int32 Unit::GetTotalAuraModifier(AuraType auratype) const
AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
- modifier += (*i)->GetModifierValue();
+ modifier += (*i)->GetModifier()->m_amount;
return modifier;
}
@@ -3945,7 +3371,7 @@ float Unit::GetTotalAuraMultiplier(AuraType auratype) const
AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
- multiplier *= (100.0f + (*i)->GetModifierValue())/100.0f;
+ multiplier *= (100.0f + (*i)->GetModifier()->m_amount)/100.0f;
return multiplier;
}
@@ -3956,11 +3382,8 @@ int32 Unit::GetMaxPositiveAuraModifier(AuraType auratype) const
AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
- {
- int32 amount = (*i)->GetModifierValue();
- if (amount > modifier)
- modifier = amount;
- }
+ if ((*i)->GetModifier()->m_amount > modifier)
+ modifier = (*i)->GetModifier()->m_amount;
return modifier;
}
@@ -3971,11 +3394,8 @@ int32 Unit::GetMaxNegativeAuraModifier(AuraType auratype) const
AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
- {
- int32 amount = (*i)->GetModifierValue();
- if (amount < modifier)
- modifier = amount;
- }
+ if ((*i)->GetModifier()->m_amount < modifier)
+ modifier = (*i)->GetModifier()->m_amount;
return modifier;
}
@@ -3989,7 +3409,7 @@ int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask)
{
Modifier* mod = (*i)->GetModifier();
if (mod->m_miscvalue & misc_mask)
- modifier += (*i)->GetModifierValue();
+ modifier += mod->m_amount;
}
return modifier;
}
@@ -4003,7 +3423,7 @@ float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask
{
Modifier* mod = (*i)->GetModifier();
if (mod->m_miscvalue & misc_mask)
- multiplier *= (100.0f + (*i)->GetModifierValue())/100.0f;
+ multiplier *= (100.0f + mod->m_amount)/100.0f;
}
return multiplier;
}
@@ -4016,9 +3436,8 @@ int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
- int32 amount = (*i)->GetModifierValue();
- if (mod->m_miscvalue & misc_mask && amount > modifier)
- modifier = amount;
+ if (mod->m_miscvalue & misc_mask && mod->m_amount > modifier)
+ modifier = mod->m_amount;
}
return modifier;
@@ -4032,9 +3451,8 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
- int32 amount = (*i)->GetModifierValue();
- if (mod->m_miscvalue & misc_mask && amount < modifier)
- modifier = amount;
+ if (mod->m_miscvalue & misc_mask && mod->m_amount < modifier)
+ modifier = mod->m_amount;
}
return modifier;
@@ -4049,7 +3467,7 @@ int32 Unit::GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value)
{
Modifier* mod = (*i)->GetModifier();
if (mod->m_miscvalue == misc_value)
- modifier += (*i)->GetModifierValue();
+ modifier += mod->m_amount;
}
return modifier;
}
@@ -4063,7 +3481,7 @@ float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_valu
{
Modifier* mod = (*i)->GetModifier();
if (mod->m_miscvalue == misc_value)
- multiplier *= (100.0f + (*i)->GetModifierValue())/100.0f;
+ multiplier *= (100.0f + mod->m_amount)/100.0f;
}
return multiplier;
}
@@ -4076,9 +3494,8 @@ int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
- int32 amount = (*i)->GetModifierValue();
- if (mod->m_miscvalue == misc_value && amount > modifier)
- modifier = amount;
+ if (mod->m_miscvalue == misc_value && mod->m_amount > modifier)
+ modifier = mod->m_amount;
}
return modifier;
@@ -4092,9 +3509,8 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
- int32 amount = (*i)->GetModifierValue();
- if (mod->m_miscvalue == misc_value && amount < modifier)
- modifier = amount;
+ if (mod->m_miscvalue == misc_value && mod->m_amount < modifier)
+ modifier = mod->m_amount;
}
return modifier;
@@ -4130,57 +3546,51 @@ bool Unit::AddAura(Aura *Aur)
// passive and persistent auras can stack with themselves any number of times
if (!Aur->IsPassive() && !Aur->IsPersistent())
{
- // replace aura if next will > spell StackAmount
- if(aurSpellInfo->StackAmount)
- {
- Aur->SetStackAmount(i->second->GetStackAmount());
- if(Aur->GetStackAmount() < aurSpellInfo->StackAmount)
- Aur->SetStackAmount(Aur->GetStackAmount()+1);
- RemoveAura(i,AURA_REMOVE_BY_STACK);
- }
- // if StackAmount==0 not allow auras from same caster
- else
+ for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2)
{
- for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2)
+ if(i2->second->GetCasterGUID()==Aur->GetCasterGUID())
{
- if(i2->second->GetCasterGUID()==Aur->GetCasterGUID())
+ // Aura can stack on self -> Stack it;
+ if(aurSpellInfo->StackAmount)
{
- // can be only single (this check done at _each_ aura add
- RemoveAura(i2,AURA_REMOVE_BY_STACK);
- break;
- }
-
- bool stop = false;
- switch(aurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()])
- {
- // DoT/HoT/etc
- case SPELL_AURA_PERIODIC_DAMAGE: // allow stack
- case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
- case SPELL_AURA_PERIODIC_LEECH:
- case SPELL_AURA_PERIODIC_HEAL:
- case SPELL_AURA_OBS_MOD_HEALTH:
- case SPELL_AURA_PERIODIC_MANA_LEECH:
- case SPELL_AURA_PERIODIC_ENERGIZE:
- case SPELL_AURA_OBS_MOD_MANA:
- case SPELL_AURA_POWER_BURN_MANA:
- break;
- default: // not allow
- // can be only single (this check done at _each_ aura add
- RemoveAura(i2,AURA_REMOVE_BY_STACK);
- stop = true;
- break;
+ i2->second->modStackAmount(1);
+ delete Aur;
+ return false;
}
+ // can be only single (this check done at _each_ aura add
+ RemoveAura(i2,AURA_REMOVE_BY_STACK);
+ break;
+ }
- if(stop)
+ bool stop = false;
+ switch(aurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()])
+ {
+ // DoT/HoT/etc
+ case SPELL_AURA_PERIODIC_DAMAGE: // allow stack
+ case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
+ case SPELL_AURA_PERIODIC_LEECH:
+ case SPELL_AURA_PERIODIC_HEAL:
+ case SPELL_AURA_OBS_MOD_HEALTH:
+ case SPELL_AURA_PERIODIC_MANA_LEECH:
+ case SPELL_AURA_PERIODIC_ENERGIZE:
+ case SPELL_AURA_OBS_MOD_MANA:
+ case SPELL_AURA_POWER_BURN_MANA:
+ break;
+ default: // not allow
+ // can be only single (this check done at _each_ aura add
+ RemoveAura(i2,AURA_REMOVE_BY_STACK);
+ stop = true;
break;
}
+
+ if(stop)
+ break;
}
}
}
- // passive auras stack with all (except passive spell proc auras)
- if ((!Aur->IsPassive() || !IsPassiveStackableSpell(Aur->GetId())) &&
- !(Aur->GetId() == 20584 || Aur->GetId() == 8326))
+ // passive auras not stacable with other ranks
+ if (!IsPassiveSpellStackableWithRanks(aurSpellInfo))
{
if (!RemoveNoStackAurasDueToAura(Aur))
{
@@ -4286,6 +3696,13 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
uint32 spellId = Aur->GetId();
uint32 effIndex = Aur->GetEffIndex();
+ // passive spell special case (only non stackable with ranks)
+ if(IsPassiveSpell(spellId))
+ {
+ if(IsPassiveSpellStackableWithRanks(spellProto))
+ return true;
+ }
+
SpellSpecific spellId_spec = GetSpellSpecific(spellId);
AuraMap::iterator i,next;
@@ -4302,9 +3719,11 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
uint32 i_spellId = i_spellProto->Id;
+ // early checks that spellId is passive non stackable spell
if(IsPassiveSpell(i_spellId))
{
- if(IsPassiveStackableSpell(i_spellId))
+ // passive non-stackable spells not stackable only for same caster
+ if(Aur->GetCasterGUID()!=i->second->GetCasterGUID())
continue;
// passive non-stackable spells not stackable only with another rank of same spell
@@ -4321,65 +3740,36 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
for(int j = 0; j < 3; ++j)
if (i_spellProto->EffectTriggerSpell[j] == spellProto->Id)
is_triggered_by_spell = true;
- if (is_triggered_by_spell) continue;
- for(int j = 0; j < 3; ++j)
- {
- // prevent remove dummy triggered spells at next effect aura add
- switch(spellProto->Effect[j]) // main spell auras added added after triggered spell
- {
- case SPELL_EFFECT_DUMMY:
- switch(spellId)
- {
- case 5420: if(i_spellId==34123) is_triggered_by_spell = true; break;
- }
- break;
- }
+ if (is_triggered_by_spell)
+ continue;
- if(is_triggered_by_spell)
- break;
+ // check if they can stack
+ bool sameCaster = Aur->GetCasterGUID() == (*i).second->GetCasterGUID();
+ if(!spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId, sameCaster))
+ continue;
- // prevent remove form main spell by triggered passive spells
- switch(i_spellProto->EffectApplyAuraName[j]) // main aura added before triggered spell
- {
- case SPELL_AURA_MOD_SHAPESHIFT:
- switch(i_spellId)
- {
- case 24858: if(spellId==24905) is_triggered_by_spell = true; break;
- case 33891: if(spellId==5420 || spellId==34123) is_triggered_by_spell = true; break;
- case 34551: if(spellId==22688) is_triggered_by_spell = true; break;
- }
- break;
- }
- }
+ //some spells should be not removed by lower rank of them (totem, paladin aura)
+ if (!sameCaster
+ &&(spellProto->Effect[effIndex]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
+ &&(spellProto->DurationIndex==21)
+ &&(spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
+ &&(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0))
+ return false;
- if(!is_triggered_by_spell)
+ // Its a parent aura (create this aura in ApplyModifier)
+ if ((*i).second->IsInUse())
{
- bool sameCaster = Aur->GetCasterGUID() == (*i).second->GetCasterGUID();
- if( spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId, sameCaster) )
- {
- //some spells should be not removed by lower rank of them (totem, paladin aura)
- if (!sameCaster
- &&(spellProto->Effect[effIndex]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
- &&(spellProto->DurationIndex==21)
- &&(spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
- &&(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0))
- return false;
+ sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex());
+ continue;
+ }
- // Its a parent aura (create this aura in ApplyModifier)
- if ((*i).second->IsInUse())
- {
- sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex());
- continue;
- }
- RemoveAurasDueToSpell(i_spellId);
+ RemoveAurasDueToSpell(i_spellId);
- if( m_Auras.empty() )
- break;
- else
- next = m_Auras.begin();
- }
- }
+ if( m_Auras.empty() )
+ break;
+ else
+ next = m_Auras.begin();
}
return true;
}
@@ -4399,6 +3789,18 @@ void Unit::RemoveAura(uint32 spellId, uint32 effindex, Aura* except)
}
}
+void Unit::RemoveAurasByCasterSpell(uint32 spellId, uint64 casterGUID)
+{
+ for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
+ {
+ Aura *aur = iter->second;
+ if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID)
+ RemoveAura(iter);
+ else
+ ++iter;
+ }
+}
+
void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler)
{
for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
@@ -4408,20 +3810,21 @@ void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit
{
// Custom dispel case
// Unstable Affliction
- if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aur->GetSpellProto()->SpellFamilyFlags & 0x010000000000LL))
+ if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aur->GetSpellProto()->SpellFamilyFlags[1] & 0x0100))
{
int32 damage = aur->GetModifier()->m_amount*9;
uint64 caster_guid = aur->GetCasterGUID();
// Remove aura
- RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
+ if (iter->second->modStackAmount(-1))
+ RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
// backfire damage and silence
dispeler->CastCustomSpell(dispeler, 31117, &damage, NULL, NULL, true, NULL, NULL,caster_guid);
iter = m_Auras.begin(); // iterator can be invalidate at cast if self-dispel
}
- else
+ else if (iter->second->modStackAmount(-1))
RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
}
else
@@ -4453,7 +3856,8 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit
stealer->AddAura(new_aur);
// Remove aura as dispel
- RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
+ if (iter->second->modStackAmount(-1))
+ RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
}
else
++iter;
@@ -4491,48 +3895,20 @@ void Unit::RemoveAurasWithDispelType( DispelType type )
}
}
-void Unit::RemoveSingleAuraFromStackByDispel(uint32 spellId)
-{
- for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
- {
- Aura *aur = iter->second;
- if (aur->GetId() == spellId)
- {
- if(iter->second->GetStackAmount() > 1)
- {
- // reapply modifier with reduced stack amount
- iter->second->ApplyModifier(false,true);
- iter->second->SetStackAmount(iter->second->GetStackAmount()-1);
- iter->second->ApplyModifier(true,true);
-
- iter->second->UpdateSlotCounterAndDuration();
- return; // not remove aura if stack amount > 1
- }
- else
- RemoveAura(iter,AURA_REMOVE_BY_DISPEL);
- }
- else
- ++iter;
- }
-}
-
void Unit::RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex)
{
AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex));
if(iter != m_Auras.end())
{
- if(iter->second->GetStackAmount() > 1)
- {
- // reapply modifier with reduced stack amount
- iter->second->ApplyModifier(false,true);
- iter->second->SetStackAmount(iter->second->GetStackAmount()-1);
- iter->second->ApplyModifier(true,true);
+ if (iter->second->modStackAmount(-1))
+ RemoveAura(iter);
+ }
+}
- iter->second->UpdateSlotCounterAndDuration();
- return; // not remove aura if stack amount > 1
- }
- RemoveAura(iter);
- }
+void Unit::RemoveSingleSpellAurasFromStack(uint32 spellId)
+{
+ for (int i=0; i<3; ++i)
+ RemoveSingleAuraFromStack(spellId, i);
}
void Unit::RemoveAurasDueToSpell(uint32 spellId, Aura* except)
@@ -4541,25 +3917,6 @@ void Unit::RemoveAurasDueToSpell(uint32 spellId, Aura* except)
RemoveAura(spellId,i,except);
}
-void Unit::RemoveAurasDueToCasterSpell(uint32 spellId, uint64 guid)
-{
- for (int k=0; k < 3; ++k)
- {
- spellEffectPair spair = spellEffectPair(spellId, k);
- for (AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);)
- {
- if (iter->second->GetCasterGUID() == guid)
- {
- RemoveAura(iter);
- break;
- //iter = m_Auras.upper_bound(spair); // overwrite by more appropriate
- }
- else
- ++iter;
- }
- }
-}
-
void Unit::RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId)
{
for (int k=0; k < 3; ++k)
@@ -4687,9 +4044,6 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
sLog.outDebug("Aura %u (%u) now is remove mode %d", Aur->GetId(), Aur->GetModifier()->m_auraname, mode);
assert(!Aur->IsInUse());
Aur->ApplyModifier(false,true);
-
- Aur->SetStackAmount(0);
-
Aur->_RemoveAura();
if(mode != AURA_REMOVE_BY_STACK)
@@ -4773,7 +4127,7 @@ void Unit::DelayAura(uint32 spellId, uint32 effindex, int32 delaytime)
iter->second->SetAuraDuration(0);
else
iter->second->SetAuraDuration(iter->second->GetAuraDuration() - delaytime);
- iter->second->UpdateAuraDuration();
+ iter->second->SendAuraUpdate(false);
sLog.outDebug("Aura %u partially interrupted on unit %u, new duration: %u ms",iter->second->GetModifier()->m_auraname, GetGUIDLow(), iter->second->GetAuraDuration());
}
}
@@ -4802,6 +4156,33 @@ Aura* Unit::GetAura(uint32 spellId, uint32 effindex)
return NULL;
}
+Aura* Unit::GetAura(AuraType type, uint32 family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID)
+{
+ AuraList const& auras = GetAurasByType(type);
+ for(AuraList::const_iterator i = auras.begin();i != auras.end(); ++i)
+ {
+ SpellEntry const *spell = (*i)->GetSpellProto();
+ if (spell->SpellFamilyName == family && spell->SpellFamilyFlags.HasFlag(familyFlag1, familyFlag2, familyFlag3))
+ {
+ if (casterGUID && (*i)->GetCasterGUID()!=casterGUID)
+ continue;
+ return (*i);
+ }
+ }
+ return NULL;
+}
+
+bool Unit::HasAura(uint32 spellId) const
+{
+ for (int i = 0; i < 3 ; ++i)
+ {
+ AuraMap::const_iterator iter = m_Auras.find(spellEffectPair(spellId, i));
+ if (iter != m_Auras.end())
+ return true;
+ }
+ return false;
+}
+
void Unit::AddDynObject(DynamicObject* dynObj)
{
m_dynObjGUIDs.push_back(dynObj->GetGUID());
@@ -4946,6 +4327,7 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage *log)
data.append(log->attacker->GetPackGUID());
data << uint32(log->SpellID);
data << uint32(log->damage); //damage amount
+ data << uint32(0);
data << uint8 (log->schoolMask); //damage school
data << uint32(log->absorb); //AbsorbedDamage
data << uint32(log->resist); //resist
@@ -4965,6 +4347,7 @@ void Unit::SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage,
data.append(GetPackGUID());
data << uint32(SpellID);
data << uint32(Damage-AbsorbedDamage-Resist-Blocked);
+ data << uint32(0); // wotlk
data << uint8(damageSchoolMask); // spell school
data << uint32(AbsorbedDamage); // AbsorbedDamage
data << uint32(Resist); // resist
@@ -5003,25 +4386,65 @@ void Unit::SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo)
void Unit::SendAttackStateUpdate(CalcDamageInfo *damageInfo)
{
- WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16+84)); // we guess size
+ uint32 count = 1;
+ WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16+45)); // we guess size
data << (uint32)damageInfo->HitInfo;
data.append(GetPackGUID());
data.append(damageInfo->target->GetPackGUID());
data << (uint32)(damageInfo->damage); // Full damage
+ data << uint32(0); // overkill value
- data << (uint8)1; // Sub damage count
- //=== Sub damage description
- data << (uint32)(damageInfo->damageSchoolMask); // School of sub damage
- data << (float)damageInfo->damage; // sub damage
- data << (uint32)damageInfo->damage; // Sub Damage
- data << (uint32)damageInfo->absorb; // Absorb
- data << (uint32)damageInfo->resist; // Resist
- //=================================================
- data << (uint32)damageInfo->TargetState;
+ data << (uint8)count; // Sub damage count
+
+ for(int i = 0; i < count; ++i)
+ {
+ data << (uint32)(damageInfo->damageSchoolMask); // School of sub damage
+ data << (float)damageInfo->damage; // sub damage
+ data << (uint32)damageInfo->damage; // Sub Damage
+ }
+
+ if(damageInfo->HitInfo & (HITINFO_ABSORB | HITINFO_ABSORB2))
+ {
+ for(int i = 0; i < count; ++i)
+ data << (uint32)damageInfo->absorb; // Absorb
+ }
+
+ if(damageInfo->HitInfo & (HITINFO_RESIST | HITINFO_RESIST2))
+ {
+ for(int i = 0; i < count; ++i)
+ data << (uint32)damageInfo->resist; // Resist
+ }
+
+ data << (uint8)damageInfo->TargetState;
data << (uint32)0;
data << (uint32)0;
- data << (uint32)damageInfo->blocked_amount;
- SendMessageToSet( &data, true );/**/
+
+ if(damageInfo->HitInfo & HITINFO_BLOCK)
+ data << (uint32)damageInfo->blocked_amount;
+
+ if(damageInfo->HitInfo & HITINFO_UNK3)
+ data << uint32(0);
+
+ if(damageInfo->HitInfo & HITINFO_UNK1)
+ {
+ data << uint32(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ for(uint8 i = 0; i < 5; ++i)
+ {
+ data << float(0);
+ data << float(0);
+ }
+ data << uint32(0);
+ }
+
+ SendMessageToSet( &data, true );
}
void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount)
@@ -5029,169 +4452,69 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType,
sLog.outDebug("WORLD: Sending SMSG_ATTACKERSTATEUPDATE");
WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16+45)); // we guess size
- data << (uint32)HitInfo;
+ data << uint32(HitInfo); // flags
data.append(GetPackGUID());
data.append(target->GetPackGUID());
- data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount);
+ data << uint32(Damage-AbsorbDamage-Resist-BlockedAmount);// damage
+ data << uint32(0); // overkill value
data << (uint8)SwingType; // count?
// for(i = 0; i < SwingType; ++i)
data << (uint32)damageSchoolMask;
data << (float)(Damage-AbsorbDamage-Resist-BlockedAmount);
- // still need to double check damage
data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount);
- data << (uint32)AbsorbDamage;
- data << (uint32)Resist;
// end loop
- data << (uint32)TargetState;
-
- if( AbsorbDamage == 0 ) //also 0x3E8 = 0x3E8, check when that happens
- data << (uint32)0;
- else
- data << (uint32)-1;
-
- data << (uint32)0;
- data << (uint32)BlockedAmount;
-
- SendMessageToSet( &data, true );
-}
-/*
-void Unit::ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 damage, SpellSchoolMask damageSchoolMask, SpellEntry const *procSpell, bool isTriggeredSpell, WeaponAttackType attType)
-{
- sLog.outDebug("ProcDamageAndSpell: attacker flags are 0x%x, victim flags 0x%x", procAttacker, procVictim);
- if(procSpell)
- sLog.outDebug("ProcDamageAndSpell: invoked due to spell id %u %s", procSpell->Id, (isTriggeredSpell?"(triggered)":""));
-
- // Assign melee/ranged proc flags for magic attacks, that are actually melee/ranged abilities
- // not assign for spell proc triggered spell to prevent infinity (or unexpected 2-3 times) melee damage spell proc call with melee damage effect
- // That is the question though if it's fully correct
- if(procSpell && !isTriggeredSpell)
+ if(HitInfo & (HITINFO_ABSORB | HITINFO_ABSORB2))
{
- if(procSpell->DmgClass == SPELL_DAMAGE_CLASS_MELEE)
- {
- if(procAttacker & PROC_FLAG_HIT_SPELL) procAttacker |= PROC_FLAG_HIT_MELEE;
- if(procAttacker & PROC_FLAG_CRIT_SPELL) procAttacker |= PROC_FLAG_CRIT_MELEE;
- if(procVictim & PROC_FLAG_STRUCK_SPELL) procVictim |= PROC_FLAG_STRUCK_MELEE;
- if(procVictim & PROC_FLAG_STRUCK_CRIT_SPELL) procVictim |= PROC_FLAG_STRUCK_CRIT_MELEE;
- attType = BASE_ATTACK; // Melee abilities are assumed to be dealt with mainhand weapon
- }
- else if (procSpell->DmgClass == SPELL_DAMAGE_CLASS_RANGED)
- {
- if(procAttacker & PROC_FLAG_HIT_SPELL) procAttacker |= PROC_FLAG_HIT_RANGED;
- if(procAttacker & PROC_FLAG_CRIT_SPELL) procAttacker |= PROC_FLAG_CRIT_RANGED;
- if(procVictim & PROC_FLAG_STRUCK_SPELL) procVictim |= PROC_FLAG_STRUCK_RANGED;
- if(procVictim & PROC_FLAG_STRUCK_CRIT_SPELL) procVictim |= PROC_FLAG_STRUCK_CRIT_RANGED;
- attType = RANGED_ATTACK;
- }
+ // for(i = 0; i < SwingType; ++i)
+ data << uint32(AbsorbDamage);
+ // end loop
}
- if(damage && (procVictim & (PROC_FLAG_STRUCK_MELEE|PROC_FLAG_STRUCK_RANGED|PROC_FLAG_STRUCK_SPELL)))
- procVictim |= (PROC_FLAG_TAKE_DAMAGE|PROC_FLAG_TOUCH);
- // Not much to do if no flags are set.
- if (procAttacker)
+ if(HitInfo & (HITINFO_RESIST | HITINFO_RESIST2))
{
- // processing auras that not generate casts at proc event before auras that generate casts to prevent proc aura added at prev. proc aura execute in set
- ProcDamageAndSpellFor(false,pVictim,procAttacker,attackerProcEffectAuraTypes,attType, procSpell, damage, damageSchoolMask);
- ProcDamageAndSpellFor(false,pVictim,procAttacker,attackerProcCastAuraTypes,attType, procSpell, damage, damageSchoolMask);
+ // for(i = 0; i < SwingType; ++i)
+ data << uint32(Resist);
+ // end loop
}
- // Now go on with a victim's events'n'auras
- // Not much to do if no flags are set or there is no victim
- if(pVictim && pVictim->isAlive() && procVictim)
+ data << (uint8)TargetState;
+ data << (uint32)0;
+ data << (uint32)0;
+
+ if(HitInfo & HITINFO_BLOCK)
{
- // processing auras that not generate casts at proc event before auras that generate casts to prevent proc aura added at prev. proc aura execute in set
- pVictim->ProcDamageAndSpellFor(true,this,procVictim,victimProcEffectAuraTypes,attType,procSpell, damage, damageSchoolMask);
- pVictim->ProcDamageAndSpellFor(true,this,procVictim,victimProcCastAuraTypes,attType,procSpell, damage, damageSchoolMask);
+ data << uint32(BlockedAmount);
}
-}
-
-void Unit::CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, SpellSchoolMask damageSchoolMask, WeaponAttackType attType, MeleeHitOutcome outcome, SpellEntry const *spellCasted, bool isTriggeredSpell)
-{
- if(!pVictim)
- return;
- uint32 procAttacker = PROC_FLAG_NONE;
- uint32 procVictim = PROC_FLAG_NONE;
-
- switch(outcome)
+ if(HitInfo & HITINFO_UNK3)
{
- case MELEE_HIT_EVADE:
- return;
- case MELEE_HIT_MISS:
- if(attType == BASE_ATTACK || attType == OFF_ATTACK)
- {
- procAttacker = PROC_FLAG_MISS;
- }
- break;
- case MELEE_HIT_BLOCK_CRIT:
- case MELEE_HIT_CRIT:
- if(spellCasted && attType == BASE_ATTACK)
- {
- procAttacker |= PROC_FLAG_CRIT_SPELL;
- procVictim |= PROC_FLAG_STRUCK_CRIT_SPELL;
- if ( outcome == MELEE_HIT_BLOCK_CRIT )
- {
- procVictim |= PROC_FLAG_BLOCK;
- procAttacker |= PROC_FLAG_TARGET_BLOCK;
- }
- }
- else if(attType == BASE_ATTACK || attType == OFF_ATTACK)
- {
- procAttacker = PROC_FLAG_HIT_MELEE | PROC_FLAG_CRIT_MELEE;
- procVictim = PROC_FLAG_STRUCK_MELEE | PROC_FLAG_STRUCK_CRIT_MELEE;
- }
- else
- {
- procAttacker = PROC_FLAG_HIT_RANGED | PROC_FLAG_CRIT_RANGED;
- procVictim = PROC_FLAG_STRUCK_RANGED | PROC_FLAG_STRUCK_CRIT_RANGED;
- }
- break;
- case MELEE_HIT_PARRY:
- procAttacker = PROC_FLAG_TARGET_DODGE_OR_PARRY;
- procVictim = PROC_FLAG_PARRY;
- break;
- case MELEE_HIT_BLOCK:
- procAttacker = PROC_FLAG_TARGET_BLOCK;
- procVictim = PROC_FLAG_BLOCK;
- break;
- case MELEE_HIT_DODGE:
- procAttacker = PROC_FLAG_TARGET_DODGE_OR_PARRY;
- procVictim = PROC_FLAG_DODGE;
- break;
- case MELEE_HIT_CRUSHING:
- if(attType == BASE_ATTACK || attType == OFF_ATTACK)
- {
- procAttacker = PROC_FLAG_HIT_MELEE | PROC_FLAG_CRIT_MELEE;
- procVictim = PROC_FLAG_STRUCK_MELEE | PROC_FLAG_STRUCK_CRIT_MELEE;
- }
- else
- {
- procAttacker = PROC_FLAG_HIT_RANGED | PROC_FLAG_CRIT_RANGED;
- procVictim = PROC_FLAG_STRUCK_RANGED | PROC_FLAG_STRUCK_CRIT_RANGED;
- }
- break;
- default:
- if(attType == BASE_ATTACK || attType == OFF_ATTACK)
- {
- procAttacker = PROC_FLAG_HIT_MELEE;
- procVictim = PROC_FLAG_STRUCK_MELEE;
- }
- else
- {
- procAttacker = PROC_FLAG_HIT_RANGED;
- procVictim = PROC_FLAG_STRUCK_RANGED;
- }
- break;
+ data << uint32(0);
}
- if(damage > 0)
- procVictim |= PROC_FLAG_TAKE_DAMAGE;
+ if(HitInfo & HITINFO_UNK1)
+ {
+ data << uint32(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ for(uint8 i = 0; i < 5; ++i)
+ {
+ data << float(0);
+ data << float(0);
+ }
+ data << uint32(0);
+ }
- if(procAttacker != PROC_FLAG_NONE || procVictim != PROC_FLAG_NONE)
- ProcDamageAndSpell(pVictim, procAttacker, procVictim, damage, damageSchoolMask, spellCasted, isTriggeredSpell, attType);
-}*/
+ SendMessageToSet( &data, true );
+}
bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown)
{
@@ -5259,7 +4582,8 @@ bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
{
SpellEntry const *dummySpell = triggeredByAura->GetSpellProto ();
- uint32 effIndex = triggeredByAura->GetEffIndex ();
+ uint32 effIndex = triggeredByAura->GetEffIndex();
+ int32 triggerAmount = triggeredByAura->GetModifier()->m_amount;
Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
@@ -5274,7 +4598,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
{
switch (dummySpell->Id)
{
- // Eye of Eye
+ // Eye for an Eye
case 9799:
case 25988:
{
@@ -5283,7 +4607,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
// return damage % to attacker but < 50% own total health
- basepoints0 = triggeredByAura->GetModifier()->m_amount*int32(damage)/100;
+ basepoints0 = triggerAmount*int32(damage)/100;
if(basepoints0 > GetMaxHealth()/2)
basepoints0 = GetMaxHealth()/2;
@@ -5312,15 +4636,14 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
if (!procSpell || procSpell->Id == 24659)
return false;
// Need remove one 24659 aura
- RemoveSingleAuraFromStack(24659, 0);
- RemoveSingleAuraFromStack(24659, 1);
+ RemoveSingleSpellAurasFromStack(24659);
return true;
}
// Restless Strength
case 24661:
{
// Need remove one 24662 aura
- RemoveSingleAuraFromStack(24662, 0);
+ RemoveSingleSpellAurasFromStack(24662);
return true;
}
// Adaptive Warding (Frostfire Regalia set)
@@ -5336,7 +4659,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
{
if(SpellEntry const* iterSpellProto = (*iter)->GetSpellProto())
{
- if(iterSpellProto->SpellFamilyName==SPELLFAMILY_MAGE && (iterSpellProto->SpellFamilyFlags & 0x10000000))
+ if(iterSpellProto->SpellFamilyName==SPELLFAMILY_MAGE && (iterSpellProto->SpellFamilyFlags[0] & 0x10000000))
{
found=true;
break;
@@ -5394,7 +4717,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
if(!target)
return false;
- basepoints0 = int32(damage * 2.5f); // manaregen
triggered_spell_id = 34650;
break;
}
@@ -5402,7 +4724,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case 33493:
{
// Cast finish spell at last charge
- if (triggeredByAura->m_procCharges > 1)
+ if (triggeredByAura->GetAuraCharges() > 1)
return false;
target = this;
@@ -5602,6 +4924,47 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
}
return false;
}
+ // Living Seed
+ case 48504:
+ {
+ triggered_spell_id = 48503;
+ basepoints0 = triggerAmount;
+ target = this;
+ break;
+ }
+ // Vampiric Touch (generic, used by some boss)
+ case 52723:
+ case 60501:
+ {
+ triggered_spell_id = 52724;
+ basepoints0 = damage / 2;
+ target = this;
+ break;
+ }
+ // Divine purpose
+ case 31871:
+ case 31872:
+ {
+ // Roll chane
+ if (!roll_chance_i(triggerAmount))
+ return false;
+
+ // Remove any stun effect on target
+ AuraMap& Auras = pVictim->GetAuras();
+ for(AuraMap::iterator iter = Auras.begin(); iter != Auras.end();)
+ {
+ SpellEntry const *spell = iter->second->GetSpellProto();
+ if( spell->Mechanic == MECHANIC_STUN ||
+ spell->EffectMechanic[iter->second->GetEffIndex()] == MECHANIC_STUN)
+ {
+ pVictim->RemoveAurasDueToSpell(spell->Id);
+ iter = Auras.begin();
+ }
+ else
+ ++iter;
+ }
+ return true;
+ }
}
break;
}
@@ -5614,7 +4977,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
// mana reward
- basepoints0 = (triggeredByAura->GetModifier()->m_amount * GetMaxPower(POWER_MANA) / 100);
+ basepoints0 = (triggerAmount * GetMaxPower(POWER_MANA) / 100);
target = this;
triggered_spell_id = 29442;
break;
@@ -5626,7 +4989,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
// mana cost save
- basepoints0 = procSpell->manaCost * triggeredByAura->GetModifier()->m_amount/100;
+ int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100;
+ basepoints0 = cost * triggerAmount/100;
if( basepoints0 <=0 )
return false;
@@ -5634,8 +4998,45 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 29077;
break;
}
+ // Hot Streak
+ if (dummySpell->SpellIconID == 2999)
+ {
+ if (effIndex!=0)
+ return true;
+ Aura *counter = GetAura(triggeredByAura->GetId(), 1);
+ if (!counter)
+ return true;
+
+ // Count spell criticals in a row in second aura
+ Modifier *mod = counter->GetModifier();
+ if (procEx & PROC_EX_CRITICAL_HIT)
+ {
+ mod->m_amount *=2;
+ if (mod->m_amount < 100) // not enough
+ return true;
+ // Crititcal counted -> roll chance
+ if (roll_chance_i(triggerAmount))
+ CastSpell(this, 48108, true, castItem, triggeredByAura);
+ }
+ mod->m_amount = 25;
+ return true;
+ }
+ // Burnout
+ if (dummySpell->SpellIconID == 2998)
+ {
+ if(!procSpell)
+ return false;
+
+ int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100;
+ basepoints0 = cost * triggerAmount/100;
+ if( basepoints0 <=0 )
+ return false;
+ triggered_spell_id = 44450;
+ target = this;
+ break;
+ }
// Incanter's Regalia set (add trigger chance to Mana Shield)
- if (dummySpell->SpellFamilyFlags & 0x0000000000008000LL)
+ if (dummySpell->SpellFamilyFlags[0] & 0x8000)
{
if(GetTypeId() != TYPEID_PLAYER)
return false;
@@ -5672,7 +5073,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case 11129:
{
//last charge and crit
- if (triggeredByAura->m_procCharges <= 1 && (procEx & PROC_EX_CRITICAL_HIT) )
+ if (triggeredByAura->GetAuraCharges() <= 1 && (procEx & PROC_EX_CRITICAL_HIT) )
{
RemoveAurasDueToSpell(28682); //-> remove Combustion auras
return true; // charge counting (will removed)
@@ -5687,7 +5088,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case SPELLFAMILY_WARRIOR:
{
// Retaliation
- if(dummySpell->SpellFamilyFlags==0x0000000800000000LL)
+ if(dummySpell->SpellFamilyFlags.IsEqual(0, 0x8, 0))
{
// check attack comes not from behind
if (!HasInArc(M_PI, pVictim))
@@ -5696,26 +5097,21 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 22858;
break;
}
- else if (dummySpell->SpellIconID == 1697) // Second Wind
+ // Second Wind
+ if (dummySpell->SpellIconID == 1697)
{
// only for spells and hit/crit (trigger start always) and not start from self casted spells (5530 Mace Stun Effect for example)
if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim)
return false;
// Need stun or root mechanic
- if (procSpell->Mechanic != MECHANIC_ROOT && procSpell->Mechanic != MECHANIC_STUN)
- {
- int32 i;
- for (i=0; i<3; i++)
- if (procSpell->EffectMechanic[i] == MECHANIC_ROOT || procSpell->EffectMechanic[i] == MECHANIC_STUN)
- break;
- if (i == 3)
- return false;
- }
+ if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_STUN))))
+ return false;
switch (dummySpell->Id)
{
case 29838: triggered_spell_id=29842; break;
case 29834: triggered_spell_id=29841; break;
+ case 42770: triggered_spell_id=42771; break;
default:
sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (SW)",dummySpell->Id);
return false;
@@ -5724,12 +5120,19 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
target = this;
break;
}
+ // Damage Shield
+ if (dummySpell->SpellIconID == 3214)
+ {
+ triggered_spell_id = 59653;
+ basepoints0 = GetShieldBlockValue() * triggerAmount / 100;
+ break;
+ }
break;
}
case SPELLFAMILY_WARLOCK:
{
// Seed of Corruption
- if (dummySpell->SpellFamilyFlags & 0x0000001000000000LL)
+ if (dummySpell->SpellFamilyFlags[1] & 0x00000010)
{
Modifier* mod = triggeredByAura->GetModifier();
// if damage is more than need or target die from damage deal finish spell
@@ -5773,6 +5176,16 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
mod->m_amount-=damage;
return true;
}
+ // Fel Synergy
+ if (dummySpell->SpellIconID == 3222)
+ {
+ target = GetPet();
+ if (!target)
+ return false;
+ triggered_spell_id = 54181;
+ basepoints0 = damage * triggerAmount / 100;
+ break;
+ }
switch(dummySpell->Id)
{
// Nightfall
@@ -5789,7 +5202,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case 30296:
{
// health
- basepoints0 = int32(damage*triggeredByAura->GetModifier()->m_amount/100);
+ basepoints0 = int32(damage*triggerAmount/100);
target = this;
triggered_spell_id = 30294;
break;
@@ -5808,7 +5221,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
// heal amount
- basepoints0 = damage * triggeredByAura->GetModifier()->m_amount/100;
+ basepoints0 = damage * triggerAmount/100;
triggered_spell_id = 37382;
break;
}
@@ -5824,7 +5237,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case SPELLFAMILY_PRIEST:
{
// Vampiric Touch
- if( dummySpell->SpellFamilyFlags & 0x0000040000000000LL )
+ if( dummySpell->SpellFamilyFlags[1] & 0x00000400 )
{
if(!pVictim || !pVictim->isAlive())
return false;
@@ -5834,10 +5247,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
// energize amount
- basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/100;
+ basepoints0 = triggerAmount*damage/100;
pVictim->CastCustomSpell(pVictim,34919,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
return true; // no hidden cooldown
}
+ // Divine Aegis
+ if (dummySpell->SpellIconID == 2820)
+ {
+ basepoints0 = damage * triggerAmount/100;
+ triggered_spell_id = 47753;
+ break;
+ }
switch(dummySpell->Id)
{
// Vampiric Embrace
@@ -5851,18 +5271,19 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
// heal amount
- basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/100;
- pVictim->CastCustomSpell(pVictim,15290,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
+ int32 team = triggerAmount*damage/500;
+ int32 self = triggerAmount*damage/100 - team;
+ pVictim->CastCustomSpell(pVictim,15290,&team,&self,NULL,true,castItem,triggeredByAura);
return true; // no hidden cooldown
}
// Priest Tier 6 Trinket (Ashtongue Talisman of Acumen)
case 40438:
{
// Shadow Word: Pain
- if( procSpell->SpellFamilyFlags & 0x0000000000008000LL )
+ if( procSpell->SpellFamilyFlags[0] & 0x8000 )
triggered_spell_id = 40441;
// Renew
- else if( procSpell->SpellFamilyFlags & 0x0000000000000010LL )
+ else if( procSpell->SpellFamilyFlags[0] & 0x10 )
triggered_spell_id = 40440;
else
return false;
@@ -5886,12 +5307,12 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
// heal amount
- basepoints0 = int32(damage * 2 / 100);
+ basepoints0 = damage * triggerAmount/100;
target = this;
triggered_spell_id = 39373;
break;
}
- // Vestments of Faith (Priest Tier 3) - 4 pieces bonus
+ // Greater Heal (Vestments of Faith (Priest Tier 3) - 4 pieces bonus)
case 28809:
{
triggered_spell_id = 28810;
@@ -5934,19 +5355,19 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
float chance;
// Starfire
- if( procSpell->SpellFamilyFlags & 0x0000000000000004LL )
+ if( procSpell->SpellFamilyFlags[0] & 0x4 )
{
triggered_spell_id = 40445;
chance = 25.f;
}
// Rejuvenation
- else if( procSpell->SpellFamilyFlags & 0x0000000000000010LL )
+ else if( procSpell->SpellFamilyFlags[0] & 0x10 )
{
triggered_spell_id = 40446;
chance = 25.f;
}
// Mangle (cat/bear)
- else if( procSpell->SpellFamilyFlags & 0x0000044000000000LL )
+ else if( procSpell->SpellFamilyFlags[1] & 0x00000440)
{
triggered_spell_id = 40452;
chance = 40.f;
@@ -5968,6 +5389,39 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
break;
}
}
+ // Eclipse
+ if (dummySpell->SpellIconID == 2856)
+ {
+ if (!procSpell)
+ return false;
+ // Only 0 aura can proc
+ if (effIndex!=0)
+ return true;
+ // Wrath crit
+ if (procSpell->SpellFamilyFlags[0] & 0x1)
+ {
+ if (!roll_chance_i(60))
+ return false;
+ triggered_spell_id = 48518;
+ target = this;
+ break;
+ }
+ // Starfire crit
+ if (procSpell->SpellFamilyFlags[0] & 0x4)
+ {
+ triggered_spell_id = 48517;
+ target = this;
+ break;
+ }
+ return false;
+ }
+ // Living Seed
+ else if (dummySpell->SpellIconID == 2860)
+ {
+ triggered_spell_id = 48504;
+ basepoints0 = triggerAmount * damage / 100;
+ break;
+ }
break;
}
case SPELLFAMILY_ROGUE:
@@ -5985,19 +5439,39 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
break;
}
}
+ // Cut to the Chase
+ if( dummySpell->SpellIconID == 2909 )
+ {
+ // "refresh your Slice and Dice duration to its 5 combo point maximum"
+ // lookup Slice and Dice
+ AuraList const& sd = GetAurasByType(SPELL_AURA_MOD_HASTE);
+ for(AuraList::const_iterator itr = sd.begin(); itr != sd.end(); ++itr)
+ {
+ SpellEntry const *spellProto = (*itr)->GetSpellProto();
+ if( spellProto->SpellFamilyName == SPELLFAMILY_ROGUE &&
+ spellProto->SpellFamilyFlags[0] & 0x40000)
+ {
+ (*itr)->SetAuraMaxDuration(GetSpellMaxDuration(spellProto));
+ (*itr)->RefreshAura();
+ return true;
+ }
+ }
+ return false;
+ }
+ // Deadly Brew
+ if( dummySpell->SpellIconID == 2963 )
+ {
+ triggered_spell_id = 25809;
+ break;
+ }
// Quick Recovery
if( dummySpell->SpellIconID == 2116 )
{
if(!procSpell)
return false;
- // only rogue's finishing moves (maybe need additional checks)
- if( procSpell->SpellFamilyName!=SPELLFAMILY_ROGUE ||
- (procSpell->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE) == 0)
- return false;
-
// energy cost save
- basepoints0 = procSpell->manaCost * triggeredByAura->GetModifier()->m_amount/100;
+ basepoints0 = procSpell->manaCost * triggerAmount/100;
if(basepoints0 <= 0)
return false;
@@ -6016,7 +5490,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
// mana cost save
- basepoints0 = procSpell->manaCost * 40/100;
+ int32 mana = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100;
+ basepoints0 = mana * 40/100;
if(basepoints0 <= 0)
return false;
@@ -6024,75 +5499,93 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 34720;
break;
}
+ // Hunting Party
+ if ( dummySpell->SpellIconID == 3406 )
+ {
+ triggered_spell_id = 57669;
+ target = this;
+ break;
+ }
+ // Lock and Load
+ if ( dummySpell->SpellIconID == 3579 )
+ {
+ // Proc only from periodic (from trap activation proc another aura of this spell)
+ if (!(procFlag & PROC_FLAG_ON_DO_PERIODIC) || !roll_chance_i(triggerAmount))
+ return false;
+ triggered_spell_id = 56453;
+ target = this;
+ break;
+ }
+ // Rapid Recuperation
+ if ( dummySpell->SpellIconID == 3560 )
+ {
+ // This effect only from Rapid Killing (mana regen)
+ if (!(procSpell->SpellFamilyFlags[1] & 0x01000000))
+ return false;
+ triggered_spell_id = 56654;
+ target = this;
+ break;
+ }
break;
}
case SPELLFAMILY_PALADIN:
{
- // Seal of Righteousness - melee proc dummy
- if (dummySpell->SpellFamilyFlags&0x000000008000000LL && triggeredByAura->GetEffIndex()==0)
+ // Seal of Righteousness - melee proc dummy (addition ${$MWS*(0.022*$AP+0.044*$SPH)} damage)
+ if (dummySpell->SpellFamilyFlags[0]&0x8000000 && effIndex==0)
{
- if(GetTypeId() != TYPEID_PLAYER)
- return false;
-
- uint32 spellId;
- switch (triggeredByAura->GetId())
- {
- case 21084: spellId = 25742; break; // Rank 1
- case 20287: spellId = 25740; break; // Rank 2
- case 20288: spellId = 25739; break; // Rank 3
- case 20289: spellId = 25738; break; // Rank 4
- case 20290: spellId = 25737; break; // Rank 5
- case 20291: spellId = 25736; break; // Rank 6
- case 20292: spellId = 25735; break; // Rank 7
- case 20293: spellId = 25713; break; // Rank 8
- case 27155: spellId = 27156; break; // Rank 9
- default:
- sLog.outError("Unit::HandleDummyAuraProc: non handled possibly SoR (Id = %u)", triggeredByAura->GetId());
- return false;
- }
- Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
- float speed = (item ? item->GetProto()->Delay : BASE_ATTACK_TIME)/1000.0f;
-
- float damageBasePoints;
- if(item && item->GetProto()->InventoryType == INVTYPE_2HWEAPON)
- // two hand weapon
- damageBasePoints=1.20f*triggeredByAura->GetModifier()->m_amount * 1.2f * 1.03f * speed/100.0f + 1;
- else
- // one hand weapon/no weapon
- damageBasePoints=0.85f*ceil(triggeredByAura->GetModifier()->m_amount * 1.2f * 1.03f * speed/100.0f) - 1;
-
- int32 damagePoint = int32(damageBasePoints + 0.03f * (GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE)+GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE))/2.0f) + 1;
-
- // apply damage bonuses manually
- if(damagePoint >= 0)
- damagePoint = SpellDamageBonus(pVictim, dummySpell, damagePoint, SPELL_DIRECT_DAMAGE);
-
- CastCustomSpell(pVictim,spellId,&damagePoint,NULL,NULL,true,NULL, triggeredByAura);
- return true; // no hidden cooldown
+ triggered_spell_id = 25742;
+ float ap = GetTotalAttackPowerValue(BASE_ATTACK);
+ int32 holy = SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) +
+ SpellBaseDamageBonusForVictim(SPELL_SCHOOL_MASK_HOLY, pVictim);
+ basepoints0 = GetAttackTime(BASE_ATTACK) * int32(ap*0.022f + 0.044f * holy) / 1000;
+ break;
}
- // Seal of Blood do damage trigger
- if(dummySpell->SpellFamilyFlags & 0x0000040000000000LL)
+ // Sacred Shield
+ if (dummySpell->SpellFamilyFlags[1]&0x00080000)
{
- switch(triggeredByAura->GetEffIndex())
- {
- case 0:
- triggered_spell_id = 31893;
- break;
- case 1:
- {
- // damage
- damage += CalculateDamage(BASE_ATTACK, false) * 35 / 100; // add spell damage from prev effect (35%)
- basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100;
-
- target = this;
- triggered_spell_id = 32221;
- break;
- }
- }
+ triggered_spell_id = 58597;
+ target = this;
+ break;
+ }
+ // Righteous Vengeance
+ if (dummySpell->SpellIconID == 3025)
+ {
+ // 4 damage tick
+ basepoints0 = triggerAmount*damage/400;
+ triggered_spell_id = 61840;
+ break;
+ }
+ // Sheath of Light
+ if (dummySpell->SpellIconID == 3030)
+ {
+ // 4 healing tick
+ basepoints0 = triggerAmount*damage/400;
+ triggered_spell_id = 54203;
+ break;
}
-
switch(dummySpell->Id)
{
+ // Judgement of Light
+ case 20185:
+ {
+ // Get judgement caster
+ Unit *caster = triggeredByAura->GetCaster();
+ if (!caster)
+ return false;
+ float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
+ int32 holy = caster->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) +
+ caster->SpellBaseDamageBonusForVictim(SPELL_SCHOOL_MASK_HOLY, this);
+ basepoints0 = int32(ap*0.10f + 0.10f*holy);
+ pVictim->CastCustomSpell(pVictim, 20267, &basepoints0, 0, 0, true, 0, triggeredByAura);
+ return true;
+ }
+ // Judgement of Wisdom
+ case 20186:
+ {
+ if (pVictim->getPowerType() == POWER_MANA)
+ pVictim->CastSpell(pVictim, 20268, true, 0, triggeredByAura);
+ return true;
+ }
// Holy Power (Redemption Armor set)
case 28789:
{
@@ -6124,7 +5617,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
}
break;
}
- //Seal of Vengeance
+ // Seal of Vengeance (damage calc on apply aura)
case 31801:
{
if(effIndex != 0) // effect 1,2 used by seal unleashing code
@@ -6133,7 +5626,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 31803;
break;
}
- // Spiritual Att.
+ // Spiritual Attunement
case 31785:
case 33776:
{
@@ -6142,11 +5635,45 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
// heal amount
- basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/100;
+ basepoints0 = triggerAmount*damage/100;
target = this;
triggered_spell_id = 31786;
break;
}
+ // Seal of Blood do damage trigger
+ case 31892:
+ {
+ if (effIndex == 0) // 0 effect - is proc on enemy
+ triggered_spell_id = 31893;
+ else if (effIndex == 1) // 1 effect - is proc on self
+ {
+ // add spell damage from prev effect (27%)
+ damage += CalculateDamage(BASE_ATTACK, false) * 27 / 100;
+ basepoints0 = triggerAmount * damage / 100;
+ target = this;
+ triggered_spell_id = 32221;
+ }
+ else
+ return true;
+ break;
+ }
+ // Seal of the Martyr do damage trigger
+ case 53720:
+ {
+ if (effIndex == 0) // 0 effect - is proc on enemy
+ triggered_spell_id = 53719;
+ else if (effIndex == 1) // 1 effect - is proc on self
+ {
+ // add spell damage from prev effect (27%)
+ damage += CalculateDamage(BASE_ATTACK, false) * 27 / 100;
+ basepoints0 = triggerAmount * damage / 100;
+ target = this;
+ triggered_spell_id = 53718;
+ }
+ else
+ return true;
+ break;
+ }
// Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
case 40470:
{
@@ -6156,13 +5683,13 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
float chance;
// Flash of light/Holy light
- if( procSpell->SpellFamilyFlags & 0x00000000C0000000LL)
+ if( procSpell->SpellFamilyFlags[0] & 0xC0000000)
{
triggered_spell_id = 40471;
chance = 15.f;
}
// Judgement
- else if( procSpell->SpellFamilyFlags & 0x0000000000800000LL )
+ else if( procSpell->SpellFamilyFlags[0] & 0x800000 )
{
triggered_spell_id = 40472;
chance = 50.f;
@@ -6175,6 +5702,33 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
break;
}
+ // Glyph of Divinity
+ case 54939:
+ {
+ // Lookup base amount mana restore
+ for (int i=0; i<3;i++)
+ if (procSpell->Effect[i] == SPELL_EFFECT_ENERGIZE)
+ {
+ int32 mana = procSpell->EffectBasePoints[i];
+ CastCustomSpell(this, 54986, 0, &mana, 0, true, castItem, triggeredByAura);
+ break;
+ }
+ return true;
+ }
+ // Glyph of Flash of Light
+ case 54936:
+ {
+ triggered_spell_id = 54957;
+ basepoints0 = triggerAmount*damage/100;
+ break;
+ }
+ // Glyph of Holy Light
+ case 54937:
+ {
+ triggered_spell_id = 54968;
+ basepoints0 = triggerAmount*damage/100;
+ break;
+ }
}
break;
}
@@ -6233,14 +5787,19 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
if( cooldown && ((Player*)this)->HasSpellCooldown(dummySpell->Id))
return false;
+ // Now amount of extra power stored in 1 effect of Enchant spell
+ // Get it by item enchant id
uint32 spellId;
switch (castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)))
{
- case 283: spellId = 33757; break; //1 Rank
- case 284: spellId = 33756; break; //2 Rank
- case 525: spellId = 33755; break; //3 Rank
- case 1669:spellId = 33754; break; //4 Rank
- case 2636:spellId = 33727; break; //5 Rank
+ case 283: spellId = 8232; break; // 1 Rank
+ case 284: spellId = 8235; break; // 2 Rank
+ case 525: spellId = 10486; break; // 3 Rank
+ case 1669:spellId = 16362; break; // 4 Rank
+ case 2636:spellId = 25505; break; // 5 Rank
+ case 3785:spellId = 58801; break; // 6 Rank
+ case 3786:spellId = 58803; break; // 7 Rank
+ case 3787:spellId = 58804; break; // 8 Rank
default:
{
sLog.outError("Unit::HandleDummyAuraProc: non handled item enchantment (rank?) %u for spell id: %u (Windfury)",
@@ -6256,7 +5815,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
}
- int32 extra_attack_power = CalculateSpellDamage(windfurySpellEntry,0,windfurySpellEntry->EffectBasePoints[0],pVictim);
+ int32 extra_attack_power = CalculateSpellDamage(windfurySpellEntry, 1, windfurySpellEntry->EffectBasePoints[1], pVictim);
// Off-Hand case
if ( castItem->GetSlot() == EQUIPMENT_SLOT_OFFHAND )
@@ -6290,17 +5849,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
float chance;
- if (procSpell->SpellFamilyFlags & 0x0000000000000001LL)
+ if (procSpell->SpellFamilyFlags[0] & 0x1)
{
triggered_spell_id = 40465; // Lightning Bolt
chance = 15.f;
}
- else if (procSpell->SpellFamilyFlags & 0x0000000000000080LL)
+ else if (procSpell->SpellFamilyFlags[0] & 0x80)
{
triggered_spell_id = 40465; // Lesser Healing Wave
chance = 10.f;
}
- else if (procSpell->SpellFamilyFlags & 0x0000001000000000LL)
+ else if (procSpell->SpellFamilyFlags[1] & 0x00000010)
{
triggered_spell_id = 40466; // Stormstrike
chance = 50.f;
@@ -6314,20 +5873,69 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
target = this;
break;
}
+ // Glyph of Healing Wave
+ case 55440:
+ {
+ // Not proc from self heals
+ if (this==pVictim)
+ return false;
+ basepoints0 = triggerAmount * damage / 100;
+ target = this;
+ triggered_spell_id = 55533;
+ break;
+ }
+ // Spirit Hunt
+ case 58877:
+ {
+ // Cast on owner
+ target = GetOwner();
+ if(!target)
+ return false;
+ basepoints0 = triggerAmount * damage / 100;
+ triggered_spell_id = 58879;
+ break;
+ }
+ }
+ // Ancestral Awakening
+ if (dummySpell->SpellIconID == 2018)
+ {
+ // TODO: frite dummy fot triggered spell
+ triggered_spell_id = 52759;
+ basepoints0 = triggerAmount * damage / 100;
+ target = this;
+ break;
}
-
// Earth Shield
- if(dummySpell->SpellFamilyFlags==0x40000000000LL)
+ if(dummySpell->SpellFamilyFlags[1] & 0x00000400)
{
- if(GetTypeId() != TYPEID_PLAYER)
- return false;
-
- // heal
- basepoints0 = triggeredByAura->GetModifier()->m_amount;
+ basepoints0 = triggerAmount;
target = this;
triggered_spell_id = 379;
break;
}
+ // Improved Water Shield
+ if (dummySpell->SpellIconID == 2287)
+ {
+ // Lesser Healing Wave need aditional 60% roll
+ if (procSpell->SpellFamilyFlags[0] & 0x80 && !roll_chance_i(60))
+ return false;
+ // lookup water shield
+ AuraList const& vs = GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
+ for(AuraList::const_iterator itr = vs.begin(); itr != vs.end(); ++itr)
+ {
+ if( (*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN &&
+ (*itr)->GetSpellProto()->SpellFamilyFlags[1] & 0x00000020)
+ {
+ uint32 spell = (*itr)->GetSpellProto()->EffectTriggerSpell[(*itr)->GetEffIndex()];
+ CastSpell(this, spell, true, castItem, triggeredByAura);
+ if ((*itr)->DropAuraCharge())
+ RemoveAurasDueToSpell((*itr)->GetId());
+ return true;
+ }
+ }
+ return false;
+ break;
+ }
// Lightning Overload
if (dummySpell->SpellIconID == 2018) // only this spell have SpellFamily Shaman SpellIconID == 2018 and dummy aura
{
@@ -6355,6 +5963,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
@@ -6362,31 +5972,26 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case 10605: spellId = 45300; break; // Rank 4
case 25439: spellId = 45301; break; // Rank 5
case 25442: spellId = 45302; break; // Rank 6
+ case 49268: spellId = 49270; break; // Rank 7
+ case 49269: spellId = 49271; break; // Rank 8
default:
sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id);
return false;
}
// No thread generated mod
+ // TODO: exist special flag in spell attributes for this, need found and use!
SpellModifier *mod = new SpellModifier;
mod->op = SPELLMOD_THREAT;
mod->value = -100;
mod->type = SPELLMOD_PCT;
mod->spellId = dummySpell->Id;
- mod->effectId = 0;
- mod->lastAffected = NULL;
- mod->mask = 0x0000000000000003LL;
- mod->charges = 0;
+ mod->mask[0] = 0x3;
((Player*)this)->AddSpellMod(mod, true);
// Remove cooldown (Chain Lightning - have Category Recovery time)
- if (procSpell->SpellFamilyFlags & 0x0000000000000002LL)
+ if (procSpell->SpellFamilyFlags[0] & 0x2)
((Player*)this)->RemoveSpellCooldown(spellId);
- // Hmmm.. in most case spells already set half basepoints but...
- // Lightning Bolt (2-10 rank) have full basepoint and half bonus from level
- // As on wiki:
- // BUG: Rank 2 to 10 (and maybe 11) of Lightning Bolt will proc another Bolt with FULL damage (not halved). This bug is known and will probably be fixed soon.
- // So - no add changes :)
CastSpell(pVictim, spellId, true, castItem, triggeredByAura);
((Player*)this)->AddSpellMod(mod, false);
@@ -6396,6 +6001,117 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return true;
}
+ // Static Shock
+ if(dummySpell->SpellIconID == 3059)
+ {
+ // lookup Lightning Shield
+ AuraList const& vs = GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
+ for(AuraList::const_iterator itr = vs.begin(); itr != vs.end(); ++itr)
+ {
+ if( (*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN &&
+ (*itr)->GetSpellProto()->SpellFamilyFlags[0] & 0x400)
+ {
+ uint32 spell = 0;
+ switch ((*itr)->GetId())
+ {
+ case 324: spell = 26364; break;
+ case 325: spell = 26365; break;
+ case 905: spell = 26366; break;
+ case 945: spell = 26367; break;
+ case 8134: spell = 26369; break;
+ case 10431: spell = 26370; break;
+ case 10432: spell = 26363; break;
+ case 25469: spell = 26371; break;
+ case 25472: spell = 26372; break;
+ case 49280: spell = 49278; break;
+ case 49281: spell = 49279; break;
+ default:
+ return false;
+ }
+ CastSpell(this, spell, true, castItem, triggeredByAura);
+ if ((*itr)->DropAuraCharge())
+ RemoveAurasDueToSpell((*itr)->GetId());
+ return true;
+ }
+ }
+ return false;
+ break;
+ }
+ break;
+ }
+ case SPELLFAMILY_DEATHKNIGHT:
+ {
+ // Blood Aura
+ if (dummySpell->SpellIconID == 2636)
+ {
+ if (GetTypeId() != TYPEID_PLAYER || !((Player*)this)->isHonorOrXPTarget(pVictim))
+ return false;
+ basepoints0 = triggerAmount * damage / 100;
+ triggered_spell_id = 53168;
+ break;
+ }
+ // Butchery
+ if (dummySpell->SpellIconID == 2664)
+ {
+ basepoints0 = triggerAmount;
+ triggered_spell_id = 50163;
+ target = this;
+ break;
+ }
+ // Dancing Rune Weapon
+ if (dummySpell->Id == 49028)
+ {
+ // 1 dummy aura for dismiss rune blade
+ if (effIndex!=2)
+ return false;
+ // TODO: wite script for this "fights on its own, doing the same attacks"
+ // NOTE: Trigger here on every attack and spell cast
+ return false;
+ }
+ // Mark of Blood
+ if (dummySpell->Id == 49005)
+ {
+ // TODO: need more info (cooldowns/PPM)
+ triggered_spell_id = 50424;
+ break;
+ }
+ // Vendetta
+ if (dummySpell->SpellFamilyFlags[0] & 0x10000)
+ {
+ basepoints0 = triggerAmount * GetMaxHealth() / 100;
+ triggered_spell_id = 50181;
+ target = this;
+ break;
+ }
+ // Necrosis
+ if (dummySpell->SpellIconID == 2709)
+ {
+ basepoints0 = triggerAmount * damage / 100;
+ triggered_spell_id = 51460;
+ break;
+ }
+ // Runic Power Back on Snare/Root
+ if (dummySpell->Id == 61257)
+ {
+ // only for spells and hit/crit (trigger start always) and not start from self casted spells
+ if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim)
+ return false;
+ // Need snare or root mechanic
+ if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_SNARE))))
+ return false;
+ triggered_spell_id = 61258;
+ target = this;
+ break;
+ }
+ // Wandering Plague
+ if (dummySpell->SpellIconID == 1614)
+ {
+ if (!roll_chance_f(GetUnitCriticalChance(BASE_ATTACK, pVictim)))
+ return false;
+ basepoints0 = triggerAmount * damage / 100;
+ triggered_spell_id = 50526;
+ break;
+ }
break;
}
default:
@@ -6431,1172 +6147,518 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return true;
}
-/*
-bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags,WeaponAttackType attackType, uint32 cooldown)
+
+bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown)
{
+ // Get triggered aura spell info
SpellEntry const* auraSpellInfo = triggeredByAura->GetSpellProto();
+ // Basepoints of trigger aura
+ int32 triggerAmount = triggeredByAura->GetModifier()->m_amount;
+
+ // Set trigger spell id, target, custom basepoints
+ uint32 trigger_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()];
+ Unit* target = NULL;
+ int32 basepoints0 = 0;
+
+ if(triggeredByAura->GetModifier()->m_auraname == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE)
+ basepoints0 = triggerAmount;
+
Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
- uint32 triggered_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()];
- Unit* target = !(procFlags & PROC_FLAG_HEAL) && IsPositiveSpell(triggered_spell_id) ? this : pVictim;
- int32 basepoints0 = 0;
-
- switch(auraSpellInfo->SpellFamilyName)
+ // Try handle uncnown trigger spells
+ if (sSpellStore.LookupEntry(trigger_spell_id)==NULL)
{
- case SPELLFAMILY_GENERIC:
- {
- switch(auraSpellInfo->Id)
- {
- // Aegis of Preservation
- case 23780:
- //Aegis Heal (instead non-existed triggered spell)
- triggered_spell_id = 23781;
- target = this;
- break;
- // Elune's Touch (moonkin mana restore)
- case 24905:
- {
- // Elune's Touch (instead non-existed triggered spell)
- triggered_spell_id = 33926;
- basepoints0 = int32(0.3f * GetTotalAttackPowerValue(BASE_ATTACK));
- target = this;
+ switch (auraSpellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ //if (auraSpellInfo->Id==59532) // Abandon Passengers on Poly
+ //if (auraSpellInfo->Id==54775) // Abandon Vehicle on Poly
+ //if (auraSpellInfo->Id==34082) // Advantaged State (DND)
+ if (auraSpellInfo->Id == 23780) // Aegis of Preservation (Aegis of Preservation trinket)
+ trigger_spell_id = 23781;
+ //else if (auraSpellInfo->Id==43504) // Alterac Valley OnKill Proc Aura
+ //else if (auraSpellInfo->Id == 48876) // Beast's Mark
+ //{
+ // trigger_spell_id = 48877;
+ //}
+ //else if (auraSpellInfo->Id == 59237) // Beast's Mark
+ //{
+ // trigger_spell_id = 59233;
+ //}
+ //else if (auraSpellInfo->Id==46939) // Black Bow of the Betrayer
+ //{
+ // trigger_spell_id = 29471; // gain mana
+ // 27526; // drain mana if possible
+ //}
+ //else if (auraSpellInfo->Id==50844) // Blood Mirror
+ //else if (auraSpellInfo->Id==54476) // Blood Presence
+ //else if (auraSpellInfo->Id==50689) // Blood Presence (Rank 1)
+ //else if (auraSpellInfo->Id==37030) // Chaotic Temperament
+ //else if (auraSpellInfo->Id==52856) // Charge
+ else if (auraSpellInfo->Id==43820) // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket)
+ {
+ // Pct value stored in dummy
+ basepoints0 = pVictim->GetCreateHealth() * auraSpellInfo->EffectBasePoints[1] / 100;
+ target = pVictim;
break;
}
- // Enlightenment
- case 29601:
- {
- // only for cast with mana price
- if(!procSpell || procSpell->powerType!=POWER_MANA || procSpell->manaCost==0 && procSpell->ManaCostPercentage==0 && procSpell->manaCostPerlevel==0)
- return false;
- break; // fall through to normal cast
+ //else if (auraSpellInfo->Id==41248) // Consuming Strikes
+ // trigger_spell_id = 41249;
+ //else if (auraSpellInfo->Id==45205) // Copy Offhand Weapon
+ //else if (auraSpellInfo->Id==57594) // Copy Ranged Weapon
+ //else if (auraSpellInfo->Id==41054) // Copy Weapon
+ // trigger_spell_id = 41055;
+ //else if (auraSpellInfo->Id==45343) // Dark Flame Aura
+ //else if (auraSpellInfo->Id==47300) // Dark Flame Aura
+ else if (auraSpellInfo->Id==57345) // Darkmoon Card: Greatness
+ {
+ uint32 stat = 0;
+ // strength
+ if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 60229;stat = GetStat(STAT_STRENGTH); }
+ // agility
+ if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 60233;stat = GetStat(STAT_AGILITY); }
+ // intellect
+ if (GetStat(STAT_INTELLECT)> stat) { trigger_spell_id = 60234;stat = GetStat(STAT_INTELLECT);}
+ // spirit
+ if (GetStat(STAT_SPIRIT) > stat) { trigger_spell_id = 60235;stat = GetStat(STAT_SPIRIT); }
}
- // Health Restore
- case 33510:
+ //else if (auraSpellInfo->Id==31255) // Deadly Swiftness (Rank 1)
+ //else if (auraSpellInfo->Id==5301) // Defensive State (DND)
+ //else if (auraSpellInfo->Id==13358) // Defensive State (DND)
+ //else if (auraSpellInfo->Id==16092) // Defensive State (DND)
+ //else if (auraSpellInfo->Id==24949) // Defensive State 2 (DND)
+ //else if (auraSpellInfo->Id==40329) // Demo Shout Sensor
+ else if (auraSpellInfo->Id == 33896) // Desperate Defense (Stonescythe Whelp, Stonescythe Alpha, Stonescythe Ambusher)
+ trigger_spell_id = 33898;
+ //else if (auraSpellInfo->Id==18943) // Double Attack
+ //else if (auraSpellInfo->Id==19194) // Double Attack
+ //else if (auraSpellInfo->Id==19817) // Double Attack
+ //else if (auraSpellInfo->Id==19818) // Double Attack
+ //else if (auraSpellInfo->Id==22835) // Drunken Rage
+ // trigger_spell_id = 14822;
+ /*
+ else if (auraSpellInfo->SpellIconID==191) // Elemental Response
{
- // at melee hit call std triggered spell
- if(procFlags & PROC_FLAG_HIT_MELEE)
- break; // fall through to normal cast
-
- // Mark of Conquest - else (at range hit) called custom case
- triggered_spell_id = 39557;
- target = this;
- break;
+ switch (auraSpellInfo->Id && auraSpellInfo->AttributesEx==0)
+ {
+ case 34191:
+ case 34329:
+ case 34524:
+ case 34582:
+ case 36733:
+ break;
+ default:
+ sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Elemental Response",auraSpellInfo->Id);
+ return false;
+ }
+ //This generic aura self-triggers a different spell for each school of magic that lands on the wearer:
+ switch (procSpell->School)
+ {
+ case SPELL_SCHOOL_FIRE: trigger_spell_id = 34192; break;
+ case SPELL_SCHOOL_FROST: trigger_spell_id = 34193; break;
+ case SPELL_SCHOOL_ARCANE:trigger_spell_id = 34194; break;
+ case SPELL_SCHOOL_NATURE:trigger_spell_id = 34195; break;
+ case SPELL_SCHOOL_SHADOW:trigger_spell_id = 34196; break;
+ case SPELL_SCHOOL_HOLY: trigger_spell_id = 34197; break;
+ case SPELL_SCHOOL_NORMAL:trigger_spell_id = 34198; break;
+ default:
+ sLog.outError("Unit::HandleProcTriggerSpell: Spell %u Elemental Response wrong school",auraSpellInfo->Id);
+ return false;
+ }
}
- // Shaleskin
- case 36576:
- return true; // nothing to do
- // Forgotten Knowledge (Blade of Wizardry)
- case 38319:
- // only for harmful enemy targeted spell
- if(!pVictim || pVictim==this || !procSpell || IsPositiveSpell(procSpell->Id))
- return false;
- break; // fall through to normal cast
- // Aura of Wrath (Darkmoon Card: Wrath trinket bonus)
- case 39442:
- {
- // proc only at non-crit hits
- if(procFlags & (PROC_FLAG_CRIT_MELEE|PROC_FLAG_CRIT_RANGED|PROC_FLAG_CRIT_SPELL))
- return false;
- break; // fall through to normal cast
+ */
+ //else if (auraSpellInfo->Id==40364) // Entangling Roots Sensor
+ //else if (auraSpellInfo->Id==33207) // Gossip NPC Periodic - Fidget
+ //else if (auraSpellInfo->Id==50051) // Ethereal Pet Aura
+ //else if (auraSpellInfo->Id==35321) // Gushing Wound
+ //else if (auraSpellInfo->Id==38363) // Gushing Wound
+ //else if (auraSpellInfo->Id==39215) // Gushing Wound
+ //else if (auraSpellInfo->Id==44527) // Hate Monster (Spar Buddy) (30 sec)
+ //else if (auraSpellInfo->Id==44819) // Hate Monster (Spar Buddy) (>30% Health)
+ //else if (auraSpellInfo->Id==44526) // Hate Monster (Spar) (30 sec)
+ //else if (auraSpellInfo->Id==44820) // Hate Monster (Spar) (<30%)
+ //else if (auraSpellInfo->Id==49059) // Horde, Hate Monster (Spar Buddy) (>30% Health)
+ //else if (auraSpellInfo->Id==40250) // Improved Duration
+ //else if (auraSpellInfo->Id==59288) // Infra-Green Shield
+ //else if (auraSpellInfo->Id==54072) // Knockback Ball Passive
+ else if (auraSpellInfo->Id==27522 || auraSpellInfo->Id==40336)
+ // Mana Drain Trigger
+ {
+ // On successful melee or ranged attack gain $29471s1 mana and if possible drain $27526s1 mana from the target.
+ if (this && this->isAlive())
+ CastSpell(this, 29471, true, castItem, triggeredByAura);
+ if (pVictim && pVictim->isAlive())
+ CastSpell(pVictim, 27526, true, castItem, triggeredByAura);
+ return true;
}
- // Augment Pain (Timbal's Focusing Crystal trinket bonus)
- case 45054:
+ //else if (auraSpellInfo->Id==55580) // Mana Link
+ //else if (auraSpellInfo->Id==45903) // Offensive State
+ //else if (auraSpellInfo->Id==44326) // Pure Energy Passive
+ //else if (auraSpellInfo->Id==43453) // Rune Ward
+ //else if (auraSpellInfo->Id== 7137) // Shadow Charge (Rank 1)
+ //else if (auraSpellInfo->Id==36576) // Shaleskin (Shaleskin Flayer, Shaleskin Ripper) 30023 trigger
+ //else if (auraSpellInfo->Id==34783) // Spell Reflection
+ //else if (auraSpellInfo->Id==36096) // Spell Reflection
+ //else if (auraSpellInfo->Id==57587) // Steal Ranged ()
+ //else if (auraSpellInfo->Id==36207) // Steal Weapon
+ //else if (auraSpellInfo->Id== 7377) // Take Immune Periodic Damage <Not Working>
+ //else if (auraSpellInfo->Id==35205) // Vanish
+ //else if (auraSpellInfo->Id==42730) // Woe Strike
+ //else if (auraSpellInfo->Id==59735) // Woe Strike
+ //else if (auraSpellInfo->Id==46146) // [PH] Ahune Spanky Hands
+ break;
+ case SPELLFAMILY_MAGE:
+ if (auraSpellInfo->SpellIconID == 2127) // Blazing Speed
{
- if(!procSpell)
- return false;
-
- //only periodic damage can trigger spell
- bool found = false;
- for(int j = 0; j < 3; ++j)
+ switch (auraSpellInfo->Id)
{
- if( procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_DAMAGE ||
- procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_DAMAGE_PERCENT ||
- procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_LEECH )
- {
- found = true;
+ case 31641: // Rank 1
+ case 31642: // Rank 2
+ trigger_spell_id = 31643;
break;
- }
+ default:
+ sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Blazing Speed",auraSpellInfo->Id);
+ return false;
}
- if(!found)
- return false;
-
- break; // fall through to normal cast
}
- // Evasive Maneuvers (Commendation of Kael'thas)
- case 45057:
+ break;
+ case SPELLFAMILY_WARRIOR:
+ if (auraSpellInfo->Id == 50421) // Scent of Blood
+ trigger_spell_id = 50422;
+ break;
+ case SPELLFAMILY_WARLOCK:
+ {
+ // Pyroclasm
+ if (auraSpellInfo->SpellIconID == 1137)
{
- // damage taken that reduces below 35% health
- // does NOT mean you must have been >= 35% before
- if (int32(GetHealth())-int32(damage) >= int32(GetMaxHealth()*0.35f))
+ if(!pVictim || !pVictim->isAlive() || pVictim == this || procSpell == NULL)
+ return false;
+ // Calculate spell tick count for spells
+ uint32 tick = 1; // Default tick = 1
+
+ // Hellfire have 15 tick
+ if (procSpell->SpellFamilyFlags[0]&0x40)
+ tick = 15;
+ // Rain of Fire have 4 tick
+ else if (procSpell->SpellFamilyFlags[0]&0x20)
+ tick = 4;
+ else
return false;
- break; // fall through to normal cast
- }
- }
- switch(triggered_spell_id)
- {
- // Setup
- case 15250:
- {
- // applied only for main target
- if(!pVictim || pVictim != getVictim())
+ // Calculate chance = baseChance / tick
+ float chance = 0;
+ switch (auraSpellInfo->Id)
+ {
+ case 18096: chance = 13.0f / tick; break;
+ case 18073: chance = 26.0f / tick; break;
+ }
+ // Roll chance
+ if (!roll_chance_f(chance))
return false;
- // continue normal case
- break;
+ trigger_spell_id = 18093;
}
- // Shamanistic Rage triggered spell
- case 30824:
- basepoints0 = int32(GetTotalAttackPowerValue(BASE_ATTACK)*triggeredByAura->GetModifier()->m_amount/100);
- break;
- }
- break;
- }
- case SPELLFAMILY_MAGE:
- {
- switch(auraSpellInfo->SpellIconID)
- {
- // Blazing Speed
- case 2127:
- //Blazing Speed (instead non-existed triggered spell)
- triggered_spell_id = 31643;
- target = this;
- break;
- }
- switch(auraSpellInfo->Id)
- {
- // Persistent Shield (Scarab Brooch)
- case 26467:
- basepoints0 = int32(damage * 0.15f);
- break;
- }
- break;
- }
- case SPELLFAMILY_WARRIOR:
- {
- //Rampage
- if((auraSpellInfo->SpellFamilyFlags & 0x100000) && auraSpellInfo->SpellIconID==2006)
- {
- //all ranks have effect[0]==AURA (Proc Trigger Spell, non-existed)
- //and effect[1]==TriggerSpell
- if(auraSpellInfo->Effect[1]!=SPELL_EFFECT_TRIGGER_SPELL)
+ // Drain Soul
+ else if (auraSpellInfo->SpellFamilyFlags[0] & 0x4000)
{
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u have wrong effect in RM",triggeredByAura->GetSpellProto()->Id);
- return false;
- }
- triggered_spell_id = auraSpellInfo->EffectTriggerSpell[1];
- break; // fall through to normal cast
- }
- break;
- }
- case SPELLFAMILY_WARLOCK:
- {
- // Pyroclasm
- if(auraSpellInfo->SpellFamilyFlags == 0x0000000000000000 && auraSpellInfo->SpellIconID==1137)
- {
- // last case for Hellfire that damage caster also but don't must stun caster
- if( pVictim == this )
+ Unit::AuraList const& mAddFlatModifier = GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
+ for(Unit::AuraList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i)
+ {
+ if ((*i)->GetModifier()->m_miscvalue == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellProto()->SpellIconID == 113)
+ {
+ int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this);
+ // Drain Soul
+ CastCustomSpell(this, 18371, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
+ break;
+ }
+ }
+ // Not remove charge (aura removed on death in any cases)
+ // Need for correct work Drain Soul SPELL_AURA_CHANNEL_DEATH_ITEM aura
return false;
-
- // custom chance
- float chance = 0;
- switch (triggeredByAura->GetId())
- {
- case 18096: chance = 13.0f; break;
- case 18073: chance = 26.0f; break;
}
- if (!roll_chance_f(chance))
- return false;
-
- // Pyroclasm (instead non-existed triggered spell)
- triggered_spell_id = 18093;
- target = pVictim;
- break;
- }
- // Drain Soul
- if(auraSpellInfo->SpellFamilyFlags & 0x0000000000004000)
- {
- bool found = false;
- Unit::AuraList const& mAddFlatModifier = GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
- for(Unit::AuraList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i)
+ // Nether Protection
+ else if (auraSpellInfo->SpellIconID == 1985)
{
- //Improved Drain Soul
- if ((*i)->GetModifier()->m_miscvalue == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellProto()->SpellIconID == 113)
+ if (!procSpell)
+ return false;
+ switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell)))
{
- int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this);
- basepoints0 = value2 * GetMaxPower(POWER_MANA) / 100;
- // Drain Soul
- CastCustomSpell(this, 18371, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- break;
+ case SPELL_SCHOOL_NORMAL:
+ case SPELL_SCHOOL_HOLY:
+ return false; // ignore
+ case SPELL_SCHOOL_FIRE: trigger_spell_id = 54371; break;
+ case SPELL_SCHOOL_NATURE: trigger_spell_id = 54375; break;
+ case SPELL_SCHOOL_FROST: trigger_spell_id = 54372; break;
+ case SPELL_SCHOOL_SHADOW: trigger_spell_id = 54374; break;
+ case SPELL_SCHOOL_ARCANE: trigger_spell_id = 54373; break;
+ default:
+ return false;
}
}
- // Not remove charge (aura removed on death in any cases)
- // Need for correct work Drain Soul SPELL_AURA_CHANNEL_DEATH_ITEM aura
- return false;
+ break;
}
- break;
- }
- case SPELLFAMILY_PRIEST:
- {
- //Blessed Recovery
- if(auraSpellInfo->SpellFamilyFlags == 0x00000000LL && auraSpellInfo->SpellIconID==1875)
+ case SPELLFAMILY_PRIEST:
{
- switch (triggeredByAura->GetSpellProto()->Id)
+ // Greater Heal Refund
+ if (auraSpellInfo->Id==37594)
+ trigger_spell_id = 37595;
+ // Blessed Recovery
+ else if (auraSpellInfo->SpellIconID == 1875)
{
- case 27811: triggered_spell_id = 27813; break;
- case 27815: triggered_spell_id = 27817; break;
- case 27816: triggered_spell_id = 27818; break;
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in BR",triggeredByAura->GetSpellProto()->Id);
- return false;
- }
-
- int32 heal_amount = damage * triggeredByAura->GetModifier()->m_amount / 100;
- basepoints0 = heal_amount/3;
- target = this;
- break;
- }
- // Shadowguard
- if((auraSpellInfo->SpellFamilyFlags & 0x80000000LL) && auraSpellInfo->SpellVisual==7958)
- {
- switch(triggeredByAura->GetSpellProto()->Id)
- {
- case 18137:
- triggered_spell_id = 28377; break; // Rank 1
- case 19308:
- triggered_spell_id = 28378; break; // Rank 2
- case 19309:
- triggered_spell_id = 28379; break; // Rank 3
- case 19310:
- triggered_spell_id = 28380; break; // Rank 4
- case 19311:
- triggered_spell_id = 28381; break; // Rank 5
- case 19312:
- triggered_spell_id = 28382; break; // Rank 6
- case 25477:
- triggered_spell_id = 28385; break; // Rank 7
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in SG",triggeredByAura->GetSpellProto()->Id);
+ switch (auraSpellInfo->Id)
+ {
+ case 27811: trigger_spell_id = 27813; break;
+ case 27815: trigger_spell_id = 27817; break;
+ case 27816: trigger_spell_id = 27818; break;
+ default:
+ sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id);
return false;
+ }
+ basepoints0 = damage * triggerAmount / 100 / 3;
+ target = this;
}
- target = pVictim;
break;
}
- break;
- }
- case SPELLFAMILY_DRUID:
- {
- switch(auraSpellInfo->Id)
+ case SPELLFAMILY_DRUID:
{
- // Leader of the Pack (triggering Improved Leader of the Pack heal)
- case 24932:
- {
- if (triggeredByAura->GetModifier()->m_amount == 0)
- return false;
- basepoints0 = triggeredByAura->GetModifier()->m_amount * GetMaxHealth() / 100;
- triggered_spell_id = 34299;
- break;
- };
- // Druid Forms Trinket (Druid Tier5 Trinket, triggers different spells per Form)
- case 37336:
+ // Druid Forms Trinket
+ if (auraSpellInfo->Id==37336)
{
switch(m_form)
{
+ case FORM_NONE: trigger_spell_id = 37344;break;
+ case FORM_CAT: trigger_spell_id = 37341;break;
case FORM_BEAR:
- case FORM_DIREBEAR:
- triggered_spell_id=37340; break;// Ursine Blessing
- case FORM_CAT:
- triggered_spell_id=37341; break;// Feline Blessing
- case FORM_TREE:
- triggered_spell_id=37342; break;// Slyvan Blessing
- case FORM_MOONKIN:
- triggered_spell_id=37343; break;// Lunar Blessing
- case FORM_NONE:
- triggered_spell_id=37344; break;// Cenarion Blessing (for caster form, except FORM_MOONKIN)
+ case FORM_DIREBEAR: trigger_spell_id = 37340;break;
+ case FORM_TREE: trigger_spell_id = 37342;break;
+ case FORM_MOONKIN: trigger_spell_id = 37343;break;
default:
return false;
}
-
- target = this;
- break;
}
- }
- break;
- }
- case SPELLFAMILY_ROGUE:
- {
- if(auraSpellInfo->SpellFamilyFlags == 0x0000000000000000LL)
- {
- switch(auraSpellInfo->SpellIconID)
+ //else if (auraSpellInfo->Id==40363)// Entangling Roots ()
+ // trigger_spell_id = ????;
+ // Leader of the Pack
+ else if (auraSpellInfo->Id == 24932)
{
- // Combat Potency
- case 2260:
- {
- // skip non offhand attacks
- if(attackType!=OFF_ATTACK)
- return false;
- break; // fall through to normal cast
- }
+ if (triggerAmount == 0)
+ return false;
+ basepoints0 = triggerAmount * GetMaxHealth() / 100;
+ trigger_spell_id = 34299;
}
+ break;
}
- break;
- }
- case SPELLFAMILY_PALADIN:
- {
- if(auraSpellInfo->SpellFamilyFlags == 0x00000000LL)
+ case SPELLFAMILY_HUNTER:
+ break;
+ case SPELLFAMILY_PALADIN:
{
- switch(auraSpellInfo->Id)
+ /*
+ // Blessed Life
+ if (auraSpellInfo->SpellIconID == 2137)
{
- // Lightning Capacitor
- case 37657:
+ switch (auraSpellInfo->Id)
{
- // trinket ProcTriggerSpell but for safe checks for player
- if(!castItem || !pVictim || !pVictim->isAlive() || GetTypeId()!=TYPEID_PLAYER)
- return false;
-
- if(((Player*)this)->HasSpellCooldown(37657))
- return false;
-
- // stacking
- CastSpell(this, 37658, true, castItem, triggeredByAura);
- // 2.5s cooldown before it can stack again, current system allow 1 sec step in cooldown
- ((Player*)this)->AddSpellCooldown(37657,0,time(NULL)+(roll_chance_i(50) ? 2 : 3));
-
- // counting
- Aura * dummy = GetDummyAura(37658);
- if (!dummy)
- return false;
-
- // release at 3 aura in stack
- if(dummy->GetStackAmount() <= 2)
- return true; // main triggered spell casted anyway
-
- RemoveAurasDueToSpell(37658);
- CastSpell(pVictim, 37661, true, castItem, triggeredByAura);
- return true;
- }
- // Healing Discount
- case 37705:
- // Healing Trance (instead non-existed triggered spell)
- triggered_spell_id = 37706;
- target = this;
- break;
- // HoTs on Heals (Fel Reaver's Piston trinket)
- case 38299:
- {
- // at direct heal effect
- if(!procSpell || !IsSpellHaveEffect(procSpell,SPELL_EFFECT_HEAL))
+ case 31828: // Rank 1
+ case 31829: // Rank 2
+ case 31830: // Rank 3
+ break;
+ default:
+ sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Blessed Life", auraSpellInfo->Id);
return false;
-
- // single proc at time
- AuraList const& scAuras = GetSingleCastAuras();
- for(AuraList::const_iterator itr = scAuras.begin(); itr != scAuras.end(); ++itr)
- if((*itr)->GetId()==triggered_spell_id)
- return false;
-
- // positive cast at victim instead self
- target = pVictim;
- break;
}
}
- switch(auraSpellInfo->SpellIconID)
+ */
+ // Healing Discount
+ if (auraSpellInfo->Id==37705)
{
- case 241:
- {
- switch(auraSpellInfo->EffectTriggerSpell[0])
- {
- //Illumination
- case 18350:
- {
- if(!procSpell)
- return false;
-
- // procspell is triggered spell but we need mana cost of original casted spell
- uint32 originalSpellId = procSpell->Id;
-
- // Holy Shock
- if(procSpell->SpellFamilyName == SPELLFAMILY_PALADIN)
- {
- if(procSpell->SpellFamilyFlags & 0x0001000000000000LL)
- {
- switch(procSpell->Id)
- {
- case 25914: originalSpellId = 20473; break;
- case 25913: originalSpellId = 20929; break;
- case 25903: originalSpellId = 20930; break;
- case 27175: originalSpellId = 27174; break;
- case 33074: originalSpellId = 33072; break;
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in HShock",procSpell->Id);
- return false;
- }
- }
- }
-
- SpellEntry const *originalSpell = sSpellStore.LookupEntry(originalSpellId);
- if(!originalSpell)
- {
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu",originalSpellId);
- return false;
- }
-
- // percent stored in effect 1 (class scripts) base points
- int32 percent = auraSpellInfo->EffectBasePoints[1]+1;
-
- basepoints0 = originalSpell->manaCost*percent/100;
- triggered_spell_id = 20272;
- target = this;
- break;
- }
- }
- break;
- }
+ trigger_spell_id = 37706;
+ target = this;
}
- }
- if(auraSpellInfo->SpellFamilyFlags & 0x00080000)
- {
- switch(auraSpellInfo->SpellIconID)
+ // Soul Preserver
+ if (auraSpellInfo->Id==60510)
{
- //Judgement of Wisdom (overwrite non existing triggered spell call in spell.dbc
- case 206:
+ trigger_spell_id = 60515;
+ target = this;
+ }
+ // Illumination
+ else if (auraSpellInfo->SpellIconID==241)
+ {
+ if(!procSpell)
+ return false;
+ // procspell is triggered spell but we need mana cost of original casted spell
+ uint32 originalSpellId = procSpell->Id;
+ // Holy Shock heal
+ if(procSpell->SpellFamilyFlags[1] & 0x00010000)
{
- if(!pVictim || !pVictim->isAlive())
- return false;
-
- switch(triggeredByAura->GetSpellProto()->Id)
+ switch(procSpell->Id)
{
- case 20186:
- triggered_spell_id = 20268; // Rank 1
- break;
- case 20354:
- triggered_spell_id = 20352; // Rank 2
- break;
- case 20355:
- triggered_spell_id = 20353; // Rank 3
- break;
- case 27164:
- triggered_spell_id = 27165; // Rank 4
- break;
+ case 25914: originalSpellId = 20473; break;
+ case 25913: originalSpellId = 20929; break;
+ case 25903: originalSpellId = 20930; break;
+ case 27175: originalSpellId = 27174; break;
+ case 33074: originalSpellId = 33072; break;
+ case 48820: originalSpellId = 48824; break;
+ case 48821: originalSpellId = 48825; break;
default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in JoW",triggeredByAura->GetSpellProto()->Id);
- return false;
+ sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in HShock",procSpell->Id);
+ return false;
}
-
- pVictim->CastSpell(pVictim,triggered_spell_id,true,castItem,triggeredByAura,GetGUID());
- return true; // no hidden cooldown
}
- //Judgement of Light
- case 299:
+ SpellEntry const *originalSpell = sSpellStore.LookupEntry(originalSpellId);
+ if(!originalSpell)
{
- if(!pVictim || !pVictim->isAlive())
- return false;
-
- // overwrite non existing triggered spell call in spell.dbc
- switch(triggeredByAura->GetSpellProto()->Id)
- {
- case 20185:
- triggered_spell_id = 20267; // Rank 1
- break;
- case 20344:
- triggered_spell_id = 20341; // Rank 2
- break;
- case 20345:
- triggered_spell_id = 20342; // Rank 3
- break;
- case 20346:
- triggered_spell_id = 20343; // Rank 4
- break;
- case 27162:
- triggered_spell_id = 27163; // Rank 5
- break;
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in JoL",triggeredByAura->GetSpellProto()->Id);
- return false;
- }
- pVictim->CastSpell(pVictim,triggered_spell_id,true,castItem,triggeredByAura,GetGUID());
- return true; // no hidden cooldown
+ sLog.outError("Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu",originalSpellId);
+ return false;
}
+ // percent stored in effect 1 (class scripts) base points
+ int32 cost = originalSpell->manaCost + originalSpell->ManaCostPercentage * GetCreateMana() / 100;
+ basepoints0 = cost*(auraSpellInfo->EffectBasePoints[1]+1)/100;
+ trigger_spell_id = 20272;
+ target = this;
}
- }
- // custom check for proc spell
- switch(auraSpellInfo->Id)
- {
- // Bonus Healing (item spell)
- case 40971:
+ // Lightning Capacitor
+ else if (auraSpellInfo->Id==37657)
{
if(!pVictim || !pVictim->isAlive())
return false;
+ // stacking
+ CastSpell(this, 37658, true, NULL, triggeredByAura);
- // bonus if health < 50%
- if(pVictim->GetHealth() >= pVictim->GetMaxHealth()*triggeredByAura->GetModifier()->m_amount/100)
+ Aura * dummy = GetDummyAura(37658);
+ // release at 3 aura in stack (cont contain in basepoint of trigger aura)
+ if(!dummy || dummy->GetStackAmount() < triggerAmount)
return false;
- // cast at target positive spell
+ RemoveAurasDueToSpell(37658);
+ trigger_spell_id = 37661;
target = pVictim;
- break;
}
- }
- switch(triggered_spell_id)
- {
- // Seal of Command
- case 20424:
- // prevent chain of triggered spell from same triggered spell
- if(procSpell && procSpell->Id==20424)
+ // Thunder Capacitor
+ else if (auraSpellInfo->Id == 54841)
+ {
+ if(!pVictim || !pVictim->isAlive())
return false;
- break;
+ // stacking
+ CastSpell(this, 54842, true, NULL, triggeredByAura);
+
+ // counting
+ Aura * dummy = GetDummyAura(54842);
+ // release at 3 aura in stack (cont contain in basepoint of trigger aura)
+ if(!dummy || dummy->GetStackAmount() < triggerAmount)
+ return false;
+
+ RemoveAurasDueToSpell(54842);
+ trigger_spell_id = 54843;
+ target = pVictim;
+ }
+ break;
}
- break;
- }
- case SPELLFAMILY_SHAMAN:
- {
- if(auraSpellInfo->SpellFamilyFlags == 0x0000000000000000)
+ case SPELLFAMILY_SHAMAN:
{
- switch(auraSpellInfo->SpellIconID)
+ // Lightning Shield (overwrite non existing triggered spell call in spell.dbc
+ if(auraSpellInfo->SpellFamilyFlags[0] & 0x400)
{
- case 19:
- {
- switch(auraSpellInfo->Id)
- {
- case 23551: // Lightning Shield - Tier2: 8 pieces proc shield
- {
- // Lightning Shield (overwrite non existing triggered spell call in spell.dbc)
- triggered_spell_id = 23552;
- target = pVictim;
- break;
- }
- case 23552: // Lightning Shield - trigger shield damage
- {
- // Lightning Shield (overwrite non existing triggered spell call in spell.dbc)
- triggered_spell_id = 27635;
- target = pVictim;
- break;
- }
- }
- break;
- }
- // Mana Surge (Shaman T1 bonus)
- case 87:
+ switch(auraSpellInfo->Id)
{
- if(!procSpell)
- return false;
-
- basepoints0 = procSpell->manaCost * 35/100;
- triggered_spell_id = 23571;
- target = this;
- break;
+ case 324: // Rank 1
+ trigger_spell_id = 26364; break;
+ case 325: // Rank 2
+ trigger_spell_id = 26365; break;
+ case 905: // Rank 3
+ trigger_spell_id = 26366; break;
+ case 945: // Rank 4
+ trigger_spell_id = 26367; break;
+ case 8134: // Rank 5
+ trigger_spell_id = 26369; break;
+ case 10431: // Rank 6
+ trigger_spell_id = 26370; break;
+ case 10432: // Rank 7
+ trigger_spell_id = 26363; break;
+ case 25469: // Rank 8
+ trigger_spell_id = 26371; break;
+ case 25472: // Rank 9
+ trigger_spell_id = 26372; break;
+ case 49280: // Rank 10
+ trigger_spell_id = 49278; break;
+ case 49281: // Rank 11
+ trigger_spell_id = 49279; break;
+ default:
+ sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield", auraSpellInfo->Id);
+ return false;
}
- //Nature's Guardian
- case 2013:
- {
- if(GetTypeId()!=TYPEID_PLAYER)
- return false;
-
- // damage taken that reduces below 30% health
- // does NOT mean you must have been >= 30% before
- if (10*(int32(GetHealth())-int32(damage)) >= 3*GetMaxHealth())
- return false;
-
- triggered_spell_id = 31616;
+ }
+ // Lightning Shield (The Ten Storms set)
+ else if (auraSpellInfo->Id == 23551)
+ {
+ trigger_spell_id = 23552;
+ target = pVictim;
+ }
+ // Damage from Lightning Shield (The Ten Storms set)
+ else if (auraSpellInfo->Id == 23552)
+ trigger_spell_id = 27635;
+ // Mana Surge (The Earthfury set)
+ else if (auraSpellInfo->Id == 23572)
+ {
+ if(!procSpell)
+ return false;
+ basepoints0 = procSpell->manaCost * 35 / 100;
+ trigger_spell_id = 23571;
+ target = this;
+ }
+ // Nature's Guardian
+ else if (auraSpellInfo->SpellIconID == 2013)
+ {
+ // Check health condition - should drop to less 30% (damage deal after this!)
+ if (!(10*(int32(GetHealth() - damage)) < 3 * GetMaxHealth()))
+ return false;
- // need check cooldown now
- if( cooldown && ((Player*)this)->HasSpellCooldown(triggered_spell_id))
- return false;
+ if(pVictim && pVictim->isAlive())
+ pVictim->getThreatManager().modifyThreatPercent(this,-10);
- basepoints0 = triggeredByAura->GetModifier()->m_amount * GetMaxHealth() / 100;
- target = this;
- if(pVictim && pVictim->isAlive())
- pVictim->getThreatManager().modifyThreatPercent(this,-10);
- break;
- }
+ basepoints0 = triggerAmount * GetMaxHealth() / 100;
+ trigger_spell_id = 31616;
+ target = this;
}
- }
-
- // Water Shield (we can't set cooldown for main spell - it's player casted spell
- if((auraSpellInfo->SpellFamilyFlags & 0x0000002000000000LL) && auraSpellInfo->SpellVisual==7358)
- {
- target = this;
break;
}
-
- // Lightning Shield
- if((auraSpellInfo->SpellFamilyFlags & 0x00000400) && auraSpellInfo->SpellVisual==37)
- {
- // overwrite non existing triggered spell call in spell.dbc
- switch(triggeredByAura->GetSpellProto()->Id)
- {
- case 324:
- triggered_spell_id = 26364; break; // Rank 1
- case 325:
- triggered_spell_id = 26365; break; // Rank 2
- case 905:
- triggered_spell_id = 26366; break; // Rank 3
- case 945:
- triggered_spell_id = 26367; break; // Rank 4
- case 8134:
- triggered_spell_id = 26369; break; // Rank 5
- case 10431:
- triggered_spell_id = 26370; break; // Rank 6
- case 10432:
- triggered_spell_id = 26363; break; // Rank 7
- case 25469:
- triggered_spell_id = 26371; break; // Rank 8
- case 25472:
- triggered_spell_id = 26372; break; // Rank 9
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield",triggeredByAura->GetSpellProto()->Id);
+ case SPELLFAMILY_DEATHKNIGHT:
+ {
+ // Acclimation
+ if (auraSpellInfo->SpellIconID == 1930)
+ {
+ if (!procSpell)
return false;
+ switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell)))
+ {
+ case SPELL_SCHOOL_NORMAL:
+ return false; // ignore
+ case SPELL_SCHOOL_HOLY: trigger_spell_id = 50490; break;
+ case SPELL_SCHOOL_FIRE: trigger_spell_id = 50362; break;
+ case SPELL_SCHOOL_NATURE: trigger_spell_id = 50488; break;
+ case SPELL_SCHOOL_FROST: trigger_spell_id = 50485; break;
+ case SPELL_SCHOOL_SHADOW: trigger_spell_id = 50489; break;
+ case SPELL_SCHOOL_ARCANE: trigger_spell_id = 54373; break;
+ default:
+ return false;
+ }
+ }
+ // Blood Presence
+ else if (auraSpellInfo->Id == 48266)
+ {
+ if (GetTypeId() != TYPEID_PLAYER)
+ return false;
+ if (!((Player*)this)->isHonorOrXPTarget(pVictim))
+ return false;
+ trigger_spell_id = 50475;
+ basepoints0 = damage * triggerAmount / 100;
}
-
- target = pVictim;
break;
}
- break;
- }
- }
-
- // standard non-dummy case
- if(!triggered_spell_id)
- {
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",auraSpellInfo->Id,triggeredByAura->GetEffIndex());
- return false;
- }
-
- SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id);
-
- if(!triggerEntry)
- {
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u have not existed EffectTriggered[%d]=%u, not handled custom case?",auraSpellInfo->Id,triggeredByAura->GetEffIndex(),triggered_spell_id);
- return false;
- }
-
- // not allow proc extra attack spell at extra attack
- if( m_extraAttacks && IsSpellHaveEffect(triggerEntry,SPELL_EFFECT_ADD_EXTRA_ATTACKS) )
- return false;
-
- if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id))
- return false;
-
- // default case
- if(!target || target!=this && !target->isAlive())
- return false;
-
- if(basepoints0)
- CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
- else
- CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura);
-
- if( cooldown && GetTypeId()==TYPEID_PLAYER )
- ((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown);
-
- return true;
-}
-*/
-
-bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown)
-{
- // Get triggered aura spell info
- SpellEntry const* auraSpellInfo = triggeredByAura->GetSpellProto();
-
- // Basepoints of trigger aura
- int32 triggerAmount = triggeredByAura->GetModifier()->m_amount;
-
- // Set trigger spell id, target, custom basepoints
- uint32 trigger_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()];
- Unit* target = NULL;
- int32 basepoints0 = 0;
-
- Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
- ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
-
- // Try handle uncnown trigger spells
- if (sSpellStore.LookupEntry(trigger_spell_id)==NULL)
- switch (auraSpellInfo->SpellFamilyName)
- {
- //=====================================================================
- // Generic class
- // ====================================================================
- // .....
- //=====================================================================
- case SPELLFAMILY_GENERIC:
-// if (auraSpellInfo->Id==34082) // Advantaged State (DND)
-// trigger_spell_id = ???;
- if (auraSpellInfo->Id == 23780) // Aegis of Preservation (Aegis of Preservation trinket)
- trigger_spell_id = 23781;
-// else if (auraSpellInfo->Id==43504) // Alterac Valley OnKill Proc Aura
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==37030) // Chaotic Temperament
-// trigger_spell_id = ;
- else if (auraSpellInfo->Id==43820) // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket)
- {
- // Pct value stored in dummy
- basepoints0 = pVictim->GetCreateHealth() * auraSpellInfo->EffectBasePoints[1] / 100;
- target = pVictim;
- break;
- }
-// else if (auraSpellInfo->Id==41248) // Consuming Strikes
-// trigger_spell_id = 41249;
-// else if (auraSpellInfo->Id==41054) // Copy Weapon
-// trigger_spell_id = 41055;
-// else if (auraSpellInfo->Id==31255) // Deadly Swiftness (Rank 1)
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==5301) // Defensive State (DND)
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==13358) // Defensive State (DND)
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==16092) // Defensive State (DND)
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==24949) // Defensive State 2 (DND)
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==40329) // Demo Shout Sensor
-// trigger_spell_id = ;
- // Desperate Defense (Stonescythe Whelp, Stonescythe Alpha, Stonescythe Ambusher)
- else if (auraSpellInfo->Id == 33896)
- trigger_spell_id = 33898;
-// else if (auraSpellInfo->Id==18943) // Double Attack
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==19194) // Double Attack
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==19817) // Double Attack
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==19818) // Double Attack
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==22835) // Drunken Rage
-// trigger_spell_id = 14822;
- /*
- else if (auraSpellInfo->SpellIconID==191) // Elemental Response
- {
- switch (auraSpellInfo->Id && auraSpellInfo->AttributesEx==0)
- {
- case 34191:
- case 34329:
- case 34524:
- case 34582:
- case 36733:break;
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Elemental Response",auraSpellInfo->Id);
- return false;
- }
- //This generic aura self-triggers a different spell for each school of magic that lands on the wearer:
- switch (procSpell->School)
- {
- case SPELL_SCHOOL_FIRE: trigger_spell_id = 34192;break;//Fire: 34192
- case SPELL_SCHOOL_FROST: trigger_spell_id = 34193;break;//Frost: 34193
- case SPELL_SCHOOL_ARCANE: trigger_spell_id = 34194;break;//Arcane: 34194
- case SPELL_SCHOOL_NATURE: trigger_spell_id = 34195;break;//Nature: 34195
- case SPELL_SCHOOL_SHADOW: trigger_spell_id = 34196;break;//Shadow: 34196
- case SPELL_SCHOOL_HOLY: trigger_spell_id = 34197;break;//Holy: 34197
- case SPELL_SCHOOL_NORMAL: trigger_spell_id = 34198;break;//Physical: 34198
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u Elemental Response wrong school",auraSpellInfo->Id);
- return false;
- }
- }*/
-// else if (auraSpellInfo->Id==6542) // Enraged Defense
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==40364) // Entangling Roots Sensor
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==33207) // Gossip NPC Periodic - Fidget
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==35321) // Gushing Wound
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==38363) // Gushing Wound
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==39215) // Gushing Wound
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==40250) // Improved Duration
-// trigger_spell_id = ;
- else if (auraSpellInfo->Id==27522) // Mana Drain Trigger
- {
- // On successful melee or ranged attack gain $29471s1 mana and if possible drain $27526s1 mana from the target.
- if (this && this->isAlive())
- CastSpell(this, 29471, true, castItem, triggeredByAura);
- if (pVictim && pVictim->isAlive())
- CastSpell(pVictim, 27526, true, castItem, triggeredByAura);
- return true;
- }
- else if (auraSpellInfo->Id==24905) // Moonkin Form (Passive)
- {
- // Elune's Touch (instead non-existed triggered spell) 30% from AP
- trigger_spell_id = 33926;
- basepoints0 = GetTotalAttackPowerValue(BASE_ATTACK) * 30 / 100;
- target = this;
- }
-// else if (auraSpellInfo->Id==43453) // Rune Ward
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==7137) // Shadow Charge (Rank 1)
-// trigger_spell_id = ;
- // Shaleskin (Shaleskin Flayer, Shaleskin Ripper) 30023 trigger
-// else if (auraSpellInfo->Id==36576)
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==34783) // Spell Reflection
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==36096) // Spell Reflection
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==36207) // Steal Weapon
-// trigger_spell_id = ;
-// else if (auraSpellInfo->Id==35205) // Vanish
- break;
- //=====================================================================
- // Mage
- //=====================================================================
- // Blazing Speed (Rank 1,2) trigger = 18350
- //=====================================================================
- case SPELLFAMILY_MAGE:
- // Blazing Speed
- if (auraSpellInfo->SpellIconID == 2127)
- {
- switch (auraSpellInfo->Id)
- {
- case 31641: // Rank 1
- case 31642: // Rank 2
- trigger_spell_id = 31643;
- break;
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Blazing Speed",auraSpellInfo->Id);
- return false;
- }
- }
- break;
- //=====================================================================
- // Warrior
- //=====================================================================
- // Rampage (Rank 1-3) trigger = 18350
- //=====================================================================
- case SPELLFAMILY_WARRIOR:
- // Rampage
- if (auraSpellInfo->SpellIconID == 2006 && auraSpellInfo->SpellFamilyFlags==0x100000)
- {
- switch(auraSpellInfo->Id)
- {
- case 29801: trigger_spell_id = 30029; break; // Rank 1
- case 30030: trigger_spell_id = 30031; break; // Rank 2
- case 30033: trigger_spell_id = 30032; break; // Rank 3
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in Rampage",auraSpellInfo->Id);
- return false;
- }
- }
- break;
- //=====================================================================
- // Warlock
- //=====================================================================
- // Pyroclasm trigger = 18350
- // Drain Soul (Rank 1-5) trigger = 0
- //=====================================================================
- case SPELLFAMILY_WARLOCK:
- {
- // Pyroclasm
- if (auraSpellInfo->SpellIconID == 1137)
- {
- if(!pVictim || !pVictim->isAlive() || pVictim == this || procSpell == NULL)
- return false;
- // Calculate spell tick count for spells
- uint32 tick = 1; // Default tick = 1
-
- // Hellfire have 15 tick
- if (procSpell->SpellFamilyFlags&0x0000000000000040LL)
- tick = 15;
- // Rain of Fire have 4 tick
- else if (procSpell->SpellFamilyFlags&0x0000000000000020LL)
- tick = 4;
- else
- return false;
-
- // Calculate chance = baseChance / tick
- float chance = 0;
- switch (auraSpellInfo->Id)
- {
- case 18096: chance = 13.0f / tick; break;
- case 18073: chance = 26.0f / tick; break;
- }
- // Roll chance
- if (!roll_chance_f(chance))
- return false;
-
- trigger_spell_id = 18093;
- }
- // Drain Soul
- else if (auraSpellInfo->SpellFamilyFlags & 0x0000000000004000LL)
- {
- Unit::AuraList const& mAddFlatModifier = GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
- for(Unit::AuraList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i)
- {
- if ((*i)->GetModifier()->m_miscvalue == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellProto()->SpellIconID == 113)
- {
- int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this);
- basepoints0 = value2 * GetMaxPower(POWER_MANA) / 100;
- }
- }
- if ( basepoints0 == 0 )
- return false;
- trigger_spell_id = 18371;
- }
- break;
- }
- //=====================================================================
- // Priest
- //=====================================================================
- // Greater Heal Refund trigger = 18350
- // Blessed Recovery (Rank 1-3) trigger = 18350
- // Shadowguard (1-7) trigger = 28376
- //=====================================================================
- case SPELLFAMILY_PRIEST:
- {
- // Greater Heal Refund
- if (auraSpellInfo->Id==37594)
- trigger_spell_id = 37595;
- // Shadowguard
- else if(auraSpellInfo->SpellFamilyFlags==0x100080000000LL && auraSpellInfo->SpellVisual==7958)
- {
- switch(auraSpellInfo->Id)
- {
- case 18137: trigger_spell_id = 28377; break; // Rank 1
- case 19308: trigger_spell_id = 28378; break; // Rank 2
- case 19309: trigger_spell_id = 28379; break; // Rank 3
- case 19310: trigger_spell_id = 28380; break; // Rank 4
- case 19311: trigger_spell_id = 28381; break; // Rank 5
- case 19312: trigger_spell_id = 28382; break; // Rank 6
- case 25477: trigger_spell_id = 28385; break; // Rank 7
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in SG", auraSpellInfo->Id);
- return false;
- }
- }
- // Blessed Recovery
- else if (auraSpellInfo->SpellIconID == 1875)
- {
- switch (auraSpellInfo->Id)
- {
- case 27811: trigger_spell_id = 27813; break;
- case 27815: trigger_spell_id = 27817; break;
- case 27816: trigger_spell_id = 27818; break;
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id);
- return false;
- }
- basepoints0 = damage * triggerAmount / 100 / 3;
- target = this;
- }
- break;
- }
- //=====================================================================
- // Druid
- // ====================================================================
- // Druid Forms Trinket trigger = 18350
- // Entangling Roots trigger = 30023
- // Leader of the Pack trigger = 18350
- //=====================================================================
- case SPELLFAMILY_DRUID:
- {
- // Druid Forms Trinket
- if (auraSpellInfo->Id==37336)
- {
- switch(m_form)
- {
- case 0: trigger_spell_id = 37344;break;
- case FORM_CAT: trigger_spell_id = 37341;break;
- case FORM_BEAR:
- case FORM_DIREBEAR: trigger_spell_id = 37340;break;
- case FORM_TREE: trigger_spell_id = 37342;break;
- case FORM_MOONKIN: trigger_spell_id = 37343;break;
- default:
- return false;
- }
- }
-// else if (auraSpellInfo->Id==40363)// Entangling Roots ()
-// trigger_spell_id = ????;
- // Leader of the Pack
- else if (auraSpellInfo->Id == 24932)
- {
- if (triggerAmount == 0)
- return false;
- basepoints0 = triggerAmount * GetMaxHealth() / 100;
- trigger_spell_id = 34299;
- }
- break;
- }
- //=====================================================================
- // Hunter
- // ====================================================================
- // ......
- //=====================================================================
- case SPELLFAMILY_HUNTER:
- break;
- //=====================================================================
- // Paladin
- // ====================================================================
- // Blessed Life trigger = 31934
- // Healing Discount trigger = 18350
- // Illumination (Rank 1-5) trigger = 18350
- // Judgement of Light (Rank 1-5) trigger = 5373
- // Judgement of Wisdom (Rank 1-4) trigger = 1826
- // Lightning Capacitor trigger = 18350
- //=====================================================================
- case SPELLFAMILY_PALADIN:
- {
- /* // Blessed Life
- if (auraSpellInfo->SpellIconID == 2137)
- {
- switch (auraSpellInfo->Id)
- {
- case 31828: // Rank 1
- case 31829: // Rank 2
- case 31830: // Rank 3
+ default:
break;
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Blessed Life", auraSpellInfo->Id);
- return false;
- }
- }*/
- // Healing Discount
- if (auraSpellInfo->Id==37705)
- {
- trigger_spell_id = 37706;
- target = this;
- }
- // Judgement of Light and Judgement of Wisdom
- else if (auraSpellInfo->SpellFamilyFlags & 0x0000000000080000LL)
- {
- switch (auraSpellInfo->Id)
- {
- // Judgement of Light
- case 20185: trigger_spell_id = 20267;break; // Rank 1
- case 20344: trigger_spell_id = 20341;break; // Rank 2
- case 20345: trigger_spell_id = 20342;break; // Rank 3
- case 20346: trigger_spell_id = 20343;break; // Rank 4
- case 27162: trigger_spell_id = 27163;break; // Rank 5
- // Judgement of Wisdom
- case 20186: trigger_spell_id = 20268;break; // Rank 1
- case 20354: trigger_spell_id = 20352;break; // Rank 2
- case 20355: trigger_spell_id = 20353;break; // Rank 3
- case 27164: trigger_spell_id = 27165;break; // Rank 4
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Judgement of Light/Wisdom", auraSpellInfo->Id);
- return false;
- }
- pVictim->CastSpell(pVictim, trigger_spell_id, true, castItem, triggeredByAura);
- return true; // no hidden cooldown
- }
- // Illumination
- else if (auraSpellInfo->SpellIconID==241)
- {
- if(!procSpell)
- return false;
- // procspell is triggered spell but we need mana cost of original casted spell
- uint32 originalSpellId = procSpell->Id;
- // Holy Shock
- if(procSpell->SpellFamilyFlags & 0x00200000)
- {
- switch(procSpell->Id)
- {
- case 25914: originalSpellId = 20473; break;
- case 25913: originalSpellId = 20929; break;
- case 25903: originalSpellId = 20930; break;
- case 27175: originalSpellId = 27174; break;
- case 33074: originalSpellId = 33072; break;
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in HShock",procSpell->Id);
- return false;
- }
- }
- SpellEntry const *originalSpell = sSpellStore.LookupEntry(originalSpellId);
- if(!originalSpell)
- {
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu",originalSpellId);
- return false;
- }
- // percent stored in effect 1 (class scripts) base points
- basepoints0 = originalSpell->manaCost*(auraSpellInfo->EffectBasePoints[1]+1)/100;
- trigger_spell_id = 20272;
- target = this;
- }
- // Lightning Capacitor
- else if (auraSpellInfo->Id==37657)
- {
- if(!pVictim || !pVictim->isAlive())
- return false;
- // stacking
- CastSpell(this, 37658, true, NULL, triggeredByAura);
- // counting
- Aura * dummy = GetDummyAura(37658);
- if (!dummy)
- return false;
- // release at 3 aura in stack (cont contain in basepoint of trigger aura)
- if(dummy->GetStackAmount() <= 2)
- return false;
-
- RemoveAurasDueToSpell(37658);
- trigger_spell_id = 37661;
- target = pVictim;
- }
- break;
- }
- //=====================================================================
- // Shaman
- //====================================================================
- // Lightning Shield trigger = 18350
- // Mana Surge trigger = 18350
- // Nature's Guardian (Rank 1-5) trigger = 18350
- //=====================================================================
- case SPELLFAMILY_SHAMAN:
- {
- //Lightning Shield (overwrite non existing triggered spell call in spell.dbc
- if(auraSpellInfo->SpellFamilyFlags==0x00000400 && auraSpellInfo->SpellVisual==37)
- {
- switch(auraSpellInfo->Id)
- {
- case 324: trigger_spell_id = 26364; break; // Rank 1
- case 325: trigger_spell_id = 26365; break; // Rank 2
- case 905: trigger_spell_id = 26366; break; // Rank 3
- case 945: trigger_spell_id = 26367; break; // Rank 4
- case 8134: trigger_spell_id = 26369; break; // Rank 5
- case 10431: trigger_spell_id = 26370; break; // Rank 6
- case 10432: trigger_spell_id = 26363; break; // Rank 7
- case 25469: trigger_spell_id = 26371; break; // Rank 8
- case 25472: trigger_spell_id = 26372; break; // Rank 9
- default:
- sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield", auraSpellInfo->Id);
- return false;
- }
- }
- // Lightning Shield (The Ten Storms set)
- else if (auraSpellInfo->Id == 23551)
- {
- trigger_spell_id = 23552;
- target = pVictim;
- }
- // Damage from Lightning Shield (The Ten Storms set)
- else if (auraSpellInfo->Id == 23552)
- trigger_spell_id = 27635;
- // Mana Surge (The Earthfury set)
- else if (auraSpellInfo->Id == 23572)
- {
- if(!procSpell)
- return false;
- basepoints0 = procSpell->manaCost * 35 / 100;
- trigger_spell_id = 23571;
- target = this;
- }
- else if (auraSpellInfo->SpellIconID == 2013) //Nature's Guardian
- {
- // Check health condition - should drop to less 30% (damage deal after this!)
- if (!(10*(int32(GetHealth() - damage)) < 3 * GetMaxHealth()))
- return false;
-
- if(pVictim && pVictim->isAlive())
- pVictim->getThreatManager().modifyThreatPercent(this,-10);
-
- basepoints0 = triggerAmount * GetMaxHealth() / 100;
- trigger_spell_id = 31616;
- target = this;
- }
- break;
- }
- // default
- default:
- break;
+ }
}
// All ok. Check current trigger spell
@@ -7670,6 +6732,15 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return false;
break;
}
+ // Rapid Recuperation
+ case 53228:
+ case 53232:
+ {
+ // This effect only from Rapid Fire (ability cast)
+ if (!(procSpell->SpellFamilyFlags[0] & 0x20))
+ return false;
+ break;
+ }
}
// Costum basepoints/target for exist spell
@@ -7699,11 +6770,16 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
// Need add combopoint AFTER finish movie (or they dropped in finish phase)
break;
}
+ // Bloodthirst (($m/100)% of max health)
+ case 23880:
+ {
+ basepoints0 = int32(GetMaxHealth() * triggerAmount / 10000);
+ break;
+ }
// Shamanistic Rage triggered spell
case 30824:
{
basepoints0 = int32(GetTotalAttackPowerValue(BASE_ATTACK) * triggerAmount / 100);
- trigger_spell_id = 30824;
break;
}
// Enlightenment (trigger only from mana cost spells)
@@ -7713,6 +6789,59 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return false;
break;
}
+ // Brain Freeze
+ case 57761:
+ {
+ if(!procSpell)
+ return false;
+ // For trigger from Blizzard need exist Improved Blizzard
+ if (procSpell->SpellFamilyName==SPELLFAMILY_MAGE && procSpell->SpellFamilyFlags[0] & 0x80)
+ {
+ bool found = false;
+ AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
+ {
+ int32 script = (*i)->GetModifier()->m_miscvalue;
+ if(script==836 || script==988 || script==989)
+ {
+ found=true;
+ break;
+ }
+ }
+ if(!found)
+ return false;
+ }
+ break;
+ }
+ // Astral Shift
+ case 52179:
+ {
+ if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim)
+ return false;
+
+ // Need stun, fear or silence mechanic
+ if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_SILENCE)|(1<<MECHANIC_STUN)|(1<<MECHANIC_FEAR))))
+ return false;
+ break;
+ }
+ // Burning Determination
+ case 54748:
+ {
+ if(!procSpell)
+ return false;
+ // Need Interrupt or Silenced mechanic
+ if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_INTERRUPT)|(1<<MECHANIC_SILENCE))))
+ return false;
+ break;
+ }
+ // Lock and Load
+ case 56453:
+ {
+ // Proc only from trap activation (from periodic proc another aura of this spell)
+ if (!(procFlags & PROC_FLAG_ON_TRAP_ACTIVATION) || !roll_chance_i(triggerAmount))
+ return false;
+ break;
+ }
}
if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(trigger_spell_id))
@@ -7739,7 +6868,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return true;
}
-bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown)
+bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown)
{
int32 scriptId = triggeredByAura->GetModifier()->m_miscvalue;
@@ -7755,21 +6884,21 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAur
{
case 836: // Improved Blizzard (Rank 1)
{
- if (!procSpell || procSpell->SpellVisual!=9487)
+ if (!procSpell || procSpell->SpellVisual[0]!=9487)
return false;
triggered_spell_id = 12484;
break;
}
case 988: // Improved Blizzard (Rank 2)
{
- if (!procSpell || procSpell->SpellVisual!=9487)
+ if (!procSpell || procSpell->SpellVisual[0]!=9487)
return false;
triggered_spell_id = 12485;
break;
}
case 989: // Improved Blizzard (Rank 3)
{
- if (!procSpell || procSpell->SpellVisual!=9487)
+ if (!procSpell || procSpell->SpellVisual[0]!=9487)
return false;
triggered_spell_id = 12486;
break;
@@ -7806,6 +6935,16 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAur
case 5497: // Improved Mana Gems (Serpent-Coil Braid)
triggered_spell_id = 37445; // Mana Surge
break;
+ case 8152: // Serendipity
+ {
+ // if heal your target over maximum health
+ if (pVictim->GetHealth() + damage < pVictim->GetMaxHealth())
+ return false;
+ int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100;
+ int32 basepoints0 = cost * triggeredByAura->GetModifier()->m_amount/100;
+ CastCustomSpell(this, 47762, &basepoints0, 0, 0, true, 0, triggeredByAura);
+ return true;
+ }
}
// not processed
@@ -7947,11 +7086,11 @@ bool Unit::IsHostileTo(Unit const* unit) const
return false;
// Sanctuary
- if(pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY) && pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY))
+ if(pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY))
return false;
// PvP FFA state
- if(pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP) && pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP))
+ if(pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
return true;
//= PvP states
@@ -8056,11 +7195,11 @@ bool Unit::IsFriendlyTo(Unit const* unit) const
return true;
// Sanctuary
- if(pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY) && pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY))
+ if(pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY))
return true;
// PvP FFA state
- if(pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP) && pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP))
+ if(pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
return false;
//= PvP states
@@ -8318,51 +7457,7 @@ void Unit::RemoveAllAttackers()
void Unit::ModifyAuraState(AuraState flag, bool apply)
{
- if (apply)
- {
- if (!HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)))
- {
- SetFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1));
- if(GetTypeId() == TYPEID_PLAYER)
- {
- const PlayerSpellMap& sp_list = ((Player*)this)->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
- {
- if(itr->second->state == PLAYERSPELL_REMOVED) continue;
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
- if (!spellInfo || !IsPassiveSpell(itr->first)) continue;
- if (spellInfo->CasterAuraState == flag)
- CastSpell(this, itr->first, true, NULL);
- }
- }
- }
- }
- else
- {
- if (HasFlag(UNIT_FIELD_AURASTATE,1<<(flag-1)))
- {
- RemoveFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1));
- Unit::AuraMap& tAuras = GetAuras();
- for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
- {
- SpellEntry const* spellProto = (*itr).second->GetSpellProto();
- if (spellProto->CasterAuraState == flag)
- {
- // exceptions (applied at state but not removed at state change)
- // Rampage
- if(spellProto->SpellIconID==2006 && spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && spellProto->SpellFamilyFlags==0x100000)
- {
- ++itr;
- continue;
- }
-
- RemoveAura(itr);
- }
- else
- ++itr;
- }
- }
- }
+ ApplyModFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1), apply);
}
Unit *Unit::GetOwner() const
@@ -8412,6 +7507,7 @@ Unit* Unit::GetCharm() const
sLog.outError("Unit::GetCharm: Charmed creature %u not exist.",GUID_LOPART(charm_guid));
const_cast<Unit*>(this)->SetCharm(0);
+ //const_cast<Unit*>(this)->SetMover(0);
}
return NULL;
@@ -8494,6 +7590,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);
@@ -8510,76 +7607,29 @@ void Unit::SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, Po
SendMessageToSet(&data, true);
}
-uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype)
+uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack)
{
if(!spellProto || !pVictim || damagetype==DIRECT_DAMAGE )
return pdamage;
- //if(spellProto->SchoolMask == SPELL_SCHOOL_MASK_NORMAL)
- // return pdamage;
- //damage = CalcArmorReducedDamage(pVictim, damage);
-
- int32 BonusDamage = 0;
- if( GetTypeId()==TYPEID_UNIT )
- {
- // Pets just add their bonus damage to their spell damage
- // note that their spell damage is just gain of their own auras
- if (((Creature*)this)->isPet())
- {
- BonusDamage = ((Pet*)this)->GetBonusDamage();
- }
- // For totems get damage bonus from owner (statue isn't totem in fact)
- else if (((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE)
- {
- if(Unit* owner = GetOwner())
- return owner->SpellDamageBonus(pVictim, spellProto, pdamage, damagetype);
- }
- }
-
- // Damage Done
- uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
-
- // Taken/Done fixed damage bonus auras
- int32 DoneAdvertisedBenefit = SpellBaseDamageBonus(GetSpellSchoolMask(spellProto))+BonusDamage;
- int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim(GetSpellSchoolMask(spellProto), pVictim);
-
- // Damage over Time spells bonus calculation
- float DotFactor = 1.0f;
- if(damagetype == DOT)
+ // For totems get damage bonus from owner (statue isn't totem in fact)
+ if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE)
{
- int32 DotDuration = GetSpellDuration(spellProto);
- // 200% limit
- if(DotDuration > 0)
- {
- if(DotDuration > 30000) DotDuration = 30000;
- if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f;
- int x = 0;
- for(int j = 0; j < 3; j++)
- {
- if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
- spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE ||
- spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
- {
- x = j;
- break;
- }
- }
- int DotTicks = 6;
- if(spellProto->EffectAmplitude[x] != 0)
- DotTicks = DotDuration / spellProto->EffectAmplitude[x];
- if(DotTicks)
- {
- DoneAdvertisedBenefit /= DotTicks;
- TakenAdvertisedBenefit /= DotTicks;
- }
- }
+ if(Unit* owner = GetOwner())
+ return owner->SpellDamageBonus(pVictim, spellProto, pdamage, damagetype);
}
// Taken/Done total percent damage auras
float DoneTotalMod = 1.0f;
float TakenTotalMod = 1.0f;
+ int32 DoneTotal = 0;
+ int32 TakenTotal = 0;
// ..done
+ // Pet damage
+ if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() )
+ DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank);
+
AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
{
@@ -8589,84 +7639,133 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
(*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 )
// 0 == any inventory type (not wand then)
{
- DoneTotalMod *= ((*i)->GetModifierValue() +100.0f)/100.0f;
+ DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
}
}
uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
+ // Add flat bonus from spell damage versus
+ DoneTotal += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, creatureTypeMask);
AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i)
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
- DoneTotalMod *= ((*i)->GetModifierValue() +100.0f)/100.0f;
-
- // ..taken
- AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
- for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i)
- if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) )
- TakenTotalMod *= ((*i)->GetModifierValue() +100.0f)/100.0f;
+ DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
- // .. taken pct: scripted (increases damage of * against targets *)
- AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ // done scripted mod (take it from owner)
+ Unit *owner = GetOwner();
+ if (!owner) owner = this;
+ AuraList const& mOverrideClassScript= owner->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
+ if (!(*i)->isAffectedOnSpell(spellProto))
+ continue;
switch((*i)->GetModifier()->m_miscvalue)
{
- //Molten Fury
- case 4920: case 4919:
- if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT))
- TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; break;
- }
- }
-
- // .. taken pct: dummy auras
- AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
- for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
- {
- switch((*i)->GetSpellProto()->SpellIconID)
- {
- //Cheat Death
- case 2109:
- if( ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) )
- {
- if(pVictim->GetTypeId() != TYPEID_PLAYER)
- continue;
- float mod = -((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2*4;
- if (mod < (*i)->GetModifier()->m_amount)
- mod = (*i)->GetModifier()->m_amount;
- TakenTotalMod *= (mod+100.0f)/100.0f;
- }
+ case 4920: // Molten Fury
+ case 4919:
+ case 6917: // Death's Embrace
+ case 6926:
+ case 6928:
+ {
+ if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
+ DoneTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f;
break;
- //This is changed in WLK, using aura 255
- //Mangle
- case 2312:
- case 44955:
- for(int j=0;j<3;j++)
- {
- if(GetEffectMechanic(spellProto, j)==MECHANIC_BLEED)
+ }
+ // Soul Siphon
+ case 4992:
+ case 4993:
+ {
+ // effect 1 m_amount
+ int32 maxPercent = (*i)->GetModifier()->m_amount;
+ // effect 0 m_amount
+ int32 stepPercent = CalculateSpellDamage((*i)->GetSpellProto(), 0, (*i)->GetSpellProto()->EffectBasePoints[0], this);
+ // count affliction effects and calc additional damage in percentage
+ int32 modPercent = 0;
+ AuraMap const& victimAuras = pVictim->GetAuras();
+ for (AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
+ {
+ SpellEntry const* m_spell = itr->second->GetSpellProto();
+ if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK || !(m_spell->SpellFamilyFlags[1] & 0x0004071B || m_spell->SpellFamilyFlags[0] & 0x8044C402))
+ continue;
+ modPercent += stepPercent * itr->second->GetStackAmount();
+ if (modPercent >= maxPercent)
{
- TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f;
+ modPercent = maxPercent;
break;
}
}
+ DoneTotalMod *= (modPercent+100.0f)/100.0f;
break;
+ }
+ case 6916: // Death's Embrace
+ case 6925:
+ case 6927:
+ if (HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT))
+ DoneTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f;
+ break;
+ case 5481: // Starfire Bonus
+ {
+ if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x200002))
+ DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
+ break;
+ }
+ case 4418: // Increased Shock Damage
+ case 4554: // Increased Lightning Damage
+ case 4555: // Improved Moonfire
+ case 5142: // Increased Lightning Damage
+ case 5147: // Improved Consecration / Libram of Resurgence
+ case 5148: // Idol of the Shooting Star
+ case 6008: // Increased Lightning Damage / Totem of Hex
+ {
+ DoneTotal+=(*i)->GetModifier()->m_amount;
+ break;
+ }
+ // Tundra Stalker
+ // Merciless Combat
+ case 7277:
+ {
+ // Merciless Combat
+ if ((*i)->GetSpellProto()->SpellIconID == 2656)
+ {
+ if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
+ DoneTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f;
+ }
+ else // Tundra Stalker
+ {
+ if (pVictim->GetAura(SPELL_AURA_DUMMY, SPELLFAMILY_DEATHKNIGHT,0, 0x04000000,0))
+ DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
+ break;
+ }
+ break;
+ }
+ case 7293: // Rage of Rivendare
+ {
+ if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0,0x02000000,0))
+ DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
+ break;
+ }
+ // Twisted Faith
+ case 7377:
+ {
+ if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0,0, GetGUID()))
+ DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
+ break;
+ }
+ // Marked for Death
+ case 7598:
+ case 7599:
+ case 7600:
+ case 7601:
+ case 7602:
+ {
+ if (pVictim->GetAura(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, 0x400))
+ DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
+ break;
+ }
}
}
- // Distribute Damage over multiple effects, reduce by AoE
- CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
-
- // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
- for(int j = 0; j < 3; ++j)
- {
- if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
- spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH )
- {
- CastingTime /= 2;
- break;
- }
- }
-
- switch(spellProto->SpellFamilyName)
+ /*switch(spellProto->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
// Siphon Essence - 0%
@@ -8680,7 +7779,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
CastingTime = 0;
}
// Darkmoon Card: Vengeance - 0.1%
- else if (spellProto->SpellVisual == 9850 && spellProto->SpellIconID == 2230)
+ else if (spellProto->SpellVisual[0] == 9850 && spellProto->SpellIconID == 2230)
{
CastingTime = 3.5;
}
@@ -8783,21 +7882,10 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
DotFactor = 0.95f;
CastingTime = 3500;
}
- // Seal of Righteousness - 10.2%/9.8% ( based on weapon type ) of Holy Damage, multiplied by weapon speed
- else if((spellProto->SpellFamilyFlags & 0x8000000LL) && spellProto->SpellIconID == 25)
+ // Judgement of Righteousness - 32%
+ else if (spellProto->SpellFamilyFlags & 0x0000000000000400LL)
{
- Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
- float wspeed = GetAttackTime(BASE_ATTACK)/1000.0f;
-
- if( item && item->GetProto()->InventoryType == INVTYPE_2HWEAPON)
- CastingTime = uint32(wspeed*3500*0.102f);
- else
- CastingTime = uint32(wspeed*3500*0.098f);
- }
- // Judgement of Righteousness - 73%
- else if ((spellProto->SpellFamilyFlags & 1024) && spellProto->SpellIconID == 25)
- {
- CastingTime = 2555;
+ CastingTime = 1120;
}
// Seal of Vengeance - 17% per Fully Stacked Tick - 5 Applications
else if ((spellProto->SpellFamilyFlags & 0x80000000000LL) && spellProto->SpellIconID == 2292)
@@ -8815,11 +7903,6 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
{
CastingTime = 0;
}
- // Seal of Righteousness trigger - already computed for parent spell
- else if ( spellProto->SpellFamilyName==SPELLFAMILY_PALADIN && spellProto->SpellIconID==25 && spellProto->AttributesEx4 & 0x00800000LL )
- {
- return pdamage;
- }
break;
case SPELLFAMILY_SHAMAN:
// totem attack
@@ -8873,58 +7956,143 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
{
CastingTime = 500;
}
- break;
- case SPELLFAMILY_DRUID:
- // Hurricane triggered spell
- if((spellProto->SpellFamilyFlags & 0x400000LL) && spellProto->SpellIconID == 220)
- {
- CastingTime = 500;
- }
- break;
- case SPELLFAMILY_WARRIOR:
- case SPELLFAMILY_HUNTER:
- case SPELLFAMILY_ROGUE:
- CastingTime = 0;
- break;
- default:
- break;
+ break;*/
+
+ // Custom scripted damage
+ // Ice Lance
+ if (spellProto->SpellFamilyName == SPELLFAMILY_MAGE && spellProto->SpellIconID == 186)
+ {
+ if (pVictim->isFrozen())
+ DoneTotalMod *= 3.0f;
}
- float LvlPenalty = CalculateLevelPenalty(spellProto);
+ // ..taken
+ AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
+ for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i)
+ if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) )
+ TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
- // Spellmod SpellDamage
- //float SpellModSpellDamage = 100.0f;
- float CoefficientPtc = DotFactor * 100.0f;
- if(spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL)
- CoefficientPtc *= ((float)CastingTime/3500.0f);
+ // .. taken pct: dummy auras
+ if (pVictim->GetTypeId() == TYPEID_PLAYER)
+ {
+ //Cheat Death
+ if (Aura *dummy = pVictim->GetDummyAura(45182))
+ {
+ float mod = -((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2*4;
+ if (mod < dummy->GetModifier()->m_amount)
+ mod = dummy->GetModifier()->m_amount;
+ TakenTotalMod *= (mod+100.0f)/100.0f;
+ }
+ }
- if(Player* modOwner = GetSpellModOwner())
- //modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,SpellModSpellDamage);
- modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,CoefficientPtc);
+ // From caster spells
+ AuraList const& mOwnerTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
+ for(AuraList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
+ if( (*i)->GetCasterGUID() == GetGUID() && (*i)->isAffectedOnSpell(spellProto))
+ TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
- //SpellModSpellDamage /= 100.0f;
- CoefficientPtc /= 100.0f;
+ // Mod damage from spell mechanic
+ uint32 mechanicMask = GetAllSpellMechanicMask(spellProto);
+ if (mechanicMask)
+ {
+ AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT);
+ for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i)
+ if(mechanicMask & uint32(1<<((*i)->GetModifier()->m_miscvalue)))
+ TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
+ }
- //float DoneActualBenefit = DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * SpellModSpellDamage * LvlPenalty;
-
- float DoneActualBenefit = DoneAdvertisedBenefit * CoefficientPtc * LvlPenalty;
- float TakenActualBenefit = TakenAdvertisedBenefit * DotFactor * LvlPenalty;
- if(spellProto->SpellFamilyName && spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL)
- TakenActualBenefit *= ((float)CastingTime / 3500.0f);
+ // Taken/Done fixed damage bonus auras
+ int32 DoneAdvertisedBenefit = SpellBaseDamageBonus(GetSpellSchoolMask(spellProto));
+ int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim(GetSpellSchoolMask(spellProto), pVictim);
+ // Pets just add their bonus damage to their spell damage
+ // note that their spell damage is just gain of their own auras
+ if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
+ DoneAdvertisedBenefit += ((Pet*)this)->GetBonusDamage();
+
+ // Check for table values
+ float coeff;
+ SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id);
+ if (bonus)
+ {
+ if (damagetype == DOT)
+ coeff = bonus->dot_damage;
+ else
+ coeff = bonus->direct_damage;
+ if (bonus->ap_bonus)
+ DoneTotal+=bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack;
+ }
+ // Default calculation
+ else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
+ {
+ // Damage Done from spell damage bonus
+ uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
+ // Damage over Time spells bonus calculation
+ float DotFactor = 1.0f;
+ if(damagetype == DOT)
+ {
+ int32 DotDuration = GetSpellDuration(spellProto);
+ // 200% limit
+ if(DotDuration > 0)
+ {
+ if(DotDuration > 30000) DotDuration = 30000;
+ if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f;
+ int x = 0;
+ for(int j = 0; j < 3; j++)
+ {
+ if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
+ spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE ||
+ spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
+ {
+ x = j;
+ break;
+ }
+ }
+ int32 DotTicks = 6;
+ if(spellProto->EffectAmplitude[x] != 0)
+ DotTicks = DotDuration / spellProto->EffectAmplitude[x];
+ if(DotTicks)
+ {
+ DoneAdvertisedBenefit /= DotTicks;
+ TakenAdvertisedBenefit /= DotTicks;
+ }
+ }
+ }
+ // Distribute Damage over multiple effects, reduce by AoE
+ CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
- float tmpDamage = (float(pdamage)+DoneActualBenefit)*DoneTotalMod;
+ // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
+ for(int j = 0; j < 3; ++j)
+ {
+ if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
+ spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH )
+ {
+ CastingTime /= 2;
+ break;
+ }
+ }
+ if(spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL)
+ coeff = (CastingTime / 3500.0f) * DotFactor;
+ else
+ coeff = DotFactor;
+ }
- // Add flat bonus from spell damage versus
- tmpDamage += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, creatureTypeMask);
+ float coeff2 = CalculateLevelPenalty(spellProto) * stack;
+ if(spellProto->SpellFamilyName) //TODO: fix this
+ TakenTotal+= TakenAdvertisedBenefit * coeff * coeff2;
+ if(Player* modOwner = GetSpellModOwner())
+ {
+ coeff *= 100.0f;
+ modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_SPELL_BONUS_DAMAGE, coeff);
+ coeff /= 100.0f;
+ }
+ DoneTotal += DoneAdvertisedBenefit * coeff * coeff2;
- // apply spellmod to Done damage
+ float tmpDamage = (pdamage + DoneTotal) * DoneTotalMod;
+ // apply spellmod to Done damage (flat and pct)
if(Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
- tmpDamage = (tmpDamage+TakenActualBenefit)*TakenTotalMod;
-
- if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() )
- tmpDamage *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank);
+ tmpDamage = (tmpDamage + TakenTotal) * TakenTotalMod;
return tmpDamage > 0 ? uint32(tmpDamage) : 0;
}
@@ -8941,32 +8109,29 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask)
// -1 == any item class (not wand then)
(*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 )
// 0 == any inventory type (not wand then)
- DoneAdvertisedBenefit += (*i)->GetModifierValue();
+ DoneAdvertisedBenefit += (*i)->GetModifier()->m_amount;
if (GetTypeId() == TYPEID_PLAYER)
{
+ // Base value
+ DoneAdvertisedBenefit +=((Player*)this)->GetBaseSpellDamageBonus();
+
// Damage bonus from stats
AuraList const& mDamageDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT);
for(AuraList::const_iterator i = mDamageDoneOfStatPercent.begin();i != mDamageDoneOfStatPercent.end(); ++i)
{
if((*i)->GetModifier()->m_miscvalue & schoolMask)
{
- SpellEntry const* iSpellProto = (*i)->GetSpellProto();
- uint8 eff = (*i)->GetEffIndex();
-
- // stat used dependent from next effect aura SPELL_AURA_MOD_SPELL_HEALING presence and misc value (stat index)
- Stats usedStat = STAT_INTELLECT;
- if(eff < 2 && iSpellProto->EffectApplyAuraName[eff+1]==SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT)
- usedStat = Stats(iSpellProto->EffectMiscValue[eff+1]);
-
- DoneAdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifierValue() / 100.0f);
+ // stat used stored in miscValueB for this aura
+ Stats usedStat = Stats((*i)->GetMiscBValue());
+ DoneAdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifier()->m_amount / 100.0f);
}
}
// ... and attack power
AuraList const& mDamageDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER);
for(AuraList::const_iterator i =mDamageDonebyAP.begin();i != mDamageDonebyAP.end(); ++i)
if ((*i)->GetModifier()->m_miscvalue & schoolMask)
- DoneAdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifierValue() / 100.0f);
+ DoneAdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifier()->m_amount / 100.0f);
}
return DoneAdvertisedBenefit;
@@ -8981,13 +8146,13 @@ int32 Unit::SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVic
AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE);
for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i)
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
- TakenAdvertisedBenefit += (*i)->GetModifierValue();
+ TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount;
// ..taken
AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0)
- TakenAdvertisedBenefit += (*i)->GetModifierValue();
+ TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount;
return TakenAdvertisedBenefit;
}
@@ -9025,21 +8190,65 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
// Modify by player victim resilience
if (pVictim->GetTypeId() == TYPEID_PLAYER)
crit_chance -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL);
+
// scripted (increase crit chance ... against ... target by x%
- if(pVictim->isFrozen()) // Shatter
+ AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
- AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
+ if (!((*i)->isAffectedOnSpell(spellProto)))
+ continue;
+ switch((*i)->GetModifier()->m_miscvalue)
{
- switch((*i)->GetModifier()->m_miscvalue)
+ case 849: if (pVictim->isFrozen()) crit_chance+= 17.0f; break; //Shatter Rank 1
+ case 910: if (pVictim->isFrozen()) crit_chance+= 34.0f; break; //Shatter Rank 2
+ case 911: if (pVictim->isFrozen()) crit_chance+= 50.0f; break; //Shatter Rank 3
+ case 7917: // Glyph of Shadowburn
+ if (pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
+ crit_chance+=(*i)->GetModifier()->m_amount;
+ break;
+ case 7997: // Renewed Hope
+ case 7998:
+ if (pVictim->HasAura(6788))
+ crit_chance+=(*i)->GetModifier()->m_amount;
+ break;
+ case 21: // Test of Faith
+ case 6935:
+ case 6918:
+ if (pVictim->GetHealth() < pVictim->GetMaxHealth()/2)
+ crit_chance+=(*i)->GetModifier()->m_amount;
+ break;
+ default:
+ break;
+ }
+ }
+ // Custom crit by class
+ switch(spellProto->SpellFamilyName)
+ {
+ case SPELLFAMILY_PALADIN:
+ // Sacred Shield
+ if (spellProto->SpellFamilyFlags[0] & 0x40000000)
{
- case 849: crit_chance+= 10.0f; break; //Shatter Rank 1
- case 910: crit_chance+= 20.0f; break; //Shatter Rank 2
- case 911: crit_chance+= 30.0f; break; //Shatter Rank 3
- case 912: crit_chance+= 40.0f; break; //Shatter Rank 4
- case 913: crit_chance+= 50.0f; break; //Shatter Rank 5
+ Aura *aura = pVictim->GetDummyAura(58597);
+ if (aura && aura->GetCasterGUID() == GetGUID())
+ crit_chance+=aura->GetModifier()->m_amount;
+ break;
}
- }
+ break;
+ case SPELLFAMILY_SHAMAN:
+ // Lava Burst
+ if (spellProto->SpellFamilyFlags[1] & 0x00001000)
+ {
+ if (Aura *flameShock = pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 10000000, 0,0, GetGUID()))
+ {
+ // Consume shock aura if not have Glyph of Flame Shock
+ if (!GetAura(55447, 0))
+ pVictim->RemoveAurasByCasterSpell(flameShock->GetId(), GetGUID());
+ return true;
+ }
+ break;
+ }
+ break;
+
}
}
break;
@@ -9050,7 +8259,6 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
if (pVictim)
{
crit_chance = GetUnitCriticalChance(attackType, pVictim);
- crit_chance+= (int32(GetMaxSkillValueForLevel(pVictim)) - int32(pVictim->GetDefenseSkillValue(this))) * 0.04f;
crit_chance+= GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask);
}
break;
@@ -9069,7 +8277,7 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
return false;
}
-uint32 Unit::SpellCriticalBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim)
+uint32 Unit::SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim)
{
// Calculate critical bonus
int32 crit_bonus;
@@ -9101,15 +8309,49 @@ uint32 Unit::SpellCriticalBonus(SpellEntry const *spellProto, uint32 damage, Uni
return damage;
}
-uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim)
+uint32 Unit::SpellCriticalHealingBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim)
{
+ // Calculate critical bonus
+ int32 crit_bonus;
+ switch(spellProto->DmgClass)
+ {
+ case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100%
+ case SPELL_DAMAGE_CLASS_RANGED:
+ // TODO: write here full calculation for melee/ranged spells
+ crit_bonus = damage;
+ break;
+ default:
+ crit_bonus = damage / 2; // for spells is 50%
+ break;
+ }
+
+
+ if(pVictim)
+ {
+ uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
+ crit_bonus = int32(crit_bonus * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask));
+ }
+
+ if(crit_bonus > 0)
+ damage += crit_bonus;
+
+ damage = int32(damage * GetTotalAuraMultiplier(SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT));
+
+ return damage;
+}
+
+uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack)
+{
+ // No heal amount for this class spells
+ if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
+ return healamount;
+
// For totems get healing bonus from owner (statue isn't totem in fact)
if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE)
if(Unit* owner = GetOwner())
- return owner->SpellHealingBonus(spellProto, healamount, damagetype, pVictim);
-
- // Healing Done
+ return owner->SpellHealingBonus(pVictim, spellProto, healamount, damagetype, stack);
+ // TODO: to be deleted
// These Spells are doing fixed amount of healing (TODO found less hack-like check)
if (spellProto->Id == 15290 || spellProto->Id == 39373 ||
spellProto->Id == 33778 || spellProto->Id == 379 ||
@@ -9118,86 +8360,91 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount,
spellProto->Id == 34299)
return healamount;
- int32 AdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto));
- uint32 CastingTime = GetSpellCastTime(spellProto);
+ // Healing Done
+ // Taken/Done total percent damage auras
+ float DoneTotalMod = 1.0f;
+ float TakenTotalMod = 1.0f;
+ int32 DoneTotal = 0;
+ int32 TakenTotal = 0;
- // Healing Taken
- AdvertisedBenefit += SpellBaseHealingBonusForVictim(GetSpellSchoolMask(spellProto), pVictim);
+ // Healing done percent
+ AuraList const& mHealingDonePct = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT);
+ for(AuraList::const_iterator i = mHealingDonePct.begin();i != mHealingDonePct.end(); ++i)
+ DoneTotalMod *= (100.0f + (*i)->GetModifier()->m_amount) / 100.0f;
- // Blessing of Light dummy effects healing taken from Holy Light and Flash of Light
- if (spellProto->SpellFamilyName == SPELLFAMILY_PALADIN && (spellProto->SpellFamilyFlags & 0x00000000C0000000LL))
+ // done scripted mod (take it from owner)
+ Unit *owner = GetOwner();
+ if (!owner) owner = this;
+ AuraList const& mOverrideClassScript= owner->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
- AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
- for(AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
+ if (!(*i)->isAffectedOnSpell(spellProto))
+ continue;
+ switch((*i)->GetModifier()->m_miscvalue)
{
- if((*i)->GetSpellProto()->SpellVisual == 9180)
+ case 4415: // Increased Rejuvenation Healing
+ case 4953:
+ case 3736: // Hateful Totem of the Third Wind / Increased Lesser Healing Wave / LK Arena (4/5/6) Totem of the Third Wind / Savage Totem of the Third Wind
+ DoneTotal+=(*i)->GetModifier()->m_amount;
+ break;
+ case 7997: // Renewed Hope
+ case 7998:
+ if (pVictim->HasAura(6788))
+ DoneTotalMod *=((*i)->GetModifier()->m_amount + 100.0f)/100.0f;
+ break;
+ case 21: // Test of Faith
+ case 6935:
+ case 6918:
+ if (pVictim->GetHealth() < pVictim->GetMaxHealth()/2)
+ DoneTotalMod *=((*i)->GetModifier()->m_amount + 100.0f)/100.0f;
+ break;
+ case 7798: // Glyph of Regrowth
{
- // Flash of Light
- if ((spellProto->SpellFamilyFlags & 0x0000000040000000LL) && (*i)->GetEffIndex() == 1)
- AdvertisedBenefit += (*i)->GetModifier()->m_amount;
- // Holy Light
- else if ((spellProto->SpellFamilyFlags & 0x0000000080000000LL) && (*i)->GetEffIndex() == 0)
- AdvertisedBenefit += (*i)->GetModifier()->m_amount;
+ if (pVictim->GetAura(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40))
+ DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
+ break;
}
- }
- }
-
- float ActualBenefit = 0.0f;
-
- if (AdvertisedBenefit != 0)
- {
- // Healing over Time spells
- float DotFactor = 1.0f;
- if(damagetype == DOT)
- {
- int32 DotDuration = GetSpellDuration(spellProto);
- if(DotDuration > 0)
+ case 8477: // Nourish Heal Boost
{
- // 200% limit
- if(DotDuration > 30000) DotDuration = 30000;
- if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f;
- int x = 0;
- for(int j = 0; j < 3; j++)
+ int32 stepPercent = (*i)->GetModifier()->m_amount;
+ int32 modPercent = 0;
+ AuraMap const& victimAuras = pVictim->GetAuras();
+ for (AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
{
- if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
- spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_HEAL ||
- spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
- {
- x = j;
- break;
- }
+ if (itr->second->GetCasterGUID()!=GetGUID())
+ continue;
+ SpellEntry const* m_spell = itr->second->GetSpellProto();
+ if ( m_spell->SpellFamilyName != SPELLFAMILY_DRUID ||
+ !(m_spell->SpellFamilyFlags[1] & 0x00000010 || m_spell->SpellFamilyFlags[0] & 0x50))
+ continue;
+ modPercent += stepPercent * itr->second->GetStackAmount();
}
- int DotTicks = 6;
- if(spellProto->EffectAmplitude[x] != 0)
- DotTicks = DotDuration / spellProto->EffectAmplitude[x];
- if(DotTicks)
- AdvertisedBenefit /= DotTicks;
+ DoneTotalMod *= (modPercent+100.0f)/100.0f;
+ break;
}
- }
-
- // distribute healing to all effects, reduce AoE damage
- CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
-
- // 0% bonus for damage and healing spells for leech spells from healing bonus
- for(int j = 0; j < 3; ++j)
- {
- if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
- spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH )
+ case 7871: // Glyph of Lesser Healing Wave
{
- CastingTime = 0;
+ if (pVictim->GetAura(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0 , 0x00000400, 0, GetGUID()))
+ DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
break;
}
+ default:
+ break;
}
+ }
- // Exception
+ /*// Exception
switch (spellProto->SpellFamilyName)
{
- case SPELLFAMILY_SHAMAN:
+ case SPELLFAMILY_GENERIC:
// Healing stream from totem (add 6% per tick from hill bonus owner)
- if (spellProto->SpellFamilyFlags & 0x000000002000LL)
+ // Possibly need do it on apply dummy aura
+ if (spellProto->Id == 52042)
CastingTime = 210;
+ break;
+ case SPELLFAMILY_SHAMAN:
// Earth Shield 30% per charge
- else if (spellProto->SpellFamilyFlags & 0x40000000000LL)
+ if (spellProto->SpellFamilyFlags & 0x40000000000LL)
CastingTime = 1050;
break;
case SPELLFAMILY_DRUID:
@@ -9241,64 +8488,119 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount,
case SPELLFAMILY_HUNTER:
CastingTime = 0;
break;
- }
-
- float LvlPenalty = CalculateLevelPenalty(spellProto);
-
- // Spellmod SpellDamage
- //float SpellModSpellDamage = 100.0f;
- float CoefficientPtc = ((float)CastingTime/3500.0f)*DotFactor*100.0f;
+ }*/
- if(Player* modOwner = GetSpellModOwner())
- //modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,SpellModSpellDamage);
- modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,CoefficientPtc);
+ // Taken/Done fixed damage bonus auras
+ int32 DoneAdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto));
+ int32 TakenAdvertisedBenefit = SpellBaseHealingBonusForVictim(GetSpellSchoolMask(spellProto), pVictim);
- //SpellModSpellDamage /= 100.0f;
- CoefficientPtc /= 100.0f;
+ // Check for table values
+ SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id);
+ float coeff;
+ if (bonus)
+ {
+ if (damagetype == DOT)
+ coeff = bonus->dot_damage;
+ else
+ coeff = bonus->direct_damage;
+ if (bonus->ap_bonus)
+ DoneTotal+=bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack;
+ }
+ // Default calculation
+ else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
+ {
+ // Damage Done from spell damage bonus
+ uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
+ // Damage over Time spells bonus calculation
+ float DotFactor = 1.0f;
+ if(damagetype == DOT)
+ {
+ int32 DotDuration = GetSpellDuration(spellProto);
+ // 200% limit
+ if(DotDuration > 0)
+ {
+ if(DotDuration > 30000) DotDuration = 30000;
+ if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f;
+ int x = 0;
+ for(int j = 0; j < 3; j++)
+ {
+ if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
+ spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE ||
+ spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
+ {
+ x = j;
+ break;
+ }
+ }
+ int32 DotTicks = 6;
+ if(spellProto->EffectAmplitude[x] != 0)
+ DotTicks = DotDuration / spellProto->EffectAmplitude[x];
+ if(DotTicks)
+ {
+ DoneAdvertisedBenefit /= DotTicks*int32(stack);
+ TakenAdvertisedBenefit /= DotTicks*int32(stack);
+ }
+ }
+ }
+ // Distribute Damage over multiple effects, reduce by AoE
+ CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
+ // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
+ for(int j = 0; j < 3; ++j)
+ {
+ if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
+ spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH )
+ {
+ CastingTime /= 2;
+ break;
+ }
+ }
+ coeff = (CastingTime / 3500.0f) * DotFactor;
+ }
- //ActualBenefit = (float)AdvertisedBenefit * ((float)CastingTime / 3500.0f) * DotFactor * SpellModSpellDamage * LvlPenalty;
- ActualBenefit = (float)AdvertisedBenefit * CoefficientPtc * LvlPenalty;
+ float coeff2 = CalculateLevelPenalty(spellProto) * 1.88f * stack;
+ TakenTotal+= TakenAdvertisedBenefit * coeff * coeff2;
+ if(Player* modOwner = GetSpellModOwner())
+ {
+ coeff *= 100.0f;
+ modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_SPELL_BONUS_DAMAGE, coeff);
+ coeff /= 100.0f;
}
+ DoneTotal += DoneAdvertisedBenefit * coeff * coeff2;
// use float as more appropriate for negative values and percent applying
- float heal = healamount + ActualBenefit;
-
- // TODO: check for ALL/SPELLS type
- // Healing done percent
- AuraList const& mHealingDonePct = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT);
- for(AuraList::const_iterator i = mHealingDonePct.begin();i != mHealingDonePct.end(); ++i)
- heal *= (100.0f + (*i)->GetModifierValue()) / 100.0f;
-
+ float heal = (healamount + DoneTotal)*DoneTotalMod;
// apply spellmod to Done amount
if(Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
+ // Taken mods
// Healing Wave cast
- if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags & 0x0000000000000040LL)
+ if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[0] & 0x40)
{
- // Search for Healing Way on Victim (stack up to 3 time)
- int32 pctMod = 0;
+ // Search for Healing Way on Victim
Unit::AuraList const& auraDummy = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr!=auraDummy.end(); ++itr)
if((*itr)->GetId() == 29203)
- pctMod += (*itr)->GetModifier()->m_amount;
- // Apply bonus
- if (pctMod)
- heal = heal * (100 + pctMod) / 100;
+ TakenTotalMod *= ((*itr)->GetModifier()->m_amount+100.0f) / 100.0f;
}
// Healing taken percent
float minval = pVictim->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
if(minval)
- heal *= (100.0f + minval) / 100.0f;
+ TakenTotalMod *= (100.0f + minval) / 100.0f;
float maxval = pVictim->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
if(maxval)
- heal *= (100.0f + maxval) / 100.0f;
+ TakenTotalMod *= (100.0f + maxval) / 100.0f;
+
+ AuraList const& mHealingGet= pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING_RECEIVED);
+ for(AuraList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i)
+ if ((*i)->isAffectedOnSpell(spellProto))
+ TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
- if (heal < 0) heal = 0;
+ heal = (heal + TakenTotal) * TakenTotalMod;
- return uint32(heal);
+ return heal < 0 ? 0 : uint32(heal);
}
int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask)
@@ -9308,25 +8610,28 @@ int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask)
AuraList const& mHealingDone = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE);
for(AuraList::const_iterator i = mHealingDone.begin();i != mHealingDone.end(); ++i)
if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0)
- AdvertisedBenefit += (*i)->GetModifierValue();
+ AdvertisedBenefit += (*i)->GetModifier()->m_amount;
// Healing bonus of spirit, intellect and strength
if (GetTypeId() == TYPEID_PLAYER)
{
+ // Base value
+ AdvertisedBenefit +=((Player*)this)->GetBaseSpellHealingBonus();
+
// Healing bonus from stats
AuraList const& mHealingDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT);
for(AuraList::const_iterator i = mHealingDoneOfStatPercent.begin();i != mHealingDoneOfStatPercent.end(); ++i)
{
// stat used dependent from misc value (stat index)
Stats usedStat = Stats((*i)->GetSpellProto()->EffectMiscValue[(*i)->GetEffIndex()]);
- AdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifierValue() / 100.0f);
+ AdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifier()->m_amount / 100.0f);
}
// ... and attack power
AuraList const& mHealingDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER);
for(AuraList::const_iterator i = mHealingDonebyAP.begin();i != mHealingDonebyAP.end(); ++i)
if ((*i)->GetModifier()->m_miscvalue & schoolMask)
- AdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifierValue() / 100.0f);
+ AdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifier()->m_amount / 100.0f);
}
return AdvertisedBenefit;
}
@@ -9337,11 +8642,11 @@ int32 Unit::SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVi
AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING);
for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0)
- AdvertisedBenefit += (*i)->GetModifierValue();
+ AdvertisedBenefit += (*i)->GetModifier()->m_amount;
return AdvertisedBenefit;
}
-bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask, bool useCharges)
+bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask)
{
//If m_immuneToSchool type contain this school type, IMMUNE damage.
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
@@ -9358,7 +8663,7 @@ bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask, bool useCharges)
return false;
}
-bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges)
+bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo)
{
if (!spellInfo)
return false;
@@ -9400,18 +8705,37 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges)
return false;
}
-bool Unit::IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const
+bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const
{
//If m_immuneToEffect type contain this effect type, IMMUNE effect.
+ uint32 effect = spellInfo->Effect[index];
SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT];
for (SpellImmuneList::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr)
if(itr->type == effect)
return true;
- SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
- for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
- if(itr->type == mechanic)
- return true;
+ if(uint32 mechanic = spellInfo->EffectMechanic[index])
+ {
+ SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
+ for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
+ if(itr->type == mechanic)
+ return true;
+ }
+
+ if(uint32 aura = spellInfo->EffectApplyAuraName[index])
+ {
+ SpellImmuneList const& list = m_spellImmune[IMMUNITY_STATE];
+ for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
+ if(itr->type == aura)
+ return true;
+ // Check for immune to application of harmful magical effects
+ AuraList const& immuneAuraApply = GetAurasByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL);
+ for(AuraList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter)
+ if (spellInfo->Dispel == DISPEL_MAGIC && // Magic debuff
+ ((*iter)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellInfo)) && // Check school
+ !IsPositiveEffect(spellInfo->Id, index)) // Harmful
+ return true;
+ }
return false;
}
@@ -9449,7 +8773,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT
AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE);
for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i)
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
- DoneFlatBenefit += (*i)->GetModifierValue();
+ DoneFlatBenefit += (*i)->GetModifier()->m_amount;
// ..done
// SPELL_AURA_MOD_DAMAGE_DONE included in weapon damage
@@ -9464,7 +8788,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT
AuraList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS);
for(AuraList::const_iterator i = mCreatureAttackPower.begin();i != mCreatureAttackPower.end(); ++i)
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
- APbonus += (*i)->GetModifierValue();
+ APbonus += (*i)->GetModifier()->m_amount;
}
else
{
@@ -9474,7 +8798,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT
AuraList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS);
for(AuraList::const_iterator i = mCreatureAttackPower.begin();i != mCreatureAttackPower.end(); ++i)
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
- APbonus += (*i)->GetModifierValue();
+ APbonus += (*i)->GetModifier()->m_amount;
}
if (APbonus!=0) // Can be negative
@@ -9499,7 +8823,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT
AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
if((*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask())
- TakenFlatBenefit += (*i)->GetModifierValue();
+ TakenFlatBenefit += (*i)->GetModifier()->m_amount;
if(attType!=RANGED_ATTACK)
TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN);
@@ -9507,8 +8831,8 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT
TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN);
// Done/Taken total percent damage auras
- float DoneTotalMod = 1;
- float TakenTotalMod = 1;
+ float DoneTotalMod = 1.0f;
+ float TakenTotalMod = 1.0f;
// ..done
// SPELL_AURA_MOD_DAMAGE_PERCENT_DONE included in weapon damage
@@ -9517,13 +8841,13 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT
AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i)
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
- DoneTotalMod *= ((*i)->GetModifierValue()+100.0f)/100.0f;
+ DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
// ..taken
AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i)
if((*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask())
- TakenTotalMod *= ((*i)->GetModifierValue()+100.0f)/100.0f;
+ TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
// .. taken pct: dummy auras
AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
@@ -9548,7 +8872,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT
if(spellProto==NULL)
break;
// Should increase Shred (initial Damage of Lacerate and Rake handled in Spell::EffectSchoolDMG)
- if(spellProto->SpellFamilyName==SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags==0x00008000LL))
+ if(spellProto->SpellFamilyName==SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags.IsEqual (0x00008000,0,0))
TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f;
break;
}
@@ -9581,13 +8905,13 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT
{
AuraList const& mModMeleeDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT);
for(AuraList::const_iterator i = mModMeleeDamageTakenPercent.begin(); i != mModMeleeDamageTakenPercent.end(); ++i)
- TakenTotalMod *= ((*i)->GetModifierValue()+100.0f)/100.0f;
+ TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
}
else
{
AuraList const& mModRangedDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT);
for(AuraList::const_iterator i = mModRangedDamageTakenPercent.begin(); i != mModRangedDamageTakenPercent.end(); ++i)
- TakenTotalMod *= ((*i)->GetModifierValue()+100.0f)/100.0f;
+ TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
}
float tmpDamage = float(int32(*pdamage) + DoneFlatBenefit) * DoneTotalMod;
@@ -9710,7 +9034,7 @@ void Unit::Unmount()
if(GetTypeId() == TYPEID_PLAYER && IsInWorld() && ((Player*)this)->GetTemporaryUnsummonedPetNumber() && isAlive())
{
Pet* NewPet = new Pet;
- if(!NewPet->LoadPetFromDB(this, 0, ((Player*)this)->GetTemporaryUnsummonedPetNumber(), true))
+ if(!NewPet->LoadPetFromDB((Player*)this, 0, ((Player*)this)->GetTemporaryUnsummonedPetNumber(), true))
delete NewPet;
((Player*)this)->SetTemporaryUnsummonedPetNumber(0);
@@ -9742,7 +9066,7 @@ void Unit::SetInCombatWith(Unit* enemy)
void Unit::CombatStart(Unit* target)
{
if(!target->IsStandState()/* && !target->hasUnitState(UNIT_STAT_STUNNED)*/)
- target->SetStandState(PLAYER_STATE_NONE);
+ target->SetStandState(UNIT_STAND_STATE_STAND);
if(!target->isInCombat() && target->GetTypeId() != TYPEID_PLAYER
&& !((Creature*)target)->HasReactState(REACT_PASSIVE) && ((Creature*)target)->AI())
@@ -10026,7 +9350,7 @@ void Unit::DestroyForNearbyPlayers()
std::list<Unit*> targets;
Trinity::AnyUnitInObjectRangeCheck check(this, World::GetMaxVisibleDistance());
- Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(targets, check);
+ Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(this, targets, check);
VisitNearbyWorldObject(World::GetMaxVisibleDistance(), searcher);
for(std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter)
if(*iter != this && (*iter)->GetTypeId() == TYPEID_PLAYER
@@ -10150,38 +9474,37 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
propagateSpeedChange();
- // Send speed change packet only for player
- if (GetTypeId()!=TYPEID_PLAYER)
- return;
-
WorldPacket data;
if(!forced)
{
switch(mtype)
{
case MOVE_WALK:
- data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+1+4+4+4+4+4+4+4);
+ data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_RUN:
- data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+1+4+4+4+4+4+4+4);
+ data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_RUN_BACK:
- data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4);
+ data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_SWIM:
- data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+1+4+4+4+4+4+4+4);
+ data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_SWIM_BACK:
- data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4);
+ data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_TURN_RATE:
- data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+1+4+4+4+4+4+4+4);
+ data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_FLIGHT:
- data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+1+4+4+4+4+4+4+4);
+ data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_FLIGHT_BACK:
- data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4);
+ data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
+ break;
+ case MOVE_PITCH_RATE:
+ data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8+4+2+4+4+4+4+4+4+4);
break;
default:
sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype);
@@ -10189,22 +9512,26 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
}
data.append(GetPackGUID());
- data << uint32(0); //movement flags
- data << uint8(0); //unk
+ data << uint32(0); // movement flags
+ data << uint16(0); // unk flags
data << uint32(getMSTime());
data << float(GetPositionX());
data << float(GetPositionY());
data << float(GetPositionZ());
data << float(GetOrientation());
- data << uint32(0); //flag unk
+ data << uint32(0); // fall time
data << float(GetSpeed(mtype));
SendMessageToSet( &data, true );
}
else
{
- // register forced speed changes for WorldSession::HandleForceSpeedChangeAck
- // and do it only for real sent packets and use run for run/mounted as client expected
- ++((Player*)this)->m_forced_speed_changes[mtype];
+ if(GetTypeId() == TYPEID_PLAYER)
+ {
+ // register forced speed changes for WorldSession::HandleForceSpeedChangeAck
+ // and do it only for real sent packets and use run for run/mounted as client expected
+ ++((Player*)this)->m_forced_speed_changes[mtype];
+ }
+
switch(mtype)
{
case MOVE_WALK:
@@ -10231,6 +9558,9 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
case MOVE_FLIGHT_BACK:
data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16);
break;
+ case MOVE_PITCH_RATE:
+ data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16);
+ break;
default:
sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype);
return;
@@ -10320,6 +9650,10 @@ bool Unit::CanHaveThreatList() const
if( ((Creature*)this)->isTotem() )
return false;
+ // vehicles can not have threat list
+ if( ((Creature*)this)->isVehicle() )
+ return false;
+
// pets can not have a threat list, unless they are controlled by a creature
if( ((Creature*)this)->isPet() && IS_PLAYER_GUID(((Pet*)this)->GetOwnerGUID()) )
return false;
@@ -10424,18 +9758,44 @@ Unit* Creature::SelectVictim()
//or who does not have threat (totem/pet/critter)
//otherwise enterevademode every update
- Unit* target = NULL;
- if(!m_ThreatManager.isThreatListEmpty())
+
+ Unit* target = NULL;
+ // First checking if we have some taunt on us
+ const AuraList& tauntAuras = GetAurasByType(SPELL_AURA_MOD_TAUNT);
+ if ( !tauntAuras.empty() )
{
- if(!HasAuraType(SPELL_AURA_MOD_TAUNT))
+ Unit* caster;
+
+ // The last taunt aura caster is alive an we are happy to attack him
+ if ( (caster = tauntAuras.back()->GetCaster()) && caster->isAlive() )
+ return getVictim();
+ else if (tauntAuras.size() > 1)
{
- target = m_ThreatManager.getHostilTarget();
+ // We do not have last taunt aura caster but we have more taunt auras,
+ // so find first available target
+
+ // Auras are pushed_back, last caster will be on the end
+ AuraList::const_iterator aura = --tauntAuras.end();
+ do
+ {
+ --aura;
+ if ( (caster = (*aura)->GetCaster()) &&
+ caster->IsInMap(this) && canAttack(caster) && caster->isInAccessiblePlaceFor((Creature*)this) )
+ {
+ target = caster;
+ break;
+ }
+ }while (aura != tauntAuras.begin());
}
else
target = getVictim();
}
+ if ( !target && !m_ThreatManager.isThreatListEmpty() )
+ // No taunt aura or taunt aura caster is dead standart target selection
+ target = m_ThreatManager.getHostilTarget();
+
if(target)
{
if(!hasUnitState(UNIT_STAT_STUNNED))
@@ -10507,8 +9867,11 @@ int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_inde
int32 randomPoints = int32(spellProto->EffectDieSides[effect_index] + level * randomPointsPerLevel);
float comboDamage = spellProto->EffectPointsPerComboPoint[effect_index];
- // prevent random generator from getting confused by spells casted with Unit::CastCustomSpell
- int32 randvalue = spellProto->EffectBaseDice[effect_index] >= randomPoints ? spellProto->EffectBaseDice[effect_index]:irand(spellProto->EffectBaseDice[effect_index], randomPoints);
+ // range can have possitive and negative values, so order its for irand
+ int32 randvalue = int32(spellProto->EffectBaseDice[effect_index]) >= randomPoints
+ ? irand(randomPoints, int32(spellProto->EffectBaseDice[effect_index]))
+ : irand(int32(spellProto->EffectBaseDice[effect_index]), randomPoints);
+
int32 value = basePoints + randvalue;
//random damage
if(comboDamage != 0 && unitPlayer /*&& target && (target->GetGUID() == unitPlayer->GetComboTarget())*/)
@@ -10562,6 +9925,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);
@@ -10612,21 +9977,15 @@ DiminishingLevels Unit::GetDiminishing(DiminishingGroup group)
void Unit::IncrDiminishing(DiminishingGroup group)
{
// Checking for existing in the table
- bool IsExist = false;
for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i)
{
if(i->DRGroup != group)
continue;
-
- IsExist = true;
if(i->hitCount < DIMINISHING_LEVEL_IMMUNE)
i->hitCount += 1;
-
- break;
+ return;
}
-
- if(!IsExist)
- m_Diminishing.push_back(DiminishingReturn(group,getMSTime(),DIMINISHING_LEVEL_2));
+ m_Diminishing.push_back(DiminishingReturn(group,getMSTime(),DIMINISHING_LEVEL_2));
}
void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster,DiminishingLevels Level)
@@ -10675,13 +10034,15 @@ void Unit::ApplyDiminishingAura( DiminishingGroup group, bool apply )
if(i->DRGroup != group)
continue;
- i->hitTime = getMSTime();
-
if(apply)
i->stack += 1;
else if(i->stack)
+ {
i->stack -= 1;
-
+ // Remember time after last aura from group removed
+ if (i->stack == 0)
+ i->hitTime = getMSTime();
+ }
break;
}
}
@@ -10763,7 +10124,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:
@@ -10876,21 +10239,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
@@ -10989,6 +10349,12 @@ void Unit::SetPower(Powers power, uint32 val)
SetStatInt32Value(UNIT_FIELD_POWER1 + power, val);
+ WorldPacket data(SMSG_POWER_UPDATE);
+ data.append(GetPackGUID());
+ data << uint8(power);
+ data << uint32(val);
+ SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER ? true : false);
+
// group update
if(GetTypeId() == TYPEID_PLAYER)
{
@@ -11102,6 +10468,7 @@ uint32 Unit::GetCreatePowers( Powers power ) const
case POWER_FOCUS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 100);
case POWER_ENERGY: return 100;
case POWER_HAPPINESS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 1050000);
+ case POWER_RUNIC_POWER: return 1000;
}
return 0;
@@ -11189,7 +10556,7 @@ void CharmInfo::InitEmptyActionBar(bool withAttack)
for(uint32 x = 0; x < 10; ++x)
{
- PetActionBar[x].Type = ACT_CAST;
+ PetActionBar[x].Type = ACT_PASSIVE;
PetActionBar[x].SpellOrAction = 0;
}
if (withAttack)
@@ -11205,13 +10572,20 @@ void CharmInfo::InitPossessCreateSpells()
InitEmptyActionBar();
if(m_unit->GetTypeId() == TYPEID_UNIT)
{
- for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
+ /*for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
{
uint32 spellid = ((Creature*)m_unit)->m_spells[i];
if(IsPassiveSpell(spellid))
m_unit->CastSpell(m_unit, spellid, true);
else
AddSpellToAB(0, spellid, ACT_CAST);
+ }*/
+ for(uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x)
+ {
+ if (IsPassiveSpell(((Creature*)m_unit)->m_spells[x]))
+ m_unit->CastSpell(m_unit, ((Creature*)m_unit)->m_spells[x], true);
+ else
+ AddSpellToAB(0, ((Creature*)m_unit)->m_spells[x], ACT_PASSIVE);
}
}
}
@@ -11255,7 +10629,7 @@ void CharmInfo::InitCharmCreateSpells()
if(onlyselfcast || !IsPositiveSpell(spellId)) //only self cast and spells versus enemies are autocastable
newstate = ACT_DISABLED;
else
- newstate = ACT_CAST;
+ newstate = ACT_PASSIVE;
AddSpellToAB(0, spellId, newstate);
}
@@ -11266,7 +10640,7 @@ bool CharmInfo::AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate)
{
for(uint8 i = 0; i < 10; i++)
{
- if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_CAST) && PetActionBar[i].SpellOrAction == oldid)
+ if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_PASSIVE) && PetActionBar[i].SpellOrAction == oldid)
{
PetActionBar[i].SpellOrAction = newid;
if(!oldid)
@@ -11308,188 +10682,9 @@ void CharmInfo::SetPetNumber(uint32 petnumber, bool statwindow)
bool Unit::isFrozen() const
{
- AuraList const& mRoot = GetAurasByType(SPELL_AURA_MOD_ROOT);
- for(AuraList::const_iterator i = mRoot.begin(); i != mRoot.end(); ++i)
- if( GetSpellSchoolMask((*i)->GetSpellProto()) & SPELL_SCHOOL_MASK_FROST)
- return true;
- return false;
+ return HasAuraState(AURA_STATE_FROZEN);
}
-/*
-struct ProcTriggeredData
-{
- ProcTriggeredData(Aura* _triggeredByAura, uint32 _cooldown)
- : triggeredByAura(_triggeredByAura),
- triggeredByAura_SpellPair(Unit::spellEffectPair(triggeredByAura->GetId(),triggeredByAura->GetEffIndex())),
- cooldown(_cooldown)
- {}
-
- Aura* triggeredByAura; // triggred aura, can be invalidate at triggered aura proccessing
- Unit::spellEffectPair triggeredByAura_SpellPair; // spell pair, used for re-find aura (by pointer comparison in range)
- uint32 cooldown; // possible hidden cooldown
-};
-
-typedef std::list< ProcTriggeredData > ProcTriggeredList;
-
-void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, AuraTypeSet const& procAuraTypes, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage, SpellSchoolMask damageSchoolMask )
-{
- for(AuraTypeSet::const_iterator aur = procAuraTypes.begin(); aur != procAuraTypes.end(); ++aur)
- {
- // List of spells (effects) that proceed. Spell prototype and aura-specific value (damage for TRIGGER_DAMAGE)
- ProcTriggeredList procTriggered;
-
- AuraList const& auras = GetAurasByType(*aur);
- for(AuraList::const_iterator i = auras.begin(), next; i != auras.end(); i = next)
- {
- next = i; ++next;
-
- Aura* i_aura = *i;
-
- uint32 cooldown; // returned at next line
- if(!IsTriggeredAtSpellProcEvent(i_aura->GetSpellProto(), procSpell, procFlag,attType,isVictim,cooldown))
- continue;
-
- procTriggered.push_back( ProcTriggeredData(i_aura, cooldown) );
- }
-
- // Handle effects proceed this time
- for(ProcTriggeredList::iterator i = procTriggered.begin(); i != procTriggered.end(); ++i)
- {
- // Some auras can be deleted in function called in this loop (except first, ofc)
- // Until storing auras in std::multimap to hard check deleting by another way
- if(i != procTriggered.begin())
- {
- bool found = false;
- AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair);
- AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair);
- for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr)
- {
- if(itr->second==i->triggeredByAura)
- {
- found = true;
- break;
- }
- }
-
- if(!found)
- {
- sLog.outError("Spell aura %u (id:%u effect:%u) has been deleted before call spell proc event handler",*aur,i->triggeredByAura_SpellPair.first,i->triggeredByAura_SpellPair.second);
- sLog.outError("It can be deleted one from early processed auras:");
- for(ProcTriggeredList::iterator i2 = procTriggered.begin(); i != i2; ++i2)
- sLog.outError(" Spell aura %u (id:%u effect:%u)",*aur,i2->triggeredByAura_SpellPair.first,i2->triggeredByAura_SpellPair.second);
- sLog.outError(" <end of list>");
- continue;
- }
- }
-
- /// this is aura triggering code call
- Aura* triggeredByAura = i->triggeredByAura;
-
- /// save charges existence before processing to prevent crash at access to deleted triggered aura after
- /// used in speedup code check before check aura existance.
- bool triggeredByAuraWithCharges = triggeredByAura->m_procCharges > 0;
-
- /// success in event proccesing
- /// used in speedup code check before check aura existance.
- bool casted = false;
-
- /// process triggered code
- switch(*aur)
- {
- case SPELL_AURA_PROC_TRIGGER_SPELL:
- {
- sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s proc aura of spell %u)",
- (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
- casted = HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, attType, i->cooldown);
- break;
- }
- case SPELL_AURA_PROC_TRIGGER_DAMAGE:
- {
- uint32 triggered_damage = triggeredByAura->GetModifier()->m_amount;
- sLog.outDebug("ProcDamageAndSpell: doing %u damage (triggered by %s aura of spell %u)",
- triggered_damage, (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
- SpellNonMeleeDamageLog(pTarget, triggeredByAura->GetId(), triggered_damage, true, true);
- casted = true;
- break;
- }
- case SPELL_AURA_DUMMY:
- {
- uint32 effect = triggeredByAura->GetEffIndex();
- sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s dummy aura of spell %u)",
- (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
- casted = HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag,i->cooldown);
- break;
- }
- case SPELL_AURA_PRAYER_OF_MENDING:
- {
- sLog.outDebug("ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
- (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
-
- casted = HandleMeandingAuraProc(triggeredByAura);
- break;
- }
- case SPELL_AURA_MOD_HASTE:
- {
- sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s haste aura of spell %u)",
- (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
- casted = HandleHasteAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag,i->cooldown);
- break;
- }
- case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
- {
- // nothing do, just charges counter
- // but count only in case appropriate school damage
- casted = triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask;
- break;
- }
- case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
- {
- sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s class script aura of spell %u)",
- (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
- casted = HandleOverrideClassScriptAuraProc(pTarget, triggeredByAura, procSpell,i->cooldown);
- break;
- }
- default:
- {
- // nothing do, just charges counter
- casted = true;
- break;
- }
- }
-
- /// Update charge (aura can be removed by triggers)
- if(casted && triggeredByAuraWithCharges)
- {
- /// need re-found aura (can be dropped by triggers)
- AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair);
- AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair);
- for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr)
- {
- if(itr->second == triggeredByAura) // pointer still valid
- {
- if(triggeredByAura->m_procCharges > 0)
- triggeredByAura->m_procCharges -= 1;
-
- triggeredByAura->UpdateAuraCharges();
- break;
- }
- }
- }
- }
-
- /// Safely remove auras with zero charges
- for(AuraList::const_iterator i = auras.begin(), next; i != auras.end(); i = next)
- {
- next = i; ++next;
- if((*i)->m_procCharges == 0)
- {
- RemoveAurasDueToSpell((*i)->GetId());
- next = auras.begin();
- }
- }
- }
-}
-*/
struct ProcTriggeredData
{
ProcTriggeredData(SpellProcEventEntry const * _spellProcEvent, Aura* _triggeredByAura)
@@ -11508,9 +10703,7 @@ typedef std::list< uint32> RemoveSpellList;
// in most case need for drop charges
// in some types of aura need do additional check
// for example SPELL_AURA_MECHANIC_IMMUNITY - need check for mechanic
-static bool isTriggerAura[TOTAL_AURAS];
-static bool isNonTriggerAura[TOTAL_AURAS];
-void InitTriggerAuraData()
+bool InitTriggerAuraData()
{
for (int i=0;i<TOTAL_AURAS;i++)
{
@@ -11529,7 +10722,7 @@ void InitTriggerAuraData()
isTriggerAura[SPELL_AURA_DAMAGE_IMMUNITY] = true;
isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL] = true;
isTriggerAura[SPELL_AURA_PROC_TRIGGER_DAMAGE] = true;
- isTriggerAura[SPELL_AURA_MOD_CASTING_SPEED] = true;
+ isTriggerAura[SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK] = true;
isTriggerAura[SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT] = true;
isTriggerAura[SPELL_AURA_MOD_POWER_COST_SCHOOL] = true;
isTriggerAura[SPELL_AURA_REFLECT_SPELLS_SCHOOL] = true;
@@ -11544,9 +10737,13 @@ void InitTriggerAuraData()
isTriggerAura[SPELL_AURA_MOD_HASTE] = true;
isTriggerAura[SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE]=true;
isTriggerAura[SPELL_AURA_PRAYER_OF_MENDING] = true;
+ isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE] = true;
+ isTriggerAura[SPELL_AURA_MOD_DAMAGE_FROM_CASTER] = true;
isNonTriggerAura[SPELL_AURA_MOD_POWER_REGEN]=true;
- isNonTriggerAura[SPELL_AURA_RESIST_PUSHBACK]=true;
+ isNonTriggerAura[SPELL_AURA_REDUCE_PUSHBACK]=true;
+
+ return true;
}
uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition)
@@ -11587,18 +10784,8 @@ uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missC
return procEx;
}
-static int deep = 0;
void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage )
{
- deep ++;
- if (deep > 5)
- {
- sLog.outError("Prevent possible stack owerflow in Unit::ProcDamageAndSpellFor");
- if (procSpell)
- sLog.outError(" Spell %u", procSpell->Id);
- deep--;
- return;
- }
// For melee/ranged based attack need update skills and set some Aura states
if (procFlag & MELEE_BASED_TRIGGER_MASK)
{
@@ -11609,7 +10796,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
if (procExtra&(PROC_EX_NORMAL_HIT|PROC_EX_MISS|PROC_EX_RESIST))
{
if (pTarget->GetTypeId() != TYPEID_PLAYER && pTarget->GetCreatureType() != CREATURE_TYPE_CRITTER)
- ((Player*)this)->UpdateCombatSkills(pTarget, attType, MELEE_HIT_MISS, isVictim);
+ ((Player*)this)->UpdateCombatSkills(pTarget, attType, isVictim);
}
// Update defence if player is victim and parry/dodge/block
if (isVictim && procExtra&(PROC_EX_DODGE|PROC_EX_PARRY|PROC_EX_BLOCK))
@@ -11661,17 +10848,6 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
((Player*)this)->AddComboPoints(pTarget, 1);
StartReactiveTimer( REACTIVE_OVERPOWER );
}
- // Enable AURA_STATE_CRIT on crit
- if (procExtra & PROC_EX_CRITICAL_HIT)
- {
- ModifyAuraState(AURA_STATE_CRIT, true);
- StartReactiveTimer( REACTIVE_CRIT );
- if(getClass()==CLASS_HUNTER)
- {
- ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true);
- StartReactiveTimer( REACTIVE_HUNTER_CRIT );
- }
- }
}
}
}
@@ -11682,11 +10858,16 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
for(AuraMap::const_iterator itr = GetAuras().begin(); itr!= GetAuras().end(); ++itr)
{
SpellProcEventEntry const* spellProcEvent = NULL;
- if(!IsTriggeredAtSpellProcEvent(itr->second, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent))
+ if(!IsTriggeredAtSpellProcEvent(pTarget, itr->second, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent))
continue;
procTriggered.push_back( ProcTriggeredData(spellProcEvent, itr->second) );
}
+
+ // Nothing found
+ if (procTriggered.empty())
+ return;
+
// Handle effects proceed this time
for(ProcTriggeredList::iterator i = procTriggered.begin(); i != procTriggered.end(); ++i)
{
@@ -11721,7 +10902,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
Modifier *auraModifier = triggeredByAura->GetModifier();
SpellEntry const *spellInfo = triggeredByAura->GetSpellProto();
uint32 effIndex = triggeredByAura->GetEffIndex();
- bool useCharges = triggeredByAura->m_procCharges > 0;
+ bool useCharges = triggeredByAura->GetAuraCharges() > 0;
// For players set spell cooldown if need
uint32 cooldown = 0;
if (GetTypeId() == TYPEID_PLAYER && spellProcEvent && spellProcEvent->cooldown)
@@ -11765,7 +10946,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
{
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (!HandleOverrideClassScriptAuraProc(pTarget, triggeredByAura, procSpell, cooldown))
+ if (!HandleOverrideClassScriptAuraProc(pTarget, damage, triggeredByAura, procSpell, cooldown))
continue;
break;
}
@@ -11777,23 +10958,15 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
HandleMeandingAuraProc(triggeredByAura);
break;
}
- case SPELL_AURA_MOD_STUN:
- // Remove by default, but if charge exist drop it
- if (triggeredByAura->m_procCharges == 0)
- removedSpells.push_back(triggeredByAura->GetId());
- break;
- case SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS:
- case SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS:
- // Hunter's Mark (1-4 Rangs)
- if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && (spellInfo->SpellFamilyFlags&0x0000000000000400LL))
- {
- uint32 basevalue = triggeredByAura->GetBasePoints();
- auraModifier->m_amount += basevalue/10;
- if (auraModifier->m_amount > basevalue*4)
- auraModifier->m_amount = basevalue*4;
- }
+ case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE:
+ {
+ sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+
+ if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ continue;
break;
- case SPELL_AURA_MOD_CASTING_SPEED:
+ }
+ case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
// Skip melee hits or instant cast spells
if (procSpell == NULL || GetSpellCastTime(procSpell) == 0)
continue;
@@ -11821,6 +10994,11 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue)
continue;
break;
+ case SPELL_AURA_MOD_DAMAGE_FROM_CASTER:
+ // Compare casters
+ if (triggeredByAura->GetCasterGUID() != pTarget->GetGUID())
+ continue;
+ break;
default:
// nothing do, just charges counter
break;
@@ -11833,18 +11011,16 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair);
for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr)
{
- if(itr->second == i->triggeredByAura)
+ // If last charge dropped add spell to remove list
+ if(itr->second == i->triggeredByAura && triggeredByAura->DropAuraCharge())
{
- triggeredByAura->m_procCharges -=1;
- triggeredByAura->UpdateAuraCharges();
- if (triggeredByAura->m_procCharges <= 0)
- removedSpells.push_back(triggeredByAura->GetId());
+ removedSpells.push_back(triggeredByAura->GetId());
break;
}
}
}
}
- if (removedSpells.size())
+ if (!removedSpells.empty())
{
// Sort spells and remove dublicates
removedSpells.sort();
@@ -11853,7 +11029,6 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
for(RemoveSpellList::const_iterator i = removedSpells.begin(); i != removedSpells.end();i++)
RemoveAurasDueToSpell(*i);
}
- deep--;
}
SpellSchoolMask Unit::GetMeleeDamageSchoolMask() const
@@ -11882,8 +11057,11 @@ void Unit::SendPetCastFail(uint32 spellid, uint8 msg)
return;
WorldPacket data(SMSG_PET_CAST_FAILED, (4+1));
+ data << uint8(0); // cast count?
data << uint32(spellid);
data << uint8(msg);
+ // uint32 for some reason
+ // uint32 for some reason
((Player*)owner)->GetSession()->SendPacket(&data);
}
@@ -12043,15 +11221,16 @@ void Unit::SetConfused(bool apply, uint64 casterGUID, uint32 spellID)
bool Unit::IsSitState() const
{
uint8 s = getStandState();
- return s == PLAYER_STATE_SIT_CHAIR || s == PLAYER_STATE_SIT_LOW_CHAIR ||
- s == PLAYER_STATE_SIT_MEDIUM_CHAIR || s == PLAYER_STATE_SIT_HIGH_CHAIR ||
- s == PLAYER_STATE_SIT;
+ return
+ s == UNIT_STAND_STATE_SIT_CHAIR || s == UNIT_STAND_STATE_SIT_LOW_CHAIR ||
+ s == UNIT_STAND_STATE_SIT_MEDIUM_CHAIR || s == UNIT_STAND_STATE_SIT_HIGH_CHAIR ||
+ s == UNIT_STAND_STATE_SIT;
}
bool Unit::IsStandState() const
{
uint8 s = getStandState();
- return !IsSitState() && s != PLAYER_STATE_SLEEP && s != PLAYER_STATE_KNEEL;
+ return !IsSitState() && s != UNIT_STAND_STATE_SLEEP && s != UNIT_STAND_STATE_KNEEL;
}
void Unit::SetStandState(uint8 state)
@@ -12105,7 +11284,6 @@ void Unit::ClearComboPointHolders()
void Unit::ClearAllReactives()
{
-
for(int i=0; i < MAX_REACTIVE; ++i)
m_reactiveTimer[i] = 0;
@@ -12113,11 +11291,6 @@ void Unit::ClearAllReactives()
ModifyAuraState(AURA_STATE_DEFENSE, false);
if (getClass() == CLASS_HUNTER && HasAuraState( AURA_STATE_HUNTER_PARRY))
ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
- if (HasAuraState( AURA_STATE_CRIT))
- ModifyAuraState(AURA_STATE_CRIT, false);
- if (getClass() == CLASS_HUNTER && HasAuraState( AURA_STATE_HUNTER_CRIT_STRIKE) )
- ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, false);
-
if(getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
((Player*)this)->ClearComboPoints();
}
@@ -12145,14 +11318,6 @@ void Unit::UpdateReactives( uint32 p_time )
if ( getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_PARRY))
ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
break;
- case REACTIVE_CRIT:
- if (HasAuraState(AURA_STATE_CRIT))
- ModifyAuraState(AURA_STATE_CRIT, false);
- break;
- case REACTIVE_HUNTER_CRIT:
- if ( getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_CRIT_STRIKE) )
- ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, false);
- break;
case REACTIVE_OVERPOWER:
if(getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
((Player*)this)->ClearComboPoints();
@@ -12172,7 +11337,7 @@ Unit* Unit::SelectNearbyTarget(float dist) const
{
std::list<Unit *> targets;
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, this, dist);
- Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
+ Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(this, targets, u_check);
VisitNearbyObject(dist, searcher);
// remove current target
@@ -12205,6 +11370,16 @@ Unit* Unit::SelectNearbyTarget(float dist) const
return *tcIter;
}
+bool Unit::hasNegativeAuraWithInterruptFlag(uint32 flag)
+{
+ for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ++iter)
+ {
+ if (!iter->second->IsPositive() && iter->second->GetSpellProto()->AuraInterruptFlags & flag)
+ return true;
+ }
+ return false;
+}
+
void Unit::ApplyAttackTimePercentMod( WeaponAttackType att,float val, bool apply )
{
float remainingTimePct = (float)m_attackTimer[att] / (GetAttackTime(att) * m_modAttackSpeedPct[att]);
@@ -12437,7 +11612,12 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id)
pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, spell_id);
- if(!pet->InitStatsForLevel(creatureTarget->getLevel()))
+ if(GetTypeId()==TYPEID_PLAYER)
+ pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
+
+ uint32 level = (creatureTarget->getLevel() < (getLevel() - 5)) ? (getLevel() - 5) : creatureTarget->getLevel();
+
+ if(!pet->InitStatsForLevel(level))
{
sLog.outError("ERROR: Pet::InitStatsForLevel() failed for creature (Entry: %u)!",creatureTarget->GetEntry());
delete pet;
@@ -12448,12 +11628,13 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id)
// this enables pet details window (Shift+P)
pet->AIM_Initialize();
pet->InitPetCreateSpells();
+ pet->InitTalentForLevel();
pet->SetHealth(pet->GetMaxHealth());
return pet;
}
-bool Unit::IsTriggeredAtSpellProcEvent(Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent )
+bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent )
{
SpellEntry const* spellProto = aura->GetSpellProto ();
@@ -12483,7 +11664,17 @@ bool Unit::IsTriggeredAtSpellProcEvent(Aura* aura, SpellEntry const* procSpell,
if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active))
return false;
- // Aura added by spell can`t trogger from self (prevent drop cahres/do triggers)
+ // In most cases req get honor or XP from kill
+ if (EventProcFlag & PROC_FLAG_KILL && GetTypeId() == TYPEID_PLAYER)
+ {
+ bool allow = ((Player*)this)->isHonorOrXPTarget(pVictim);
+ // Shadow Word: Death - can trigger from every kill
+ if (aura->GetId() == 32409)
+ allow = true;
+ if (!allow)
+ return false;
+ }
+ // Aura added by spell can`t trogger from self (prevent drop charges/do triggers)
// But except periodic triggers (can triggered from self)
if(procSpell && procSpell->Id == spellProto->Id && !(spellProto->procFlags&PROC_FLAG_ON_TAKE_PERIODIC))
return false;
@@ -12528,7 +11719,10 @@ bool Unit::IsTriggeredAtSpellProcEvent(Aura* aura, SpellEntry const* procSpell,
}
// Apply chance modifer aura
if(Player* modOwner = GetSpellModOwner())
+ {
modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance);
+ modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_PROC_CHANCE,chance);
+ }
return roll_chance_f(chance);
}
@@ -12542,10 +11736,10 @@ bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura )
uint64 caster_guid = triggeredByAura->GetCasterGUID();
// jumps
- int32 jumps = triggeredByAura->m_procCharges-1;
+ int32 jumps = triggeredByAura->GetAuraCharges()-1;
// current aura expire
- triggeredByAura->m_procCharges = 1; // will removed at next charges decrease
+ triggeredByAura->SetAuraCharges(1); // will removed at next charges decrease
// next target selection
if(jumps > 0 && GetTypeId()==TYPEID_PLAYER && IS_PLAYER_GUID(caster_guid))
@@ -12568,10 +11762,7 @@ bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura )
mod->value = jumps-5; // negative
mod->type = SPELLMOD_FLAT;
mod->spellId = spellProto->Id;
- mod->effectId = effIdx;
- mod->lastAffected = NULL;
- mod->mask = spellProto->SpellFamilyFlags;
- mod->charges = 0;
+ mod->mask = spellProto->SpellFamilyFlags;
caster->AddSpellMod(mod, true);
CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID());
@@ -12629,7 +11820,7 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
if(player && player!=pVictim)
{
if(player->RewardPlayerAndGroupAtKill(pVictim))
- player->ProcDamageAndSpell(pVictim, PROC_FLAG_KILL_AND_GET_XP, PROC_FLAG_KILLED, PROC_EX_NONE, 0);
+ player->ProcDamageAndSpell(pVictim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_EX_NONE, 0);
else
player->ProcDamageAndSpell(pVictim, PROC_FLAG_NONE, PROC_FLAG_KILLED,PROC_EX_NONE, 0);
}
@@ -12761,6 +11952,15 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
bg->HandleKillUnit((Creature*)pVictim, player);
}
}
+
+ // achievement stuff
+ if ( pVictim->GetTypeId() == TYPEID_PLAYER)
+ {
+ if(GetTypeId() == TYPEID_UNIT)
+ ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry());
+ else if(GetTypeId() == TYPEID_PLAYER)
+ ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1);
+ }
}
void Unit::SetControlled(bool apply, UnitState state)
@@ -12830,7 +12030,7 @@ void Unit::SetStunned(bool apply)
if(apply)
{
SetUInt64Value(UNIT_FIELD_TARGET, 0);
- SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
CastStop();
// Creature specific
@@ -12848,7 +12048,7 @@ void Unit::SetStunned(bool apply)
{
if(isAlive() && getVictim())
SetUInt64Value(UNIT_FIELD_TARGET, getVictim()->GetGUID());
- RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
if(!hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
{
@@ -12983,7 +12183,7 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess)
{
if(((Player*)this)->isAFK())
((Player*)this)->ToggleAFK();
- ((Player*)this)->SetViewport(GetGUID(), false);
+ ((Player*)this)->SetClientControl(this, 0);
}
// Pets already have a properly initialized CharmInfo, don't overwrite it.
@@ -13001,9 +12201,10 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess)
if(possess)
{
addUnitState(UNIT_STAT_POSSESSED);
- SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
AddPlayerToVision((Player*)charmer);
- ((Player*)charmer)->SetViewport(GetGUID(), true);
+ ((Player*)charmer)->SetClientControl(this, 1);
+ ((Player*)charmer)->SetMover(this);
charmer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
}
// Charm demon
@@ -13052,7 +12253,7 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer)
if(possess)
{
clearUnitState(UNIT_STAT_POSSESSED);
- RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
}
if(GetTypeId() == TYPEID_UNIT)
@@ -13073,7 +12274,7 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer)
}
}
else
- ((Player*)this)->SetViewport(GetGUID(), true);
+ ((Player*)this)->SetClientControl(this, 1);
// If charmer still exists
if(!charmer)
@@ -13085,7 +12286,8 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer)
if(possess)
{
RemovePlayerFromVision((Player*)charmer);
- ((Player*)charmer)->SetViewport(charmer->GetGUID(), true);
+ ((Player*)charmer)->SetClientControl(charmer, 1);
+ ((Player*)charmer)->SetMover(charmer);
charmer->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
}
// restore UNIT_FIELD_BYTES_0
@@ -13242,7 +12444,7 @@ void Unit::AddAura(uint32 spellId, Unit* target)
{
if(spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA)
{
- if(target->IsImmunedToSpellEffect(spellInfo->Effect[i], spellInfo->EffectMechanic[i]))
+ if(target->IsImmunedToSpellEffect(spellInfo, i))
continue;
if(spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_CASTER)
@@ -13257,4 +12459,70 @@ void Unit::AddAura(uint32 spellId, Unit* target)
}
}
}
-} \ No newline at end of file
+}
+
+// Melee based spells can be miss, parry or dodge on this step
+// Crit or block - determined on damage calculation phase! (and can be both in some time)
+float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const
+{
+ // Calculate hit chance (more correct for chance mod)
+ int32 HitChance;
+
+ // PvP - PvE melee chances
+ /*int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 5 : 7;
+ int32 leveldif = pVictim->getLevelForTarget(this) - getLevelForTarget(pVictim);
+ if(leveldif < 3)
+ HitChance = 95 - leveldif;
+ else
+ HitChance = 93 - (leveldif - 2) * lchance;*/
+ if (spellId || attType == RANGED_ATTACK || !haveOffhandWeapon())
+ HitChance = 95.0f;
+ else
+ HitChance = 76.0f;
+
+ // Hit chance depends from victim auras
+ if(attType == RANGED_ATTACK)
+ HitChance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE);
+ else
+ HitChance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE);
+
+ // Spellmod from SPELLMOD_RESIST_MISS_CHANCE
+ if(spellId)
+ {
+ if(Player *modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_MISS_CHANCE, HitChance);
+ }
+
+ // Miss = 100 - hit
+ float miss_chance= 100.0f - HitChance;
+
+ // Bonuses from attacker aura and ratings
+ if (attType == RANGED_ATTACK)
+ miss_chance -= m_modRangedHitChance;
+ else
+ miss_chance -= m_modMeleeHitChance;
+
+ // bonus from skills is 0.04%
+ //miss_chance -= skillDiff * 0.04f;
+ int32 diff = -skillDiff;
+ if(pVictim->GetTypeId()==TYPEID_PLAYER)
+ miss_chance += diff > 0 ? diff * 0.04 : diff * 0.02;
+ else
+ miss_chance += diff > 10 ? 2 + (diff - 10) * 0.4 : diff * 0.1;
+
+ // Limit miss chance from 0 to 60%
+ if (miss_chance < 0.0f)
+ return 0.0f;
+ if (miss_chance > 60.0f)
+ return 60.0f;
+ return miss_chance;
+}
+
+void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
+{
+ WorldObject::SetPhaseMask(newPhaseMask,update);
+
+ if(IsInWorld())
+ if(Pet* pet = GetPet())
+ pet->SetPhaseMask(newPhaseMask,true);
+}
diff --git a/src/game/Unit.h b/src/game/Unit.h
index b1ca703007c..aa038ab1fb4 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -45,7 +45,8 @@ enum SpellInterruptFlags
SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back
SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, // interrupt
SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, // no
- SPELL_INTERRUPT_FLAG_DAMAGE = 0x10 // _complete_ interrupt on direct damage?
+ SPELL_INTERRUPT_FLAG_ABORT_ON_DMG = 0x10, // _complete_ interrupt on direct damage
+ //SPELL_INTERRUPT_UNK = 0x20 // unk, 564 of 727 spells having this spell start with "Glyph"
};
enum SpellChannelInterruptFlags
@@ -101,7 +102,7 @@ enum SpellModOp
SPELLMOD_CASTING_TIME = 10,
SPELLMOD_COOLDOWN = 11,
SPELLMOD_EFFECT2 = 12,
- // spellmod 13 unused
+ SPELLMOD_IGNORE_ARMOR = 13,
SPELLMOD_COST = 14,
SPELLMOD_CRIT_DAMAGE_BONUS = 15,
SPELLMOD_RESIST_MISS_CHANCE = 16,
@@ -109,13 +110,16 @@ enum SpellModOp
SPELLMOD_CHANCE_OF_SUCCESS = 18,
SPELLMOD_ACTIVATION_TIME = 19,
SPELLMOD_EFFECT_PAST_FIRST = 20,
- SPELLMOD_CASTING_TIME_OLD = 21,
+ SPELLMOD_GLOBAL_COOLDOWN = 21, //TODO: GCD is not checked by server currently
SPELLMOD_DOT = 22,
SPELLMOD_EFFECT3 = 23,
SPELLMOD_SPELL_BONUS_DAMAGE = 24,
- // spellmod 25, 26 unused
+ // spellmod 25
+ SPELLMOD_PROC_CHANCE = 26,
SPELLMOD_MULTIPLE_VALUE = 27,
- SPELLMOD_RESIST_DISPEL_CHANCE = 28
+ SPELLMOD_RESIST_DISPEL_CHANCE = 28,
+ SPELLMOD_CRIT_DAMAGE_BONUS_2 = 29, //one not used spell
+ SPELLMOD_SPELL_COST_REFUND_ON_FAIL = 30
};
#define MAX_SPELLMOD 32
@@ -129,6 +133,35 @@ enum SpellFacingFlags
#define BASE_MAXDAMAGE 2.0f
#define BASE_ATTACK_TIME 2000
+// byte value (UNIT_FIELD_BYTES_1,0)
+enum UnitStandStateType
+{
+ UNIT_STAND_STATE_STAND = 0,
+ UNIT_STAND_STATE_SIT = 1,
+ UNIT_STAND_STATE_SIT_CHAIR = 2,
+ UNIT_STAND_STATE_SLEEP = 3,
+ UNIT_STAND_STATE_SIT_LOW_CHAIR = 4,
+ UNIT_STAND_STATE_SIT_MEDIUM_CHAIR = 5,
+ UNIT_STAND_STATE_SIT_HIGH_CHAIR = 6,
+ UNIT_STAND_STATE_DEAD = 7,
+ UNIT_STAND_STATE_KNEEL = 8
+};
+
+// byte flag value (UNIT_FIELD_BYTES_1,2)
+enum UnitStandFlags
+{
+ UNIT_STAND_FLAGS_CREEP = 0x02,
+ UNIT_STAND_FLAGS_ALL = 0xFF
+};
+
+// byte flags value (UNIT_FIELD_BYTES_1,3)
+enum UnitBytes1_Flags
+{
+ UNIT_BYTE1_FLAG_ALWAYS_STAND = 0x01,
+ UNIT_BYTE1_FLAG_UNTRACKABLE = 0x04,
+ UNIT_BYTE1_FLAG_ALL = 0xFF
+};
+
// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2
enum ShapeshiftForm
{
@@ -149,6 +182,7 @@ enum ShapeshiftForm
FORM_BERSERKERSTANCE = 0x13,
FORM_TEST = 0x14,
FORM_ZOMBIE = 0x15,
+ FORM_METAMORPHOSIS = 0x16,
FORM_FLIGHT_EPIC = 0x1B,
FORM_SHADOW = 0x1C,
FORM_FLIGHT = 0x1D,
@@ -168,14 +202,14 @@ enum SheathState
// byte (1 from 0..3) of UNIT_FIELD_BYTES_2
enum UnitBytes2_Flags
{
- UNIT_BYTE2_FLAG_UNK0 = 0x01,
- UNIT_BYTE2_FLAG_UNK1 = 0x02,
- UNIT_BYTE2_FLAG_UNK2 = 0x04,
+ UNIT_BYTE2_FLAG_PVP = 0x01,
+ UNIT_BYTE2_FLAG_UNK1 = 0x02,
+ UNIT_BYTE2_FLAG_FFA_PVP = 0x04,
UNIT_BYTE2_FLAG_SANCTUARY = 0x08,
- UNIT_BYTE2_FLAG_AURAS = 0x10, // show possitive auras as positive, and allow its dispel
- UNIT_BYTE2_FLAG_UNK5 = 0x20,
- UNIT_BYTE2_FLAG_UNK6 = 0x40,
- UNIT_BYTE2_FLAG_UNK7 = 0x80
+ UNIT_BYTE2_FLAG_UNK4 = 0x10,
+ UNIT_BYTE2_FLAG_UNK5 = 0x20,
+ UNIT_BYTE2_FLAG_UNK6 = 0x40,
+ UNIT_BYTE2_FLAG_UNK7 = 0x80
};
// byte (2 from 0..3) of UNIT_FIELD_BYTES_2
@@ -213,16 +247,27 @@ enum HitInfo
HITINFO_UNK1 = 0x00000001, // req correct packet structure
HITINFO_NORMALSWING2 = 0x00000002,
HITINFO_LEFTSWING = 0x00000004,
+ HITINFO_UNK2 = 0x00000008,
HITINFO_MISS = 0x00000010,
- HITINFO_ABSORB = 0x00000020, // plays absorb sound
- HITINFO_RESIST = 0x00000040, // resisted at least some damage
- HITINFO_CRITICALHIT = 0x00000080,
- HITINFO_UNK2 = 0x00000100, // wotlk?
- HITINFO_UNK3 = 0x00002000, // wotlk?
- HITINFO_GLANCING = 0x00004000,
- HITINFO_CRUSHING = 0x00008000,
- HITINFO_NOACTION = 0x00010000,
- HITINFO_SWINGNOHITSOUND = 0x00080000
+ HITINFO_ABSORB = 0x00000020, // absorbed damage
+ HITINFO_ABSORB2 = 0x00000040, // absorbed damage
+ HITINFO_RESIST = 0x00000080, // resisted atleast some damage
+ HITINFO_RESIST2 = 0x00000100, // resisted atleast some damage
+ HITINFO_CRITICALHIT = 0x00000200, // critical hit
+ // 0x00000400
+ // 0x00000800
+ // 0x00001000
+ HITINFO_BLOCK = 0x00002000, // blocked damage
+ // 0x00004000
+ // 0x00008000
+ HITINFO_GLANCING = 0x00010000,
+ HITINFO_CRUSHING = 0x00020000,
+ HITINFO_NOACTION = 0x00040000, // guessed
+ // 0x00080000
+ // 0x00100000
+ HITINFO_SWINGNOHITSOUND = 0x00200000, // guessed
+ // 0x00400000
+ HITINFO_UNK3 = 0x00800000
};
//i would like to remove this: (it is defined in item.h
@@ -294,11 +339,13 @@ enum UnitMods
UNIT_MOD_STAT_INTELLECT,
UNIT_MOD_STAT_SPIRIT,
UNIT_MOD_HEALTH,
- UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_HAPPINESS must be in existed order, it's accessed by index values of Powers enum.
+ UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_RUNIC_POWER must be in existed order, it's accessed by index values of Powers enum.
UNIT_MOD_RAGE,
UNIT_MOD_FOCUS,
UNIT_MOD_ENERGY,
UNIT_MOD_HAPPINESS,
+ UNIT_MOD_RUNE,
+ UNIT_MOD_RUNIC_POWER,
UNIT_MOD_ARMOR, // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum.
UNIT_MOD_RESISTANCE_HOLY,
UNIT_MOD_RESISTANCE_FIRE,
@@ -318,7 +365,7 @@ enum UnitMods
UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR,
UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1,
UNIT_MOD_POWER_START = UNIT_MOD_MANA,
- UNIT_MOD_POWER_END = UNIT_MOD_HAPPINESS + 1
+ UNIT_MOD_POWER_END = UNIT_MOD_RUNIC_POWER + 1
};
enum BaseModGroup
@@ -385,9 +432,10 @@ enum UnitMoveType
MOVE_TURN_RATE = 5,
MOVE_FLIGHT = 6,
MOVE_FLIGHT_BACK = 7,
+ MOVE_PITCH_RATE = 8
};
-#define MAX_MOVE_TYPE 8
+#define MAX_MOVE_TYPE 9
extern float baseMoveSpeed[MAX_MOVE_TYPE];
// assume it is 25 yard per 0.6 second
@@ -397,11 +445,10 @@ enum WeaponAttackType
{
BASE_ATTACK = 0,
OFF_ATTACK = 1,
- RANGED_ATTACK = 2
+ RANGED_ATTACK = 2,
+ MAX_ATTACK
};
-#define MAX_ATTACK 3
-
enum CombatRating
{
CR_WEAPON_SKILL = 0,
@@ -427,10 +474,11 @@ enum CombatRating
CR_WEAPON_SKILL_MAINHAND = 20,
CR_WEAPON_SKILL_OFFHAND = 21,
CR_WEAPON_SKILL_RANGED = 22,
- CR_EXPERTISE = 23
+ CR_EXPERTISE = 23,
+ CR_ARMOR_PENETRATION = 24
};
-#define MAX_COMBAT_RATING 24
+#define MAX_COMBAT_RATING 25
enum DamageEffectType
{
@@ -455,45 +503,48 @@ enum UnitVisibility
// Value masks for UNIT_FIELD_FLAGS
enum UnitFlags
{
- UNIT_FLAG_UNKNOWN7 = 0x00000001,
+ UNIT_FLAG_UNK_0 = 0x00000001,
UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable
UNIT_FLAG_DISABLE_MOVE = 0x00000004,
UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state
UNIT_FLAG_RENAME = 0x00000010,
UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP
- UNIT_FLAG_UNKNOWN9 = 0x00000040,
+ UNIT_FLAG_UNK_6 = 0x00000040,
UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE
UNIT_FLAG_NOT_ATTACKABLE_2 = 0x00000100, // 2.0.8
- UNIT_FLAG_UNKNOWN11 = 0x00000200,
+ UNIT_FLAG_UNK_9 = 0x00000200, // 3.0.3 - makes you unable to attack everything
UNIT_FLAG_LOOTING = 0x00000400, // loot animation
UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8
- UNIT_FLAG_PVP = 0x00001000,
+ UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3
UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1
- UNIT_FLAG_UNKNOWN4 = 0x00004000, // 2.0.8
- UNIT_FLAG_UNKNOWN13 = 0x00008000,
- UNIT_FLAG_UNKNOWN14 = 0x00010000,
- UNIT_FLAG_PACIFIED = 0x00020000,
- UNIT_FLAG_DISABLE_ROTATE = 0x00040000, // stunned, 2.1.1
+ UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8
+ UNIT_FLAG_UNK_15 = 0x00008000,
+ UNIT_FLAG_UNK_16 = 0x00010000,
+ UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok
+ UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok
UNIT_FLAG_IN_COMBAT = 0x00080000,
UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag
- UNIT_FLAG_DISARMED = 0x00200000, // disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
+ UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
UNIT_FLAG_CONFUSED = 0x00400000,
UNIT_FLAG_FLEEING = 0x00800000,
- UNIT_FLAG_UNKNOWN5 = 0x01000000, // used in spell Eyes of the Beast for pet...
+ UNIT_FLAG_UNK_24 = 0x01000000, // used in spell Eyes of the Beast for pet...
UNIT_FLAG_NOT_SELECTABLE = 0x02000000,
UNIT_FLAG_SKINNABLE = 0x04000000,
UNIT_FLAG_MOUNT = 0x08000000,
- UNIT_FLAG_UNKNOWN17 = 0x10000000,
- UNIT_FLAG_UNKNOWN6 = 0x20000000, // used in Feing Death spell
- UNIT_FLAG_SHEATHE = 0x40000000
+ UNIT_FLAG_UNK_28 = 0x10000000,
+ UNIT_FLAG_UNK_29 = 0x20000000, // used in Feing Death spell
+ UNIT_FLAG_SHEATHE = 0x40000000,
+ UNIT_FLAG_UNK_31 = 0x80000000
};
// Value masks for UNIT_FIELD_FLAGS_2
enum UnitFlags2
{
- UNIT_FLAG2_FEIGN_DEATH = 0x00000001,
- UNIT_FLAG2_COMPREHEND_LANG= 0x00000008,
- UNIT_FLAG2_FORCE_MOVE = 0x00000040
+ UNIT_FLAG2_FEIGN_DEATH = 0x00000001,
+ UNIT_FLAG2_UNK1 = 0x00000002, // Hide unit model (show only player equip)
+ UNIT_FLAG2_COMPREHEND_LANG = 0x00000008,
+ UNIT_FLAG2_FORCE_MOVE = 0x00000040,
+ UNIT_FLAG2_REGENERATE_POWER = 0x00000800
};
/// Non Player Character flags
@@ -581,8 +632,9 @@ struct DiminishingReturn
enum MeleeHitOutcome
{
MELEE_HIT_EVADE, MELEE_HIT_MISS, MELEE_HIT_DODGE, MELEE_HIT_BLOCK, MELEE_HIT_PARRY,
- MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL, MELEE_HIT_BLOCK_CRIT
+ MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL
};
+
struct CleanDamage
{
CleanDamage(uint32 _damage, WeaponAttackType _attackType, MeleeHitOutcome _hitOutCome) :
@@ -639,8 +691,20 @@ uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missC
struct UnitActionBarEntry
{
- uint32 Type;
- uint32 SpellOrAction;
+ UnitActionBarEntry() : Raw(0) {}
+
+ union
+ {
+ struct
+ {
+ uint16 SpellOrAction;
+ uint16 Type;
+ };
+ struct
+ {
+ uint32 Raw;
+ };
+ };
};
#define MAX_DECLINED_NAME_CASES 5
@@ -662,13 +726,12 @@ enum CurrentSpellTypes
enum ActiveStates
{
- ACT_ENABLED = 0xC100,
- ACT_DISABLED = 0x8100,
- ACT_COMMAND = 0x0700,
- ACT_REACTION = 0x0600,
- ACT_CAST = 0x0100,
- ACT_PASSIVE = 0x0000,
- ACT_DECIDE = 0x0001
+ ACT_PASSIVE = 0x0100, // 0x0100 - passive
+ ACT_DISABLED = 0x8100, // 0x8000 - castable
+ ACT_ENABLED = 0xC100, // 0x4000 | 0x8000 - auto cast + castable
+ ACT_COMMAND = 0x0700, // 0x0100 | 0x0200 | 0x0400
+ ACT_REACTION = 0x0600, // 0x0200 | 0x0400
+ ACT_DECIDE = 0x0001 // what is it?
};
enum ReactStates
@@ -733,14 +796,12 @@ struct TRINITY_DLL_SPEC CharmInfo
enum ReactiveType
{
- REACTIVE_DEFENSE = 1,
- REACTIVE_HUNTER_PARRY = 2,
- REACTIVE_CRIT = 3,
- REACTIVE_HUNTER_CRIT = 4,
- REACTIVE_OVERPOWER = 5
+ REACTIVE_DEFENSE = 0,
+ REACTIVE_HUNTER_PARRY = 1,
+ REACTIVE_OVERPOWER = 2
};
-#define MAX_REACTIVE 6
+#define MAX_REACTIVE 3
#define MAX_TOTEM 4
// delay time next attack to prevent client attack animation problems
@@ -756,8 +817,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
typedef std::multimap< spellEffectPair, Aura*> AuraMap;
typedef std::list<Aura *> AuraList;
typedef std::list<DiminishingReturn> Diminishing;
- typedef std::set<AuraType> AuraTypeSet;
typedef std::set<uint32> ComboPointHolderSet;
+ typedef std::map<uint8, uint32> VisibleAuraMap;
virtual ~Unit ( );
@@ -797,9 +858,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
}
void _removeAttacker(Unit *pAttacker) // must be called only from Unit::AttackStop()
{
- AttackerSet::iterator itr = m_attackers.find(pAttacker);
- if(itr != m_attackers.end())
- m_attackers.erase(itr);
+ m_attackers.erase(pAttacker);
}
Unit * getAttackerForHelper() // If someone wants to help, who to give them
{
@@ -821,6 +880,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void CombatStop(bool cast = false);
void CombatStopWithPets(bool cast = false);
Unit* SelectNearbyTarget(float dist = NOMINAL_MELEE_RANGE) const;
+ bool hasNegativeAuraWithInterruptFlag(uint32 flag);
void addUnitState(uint32 f) { m_state |= f; }
bool hasUnitState(const uint32 f) const { return (m_state & f); }
@@ -888,8 +948,14 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
return false;
}
- bool IsPvP() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); }
- void SetPvP(bool state) { if(state) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); else RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); }
+ bool IsPvP() const { return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); }
+ void SetPvP(bool state)
+ {
+ if(state)
+ SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
+ else
+ RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
+ }
uint32 GetCreatureType() const;
uint32 GetCreatureTypeMask() const
{
@@ -902,6 +968,9 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
bool IsStandState() const;
void SetStandState(uint8 state);
+ void SetStandFlags(uint8 flags) { SetByteFlag(UNIT_FIELD_BYTES_1, 2,flags); }
+ void RemoveStandFlags(uint8 flags) { RemoveByteFlag(UNIT_FIELD_BYTES_1, 2,flags); }
+
bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); }
uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
void Mount(uint32 mount);
@@ -924,6 +993,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss);
void CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType = BASE_ATTACK);
+ int32 GetIgnoredArmorMultiplier(SpellEntry const *spellInfo, WeaponAttackType attackType);
void DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss);
float MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const;
@@ -944,7 +1014,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
float GetPPMProcChance(uint32 WeaponSpeed, float PPM) const;
MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType) const;
- MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted ) const;
+ MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const;
bool isVendor() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR ); }
bool isTrainer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER ); }
@@ -984,7 +1054,10 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
bool HasAuraType(AuraType auraType) const;
bool HasAura(uint32 spellId, uint32 effIndex) const
- { return m_Auras.find(spellEffectPair(spellId, effIndex)) != m_Auras.end(); }
+ {
+ return m_Auras.find(spellEffectPair(spellId, effIndex)) != m_Auras.end();
+ }
+ bool HasAura(uint32 spellId) const;
bool virtual HasSpell(uint32 /*spellID*/) const { return false; }
@@ -1104,11 +1177,11 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL);
- void RemoveSingleAuraFromStackByDispel(uint32 spellId);
- void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex);
+ void RemoveSingleSpellAurasFromStack(uint32 spellId);
+ void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex);
void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL);
void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId);
- void RemoveAurasDueToCasterSpell(uint32 spellId, uint64 guid);
+ void RemoveAurasByCasterSpell(uint32 spellId, uint64 casterGUID);
void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler);
void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer);
void RemoveAurasDueToSpellByCancel(uint32 spellId);
@@ -1224,13 +1297,13 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false, bool is3dDistance = true) const;
bool canDetectInvisibilityOf(Unit const* u) const;
bool canDetectStealthOf(Unit const* u, float distance) const;
+ void SetPhaseMask(uint32 newPhaseMask, bool update);// overwrite WorldObject::SetPhaseMask
// virtual functions for all world objects types
bool isVisibleForInState(Player const* u, bool inVisibleList) const;
// function for low level grid visibility checks in player/creature cases
virtual bool IsVisibleInGridForPlayer(Player const* pl) const = 0;
- bool waterbreath;
AuraList & GetSingleCastAuras() { return m_scAuras; }
AuraList const& GetSingleCastAuras() const { return m_scAuras; }
SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
@@ -1247,7 +1320,26 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void removeHatedBy(HostilReference* /*pHostilReference*/ ) { /* nothing to do yet */ }
HostilRefManager& getHostilRefManager() { return m_HostilRefManager; }
+ 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)
+ m_visibleAuras.erase(slot);
+ else
+ m_visibleAuras[slot] = spellid;
+ }
+ VisibleAuraMap const *GetVisibleAuras() { return &m_visibleAuras; }
+ uint8 GetVisibleAurasCount() { return m_visibleAuras.size(); }
+
Aura* GetAura(uint32 spellId, uint32 effindex);
+ Aura* GetAura(AuraType type, uint32 family, uint32 familyFlag1 = 0, uint32 familyFlag2 = 0, uint32 familyFlag3 = 0, uint64 casterGUID = 0);
+
AuraMap & GetAuras() { return m_Auras; }
AuraMap const& GetAuras() const { return m_Auras; }
AuraList const& GetAurasByType(AuraType type) const { return m_modAuras[type]; }
@@ -1298,11 +1390,12 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask);
int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim);
int32 SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim);
- uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 damage, DamageEffectType damagetype);
- uint32 SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim);
+ uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 damage, DamageEffectType damagetype, uint32 stack = 1);
+ uint32 SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1);
bool isSpellBlocked(Unit *pVictim, SpellEntry const *spellProto, WeaponAttackType attackType = BASE_ATTACK);
bool isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK);
- uint32 SpellCriticalBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim);
+ uint32 SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim);
+ uint32 SpellCriticalHealingBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim);
void SetLastManaUse(uint32 spellCastTime) { m_lastManaUse = spellCastTime; }
bool IsUnderLastManaUseEffect() const;
@@ -1314,13 +1407,13 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply);
void ApplySpellDispelImmunity(const SpellEntry * spellProto, DispelType type, bool apply);
- virtual bool IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges = false);
+ virtual bool IsImmunedToSpell(SpellEntry const* spellInfo);
// redefined in Creature
- bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask, bool useCharges = false);
- virtual bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const;
+ bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask);
+ virtual bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const;
// redefined in Creature
- uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage);
+ uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType=MAX_ATTACK);
void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist);
void UpdateSpeed(UnitMoveType mtype, bool forced);
@@ -1438,6 +1531,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
float m_weaponDamage[MAX_ATTACK][2];
bool m_canModifyStats;
//std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem
+ VisibleAuraMap m_visibleAuras;
float m_speed_rate[MAX_MOVE_TYPE];
@@ -1450,17 +1544,18 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
uint32 m_unit_movement_flags;
uint32 m_reactiveTimer[MAX_REACTIVE];
+ uint32 m_regenTimer;
ThreatManager m_ThreatManager;
private:
void SendAttackStop(Unit* victim); // only from AttackStop(Unit*)
//void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*)
- bool IsTriggeredAtSpellProcEvent( Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent );
+ bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent );
bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
- bool HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura* triggredByAura, SpellEntry const *procSpell, uint32 cooldown);
+ bool HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 cooldown);
bool HandleMeandingAuraProc(Aura* triggeredByAura);
uint32 m_state; // Even derived shouldn't modify
diff --git a/src/game/UpdateData.cpp b/src/game/UpdateData.cpp
index 2b6282997e8..ce50a326917 100644
--- a/src/game/UpdateData.cpp
+++ b/src/game/UpdateData.cpp
@@ -108,7 +108,7 @@ bool UpdateData::BuildPacket(WorldPacket *packet, bool hasTransport)
ByteBuffer buf(m_data.size() + 10 + m_outOfRangeGUIDs.size()*8);
buf << (uint32) (!m_outOfRangeGUIDs.empty() ? m_blockCount + 1 : m_blockCount);
- buf << (uint8) (hasTransport ? 1 : 0);
+ //buf << (uint8) (hasTransport ? 1 : 0);
if(!m_outOfRangeGUIDs.empty())
{
diff --git a/src/game/UpdateData.h b/src/game/UpdateData.h
index 8fdcac4b400..48c7fc35efc 100644
--- a/src/game/UpdateData.h
+++ b/src/game/UpdateData.h
@@ -38,11 +38,12 @@ enum OBJECT_UPDATE_FLAGS
UPDATEFLAG_NONE = 0x00,
UPDATEFLAG_SELF = 0x01,
UPDATEFLAG_TRANSPORT = 0x02,
- UPDATEFLAG_FULLGUID = 0x04,
+ UPDATEFLAG_HAS_TARGET = 0x04,
UPDATEFLAG_LOWGUID = 0x08,
UPDATEFLAG_HIGHGUID = 0x10,
UPDATEFLAG_LIVING = 0x20,
- UPDATEFLAG_HASPOSITION = 0x40
+ UPDATEFLAG_HAS_POSITION = 0x40,
+ UPDATEFLAG_VEHICLE = 0x80
};
class UpdateData
diff --git a/src/game/UpdateFields.h b/src/game/UpdateFields.h
index db64e0bc1dd..3810cb83429 100644
--- a/src/game/UpdateFields.h
+++ b/src/game/UpdateFields.h
@@ -21,7 +21,7 @@
#ifndef _UPDATEFIELDS_AUTO_H
#define _UPDATEFIELDS_AUTO_H
-// Auto generated for version 2, 4, 3, 8606
+// Auto generated for version 3, 0, 3, 9183
enum EObjectFields
{
@@ -43,13 +43,37 @@ enum EItemFields
ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2
ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER_ONLY, UNK2
ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ENCHANTMENT = OBJECT_END + 0x0010, // Size: 33, Type: INT, Flags: PUBLIC
- ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0031, // Size: 1, Type: INT, Flags: PUBLIC
- ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0032, // Size: 1, Type: INT, Flags: PUBLIC
- ITEM_FIELD_ITEM_TEXT_ID = OBJECT_END + 0x0033, // Size: 1, Type: INT, Flags: OWNER_ONLY
- ITEM_FIELD_DURABILITY = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2
- ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2
- ITEM_END = OBJECT_END + 0x0036,
+ ITEM_FIELD_ENCHANTMENT_1_1 = OBJECT_END + 0x0010, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_1_3 = OBJECT_END + 0x0012, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_2_1 = OBJECT_END + 0x0013, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_2_3 = OBJECT_END + 0x0015, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_3_1 = OBJECT_END + 0x0016, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_3_3 = OBJECT_END + 0x0018, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_4_1 = OBJECT_END + 0x0019, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_4_3 = OBJECT_END + 0x001B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_5_1 = OBJECT_END + 0x001C, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_5_3 = OBJECT_END + 0x001E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_6_1 = OBJECT_END + 0x001F, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_6_3 = OBJECT_END + 0x0021, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_7_1 = OBJECT_END + 0x0022, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_7_3 = OBJECT_END + 0x0024, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_8_1 = OBJECT_END + 0x0025, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_8_3 = OBJECT_END + 0x0027, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_9_1 = OBJECT_END + 0x0028, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_9_3 = OBJECT_END + 0x002A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_10_1 = OBJECT_END + 0x002B, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_10_3 = OBJECT_END + 0x002D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_11_1 = OBJECT_END + 0x002E, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_11_3 = OBJECT_END + 0x0030, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_12_1 = OBJECT_END + 0x0031, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_12_3 = OBJECT_END + 0x0033, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ITEM_TEXT_ID = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: OWNER_ONLY
+ ITEM_FIELD_DURABILITY = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2
+ ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0038, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2
+ ITEM_FIELD_PAD = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: NONE
+ ITEM_END = OBJECT_END + 0x003A,
};
enum EContainerFields
@@ -64,93 +88,94 @@ enum EUnitFields
{
UNIT_FIELD_CHARM = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_SUMMON = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_CREATEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_TARGET = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_PERSUADED = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_FIELD_CRITTER = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PRIVATE
+ UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_FIELD_CREATEDBY = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC
+ UNIT_FIELD_TARGET = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0x000E, // Size: 2, Type: LONG, Flags: PUBLIC
- UNIT_FIELD_HEALTH = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: DYNAMIC
- UNIT_FIELD_POWER1 = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER2 = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER3 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER4 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER5 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: DYNAMIC
- UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_LEVEL = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_BYTES_0 = OBJECT_END + 0x001E, // Size: 1, Type: BYTES, Flags: PUBLIC
- UNIT_VIRTUAL_ITEM_SLOT_DISPLAY = OBJECT_END + 0x001F, // Size: 3, Type: INT, Flags: PUBLIC
- UNIT_VIRTUAL_ITEM_INFO = OBJECT_END + 0x0022, // Size: 6, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_FLAGS = OBJECT_END + 0x0028, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0029, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_AURA = OBJECT_END + 0x002A, // Size: 56, Type: INT, Flags: PUBLIC
- UNIT_FIELD_AURAFLAGS = OBJECT_END + 0x0062, // Size: 14, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_AURALEVELS = OBJECT_END + 0x0070, // Size: 14, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_AURAAPPLICATIONS = OBJECT_END + 0x007E, // Size: 14, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_AURASTATE = OBJECT_END + 0x008C, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x008D, // Size: 2, Type: INT, Flags: PUBLIC
- UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x008F, // Size: 1, Type: INT, Flags: PRIVATE
- UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x0090, // Size: 1, Type: FLOAT, Flags: PUBLIC
- UNIT_FIELD_COMBATREACH = OBJECT_END + 0x0091, // Size: 1, Type: FLOAT, Flags: PUBLIC
- UNIT_FIELD_DISPLAYID = OBJECT_END + 0x0092, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x0093, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x0094, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0095, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
- UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0096, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
- UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0097, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
- UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0098, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
- UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0099, // Size: 1, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_PETNUMBER = OBJECT_END + 0x009A, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x009B, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x009C, // Size: 1, Type: INT, Flags: OWNER_ONLY
- UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x009D, // Size: 1, Type: INT, Flags: OWNER_ONLY
- UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x009E, // Size: 1, Type: INT, Flags: DYNAMIC
- UNIT_CHANNEL_SPELL = OBJECT_END + 0x009F, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_MOD_CAST_SPEED = OBJECT_END + 0x00A0, // Size: 1, Type: FLOAT, Flags: PUBLIC
- UNIT_CREATED_BY_SPELL = OBJECT_END + 0x00A1, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_NPC_FLAGS = OBJECT_END + 0x00A2, // Size: 1, Type: INT, Flags: DYNAMIC
- UNIT_NPC_EMOTESTATE = OBJECT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_TRAINING_POINTS = OBJECT_END + 0x00A4, // Size: 1, Type: TWO_SHORT, Flags: OWNER_ONLY
- UNIT_FIELD_STAT0 = OBJECT_END + 0x00A5, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_STAT1 = OBJECT_END + 0x00A6, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_STAT2 = OBJECT_END + 0x00A7, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_STAT3 = OBJECT_END + 0x00A8, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_STAT4 = OBJECT_END + 0x00A9, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x00AA, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x00AB, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x00AC, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x00AD, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x00AE, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x00AF, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x00B0, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x00B1, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x00B2, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x00B3, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_RESISTANCES = OBJECT_END + 0x00B4, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
- UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x00BB, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x00C2, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_BASE_MANA = OBJECT_END + 0x00C9, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x00CA, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_BYTES_2 = OBJECT_END + 0x00CB, // Size: 1, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x00CC, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x00CD, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x00CE, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x00CF, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x00D0, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x00D1, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x00D2, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x00D3, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x00D4, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x00DB, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x00E2, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
- UNIT_FIELD_PADDING = OBJECT_END + 0x00E3, // Size: 1, Type: INT, Flags: NONE
- UNIT_END = OBJECT_END + 0x00E4,
+ UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0010, // Size: 1, Type: BYTES, Flags: PUBLIC
+ UNIT_FIELD_HEALTH = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER1 = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER2 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER3 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER4 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER5 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER6 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER7 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001E, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER6 = OBJECT_END + 0x001F, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER7 = OBJECT_END + 0x0020, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x0021, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0028, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_LEVEL = OBJECT_END + 0x002F, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0030, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x0031, // Size: 3, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_FLAGS = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_AURASTATE = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0037, // Size: 2, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: PRIVATE
+ UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x003A, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_FIELD_COMBATREACH = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_FIELD_DISPLAYID = OBJECT_END + 0x003C, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x003F, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
+ UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0040, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
+ UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0041, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
+ UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
+ UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0043, // Size: 1, Type: BYTES, Flags: PUBLIC
+ UNIT_FIELD_PETNUMBER = OBJECT_END + 0x0044, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: OWNER_ONLY
+ UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: OWNER_ONLY
+ UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: DYNAMIC
+ UNIT_CHANNEL_SPELL = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_MOD_CAST_SPEED = OBJECT_END + 0x004A, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_CREATED_BY_SPELL = OBJECT_END + 0x004B, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_NPC_FLAGS = OBJECT_END + 0x004C, // Size: 1, Type: INT, Flags: DYNAMIC
+ UNIT_NPC_EMOTESTATE = OBJECT_END + 0x004D, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_STAT0 = OBJECT_END + 0x004E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_STAT1 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_STAT2 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_STAT3 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_STAT4 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0057, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0058, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x005A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x005C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_RESISTANCES = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
+ UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x006B, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_BASE_MANA = OBJECT_END + 0x0072, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x0073, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_BYTES_2 = OBJECT_END + 0x0074, // Size: 1, Type: BYTES, Flags: PUBLIC
+ UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x0075, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x0076, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0078, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x0079, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x007A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x007B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x007C, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x007D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x0084, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x008B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
+ UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x008C, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_FIELD_PADDING = OBJECT_END + 0x008D, // Size: 1, Type: INT, Flags: NONE
+ UNIT_END = OBJECT_END + 0x008E,
PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
@@ -262,160 +287,184 @@ enum EUnitFields
PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x006C, // Size: 1, Type: BYTES, Flags: PRIVATE
PLAYER_QUEST_LOG_25_4 = UNIT_END + 0x006D, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_VISIBLE_ITEM_1_CREATOR = UNIT_END + 0x006E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_1_0 = UNIT_END + 0x0070, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_1_PROPERTIES = UNIT_END + 0x007C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_1_PAD = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_2_CREATOR = UNIT_END + 0x007E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_2_0 = UNIT_END + 0x0080, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_2_PROPERTIES = UNIT_END + 0x008C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_2_PAD = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_3_CREATOR = UNIT_END + 0x008E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_3_0 = UNIT_END + 0x0090, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_3_PROPERTIES = UNIT_END + 0x009C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_3_PAD = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_4_CREATOR = UNIT_END + 0x009E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_4_0 = UNIT_END + 0x00A0, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_4_PROPERTIES = UNIT_END + 0x00AC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_4_PAD = UNIT_END + 0x00AD, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_5_CREATOR = UNIT_END + 0x00AE, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_5_0 = UNIT_END + 0x00B0, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_5_PROPERTIES = UNIT_END + 0x00BC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_5_PAD = UNIT_END + 0x00BD, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_6_CREATOR = UNIT_END + 0x00BE, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_6_0 = UNIT_END + 0x00C0, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_6_PROPERTIES = UNIT_END + 0x00CC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_6_PAD = UNIT_END + 0x00CD, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_7_CREATOR = UNIT_END + 0x00CE, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_7_0 = UNIT_END + 0x00D0, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_7_PROPERTIES = UNIT_END + 0x00DC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_7_PAD = UNIT_END + 0x00DD, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_8_CREATOR = UNIT_END + 0x00DE, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_8_0 = UNIT_END + 0x00E0, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_8_PROPERTIES = UNIT_END + 0x00EC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_8_PAD = UNIT_END + 0x00ED, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_9_CREATOR = UNIT_END + 0x00EE, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_9_0 = UNIT_END + 0x00F0, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_9_PROPERTIES = UNIT_END + 0x00FC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_9_PAD = UNIT_END + 0x00FD, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_10_CREATOR = UNIT_END + 0x00FE, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_10_0 = UNIT_END + 0x0100, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_10_PROPERTIES = UNIT_END + 0x010C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_10_PAD = UNIT_END + 0x010D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_11_CREATOR = UNIT_END + 0x010E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_11_0 = UNIT_END + 0x0110, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_11_PROPERTIES = UNIT_END + 0x011C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_11_PAD = UNIT_END + 0x011D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_12_CREATOR = UNIT_END + 0x011E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_12_0 = UNIT_END + 0x0120, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_12_PROPERTIES = UNIT_END + 0x012C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_12_PAD = UNIT_END + 0x012D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_13_CREATOR = UNIT_END + 0x012E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_13_0 = UNIT_END + 0x0130, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_13_PROPERTIES = UNIT_END + 0x013C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_13_PAD = UNIT_END + 0x013D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_14_CREATOR = UNIT_END + 0x013E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_14_0 = UNIT_END + 0x0140, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_14_PROPERTIES = UNIT_END + 0x014C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_14_PAD = UNIT_END + 0x014D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_15_CREATOR = UNIT_END + 0x014E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_15_0 = UNIT_END + 0x0150, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_15_PROPERTIES = UNIT_END + 0x015C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_15_PAD = UNIT_END + 0x015D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_16_CREATOR = UNIT_END + 0x015E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_16_0 = UNIT_END + 0x0160, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_16_PROPERTIES = UNIT_END + 0x016C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_16_PAD = UNIT_END + 0x016D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_17_CREATOR = UNIT_END + 0x016E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_17_0 = UNIT_END + 0x0170, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_17_PROPERTIES = UNIT_END + 0x017C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_17_PAD = UNIT_END + 0x017D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_18_CREATOR = UNIT_END + 0x017E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_18_0 = UNIT_END + 0x0180, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_18_PROPERTIES = UNIT_END + 0x018C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_18_PAD = UNIT_END + 0x018D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_19_CREATOR = UNIT_END + 0x018E, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_19_0 = UNIT_END + 0x0190, // Size: 12, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_19_PROPERTIES = UNIT_END + 0x019C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_19_PAD = UNIT_END + 0x019D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_CHOSEN_TITLE = UNIT_END + 0x019E, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_FIELD_PAD_0 = UNIT_END + 0x019F, // Size: 1, Type: INT, Flags: NONE
- PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x01A0, // Size: 46, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x01CE, // Size: 32, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x01EE, // Size: 56, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x0226, // Size: 14, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x0234, // Size: 24, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x024C, // Size: 64, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_VANITYPET_SLOT_1 = UNIT_END + 0x028C, // Size: 36, Type: LONG, Flags: PRIVATE
- PLAYER_FARSIGHT = UNIT_END + 0x02B0, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x02B2, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER_XP = UNIT_END + 0x02B4, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x02B5, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x02B6, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x0436, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_TRACK_CREATURES = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_TRACK_RESOURCES = UNIT_END + 0x0439, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x043A, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x043B, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x043C, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_EXPERTISE = UNIT_END + 0x043D, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x043E, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x043F, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x0440, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0441, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0442, // Size: 7, Type: FLOAT, Flags: PRIVATE
- PLAYER_SHIELD_BLOCK = UNIT_END + 0x0449, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x044A, // Size: 128, Type: BYTES, Flags: PRIVATE
- PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x04CA, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_COINAGE = UNIT_END + 0x04CB, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x04CC, // Size: 7, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x04D3, // Size: 7, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x04DA, // Size: 7, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x04E1, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x04E2, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x04E3, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BYTES = UNIT_END + 0x04E4, // Size: 1, Type: BYTES, Flags: PRIVATE
- PLAYER_AMMO_ID = UNIT_END + 0x04E5, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_SELF_RES_SPELL = UNIT_END + 0x04E6, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x04E7, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x04E8, // Size: 12, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x04F4, // Size: 12, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_KILLS = UNIT_END + 0x0500, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x0501, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x0502, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_LIFETIME_HONORBALE_KILLS = UNIT_END + 0x0503, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BYTES2 = UNIT_END + 0x0504, // Size: 1, Type: BYTES, Flags: PRIVATE
- PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x0505, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x0506, // Size: 24, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x051E, // Size: 18, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x0530, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x0531, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_MANA_REGEN = UNIT_END + 0x0532, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT = UNIT_END + 0x0533, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x0534, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x0535, // Size: 25, Type: INT, Flags: PRIVATE
- PLAYER_END = UNIT_END + 0x054E,
+ PLAYER_VISIBLE_ITEM_1_0 = UNIT_END + 0x0070, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_1_PROPERTIES = UNIT_END + 0x007D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_1_SEED = UNIT_END + 0x007E, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_1_PAD = UNIT_END + 0x007F, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_2_CREATOR = UNIT_END + 0x0080, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_2_0 = UNIT_END + 0x0082, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_2_PROPERTIES = UNIT_END + 0x008F, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_2_SEED = UNIT_END + 0x0090, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_2_PAD = UNIT_END + 0x0091, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_3_CREATOR = UNIT_END + 0x0092, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_3_0 = UNIT_END + 0x0094, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_3_PROPERTIES = UNIT_END + 0x00A1, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_3_SEED = UNIT_END + 0x00A2, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_3_PAD = UNIT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_4_CREATOR = UNIT_END + 0x00A4, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_4_0 = UNIT_END + 0x00A6, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_4_PROPERTIES = UNIT_END + 0x00B3, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_4_SEED = UNIT_END + 0x00B4, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_4_PAD = UNIT_END + 0x00B5, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_5_CREATOR = UNIT_END + 0x00B6, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_5_0 = UNIT_END + 0x00B8, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_5_PROPERTIES = UNIT_END + 0x00C5, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_5_SEED = UNIT_END + 0x00C6, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_5_PAD = UNIT_END + 0x00C7, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_6_CREATOR = UNIT_END + 0x00C8, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_6_0 = UNIT_END + 0x00CA, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_6_PROPERTIES = UNIT_END + 0x00D7, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_6_SEED = UNIT_END + 0x00D8, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_6_PAD = UNIT_END + 0x00D9, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_7_CREATOR = UNIT_END + 0x00DA, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_7_0 = UNIT_END + 0x00DC, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_7_PROPERTIES = UNIT_END + 0x00E9, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_7_SEED = UNIT_END + 0x00EA, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_7_PAD = UNIT_END + 0x00EB, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_8_CREATOR = UNIT_END + 0x00EC, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_8_0 = UNIT_END + 0x00EE, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_8_PROPERTIES = UNIT_END + 0x00FB, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_8_SEED = UNIT_END + 0x00FC, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_8_PAD = UNIT_END + 0x00FD, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_9_CREATOR = UNIT_END + 0x00FE, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_9_0 = UNIT_END + 0x0100, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_9_PROPERTIES = UNIT_END + 0x010D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_9_SEED = UNIT_END + 0x010E, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_9_PAD = UNIT_END + 0x010F, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_10_CREATOR = UNIT_END + 0x0110, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_10_0 = UNIT_END + 0x0112, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_10_PROPERTIES = UNIT_END + 0x011F, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_10_SEED = UNIT_END + 0x0120, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_10_PAD = UNIT_END + 0x0121, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_11_CREATOR = UNIT_END + 0x0122, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_11_0 = UNIT_END + 0x0124, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_11_PROPERTIES = UNIT_END + 0x0131, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_11_SEED = UNIT_END + 0x0132, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_11_PAD = UNIT_END + 0x0133, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_12_CREATOR = UNIT_END + 0x0134, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_12_0 = UNIT_END + 0x0136, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_12_PROPERTIES = UNIT_END + 0x0143, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_12_SEED = UNIT_END + 0x0144, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_12_PAD = UNIT_END + 0x0145, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_13_CREATOR = UNIT_END + 0x0146, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_13_0 = UNIT_END + 0x0148, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_13_PROPERTIES = UNIT_END + 0x0155, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_13_SEED = UNIT_END + 0x0156, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_13_PAD = UNIT_END + 0x0157, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_14_CREATOR = UNIT_END + 0x0158, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_14_0 = UNIT_END + 0x015A, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_14_PROPERTIES = UNIT_END + 0x0167, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_14_SEED = UNIT_END + 0x0168, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_14_PAD = UNIT_END + 0x0169, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_15_CREATOR = UNIT_END + 0x016A, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_15_0 = UNIT_END + 0x016C, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_15_PROPERTIES = UNIT_END + 0x0179, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_15_SEED = UNIT_END + 0x017A, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_15_PAD = UNIT_END + 0x017B, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_16_CREATOR = UNIT_END + 0x017C, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_16_0 = UNIT_END + 0x017E, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_16_PROPERTIES = UNIT_END + 0x018B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_16_SEED = UNIT_END + 0x018C, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_16_PAD = UNIT_END + 0x018D, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_17_CREATOR = UNIT_END + 0x018E, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_17_0 = UNIT_END + 0x0190, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_17_PROPERTIES = UNIT_END + 0x019D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_17_SEED = UNIT_END + 0x019E, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_17_PAD = UNIT_END + 0x019F, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_18_CREATOR = UNIT_END + 0x01A0, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_18_0 = UNIT_END + 0x01A2, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_18_PROPERTIES = UNIT_END + 0x01AF, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_18_SEED = UNIT_END + 0x01B0, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_18_PAD = UNIT_END + 0x01B1, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_19_CREATOR = UNIT_END + 0x01B2, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_19_0 = UNIT_END + 0x01B4, // Size: 13, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_19_PROPERTIES = UNIT_END + 0x01C1, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_19_SEED = UNIT_END + 0x01C2, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_19_PAD = UNIT_END + 0x01C3, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_CHOSEN_TITLE = UNIT_END + 0x01C4, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_FIELD_PAD_0 = UNIT_END + 0x01C5, // Size: 1, Type: INT, Flags: NONE
+ PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x01C6, // Size: 46, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x01F4, // Size: 32, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x0214, // Size: 56, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x024C, // Size: 14, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x025A, // Size: 24, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x0272, // Size: 64, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_VANITYPET_SLOT_1 = UNIT_END + 0x02B2, // Size: 36, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_CURRENCYTOKEN_SLOT_1 = UNIT_END + 0x02D6, // Size: 64, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_QUESTBAG_SLOT_1 = UNIT_END + 0x0316, // Size: 64, Type: LONG, Flags: PRIVATE
+ PLAYER_FARSIGHT = UNIT_END + 0x0356, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x0358, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER__FIELD_KNOWN_TITLES1 = UNIT_END + 0x035A, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_KNOWN_CURRENCIES = UNIT_END + 0x035C, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER_XP = UNIT_END + 0x035E, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x035F, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x0360, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x04E0, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x04E1, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_TRACK_CREATURES = UNIT_END + 0x04E2, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_TRACK_RESOURCES = UNIT_END + 0x04E3, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x04E4, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x04E5, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x04E6, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_EXPERTISE = UNIT_END + 0x04E7, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x04E8, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x04E9, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x04EA, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x04EB, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x04EC, // Size: 7, Type: FLOAT, Flags: PRIVATE
+ PLAYER_SHIELD_BLOCK = UNIT_END + 0x04F3, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE = UNIT_END + 0x04F4, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x04F5, // Size: 128, Type: BYTES, Flags: PRIVATE
+ PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x0575, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_COINAGE = UNIT_END + 0x0576, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x0577, // Size: 7, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x057E, // Size: 7, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x0585, // Size: 7, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x058C, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x058D, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x058E, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BYTES = UNIT_END + 0x058F, // Size: 1, Type: BYTES, Flags: PRIVATE
+ PLAYER_AMMO_ID = UNIT_END + 0x0590, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_SELF_RES_SPELL = UNIT_END + 0x0591, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x0592, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x0593, // Size: 12, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x059F, // Size: 12, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_KILLS = UNIT_END + 0x05AB, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x05AC, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x05AD, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_LIFETIME_HONORBALE_KILLS = UNIT_END + 0x05AE, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BYTES2 = UNIT_END + 0x05AF, // Size: 1, Type: BYTES, Flags: PRIVATE
+ PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x05B0, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x05B1, // Size: 25, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x05CA, // Size: 18, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x05DC, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x05DD, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x05DE, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x05DF, // Size: 25, Type: INT, Flags: PRIVATE
+ PLAYER_RUNE_REGEN_1 = UNIT_END + 0x05F8, // Size: 4, Type: FLOAT, Flags: PRIVATE
+ PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x05FC, // Size: 3, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x05FF, // Size: 8, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x0607, // Size: 8, Type: INT, Flags: PRIVATE
+ PLAYER_GLYPHS_ENABLED = UNIT_END + 0x060F, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_END = UNIT_END + 0x0610,
};
enum EGameObjectFields
{
OBJECT_FIELD_CREATED_BY = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
GAMEOBJECT_DISPLAYID = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_ROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC
- GAMEOBJECT_STATE = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_POS_X = OBJECT_END + 0x0009, // Size: 1, Type: FLOAT, Flags: PUBLIC
- GAMEOBJECT_POS_Y = OBJECT_END + 0x000A, // Size: 1, Type: FLOAT, Flags: PUBLIC
- GAMEOBJECT_POS_Z = OBJECT_END + 0x000B, // Size: 1, Type: FLOAT, Flags: PUBLIC
- GAMEOBJECT_FACING = OBJECT_END + 0x000C, // Size: 1, Type: FLOAT, Flags: PUBLIC
- GAMEOBJECT_DYN_FLAGS = OBJECT_END + 0x000D, // Size: 1, Type: INT, Flags: DYNAMIC
- GAMEOBJECT_FACTION = OBJECT_END + 0x000E, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_TYPE_ID = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC
+ GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ GAMEOBJECT_ROTATION = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC
+ GAMEOBJECT_PARENTROTATION = OBJECT_END + 0x0006, // Size: 4, Type: FLOAT, Flags: PUBLIC
+ GAMEOBJECT_POS_X = OBJECT_END + 0x000A, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ GAMEOBJECT_POS_Y = OBJECT_END + 0x000B, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ GAMEOBJECT_POS_Z = OBJECT_END + 0x000C, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ GAMEOBJECT_FACING = OBJECT_END + 0x000D, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ GAMEOBJECT_DYNAMIC = OBJECT_END + 0x000E, // Size: 1, Type: TWO_SHORT, Flags: DYNAMIC
+ GAMEOBJECT_FACTION = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC
GAMEOBJECT_LEVEL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_ARTKIT = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_ANIMPROGRESS = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: DYNAMIC
- GAMEOBJECT_PADDING = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: NONE
- GAMEOBJECT_END = OBJECT_END + 0x0014,
+ GAMEOBJECT_BYTES_1 = OBJECT_END + 0x0011, // Size: 1, Type: BYTES, Flags: PUBLIC
+ GAMEOBJECT_END = OBJECT_END + 0x0012,
};
enum EDynamicObjectFields
diff --git a/src/game/UpdateMask.h b/src/game/UpdateMask.h
index 9949dd6aa5b..16fa753028f 100644
--- a/src/game/UpdateMask.h
+++ b/src/game/UpdateMask.h
@@ -36,27 +36,27 @@ class UpdateMask
delete [] mUpdateMask;
}
- inline void SetBit (uint32 index)
+ void SetBit (uint32 index)
{
( (uint8 *)mUpdateMask )[ index >> 3 ] |= 1 << ( index & 0x7 );
}
- inline void UnsetBit (uint32 index)
+ void UnsetBit (uint32 index)
{
( (uint8 *)mUpdateMask )[ index >> 3 ] &= (0xff ^ (1 << ( index & 0x7 ) ) );
}
- inline bool GetBit (uint32 index)
+ bool GetBit (uint32 index) const
{
return ( ( (uint8 *)mUpdateMask)[ index >> 3 ] & ( 1 << ( index & 0x7 ) )) != 0;
}
- inline uint32 GetBlockCount() { return mBlocks; }
- inline uint32 GetLength() { return mBlocks << 2; }
- inline uint32 GetCount() { return mCount; }
- inline uint8* GetMask() { return (uint8*)mUpdateMask; }
+ uint32 GetBlockCount() const { return mBlocks; }
+ uint32 GetLength() const { return mBlocks << 2; }
+ uint32 GetCount() const { return mCount; }
+ uint8* GetMask() { return (uint8*)mUpdateMask; }
- inline void SetCount (uint32 valuesCount)
+ void SetCount (uint32 valuesCount)
{
if(mUpdateMask)
delete [] mUpdateMask;
@@ -68,13 +68,13 @@ class UpdateMask
memset(mUpdateMask, 0, mBlocks << 2);
}
- inline void Clear()
+ void Clear()
{
if (mUpdateMask)
memset(mUpdateMask, 0, mBlocks << 2);
}
- inline UpdateMask& operator = ( const UpdateMask& mask )
+ UpdateMask& operator = ( const UpdateMask& mask )
{
SetCount(mask.mCount);
memcpy(mUpdateMask, mask.mUpdateMask, mBlocks << 2);
@@ -82,21 +82,21 @@ class UpdateMask
return *this;
}
- inline void operator &= ( const UpdateMask& mask )
+ void operator &= ( const UpdateMask& mask )
{
ASSERT(mask.mCount <= mCount);
for (uint32 i = 0; i < mBlocks; i++)
mUpdateMask[i] &= mask.mUpdateMask[i];
}
- inline void operator |= ( const UpdateMask& mask )
+ void operator |= ( const UpdateMask& mask )
{
ASSERT(mask.mCount <= mCount);
for (uint32 i = 0; i < mBlocks; i++)
mUpdateMask[i] |= mask.mUpdateMask[i];
}
- inline UpdateMask operator & ( const UpdateMask& mask ) const
+ UpdateMask operator & ( const UpdateMask& mask ) const
{
ASSERT(mask.mCount <= mCount);
@@ -107,7 +107,7 @@ class UpdateMask
return newmask;
}
- inline UpdateMask operator | ( const UpdateMask& mask ) const
+ UpdateMask operator | ( const UpdateMask& mask ) const
{
ASSERT(mask.mCount <= mCount);
diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp
new file mode 100644
index 00000000000..4e1153a166b
--- /dev/null
+++ b/src/game/Vehicle.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Common.h"
+#include "Log.h"
+#include "WorldSession.h"
+#include "WorldPacket.h"
+#include "ObjectMgr.h"
+#include "SpellMgr.h"
+#include "Vehicle.h"
+#include "MapManager.h"
+#include "SpellAuras.h"
+#include "Unit.h"
+#include "Util.h"
+
+Vehicle::Vehicle() : Creature(), m_vehicleId(0)
+{
+ m_isVehicle = true;
+ m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_VEHICLE);
+}
+
+Vehicle::~Vehicle()
+{
+ if(m_uint32Values) // only for fully created Object
+ ObjectAccessor::Instance().RemoveObject(this);
+}
+
+void Vehicle::AddToWorld()
+{
+ ///- Register the vehicle for guid lookup
+ if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this);
+ Unit::AddToWorld();
+}
+
+void Vehicle::RemoveFromWorld()
+{
+ ///- Remove the vehicle from the accessor
+ if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this);
+ ///- Don't call the function for Creature, normal mobs + totems go in a different storage
+ Unit::RemoveFromWorld();
+}
+
+void Vehicle::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState
+{
+ Creature::setDeathState(s);
+}
+
+void Vehicle::Update(uint32 diff)
+{
+ Creature::Update(diff);
+}
+
+bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team)
+{
+ SetMapId(map->GetId());
+ SetInstanceId(map->GetInstanceId());
+
+ Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE);
+
+ if(!InitEntry(Entry, team))
+ return false;
+
+ m_defaultMovementType = IDLE_MOTION_TYPE;
+
+ AIM_Initialize();
+
+ SetVehicleId(vehicleId);
+
+ SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
+ SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f);
+
+ CreatureInfo const *ci = GetCreatureInfo();
+ setFaction(team == ALLIANCE ? ci->faction_A : ci->faction_H);
+ SetMaxHealth(ci->maxhealth);
+ SelectLevel(ci);
+ SetHealth(GetMaxHealth());
+
+ return true;
+}
+
+void Vehicle::Dismiss()
+{
+ SendObjectDeSpawnAnim(GetGUID());
+ CombatStop();
+ CleanupsBeforeDelete();
+ AddObjectToRemoveList();
+}
diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h
new file mode 100644
index 00000000000..7fd8b60c40a
--- /dev/null
+++ b/src/game/Vehicle.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MANGOSSERVER_VEHICLE_H
+#define MANGOSSERVER_VEHICLE_H
+
+#include "ObjectDefines.h"
+#include "Creature.h"
+#include "Unit.h"
+
+class Vehicle : public Creature
+{
+ public:
+ explicit Vehicle();
+ virtual ~Vehicle();
+
+ void AddToWorld();
+ void RemoveFromWorld();
+
+ bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team);
+
+ void setDeathState(DeathState s); // overwrite virtual Creature::setDeathState and Unit::setDeathState
+ void Update(uint32 diff); // overwrite virtual Creature::Update and Unit::Update
+
+ uint32 GetVehicleId() { return m_vehicleId; }
+ void SetVehicleId(uint32 vehicleid) { m_vehicleId = vehicleid; }
+
+ void Dismiss();
+
+ protected:
+ uint32 m_vehicleId;
+
+ private:
+ void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called
+ {
+ assert(false);
+ }
+ void DeleteFromDB() // overwrited of Creature::DeleteFromDB - don't must be called
+ {
+ assert(false);
+ }
+};
+#endif
diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp
index fc0ca9e8007..bf999dbbc03 100644
--- a/src/game/WaypointManager.cpp
+++ b/src/game/WaypointManager.cpp
@@ -29,7 +29,7 @@ WaypointStore WaypointMgr;
void WaypointStore::Free()
{
- waypoint_map.clear();
+ waypoint_map.clear();
}
void WaypointStore::Load()
diff --git a/src/game/WaypointMovementGenerator.h b/src/game/WaypointMovementGenerator.h
index e9c806a4f7d..21163ded11c 100644
--- a/src/game/WaypointMovementGenerator.h
+++ b/src/game/WaypointMovementGenerator.h
@@ -48,7 +48,7 @@ class TRINITY_DLL_SPEC PathMovementBase
PathMovementBase() : i_currentNode(0) {}
virtual ~PathMovementBase() {};
- inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); }
+ bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); }
void LoadPath(T &);
void ReloadPath(T &);
@@ -109,7 +109,7 @@ public PathMovementBase<Player>
Path& GetPath() { return i_path; }
uint32 GetPathAtMapEnd() const;
- inline bool HasArrived() const { return (i_currentNode >= i_path.Size()); }
+ bool HasArrived() const { return (i_currentNode >= i_path.Size()); }
void SetCurrentNodeAfterTeleport();
void SkipCurrentNode() { ++i_currentNode; }
bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
diff --git a/src/game/Weather.cpp b/src/game/Weather.cpp
index d825b2f4064..11eedab7593 100644
--- a/src/game/Weather.cpp
+++ b/src/game/Weather.cpp
@@ -42,7 +42,7 @@ Weather::Weather(uint32 zone, WeatherZoneChances const* weatherChances) : m_zone
}
/// Launch a weather update
-bool Weather::Update(time_t diff)
+bool Weather::Update(uint32 diff)
{
if (m_timer.GetCurrent()>=0)
m_timer.Update(diff);
diff --git a/src/game/Weather.h b/src/game/Weather.h
index 7fc3068ffe7..8d9585b07d3 100644
--- a/src/game/Weather.h
+++ b/src/game/Weather.h
@@ -62,7 +62,7 @@ class Weather
void SetWeather(WeatherType type, float grade);
/// For which zone is this weather?
uint32 GetZone() { return m_zone; };
- bool Update(time_t diff);
+ bool Update(uint32 diff);
private:
WeatherState GetWeatherState() const;
uint32 m_zone;
diff --git a/src/game/World.cpp b/src/game/World.cpp
index e84894bdb27..4914550231b 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -37,6 +37,7 @@
#include "SkillDiscovery.h"
#include "World.h"
#include "AccountMgr.h"
+#include "AchievementMgr.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Chat.h"
@@ -237,7 +238,7 @@ World::AddSession_ (WorldSession* s)
uint32 Sessions = GetActiveAndQueuedSessionCount ();
uint32 pLimit = GetPlayerAmountLimit ();
- uint32 QueueSize = GetQueueSize (); //number of players in the queue
+ uint32 QueueSize = GetQueueSize (); //number of players in the queue
//so we don't count the user trying to
//login as a session and queue the socket that we are using
@@ -254,10 +255,10 @@ World::AddSession_ (WorldSession* s)
WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
packet << uint8 (AUTH_OK);
- packet << uint32 (0); // unknown random value...
- packet << uint8 (0);
- packet << uint32 (0);
- packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
+ packet << uint32 (0); // BillingTimeRemaining
+ packet << uint8 (0); // BillingPlanFlags
+ packet << uint32 (0); // BillingTimeRested
+ packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
s->SendPacket (&packet);
UpdateMaxSessionCounters ();
@@ -265,7 +266,7 @@ World::AddSession_ (WorldSession* s)
// Updates the population
if (pLimit > 0)
{
- float popu = GetActiveSessionCount (); //updated number of users on the server
+ float popu = GetActiveSessionCount (); //updated number of users on the server
popu /= pLimit;
popu *= 2;
LoginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
@@ -292,10 +293,10 @@ void World::AddQueuedPlayer(WorldSession* sess)
// The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
WorldPacket packet (SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
packet << uint8 (AUTH_WAIT_QUEUE);
- packet << uint32 (0); // unknown random value...
- packet << uint8 (0);
- packet << uint32 (0);
- packet << uint8 (sess->Expansion () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account
+ packet << uint32 (0); // BillingTimeRemaining
+ packet << uint8 (0); // BillingPlanFlags
+ packet << uint32 (0); // BillingTimeRested
+ packet << uint8 (sess->Expansion () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account
packet << uint32(GetQueuePos (sess));
sess->SendPacket (&packet);
@@ -419,24 +420,30 @@ void World::LoadConfigSettings(bool reload)
rate_values[RATE_HEALTH] = sConfig.GetFloatDefault("Rate.Health", 1);
if(rate_values[RATE_HEALTH] < 0)
{
- sLog.outError("Rate.Health (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_HEALTH]);
+ sLog.outError("Rate.Health (%f) must be > 0. Using 1 instead.",rate_values[RATE_HEALTH]);
rate_values[RATE_HEALTH] = 1;
}
rate_values[RATE_POWER_MANA] = sConfig.GetFloatDefault("Rate.Mana", 1);
if(rate_values[RATE_POWER_MANA] < 0)
{
- sLog.outError("Rate.Mana (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_POWER_MANA]);
+ sLog.outError("Rate.Mana (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_MANA]);
rate_values[RATE_POWER_MANA] = 1;
}
rate_values[RATE_POWER_RAGE_INCOME] = sConfig.GetFloatDefault("Rate.Rage.Income", 1);
rate_values[RATE_POWER_RAGE_LOSS] = sConfig.GetFloatDefault("Rate.Rage.Loss", 1);
if(rate_values[RATE_POWER_RAGE_LOSS] < 0)
{
- sLog.outError("Rate.Rage.Loss (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_POWER_RAGE_LOSS]);
+ sLog.outError("Rate.Rage.Loss (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_RAGE_LOSS]);
rate_values[RATE_POWER_RAGE_LOSS] = 1;
}
+ rate_values[RATE_POWER_RUNICPOWER_INCOME] = sConfig.GetFloatDefault("Rate.RunicPower.Income", 1);
+ rate_values[RATE_POWER_RUNICPOWER_LOSS] = sConfig.GetFloatDefault("Rate.RunicPower.Loss", 1);
+ if(rate_values[RATE_POWER_RUNICPOWER_LOSS] < 0)
+ {
+ sLog.outError("Rate.RunicPower.Loss (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_RUNICPOWER_LOSS]);
+ rate_values[RATE_POWER_RUNICPOWER_LOSS] = 1;
+ }
rate_values[RATE_POWER_FOCUS] = sConfig.GetFloatDefault("Rate.Focus", 1.0f);
- rate_values[RATE_LOYALTY] = sConfig.GetFloatDefault("Rate.Loyalty", 1.0f);
rate_values[RATE_SKILL_DISCOVERY] = sConfig.GetFloatDefault("Rate.Skill.Discovery", 1.0f);
rate_values[RATE_DROP_ITEM_POOR] = sConfig.GetFloatDefault("Rate.Drop.Item.Poor", 1.0f);
rate_values[RATE_DROP_ITEM_NORMAL] = sConfig.GetFloatDefault("Rate.Drop.Item.Normal", 1.0f);
@@ -450,7 +457,6 @@ void World::LoadConfigSettings(bool reload)
rate_values[RATE_XP_KILL] = sConfig.GetFloatDefault("Rate.XP.Kill", 1.0f);
rate_values[RATE_XP_QUEST] = sConfig.GetFloatDefault("Rate.XP.Quest", 1.0f);
rate_values[RATE_XP_EXPLORE] = sConfig.GetFloatDefault("Rate.XP.Explore", 1.0f);
- rate_values[RATE_XP_PAST_70] = sConfig.GetFloatDefault("Rate.XP.PastLevel70", 1.0f);
rate_values[RATE_REPUTATION_GAIN] = sConfig.GetFloatDefault("Rate.Reputation.Gain", 1.0f);
rate_values[RATE_CREATURE_NORMAL_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Normal.Damage", 1.0f);
rate_values[RATE_CREATURE_ELITE_ELITE_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.Elite.Damage", 1.0f);
@@ -629,6 +635,15 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = m_configs[CONFIG_CHARACTERS_PER_REALM];
}
+ m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("HeroicCharactersPerRealm", 1);
+ if(m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] < 0 || m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] > 10)
+ {
+ sLog.outError("HeroicCharactersPerRealm (%i) must be in range 0..10. Set to 1.",m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]);
+ m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = 1;
+ }
+
+ m_configs[CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING] = sConfig.GetIntDefault("MinLevelForHeroicCharacterCreating", 55);
+
m_configs[CONFIG_SKIP_CINEMATICS] = sConfig.GetIntDefault("SkipCinematics", 0);
if(m_configs[CONFIG_SKIP_CINEMATICS] < 0 || m_configs[CONFIG_SKIP_CINEMATICS] > 2)
{
@@ -663,6 +678,20 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_START_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL];
}
+ m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = sConfig.GetIntDefault("StartHeroicPlayerLevel", 55);
+ if(m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] < 1)
+ {
+ sLog.outError("StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to 55.",
+ m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]);
+ m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = 55;
+ }
+ else if(m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] > m_configs[CONFIG_MAX_PLAYER_LEVEL])
+ {
+ sLog.outError("StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.",
+ m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]);
+ m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL];
+ }
+
m_configs[CONFIG_START_PLAYER_MONEY] = sConfig.GetIntDefault("StartPlayerMoney", 0);
if(m_configs[CONFIG_START_PLAYER_MONEY] < 0)
{
@@ -724,8 +753,11 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfig.GetBoolDefault("Instance.IgnoreRaid", false);
m_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfig.GetBoolDefault("Battleground.CastDeserter", true);
- m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", true);
+ m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", false);
m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false);
+ m_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Arena.QueueAnnouncer.Enable", false);
+ m_configs[CONFIG_ARENA_SEASON_ID] = sConfig.GetIntDefault ("Arena.ArenaSeason.ID", 1);
+ m_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfig.GetBoolDefault("Arena.ArenaSeason.InProgress", true);
m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true);
m_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfig.GetIntDefault("Instance.ResetTimeHour", 4);
@@ -735,15 +767,17 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_MIN_PETITION_SIGNS] = sConfig.GetIntDefault("MinPetitionSigns", 9);
if(m_configs[CONFIG_MIN_PETITION_SIGNS] > 9)
{
- sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.",m_configs[CONFIG_MIN_PETITION_SIGNS]);
+ sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.", m_configs[CONFIG_MIN_PETITION_SIGNS]);
m_configs[CONFIG_MIN_PETITION_SIGNS] = 9;
}
- m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState",2);
- m_configs[CONFIG_GM_CHAT] = sConfig.GetIntDefault("GM.Chat",2);
- m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetIntDefault("GM.WhisperingTo",2);
- m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList",false);
- m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList",false);
+ m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState", 2);
+ m_configs[CONFIG_GM_VISIBLE_STATE] = sConfig.GetIntDefault("GM.Visible", 2);
+ //m_configs[CONFIG_GM_ACCEPT_TICKETS] = sConfig.GetIntDefault("GM.AcceptTickets", 2);
+ m_configs[CONFIG_GM_CHAT] = sConfig.GetIntDefault("GM.Chat", 2);
+ m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetIntDefault("GM.WhisperingTo", 2);
+ m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList", false);
+ m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList", false);
m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetBoolDefault("GM.LogTrade", false);
m_configs[CONFIG_START_GM_LEVEL] = sConfig.GetIntDefault("GM.StartLevel", 1);
if(m_configs[CONFIG_START_GM_LEVEL] < m_configs[CONFIG_START_PLAYER_LEVEL])
@@ -757,6 +791,8 @@ void World::LoadConfigSettings(bool reload)
sLog.outError("GM.StartLevel (%i) must be in range 1..%u. Set to %u.", m_configs[CONFIG_START_GM_LEVEL], MAX_LEVEL, MAX_LEVEL);
m_configs[CONFIG_START_GM_LEVEL] = MAX_LEVEL;
}
+ m_configs[CONFIG_GM_LOWER_SECURITY] = sConfig.GetBoolDefault("GM.LowerSecurity", false);
+ m_configs[CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS] = sConfig.GetBoolDefault("GM.AllowAchievementGain", true);
m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0);
@@ -783,6 +819,7 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_SKILL_CHANCE_SKINNING_STEPS] = sConfig.GetIntDefault("SkillChance.SkinningSteps",75);
m_configs[CONFIG_SKILL_PROSPECTING] = sConfig.GetBoolDefault("SkillChance.Prospecting",false);
+ m_configs[CONFIG_SKILL_MILLING] = sConfig.GetBoolDefault("SkillChance.Milling",false);
m_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfig.GetIntDefault("SkillGain.Crafting", 1);
if(m_configs[CONFIG_SKILL_GAIN_CRAFTING] < 0)
@@ -871,6 +908,8 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_DEATH_SICKNESS_LEVEL] = sConfig.GetIntDefault("Death.SicknessLevel", 11);
m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvP", true);
m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvE", true);
+ m_configs[CONFIG_DEATH_BONES_WORLD] = sConfig.GetBoolDefault("Death.Bones.World", true);
+ m_configs[CONFIG_DEATH_BONES_BG_OR_ARENA] = sConfig.GetBoolDefault("Death.Bones.BattlegroundOrArena", true);
m_configs[CONFIG_THREAT_RADIUS] = sConfig.GetIntDefault("ThreatRadius", 60);
@@ -1069,7 +1108,7 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Script Names...");
objmgr.LoadScriptNames();
- sLog.outString( "Loading InstanceTemplate" );
+ sLog.outString( "Loading InstanceTemplate..." );
objmgr.LoadInstanceTemplate();
sLog.outString( "Loading SkillLineAbilityMultiMap Data..." );
@@ -1077,11 +1116,12 @@ void World::SetInitialWorldSettings()
///- Clean up and pack instances
sLog.outString( "Cleaning up instances..." );
- sInstanceSaveManager.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables
+ sInstanceSaveManager.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables
sLog.outString( "Packing instances..." );
sInstanceSaveManager.PackInstances();
+ sLog.outString();
sLog.outString( "Loading Localization strings..." );
objmgr.LoadCreatureLocales();
objmgr.LoadGameObjectLocales();
@@ -1091,6 +1131,8 @@ void World::SetInitialWorldSettings()
objmgr.LoadPageTextLocales();
objmgr.LoadNpcOptionLocales();
objmgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
+ sLog.outString( ">>> Localization strings loaded" );
+ sLog.outString();
sLog.outString( "Loading Page Texts..." );
objmgr.LoadPageTexts();
@@ -1119,6 +1161,9 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Spell Proc Event conditions..." );
spellmgr.LoadSpellProcEvents();
+ sLog.outString( "Loading Spell Bonus Data..." );
+ spellmgr.LoadSpellBonusess();
+
sLog.outString( "Loading Aggro Spells Definitions...");
spellmgr.LoadSpellThreats();
@@ -1156,7 +1201,10 @@ void World::SetInitialWorldSettings()
objmgr.LoadCreatures();
sLog.outString( "Loading Creature Addon Data..." );
+ sLog.outString();
objmgr.LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures()
+ sLog.outString( ">>> Creature Addon Data loaded" );
+ sLog.outString();
sLog.outString( "Loading Creature Respawn Data..." ); // must be after PackInstances()
objmgr.LoadCreatureRespawnTimes();
@@ -1168,7 +1216,10 @@ void World::SetInitialWorldSettings()
objmgr.LoadGameobjectRespawnTimes();
sLog.outString( "Loading Game Event Data...");
+ sLog.outString();
gameeventmgr.LoadFromDB();
+ sLog.outString( ">>> Game Event Data loaded" );
+ sLog.outString();
sLog.outString( "Loading Weather Data..." );
objmgr.LoadWeatherZoneChances();
@@ -1177,7 +1228,10 @@ void World::SetInitialWorldSettings()
objmgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables
sLog.outString( "Loading Quests Relations..." );
+ sLog.outString();
objmgr.LoadQuestRelations(); // must be after quest load
+ sLog.outString( ">>> Quests Relations loaded" );
+ sLog.outString();
sLog.outString( "Loading AreaTrigger definitions..." );
objmgr.LoadAreaTriggerTeleports(); // must be after item template load
@@ -1203,14 +1257,20 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading spell pet auras..." );
spellmgr.LoadSpellPetAuras();
+ sLog.outString( "Loading pet levelup spells..." );
+ spellmgr.LoadPetLevelupSpellMap();
+
sLog.outString( "Loading spell extra attributes...(TODO)" );
spellmgr.LoadSpellCustomAttr();
sLog.outString( "Loading linked spells..." );
spellmgr.LoadSpellLinked();
- sLog.outString( "Loading player Create Info & Level Stats..." );
+ sLog.outString( "Loading Player Create Info & Level Stats..." );
+ sLog.outString();
objmgr.LoadPlayerInfo();
+ sLog.outString( ">>> Player Create Info & Level Stats loaded" );
+ sLog.outString();
sLog.outString( "Loading Exploration BaseXP Data..." );
objmgr.LoadExplorationBaseXP();
@@ -1231,7 +1291,10 @@ void World::SetInitialWorldSettings()
objmgr.LoadSpellDisabledEntrys();
sLog.outString( "Loading Loot Tables..." );
+ sLog.outString();
LoadLootTables();
+ sLog.outString( ">>> Loot Tables loaded" );
+ sLog.outString();
sLog.outString( "Loading Skill Discovery Table..." );
LoadSkillDiscoveryTable();
@@ -1242,10 +1305,22 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Skill Fishing base level requirements..." );
objmgr.LoadFishingBaseSkillLevel();
+ sLog.outString( "Loading Achievements..." );
+ sLog.outString();
+ achievementmgr.LoadAchievementCriteriaList();
+ achievementmgr.LoadRewards();
+ achievementmgr.LoadRewardLocales();
+ achievementmgr.LoadCompletedAchievements();
+ sLog.outString( ">>> Achievements loaded" );
+ sLog.outString();
+
///- Load dynamic data tables from the database
sLog.outString( "Loading Auctions..." );
+ sLog.outString();
objmgr.LoadAuctionItems();
objmgr.LoadAuctions();
+ sLog.outString( ">>> Auctions loaded" );
+ sLog.outString();
sLog.outString( "Loading Guilds..." );
objmgr.LoadGuilds();
@@ -1259,7 +1334,7 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading ReservedNames..." );
objmgr.LoadReservedPlayersNames();
- sLog.outString( "Loading GameObject for quests..." );
+ sLog.outString( "Loading GameObjects for quests..." );
objmgr.LoadGameObjectForQuests();
sLog.outString( "Loading BattleMasters..." );
@@ -1274,13 +1349,14 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Npc Options..." );
objmgr.LoadNpcOptions();
- sLog.outString( "Loading vendors..." );
+ sLog.outString( "Loading Vendors..." );
objmgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate
- sLog.outString( "Loading trainers..." );
+ sLog.outString( "Loading Trainers..." );
objmgr.LoadTrainerSpell(); // must be after load CreatureTemplate
sLog.outString( "Loading Waypoints..." );
+ sLog.outString();
WaypointMgr.Load();
sLog.outString( "Loading Creature Formations..." );
@@ -1295,12 +1371,15 @@ void World::SetInitialWorldSettings()
///- Load and initialize scripts
sLog.outString( "Loading Scripts..." );
+ sLog.outString();
objmgr.LoadQuestStartScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate
objmgr.LoadQuestEndScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate
objmgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadWaypointScripts();
+ sLog.outString( ">>> Scripts loaded" );
+ sLog.outString();
sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls
objmgr.LoadDbScriptStrings();
@@ -1422,6 +1501,7 @@ void World::DetectDBCLang()
m_defaultDbcLocale = LocaleConstant(default_locale);
sLog.outString("Using %s DBC Locale as default. All available DBC locales: %s",localeNames[m_defaultDbcLocale],availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str());
+ sLog.outString();
}
void World::RecordTimeDiff(const char *text, ...)
@@ -1451,7 +1531,7 @@ void World::RecordTimeDiff(const char *text, ...)
}
/// Update the World !
-void World::Update(time_t diff)
+void World::Update(uint32 diff)
{
m_updateTime = uint32(diff);
if(m_configs[CONFIG_INTERVAL_LOG_UPDATE])
@@ -1739,6 +1819,9 @@ void World::ScriptsProcess()
case HIGHGUID_PET:
source = HashMapHolder<Pet>::Find(step.sourceGUID);
break;
+ case HIGHGUID_VEHICLE:
+ source = HashMapHolder<Vehicle>::Find(step.sourceGUID);
+ break;
case HIGHGUID_PLAYER:
source = HashMapHolder<Player>::Find(step.sourceGUID);
break;
@@ -1778,6 +1861,9 @@ void World::ScriptsProcess()
case HIGHGUID_PET:
target = HashMapHolder<Pet>::Find(step.targetGUID);
break;
+ case HIGHGUID_VEHICLE:
+ target = HashMapHolder<Vehicle>::Find(step.targetGUID);
+ break;
case HIGHGUID_PLAYER: // empty GUID case also
target = HashMapHolder<Player>::Find(step.targetGUID);
break;
@@ -2008,8 +2094,8 @@ void World::ScriptsProcess()
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
- Trinity::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong);
- Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(go,go_check);
+ MaNGOS::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong);
+ MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(summoner, go,go_check);
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -2069,8 +2155,8 @@ void World::ScriptsProcess()
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
- Trinity::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
- Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(door,go_check);
+ MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
+ MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check);
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -2125,8 +2211,8 @@ void World::ScriptsProcess()
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
- Trinity::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
- Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(door,go_check);
+ MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
+ MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check);
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -2342,7 +2428,7 @@ void World::ScriptsProcess()
//sLog.outDebug("Attempting to find Creature: Db GUID: %i", step.script->datalong);
Trinity::CreatureWithDbGUIDCheck target_check(((Unit*)source), step.script->datalong);
- Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(target,target_check);
+ Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(((Unit*)source), target, target_check);
TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
@@ -2850,7 +2936,7 @@ void World::SendServerMessage(uint32 type, const char *text, Player* player)
SendGlobalMessage( &data );
}
-void World::UpdateSessions( time_t diff )
+void World::UpdateSessions( uint32 diff )
{
///- Add new sessions
while(!addSessQueue.empty())
diff --git a/src/game/World.h b/src/game/World.h
index 63d9b52d7f2..c132110fa7f 100644
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -103,9 +103,12 @@ enum WorldConfigs
CONFIG_CHARACTERS_CREATING_DISABLED,
CONFIG_CHARACTERS_PER_ACCOUNT,
CONFIG_CHARACTERS_PER_REALM,
+ CONFIG_HEROIC_CHARACTERS_PER_REALM,
+ CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING,
CONFIG_SKIP_CINEMATICS,
CONFIG_MAX_PLAYER_LEVEL,
CONFIG_START_PLAYER_LEVEL,
+ CONFIG_START_HEROIC_PLAYER_LEVEL,
CONFIG_START_PLAYER_MONEY,
CONFIG_MAX_HONOR_POINTS,
CONFIG_START_HONOR_POINTS,
@@ -122,12 +125,16 @@ enum WorldConfigs
CONFIG_MAX_PRIMARY_TRADE_SKILL,
CONFIG_MIN_PETITION_SIGNS,
CONFIG_GM_LOGIN_STATE,
+ CONFIG_GM_VISIBLE_STATE,
+ CONFIG_GM_ACCEPT_TICKETS,
CONFIG_GM_CHAT,
CONFIG_GM_WISPERING_TO,
CONFIG_GM_IN_GM_LIST,
CONFIG_GM_IN_WHO_LIST,
CONFIG_GM_LOG_TRADE,
CONFIG_START_GM_LEVEL,
+ CONFIG_GM_LOWER_SECURITY,
+ CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS,
CONFIG_GROUP_VISIBILITY,
CONFIG_MAIL_DELIVERY_DELAY,
CONFIG_UPTIME_UPDATE,
@@ -170,6 +177,8 @@ enum WorldConfigs
CONFIG_DEATH_SICKNESS_LEVEL,
CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP,
CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE,
+ CONFIG_DEATH_BONES_WORLD,
+ CONFIG_DEATH_BONES_BG_OR_ARENA,
CONFIG_THREAT_RADIUS,
CONFIG_INSTANT_LOGOUT,
CONFIG_DISABLE_BREATHING,
@@ -182,8 +191,11 @@ enum WorldConfigs
CONFIG_ARENA_RATING_DISCARD_TIMER,
CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
+ CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
+ CONFIG_ARENA_SEASON_ID,
+ CONFIG_ARENA_SEASON_IN_PROGRESS,
CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
-
+ CONFIG_SKILL_MILLING,
CONFIG_MAX_WHO,
CONFIG_BG_START_MUSIC,
CONFIG_START_ALL_SPELLS,
@@ -211,6 +223,8 @@ enum Rates
RATE_POWER_MANA,
RATE_POWER_RAGE_INCOME,
RATE_POWER_RAGE_LOSS,
+ RATE_POWER_RUNICPOWER_INCOME,
+ RATE_POWER_RUNICPOWER_LOSS,
RATE_POWER_FOCUS,
RATE_SKILL_DISCOVERY,
RATE_DROP_ITEM_POOR,
@@ -225,7 +239,6 @@ enum Rates
RATE_XP_KILL,
RATE_XP_QUEST,
RATE_XP_EXPLORE,
- RATE_XP_PAST_70,
RATE_REPUTATION_GAIN,
RATE_CREATURE_NORMAL_HP,
RATE_CREATURE_ELITE_ELITE_HP,
@@ -254,7 +267,6 @@ enum Rates
RATE_MINING_AMOUNT,
RATE_MINING_NEXT,
RATE_TALENT,
- RATE_LOYALTY,
RATE_CORPSE_DECAY_LOOTED,
RATE_INSTANCE_RESET_TIME,
RATE_TARGET_POS_RECALCULATION_RANGE,
@@ -450,9 +462,9 @@ class World
static void StopNow(uint8 exitcode) { m_stopEvent = true; m_ExitCode = exitcode; }
static bool IsStopped() { return m_stopEvent; }
- void Update(time_t diff);
+ void Update(uint32 diff);
- void UpdateSessions( time_t diff );
+ void UpdateSessions( uint32 diff );
/// Set a server rate (see #Rates)
void setRate(Rates rate,float value) { rate_values[rate]=value; }
/// Get a server rate (see #Rates)
diff --git a/src/game/WorldLog.h b/src/game/WorldLog.h
index 8ec03d37d6d..5fb0362a6f1 100644
--- a/src/game/WorldLog.h
+++ b/src/game/WorldLog.h
@@ -51,9 +51,9 @@ class TRINITY_DLL_DECL WorldLog : public Trinity::Singleton<WorldLog, Trinity::C
public:
void Initialize();
/// Is the world logger active?
- inline bool LogWorld(void) const { return (i_file != NULL); }
+ bool LogWorld(void) const { return (i_file != NULL); }
/// %Log to the file
- inline void Log(char const *fmt, ...)
+ void Log(char const *fmt, ...)
{
if( LogWorld() )
{
diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp
index e043bbe9659..6ec807b710f 100644
--- a/src/game/WorldSession.cpp
+++ b/src/game/WorldSession.cpp
@@ -318,6 +318,10 @@ void WorldSession::LogoutPlayer(bool Save)
if(_player->InBattleGround())
_player->LeaveBattleground();
+ ///- Teleport to home if the player is in an invalid instance
+ if(!_player->m_InstanceValid && !_player->isGameMaster())
+ _player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation());
+
sOutdoorPvPMgr.HandlePlayerLeaveZone(_player,_player->GetZoneId());
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
@@ -526,3 +530,93 @@ void WorldSession::SendAuthWaitQue(uint32 position)
SendPacket(&packet);
}
}
+
+void WorldSession::LoadAccountData()
+{
+ for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
+ {
+ AccountData data;
+ m_accountData[i] = data;
+ }
+
+ QueryResult *result = CharacterDatabase.PQuery("SELECT type, time, data FROM account_data WHERE account='%u'", GetAccountId());
+
+ if(!result)
+ return;
+
+ do
+ {
+ Field *fields = result->Fetch();
+
+ uint32 type = fields[0].GetUInt32();
+ if(type < NUM_ACCOUNT_DATA_TYPES)
+ {
+ m_accountData[type].Time = fields[1].GetUInt32();
+ m_accountData[type].Data = fields[2].GetCppString();
+ }
+ } while (result->NextRow());
+
+ delete result;
+}
+
+void WorldSession::SetAccountData(uint32 type, time_t time_, std::string data)
+{
+ m_accountData[type].Time = time_;
+ m_accountData[type].Data = data;
+
+ uint32 acc = GetAccountId();
+
+ CharacterDatabase.BeginTransaction ();
+ CharacterDatabase.PExecute("DELETE FROM account_data WHERE account='%u' AND type='%u'", acc, type);
+ CharacterDatabase.escape_string(data);
+ CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)time_, data.c_str());
+ CharacterDatabase.CommitTransaction ();
+}
+
+void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo *mi)
+{
+ CHECK_PACKET_SIZE(data, data.rpos()+4+2+4+4+4+4+4);
+ data >> mi->flags;
+ data >> mi->unk1;
+ data >> mi->time;
+ data >> mi->x;
+ data >> mi->y;
+ data >> mi->z;
+ data >> mi->o;
+
+ if(mi->flags & MOVEMENTFLAG_ONTRANSPORT)
+ {
+ CHECK_PACKET_SIZE(data, data.rpos()+8+4+4+4+4+4+1);
+ data >> mi->t_guid;
+ data >> mi->t_x;
+ data >> mi->t_y;
+ data >> mi->t_z;
+ data >> mi->t_o;
+ data >> mi->t_time;
+ data >> mi->t_seat;
+ }
+
+ if((mi->flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (mi->unk1 & 0x20))
+ {
+ CHECK_PACKET_SIZE(data, data.rpos()+4);
+ data >> mi->s_pitch;
+ }
+
+ CHECK_PACKET_SIZE(data, data.rpos()+4);
+ data >> mi->fallTime;
+
+ if(mi->flags & MOVEMENTFLAG_JUMPING)
+ {
+ CHECK_PACKET_SIZE(data, data.rpos()+4+4+4+4);
+ data >> mi->j_unk;
+ data >> mi->j_sinAngle;
+ data >> mi->j_cosAngle;
+ data >> mi->j_xyspeed;
+ }
+
+ if(mi->flags & MOVEMENTFLAG_SPLINE)
+ {
+ CHECK_PACKET_SIZE(data, data.rpos()+4);
+ data >> mi->u_unk1;
+ }
+}
diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h
index af4c059f5ee..295f69e0eb2 100644
--- a/src/game/WorldSession.h
+++ b/src/game/WorldSession.h
@@ -47,6 +47,16 @@ class CharacterHandler;
#define CHECK_PACKET_SIZE(P,S) if((P).size() < (S)) return SizeError((P),(S));
+#define NUM_ACCOUNT_DATA_TYPES 8
+
+struct AccountData
+{
+ AccountData() : Time(0), Data("") {}
+
+ time_t Time;
+ std::string Data;
+};
+
enum PartyOperation
{
PARTY_OP_INVITE = 0,
@@ -81,6 +91,8 @@ class TRINITY_DLL_SPEC WorldSession
void SizeError(WorldPacket const& packet, uint32 size) const;
+ void ReadMovementInfo(WorldPacket &data, MovementInfo *mi);
+
void SendPacket(WorldPacket const* packet);
void SendNotification(const char *format,...) ATTR_PRINTF(2,3);
void SendNotification(int32 string_id,...);
@@ -153,6 +165,11 @@ class TRINITY_DLL_SPEC WorldSession
//pet
void SendPetNameQuery(uint64 guid, uint32 petnumber);
+ // Account Data
+ AccountData *GetAccountData(uint32 type) { return &m_accountData[type]; }
+ void SetAccountData(uint32 type, time_t time_, std::string data);
+ void LoadAccountData();
+
//mail
//used with item_page table
bool SendItemInfo( uint32 itemid, WorldPacket data );
@@ -310,6 +327,7 @@ class TRINITY_DLL_SPEC WorldSession
void HandleGameObjectUseOpcode(WorldPacket& recPacket);
void HandleMeetingStoneInfo(WorldPacket& recPacket);
+ void HandleGameobjectReportUse(WorldPacket& recvPacket);
void HandleNameQueryOpcode(WorldPacket& recvPacket);
@@ -323,9 +341,10 @@ class TRINITY_DLL_SPEC WorldSession
void HandleMoveWorldportAckOpcode(); // for server-side calls
void HandleMovementOpcodes(WorldPacket& recvPacket);
- void HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& movementInfo, uint32& MovementFlags);
+ //void HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& movementInfo, uint32& MovementFlags);
void HandleSetActiveMoverOpcode(WorldPacket &recv_data);
- void HandleNotActiveMoverOpcode(WorldPacket &recv_data);
+ void HandleMoveNotActiveMover(WorldPacket &recv_data);
+ void HandleDismissControlledVehicle(WorldPacket &recv_data);
void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data);
void HandleRequestRaidInfoOpcode( WorldPacket & recv_data );
@@ -386,7 +405,7 @@ class TRINITY_DLL_SPEC WorldSession
void HandleGuildSaveEmblemOpcode(WorldPacket& recvPacket);
void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket);
- void HandleTaxiQueryAvailableNodesOpcode(WorldPacket& recvPacket);
+ void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket);
void HandleActivateTaxiOpcode(WorldPacket& recvPacket);
void HandleActivateTaxiFarOpcode(WorldPacket& recvPacket);
void HandleTaxiNextDestinationOpcode(WorldPacket& recvPacket);
@@ -430,6 +449,7 @@ class TRINITY_DLL_SPEC WorldSession
void HandleAuctionRemoveItem( WorldPacket & recv_data );
void HandleAuctionListOwnerItems( WorldPacket & recv_data );
void HandleAuctionPlaceBid( WorldPacket & recv_data );
+ void HandleAuctionListPendingSales( WorldPacket & recv_data );
void HandleGetMail( WorldPacket & recv_data );
void HandleSendMail( WorldPacket & recv_data );
@@ -545,6 +565,7 @@ class TRINITY_DLL_SPEC WorldSession
void HandlePetUnlearnOpcode( WorldPacket& recvPacket );
void HandlePetSpellAutocastOpcode( WorldPacket& recvPacket );
void HandlePetCastSpellOpcode( WorldPacket& recvPacket );
+ void HandlePetLearnTalent( WorldPacket& recvPacket );
void HandleSetActionBar(WorldPacket& recv_data);
@@ -581,10 +602,9 @@ class TRINITY_DLL_SPEC WorldSession
void HandleLfmSetNoneOpcode(WorldPacket& recv_data);
void HandleLfmSetOpcode(WorldPacket& recv_data);
void HandleLfgSetCommentOpcode(WorldPacket& recv_data);
- void HandleNewUnknownOpcode(WorldPacket& recv_data);
void HandleChooseTitleOpcode(WorldPacket& recv_data);
void HandleRealmStateRequestOpcode(WorldPacket& recv_data);
- void HandleAllowMoveAckOpcode(WorldPacket& recv_data);
+ void HandleTimeSyncResp(WorldPacket& recv_data);
void HandleWhoisOpcode(WorldPacket& recv_data);
void HandleResetInstancesOpcode(WorldPacket& recv_data);
@@ -630,6 +650,29 @@ class TRINITY_DLL_SPEC WorldSession
void HandleGuildBankBuyTab(WorldPacket& recv_data);
void HandleGuildBankTabText(WorldPacket& recv_data);
void HandleGuildBankSetTabText(WorldPacket& recv_data);
+
+ // Calendar
+ void HandleCalendarGetCalendar(WorldPacket& recv_data);
+ void HandleCalendarGetEvent(WorldPacket& recv_data);
+ void HandleCalendarGuildFilter(WorldPacket& recv_data);
+ void HandleCalendarArenaTeam(WorldPacket& recv_data);
+ void HandleCalendarAddEvent(WorldPacket& recv_data);
+ void HandleCalendarUpdateEvent(WorldPacket& recv_data);
+ void HandleCalendarRemoveEvent(WorldPacket& recv_data);
+ void HandleCalendarCopyEvent(WorldPacket& recv_data);
+ void HandleCalendarEventInvite(WorldPacket& recv_data);
+ void HandleCalendarEventRsvp(WorldPacket& recv_data);
+ void HandleCalendarEventRemoveInvite(WorldPacket& recv_data);
+ void HandleCalendarEventStatus(WorldPacket& recv_data);
+ void HandleCalendarEventModeratorStatus(WorldPacket& recv_data);
+ void HandleCalendarComplain(WorldPacket& recv_data);
+ void HandleCalendarGetNumPending(WorldPacket& recv_data);
+
+ void HandleSpellClick(WorldPacket& recv_data);
+ void HandleAlterAppearance(WorldPacket& recv_data);
+ void HandleRemoveGlyph(WorldPacket& recv_data);
+ void HandleCharCustomize(WorldPacket& recv_data);
+ void HandleInspectAchievements(WorldPacket& recv_data);
private:
// private trade methods
void moveItems(Item* myItems[], Item* hisItems[]);
@@ -652,6 +695,7 @@ class TRINITY_DLL_SPEC WorldSession
LocaleConstant m_sessionDbcLocale;
int m_sessionDbLocaleIndex;
uint32 m_latency;
+ AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES];
ZThread::LockedQueue<WorldPacket*,ZThread::FastMutex> _recvQueue;
};
diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp
index 2551f1d07da..9e1737d13e1 100644
--- a/src/game/WorldSocket.cpp
+++ b/src/game/WorldSocket.cpp
@@ -54,8 +54,37 @@
struct ServerPktHeader
{
- uint16 size;
- uint16 cmd;
+ /**
+ * size is the length of the payload _plus_ the length of the opcode
+ */
+ ServerPktHeader(uint32 size, uint16 cmd) : size(size)
+ {
+ uint8 headerIndex=0;
+ if(isLargePacket())
+ {
+ sLog.outDebug("initializing large server to client packet. Size: %u, cmd: %u", size, cmd);
+ header[headerIndex++] = 0x80|(0xFF &(size>>16));
+ }
+ header[headerIndex++] = 0xFF &(size>>8);
+ header[headerIndex++] = 0xFF &size;
+
+ header[headerIndex++] = 0xFF & cmd;
+ header[headerIndex++] = 0xFF & (cmd>>8);
+ }
+
+ uint8 getHeaderLength()
+ {
+ // cmd = 2 bytes, size= 2||3bytes
+ return 2+(isLargePacket()?3:2);
+ }
+
+ bool isLargePacket()
+ {
+ return size > 0x7FFF;
+ }
+
+ const uint32 size;
+ uint8 header[5];
};
struct ClientPktHeader
@@ -84,6 +113,9 @@ m_OverSpeedPings (0),
m_LastPingTime (ACE_Time_Value::zero)
{
reference_counting_policy ().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
+
+ msg_queue()->high_water_mark(8*1024*1024);
+ msg_queue()->low_water_mark(8*1024*1024);
}
WorldSocket::~WorldSocket (void)
@@ -97,10 +129,6 @@ WorldSocket::~WorldSocket (void)
closing_ = true;
peer ().close ();
-
- WorldPacket* pct;
- while (m_PacketQueue.dequeue_head (pct) == 0)
- delete pct;
}
bool WorldSocket::IsClosed (void) const
@@ -160,18 +188,35 @@ int WorldSocket::SendPacket (const WorldPacket& pct)
sWorldLog.Log ("\n\n");
}
- if (iSendPacket (pct) == -1)
+ ServerPktHeader header(pct.size()+2, pct.GetOpcode());
+ m_Crypt.EncryptSend ( header.header, header.getHeaderLength());
+
+ if (m_OutBuffer->space () >= pct.size () + header.getHeaderLength() && msg_queue()->is_empty())
+ {
+ // Put the packet on the buffer.
+ if (m_OutBuffer->copy ((char*) header.header, header.getHeaderLength()) == -1)
+ ACE_ASSERT (false);
+
+ if (!pct.empty ())
+ if (m_OutBuffer->copy ((char*) pct.contents (), pct.size ()) == -1)
+ ACE_ASSERT (false);
+ }
+ else
{
- WorldPacket* npct;
+ // Enqueue the packet.
+ ACE_Message_Block* mb;
+
+ ACE_NEW_RETURN(mb, ACE_Message_Block(pct.size () + header.getHeaderLength()), -1);
+
+ mb->copy((char*) header.header, header.getHeaderLength());
- ACE_NEW_RETURN (npct, WorldPacket (pct), -1);
+ if (!pct.empty ())
+ mb->copy((const char*)pct.contents(), pct.size ());
- // NOTE maybe check of the size of the queue can be good ?
- // to make it bounded instead of unbounded
- if (m_PacketQueue.enqueue_tail (npct) == -1)
+ if(msg_queue()->enqueue_tail(mb,(ACE_Time_Value*)&ACE_Time_Value::zero) == -1)
{
- delete npct;
- sLog.outError ("WorldSocket::SendPacket: m_PacketQueue.enqueue_tail failed");
+ sLog.outError("WorldSocket::SendPacket enqueue_tail");
+ mb->release();
return -1;
}
}
@@ -296,7 +341,7 @@ int WorldSocket::handle_output (ACE_HANDLE)
const size_t send_len = m_OutBuffer->length ();
if (send_len == 0)
- return cancel_wakeup_output (Guard);
+ return handle_output_queue (Guard);
#ifdef MSG_NOSIGNAL
ssize_t n = peer ().send (m_OutBuffer->rd_ptr (), send_len, MSG_NOSIGNAL);
@@ -326,15 +371,73 @@ int WorldSocket::handle_output (ACE_HANDLE)
{
m_OutBuffer->reset ();
- if (!iFlushPacketQueue ())
- return cancel_wakeup_output (Guard);
- else
- return schedule_wakeup_output (Guard);
+ return handle_output_queue (Guard);
}
ACE_NOTREACHED (return 0);
}
+int WorldSocket::handle_output_queue (GuardType& g)
+{
+ if(msg_queue()->is_empty())
+ return cancel_wakeup_output(g);
+
+ ACE_Message_Block *mblk;
+
+ if(msg_queue()->dequeue_head(mblk, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1)
+ {
+ sLog.outError("WorldSocket::handle_output_queue dequeue_head");
+ return -1;
+ }
+
+ const size_t send_len = mblk->length ();
+
+#ifdef MSG_NOSIGNAL
+ ssize_t n = peer ().send (mblk->rd_ptr (), send_len, MSG_NOSIGNAL);
+#else
+ ssize_t n = peer ().send (mblk->rd_ptr (), send_len);
+#endif // MSG_NOSIGNAL
+
+ if (n == 0)
+ {
+ mblk->release();
+
+ return -1;
+ }
+ else if (n == -1)
+ {
+ if (errno == EWOULDBLOCK || errno == EAGAIN)
+ {
+ msg_queue()->enqueue_head(mblk, (ACE_Time_Value*) &ACE_Time_Value::zero);
+ return schedule_wakeup_output (g);
+ }
+
+ mblk->release();
+ return -1;
+ }
+ else if (n < send_len) //now n > 0
+ {
+ mblk->rd_ptr (static_cast<size_t> (n));
+
+ if (msg_queue()->enqueue_head(mblk, (ACE_Time_Value*) &ACE_Time_Value::zero) == -1)
+ {
+ sLog.outError("WorldSocket::handle_output_queue enqueue_head");
+ mblk->release();
+ return -1;
+ }
+
+ return schedule_wakeup_output (g);
+ }
+ else //now n == send_len
+ {
+ mblk->release();
+
+ return msg_queue()->is_empty() ? cancel_wakeup_output(g) : ACE_Event_Handler::WRITE_MASK;
+ }
+
+ ACE_NOTREACHED(return -1);
+}
+
int WorldSocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask)
{
// Critical section
@@ -362,10 +465,15 @@ int WorldSocket::Update (void)
if (closing_)
return -1;
- if (m_OutActive || m_OutBuffer->length () == 0)
+ if (m_OutActive || (m_OutBuffer->length () == 0 && msg_queue()->is_empty()))
return 0;
- return handle_output (get_handle ());
+ int ret;
+ do
+ ret = handle_output (get_handle ());
+ while( ret > 0 );
+
+ return ret;
}
int WorldSocket::handle_input_header (void)
@@ -639,7 +747,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
// NOTE: ATM the socket is singlethread, have this in mind ...
uint8 digest[20];
uint32 clientSeed;
- uint32 unk2;
+ uint32 unk2, unk3;
uint32 BuiltNumberClient;
uint32 id, security;
//uint8 expansion = 0;
@@ -661,6 +769,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
recvPacket >> BuiltNumberClient; // for now no use
recvPacket >> unk2;
recvPacket >> account;
+ recvPacket >> unk3;
if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20))
{
@@ -684,17 +793,17 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
QueryResult *result =
LoginDatabase.PQuery ("SELECT "
- "id, " //0
- "gmlevel, " //1
- "sessionkey, " //2
- "last_ip, " //3
- "locked, " //4
- "sha_pass_hash, " //5
- "v, " //6
- "s, " //7
- "expansion, " //8
- "mutetime, " //9
- "locale " //10
+ "id, " //0
+ "gmlevel, " //1
+ "sessionkey, " //2
+ "last_ip, " //3
+ "locked, " //4
+ "sha_pass_hash, " //5
+ "v, " //6
+ "s, " //7
+ "expansion, " //8
+ "mutetime, " //9
+ "locale " //10
"FROM account "
"WHERE username = '%s'",
safe_account.c_str ());
@@ -788,6 +897,9 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
id = fields[0].GetUInt32 ();
security = fields[1].GetUInt16 ();
+ if(security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB
+ security = SEC_ADMINISTRATOR;
+
K.SetHexStr (fields[2].GetString ());
time_t mutetime = time_t (fields[9].GetUInt64 ());
@@ -880,6 +992,8 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
m_Crypt.SetKey (&K);
m_Crypt.Init ();
+ m_Session->LoadAccountData();
+
// In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec
ACE_OS::sleep (ACE_Time_Value (0, 10000));
@@ -961,25 +1075,19 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket)
return SendPacket (packet);
}
-int WorldSocket::iSendPacket (const WorldPacket& pct)
+/*int WorldSocket::iSendPacket (const WorldPacket& pct)
{
- if (m_OutBuffer->space () < pct.size () + sizeof (ServerPktHeader))
+ ServerPktHeader header(pct.size()+2, pct.GetOpcode());
+ if (m_OutBuffer->space () < pct.size () + header.getHeaderLength())
{
errno = ENOBUFS;
return -1;
}
- ServerPktHeader header;
- header.cmd = pct.GetOpcode ();
- EndianConvert(header.cmd);
+ m_Crypt.EncryptSend ( header.header, header.getHeaderLength());
- header.size = (uint16) pct.size () + 2;
- EndianConvertReverse(header.size);
-
- m_Crypt.EncryptSend ((uint8*) & header, sizeof (header));
-
- if (m_OutBuffer->copy ((char*) & header, sizeof (header)) == -1)
+ if (m_OutBuffer->copy ((char*) header.header, header.getHeaderLength()) == -1)
ACE_ASSERT (false);
if (!pct.empty ())
@@ -1015,4 +1123,4 @@ bool WorldSocket::iFlushPacketQueue ()
}
return haveone;
-}
+}*/
diff --git a/src/game/WorldSocket.h b/src/game/WorldSocket.h
index 973cbb07cb0..21c1bf3f1e2 100644
--- a/src/game/WorldSocket.h
+++ b/src/game/WorldSocket.h
@@ -103,9 +103,6 @@ class WorldSocket : protected WorldHandler
typedef ACE_Thread_Mutex LockType;
typedef ACE_Guard<LockType> GuardType;
- /// Queue for storing packets for which there is no space.
- typedef ACE_Unbounded_Queue< WorldPacket* > PacketQueueT;
-
/// Check if socket is closed.
bool IsClosed (void) const;
@@ -161,6 +158,9 @@ class WorldSocket : protected WorldHandler
int cancel_wakeup_output (GuardType& g);
int schedule_wakeup_output (GuardType& g);
+ /// Drain the queue if its not empty.
+ int handle_output_queue (GuardType& g);
+
/// process one incoming packet.
/// @param new_pct received packet ,note that you need to delete it.
int ProcessIncoming (WorldPacket* new_pct);
@@ -171,16 +171,6 @@ class WorldSocket : protected WorldHandler
/// Called by ProcessIncoming() on CMSG_PING.
int HandlePing (WorldPacket& recvPacket);
- /// Try to write WorldPacket to m_OutBuffer ,return -1 if no space
- /// Need to be called with m_OutBufferLock lock held
- int iSendPacket (const WorldPacket& pct);
-
- /// Flush m_PacketQueue if there are packets in it
- /// Need to be called with m_OutBufferLock lock held
- /// @return true if it wrote to the buffer ( AKA you need
- /// to mark the socket for output ).
- bool iFlushPacketQueue ();
-
private:
/// Time in which the last ping was received
ACE_Time_Value m_LastPingTime;
@@ -220,10 +210,6 @@ class WorldSocket : protected WorldHandler
/// Size of the m_OutBuffer.
size_t m_OutBufferSize;
- /// Here are stored packets for which there was no space on m_OutBuffer,
- /// this allows not-to kick player if its buffer is overflowed.
- PacketQueueT m_PacketQueue;
-
/// True if the socket is registered with the reactor for output
bool m_OutActive;
diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp
index daa8a2f8fa3..0492a85a8f4 100644
--- a/src/game/debugcmds.cpp
+++ b/src/game/debugcmds.cpp
@@ -63,6 +63,7 @@ bool ChatHandler::HandleDebugSpellFailCommand(const char* args)
uint8 failnum = (uint8)atoi(px);
WorldPacket data(SMSG_CAST_FAILED, 5);
+ data << uint8(0);
data << uint32(133);
data << uint8(failnum);
m_session->SendPacket(&data);
@@ -132,8 +133,12 @@ bool ChatHandler::HandleBuyErrorCommand(const char* args)
bool ChatHandler::HandleSendOpcodeCommand(const char* /*args*/)
{
Unit *unit = getSelectedUnit();
+ Player *player = NULL;
if (!unit || (unit->GetTypeId() != TYPEID_PLAYER))
- unit = m_session->GetPlayer();
+ player = m_session->GetPlayer();
+ else
+ player = (Player*)unit;
+ if(!unit) unit = player;
std::ifstream ifs("opcode.txt");
if(ifs.bad())
@@ -192,6 +197,14 @@ bool ChatHandler::HandleSendOpcodeCommand(const char* /*args*/)
{
data.append(unit->GetPackGUID());
}
+ else if(type == "myguid")
+ data.append(player->GetPackGUID());
+ else if(type == "pos")
+ {
+ data << unit->GetPositionX();
+ data << unit->GetPositionY();
+ data << unit->GetPositionZ();
+ }
else
{
sLog.outDebug("Sending opcode: unknown type '%s'", type.c_str());
@@ -201,7 +214,7 @@ bool ChatHandler::HandleSendOpcodeCommand(const char* /*args*/)
ifs.close();
sLog.outDebug("Sending opcode %u", data.GetOpcode());
data.hexlike();
- ((Player*)unit)->GetSession()->SendPacket(&data);
+ player->GetSession()->SendPacket(&data);
PSendSysMessage(LANG_COMMAND_OPCODESENT, data.GetOpcode(), unit->GetName());
return true;
}
@@ -570,3 +583,63 @@ bool ChatHandler::HandleDebugHostilRefList(const char * /*args*/)
SendSysMessage("End of hostil reference list.");
return true;
}
+
+bool ChatHandler::HandleSpawnVehicle(const char* args)
+{
+ if(!args)
+ return false;
+
+ char* e = strtok((char*)args, " ");
+ char* i = strtok(NULL, " ");
+
+ if (!e || !i)
+ return false;
+
+ uint32 entry = (uint32)atoi(e);
+ uint32 id = (uint32)atoi(i);
+
+ CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry);
+
+ if(!ci)
+ return false;
+
+ VehicleEntry const *ve = sVehicleStore.LookupEntry(id);
+
+ if(!ve)
+ return false;
+
+ Vehicle *v = new Vehicle;
+ Map *map = m_session->GetPlayer()->GetMap();
+ if(!v->Create(objmgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, entry, id, m_session->GetPlayer()->GetTeam()))
+ {
+ delete v;
+ return false;
+ }
+
+ float px, py, pz;
+ m_session->GetPlayer()->GetClosePoint(px, py, pz, m_session->GetPlayer()->GetObjectSize());
+
+ v->Relocate(px, py, pz, m_session->GetPlayer()->GetOrientation());
+
+ if(!v->IsPositionValid())
+ {
+ sLog.outError("ERROR: Vehicle (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
+ v->GetGUIDLow(), v->GetEntry(), v->GetPositionX(), v->GetPositionY());
+ delete v;
+ return false;
+ }
+
+ map->Add((Creature*)v);
+
+ return true;
+}
+
+bool ChatHandler::HandleSendLargePacketCommand(const char* args)
+{
+ const char* stuffingString = "This is a dummy string to push the packet's size beyond 128000 bytes. ";
+ std::ostringstream ss;
+ while(strlen(ss.str().c_str()) < 128000)
+ ss << stuffingString;
+ SendSysMessage(ss.str().c_str());
+ return true;
+}