aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/AI/CoreAI/TotemAI.cpp11
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp16
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.h1
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp28
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp39
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h16
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp84
-rw-r--r--src/server/game/Accounts/AccountMgr.h6
-rw-r--r--src/server/game/Accounts/BattlenetAccountMgr.cpp151
-rw-r--r--src/server/game/Accounts/BattlenetAccountMgr.h45
-rw-r--r--src/server/game/Accounts/RBAC.h14
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp2800
-rw-r--r--src/server/game/Achievements/AchievementMgr.h122
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp17
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.h2
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp15
-rw-r--r--src/server/game/Battlefield/Battlefield.h6
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.cpp9
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.h1
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.h2
-rw-r--r--src/server/game/Battlegrounds/Arena.cpp12
-rw-r--r--src/server/game/Battlegrounds/ArenaScore.h76
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.cpp124
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.h57
-rw-r--r--src/server/game/Battlegrounds/ArenaTeamMgr.cpp56
-rw-r--r--src/server/game/Battlegrounds/ArenaTeamMgr.h2
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp173
-rw-r--r--src/server/game/Battlegrounds/Battleground.h23
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp564
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.h14
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.cpp13
-rw-r--r--src/server/game/Battlegrounds/BattlegroundScore.h81
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.h10
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.h16
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp36
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundBFG.h63
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.h8
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.h10
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp13
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.h10
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp36
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundTP.h63
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp6
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.h10
-rw-r--r--src/server/game/CMakeLists.txt1
-rw-r--r--src/server/game/Calendar/CalendarMgr.cpp8
-rw-r--r--src/server/game/Calendar/CalendarMgr.h3
-rw-r--r--src/server/game/Chat/Channels/ChannelMgr.cpp1
-rw-r--r--src/server/game/Chat/Chat.cpp30
-rw-r--r--src/server/game/Chat/Chat.h5
-rw-r--r--src/server/game/Chat/ChatLink.cpp30
-rw-r--r--src/server/game/Chat/ChatLink.h2
-rw-r--r--src/server/game/Combat/ThreatManager.cpp4
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp73
-rw-r--r--src/server/game/Conditions/ConditionMgr.h5
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp139
-rw-r--r--src/server/game/DataStores/DB2Stores.h35
-rw-r--r--src/server/game/DataStores/DB2Structure.h160
-rw-r--r--src/server/game/DataStores/DB2Utility.cpp171
-rw-r--r--src/server/game/DataStores/DB2Utility.h40
-rw-r--r--src/server/game/DataStores/DB2fmt.h27
-rw-r--r--src/server/game/DataStores/DBCEnums.h235
-rw-r--r--src/server/game/DataStores/DBCStores.cpp641
-rw-r--r--src/server/game/DataStores/DBCStores.h75
-rw-r--r--src/server/game/DataStores/DBCStructure.h1407
-rw-r--r--src/server/game/DataStores/DBCfmt.h189
-rw-r--r--src/server/game/DungeonFinding/LFG.h38
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp142
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.h64
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.cpp12
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.h4
-rw-r--r--src/server/game/DungeonFinding/LFGScripts.cpp2
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.cpp108
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.h46
-rw-r--r--src/server/game/Entities/Corpse/Corpse.cpp21
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp162
-rw-r--r--src/server/game/Entities/Creature/Creature.h74
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp220
-rw-r--r--src/server/game/Entities/Creature/GossipDef.h2
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.cpp10
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.cpp18
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.h2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp27
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h10
-rw-r--r--src/server/game/Entities/Item/Item.cpp378
-rw-r--r--src/server/game/Entities/Item/Item.h226
-rw-r--r--src/server/game/Entities/Item/ItemPrototype.h231
-rw-r--r--src/server/game/Entities/Object/Object.cpp556
-rw-r--r--src/server/game/Entities/Object/Object.h98
-rw-r--r--src/server/game/Entities/Object/ObjectDefines.h53
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateData.cpp97
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateData.h41
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp1388
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFieldFlags.h1
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFields.h902
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp69
-rw-r--r--src/server/game/Entities/Pet/Pet.h3
-rw-r--r--src/server/game/Entities/Player/Player.cpp5307
-rw-r--r--src/server/game/Entities/Player/Player.h752
-rw-r--r--src/server/game/Entities/Player/SocialMgr.cpp1
-rw-r--r--src/server/game/Entities/Totem/Totem.cpp16
-rw-r--r--src/server/game/Entities/Totem/Totem.h9
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp24
-rw-r--r--src/server/game/Entities/Transport/Transport.h2
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp419
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp3936
-rw-r--r--src/server/game/Entities/Unit/Unit.h278
-rw-r--r--[-rwxr-xr-x]src/server/game/Entities/Vehicle/Vehicle.cpp7
-rw-r--r--src/server/game/Entities/Vehicle/VehicleDefines.h24
-rw-r--r--src/server/game/Events/GameEventMgr.cpp11
-rw-r--r--src/server/game/Events/GameEventMgr.h1
-rw-r--r--src/server/game/Globals/ObjectAccessor.cpp10
-rw-r--r--src/server/game/Globals/ObjectAccessor.h1
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp2152
-rw-r--r--src/server/game/Globals/ObjectMgr.h132
-rw-r--r--src/server/game/Grids/GridDefines.h7
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.cpp8
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h140
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiersImpl.h101
-rw-r--r--src/server/game/Grids/ObjectGridLoader.cpp3
-rw-r--r--src/server/game/Grids/ObjectGridLoader.h1
-rw-r--r--src/server/game/Groups/Group.cpp62
-rw-r--r--src/server/game/Groups/Group.h58
-rw-r--r--src/server/game/Guilds/Guild.cpp1352
-rw-r--r--src/server/game/Guilds/Guild.h253
-rw-r--r--src/server/game/Guilds/GuildFinderMgr.cpp333
-rw-r--r--src/server/game/Guilds/GuildFinderMgr.h277
-rw-r--r--src/server/game/Guilds/GuildMgr.cpp206
-rw-r--r--src/server/game/Guilds/GuildMgr.h15
-rw-r--r--src/server/game/Handlers/ArenaTeamHandler.cpp73
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp176
-rw-r--r--src/server/game/Handlers/AuthHandler.cpp26
-rw-r--r--src/server/game/Handlers/BattleGroundHandler.cpp546
-rw-r--r--src/server/game/Handlers/BattlefieldHandler.cpp273
-rw-r--r--src/server/game/Handlers/CalendarHandler.cpp9
-rw-r--r--src/server/game/Handlers/ChannelHandler.cpp100
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp306
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp494
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp557
-rw-r--r--src/server/game/Handlers/GuildFinderHandler.cpp442
-rw-r--r--src/server/game/Handlers/GuildHandler.cpp661
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp816
-rw-r--r--src/server/game/Handlers/LFGHandler.cpp565
-rw-r--r--src/server/game/Handlers/LootHandler.cpp13
-rw-r--r--src/server/game/Handlers/MailHandler.cpp148
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp459
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp216
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp89
-rw-r--r--src/server/game/Handlers/PetHandler.cpp42
-rw-r--r--src/server/game/Handlers/PetitionsHandler.cpp12
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp97
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp142
-rw-r--r--src/server/game/Handlers/ReferAFriendHandler.cpp3
-rw-r--r--src/server/game/Handlers/SkillHandler.cpp36
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp96
-rw-r--r--src/server/game/Handlers/TaxiHandler.cpp13
-rw-r--r--src/server/game/Handlers/TicketHandler.cpp4
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp245
-rw-r--r--src/server/game/Handlers/VehicleHandler.cpp50
-rw-r--r--src/server/game/Handlers/VoiceChatHandler.cpp4
-rw-r--r--src/server/game/Handlers/VoidStorageHandler.cpp619
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.cpp4
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.h8
-rw-r--r--src/server/game/Instances/InstanceScript.cpp15
-rw-r--r--src/server/game/Instances/InstanceScript.h22
-rw-r--r--src/server/game/Loot/LootMgr.cpp26
-rw-r--r--src/server/game/Mails/Mail.h16
-rw-r--r--src/server/game/Maps/Map.cpp55
-rw-r--r--src/server/game/Maps/Map.h2
-rw-r--r--src/server/game/Maps/MapManager.cpp2
-rw-r--r--src/server/game/Maps/TransportMgr.cpp15
-rw-r--r--src/server/game/Maps/TransportMgr.h2
-rw-r--r--src/server/game/Miscellaneous/Formulas.h23
-rw-r--r--src/server/game/Miscellaneous/Language.h25
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h1338
-rw-r--r--src/server/game/Movement/MotionMaster.cpp5
-rw-r--r--[-rwxr-xr-x]src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp17
-rwxr-xr-x[-rw-r--r--]src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp0
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp7
-rw-r--r--src/server/game/Movement/MovementStructures.cpp5451
-rw-r--r--src/server/game/Movement/MovementStructures.h158
-rw-r--r--src/server/game/Movement/PathGenerator.cpp2
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.cpp4
-rw-r--r--src/server/game/Movement/Spline/MoveSplineFlag.h102
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.cpp28
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.h16
-rw-r--r--src/server/game/Movement/Spline/MovementPacketBuilder.cpp127
-rw-r--r--src/server/game/Movement/Spline/MovementPacketBuilder.h18
-rw-r--r--src/server/game/Movement/Spline/MovementTypedefs.h2
-rw-r--r--src/server/game/Movement/Spline/MovementUtil.cpp162
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.h5
-rw-r--r--src/server/game/Quests/QuestDef.cpp202
-rw-r--r--src/server/game/Quests/QuestDef.h85
-rw-r--r--src/server/game/Reputation/ReputationMgr.cpp3
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp77
-rw-r--r--src/server/game/Scripting/ScriptLoader.h1
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp6
-rw-r--r--src/server/game/Scripting/ScriptMgr.h13
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2950
-rw-r--r--src/server/game/Server/Protocol/Opcodes.h2738
-rw-r--r--src/server/game/Server/Protocol/PacketLog.cpp2
-rw-r--r--src/server/game/Server/WorldPacket.cpp106
-rw-r--r--src/server/game/Server/WorldPacket.h75
-rw-r--r--src/server/game/Server/WorldSession.cpp496
-rw-r--r--src/server/game/Server/WorldSession.h146
-rw-r--r--src/server/game/Server/WorldSocket.cpp170
-rw-r--r--src/server/game/Server/WorldSocket.h4
-rw-r--r--src/server/game/Spells/Auras/SpellAuraDefines.h98
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp659
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h12
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp257
-rw-r--r--src/server/game/Spells/Spell.cpp706
-rw-r--r--src/server/game/Spells/Spell.h19
-rw-r--r--src/server/game/Spells/SpellEffects.cpp608
-rw-r--r--src/server/game/Spells/SpellInfo.cpp599
-rw-r--r--src/server/game/Spells/SpellInfo.h67
-rw-r--r--src/server/game/Spells/SpellMgr.cpp343
-rw-r--r--src/server/game/Spells/SpellMgr.h44
-rw-r--r--src/server/game/Texts/CreatureTextMgr.cpp1
-rw-r--r--src/server/game/Texts/CreatureTextMgr.h2
-rw-r--r--src/server/game/Tickets/TicketMgr.cpp5
-rw-r--r--src/server/game/Tools/PlayerDump.cpp19
-rw-r--r--src/server/game/Tools/PlayerDump.h3
-rw-r--r--src/server/game/Warden/WardenWin.cpp4
-rw-r--r--src/server/game/Weather/Weather.cpp1
-rw-r--r--src/server/game/Weather/Weather.h2
-rw-r--r--src/server/game/Weather/WeatherMgr.cpp1
-rw-r--r--src/server/game/World/World.cpp299
-rw-r--r--src/server/game/World/World.h62
233 files changed, 35984 insertions, 18943 deletions
diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp
index 245a47dbe64..27ecc2716f3 100644
--- a/src/server/game/AI/CoreAI/TotemAI.cpp
+++ b/src/server/game/AI/CoreAI/TotemAI.cpp
@@ -95,15 +95,4 @@ void TotemAI::UpdateAI(uint32 /*diff*/)
void TotemAI::AttackStart(Unit* /*victim*/)
{
- // Sentry totem sends ping on attack
- if (me->GetEntry() == SENTRY_TOTEM_ENTRY)
- if (Unit* owner = me->GetOwner())
- if (Player* player = owner->ToPlayer())
- {
- WorldPacket data(MSG_MINIMAP_PING, (8+4+4));
- data << me->GetGUID();
- data << me->GetPositionX();
- data << me->GetPositionY();
- player->SendDirectMessage(&data);
- }
}
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index 06820b03218..614f5826824 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -234,7 +234,7 @@ SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mec
continue;
//Continue if we don't have the mana to actually cast this spell
- if (tempSpell->ManaCost > me->GetPower(Powers(tempSpell->PowerType)))
+ if (tempSpell->ManaCost > (uint32)me->GetPower(Powers(tempSpell->PowerType)))
continue;
//Check if the spell meets our range requirements
@@ -586,6 +586,20 @@ void BossAI::UpdateAI(uint32 diff)
DoMeleeAttackIfReady();
}
+void BossAI::_DespawnAtEvade()
+{
+ uint32 corpseDelay = me->GetCorpseDelay();
+ uint32 respawnDelay = me->GetRespawnDelay();
+
+ me->SetCorpseDelay(1);
+ me->SetRespawnDelay(29);
+
+ me->DespawnOrUnsummon();
+
+ me->SetCorpseDelay(corpseDelay);
+ me->SetRespawnDelay(respawnDelay);
+}
+
// WorldBossAI - for non-instanced bosses
WorldBossAI::WorldBossAI(Creature* creature) :
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
index c9f7f342183..e03bbd8c6a2 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
@@ -360,6 +360,7 @@ class BossAI : public ScriptedAI
void _EnterCombat();
void _JustDied();
void _JustReachedHome() { me->setActive(false); }
+ void _DespawnAtEvade();
bool CheckInRoom()
{
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 02298684584..d4b41f529a9 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -1045,7 +1045,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
delete targets;
break;
}
- case SMART_ACTION_SET_INGAME_PHASE_MASK:
+ case SMART_ACTION_SET_INGAME_PHASE_ID:
{
ObjectList* targets = GetTargets(e, unit);
@@ -1053,12 +1053,23 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
- {
- if (IsUnit(*itr))
- (*itr)->ToUnit()->SetPhaseMask(e.action.ingamePhaseMask.mask, true);
- else if (IsGameObject(*itr))
- (*itr)->ToGameObject()->SetPhaseMask(e.action.ingamePhaseMask.mask, true);
- }
+ (*itr)->SetInPhase(e.action.ingamePhaseId.id, true, e.action.ingamePhaseId.apply == 1);
+
+ delete targets;
+ break;
+ }
+ case SMART_ACTION_SET_INGAME_PHASE_GROUP:
+ {
+ ObjectList* targets = GetTargets(e, unit);
+
+ if (!targets)
+ break;
+
+ std::set<uint32> const& phases = GetPhasesForGroup(e.action.ingamePhaseGroup.groupId);
+
+ for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
+ for (auto phase : phases)
+ (*itr)->SetInPhase(phase, true, e.action.ingamePhaseGroup.apply == 1);
delete targets;
break;
@@ -1392,8 +1403,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
if (e.GetTargetType() == SMART_TARGET_SELF)
- me->SetFacingTo((me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && me->GetTransGUID() ?
- me->GetTransportHomePosition() : me->GetHomePosition()).GetOrientation());
+ me->SetFacingTo((me->GetTransport() ? me->GetTransportHomePosition() : me->GetHomePosition()).GetOrientation());
else if (e.GetTargetType() == SMART_TARGET_POSITION)
me->SetFacingTo(e.target.o);
else if (ObjectList* targets = GetTargets(e, unit))
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 2e8453904a1..af24298c60d 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -1008,6 +1008,44 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
}
break;
}
+ case SMART_ACTION_SET_INGAME_PHASE_ID:
+ {
+ uint32 phaseId = e.action.ingamePhaseId.id;
+ uint32 apply = e.action.ingamePhaseId.apply;
+
+ if (apply != 0 && apply != 1)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_SET_INGAME_PHASE_ID uses invalid apply value %u (Should be 0 or 1) for creature %u, skipped", apply, e.entryOrGuid);
+ return false;
+ }
+
+ PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseId);
+ if (!phase)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_SET_INGAME_PHASE_ID uses invalid phaseid %u for creature %u, skipped", phaseId, e.entryOrGuid);
+ return false;
+ }
+ break;
+ }
+ case SMART_ACTION_SET_INGAME_PHASE_GROUP:
+ {
+ uint32 phaseGroup = e.action.ingamePhaseGroup.groupId;
+ uint32 apply = e.action.ingamePhaseGroup.apply;
+
+ if (apply != 0 && apply != 1)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_SET_INGAME_PHASE_GROUP uses invalid apply value %u (Should be 0 or 1) for creature %u, skipped", apply, e.entryOrGuid);
+ return false;
+ }
+
+ PhaseGroupEntry const* phase = sPhaseGroupStore.LookupEntry(phaseGroup);
+ if (!phase)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_SET_INGAME_PHASE_GROUP uses invalid phase group id %u for creature %u, skipped", phaseGroup, e.entryOrGuid);
+ return false;
+ }
+ break;
+ }
case SMART_ACTION_FOLLOW:
case SMART_ACTION_SET_ORIENTATION:
case SMART_ACTION_STORE_TARGET_LIST:
@@ -1037,7 +1075,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_SET_RUN:
case SMART_ACTION_SET_SWIM:
case SMART_ACTION_FORCE_DESPAWN:
- case SMART_ACTION_SET_INGAME_PHASE_MASK:
case SMART_ACTION_SET_UNIT_FLAG:
case SMART_ACTION_REMOVE_UNIT_FLAG:
case SMART_ACTION_PLAYMOVIE:
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index d4afba54498..f09e16268c1 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -23,6 +23,7 @@
#include "CreatureAI.h"
#include "Unit.h"
#include "Spell.h"
+#include "DB2Stores.h"
//#include "SmartScript.h"
//#include "SmartAI.h"
@@ -432,7 +433,7 @@ enum SMART_ACTION
SMART_ACTION_THREAT_SINGLE_PCT = 13, // Threat%
SMART_ACTION_THREAT_ALL_PCT = 14, // Threat%
SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS = 15, // QuestID
- SMART_ACTION_UNUSED_16 = 16, // UNUSED
+ SMART_ACTION_SET_INGAME_PHASE_GROUP = 16, // phaseGroupId, apply
SMART_ACTION_SET_EMOTE_STATE = 17, // emoteID
SMART_ACTION_SET_UNIT_FLAG = 18, // Flags (may be more than one field OR'd together), Target
SMART_ACTION_REMOVE_UNIT_FLAG = 19, // Flags (may be more than one field OR'd together), Target
@@ -460,7 +461,7 @@ enum SMART_ACTION
SMART_ACTION_FORCE_DESPAWN = 41, // timer
SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL = 42, // MinHpValue(+pct, -flat)
SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to dismount)
- SMART_ACTION_SET_INGAME_PHASE_MASK = 44, // mask
+ SMART_ACTION_SET_INGAME_PHASE_ID = 44, // PhaseId, apply
SMART_ACTION_SET_DATA = 45, // Field, Data (only creature @todo)
SMART_ACTION_MOVE_FORWARD = 46, // distance
SMART_ACTION_SET_VISIBILITY = 47, // on/off
@@ -727,8 +728,15 @@ struct SmartAction
struct
{
- uint32 mask;
- } ingamePhaseMask;
+ uint32 id;
+ uint32 apply;
+ } ingamePhaseId;
+
+ struct
+ {
+ uint32 groupId;
+ uint32 apply;
+ } ingamePhaseGroup;
struct
{
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index ff30fe7ba35..c7437909f05 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -33,17 +33,17 @@ AccountMgr::~AccountMgr()
ClearRBAC();
}
-AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password, std::string email = "")
+AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password, std::string email /*= ""*/)
{
if (utf8length(username) > MAX_ACCOUNT_STR)
- return AOR_NAME_TOO_LONG; // username's too long
+ return AccountOpResult::AOR_NAME_TOO_LONG; // username's too long
- normalizeString(username);
- normalizeString(password);
- normalizeString(email);
+ Utf8ToUpperOnlyLatin(username);
+ Utf8ToUpperOnlyLatin(password);
+ Utf8ToUpperOnlyLatin(email);
if (GetId(username))
- return AOR_NAME_ALREADY_EXIST; // username does already exist
+ return AccountOpResult::AOR_NAME_ALREADY_EXIST; // username does already exist
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT);
@@ -57,7 +57,7 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS_INIT);
LoginDatabase.Execute(stmt);
- return AOR_OK; // everything's fine
+ return AccountOpResult::AOR_OK; // everything's fine
}
AccountOpResult AccountMgr::DeleteAccount(uint32 accountId)
@@ -68,7 +68,7 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accountId)
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (!result)
- return AOR_NAME_NOT_EXIST;
+ return AccountOpResult::AOR_NAME_NOT_EXIST;
// Obtain accounts characters
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID);
@@ -129,7 +129,7 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accountId)
LoginDatabase.CommitTransaction(trans);
- return AOR_OK;
+ return AccountOpResult::AOR_OK;
}
AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword)
@@ -140,16 +140,16 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUser
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (!result)
- return AOR_NAME_NOT_EXIST;
+ return AccountOpResult::AOR_NAME_NOT_EXIST;
if (utf8length(newUsername) > MAX_ACCOUNT_STR)
- return AOR_NAME_TOO_LONG;
+ return AccountOpResult::AOR_NAME_TOO_LONG;
if (utf8length(newPassword) > MAX_ACCOUNT_STR)
- return AOR_PASS_TOO_LONG;
+ return AccountOpResult::AOR_PASS_TOO_LONG;
- normalizeString(newUsername);
- normalizeString(newPassword);
+ Utf8ToUpperOnlyLatin(newUsername);
+ Utf8ToUpperOnlyLatin(newPassword);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_USERNAME);
@@ -159,7 +159,7 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUser
LoginDatabase.Execute(stmt);
- return AOR_OK;
+ return AccountOpResult::AOR_OK;
}
AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPassword)
@@ -169,17 +169,17 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPass
if (!GetName(accountId, username))
{
sScriptMgr->OnFailedPasswordChange(accountId);
- return AOR_NAME_NOT_EXIST; // account doesn't exist
+ return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist
}
if (utf8length(newPassword) > MAX_ACCOUNT_STR)
{
sScriptMgr->OnFailedPasswordChange(accountId);
- return AOR_PASS_TOO_LONG;
+ return AccountOpResult::AOR_PASS_TOO_LONG;
}
- normalizeString(username);
- normalizeString(newPassword);
+ Utf8ToUpperOnlyLatin(username);
+ Utf8ToUpperOnlyLatin(newPassword);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_PASSWORD);
@@ -197,7 +197,7 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPass
LoginDatabase.Execute(stmt);
sScriptMgr->OnPasswordChange(accountId);
- return AOR_OK;
+ return AccountOpResult::AOR_OK;
}
AccountOpResult AccountMgr::ChangeEmail(uint32 accountId, std::string newEmail)
@@ -207,17 +207,17 @@ AccountOpResult AccountMgr::ChangeEmail(uint32 accountId, std::string newEmail)
if (!GetName(accountId, username))
{
sScriptMgr->OnFailedEmailChange(accountId);
- return AOR_NAME_NOT_EXIST; // account doesn't exist
+ return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist
}
if (utf8length(newEmail) > MAX_EMAIL_STR)
{
sScriptMgr->OnFailedEmailChange(accountId);
- return AOR_EMAIL_TOO_LONG;
+ return AccountOpResult::AOR_EMAIL_TOO_LONG;
}
- normalizeString(username);
- normalizeString(newEmail);
+ Utf8ToUpperOnlyLatin(username);
+ Utf8ToUpperOnlyLatin(newEmail);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_EMAIL);
@@ -227,7 +227,7 @@ AccountOpResult AccountMgr::ChangeEmail(uint32 accountId, std::string newEmail)
LoginDatabase.Execute(stmt);
sScriptMgr->OnEmailChange(accountId);
- return AOR_OK;
+ return AccountOpResult::AOR_OK;
}
AccountOpResult AccountMgr::ChangeRegEmail(uint32 accountId, std::string newEmail)
@@ -235,19 +235,16 @@ AccountOpResult AccountMgr::ChangeRegEmail(uint32 accountId, std::string newEmai
std::string username;
if (!GetName(accountId, username))
- {
- sScriptMgr->OnFailedEmailChange(accountId);
- return AOR_NAME_NOT_EXIST; // account doesn't exist
- }
+ return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist
if (utf8length(newEmail) > MAX_EMAIL_STR)
{
sScriptMgr->OnFailedEmailChange(accountId);
- return AOR_EMAIL_TOO_LONG;
+ return AccountOpResult::AOR_EMAIL_TOO_LONG;
}
- normalizeString(username);
- normalizeString(newEmail);
+ Utf8ToUpperOnlyLatin(username);
+ Utf8ToUpperOnlyLatin(newEmail);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_REG_EMAIL);
@@ -257,7 +254,7 @@ AccountOpResult AccountMgr::ChangeRegEmail(uint32 accountId, std::string newEmai
LoginDatabase.Execute(stmt);
sScriptMgr->OnEmailChange(accountId);
- return AOR_OK;
+ return AccountOpResult::AOR_OK;
}
uint32 AccountMgr::GetId(std::string const& username)
@@ -325,8 +322,8 @@ bool AccountMgr::CheckPassword(uint32 accountId, std::string password)
if (!GetName(accountId, username))
return false;
- normalizeString(username);
- normalizeString(password);
+ Utf8ToUpperOnlyLatin(username);
+ Utf8ToUpperOnlyLatin(password);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_CHECK_PASSWORD);
stmt->setUInt32(0, accountId);
@@ -344,8 +341,8 @@ bool AccountMgr::CheckEmail(uint32 accountId, std::string newEmail)
if (!GetEmail(accountId, oldEmail))
return false;
- normalizeString(oldEmail);
- normalizeString(newEmail);
+ Utf8ToUpperOnlyLatin(oldEmail);
+ Utf8ToUpperOnlyLatin(newEmail);
if (strcmp(oldEmail.c_str(), newEmail.c_str()) == 0)
return true;
@@ -363,19 +360,6 @@ uint32 AccountMgr::GetCharactersCount(uint32 accountId)
return (result) ? (*result)[0].GetUInt64() : 0;
}
-bool AccountMgr::normalizeString(std::string& utf8String)
-{
- wchar_t buffer[MAX_ACCOUNT_STR+1];
-
- size_t maxLength = MAX_ACCOUNT_STR;
- if (!Utf8toWStr(utf8String, buffer, maxLength))
- return false;
-
- std::transform(&buffer[0], buffer+maxLength, &buffer[0], wcharToUpperOnlyLatin);
-
- return WStrToUtf8(buffer, maxLength, utf8String);
-}
-
std::string AccountMgr::CalculateShaPassHash(std::string const& name, std::string const& password)
{
SHA1Hash sha;
diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h
index c4b4bd93728..add00ec7feb 100644
--- a/src/server/game/Accounts/AccountMgr.h
+++ b/src/server/game/Accounts/AccountMgr.h
@@ -21,7 +21,7 @@
#include "RBAC.h"
-enum AccountOpResult
+enum class AccountOpResult : uint8
{
AOR_OK,
AOR_NAME_TOO_LONG,
@@ -39,6 +39,7 @@ enum PasswordChangeSecurity
PW_RBAC
};
+#define MAX_PASS_STR 16
#define MAX_ACCOUNT_STR 16
#define MAX_EMAIL_STR 64
@@ -61,7 +62,7 @@ class AccountMgr
return &instance;
}
- AccountOpResult CreateAccount(std::string username, std::string password, std::string email);
+ AccountOpResult CreateAccount(std::string username, std::string password, std::string email = "");
static AccountOpResult DeleteAccount(uint32 accountId);
static AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword);
static AccountOpResult ChangePassword(uint32 accountId, std::string newPassword);
@@ -78,7 +79,6 @@ class AccountMgr
static uint32 GetCharactersCount(uint32 accountId);
static std::string CalculateShaPassHash(std::string const& name, std::string const& password);
- static bool normalizeString(std::string& utf8String);
static bool IsPlayerAccount(uint32 gmlevel);
static bool IsAdminAccount(uint32 gmlevel);
static bool IsConsoleAccount(uint32 gmlevel);
diff --git a/src/server/game/Accounts/BattlenetAccountMgr.cpp b/src/server/game/Accounts/BattlenetAccountMgr.cpp
new file mode 100644
index 00000000000..23c1b7cdd61
--- /dev/null
+++ b/src/server/game/Accounts/BattlenetAccountMgr.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "AccountMgr.h"
+#include "BattlenetAccountMgr.h"
+#include "DatabaseEnv.h"
+#include "Util.h"
+#include "SHA256.h"
+
+AccountOpResult Battlenet::AccountMgr::CreateBattlenetAccount(std::string email, std::string password)
+{
+ if (utf8length(email) > MAX_BNET_EMAIL_STR)
+ return AccountOpResult::AOR_NAME_TOO_LONG;
+
+ if (utf8length(password) > MAX_PASS_STR)
+ return AccountOpResult::AOR_PASS_TOO_LONG;
+
+ Utf8ToUpperOnlyLatin(email);
+ Utf8ToUpperOnlyLatin(password);
+
+ if (GetId(email))
+ return AccountOpResult::AOR_NAME_ALREADY_EXIST;
+
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_ACCOUNT);
+ stmt->setString(0, email);
+ stmt->setString(1, CalculateShaPassHash(email, password));
+ LoginDatabase.Execute(stmt);
+
+ return AccountOpResult::AOR_OK;
+}
+
+AccountOpResult Battlenet::AccountMgr::ChangePassword(uint32 accountId, std::string newPassword)
+{
+ std::string username;
+ if (!GetName(accountId, username))
+ return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist
+
+ Utf8ToUpperOnlyLatin(username);
+ Utf8ToUpperOnlyLatin(newPassword);
+ if (utf8length(newPassword) > MAX_PASS_STR)
+ return AccountOpResult::AOR_PASS_TOO_LONG;
+
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_PASSWORD);
+ stmt->setString(0, CalculateShaPassHash(username, newPassword));
+ stmt->setUInt32(1, accountId);
+ LoginDatabase.Execute(stmt);
+
+ return AccountOpResult::AOR_OK;
+}
+
+uint32 Battlenet::AccountMgr::GetId(std::string const& username)
+{
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_EMAIL);
+ stmt->setString(0, username);
+ if (PreparedQueryResult result = LoginDatabase.Query(stmt))
+ return (*result)[0].GetUInt32();
+
+ return 0;
+}
+
+uint32 Battlenet::AccountMgr::GetIdByGameAccount(uint32 gameAccountId)
+{
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT);
+ stmt->setUInt32(0, gameAccountId);
+ if (PreparedQueryResult result = LoginDatabase.Query(stmt))
+ return (*result)[0].GetUInt32();
+
+ return 0;
+}
+
+bool Battlenet::AccountMgr::GetName(uint32 accountId, std::string& name)
+{
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_EMAIL_BY_ID);
+ stmt->setUInt32(0, accountId);
+ if (PreparedQueryResult result = LoginDatabase.Query(stmt))
+ {
+ name = (*result)[0].GetString();
+ return true;
+ }
+
+ return false;
+}
+
+bool Battlenet::AccountMgr::CheckPassword(uint32 accountId, std::string password)
+{
+ std::string username;
+
+ if (!GetName(accountId, username))
+ return false;
+
+ Utf8ToUpperOnlyLatin(username);
+ Utf8ToUpperOnlyLatin(password);
+
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHECK_PASSWORD);
+ stmt->setUInt32(0, accountId);
+ stmt->setString(1, CalculateShaPassHash(username, password));
+
+ return LoginDatabase.Query(stmt) != nullptr;
+}
+
+std::string Battlenet::AccountMgr::CalculateShaPassHash(std::string const& name, std::string const& password)
+{
+ SHA256Hash email;
+ email.UpdateData(name);
+ email.Finalize();
+
+ SHA256Hash sha;
+ sha.UpdateData(ByteArrayToHexStr(email.GetDigest(), email.GetLength()));
+ sha.UpdateData(":");
+ sha.UpdateData(password);
+ sha.Finalize();
+
+ return ByteArrayToHexStr(sha.GetDigest(), sha.GetLength(), true);
+}
+
+bool Battlenet::AccountMgr::GetAccountIdAndIndex(std::string const& account, uint32* battlenetAccountId, uint8* battlenetAccountIndex)
+{
+ Tokenizer tokens(account, '#');
+ if (tokens.size() != 2)
+ return false;
+
+ if (!battlenetAccountId)
+ return false;
+
+ *battlenetAccountId = atol(tokens[0]);
+ if (!*battlenetAccountId)
+ return false;
+
+ if (battlenetAccountIndex)
+ {
+ *battlenetAccountIndex = atol(tokens[1]);
+ if (!*battlenetAccountIndex)
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/server/game/Accounts/BattlenetAccountMgr.h b/src/server/game/Accounts/BattlenetAccountMgr.h
new file mode 100644
index 00000000000..c41a54189e5
--- /dev/null
+++ b/src/server/game/Accounts/BattlenetAccountMgr.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BattlenetAccountMgr_h__
+#define BattlenetAccountMgr_h__
+
+#include "Define.h"
+#include <string>
+
+enum class AccountOpResult : uint8;
+
+#define MAX_BNET_EMAIL_STR 320
+
+namespace Battlenet
+{
+ namespace AccountMgr
+ {
+ AccountOpResult CreateBattlenetAccount(std::string email, std::string password);
+ AccountOpResult ChangePassword(uint32 accountId, std::string newPassword);
+ bool CheckPassword(uint32 accountId, std::string password);
+
+ uint32 GetId(std::string const& username);
+ bool GetName(uint32 accountId, std::string& name);
+ uint32 GetIdByGameAccount(uint32 gameAccountId);
+
+ std::string CalculateShaPassHash(std::string const& name, std::string const& password);
+ bool GetAccountIdAndIndex(std::string const& account, uint32* battlenetAccountId, uint8* battlenetAccountIndex);
+ }
+}
+
+#endif // BattlenetAccountMgr_h__
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index f2637a5febc..d7cde6d1794 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -110,13 +110,13 @@ enum RBACPermissions
RBAC_PERM_COMMAND_RBAC_ACC_PERM_DENY = 204,
RBAC_PERM_COMMAND_RBAC_ACC_PERM_REVOKE = 205,
RBAC_PERM_COMMAND_RBAC_LIST = 206,
- // 207 - reuse
- // 208 - reuse
- // 209 - reuse
- // 210 - reuse
- // 211 - reuse
- // 212 - reuse
- // 213 - reuse
+ RBAC_PERM_COMMAND_BNET_ACCOUNT = 207,
+ RBAC_PERM_COMMAND_BNET_ACCOUNT_CREATE = 208,
+ RBAC_PERM_COMMAND_BNET_ACCOUNT_LOCK_COUNTRY = 209,
+ RBAC_PERM_COMMAND_BNET_ACCOUNT_LOCK_IP = 210,
+ RBAC_PERM_COMMAND_BNET_ACCOUNT_PASSWORD = 211,
+ RBAC_PERM_COMMAND_BNET_ACCOUNT_SET = 212,
+ RBAC_PERM_COMMAND_BNET_ACCOUNT_SET_PASSWORD = 213,
// 214 - reuse
// 215 - reuse
// 216 - reuse
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index d54b0572252..17db09eedfb 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -28,6 +28,7 @@
#include "DisableMgr.h"
#include "GameEventMgr.h"
#include "GridNotifiersImpl.h"
+#include "Group.h"
#include "Guild.h"
#include "GuildMgr.h"
#include "InstanceScript.h"
@@ -73,7 +74,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
return false;
}
- switch (criteria->requiredType)
+ switch (criteria->type)
{
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
@@ -103,7 +104,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
default:
if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT)
{
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` has data for non-supported criteria type (Entry: %u Type: %u), ignored.", criteria->ID, criteria->requiredType);
+ TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` has data for non-supported criteria type (Entry: %u Type: %u), ignored.", criteria->ID, criteria->type);
return false;
}
break;
@@ -113,27 +114,32 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
{
case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE:
case ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT:
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY:
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE:
if (!creature.id || !sObjectMgr->GetCreatureTemplate(creature.id))
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) has non-existing creature id in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, creature.id);
+ criteria->ID, criteria->type, dataType, creature.id);
return false;
}
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
+ if (!classRace.class_id && !classRace.race_id)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) must not have 0 in either value field, ignored.",
+ criteria->ID, criteria->type, dataType);
+ return false;
+ }
if (classRace.class_id && ((1 << (classRace.class_id-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) has non-existing class in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, classRace.class_id);
+ criteria->ID, criteria->type, dataType, classRace.class_id);
return false;
}
if (classRace.race_id && ((1 << (classRace.race_id-1)) & RACEMASK_ALL_PLAYABLE) == 0)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) has non-existing race in value2 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, classRace.race_id);
+ criteria->ID, criteria->type, dataType, classRace.race_id);
return false;
}
return true;
@@ -141,15 +147,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (health.percent < 1 || health.percent > 100)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH (%u) has wrong percent value in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, health.percent);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD:
- if (player_dead.own_team_flag > 1)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD (%u) has wrong boolean value1 (%u).",
- criteria->ID, criteria->requiredType, dataType, player_dead.own_team_flag);
+ criteria->ID, criteria->type, dataType, health.percent);
return false;
}
return true;
@@ -160,36 +158,28 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (!spellEntry)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has wrong spell id in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id);
+ criteria->ID, criteria->type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id);
return false;
}
if (aura.effect_idx >= 3)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has wrong spell effect index in value2 (%u), ignored.",
- criteria->ID, criteria->requiredType, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.effect_idx);
+ criteria->ID, criteria->type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.effect_idx);
return false;
}
if (!spellEntry->Effects[aura.effect_idx].ApplyAuraName)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has non-aura spell effect (ID: %u Effect: %u), ignores.",
- criteria->ID, criteria->requiredType, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id, aura.effect_idx);
+ criteria->ID, criteria->type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id, aura.effect_idx);
return false;
}
return true;
}
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA:
- if (!GetAreaEntryByAreaID(area.id))
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA (%u) has wrong area id in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, area.id);
- return false;
- }
- return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE:
if (value.compType >= COMP_TYPE_MAX)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE (%u) has wrong ComparisionType in value2 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, value.compType);
+ criteria->ID, criteria->type, dataType, value.compType);
return false;
}
return true;
@@ -197,7 +187,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (level.minlevel > STRONG_MAX_LEVEL)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL (%u) has wrong minlevel in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, level.minlevel);
+ criteria->ID, criteria->type, dataType, level.minlevel);
return false;
}
return true;
@@ -205,7 +195,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (gender.gender > GENDER_NONE)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER (%u) has wrong gender in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, gender.gender);
+ criteria->ID, criteria->type, dataType, gender.gender);
return false;
}
return true;
@@ -213,15 +203,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (!ScriptId)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT (%u) does not have ScriptName set, ignored.",
- criteria->ID, criteria->requiredType, dataType);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY:
- if (difficulty.difficulty >= MAX_DIFFICULTY)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY (%u) has wrong difficulty in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, difficulty.difficulty);
+ criteria->ID, criteria->type, dataType);
return false;
}
return true;
@@ -229,7 +211,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (map_players.maxcount <= 0)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT (%u) has wrong max players count in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, map_players.maxcount);
+ criteria->ID, criteria->type, dataType, map_players.maxcount);
return false;
}
return true;
@@ -237,7 +219,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (team.team != ALLIANCE && team.team != HORDE)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM (%u) has unknown team in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, team.team);
+ criteria->ID, criteria->type, dataType, team.team);
return false;
}
return true;
@@ -245,7 +227,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (drunk.state >= MAX_DRUNKEN)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK (%u) has unknown drunken state in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, drunk.state);
+ criteria->ID, criteria->type, dataType, drunk.state);
return false;
}
return true;
@@ -253,25 +235,28 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (!sHolidaysStore.LookupEntry(holiday.id))
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY (%u) has unknown holiday in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, holiday.id);
+ criteria->ID, criteria->type, dataType, holiday.id);
return false;
}
return true;
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT:
+ {
+ GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
+ if (game_event.id < 1 || game_event.id >= events.size())
+ {
+ TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT (%u) has unknown game_event in value1 (%u), ignored.",
+ criteria->ID, criteria->type, dataType, game_event.id);
+ return false;
+ }
+ return true;
+ }
case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE:
return true; // not check correctness node indexes
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM:
if (equipped_item.item_quality >= MAX_ITEM_QUALITY)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM (%u) has unknown quality state in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, equipped_item.item_quality);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID:
- if (!sMapStore.LookupEntry(map_id.mapId))
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID (%u) has unknown map id in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, map_id.mapId);
+ criteria->ID, criteria->type, dataType, equipped_item.item_quality);
return false;
}
return true;
@@ -279,19 +264,19 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (!classRace.class_id && !classRace.race_id)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) must not have 0 in either value field, ignored.",
- criteria->ID, criteria->requiredType, dataType);
+ criteria->ID, criteria->type, dataType);
return false;
}
if (classRace.class_id && ((1 << (classRace.class_id-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) has non-existing class in value1 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, classRace.class_id);
+ criteria->ID, criteria->type, dataType, classRace.class_id);
return false;
}
if (classRace.race_id && ((1 << (classRace.race_id-1)) & RACEMASK_ALL_PLAYABLE) == 0)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) has non-existing race in value2 (%u), ignored.",
- criteria->ID, criteria->requiredType, dataType, classRace.race_id);
+ criteria->ID, criteria->type, dataType, classRace.race_id);
return false;
}
return true;
@@ -299,17 +284,17 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
if (!sCharTitlesStore.LookupEntry(known_title.title_id))
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE (%u) have unknown title_id in value1 (%u), ignore.",
- criteria->ID, criteria->requiredType, dataType, known_title.title_id);
+ criteria->ID, criteria->type, dataType, known_title.title_id);
return false;
}
return true;
default:
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) has data for non-supported data type (%u), ignored.", criteria->ID, criteria->requiredType, dataType);
+ TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) has data for non-supported data type (%u), ignored.", criteria->ID, criteria->type, dataType);
return false;
}
}
-bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Unit const* target, uint32 miscvalue1 /*= 0*/) const
+bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Unit const* target, uint32 miscValue1 /*= 0*/) const
{
switch (dataType)
{
@@ -339,25 +324,12 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
if (!target || target->GetTypeId() != TYPEID_PLAYER)
return false;
return !target->HealthAbovePct(health.percent);
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD:
- if (target && !target->IsAlive())
- if (const Player* player = target->ToPlayer())
- if (player->GetDeathTimer() != 0)
- // flag set == must be same team, not set == different team
- return (player->GetTeam() == source->GetTeam()) == (player_dead.own_team_flag != 0);
- return false;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA:
return source->HasAuraEffect(aura.spell_id, aura.effect_idx);
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA:
- {
- uint32 zone_id, area_id;
- source->GetZoneAndAreaId(zone_id, area_id);
- return area.id == zone_id || area.id == area_id;
- }
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA:
return target && target->HasAuraEffect(aura.spell_id, aura.effect_idx);
case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE:
- return CompareValues(ComparisionType(value.compType), miscvalue1, value.value);
+ return CompareValues(ComparisionType(value.compType), miscValue1, value.value);
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL:
if (!target)
return false;
@@ -368,11 +340,6 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
return target->getGender() == gender.gender;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT:
return sScriptMgr->OnCriteriaCheck(ScriptId, const_cast<Player*>(source), const_cast<Unit*>(target));
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY:
- if (source->GetMap()->IsRaid())
- if (source->GetMap()->Is25ManRaid() != ((difficulty.difficulty & RAID_DIFFICULTY_MASK_25MAN) != 0))
- return false;
- return source->GetMap()->GetSpawnMode() >= difficulty.difficulty;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT:
return source->GetMap()->GetPlayersCountExceptGMs() <= map_players.maxcount;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM:
@@ -383,6 +350,8 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
return Player::GetDrunkenstateByValue(source->GetDrunkValue()) >= DrunkenState(drunk.state);
case ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY:
return IsHolidayActive(HolidayIds(holiday.id));
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT:
+ return IsEventActive(game_event.id);
case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE:
{
Battleground* bg = source->GetBattleground();
@@ -410,34 +379,22 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
dataType, criteria_id, map->GetId());
return false;
}
- return instance->CheckAchievementCriteriaMeet(criteria_id, source, target, miscvalue1);
+ return instance->CheckAchievementCriteriaMeet(criteria_id, source, target, miscValue1);
}
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM:
{
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscvalue1);
+ ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1);
if (!pProto)
return false;
return pProto->ItemLevel >= equipped_item.item_level && pProto->Quality >= equipped_item.item_quality;
}
case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID:
return source->GetMapId() == map_id.mapId;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY:
- {
- time_t birthday_start = time_t(sWorld->getIntConfig(CONFIG_BIRTHDAY_TIME));
- tm birthday_tm;
- localtime_r(&birthday_start, &birthday_tm);
-
- // exactly N birthday
- birthday_tm.tm_year += birthday_login.nth_birthday;
-
- time_t birthday = mktime(&birthday_tm);
- time_t now = sWorld->GetGameTime();
- return now <= birthday + DAY && now >= birthday;
- }
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE:
{
if (CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(known_title.title_id))
- return source->HasTitle(titleInfo->bit_index);
+ return source && source->HasTitle(titleInfo->bit_index);
+
return false;
}
default:
@@ -446,52 +403,97 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
return false;
}
-bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target, uint32 miscvalue /*= 0*/) const
+bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target, uint32 miscValue /*= 0*/) const
{
for (Storage::const_iterator itr = storage.begin(); itr != storage.end(); ++itr)
- if (!itr->Meets(criteria_id, source, target, miscvalue))
+ if (!itr->Meets(criteria_id, source, target, miscValue))
return false;
return true;
}
-AchievementMgr::AchievementMgr(Player* player)
+template<class T>
+AchievementMgr<T>::AchievementMgr(T* owner): _owner(owner), _achievementPoints(0) { }
+
+template<class T>
+AchievementMgr<T>::~AchievementMgr() { }
+
+template<class T>
+void AchievementMgr<T>::SendPacket(WorldPacket* data) const { }
+
+template<>
+void AchievementMgr<Guild>::SendPacket(WorldPacket* data) const
{
- m_player = player;
+ GetOwner()->BroadcastPacket(data);
}
-AchievementMgr::~AchievementMgr() { }
+template<>
+void AchievementMgr<Player>::SendPacket(WorldPacket* data) const
+{
+ GetOwner()->GetSession()->SendPacket(data);
+}
-void AchievementMgr::Reset()
+template<class T>
+void AchievementMgr<T>::RemoveCriteriaProgress(AchievementCriteriaEntry const* entry)
{
- for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
- {
- WorldPacket data(SMSG_ACHIEVEMENT_DELETED, 4);
- data << uint32(iter->first);
- m_player->SendDirectMessage(&data);
- }
+ if (!entry)
+ return;
- for (CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
- {
- WorldPacket data(SMSG_CRITERIA_DELETED, 4);
- data << uint32(iter->first);
- m_player->SendDirectMessage(&data);
- }
+ CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID);
+ if (criteriaProgress == m_criteriaProgress.end())
+ return;
- m_completedAchievements.clear();
- m_criteriaProgress.clear();
- DeleteFromDB(m_player->GetGUIDLow());
+ WorldPacket data(SMSG_CRITERIA_DELETED, 4);
+ data << uint32(entry->ID);
+ SendPacket(&data);
- // re-fill data
- CheckAllAchievementCriteria();
+ m_criteriaProgress.erase(criteriaProgress);
}
-void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, bool evenIfCriteriaComplete)
+template<>
+void AchievementMgr<Guild>::RemoveCriteriaProgress(AchievementCriteriaEntry const* entry)
{
- TC_LOG_DEBUG("achievement", "AchievementMgr::ResetAchievementCriteria(%u, %u, %u)", type, miscvalue1, miscvalue2);
+ if (!entry)
+ return;
+
+ CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID);
+ if (criteriaProgress == m_criteriaProgress.end())
+ return;
+
+ ObjectGuid guid = GetOwner()->GetGUID();
+
+ WorldPacket data(SMSG_GUILD_CRITERIA_DELETED, 4 + 8);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[4]);
+
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[7]);
+ data << uint32(entry->ID);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[6]);
+
+ SendPacket(&data);
+
+ m_criteriaProgress.erase(criteriaProgress);
+}
+
+template<class T>
+void AchievementMgr<T>::ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1, uint64 miscValue2, bool evenIfCriteriaComplete)
+{
+ TC_LOG_DEBUG("achievement", "ResetAchievementCriteria(%u, " UI64FMTD ", " UI64FMTD ")", type, miscValue1, miscValue2);
// disable for gamemasters with GM-mode enabled
- if (m_player->IsGameMaster())
+ if (GetOwner()->IsGameMaster())
return;
AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type);
@@ -499,7 +501,7 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uin
{
AchievementCriteriaEntry const* achievementCriteria = (*i);
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->referredAchievement);
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->achievement);
if (!achievement)
continue;
@@ -508,9 +510,9 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uin
continue;
for (uint8 j = 0; j < MAX_CRITERIA_REQUIREMENTS; ++j)
- if (achievementCriteria->additionalRequirements[j].additionalRequirement_type == miscvalue1 &&
+ if (achievementCriteria->additionalRequirements[j].additionalRequirement_type == miscValue1 &&
(!achievementCriteria->additionalRequirements[j].additionalRequirement_value ||
- achievementCriteria->additionalRequirements[j].additionalRequirement_value == miscvalue2))
+ achievementCriteria->additionalRequirements[j].additionalRequirement_value == miscValue2))
{
RemoveCriteriaProgress(achievementCriteria);
break;
@@ -518,7 +520,19 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uin
}
}
-void AchievementMgr::DeleteFromDB(uint32 lowguid)
+template<>
+void AchievementMgr<Guild>::ResetAchievementCriteria(AchievementCriteriaTypes /*type*/, uint64 /*miscValue1*/, uint64 /*miscValue2*/, bool /*evenIfCriteriaComplete*/)
+{
+ // Not needed
+}
+
+template<class T>
+void AchievementMgr<T>::DeleteFromDB(uint32 /*lowguid*/)
+{
+}
+
+template<>
+void AchievementMgr<Player>::DeleteFromDB(uint32 lowguid)
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -533,7 +547,29 @@ void AchievementMgr::DeleteFromDB(uint32 lowguid)
CharacterDatabase.CommitTransaction(trans);
}
-void AchievementMgr::SaveToDB(SQLTransaction& trans)
+template<>
+void AchievementMgr<Guild>::DeleteFromDB(uint32 lowguid)
+{
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENTS);
+ stmt->setUInt32(0, lowguid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt32(0, lowguid);
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+template<class T>
+void AchievementMgr<T>::SaveToDB(SQLTransaction& /*trans*/)
+{
+}
+
+template<>
+void AchievementMgr<Player>::SaveToDB(SQLTransaction& trans)
{
if (!m_completedAchievements.empty())
{
@@ -544,11 +580,11 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT);
stmt->setUInt16(0, iter->first);
- stmt->setUInt32(1, GetPlayer()->GetGUID());
+ stmt->setUInt32(1, GetOwner()->GetGUID());
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT);
- stmt->setUInt32(0, GetPlayer()->GetGUID());
+ stmt->setUInt32(0, GetOwner()->GetGUID());
stmt->setUInt16(1, iter->first);
stmt->setUInt32(2, uint32(iter->second.date));
trans->Append(stmt);
@@ -565,14 +601,14 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans)
continue;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS_BY_CRITERIA);
- stmt->setUInt32(0, GetPlayer()->GetGUID());
+ stmt->setUInt32(0, GetOwner()->GetGUID());
stmt->setUInt16(1, iter->first);
trans->Append(stmt);
if (iter->second.counter)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS);
- stmt->setUInt32(0, GetPlayer()->GetGUID());
+ stmt->setUInt32(0, GetOwner()->GetGUID());
stmt->setUInt16(1, iter->first);
stmt->setUInt32(2, iter->second.counter);
stmt->setUInt32(3, uint32(iter->second.date));
@@ -584,7 +620,61 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans)
}
}
-void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
+template<>
+void AchievementMgr<Guild>::SaveToDB(SQLTransaction& trans)
+{
+ PreparedStatement* stmt;
+ std::ostringstream guidstr;
+ for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
+ {
+ if (!itr->second.changed)
+ continue;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_ACHIEVEMENT);
+ stmt->setUInt32(0, GetOwner()->GetId());
+ stmt->setUInt16(1, itr->first);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_ACHIEVEMENT);
+ stmt->setUInt32(0, GetOwner()->GetId());
+ stmt->setUInt16(1, itr->first);
+ stmt->setUInt32(2, itr->second.date);
+ for (std::set<uint64>::const_iterator gItr = itr->second.guids.begin(); gItr != itr->second.guids.end(); ++gItr)
+ guidstr << GUID_LOPART(*gItr) << ',';
+
+ stmt->setString(3, guidstr.str());
+ trans->Append(stmt);
+
+ guidstr.str("");
+ }
+
+ for (CriteriaProgressMap::const_iterator itr = m_criteriaProgress.begin(); itr != m_criteriaProgress.end(); ++itr)
+ {
+ if (!itr->second.changed)
+ continue;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt32(0, GetOwner()->GetId());
+ stmt->setUInt16(1, itr->first);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt32(0, GetOwner()->GetId());
+ stmt->setUInt16(1, itr->first);
+ stmt->setUInt64(2, itr->second.counter);
+ stmt->setUInt32(3, itr->second.date);
+ stmt->setUInt32(4, GUID_LOPART(itr->second.CompletedGUID));
+ trans->Append(stmt);
+ }
+}
+
+template<class T>
+void AchievementMgr<T>::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
+{
+}
+
+template<>
+void AchievementMgr<Player>::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
{
if (achievementResult)
{
@@ -602,22 +692,26 @@ void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQ
ca.date = time_t(fields[1].GetUInt32());
ca.changed = false;
+ _achievementPoints += achievement->points;
+
// title achievement rewards are retroactive
if (AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement))
- if (uint32 titleId = reward->titleId[Player::TeamForRace(GetPlayer()->getRace()) == ALLIANCE ? 0 : 1])
+ if (uint32 titleId = reward->titleId[Player::TeamForRace(GetOwner()->getRace()) == ALLIANCE ? 0 : 1])
if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId))
- GetPlayer()->SetTitle(titleEntry);
+ GetOwner()->SetTitle(titleEntry);
- } while (achievementResult->NextRow());
+ }
+ while (achievementResult->NextRow());
}
if (criteriaResult)
{
+ time_t now = time(NULL);
do
{
Field* fields = criteriaResult->Fetch();
uint32 id = fields[0].GetUInt16();
- uint32 counter = fields[1].GetUInt32();
+ uint64 counter = fields[1].GetUInt64();
time_t date = time_t(fields[2].GetUInt32());
AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(id);
@@ -627,81 +721,242 @@ void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQ
TC_LOG_ERROR("achievement", "Non-existing achievement criteria %u data removed from table `character_achievement_progress`.", id);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA);
-
stmt->setUInt16(0, uint16(id));
-
CharacterDatabase.Execute(stmt);
continue;
}
- if (criteria->timeLimit && time_t(date + criteria->timeLimit) < time(NULL))
+ if (criteria->timeLimit && time_t(date + criteria->timeLimit) < now)
+ continue;
+
+ CriteriaProgress& progress = m_criteriaProgress[id];
+ progress.counter = counter;
+ progress.date = date;
+ progress.changed = false;
+ }
+ while (criteriaResult->NextRow());
+ }
+}
+
+template<>
+void AchievementMgr<Guild>::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
+{
+ if (achievementResult)
+ {
+ do
+ {
+ Field* fields = achievementResult->Fetch();
+ uint32 achievementid = fields[0].GetUInt16();
+
+ // must not happen: cleanup at server startup in sAchievementMgr->LoadCompletedAchievements()
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementid);
+ if (!achievement)
+ continue;
+
+ CompletedAchievementData& ca = m_completedAchievements[achievementid];
+ ca.date = time_t(fields[1].GetUInt32());
+ Tokenizer guids(fields[2].GetString(), ' ');
+ for (uint32 i = 0; i < guids.size(); ++i)
+ ca.guids.insert(MAKE_NEW_GUID(atol(guids[i]), 0, HIGHGUID_PLAYER));
+
+ ca.changed = false;
+
+ _achievementPoints += achievement->points;
+ }
+ while (achievementResult->NextRow());
+ }
+
+ if (criteriaResult)
+ {
+ time_t now = time(NULL);
+ do
+ {
+ Field* fields = criteriaResult->Fetch();
+ uint32 id = fields[0].GetUInt16();
+ uint32 counter = fields[1].GetUInt32();
+ time_t date = time_t(fields[2].GetUInt32());
+ uint64 guid = fields[3].GetUInt32();
+
+ AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(id);
+ if (!criteria)
+ {
+ // we will remove not existed criteria for all guilds
+ TC_LOG_ERROR("achievement", "Non-existing achievement criteria %u data removed from table `guild_achievement_progress`.", id);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA_GUILD);
+ stmt->setUInt16(0, uint16(id));
+ CharacterDatabase.Execute(stmt);
+ continue;
+ }
+
+ if (criteria->timeLimit && time_t(date + criteria->timeLimit) < now)
continue;
CriteriaProgress& progress = m_criteriaProgress[id];
progress.counter = counter;
progress.date = date;
+ progress.CompletedGUID = MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER);
progress.changed = false;
} while (criteriaResult->NextRow());
}
}
-void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) const
+template<class T>
+void AchievementMgr<T>::Reset()
{
- if (GetPlayer()->GetSession()->PlayerLoading())
- return;
+}
- // Don't send for achievements with ACHIEVEMENT_FLAG_TRACKING
+template<>
+void AchievementMgr<Player>::Reset()
+{
+ for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
+ {
+ WorldPacket data(SMSG_ACHIEVEMENT_DELETED, 4);
+ data << uint32(iter->first);
+ SendPacket(&data);
+ }
+
+ for (CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
+ {
+ WorldPacket data(SMSG_CRITERIA_DELETED, 4);
+ data << uint32(iter->first);
+ SendPacket(&data);
+ }
+
+ m_completedAchievements.clear();
+ _achievementPoints = 0;
+ m_criteriaProgress.clear();
+ DeleteFromDB(GetOwner()->GetGUIDLow());
+
+ // re-fill data
+ CheckAllAchievementCriteria(GetOwner());
+}
+
+template<>
+void AchievementMgr<Guild>::Reset()
+{
+ ObjectGuid guid = GetOwner()->GetGUID();
+ for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
+ {
+ WorldPacket data(SMSG_GUILD_ACHIEVEMENT_DELETED, 4);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[6]);
+ data << uint32(iter->first);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[7]);
+ data.AppendPackedTime(iter->second.date);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[2]);
+ SendPacket(&data);
+ }
+
+ while (!m_criteriaProgress.empty())
+ if (AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(m_criteriaProgress.begin()->first))
+ RemoveCriteriaProgress(criteria);
+
+ _achievementPoints = 0;
+ m_completedAchievements.clear();
+ DeleteFromDB(GetOwner()->GetId());
+}
+
+template<class T>
+void AchievementMgr<T>::SendAchievementEarned(AchievementEntry const* achievement) const
+{
+ // Don't send for achievements with ACHIEVEMENT_FLAG_HIDDEN
if (achievement->flags & ACHIEVEMENT_FLAG_HIDDEN)
return;
- #ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("achievement", "AchievementMgr::SendAchievementEarned(%u)", achievement->ID);
- #endif
+ TC_LOG_DEBUG("achievement", "AchievementMgr::SendAchievementEarned(%u)", achievement->ID);
- if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId()))
+ if (Guild* guild = sGuildMgr->GetGuildById(GetOwner()->GetGuildId()))
{
- Trinity::AchievementChatBuilder _builder(GetPlayer(), CHAT_MSG_GUILD_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, achievement->ID);
+ Trinity::AchievementChatBuilder _builder(GetOwner(), CHAT_MSG_GUILD_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, achievement->ID);
Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> _localizer(_builder);
- guild->BroadcastWorker(_localizer, GetPlayer());
+ guild->BroadcastWorker(_localizer, GetOwner());
}
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH))
{
// broadcast realm first reached
- WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, GetPlayer()->GetName().size() + 1 + 8 + 4 + 4);
- data << GetPlayer()->GetName();
- data << uint64(GetPlayer()->GetGUID());
+ WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, GetOwner()->GetName().size() + 1 + 8 + 4 + 4);
+ data << GetOwner()->GetName();
+ data << uint64(GetOwner()->GetGUID());
data << uint32(achievement->ID);
data << uint32(0); // 1=link supplied string as player name, 0=display plain string
sWorld->SendGlobalMessage(&data);
}
// if player is in world he can tell his friends about new achievement
- else if (GetPlayer()->IsInWorld())
+ else if (GetOwner()->IsInWorld())
{
- Trinity::AchievementChatBuilder _builder(GetPlayer(), CHAT_MSG_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, achievement->ID);
+ Trinity::AchievementChatBuilder _builder(GetOwner(), CHAT_MSG_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, achievement->ID);
Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> _localizer(_builder);
- Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> > _worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _localizer);
- GetPlayer()->VisitNearbyWorldObject(sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _worker);
+ Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> > _worker(GetOwner(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _localizer);
+ GetOwner()->VisitNearbyWorldObject(sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _worker);
}
WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8);
- data.append(GetPlayer()->GetPackGUID());
+ data.append(GetOwner()->GetPackGUID());
data << uint32(achievement->ID);
data.AppendPackedTime(time(NULL));
- data << uint32(0);
- GetPlayer()->SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
+ data << uint32(0); // does not notify player ingame
+ GetOwner()->SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
+}
+
+template<>
+void AchievementMgr<Guild>::SendAchievementEarned(AchievementEntry const* achievement) const
+{
+ ObjectGuid guid = GetOwner()->GetGUID();
+
+ WorldPacket data(SMSG_GUILD_ACHIEVEMENT_EARNED, 8+4+8);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[5]);
+
+ data.WriteByteSeq(guid[2]);
+ data.AppendPackedTime(time(NULL));
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[3]);
+ data << uint32(achievement->ID);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[6]);
+
+ SendPacket(&data);
+}
+
+template<class T>
+void AchievementMgr<T>::SendCriteriaUpdate(AchievementCriteriaEntry const* /*entry*/, CriteriaProgress const* /*progress*/, uint32 /*timeElapsed*/, bool /*timedCompleted*/) const
+{
}
-void AchievementMgr::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const
+template<>
+void AchievementMgr<Player>::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const
{
- WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8);
+ WorldPacket data(SMSG_CRITERIA_UPDATE, 8 + 4 + 8);
data << uint32(entry->ID);
// the counter is packed like a packed Guid
data.appendPackGUID(progress->counter);
- data.append(GetPlayer()->GetPackGUID());
+ data.appendPackGUID(GetOwner()->GetGUID());
if (!entry->timeLimit)
data << uint32(0);
else
@@ -709,20 +964,75 @@ void AchievementMgr::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, C
data.AppendPackedTime(progress->date);
data << uint32(timeElapsed); // time elapsed in seconds
data << uint32(0); // unk
- GetPlayer()->SendDirectMessage(&data);
+ SendPacket(&data);
+}
+
+template<>
+void AchievementMgr<Guild>::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 /*timeElapsed*/, bool /*timedCompleted*/) const
+{
+ //will send response to criteria progress request
+ WorldPacket data(SMSG_GUILD_CRITERIA_DATA, 3 + 1 + 1 + 8 + 8 + 4 + 4 + 4 + 4 + 4);
+
+ ObjectGuid counter = progress->counter; // for accessing every byte individually
+ ObjectGuid guid = progress->CompletedGUID;
+
+ data.WriteBits(1, 21);
+ data.WriteBit(counter[4]);
+ data.WriteBit(counter[1]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(counter[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(counter[5]);
+ data.WriteBit(counter[0]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(counter[2]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(counter[6]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(counter[7]);
+ data.WriteBit(guid[4]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(guid[5]);
+ data << uint32(progress->date); // unknown date
+ data.WriteByteSeq(counter[3]);
+ data.WriteByteSeq(counter[7]);
+ data << uint32(progress->date); // unknown date
+ data.WriteByteSeq(counter[6]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(counter[4]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(counter[0]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(counter[1]);
+ data.WriteByteSeq(guid[6]);
+ data << uint32(progress->date); // last update time (not packed!)
+ data << uint32(entry->ID);
+ data.WriteByteSeq(counter[5]);
+ data << uint32(0);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(counter[2]);
+ data.WriteByteSeq(guid[0]);
+
+ SendPacket(&data);
}
/**
* called at player login. The player might have fulfilled some achievements when the achievement system wasn't working yet
*/
-void AchievementMgr::CheckAllAchievementCriteria()
+template<class T>
+void AchievementMgr<T>::CheckAllAchievementCriteria(Player* referencePlayer)
{
// suppress sending packets
for (uint32 i=0; i<ACHIEVEMENT_CRITERIA_TYPE_TOTAL; ++i)
- UpdateAchievementCriteria(AchievementCriteriaTypes(i));
+ UpdateAchievementCriteria(AchievementCriteriaTypes(i), 0, 0, 0, NULL, referencePlayer);
}
-static const uint32 achievIdByArenaSlot[MAX_ARENA_SLOT] = { 1057, 1107, 1108 };
+static const uint32 achievIdByArenaSlot[MAX_ARENA_SLOT] = {1057, 1107, 1108};
static const uint32 achievIdForDungeon[][4] =
{
// ach_cr_id, is_dungeon, is_raid, is_heroic_dungeon
@@ -734,28 +1044,62 @@ static const uint32 achievIdForDungeon[][4] =
{ 0, false, false, false }
};
+// Helper function to avoid having to specialize template for a 800 line long function
+template <typename T> static bool IsGuild() { return false; }
+template<> bool IsGuild<Guild>() { return true; }
+
/**
* this function will be called whenever the user might have done a criteria relevant action
*/
-void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= NULL*/)
+template<class T>
+void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit const* unit /*= NULL*/, Player* referencePlayer /*= NULL*/)
{
- TC_LOG_DEBUG("achievement", "AchievementMgr::UpdateAchievementCriteria(%u, %u, %u)", type, miscValue1, miscValue2);
+ if (type >= ACHIEVEMENT_CRITERIA_TYPE_TOTAL)
+ {
+ TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: Wrong criteria type %u", type);
+ return;
+ }
+
+ if (!referencePlayer)
+ {
+ TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: Player is NULL! Cant update criteria");
+ return;
+ }
// disable for gamemasters with GM-mode enabled
- if (m_player->IsGameMaster())
+ if (referencePlayer->IsGameMaster())
+ {
+ TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: [Player %s GM mode on] %s, %s (%u), " UI64FMTD ", " UI64FMTD ", " UI64FMTD
+ , referencePlayer->GetName().c_str(), GetLogNameForGuid(GetOwner()->GetGUID()), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2, miscValue3);
return;
+ }
- AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type);
+ TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: %s, %s (%u), " UI64FMTD ", " UI64FMTD ", " UI64FMTD
+ , GetLogNameForGuid(GetOwner()->GetGUID()), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2, miscValue3);
+
+ // Lua_GetGuildLevelEnabled() is checked in achievement UI to display guild tab
+ if (IsGuild<T>() && !sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED))
+ return;
+
+ AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type, IsGuild<T>());
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
AchievementCriteriaEntry const* achievementCriteria = (*i);
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->referredAchievement);
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->achievement);
if (!achievement)
+ {
+ TC_LOG_ERROR("achievement", "UpdateAchievementCriteria: Achievement %u not found!", achievementCriteria->achievement);
continue;
+ }
- if (!CanUpdateCriteria(achievementCriteria, achievement))
+ if (!CanUpdateCriteria(achievementCriteria, achievement, miscValue1, miscValue2, miscValue3, unit, referencePlayer))
continue;
+ // requirements not found in the dbc
+ if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
+ if (!data->Meets(referencePlayer, unit, miscValue1))
+ continue;
+
switch (type)
{
// std. case: increment at 1
@@ -768,13 +1112,39 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
+ case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
+ case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
+ case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
+ SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
break;
- // std case: increment at miscvalue1
+ // std case: increment at miscValue1
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
@@ -785,116 +1155,44 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:/* FIXME: for online player only currently */
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
+ case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
break;
- // std case: high value at miscvalue1
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
+ SetCriteriaProgress(achievementCriteria, miscValue2, referencePlayer, PROGRESS_ACCUMULATE);
+ break;
+ // std case: high value at miscValue1
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD: /* FIXME: for online player only currently */
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_HIGHEST);
- break;
-
- // specialized cases
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- if (achievement->categoryId == CATEGORY_CHILDRENS_WEEK)
- {
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), NULL))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (achievementCriteria->win_bg.bgMapID != GetPlayer()->GetMapId())
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
- 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;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue2)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit, miscValue1))
- continue;
-
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
- if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
- if (!data->Meets(GetPlayer(), unit))
- continue;
- SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->getLevel(), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
- // update at loading or specific skill update
- if (miscValue1 && miscValue1 != achievementCriteria->reach_skill_level.skillID)
- continue;
- if (uint32 skillvalue = GetPlayer()->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID))
- SetCriteriaProgress(achievementCriteria, skillvalue);
+ if (uint32 skillvalue = referencePlayer->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID))
+ SetCriteriaProgress(achievementCriteria, skillvalue, referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
- // update at loading or specific skill update
- if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_level.skillID)
- continue;
- if (uint32 maxSkillvalue = GetPlayer()->GetPureMaxSkillValue(achievementCriteria->learn_skill_level.skillID))
- SetCriteriaProgress(achievementCriteria, maxSkillvalue);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
- if (m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end())
- SetCriteriaProgress(achievementCriteria, 1);
+ if (uint32 maxSkillvalue = referencePlayer->GetPureMaxSkillValue(achievementCriteria->learn_skill_level.skillID))
+ SetCriteriaProgress(achievementCriteria, maxSkillvalue, referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
- {
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetRewardedQuestCount());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetRewardedQuestCount(), referencePlayer);
break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
{
time_t nextDailyResetTime = sWorld->GetNextDailyQuestsResetTime();
@@ -904,7 +1202,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
{
// reset if player missed one day.
if (progress && progress->date < (nextDailyResetTime - 2 * DAY))
- SetCriteriaProgress(achievementCriteria, 0, PROGRESS_SET);
+ SetCriteriaProgress(achievementCriteria, 0, referencePlayer, PROGRESS_SET);
continue;
}
@@ -913,7 +1211,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
// 1st time. Start count.
progressType = PROGRESS_SET;
else if (progress->date < (nextDailyResetTime - 2 * DAY))
- // last progress is older than 2 days. Player missed 1 day => Retart count.
+ // last progress is older than 2 days. Player missed 1 day => Restart count.
progressType = PROGRESS_SET;
else if (progress->date < (nextDailyResetTime - DAY))
// last progress is between 1 and 2 days. => 1st time of the day.
@@ -922,462 +1220,54 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
// last progress is within the day before the reset => Already counted today.
continue;
- SetCriteriaProgress(achievementCriteria, 1, progressType);
+ SetCriteriaProgress(achievementCriteria, 1, referencePlayer, progressType);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
{
- // speedup for non-login case
- if (miscValue1 && miscValue1 != achievementCriteria->complete_quests_in_zone.zoneID)
- continue;
-
uint32 counter = 0;
- const RewardedQuestSet &rewQuests = GetPlayer()->getRewardedQuests();
+ const RewardedQuestSet &rewQuests = referencePlayer->getRewardedQuests();
for (RewardedQuestSet::const_iterator itr = rewQuests.begin(); itr != rewQuests.end(); ++itr)
{
Quest const* quest = sObjectMgr->GetQuestTemplate(*itr);
if (quest && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->complete_quests_in_zone.zoneID)
++counter;
}
- SetCriteriaProgress(achievementCriteria, counter);
+ SetCriteriaProgress(achievementCriteria, counter, referencePlayer);
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, PROGRESS_ACCUMULATE);
- 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, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- // skip wrong arena achievements, if not achievIdByArenaSlot then normal total death counter
- bool notfit = false;
- for (int j = 0; j < MAX_ARENA_SLOT; ++j)
- {
- if (achievIdByArenaSlot[j] == achievement->ID)
- {
- Battleground* bg = GetPlayer()->GetBattleground();
- if (!bg || !bg->isArena() || ArenaTeam::GetSlotByType(bg->GetArenaType()) != j)
- notfit = true;
-
- break;
- }
- }
- if (notfit)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- Map const* map = GetPlayer()->IsInWorld() ? GetPlayer()->GetMap() : sMapMgr->FindMap(GetPlayer()->GetMapId(), GetPlayer()->GetInstanceId());
- if (!map || !map->IsDungeon())
- continue;
-
- // search case
- bool found = false;
- for (int j = 0; achievIdForDungeon[j][0]; ++j)
- {
- if (achievIdForDungeon[j][0] == achievement->ID)
- {
- if (map->IsRaid())
- {
- // if raid accepted (ignore difficulty)
- if (!achievIdForDungeon[j][2])
- break; // for
- }
- else if (GetPlayer()->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL)
- {
- // dungeon in normal mode accepted
- if (!achievIdForDungeon[j][1])
- break; // for
- }
- else
- {
- // dungeon in heroic mode accepted
- if (!achievIdForDungeon[j][3])
- break; // for
- }
-
- found = true;
- break; // for
- }
- }
- if (!found)
- continue;
-
- //FIXME: work only for instances where max == min for players
- if (map->ToInstanceMap()->GetMaxPlayers() != achievementCriteria->death_in_dungeon.manLimit)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- 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, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- // if team check required: must kill by opposition faction
- if (achievement->ID == 318 && miscValue2 == GetPlayer()->GetTeam())
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- // miscvalue1 is the ingame fallheight*100 as stored in dbc
- SetCriteriaProgress(achievementCriteria, miscValue1);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (miscValue2 != achievementCriteria->death_from.type)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ // miscValue1 is the ingame fallheight*100 as stored in dbc
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
- {
- // if miscvalues != 0, it contains the questID.
- if (miscValue1)
- {
- if (miscValue1 != achievementCriteria->complete_quest.questID)
- continue;
- }
- else
- {
- // login case.
- if (!GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID))
- continue;
- }
-
- if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
- if (!data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->be_spell_target.spellID)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data)
- continue;
-
- if (!data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->cast_spell.spellID)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data)
- continue;
-
- if (!data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
- if (miscValue1 && miscValue1 != achievementCriteria->learn_spell.spellID)
- continue;
-
- if (GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID))
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
- {
- // miscvalue1=loot_type (note: 0 = LOOT_CORPSE and then it ignored)
- // miscvalue2=count of item loot
- if (!miscValue1 || !miscValue2)
- continue;
- if (miscValue1 != achievementCriteria->loot_type.lootType)
- continue;
-
- // zone specific
- if (achievementCriteria->loot_type.lootTypeCount == 1)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
- // speedup for non-login case
- if (miscValue1 && achievementCriteria->own_item.itemID != miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
- if (!miscValue1) // no update at login
- continue;
-
- // additional requirements
- if (achievementCriteria->additionalRequirements[0].additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit, miscValue1))
- {
- // reset the progress as we have a win without the requirement.
- SetCriteriaProgress(achievementCriteria, 0);
- continue;
- }
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- 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;
-
- // Children's Week achievements have extra requirements
- if (achievement->categoryId == CATEGORY_CHILDRENS_WEEK)
- {
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), NULL))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- 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, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
- {
- WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference);
- if (!worldOverlayEntry)
- break;
-
- bool matchFound = false;
- for (int j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
- {
- uint32 area_id = worldOverlayEntry->areatableID[j];
- if (!area_id) // array have 0 only in empty tail
- break;
-
- int32 exploreFlag = GetAreaFlagByAreaID(area_id);
- if (exploreFlag < 0)
- continue;
-
- uint32 playerIndexOffset = uint32(exploreFlag) / 32;
- uint32 mask = 1<< (uint32(exploreFlag) % 32);
-
- if (GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
- {
- matchFound = true;
- break;
- }
- }
-
- if (matchFound)
- SetCriteriaProgress(achievementCriteria, 1);
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ SetCriteriaProgress(achievementCriteria, 1, referencePlayer);
break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetBankBagSlotCount());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetBankBagSlotCount(), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
{
- // skip faction check only at loading
- if (miscValue1 && miscValue1 != achievementCriteria->gain_reputation.factionID)
- continue;
-
- int32 reputation = GetPlayer()->GetReputationMgr().GetReputation(achievementCriteria->gain_reputation.factionID);
+ int32 reputation = referencePlayer->GetReputationMgr().GetReputation(achievementCriteria->gain_reputation.factionID);
if (reputation > 0)
- SetCriteriaProgress(achievementCriteria, reputation);
+ SetCriteriaProgress(achievementCriteria, reputation, referencePlayer);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
- {
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetExaltedFactionCount());
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
- {
- // skip for login case
- if (!miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
- {
- // miscvalue1 = itemid
- // miscvalue2 = itemSlot
- if (!miscValue1)
- continue;
-
- if (miscValue2 != achievementCriteria->equip_epic_item.itemSlot)
- continue;
-
- // check item level and quality via achievement_criteria_data
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), 0, miscValue1))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
- {
- // miscvalue1 = itemid
- // miscvalue2 = diced value
- if (!miscValue1)
- continue;
- if (miscValue2 != achievementCriteria->roll_greed_on_loot.rollValue)
- continue;
-
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1);
- if (!pProto)
- continue;
-
- // check item level via achievement_criteria_data
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), 0, pProto->ItemLevel))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
- {
- // miscvalue1 = emote
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->do_emote.emoteID)
- continue;
- if (achievementCriteria->do_emote.count)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
- case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
- {
- if (!miscValue1)
- continue;
-
- if (achievementCriteria->additionalRequirements[0].additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP)
- {
- if (GetPlayer()->GetMapId() != achievementCriteria->additionalRequirements[0].additionalRequirement_value)
- continue;
-
- // map specific case (BG in fact) expected player targeted damage/heal
- if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
- // miscvalue1 = item_id
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->equip_item.itemID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
- // miscvalue1 = go entry
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->use_gameobject.goEntry)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->fish_in_gameobject.goEntry)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetExaltedFactionCount(), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
{
- if (miscValue1 && miscValue1 != achievementCriteria->learn_skillline_spell.skillLine)
- continue;
-
uint32 spellCount = 0;
- for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin();
- spellIter != GetPlayer()->GetSpellMap().end();
+ for (PlayerSpellMap::const_iterator spellIter = referencePlayer->GetSpellMap().begin();
+ spellIter != referencePlayer->GetSpellMap().end();
++spellIter)
{
SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellIter->first);
@@ -1387,56 +1277,23 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
spellCount++;
}
}
- SetCriteriaProgress(achievementCriteria, spellCount);
+ SetCriteriaProgress(achievementCriteria, spellCount, referencePlayer);
break;
}
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- if (achievementCriteria->win_duel.duelCount)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data)
- continue;
-
- if (!data->Meets(GetPlayer(), unit))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetReveredFactionCount());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetReveredFactionCount(), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetHonoredFactionCount());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetHonoredFactionCount(), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetVisibleFactionCount());
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetVisibleFactionCount(), referencePlayer);
break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(miscValue1);
- if (!proto || proto->Quality < ITEM_QUALITY_EPIC)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
{
- if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_line.skillLine)
- continue;
-
uint32 spellCount = 0;
- for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin();
- spellIter != GetPlayer()->GetSpellMap().end();
+ for (PlayerSpellMap::const_iterator spellIter = referencePlayer->GetSpellMap().begin();
+ spellIter != referencePlayer->GetSpellMap().end();
++spellIter)
{
SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellIter->first);
@@ -1444,78 +1301,21 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (skillIter->second->skillId == achievementCriteria->learn_skill_line.skillLine)
spellCount++;
}
- SetCriteriaProgress(achievementCriteria, spellCount);
+ SetCriteriaProgress(achievementCriteria, spellCount, referencePlayer);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS));
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
- if (!miscValue1 || miscValue1 != achievementCriteria->hk_class.classID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
- if (!miscValue1 || miscValue1 != achievementCriteria->hk_race.raceID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS), referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
- SetCriteriaProgress(achievementCriteria, GetPlayer()->GetMoney(), PROGRESS_HIGHEST);
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetMoney(), referencePlayer, PROGRESS_HIGHEST);
break;
case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
- {
if (!miscValue1)
- {
- uint32 points = 0;
- for (CompletedAchievementMap::iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
- if (AchievementEntry const* pAchievement = sAchievementMgr->GetAchievement(itr->first))
- points += pAchievement->points;
- SetCriteriaProgress(achievementCriteria, points, PROGRESS_SET);
- }
+ SetCriteriaProgress(achievementCriteria, _achievementPoints, referencePlayer, PROGRESS_SET);
else
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->bg_objective.objectiveId)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
- {
- // skip login update
- if (!miscValue1)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->honorable_kill_at_area.areaID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
{
uint32 reqTeamType = achievementCriteria->highest_team_rating.teamtype;
@@ -1525,13 +1325,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (miscValue2 != reqTeamType)
continue;
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_HIGHEST);
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
}
- else // login case
+ else // login case
{
for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
{
- uint32 teamId = GetPlayer()->GetArenaTeamId(arena_slot);
+ uint32 teamId = referencePlayer->GetArenaTeamId(arena_slot);
if (!teamId)
continue;
@@ -1539,7 +1339,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (!team || team->GetType() != reqTeamType)
continue;
- SetCriteriaProgress(achievementCriteria, team->GetStats().Rating, PROGRESS_HIGHEST);
+ SetCriteriaProgress(achievementCriteria, team->GetStats().Rating, referencePlayer, PROGRESS_HIGHEST);
break;
}
}
@@ -1555,13 +1355,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (miscValue2 != reqTeamType)
continue;
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_HIGHEST);
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
}
- else // login case
+ else // login case
{
for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
{
- uint32 teamId = GetPlayer()->GetArenaTeamId(arena_slot);
+ uint32 teamId = referencePlayer->GetArenaTeamId(arena_slot);
if (!teamId)
continue;
@@ -1569,69 +1369,57 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (!team || team->GetType() != reqTeamType)
continue;
- if (ArenaTeamMember const* member = team->GetMember(GetPlayer()->GetGUID()))
+ if (ArenaTeamMember const* member = team->GetMember(referencePlayer->GetGUID()))
{
- SetCriteriaProgress(achievementCriteria, member->PersonalRating, PROGRESS_HIGHEST);
+ SetCriteriaProgress(achievementCriteria, member->PersonalRating, referencePlayer, PROGRESS_HIGHEST);
break;
}
}
}
-
break;
}
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
- {
- // Check map id requirement
- if (miscValue1 == achievementCriteria->win_arena.mapID)
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
- {
- // This criteria is only called directly after login - with expected miscvalue1 == 1
- if (!miscValue1)
- continue;
-
- // They have no proper requirements in dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- // std case: not exist in DBC, not triggered in code as result
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer);
break;
// FIXME: not triggered in code as result, need to implement
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA:
case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
+ case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS:
+ case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD:
+ case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL:
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING:
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
break; // Not implemented yet :(
}
if (IsCompletedCriteria(achievementCriteria, achievement))
- CompletedCriteriaFor(achievement);
+ CompletedCriteriaFor(achievement, referencePlayer);
// check again the completeness for SUMM and REQ COUNT achievements,
// as they don't depend on the completed criteria but on the sum of the progress of each individual criteria
if (achievement->flags & ACHIEVEMENT_FLAG_SUMM)
if (IsCompletedAchievement(achievement))
- CompletedAchievement(achievement);
+ CompletedAchievement(achievement, referencePlayer);
if (AchievementEntryList const* achRefList = sAchievementMgr->GetAchievementByReferencedId(achievement->ID))
for (AchievementEntryList::const_iterator itr = achRefList->begin(); itr != achRefList->end(); ++itr)
if (IsCompletedAchievement(*itr))
- CompletedAchievement(*itr);
+ CompletedAchievement(*itr, referencePlayer);
}
}
-bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement)
+template<class T>
+bool AchievementMgr<T>::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement)
{
if (!achievement)
return false;
@@ -1651,13 +1439,14 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
if (!progress)
return false;
- switch (achievementCriteria->requiredType)
+ switch (AchievementCriteriaTypes(achievementCriteria->type))
{
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
return progress->counter >= achievementCriteria->win_bg.winCount;
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
return progress->counter >= achievementCriteria->kill_creature.creatureCount;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
return progress->counter >= achievementCriteria->reach_level.level;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
return progress->counter >= achievementCriteria->reach_skill_level.skillLevel;
@@ -1752,6 +1541,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
return progress->counter >= achievementCriteria->use_lfg.dungeonsComplete;
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
return progress->counter >= achievementCriteria->get_killing_blow.killCount;
+ case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
+ return progress->counter >= achievementCriteria->currencyGain.count;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
return achievementCriteria->win_arena.count && progress->counter >= achievementCriteria->win_arena.count;
case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
@@ -1785,19 +1576,18 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR:
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
default:
break;
}
+
return false;
}
-void AchievementMgr::CompletedCriteriaFor(AchievementEntry const* achievement)
+template<class T>
+void AchievementMgr<T>::CompletedCriteriaFor(AchievementEntry const* achievement, Player* referencePlayer)
{
// counter can never complete
if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER)
@@ -1808,26 +1598,27 @@ void AchievementMgr::CompletedCriteriaFor(AchievementEntry const* achievement)
return;
if (IsCompletedAchievement(achievement))
- CompletedAchievement(achievement);
+ CompletedAchievement(achievement, referencePlayer);
}
-bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
+template<class T>
+bool AchievementMgr<T>::IsCompletedAchievement(AchievementEntry const* entry)
{
// counter can never complete
if (entry->flags & ACHIEVEMENT_FLAG_COUNTER)
return false;
// for achievement with referenced achievement criterias get from referenced and counter from self
- uint32 achievmentForTestId = entry->refAchievement ? entry->refAchievement : entry->ID;
- uint32 achievmentForTestCount = entry->count;
+ uint32 achievementForTestId = entry->refAchievement ? entry->refAchievement : entry->ID;
+ uint32 achievementForTestCount = entry->count;
- AchievementCriteriaEntryList const* cList = sAchievementMgr->GetAchievementCriteriaByAchievement(achievmentForTestId);
+ AchievementCriteriaEntryList const* cList = sAchievementMgr->GetAchievementCriteriaByAchievement(achievementForTestId);
if (!cList)
return false;
- uint32 count = 0;
+ uint64 count = 0;
// For SUMM achievements, we have to count the progress of each criteria of the achievement.
- // Oddly, the target count is NOT countained in the achievement, but in each individual criteria
+ // Oddly, the target count is NOT contained in the achievement, but in each individual criteria
if (entry->flags & ACHIEVEMENT_FLAG_SUMM)
{
for (AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr)
@@ -1862,18 +1653,19 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
completed_all = false;
// completed as have req. count of completed criterias
- if (achievmentForTestCount > 0 && achievmentForTestCount <= count)
+ if (achievementForTestCount > 0 && achievementForTestCount <= count)
return true;
}
// all criterias completed requirement
- if (completed_all && achievmentForTestCount == 0)
+ if (completed_all && achievementForTestCount == 0)
return true;
return false;
}
-CriteriaProgress* AchievementMgr::GetCriteriaProgress(AchievementCriteriaEntry const* entry)
+template<class T>
+CriteriaProgress* AchievementMgr<T>::GetCriteriaProgress(AchievementCriteriaEntry const* entry)
{
CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID);
@@ -1883,14 +1675,16 @@ CriteriaProgress* AchievementMgr::GetCriteriaProgress(AchievementCriteriaEntry c
return &(iter->second);
}
-void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype)
+template<class T>
+void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint64 changeValue, Player* referencePlayer, ProgressType ptype)
{
// Don't allow to cheat - doing timed achievements without timer active
TimedAchievementMap::iterator timedIter = m_timedAchievements.find(entry->ID);
if (entry->timeLimit && timedIter == m_timedAchievements.end())
return;
- TC_LOG_DEBUG("achievement", "AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue, m_player->GetGUIDLow());
+ TC_LOG_DEBUG("achievement", "SetCriteriaProgress(%u, " UI64FMTD ") for (%s GUID: %u)",
+ entry->ID, changeValue, GetLogNameForGuid(GetOwner()->GetGUID()), GUID_LOPART(GetOwner()->GetGUID()));
CriteriaProgress* progress = GetCriteriaProgress(entry);
if (!progress)
@@ -1905,7 +1699,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
}
else
{
- uint32 newValue = 0;
+ uint64 newValue = 0;
switch (ptype)
{
case PROGRESS_SET:
@@ -1914,7 +1708,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
case PROGRESS_ACCUMULATE:
{
// avoid overflow
- uint32 max_value = std::numeric_limits<uint32>::max();
+ uint64 max_value = std::numeric_limits<uint64>::max();
newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value;
break;
}
@@ -1933,41 +1727,28 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
progress->changed = true;
progress->date = time(NULL); // set the date to the latest update.
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(entry->achievement);
uint32 timeElapsed = 0;
- bool timedCompleted = false;
+ bool criteriaComplete = IsCompletedCriteria(entry, achievement);
if (entry->timeLimit)
{
- // has to exist else we wouldn't be here
- timedCompleted = IsCompletedCriteria(entry, sAchievementMgr->GetAchievement(entry->referredAchievement));
// Client expects this in packet
timeElapsed = entry->timeLimit - (timedIter->second/IN_MILLISECONDS);
// Remove the timer, we wont need it anymore
- if (timedCompleted)
+ if (criteriaComplete)
m_timedAchievements.erase(timedIter);
}
- SendCriteriaUpdate(entry, progress, timeElapsed, timedCompleted);
-}
-
-void AchievementMgr::RemoveCriteriaProgress(AchievementCriteriaEntry const* entry)
-{
- if (!entry)
- return;
+ if (criteriaComplete && achievement->flags & ACHIEVEMENT_FLAG_SHOW_CRITERIA_MEMBERS && !progress->CompletedGUID)
+ progress->CompletedGUID = referencePlayer->GetGUID();
- CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID);
- if (criteriaProgress == m_criteriaProgress.end())
- return;
-
- WorldPacket data(SMSG_CRITERIA_DELETED, 4);
- data << uint32(entry->ID);
- m_player->SendDirectMessage(&data);
-
- m_criteriaProgress.erase(criteriaProgress);
+ SendCriteriaUpdate(entry, progress, timeElapsed, criteriaComplete);
}
-void AchievementMgr::UpdateTimedAchievements(uint32 timeDiff)
+template<class T>
+void AchievementMgr<T>::UpdateTimedAchievements(uint32 timeDiff)
{
if (!m_timedAchievements.empty())
{
@@ -1989,15 +1770,21 @@ void AchievementMgr::UpdateTimedAchievements(uint32 timeDiff)
}
}
-void AchievementMgr::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost /*= 0*/)
+template<class T>
+void AchievementMgr<T>::StartTimedAchievement(AchievementCriteriaTimedTypes /*type*/, uint32 /*entry*/, uint32 /*timeLost = 0*/)
+{
+}
+
+template<>
+void AchievementMgr<Player>::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost /* = 0 */)
{
AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetTimedAchievementCriteriaByType(type);
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
- if ((*i)->timerStartEvent != entry)
+ if ((*i)->timedCriteriaMiscId != entry)
continue;
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement((*i)->referredAchievement);
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement((*i)->achievement);
if (m_timedAchievements.find((*i)->ID) == m_timedAchievements.end() && !IsCompletedCriteria(*i, achievement))
{
// Start the timer
@@ -2006,18 +1793,19 @@ void AchievementMgr::StartTimedAchievement(AchievementCriteriaTimedTypes type, u
m_timedAchievements[(*i)->ID] = (*i)->timeLimit * IN_MILLISECONDS - timeLost;
// and at client too
- SetCriteriaProgress(*i, 0, PROGRESS_SET);
+ SetCriteriaProgress(*i, 0, GetOwner(), PROGRESS_SET);
}
}
}
}
-void AchievementMgr::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
+template<class T>
+void AchievementMgr<T>::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
{
AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetTimedAchievementCriteriaByType(type);
- for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i!=achievementCriteriaList.end(); ++i)
+ for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
- if ((*i)->timerStartEvent != entry)
+ if ((*i)->timedCriteriaMiscId != entry)
continue;
TimedAchievementMap::iterator timedIter = m_timedAchievements.find((*i)->ID);
@@ -2033,19 +1821,26 @@ void AchievementMgr::RemoveTimedAchievement(AchievementCriteriaTimedTypes type,
}
}
-void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
+template<>
+void AchievementMgr<Player>::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer)
{
// disable for gamemasters with GM-mode enabled
- if (m_player->IsGameMaster())
+ if (GetOwner()->IsGameMaster())
return;
if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID))
return;
+ if (achievement->flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS)
+ if (Guild* guild = referencePlayer->GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_PLAYER_ACHIEVEMENT, referencePlayer->GetGUID(), achievement->flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER, achievement->ID);
+
+ if (!GetOwner()->GetSession()->PlayerLoading())
+ SendAchievementEarned(achievement);
+
TC_LOG_INFO("achievement", "AchievementMgr::CompletedAchievement(%u). Player: %s (%u)",
- achievement->ID, m_player->GetName().c_str(), m_player->GetGUIDLow());
+ achievement->ID, GetOwner()->GetName().c_str(), GetOwner()->GetGUIDLow());
- SendAchievementEarned(achievement);
CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
ca.date = time(NULL);
ca.changed = true;
@@ -2055,8 +1850,10 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
if (!(achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
sAchievementMgr->SetRealmCompleted(achievement);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points);
+ _achievementPoints += achievement->points;
+
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points, 0, 0, NULL, referencePlayer);
// reward items and titles if any
AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement);
@@ -2070,9 +1867,9 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
//! Since no common attributes were found, (not even in titleRewardFlags field)
//! we explicitly check by ID. Maybe in the future we could move the achievement_reward
//! condition fields to the condition system.
- if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetPlayer()->getGender() : (GetPlayer()->GetTeam() == ALLIANCE ? 0 : 1)])
+ if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetOwner()->getGender() : (GetOwner()->GetTeam() == ALLIANCE ? 0 : 1)])
if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId))
- GetPlayer()->SetTitle(titleEntry);
+ GetOwner()->SetTitle(titleEntry);
// mail
if (reward->sender)
@@ -2085,7 +1882,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
std::string subject = reward->subject;
std::string text = reward->text;
- int locIdx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex();
+ int locIdx = GetOwner()->GetSession()->GetSessionDbLocaleIndex();
if (locIdx >= 0)
{
if (AchievementRewardLocale const* loc = sAchievementMgr->GetAchievementRewardLocale(achievement))
@@ -2100,7 +1897,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
SQLTransaction trans = CharacterDatabase.BeginTransaction();
- Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetPlayer()) : NULL;
+ Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetOwner()) : NULL;
if (item)
{
// save new item before send
@@ -2110,74 +1907,391 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
draft.AddItem(item);
}
- draft.SendMailTo(trans, GetPlayer(), MailSender(MAIL_CREATURE, reward->sender));
+ draft.SendMailTo(trans, GetOwner(), MailSender(MAIL_CREATURE, reward->sender));
CharacterDatabase.CommitTransaction(trans);
}
}
-void AchievementMgr::SendAllAchievementData() const
+template<>
+void AchievementMgr<Guild>::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer)
{
- WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, m_completedAchievements.size()*8+4+m_criteriaProgress.size()*38+4);
- BuildAllDataPacket(&data);
- GetPlayer()->GetSession()->SendPacket(&data);
+ TC_LOG_DEBUG("achievement", "AchievementMgr<Guild>::CompletedAchievement(%u)", achievement->ID);
+
+ if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID))
+ return;
+
+ if (achievement->flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS)
+ if (Guild* guild = referencePlayer->GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_GUILD_ACHIEVEMENT, 0, achievement->flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER, achievement->ID);
+
+ SendAchievementEarned(achievement);
+ CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
+ ca.date = time(NULL);
+ ca.changed = true;
+
+ if (achievement->flags & ACHIEVEMENT_FLAG_SHOW_GUILD_MEMBERS)
+ {
+ if (referencePlayer->GetGuildId() == GetOwner()->GetId())
+ ca.guids.insert(referencePlayer->GetGUID());
+
+ if (Group const* group = referencePlayer->GetGroup())
+ for (GroupReference const* ref = group->GetFirstMember(); ref != NULL; ref = ref->next())
+ if (Player const* groupMember = ref->GetSource())
+ if (groupMember->GetGuildId() == GetOwner()->GetId())
+ ca.guids.insert(groupMember->GetGUID());
+ }
+
+ sAchievementMgr->SetRealmCompleted(achievement);
+
+ _achievementPoints += achievement->points;
+
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points, 0, 0, NULL, referencePlayer);
}
-void AchievementMgr::SendRespondInspectAchievements(Player* player) const
+struct VisibleAchievementPred
+{
+ bool operator()(CompletedAchievementMap::value_type const& val)
+ {
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(val.first);
+ return achievement && !(achievement->flags & ACHIEVEMENT_FLAG_HIDDEN);
+ }
+};
+
+template<class T>
+void AchievementMgr<T>::SendAllAchievementData(Player* /*receiver*/) const
{
- WorldPacket data(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, 9+m_completedAchievements.size()*8+4+m_criteriaProgress.size()*38+4);
- data.append(GetPlayer()->GetPackGUID());
- BuildAllDataPacket(&data);
- player->GetSession()->SendPacket(&data);
+ VisibleAchievementPred isVisible;
+ size_t numCriteria = m_criteriaProgress.size();
+ size_t numAchievements = std::count_if(m_completedAchievements.begin(), m_completedAchievements.end(), isVisible);
+ ByteBuffer criteriaData(numCriteria * (4 + 4 + 4 + 4 + 8 + 8));
+ ObjectGuid guid = GetOwner()->GetGUID();
+ ObjectGuid counter;
+
+ WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, 4 + numAchievements * (4 + 4) + 4 + numCriteria * (4 + 4 + 4 + 4 + 8 + 8));
+ data.WriteBits(numCriteria, 21);
+ for (CriteriaProgressMap::const_iterator itr = m_criteriaProgress.begin(); itr != m_criteriaProgress.end(); ++itr)
+ {
+ counter = itr->second.counter;
+
+ data.WriteBit(guid[4]);
+ data.WriteBit(counter[3]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(counter[0]);
+ data.WriteBit(counter[6]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(counter[4]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(counter[7]);
+ data.WriteBit(guid[7]);
+ data.WriteBits(0u, 2);
+ data.WriteBit(guid[6]);
+ data.WriteBit(counter[2]);
+ data.WriteBit(counter[1]);
+ data.WriteBit(counter[5]);
+ data.WriteBit(guid[1]);
+
+ criteriaData.WriteByteSeq(guid[3]);
+ criteriaData.WriteByteSeq(counter[5]);
+ criteriaData.WriteByteSeq(counter[6]);
+ criteriaData.WriteByteSeq(guid[4]);
+ criteriaData.WriteByteSeq(guid[6]);
+ criteriaData.WriteByteSeq(counter[2]);
+ criteriaData << uint32(0); // timer 2
+ criteriaData.WriteByteSeq(guid[2]);
+ criteriaData << uint32(itr->first); // criteria id
+ criteriaData.WriteByteSeq(guid[5]);
+ criteriaData.WriteByteSeq(counter[0]);
+ criteriaData.WriteByteSeq(counter[3]);
+ criteriaData.WriteByteSeq(counter[1]);
+ criteriaData.WriteByteSeq(counter[4]);
+ criteriaData.WriteByteSeq(guid[0]);
+ criteriaData.WriteByteSeq(guid[7]);
+ criteriaData.WriteByteSeq(counter[7]);
+ criteriaData << uint32(0); // timer 1
+ criteriaData.AppendPackedTime(itr->second.date); // criteria date
+ criteriaData.WriteByteSeq(guid[1]);
+ }
+
+ data.WriteBits(numAchievements, 23);
+ data.FlushBits();
+ data.append(criteriaData);
+
+ for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
+ {
+ if (!isVisible(*itr))
+ continue;
+
+ data << uint32(itr->first);
+ data.AppendPackedTime(itr->second.date);
+ }
+
+ SendPacket(&data);
}
-/**
- * used by SMSG_RESPOND_INSPECT_ACHIEVEMENT and SMSG_ALL_ACHIEVEMENT_DATA
- */
-void AchievementMgr::BuildAllDataPacket(WorldPacket* data) const
+template<>
+void AchievementMgr<Guild>::SendAllAchievementData(Player* receiver) const
{
- for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
+ VisibleAchievementPred isVisible;
+ WorldPacket data(SMSG_GUILD_ACHIEVEMENT_DATA, m_completedAchievements.size() * (4 + 4) + 3);
+ data.WriteBits(std::count_if(m_completedAchievements.begin(), m_completedAchievements.end(), isVisible), 23);
+ for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
{
- // Skip hidden achievements
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(iter->first);
- if (!achievement || achievement->flags & ACHIEVEMENT_FLAG_HIDDEN)
+ if (!isVisible(*itr))
continue;
- *data << uint32(iter->first);
- data->AppendPackedTime(iter->second.date);
+ data.AppendPackedTime(itr->second.date);
+ data << uint32(itr->first);
}
- *data << int32(-1);
- for (CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
+ receiver->GetSession()->SendPacket(&data);
+}
+
+template<>
+void AchievementMgr<Player>::SendAchievementInfo(Player* receiver, uint32 /*achievementId = 0 */) const
+{
+ ObjectGuid guid = GetOwner()->GetGUID();
+ ObjectGuid counter;
+
+ VisibleAchievementPred isVisible;
+ size_t numCriteria = m_criteriaProgress.size();
+ size_t numAchievements = std::count_if(m_completedAchievements.begin(), m_completedAchievements.end(), isVisible);
+ ByteBuffer criteriaData(numCriteria * 16);
+
+ WorldPacket data(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, 1 + 8 + 3 + 3 + numAchievements * (4 + 4) + numCriteria * (0));
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[1]);
+ data.WriteBits(numAchievements, 23);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[3]);
+ data.WriteBits(numCriteria, 21);
+ data.WriteBit(guid[2]);
+ for (CriteriaProgressMap::const_iterator itr = m_criteriaProgress.begin(); itr != m_criteriaProgress.end(); ++itr)
+ {
+ counter = itr->second.counter;
+
+ data.WriteBit(counter[5]);
+ data.WriteBit(counter[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(counter[6]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(counter[4]);
+ data.WriteBit(counter[1]);
+ data.WriteBit(counter[2]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[7]);
+ data.WriteBits(0, 2); // criteria progress flags
+ data.WriteBit(counter[0]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(counter[7]);
+
+ criteriaData.WriteByteSeq(guid[3]);
+ criteriaData.WriteByteSeq(counter[4]);
+ criteriaData << uint32(0); // timer 1
+ criteriaData.WriteByteSeq(guid[1]);
+ criteriaData.AppendPackedTime(itr->second.date);
+ criteriaData.WriteByteSeq(counter[3]);
+ criteriaData.WriteByteSeq(counter[7]);
+ criteriaData.WriteByteSeq(guid[5]);
+ criteriaData.WriteByteSeq(counter[0]);
+ criteriaData.WriteByteSeq(guid[4]);
+ criteriaData.WriteByteSeq(guid[2]);
+ criteriaData.WriteByteSeq(guid[6]);
+ criteriaData.WriteByteSeq(guid[7]);
+ criteriaData.WriteByteSeq(counter[6]);
+ criteriaData << uint32(itr->first);
+ criteriaData << uint32(0); // timer 2
+ criteriaData.WriteByteSeq(counter[1]);
+ criteriaData.WriteByteSeq(counter[5]);
+ criteriaData.WriteByteSeq(guid[0]);
+ criteriaData.WriteByteSeq(counter[2]);
+ }
+
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.FlushBits();
+ data.append(criteriaData);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[2]);
+
+ for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
+ {
+ if (!isVisible(*itr))
+ continue;
+
+ data << uint32(itr->first);
+ data.AppendPackedTime(itr->second.date);
+ }
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[5]);
+
+ receiver->GetSession()->SendPacket(&data);
+}
+
+template<>
+void AchievementMgr<Guild>::SendAchievementInfo(Player* receiver, uint32 achievementId /*= 0*/) const
+{
+ //will send response to criteria progress request
+ AchievementCriteriaEntryList const* criteria = sAchievementMgr->GetAchievementCriteriaByAchievement(achievementId);
+ if (!criteria)
+ {
+ // send empty packet
+ WorldPacket data(SMSG_GUILD_CRITERIA_DATA, 3);
+ data.WriteBits(0, 21);
+ receiver->GetSession()->SendPacket(&data);
+ return;
+ }
+
+ ObjectGuid counter;
+ ObjectGuid guid;
+ uint32 numCriteria = 0;
+ ByteBuffer criteriaData(criteria->size() * (8 + 8 + 4 + 4 + 4));
+ ByteBuffer criteriaBits(criteria->size() * (8 + 8) / 8);
+ for (AchievementCriteriaEntryList::const_iterator itr = criteria->begin(); itr != criteria->end(); ++itr)
+ {
+ uint32 criteriaId = (*itr)->ID;
+ CriteriaProgressMap::const_iterator progress = m_criteriaProgress.find(criteriaId);
+ if (progress == m_criteriaProgress.end())
+ continue;
+
+ ++numCriteria;
+ }
+
+ criteriaBits.WriteBits(numCriteria, 21);
+
+ for (AchievementCriteriaEntryList::const_iterator itr = criteria->begin(); itr != criteria->end(); ++itr)
{
- *data << uint32(iter->first);
- data->appendPackGUID(iter->second.counter);
- data->append(GetPlayer()->GetPackGUID());
- *data << uint32(0);
- data->AppendPackedTime(iter->second.date);
- *data << uint32(0);
- *data << uint32(0);
+ uint32 criteriaId = (*itr)->ID;
+ CriteriaProgressMap::const_iterator progress = m_criteriaProgress.find(criteriaId);
+ if (progress == m_criteriaProgress.end())
+ continue;
+
+ counter = progress->second.counter;
+ guid = progress->second.CompletedGUID;
+
+ criteriaBits.WriteBit(counter[4]);
+ criteriaBits.WriteBit(counter[1]);
+ criteriaBits.WriteBit(guid[2]);
+ criteriaBits.WriteBit(counter[3]);
+ criteriaBits.WriteBit(guid[1]);
+ criteriaBits.WriteBit(counter[5]);
+ criteriaBits.WriteBit(counter[0]);
+ criteriaBits.WriteBit(guid[3]);
+ criteriaBits.WriteBit(counter[2]);
+ criteriaBits.WriteBit(guid[7]);
+ criteriaBits.WriteBit(guid[5]);
+ criteriaBits.WriteBit(guid[0]);
+ criteriaBits.WriteBit(counter[6]);
+ criteriaBits.WriteBit(guid[6]);
+ criteriaBits.WriteBit(counter[7]);
+ criteriaBits.WriteBit(guid[4]);
+
+ criteriaData.WriteByteSeq(guid[5]);
+ criteriaData << uint32(progress->second.date); // unknown date
+ criteriaData.WriteByteSeq(counter[3]);
+ criteriaData.WriteByteSeq(counter[7]);
+ criteriaData << uint32(progress->second.date); // unknown date
+ criteriaData.WriteByteSeq(counter[6]);
+ criteriaData.WriteByteSeq(guid[4]);
+ criteriaData.WriteByteSeq(guid[1]);
+ criteriaData.WriteByteSeq(counter[4]);
+ criteriaData.WriteByteSeq(guid[3]);
+ criteriaData.WriteByteSeq(counter[0]);
+ criteriaData.WriteByteSeq(guid[2]);
+ criteriaData.WriteByteSeq(counter[1]);
+ criteriaData.WriteByteSeq(guid[6]);
+ criteriaData << uint32(progress->second.date); // last update time (not packed!)
+ criteriaData << uint32(criteriaId);
+ criteriaData.WriteByteSeq(counter[5]);
+ criteriaData << uint32(0);
+ criteriaData.WriteByteSeq(guid[7]);
+ criteriaData.WriteByteSeq(counter[2]);
+ criteriaData.WriteByteSeq(guid[0]);
}
- *data << int32(-1);
+ WorldPacket data(SMSG_GUILD_CRITERIA_DATA, criteriaBits.size() + criteriaData.size());
+ data.append(criteriaBits);
+ if (numCriteria)
+ data.append(criteriaData);
+
+ receiver->GetSession()->SendPacket(&data);
}
-bool AchievementMgr::HasAchieved(uint32 achievementId) const
+template<class T>
+bool AchievementMgr<T>::HasAchieved(uint32 achievementId) const
{
return m_completedAchievements.find(achievementId) != m_completedAchievements.end();
}
-bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement)
+template<class T>
+bool AchievementMgr<T>::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer)
{
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, NULL))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: %s (Id: %u Type %s) Disabled",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
+ return false;
+ }
+
+ if (achievement->mapID != -1 && referencePlayer->GetMapId() != uint32(achievement->mapID))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: %s (Id: %u Type %s) Wrong map",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
+ return false;
+ }
+
+ if ((achievement->requiredFaction == ACHIEVEMENT_FACTION_HORDE && referencePlayer->GetTeam() != HORDE) ||
+ (achievement->requiredFaction == ACHIEVEMENT_FACTION_ALLIANCE && referencePlayer->GetTeam() != ALLIANCE))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: %s (Id: %u Type %s) Wrong faction",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
return false;
+ }
- if (achievement->mapID != -1 && GetPlayer()->GetMapId() != uint32(achievement->mapID))
+ if (IsCompletedCriteria(criteria, achievement))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: %s (Id: %u Type %s) Is Completed",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
return false;
+ }
- if ((achievement->requiredFaction == ACHIEVEMENT_FACTION_HORDE && GetPlayer()->GetTeam() != HORDE) ||
- (achievement->requiredFaction == ACHIEVEMENT_FACTION_ALLIANCE && GetPlayer()->GetTeam() != ALLIANCE))
+ if (!RequirementsSatisfied(criteria, miscValue1, miscValue2, miscValue3, unit, referencePlayer))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: %s (Id: %u Type %s) Requirements not satisfied",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
return false;
+ }
+ if (!AdditionalRequirementsSatisfied(criteria, miscValue1, miscValue2, unit, referencePlayer))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: %s (Id: %u Type %s) Additional requirements not satisfied",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
+ return false;
+ }
+
+ if (!ConditionsSatisfied(criteria, referencePlayer))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: %s (Id: %u Type %s) Conditions not satisfied",
+ criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type));
+ return false;
+ }
+
+ return true;
+}
+
+template<class T>
+bool AchievementMgr<T>::ConditionsSatisfied(AchievementCriteriaEntry const* criteria, Player* referencePlayer) const
+{
for (uint32 i = 0; i < MAX_CRITERIA_REQUIREMENTS; ++i)
{
if (!criteria->additionalRequirements[i].additionalRequirement_type)
@@ -2186,11 +2300,11 @@ bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria,
switch (criteria->additionalRequirements[i].additionalRequirement_type)
{
case ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP:
- if (GetPlayer()->GetMapId() != criteria->additionalRequirements[i].additionalRequirement_value)
+ if (referencePlayer->GetMapId() != criteria->additionalRequirements[i].additionalRequirement_value)
return false;
break;
case ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP:
- if (GetPlayer()->GetGroup())
+ if (referencePlayer->GetGroup())
return false;
break;
default:
@@ -2198,13 +2312,739 @@ bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria,
}
}
- // don't update already completed criteria
- if (IsCompletedCriteria(criteria, achievement))
- return false;
+ return true;
+}
+template<class T>
+bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const* achievementCriteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer) const
+{
+ switch (AchievementCriteriaTypes(achievementCriteria->type))
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
+ case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
+ case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
+ case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
+ if (!miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
+ case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ if (m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) == m_completedAchievements.end())
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ if (!miscValue1 || achievementCriteria->win_bg.bgMapID != referencePlayer->GetMapId())
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ if (!miscValue1 || achievementCriteria->kill_creature.creatureID != miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ // update at loading or specific skill update
+ if (miscValue1 && miscValue1 != achievementCriteria->reach_skill_level.skillID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ // update at loading or specific skill update
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_level.skillID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ if (miscValue1 && miscValue1 != achievementCriteria->complete_quests_in_zone.zoneID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ if (!miscValue1 || referencePlayer->GetMapId() != achievementCriteria->complete_battleground.mapID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ if (!miscValue1 || referencePlayer->GetMapId() != achievementCriteria->death_at_map.mapID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
+ {
+ if (!miscValue1)
+ return false;
+ // skip wrong arena achievements, if not achievIdByArenaSlot then normal total death counter
+ bool notfit = false;
+ for (int j = 0; j < MAX_ARENA_SLOT; ++j)
+ {
+ if (achievIdByArenaSlot[j] == achievementCriteria->achievement)
+ {
+ Battleground* bg = referencePlayer->GetBattleground();
+ if (!bg || !bg->isArena() || ArenaTeam::GetSlotByType(bg->GetArenaType()) != j)
+ notfit = true;
+ break;
+ }
+ }
+ if (notfit)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ {
+ if (!miscValue1)
+ return false;
+
+ Map const* map = referencePlayer->IsInWorld() ? referencePlayer->GetMap() : sMapMgr->FindMap(referencePlayer->GetMapId(), referencePlayer->GetInstanceId());
+ if (!map || !map->IsDungeon())
+ return false;
+
+ // search case
+ bool found = false;
+ for (int j = 0; achievIdForDungeon[j][0]; ++j)
+ {
+ if (achievIdForDungeon[j][0] == achievementCriteria->achievement)
+ {
+ if (map->IsRaid())
+ {
+ // if raid accepted (ignore difficulty)
+ if (!achievIdForDungeon[j][2])
+ break; // for
+ }
+ else if (referencePlayer->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL)
+ {
+ // dungeon in normal mode accepted
+ if (!achievIdForDungeon[j][1])
+ break; // for
+ }
+ else
+ {
+ // dungeon in heroic mode accepted
+ if (!achievIdForDungeon[j][3])
+ break; // for
+ }
+
+ found = true;
+ break; // for
+ }
+ }
+ if (!found)
+ return false;
+
+ //FIXME: work only for instances where max == min for players
+ if (((InstanceMap*)map)->GetMaxPlayers() != achievementCriteria->death_in_dungeon.manLimit)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ if (!miscValue1 || miscValue1 != achievementCriteria->killed_by_creature.creatureEntry)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ if (!miscValue1 || !unit || unit->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
+ if (!miscValue1 || miscValue2 != achievementCriteria->death_from.type)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
+ {
+ // if miscValues != 0, it contains the questID.
+ if (miscValue1)
+ {
+ if (miscValue1 != achievementCriteria->complete_quest.questID)
+ return false;
+ }
+ else
+ {
+ // login case.
+ if (!referencePlayer->GetQuestRewardStatus(achievementCriteria->complete_quest.questID))
+ return false;
+ }
+
+ if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
+ if (!data->Meets(referencePlayer, unit))
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ if (!miscValue1 || miscValue1 != achievementCriteria->be_spell_target.spellID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ if (!miscValue1 || miscValue1 != achievementCriteria->cast_spell.spellID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_spell.spellID)
+ return false;
+
+ if (!referencePlayer->HasSpell(achievementCriteria->learn_spell.spellID))
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
+ // miscValue1 = itemId - miscValue2 = count of item loot
+ // miscValue3 = loot_type (note: 0 = LOOT_CORPSE and then it ignored)
+ if (!miscValue1 || !miscValue2 || !miscValue3 || miscValue3 != achievementCriteria->loot_type.lootType)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ if (miscValue1 && achievementCriteria->own_item.itemID != miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ if (!miscValue1 || achievementCriteria->use_item.itemID != miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ if (!miscValue1 || miscValue1 != achievementCriteria->own_item.itemID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ {
+ WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference);
+ if (!worldOverlayEntry)
+ break;
+
+ bool matchFound = false;
+ for (int j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
+ {
+ uint32 area_id = worldOverlayEntry->areatableID[j];
+ if (!area_id) // array have 0 only in empty tail
+ break;
+
+ int32 exploreFlag = GetAreaFlagByAreaID(area_id);
+ if (exploreFlag < 0)
+ continue;
+
+ uint32 playerIndexOffset = uint32(exploreFlag) / 32;
+ uint32 mask = 1 << (uint32(exploreFlag) % 32);
+
+ if (referencePlayer->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
+ {
+ matchFound = true;
+ break;
+ }
+ }
+
+ if (!matchFound)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
+ if (miscValue1 && miscValue1 != achievementCriteria->gain_reputation.factionID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ // miscValue1 = itemid miscValue2 = itemSlot
+ if (!miscValue1 || miscValue2 != achievementCriteria->equip_epic_item.itemSlot)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ {
+ // miscValue1 = itemid miscValue2 = diced value
+ if (!miscValue1 || miscValue2 != achievementCriteria->roll_greed_on_loot.rollValue)
+ return false;
+
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!proto)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ if (!miscValue1 || miscValue1 != achievementCriteria->do_emote.emoteID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
+ case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
+ if (!miscValue1)
+ return false;
+
+ if (achievementCriteria->additionalRequirements[0].additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP)
+ {
+ if (referencePlayer->GetMapId() != achievementCriteria->additionalRequirements[0].additionalRequirement_value)
+ return false;
+
+ // map specific case (BG in fact) expected player targeted damage/heal
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ }
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
+ // miscValue1 = item_id
+ if (!miscValue1 || miscValue1 != achievementCriteria->equip_item.itemID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
+ if (!miscValue1 || miscValue1 != achievementCriteria->use_gameobject.goEntry)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ if (!miscValue1 || miscValue1 != achievementCriteria->fish_in_gameobject.goEntry)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_skillline_spell.skillLine)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ {
+ if (!miscValue1)
+ return false;
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!proto || proto->Quality < ITEM_QUALITY_EPIC)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_line.skillLine)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
+ if (!miscValue1 || miscValue1 != achievementCriteria->hk_class.classID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
+ if (!miscValue1 || miscValue1 != achievementCriteria->hk_race.raceID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ if (!miscValue1 || miscValue1 != achievementCriteria->bg_objective.objectiveId)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ if (!miscValue1 || miscValue1 != achievementCriteria->honorable_kill_at_area.areaID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
+ if (!miscValue1 || !miscValue2 || int64(miscValue2) < 0
+ || miscValue1 != achievementCriteria->currencyGain.currency)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
+ if (miscValue1 != achievementCriteria->win_arena.mapID)
+ return false;
+ break;
+ default:
+ break;
+ }
return true;
}
+template<class T>
+bool AchievementMgr<T>::AdditionalRequirementsSatisfied(AchievementCriteriaEntry const* criteria, uint64 miscValue1, uint64 /*miscValue2*/, Unit const* unit, Player* referencePlayer) const
+{
+ for (uint8 i = 0; i < MAX_ADDITIONAL_CRITERIA_CONDITIONS; ++i)
+ {
+ uint32 reqType = criteria->additionalConditionType[i];
+ uint32 reqValue = criteria->additionalConditionValue[i];
+
+ switch (AchievementCriteriaAdditionalCondition(reqType))
+ {
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY: // 4
+ if (!unit || unit->GetEntry() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER: // 5
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD: // 6
+ if (!unit || unit->IsAlive())
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY: // 7
+ if (!unit || !referencePlayer->IsHostileTo(unit))
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA: // 8
+ if (!referencePlayer->HasAura(reqValue))
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA: // 10
+ if (!unit || !unit->HasAura(reqValue))
+ return false;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE: // 11
+ if (!unit || !unit->HasAuraType(AuraType(reqValue)))
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN: // 14
+ {
+ // miscValue1 is itemid
+ ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!item || item->Quality < reqValue)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS: // 15
+ {
+ // miscValue1 is itemid
+ ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!item || item->Quality != reqValue)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE: // 17
+ {
+ uint32 zoneId, areaId;
+ referencePlayer->GetZoneAndAreaId(zoneId, areaId);
+ if (zoneId != reqValue && areaId != reqValue)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE: // 18
+ {
+ if (!unit)
+ return false;
+ uint32 zoneId, areaId;
+ unit->GetZoneAndAreaId(zoneId, areaId);
+ if (zoneId != reqValue && areaId != reqValue)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY: // 20
+ if (uint32(referencePlayer->GetMap()->GetDifficulty()) != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE: // 25
+ if (referencePlayer->getRace() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS: // 26
+ if (referencePlayer->getClass() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE: // 27
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER || unit->getRace() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS: // 28
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER || unit->getClass() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS: // 29
+ if (referencePlayer->GetGroup() && referencePlayer->GetGroup()->GetMembersCount() >= reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE: // 30
+ {
+ if (!unit)
+ return false;
+ Creature const* const creature = unit->ToCreature();
+ if (!creature || creature->GetCreatureType() != reqValue)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP: // 32
+ if (referencePlayer->GetMapId() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX: // 38
+ // miscValue1 is title's bit index
+ if (miscValue1 != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL: // 39
+ if (referencePlayer->getLevel() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL: // 40
+ if (!unit || unit->getLevel() != reqValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE: // 41
+ if (!unit || unit->GetZoneId() != reqValue)
+ return false;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW: // 46
+ if (!unit || unit->GetHealthPct() >= reqValue)
+ return false;
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+char const* AchievementGlobalMgr::GetCriteriaTypeString(uint32 type)
+{
+ return GetCriteriaTypeString(AchievementCriteriaTypes(type));
+}
+
+char const* AchievementGlobalMgr::GetCriteriaTypeString(AchievementCriteriaTypes type)
+{
+ switch (type)
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ return "KILL_CREATURE";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ return "TYPE_WIN_BG";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS:
+ return "COMPLETE_RESEARCH";
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ return "REACH_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ return "REACH_SKILL_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ return "COMPLETE_ACHIEVEMENT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ return "COMPLETE_QUEST_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
+ return "COMPLETE_DAILY_QUEST_DAILY";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ return "COMPLETE_QUESTS_IN_ZONE";
+ case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
+ return "CURRENCY";
+ case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
+ return "DAMAGE_DONE";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ return "COMPLETE_DAILY_QUEST";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ return "COMPLETE_BATTLEGROUND";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ return "DEATH_AT_MAP";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
+ return "DEATH";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ return "DEATH_IN_DUNGEON";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
+ return "COMPLETE_RAID";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ return "KILLED_BY_CREATURE";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ return "KILLED_BY_PLAYER";
+ case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ return "FALL_WITHOUT_DYING";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
+ return "DEATHS_FROM";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
+ return "COMPLETE_QUEST";
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ return "BE_SPELL_TARGET";
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ return "CAST_SPELL";
+ case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ return "BG_OBJECTIVE_CAPTURE";
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ return "HONORABLE_KILL_AT_AREA";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
+ return "WIN_ARENA";
+ case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA:
+ return "PLAY_ARENA";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
+ return "LEARN_SPELL";
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
+ return "HONORABLE_KILL";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ return "OWN_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ return "WIN_RATED_ARENA";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
+ return "HIGHEST_TEAM_RATING";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ return "HIGHEST_PERSONAL_RATING";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ return "LEARN_SKILL_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ return "USE_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ return "LOOT_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ return "EXPLORE_AREA";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
+ return "OWN_RANK";
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
+ return "BUY_BANK_SLOT";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
+ return "GAIN_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ return "GAIN_EXALTED_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ return "VISIT_BARBER_SHOP";
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ return "EQUIP_EPIC_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ return "ROLL_NEED_ON_LOOT";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ return "GREED_ON_LOOT";
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
+ return "HK_CLASS";
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
+ return "HK_RACE";
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ return "DO_EMOTE";
+ case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
+ return "HEALING_DONE";
+ case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
+ return "GET_KILLING_BLOWS";
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
+ return "EQUIP_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
+ return "MONEY_FROM_VENDORS";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
+ return "GOLD_SPENT_FOR_TALENTS";
+ case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ return "NUMBER_OF_TALENT_RESETS";
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
+ return "MONEY_FROM_QUEST_REWARD";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
+ return "GOLD_SPENT_FOR_TRAVELLING";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
+ return "GOLD_SPENT_AT_BARBER";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+ return "GOLD_SPENT_FOR_MAIL";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
+ return "LOOT_MONEY";
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
+ return "USE_GAMEOBJECT";
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ return "BE_SPELL_TARGET2";
+ case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ return "SPECIAL_PVP_KILL";
+ case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ return "FISH_IN_GAMEOBJECT";
+ case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
+ return "ON_LOGIN";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ return "LEARN_SKILLLINE_SPELLS";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
+ return "WIN_DUEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
+ return "LOSE_DUEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ return "KILL_CREATURE_TYPE";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
+ return "GOLD_EARNED_BY_AUCTIONS";
+ case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
+ return "CREATE_AUCTION";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
+ return "HIGHEST_AUCTION_BID";
+ case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
+ return "WON_AUCTIONS";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
+ return "HIGHEST_AUCTION_SOLD";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
+ return "HIGHEST_GOLD_VALUE_OWNED";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
+ return "GAIN_REVERED_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
+ return "GAIN_HONORED_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
+ return "KNOWN_FACTIONS";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ return "LOOT_EPIC_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ return "RECEIVE_EPIC_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
+ return "ROLL_NEED";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
+ return "ROLL_GREED";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
+ return "HIT_DEALT";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
+ return "HIT_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
+ return "TOTAL_DAMAGE_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST:
+ return "HIGHEST_HEAL_CAST";
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
+ return "TOTAL_HEALING_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
+ return "HIGHEST_HEALING_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
+ return "QUEST_ABANDONED";
+ case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ return "FLIGHT_PATHS_TAKEN";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
+ return "LOOT_TYPE";
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ return "CAST_SPELL2";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
+ return "LEARN_SKILL_LINE";
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
+ return "EARN_HONORABLE_KILL";
+ case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ return "ACCEPTED_SUMMONINGS";
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
+ return "EARN_ACHIEVEMENT_POINTS";
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ return "USE_LFD_TO_GROUP_WITH_PLAYERS";
+ case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS:
+ return "SPENT_GOLD_GUILD_REPAIRS";
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ return "REACH_GUILD_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD:
+ return "CRAFT_ITEMS_GUILD";
+ case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL:
+ return "CATCH_FROM_POOL";
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS:
+ return "BUY_GUILD_BANK_SLOTS";
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS:
+ return "EARN_GUILD_ACHIEVEMENT_POINTS";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND:
+ return "WIN_RATED_BATTLEGROUND";
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING:
+ return "REACH_BG_RATING";
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD:
+ return "BUY_GUILD_TABARD";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD:
+ return "COMPLETE_QUESTS_GUILD";
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD:
+ return "HONORABLE_KILLS_GUILD";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD:
+ return "KILL_CREATURE_TYPE_GUILD";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE:
+ return "GUILD_CHALLENGE_TYPE";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
+ return "GUILD_CHALLENGE";
+ }
+ return "MISSING_TYPE";
+}
+
+template class AchievementMgr<Guild>;
+template class AchievementMgr<Player>;
+
//==========================================================
void AchievementGlobalMgr::LoadAchievementCriteriaList()
{
@@ -2216,23 +3056,28 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList()
return;
}
- uint32 loaded = 0;
+ uint32 criterias = 0;
+ uint32 guildCriterias = 0;
for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId)
{
AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(entryId);
if (!criteria)
continue;
- m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria);
- m_AchievementCriteriaListByAchievement[criteria->referredAchievement].push_back(criteria);
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->achievement);
- if (criteria->timeLimit)
- m_AchievementCriteriasByTimedType[criteria->timedType].push_back(criteria);
+ m_AchievementCriteriaListByAchievement[criteria->achievement].push_back(criteria);
+
+ if (achievement && achievement->flags & ACHIEVEMENT_FLAG_GUILD)
+ ++guildCriterias, m_GuildAchievementCriteriasByType[criteria->type].push_back(criteria);
+ else
+ ++criterias, m_AchievementCriteriasByType[criteria->type].push_back(criteria);
- ++loaded;
+ if (criteria->timeLimit)
+ m_AchievementCriteriasByTimedType[criteria->timedCriteriaStartType].push_back(criteria);
}
- TC_LOG_INFO("server.loading", ">> Loaded %u achievement criteria in %u ms", loaded, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded %u achievement criteria and %u guild achievement crieteria in %u ms", criterias, guildCriterias, GetMSTimeDiffToNow(oldMSTime));
}
void AchievementGlobalMgr::LoadAchievementReferenceList()
@@ -2322,79 +3167,6 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
}
while (result->NextRow());
- // post loading checks
- for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId)
- {
- AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(entryId);
- if (!criteria)
- continue;
-
- switch (criteria->requiredType)
- {
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
- case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
- case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
- case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
- // achievement requires db data
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
- {
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->referredAchievement);
- if (!achievement)
- continue;
-
- // exist many achievements with this criteria, use at this moment hardcoded check to skil simple case
- if (achievement->ID == 1282)
- break;
-
- continue;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA: // need skip generic cases
- if (criteria->additionalRequirements[0].additionalRequirement_type != ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE)
- continue;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: // need skip generic cases
- if (criteria->do_emote.count == 0)
- continue;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: // skip statistics
- if (criteria->win_duel.duelCount == 0)
- continue;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: // need skip generic cases
- if (criteria->loot_type.lootTypeCount != 1)
- continue;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // only Children's Week achievements
- {
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->referredAchievement);
- if (!achievement)
- continue;
- if (achievement->categoryId != CATEGORY_CHILDRENS_WEEK)
- continue;
- break;
- }
- default: // type not use DB data, ignore
- continue;
- }
-
- if (!GetCriteriaDataSet(criteria) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, entryId, NULL))
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` does not have expected data for criteria (Entry: %u Type: %u) for achievement %u.", criteria->ID, criteria->requiredType, criteria->referredAchievement);
- }
-
TC_LOG_INFO("server.loading", ">> Loaded %u additional achievement criteria data in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index 219a8fd52fb..efa3e3ce5fa 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -39,26 +39,25 @@ typedef std::unordered_map<uint32, AchievementEntryList> AchievementList
struct CriteriaProgress
{
- uint32 counter;
+ uint64 counter;
time_t date; // latest update time.
+ uint64 CompletedGUID; // GUID of the player that completed this criteria (guild achievements)
bool changed;
};
enum AchievementCriteriaDataType
-{ // value1 value2 comment
- ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0, // 0 0
- ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1, // creature_id 0
- ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // class_id race_id
- ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH= 3, // health_percent 0
- ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4, // own_team 0 not corpse (not released body), own_team == false if enemy team expected
- ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5, // spell_id effect_idx
- ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA = 6, // area id 0
- ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7, // spell_id effect_idx
- ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE = 8, // minvalue value provided with achievement update must be not less that limit
- ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL = 9, // minlevel minlevel of target
+{ // value1 value2 comment
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0, // 0 0
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1, // creature_id 0
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // class_id race_id
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH= 3, // health_percent 0
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5, // spell_id effect_idx
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7, // spell_id effect_idx
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE = 8, // minvalue value provided with achievement update must be not less that limit
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL = 9, // minlevel minlevel of target
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER = 10, // gender 0=male; 1=female
ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT = 11, // scripted requirement
- ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY = 12, // difficulty normal/heroic difficulty for current event map
+ // REUSE
ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13, // count "with less than %u people in the zone"
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM = 14, // team HORDE(67), ALLIANCE(469)
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK = 15, // drunken_state 0 (enum DrunkenState) of player
@@ -68,11 +67,12 @@ enum AchievementCriteriaDataType
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19, // item_level item_quality for equipped item in slot to check item level and quality
ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20, // map_id 0 player must be on map with id in map_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21, // class_id race_id
- ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY = 22, // N login on day of N-th Birthday
- ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23 // title_id known (pvp) title, values from dbc
-};
+ // REUSE
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23, // title_id known (pvp) title, values from dbc
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT = 24, // game_event_id 0
-#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 24 // maximum value in AchievementCriteriaDataType enum
+ MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE
+};
struct AchievementCriteriaData
{
@@ -97,11 +97,6 @@ struct AchievementCriteriaData
{
uint32 percent;
} health;
- // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4
- struct
- {
- uint32 own_team_flag;
- } player_dead;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7
struct
@@ -109,11 +104,6 @@ struct AchievementCriteriaData
uint32 spell_id;
uint32 effect_idx;
} aura;
- // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA = 6
- struct
- {
- uint32 id;
- } area;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE = 8
struct
{
@@ -131,11 +121,6 @@ struct AchievementCriteriaData
uint32 gender;
} gender;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT = 11 (no data)
- // ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY = 12
- struct
- {
- uint32 difficulty;
- } difficulty;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13
struct
{
@@ -174,17 +159,17 @@ struct AchievementCriteriaData
{
uint32 mapId;
} map_id;
- // ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY = 21
- struct
- {
- uint32 nth_birthday;
- } birthday_login;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_KNOWN_TITLE = 22
struct
{
uint32 title_id;
} known_title;
- // ...
+ // ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT = 24
+ struct
+ {
+ uint32 id;
+ } game_event;
+ // raw
struct
{
uint32 value1;
@@ -248,6 +233,7 @@ typedef std::unordered_map<uint32, AchievementRewardLocale> AchievementRewardLoc
struct CompletedAchievementData
{
time_t date;
+ std::set<uint64> guids;
bool changed;
};
@@ -261,45 +247,53 @@ enum ProgressType
PROGRESS_HIGHEST
};
+template<class T>
class AchievementMgr
{
public:
- AchievementMgr(Player* player);
+ AchievementMgr(T* owner);
~AchievementMgr();
void Reset();
static void DeleteFromDB(uint32 lowguid);
void LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult);
void SaveToDB(SQLTransaction& trans);
- void ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, bool evenIfCriteriaComplete = false);
- void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, Unit* unit = NULL);
- void CompletedAchievement(AchievementEntry const* entry);
- void CheckAllAchievementCriteria();
- void SendAllAchievementData() const;
- void SendRespondInspectAchievements(Player* player) const;
+ void ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, bool evenIfCriteriaComplete = false);
+ void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, Unit const* unit = NULL, Player* referencePlayer = NULL);
+ void CompletedAchievement(AchievementEntry const* entry, Player* referencePlayer);
+ void CheckAllAchievementCriteria(Player* referencePlayer);
+ void SendAllAchievementData(Player* receiver) const;
+ void SendAchievementInfo(Player* receiver, uint32 achievementId = 0) const;
bool HasAchieved(uint32 achievementId) const;
- Player* GetPlayer() const { return m_player; }
+ T* GetOwner() const { return _owner; }
+
void UpdateTimedAchievements(uint32 timeDiff);
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry); // used for quest and scripted timed achievements
+ uint32 GetAchievementPoints() const { return _achievementPoints; }
private:
void SendAchievementEarned(AchievementEntry const* achievement) const;
void SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const;
CriteriaProgress* GetCriteriaProgress(AchievementCriteriaEntry const* entry);
- void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype = PROGRESS_SET);
+ void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint64 changeValue, Player* referencePlayer, ProgressType ptype = PROGRESS_SET);
void RemoveCriteriaProgress(AchievementCriteriaEntry const* entry);
- void CompletedCriteriaFor(AchievementEntry const* achievement);
+ void CompletedCriteriaFor(AchievementEntry const* achievement, Player* referencePlayer);
bool IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement);
bool IsCompletedAchievement(AchievementEntry const* entry);
- bool CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement);
- void BuildAllDataPacket(WorldPacket* data) const;
+ bool CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer);
+ void SendPacket(WorldPacket* data) const;
- Player* m_player;
+ bool ConditionsSatisfied(AchievementCriteriaEntry const* criteria, Player* referencePlayer) const;
+ bool RequirementsSatisfied(AchievementCriteriaEntry const* criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer) const;
+ bool AdditionalRequirementsSatisfied(AchievementCriteriaEntry const* criteria, uint64 miscValue1, uint64 miscValue2, Unit const* unit, Player* referencePlayer) const;
+
+ T* _owner;
CriteriaProgressMap m_criteriaProgress;
CompletedAchievementMap m_completedAchievements;
typedef std::map<uint32, uint32> TimedAchievementMap;
TimedAchievementMap m_timedAchievements; // Criteria id/time left in MS
+ uint32 _achievementPoints;
};
class AchievementGlobalMgr
@@ -308,15 +302,18 @@ class AchievementGlobalMgr
~AchievementGlobalMgr() { }
public:
+ static char const* GetCriteriaTypeString(AchievementCriteriaTypes type);
+ static char const* GetCriteriaTypeString(uint32 type);
+
static AchievementGlobalMgr* instance()
{
static AchievementGlobalMgr instance;
return &instance;
}
- AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type) const
+ AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type, bool guild = false) const
{
- return m_AchievementCriteriasByType[type];
+ return guild ? m_GuildAchievementCriteriasByType[type] : m_AchievementCriteriasByType[type];
}
AchievementCriteriaEntryList const& GetTimedAchievementCriteriaByType(AchievementCriteriaTimedTypes type) const
@@ -364,6 +361,24 @@ class AchievementGlobalMgr
m_allCompletedAchievements.insert(achievement->ID);
}
+ bool IsGroupCriteriaType(AchievementCriteriaTypes type) const
+ {
+ switch (type)
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: // NYI
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: // NYI
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND: // NYI
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+ }
+
void LoadAchievementCriteriaList();
void LoadAchievementCriteriaData();
void LoadAchievementReferenceList();
@@ -377,6 +392,7 @@ class AchievementGlobalMgr
// store achievement criterias by type to speed up lookup
AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
+ AchievementCriteriaEntryList m_GuildAchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
AchievementCriteriaEntryList m_AchievementCriteriasByTimedType[ACHIEVEMENT_TIMED_TYPE_MAX];
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index f4699f0519e..40935a0712c 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -231,7 +231,7 @@ void AuctionHouseMgr::SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 new
}
//this function sends mail, when auction is cancelled to old bidder
-void AuctionHouseMgr::SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans)
+void AuctionHouseMgr::SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans, Item* item)
{
uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER);
Player* bidder = ObjectAccessor::FindPlayer(bidder_guid);
@@ -240,6 +240,9 @@ void AuctionHouseMgr::SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQ
if (!bidder)
bidder_accId = sObjectMgr->GetPlayerAccountIdByGUID(bidder_guid);
+ if (bidder)
+ bidder->GetSession()->SendAuctionRemovedNotification(auction->Id, auction->itemEntry, item->GetItemRandomPropertyId());
+
// bidder exist
if (bidder || bidder_accId)
MailDraft(auction->BuildAuctionMailSubject(AUCTION_CANCELLED_TO_BIDDER), AuctionEntry::BuildAuctionMailBody(auction->owner, auction->bid, auction->buyout, auction->deposit, 0))
@@ -574,7 +577,7 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player
if (itemRandProp)
{
- char* const* temp = itemRandProp->nameSuffix;
+ char* temp = itemRandProp->nameSuffix;
// dbc local name
if (temp)
@@ -614,7 +617,7 @@ bool AuctionEntry::BuildAuctionInfo(WorldPacket& data) const
data << uint32(Id);
data << uint32(item->GetEntry());
- for (uint8 i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; ++i)
+ for (uint8 i = 0; i < PROP_ENCHANTMENT_SLOT_0; ++i) // PROP_ENCHANTMENT_SLOT_0 = 10
{
data << uint32(item->GetEnchantmentId(EnchantmentSlot(i)));
data << uint32(item->GetEnchantmentDuration(EnchantmentSlot(i)));
@@ -627,13 +630,13 @@ bool AuctionEntry::BuildAuctionInfo(WorldPacket& data) const
data << uint32(item->GetSpellCharges()); // item->charge FFFFFFF
data << uint32(0); // Unknown
data << uint64(owner); // Auction->owner
- data << uint32(startbid); // Auction->startbid (not sure if useful)
- data << uint32(bid ? GetAuctionOutBid() : 0);
+ data << uint64(startbid); // Auction->startbid (not sure if useful)
+ data << uint64(bid ? GetAuctionOutBid() : 0);
// Minimal outbid
- data << uint32(buyout); // Auction->buyout
+ data << uint64(buyout); // Auction->buyout
data << uint32((expire_time - time(NULL)) * IN_MILLISECONDS); // time left
data << uint64(bidder); // auction->bidder current
- data << uint32(bid); // current bid
+ data << uint64(bid); // current bid
return true;
}
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h
index 597da13cb1b..8e74b4c53a6 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.h
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h
@@ -166,7 +166,7 @@ class AuctionHouseMgr
void SendAuctionSuccessfulMail(AuctionEntry* auction, SQLTransaction& trans);
void SendAuctionExpiredMail(AuctionEntry* auction, SQLTransaction& trans);
void SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 newPrice, Player* newBidder, SQLTransaction& trans);
- void SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans);
+ void SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans, Item* item);
static uint32 GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 time, Item* pItem, uint32 count);
static AuctionHouseEntry const* GetAuctionHouseEntry(uint32 factionTemplateId);
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index b04d0d360ee..5ef3426d602 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -37,6 +37,7 @@ Battlefield::Battlefield()
m_isActive = false;
m_DefenderTeam = TEAM_NEUTRAL;
+ m_Guid = 0;
m_TypeId = 0;
m_BattleId = 0;
m_ZoneId = 0;
@@ -106,7 +107,7 @@ void Battlefield::HandlePlayerLeaveZone(Player* player, uint32 /*zone*/)
if (m_PlayersInWar[player->GetTeamId()].find(player->GetGUID()) != m_PlayersInWar[player->GetTeamId()].end())
{
m_PlayersInWar[player->GetTeamId()].erase(player->GetGUID());
- player->GetSession()->SendBfLeaveMessage(m_BattleId);
+ player->GetSession()->SendBfLeaveMessage(m_Guid);
if (Group* group = player->GetGroup()) // Remove the player from the raid group
group->RemoveMember(player->GetGUID());
@@ -210,7 +211,7 @@ void Battlefield::InvitePlayerToQueue(Player* player)
return;
if (m_PlayersInQueue[player->GetTeamId()].size() <= m_MinPlayer || m_PlayersInQueue[GetOtherTeam(player->GetTeamId())].size() >= m_MinPlayer)
- player->GetSession()->SendBfInvitePlayerToQueue(m_BattleId);
+ player->GetSession()->SendBfInvitePlayerToQueue(m_Guid);
}
void Battlefield::InvitePlayersInQueueToWar()
@@ -279,7 +280,7 @@ void Battlefield::InvitePlayerToWar(Player* player)
m_PlayersWillBeKick[player->GetTeamId()].erase(player->GetGUID());
m_InvitedPlayers[player->GetTeamId()][player->GetGUID()] = time(NULL) + m_TimeForAcceptInvite;
- player->GetSession()->SendBfInvitePlayerToWar(m_BattleId, m_ZoneId, m_TimeForAcceptInvite);
+ player->GetSession()->SendBfInvitePlayerToWar(m_Guid, m_ZoneId, m_TimeForAcceptInvite);
}
void Battlefield::InitStalker(uint32 entry, Position const& pos)
@@ -357,6 +358,7 @@ void Battlefield::DoPlaySoundToAll(uint32 SoundID)
WorldPacket data;
data.Initialize(SMSG_PLAY_SOUND, 4);
data << uint32(SoundID);
+ data << uint64(0);
for (int team = 0; team < BG_TEAMS_COUNT; team++)
for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
@@ -375,7 +377,7 @@ void Battlefield::PlayerAcceptInviteToQueue(Player* player)
// Add player in queue
m_PlayersInQueue[player->GetTeamId()].insert(player->GetGUID());
// Send notification
- player->GetSession()->SendBfQueueInviteResponse(m_BattleId, m_ZoneId);
+ player->GetSession()->SendBfQueueInviteResponse(m_Guid, m_ZoneId);
}
// Called in WorldSession::HandleBfExitRequest
@@ -393,7 +395,7 @@ void Battlefield::PlayerAcceptInviteToWar(Player* player)
if (AddOrSetPlayerToCorrectBfGroup(player))
{
- player->GetSession()->SendBfEntered(m_BattleId);
+ player->GetSession()->SendBfEntered(m_Guid);
m_PlayersInWar[player->GetTeamId()].insert(player->GetGUID());
m_InvitedPlayers[player->GetTeamId()].erase(player->GetGUID());
@@ -476,14 +478,12 @@ void Battlefield::HideNpc(Creature* creature)
creature->CombatStop();
creature->SetReactState(REACT_PASSIVE);
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
- creature->SetPhaseMask(2, true);
creature->DisappearAndDie();
creature->SetVisible(false);
}
void Battlefield::ShowNpc(Creature* creature, bool aggressive)
{
- creature->SetPhaseMask(1, true);
creature->SetVisible(true);
creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
if (!creature->IsAlive())
@@ -796,7 +796,6 @@ Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, fl
delete creature;
return nullptr;
}
-
creature->SetHomePosition(x, y, z, o);
CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h
index 15498d1f045..0aa6a51d6bf 100644
--- a/src/server/game/Battlefield/Battlefield.h
+++ b/src/server/game/Battlefield/Battlefield.h
@@ -23,7 +23,8 @@
enum BattlefieldTypes
{
- BATTLEFIELD_WG // Wintergrasp
+ BATTLEFIELD_WG, // Wintergrasp
+ BATTLEFIELD_TB // Tol Barad (cataclysm)
};
enum BattlefieldIDs
@@ -222,6 +223,7 @@ class Battlefield : public ZoneScript
uint32 GetTypeId() { return m_TypeId; }
uint32 GetZoneId() { return m_ZoneId; }
+ uint64 GetGUID() { return m_Guid; }
void TeamApplyBuff(TeamId team, uint32 spellId, uint32 spellId2 = 0);
@@ -342,6 +344,8 @@ class Battlefield : public ZoneScript
void InitStalker(uint32 entry, Position const& pos);
protected:
+ uint64 m_Guid;
+
uint64 StalkerGuid;
uint32 m_Timer; // Global timer for event
bool m_IsEnabled;
diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp
index 8aa58f0ac4b..c531e22bc20 100644
--- a/src/server/game/Battlefield/BattlefieldMgr.cpp
+++ b/src/server/game/Battlefield/BattlefieldMgr.cpp
@@ -123,6 +123,15 @@ Battlefield* BattlefieldMgr::GetBattlefieldByBattleId(uint32 battleId)
return NULL;
}
+Battlefield* BattlefieldMgr::GetBattlefieldByGUID(uint64 guid)
+{
+ for (BattlefieldSet::iterator itr = _battlefieldSet.begin(); itr != _battlefieldSet.end(); ++itr)
+ if ((*itr)->GetGUID() == guid)
+ return *itr;
+
+ return NULL;
+}
+
ZoneScript* BattlefieldMgr::GetZoneScript(uint32 zoneId)
{
BattlefieldMap::iterator itr = _battlefieldMap.find(zoneId);
diff --git a/src/server/game/Battlefield/BattlefieldMgr.h b/src/server/game/Battlefield/BattlefieldMgr.h
index f51a7177a88..0fa4add13a8 100644
--- a/src/server/game/Battlefield/BattlefieldMgr.h
+++ b/src/server/game/Battlefield/BattlefieldMgr.h
@@ -44,6 +44,7 @@ class BattlefieldMgr
// return assigned battlefield
Battlefield* GetBattlefieldToZoneId(uint32 zoneId);
Battlefield* GetBattlefieldByBattleId(uint32 battleId);
+ Battlefield* GetBattlefieldByGUID(uint64 guid);
ZoneScript* GetZoneScript(uint32 zoneId);
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h
index 0ba9e816b2e..03c2992e812 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.h
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h
@@ -73,7 +73,7 @@ enum WintergraspSpells
// Other spells
SPELL_WINTERGRASP_WATER = 36444,
SPELL_ESSENCE_OF_WINTERGRASP = 58045,
- SPELL_WINTERGRASP_RESTRICTED_FLIGHT_AREA = 58730,
+ SPELL_WINTERGRASP_RESTRICTED_FLIGHT_AREA = 91604,
// Phasing spells
SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT = 56618, // ADDS PHASE 16
diff --git a/src/server/game/Battlegrounds/Arena.cpp b/src/server/game/Battlegrounds/Arena.cpp
index cdc6fc3cac0..7a72afa2b12 100644
--- a/src/server/game/Battlegrounds/Arena.cpp
+++ b/src/server/game/Battlegrounds/Arena.cpp
@@ -18,6 +18,8 @@
#include "Arena.h"
#include "ArenaScore.h"
#include "ArenaTeamMgr.h"
+#include "GuildMgr.h"
+#include "Guild.h"
#include "Language.h"
#include "ObjectAccessor.h"
#include "Player.h"
@@ -141,6 +143,7 @@ void Arena::EndBattleground(uint32 winner)
uint32 winnerMatchmakerRating = 0;
int32 winnerChange = 0;
int32 winnerMatchmakerChange = 0;
+ bool guildAwarded = false;
ArenaTeam* winnerArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(winner));
ArenaTeam* loserArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(winner)));
@@ -221,11 +224,20 @@ void Arena::EndBattleground(uint32 winner)
uint32 rating = player->GetArenaPersonalRating(winnerArenaTeam->GetSlot());
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA, GetMapId());
+ player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, sWorld->getIntConfig(CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD));
// Last standing - Rated 5v5 arena & be solely alive player
if (GetArenaType() == ARENA_TYPE_5v5 && aliveWinners == 1 && player->IsAlive())
player->CastSpell(player, SPELL_LAST_MAN_STANDING, true);
+ if (!guildAwarded)
+ {
+ guildAwarded = true;
+ if (uint32 guildId = GetBgMap()->GetOwnerGuildId(player->GetBGTeam()))
+ if (Guild* guild = sGuildMgr->GetGuildById(guildId))
+ guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, std::max<uint32>(winnerArenaTeam->GetRating(), 1), 0, 0, NULL, player);
+ }
+
winnerArenaTeam->MemberWon(player, loserMatchmakerRating, winnerMatchmakerChange);
}
else
diff --git a/src/server/game/Battlegrounds/ArenaScore.h b/src/server/game/Battlegrounds/ArenaScore.h
index 638275b1833..162cf729181 100644
--- a/src/server/game/Battlegrounds/ArenaScore.h
+++ b/src/server/game/Battlegrounds/ArenaScore.h
@@ -20,29 +20,76 @@
#include "BattlegroundScore.h"
#include "SharedDefines.h"
+#include "Player.h"
+#include "ObjectAccessor.h"
struct ArenaScore : public BattlegroundScore
{
friend class Arena;
protected:
- ArenaScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid), TeamId(team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE) { }
+ ArenaScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid, team), TeamId(team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE) { }
- void AppendToPacket(WorldPacket& data) final
+ void AppendToPacket(WorldPacket& data, ByteBuffer& content) final
{
- data << uint64(PlayerGuid);
+ uint32 primaryTree = 0;
+ if (Player* player = ObjectAccessor::FindPlayer(PlayerGuid))
+ primaryTree = player->GetPrimaryTalentTree(player->GetActiveSpec());
- data << uint32(KillingBlows);
- data << uint8(TeamId);
- data << uint32(DamageDone);
- data << uint32(HealingDone);
+ data.WriteBit(0); // Unk 1
+ data.WriteBit(0); // Unk 2
+ data.WriteBit(PlayerGuid[2]);
+ data.WriteBit(/*!IsArena*/ 0); // IsArena
+ data.WriteBit(0); // Unk 4
+ data.WriteBit(0); // Unk 5
+ data.WriteBit(0); // Unk 6
+ data.WriteBit(PlayerGuid[3]);
+ data.WriteBit(PlayerGuid[0]);
+ data.WriteBit(PlayerGuid[5]);
+ data.WriteBit(PlayerGuid[1]);
+ data.WriteBit(PlayerGuid[6]);
+ data.WriteBit(TeamId);
+ data.WriteBit(PlayerGuid[7]);
- BuildObjectivesBlock(data);
+ content << uint32(HealingDone); // healing done
+ content << uint32(DamageDone); // damage done
+
+ content.WriteByteSeq(PlayerGuid[4]);
+ content << uint32(KillingBlows);
+
+ //if (unk5)
+ // content << int32(RatingChange); // RatingChange
+
+ content.WriteByteSeq(PlayerGuid[5]);
+
+ //if (unk 6)
+ // content << uint32();
+
+ //if (unk 2)
+ // content << uint32();
+
+ content.WriteByteSeq(PlayerGuid[1]);
+ content.WriteByteSeq(PlayerGuid[6]);
+
+ content << int32(primaryTree);
+
+ BuildObjectivesBlock(data, content);
+
+ data.WriteBit(PlayerGuid[4]);
+
+ content.WriteByteSeq(PlayerGuid[0]);
+ content.WriteByteSeq(PlayerGuid[3]);
+
+ //if (unk 4)
+ // content << uint32() unk
+
+ content.WriteByteSeq(PlayerGuid[7]);
+ content.WriteByteSeq(PlayerGuid[2]);
}
- void BuildObjectivesBlock(WorldPacket& data) final
+ void BuildObjectivesBlock(WorldPacket& data, ByteBuffer& /*content*/) final
{
- data << uint32(0); // Objectives Count
+ data.WriteBits(0, 24); // Objectives Count
}
// For Logging purpose
@@ -86,14 +133,19 @@ struct ArenaTeamScore
uint32 ratingWon = std::max(RatingChange, 0);
// should be old rating, new rating, and client will calculate rating change itself
+ data << uint32(MatchmakerRating);
data << uint32(ratingLost);
data << uint32(ratingWon);
- data << uint32(MatchmakerRating);
+ }
+
+ void BuildTeamInfoLengthBlock(WorldPacket& data)
+ {
+ data.WriteBits(TeamName.length(), 8);
}
void BuildTeamInfoBlock(WorldPacket& data)
{
- data << TeamName;
+ data.WriteString(TeamName);
}
int32 RatingChange;
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp
index 2ca60534f30..17d95dbbe6b 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeam.cpp
@@ -41,14 +41,16 @@ ArenaTeam::ArenaTeam()
ArenaTeam::~ArenaTeam()
{ }
-bool ArenaTeam::Create(uint64 captainGuid, uint8 type, std::string const& teamName, uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor, uint8 borderStyle, uint32 borderColor)
+bool ArenaTeam::Create(uint64 captainGuid, uint8 type, std::string const& arenaTeamName,
+ uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor,
+ uint8 borderStyle, uint32 borderColor)
{
// Check if captain is present
if (!ObjectAccessor::FindPlayer(captainGuid))
return false;
// Check if arena team name is already taken
- if (sArenaTeamMgr->GetArenaTeamByName(teamName))
+ if (sArenaTeamMgr->GetArenaTeamByName(arenaTeamName))
return false;
// Generate new arena team id
@@ -57,7 +59,7 @@ bool ArenaTeam::Create(uint64 captainGuid, uint8 type, std::string const& teamNa
// Assign member variables
CaptainGuid = captainGuid;
Type = type;
- TeamName = teamName;
+ TeamName = arenaTeamName;
BackgroundColor = backgroundColor;
EmblemStyle = emblemStyle;
EmblemColor = emblemColor;
@@ -179,7 +181,7 @@ bool ArenaTeam::AddMember(uint64 playerGuid)
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1);
}
- TC_LOG_INFO("bg.arena", "Player: %s [GUID: %u] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), GUID_LOPART(playerGuid), GetType(), GetId(), GetName().c_str());
+ TC_LOG_DEBUG("bg.arena", "Player: %s [GUID: %u] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), GUID_LOPART(playerGuid), GetType(), GetId(), GetName().c_str());
return true;
}
@@ -321,10 +323,9 @@ void ArenaTeam::DelMember(uint64 guid, bool cleanDb)
break;
}
- // Inform player and remove arena team info from player data
+ // Remove arena team info from player data
if (Player* player = ObjectAccessor::FindPlayer(guid))
{
- player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0);
// delete all info regarding this team
for (uint32 i = 0; i < ARENA_TEAM_END; ++i)
player->SetArenaTeamInfoField(GetSlot(), ArenaTeamInfoType(i), 0);
@@ -343,19 +344,18 @@ void ArenaTeam::DelMember(uint64 guid, bool cleanDb)
void ArenaTeam::Disband(WorldSession* session)
{
- // Remove all members from arena team
- while (!Members.empty())
- DelMember(Members.front().Guid, false);
-
// Broadcast update
if (session)
{
BroadcastEvent(ERR_ARENA_TEAM_DISBANDED_S, 0, 2, session->GetPlayerName(), GetName(), "");
-
if (Player* player = session->GetPlayer())
TC_LOG_DEBUG("bg.arena", "Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u, Name: %s].", player->GetName().c_str(), player->GetGUIDLow(), GetType(), GetId(), GetName().c_str());
}
+ // Remove all members from arena team
+ while (!Members.empty())
+ DelMember(Members.front().Guid, false);
+
// Update database
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -580,6 +580,20 @@ uint8 ArenaTeam::GetSlotByType(uint32 type)
return 0xFF;
}
+uint8 ArenaTeam::GetTypeBySlot(uint8 slot)
+{
+ switch (slot)
+ {
+ case 0: return ARENA_TEAM_2v2;
+ case 1: return ARENA_TEAM_3v3;
+ case 2: return ARENA_TEAM_5v5;
+ default:
+ break;
+ }
+ TC_LOG_ERROR("bg.arena", "FATAL: Unknown arena team slot %u for some arena team", slot);
+ return 0xFF;
+}
+
bool ArenaTeam::IsMember(uint64 guid) const
{
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
@@ -589,32 +603,6 @@ bool ArenaTeam::IsMember(uint64 guid) const
return false;
}
-uint32 ArenaTeam::GetPoints(uint32 memberRating)
-{
- // Returns how many points would be awarded with this team type with this rating
- float points;
-
- uint32 rating = memberRating + 150 < Stats.Rating ? memberRating : Stats.Rating;
-
- if (rating <= 1500)
- {
- if (sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) < 6)
- points = (float)rating * 0.22f + 14.0f;
- else
- points = 344;
- }
- else
- points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating));
-
- // Type penalties for teams < 5v5
- if (Type == ARENA_TEAM_2v2)
- points *= 0.76f;
- else if (Type == ARENA_TEAM_3v3)
- points *= 0.88f;
-
- return (uint32) points;
-}
-
uint32 ArenaTeam::GetAverageMMR(Group* group) const
{
if (!group)
@@ -628,7 +616,7 @@ uint32 ArenaTeam::GetAverageMMR(Group* group) const
if (!ObjectAccessor::FindPlayer(itr->Guid))
continue;
- // Skip if player is not member of group
+ // Skip if player is not a member of group
if (!group->IsMember(itr->Guid))
continue;
@@ -652,7 +640,7 @@ float ArenaTeam::GetChanceAgainst(uint32 ownRating, uint32 opponentRating)
return 1.0f / (1.0f + exp(log(10.0f) * (float)((float)opponentRating - (float)ownRating) / 650.0f));
}
-int32 ArenaTeam::GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float& confidence_factor*/)
+int32 ArenaTeam::GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won)
{
// 'Chance' calculation - to beat the opponent
// This is a simulation. Not much info on how it really works
@@ -731,17 +719,17 @@ void ArenaTeam::FinishGame(int32 mod)
}
}
-int32 ArenaTeam::WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change)
+int32 ArenaTeam::WonAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32& ratingChange)
{
// Called when the team has won
// Change in Matchmaker rating
- int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, true);
+ int32 mod = GetMatchmakerRatingMod(ownMMRating, opponentMMRating, true);
// Change in Team Rating
- rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, true);
+ ratingChange = GetRatingMod(Stats.Rating, opponentMMRating, true);
// Modify the team stats accordingly
- FinishGame(rating_change);
+ FinishGame(ratingChange);
// Update number of wins per season and week
Stats.WeekWins += 1;
@@ -751,23 +739,23 @@ int32 ArenaTeam::WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32
return mod;
}
-int32 ArenaTeam::LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change)
+int32 ArenaTeam::LostAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32& ratingChange)
{
// Called when the team has lost
// Change in Matchmaker Rating
- int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, false);
+ int32 mod = GetMatchmakerRatingMod(ownMMRating, opponentMMRating, false);
// Change in Team Rating
- rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, false);
+ ratingChange = GetRatingMod(Stats.Rating, opponentMMRating, false);
// Modify the team stats accordingly
- FinishGame(rating_change);
+ FinishGame(ratingChange);
// return the rating change, used to display it on the results screen
return mod;
}
-void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
+void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange)
{
// Called for each participant of a match after losing
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
@@ -779,7 +767,7 @@ void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32
itr->ModifyPersonalRating(player, mod, GetType());
// Update matchmaker rating
- itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
+ itr->ModifyMatchmakerRating(matchmakerRatingChange, GetSlot());
// Update personal played stats
itr->WeekGames +=1;
@@ -793,7 +781,7 @@ void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32
}
}
-void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
+void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 matchmakerRatingChange)
{
// Called for offline player after ending rated arena match!
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
@@ -805,7 +793,7 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, i
itr->ModifyPersonalRating(NULL, mod, GetType());
// update matchmaker rating
- itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
+ itr->ModifyMatchmakerRating(matchmakerRatingChange, GetSlot());
// update personal played stats
itr->WeekGames += 1;
@@ -815,7 +803,7 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, i
}
}
-void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
+void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange)
{
// called for each participant after winning a match
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
@@ -827,7 +815,7 @@ void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32
itr->ModifyPersonalRating(player, mod, GetType());
// update matchmaker rating
- itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
+ itr->ModifyMatchmakerRating(matchmakerRatingChange, GetSlot());
// update personal stats
itr->WeekGames +=1;
@@ -842,36 +830,6 @@ void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32
}
}
-void ArenaTeam::UpdateArenaPointsHelper(std::map<uint32, uint32>& playerPoints)
-{
- // Called after a match has ended and the stats are already modified
- // Helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons)
- // 10 played games per week is a minimum
- if (Stats.WeekGames < 10)
- return;
-
- // To get points, a player has to participate in at least 30% of the matches
- uint32 requiredGames = (uint32)ceil(Stats.WeekGames * 0.3f);
-
- for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
- {
- // The player participated in enough games, update his points
- uint32 pointsToAdd = 0;
- if (itr->WeekGames >= requiredGames)
- pointsToAdd = GetPoints(itr->PersonalRating);
-
- std::map<uint32, uint32>::iterator plr_itr = playerPoints.find(GUID_LOPART(itr->Guid));
- if (plr_itr != playerPoints.end())
- {
- // Check if there is already more points
- if (plr_itr->second < pointsToAdd)
- playerPoints[GUID_LOPART(itr->Guid)] = pointsToAdd;
- }
- else
- playerPoints[GUID_LOPART(itr->Guid)] = pointsToAdd;
- }
-}
-
void ArenaTeam::SaveToDB()
{
// Save team and member stats to db
diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h
index d3b6342b273..c4f6201434f 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.h
+++ b/src/server/game/Battlegrounds/ArenaTeam.h
@@ -19,8 +19,10 @@
#ifndef TRINITYCORE_ARENATEAM_H
#define TRINITYCORE_ARENATEAM_H
+#include "Define.h"
#include "QueryResult.h"
#include <list>
+#include <string>
#include <map>
class WorldSession;
@@ -38,6 +40,7 @@ enum ArenaTeamCommandTypes
enum ArenaTeamCommandErrors
{
+ ERR_ARENA_TEAM_CREATED = 0x00,
ERR_ARENA_TEAM_INTERNAL = 0x01,
ERR_ALREADY_IN_ARENA_TEAM = 0x02,
ERR_ALREADY_IN_ARENA_TEAM_S = 0x03,
@@ -56,7 +59,8 @@ enum ArenaTeamCommandErrors
ERR_ARENA_TEAM_TARGET_TOO_HIGH_S = 0x16,
ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S = 0x17,
ERR_ARENA_TEAM_NOT_FOUND = 0x1B,
- ERR_ARENA_TEAMS_LOCKED = 0x1E
+ ERR_ARENA_TEAMS_LOCKED = 0x1E,
+ ERR_ARENA_TEAM_TOO_MANY_CREATE = 0x21,
};
enum ArenaTeamEvents
@@ -69,14 +73,6 @@ enum ArenaTeamEvents
ERR_ARENA_TEAM_DISBANDED_S = 8 // captain name + arena team name
};
-/*
-need info how to send these ones:
-ERR_ARENA_TEAM_YOU_JOIN_S - client show it automatically when accept invite
-ERR_ARENA_TEAM_TARGET_TOO_LOW_S
-ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S
-ERR_ARENA_TEAM_LEVEL_TOO_LOW_I
-*/
-
enum ArenaTeamTypes
{
ARENA_TEAM_2v2 = 2,
@@ -118,17 +114,20 @@ class ArenaTeam
ArenaTeam();
~ArenaTeam();
- bool Create(uint64 captainGuid, uint8 type, std::string const& teamName, uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor, uint8 borderStyle, uint32 borderColor);
+ bool Create(uint64 captainGuid, uint8 type, std::string const& teamName,
+ uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor,
+ uint8 borderStyle, uint32 borderColor);
void Disband(WorldSession* session);
void Disband();
typedef std::list<ArenaTeamMember> MemberList;
- uint32 GetId() const { return TeamId; }
- uint32 GetType() const { return Type; }
- uint8 GetSlot() const { return GetSlotByType(GetType()); }
+ uint32 GetId() const { return TeamId; }
+ uint32 GetType() const { return Type; }
+ uint8 GetSlot() const { return GetSlotByType(GetType()); }
static uint8 GetSlotByType(uint32 type);
- uint64 GetCaptain() const { return CaptainGuid; }
+ static uint8 GetTypeBySlot(uint8 slot);
+ uint64 GetCaptain() const { return CaptainGuid; }
std::string const& GetName() const { return TeamName; }
const ArenaTeamStats& GetStats() const { return Stats; }
@@ -138,9 +137,6 @@ class ArenaTeam
void SetCaptain(uint64 guid);
bool SetName(std::string const& name);
bool AddMember(uint64 PlayerGuid);
-
- // Shouldn't be uint64 ed, because than can reference guid from members on Disband
- // and this method removes given record from list. So invalid reference can happen.
void DelMember(uint64 guid, bool cleanDb);
size_t GetMembersSize() const { return Members.size(); }
@@ -170,27 +166,26 @@ class ArenaTeam
void SendStats(WorldSession* session);
void Inspect(WorldSession* session, uint64 guid);
- uint32 GetPoints(uint32 MemberRating);
- int32 GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
- int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
- float GetChanceAgainst(uint32 ownRating, uint32 opponentRating);
- int32 WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change);
- void MemberWon(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange);
- int32 LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change);
- void MemberLost(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange = -12);
- void OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange = -12);
+ static int32 GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
+ static int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
+ static float GetChanceAgainst(uint32 ownRating, uint32 opponentRating);
+
+ int32 WonAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32& rating_change);
+ void MemberWon(Player* player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange = 12);
- void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints);
+ int32 LostAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32& rating_change);
+ void MemberLost(Player* player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange = -12);
+ void OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 matchmakerRatingChange = -12);
void FinishWeek();
void FinishGame(int32 mod);
protected:
- uint32 TeamId;
- uint8 Type;
+ uint32 TeamId;
+ uint8 Type;
std::string TeamName;
- uint64 CaptainGuid;
+ uint64 CaptainGuid;
uint32 BackgroundColor; // ARGB format
uint8 EmblemStyle; // icon id
@@ -198,7 +193,7 @@ class ArenaTeam
uint8 BorderStyle; // border image id
uint32 BorderColor; // ARGB format
- MemberList Members;
+ MemberList Members;
ArenaTeamStats Stats;
};
#endif
diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
index cd49158b5d0..0098c8a1bcb 100644
--- a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
@@ -134,59 +134,3 @@ void ArenaTeamMgr::LoadArenaTeams()
TC_LOG_INFO("server.loading", ">> Loaded %u arena teams in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-
-void ArenaTeamMgr::DistributeArenaPoints()
-{
- // Used to distribute arena points based on last week's stats
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_START);
-
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_START);
-
- // Temporary structure for storing maximum points to add values for all players
- std::map<uint32, uint32> PlayerPoints;
-
- // At first update all points for all team members
- for (ArenaTeamContainer::iterator teamItr = GetArenaTeamMapBegin(); teamItr != GetArenaTeamMapEnd(); ++teamItr)
- if (ArenaTeam* at = teamItr->second)
- at->UpdateArenaPointsHelper(PlayerPoints);
-
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
-
- PreparedStatement* stmt;
-
- // Cycle that gives points to all players
- for (std::map<uint32, uint32>::iterator playerItr = PlayerPoints.begin(); playerItr != PlayerPoints.end(); ++playerItr)
- {
- // Add points to player if online
- if (Player* player = HashMapHolder<Player>::Find(playerItr->first))
- player->ModifyArenaPoints(playerItr->second, trans);
- else // Update database
- {
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_CHAR_ARENA_POINTS);
- stmt->setUInt32(0, playerItr->second);
- stmt->setUInt32(1, playerItr->first);
- trans->Append(stmt);
- }
- }
-
- CharacterDatabase.CommitTransaction(trans);
-
- PlayerPoints.clear();
-
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_END);
-
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_START);
- for (ArenaTeamContainer::iterator titr = GetArenaTeamMapBegin(); titr != GetArenaTeamMapEnd(); ++titr)
- {
- if (ArenaTeam* at = titr->second)
- {
- at->FinishWeek();
- at->SaveToDB();
- at->NotifyStatsChanged();
- }
- }
-
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_END);
-
- sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_END);
-}
diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.h b/src/server/game/Battlegrounds/ArenaTeamMgr.h
index 118e9674fbf..eaf39278c28 100644
--- a/src/server/game/Battlegrounds/ArenaTeamMgr.h
+++ b/src/server/game/Battlegrounds/ArenaTeamMgr.h
@@ -46,8 +46,6 @@ public:
ArenaTeamContainer::iterator GetArenaTeamMapBegin() { return ArenaTeamStore.begin(); }
ArenaTeamContainer::iterator GetArenaTeamMapEnd() { return ArenaTeamStore.end(); }
- void DistributeArenaPoints();
-
uint32 GenerateArenaTeamId();
void SetNextArenaTeamId(uint32 Id) { NextArenaTeamId = Id; }
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 86236cd0f2b..584117e7666 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -26,6 +26,8 @@
#include "Formulas.h"
#include "GridNotifiersImpl.h"
#include "Group.h"
+#include "GuildMgr.h"
+#include "Guild.h"
#include "MapManager.h"
#include "Object.h"
#include "ObjectMgr.h"
@@ -112,6 +114,7 @@ void Battleground::BroadcastWorker(Do& _do)
Battleground::Battleground()
{
+ m_Guid = 0;
m_TypeID = BATTLEGROUND_TYPE_NONE;
m_RandomTypeID = BATTLEGROUND_TYPE_NONE;
m_InstanceID = 0;
@@ -126,6 +129,7 @@ Battleground::Battleground()
m_IsArena = false;
_winnerTeamId = BG_TEAM_NEUTRAL;
m_StartTime = 0;
+ m_CountdownTimer = 0;
m_ResetStatTimer = 0;
m_ValidStartPositionTimer = 0;
m_Events = 0;
@@ -244,7 +248,7 @@ void Battleground::Update(uint32 diff)
// after 47 minutes without one team losing, the arena closes with no winner and no rating change
if (isArena())
{
- if (GetStartTime() >= 47 * MINUTE*IN_MILLISECONDS)
+ if (GetElapsedTime() >= 47 * MINUTE*IN_MILLISECONDS)
{
EndBattleground(0);
return;
@@ -267,8 +271,12 @@ void Battleground::Update(uint32 diff)
}
// Update start time and reset stats timer
- m_StartTime += diff;
- m_ResetStatTimer += diff;
+ SetElapsedTime(GetElapsedTime() + diff);
+ if (GetStatus() == STATUS_WAIT_JOIN)
+ {
+ m_ResetStatTimer += diff;
+ m_CountdownTimer += diff;
+ }
PostUpdateImpl(diff);
}
@@ -429,6 +437,9 @@ inline void Battleground::_ProcessJoin(uint32 diff)
// *********************************************************
ModifyStartDelayTime(diff);
+ if (!isArena())
+ SetRemainingTime(300000);
+
if (m_ResetStatTimer > 5000)
{
m_ResetStatTimer = 0;
@@ -437,6 +448,23 @@ inline void Battleground::_ProcessJoin(uint32 diff)
player->ResetAllPowers();
}
+ // Send packet every 10 seconds until the 2nd field reach 0
+ if (m_CountdownTimer >= 10000)
+ {
+ uint32 countdownMaxForBGType = isArena() ? ARENA_COUNTDOWN_MAX : BATTLEGROUND_COUNTDOWN_MAX;
+
+ WorldPacket data(SMSG_START_TIMER, 4+4+4);
+ data << uint32(0); // unk
+ data << uint32(countdownMaxForBGType - (GetElapsedTime() / 1000));
+ data << uint32(countdownMaxForBGType);
+
+ for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
+ if (Player* player = ObjectAccessor::FindPlayer(itr->first))
+ player->GetSession()->SendPacket(&data);
+
+ m_CountdownTimer = 0;
+ }
+
if (!(m_Events & BG_STARTING_EVENT_1))
{
m_Events |= BG_STARTING_EVENT_1;
@@ -494,8 +522,12 @@ inline void Battleground::_ProcessJoin(uint32 diff)
WorldPacket status;
BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(m_TypeID, GetArenaType());
uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&status, this, queueSlot, STATUS_IN_PROGRESS, 0, GetStartTime(), GetArenaType(), player->GetBGTeam());
- player->SendDirectMessage(&status);
+
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&status, this, player, queueSlot, STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(m_TypeID), GetElapsedTime(), GetArenaType());
+ player->GetSession()->SendPacket(&status);
+
+ // Correctly display EnemyUnitFrame
+ player->SetByteValue(PLAYER_BYTES_3, 3, player->GetBGTeam());
player->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
player->ResetAllPowers();
@@ -536,6 +568,9 @@ inline void Battleground::_ProcessJoin(uint32 diff)
sWorld->SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName().c_str(), GetMinLevel(), GetMaxLevel());
}
}
+
+ if (GetRemainingTime() > 0 && (m_EndTime -= diff) > 0)
+ SetRemainingTime(GetRemainingTime() - diff);
}
inline void Battleground::_ProcessLeave(uint32 diff)
@@ -544,10 +579,10 @@ inline void Battleground::_ProcessLeave(uint32 diff)
// *** BATTLEGROUND ENDING SYSTEM ***
// *********************************************************
// remove all players from battleground after 2 minutes
- m_EndTime -= diff;
- if (m_EndTime <= 0)
+ SetRemainingTime(GetRemainingTime() - diff);
+ if (GetRemainingTime() <= 0)
{
- m_EndTime = 0;
+ SetRemainingTime(0);
BattlegroundPlayerMap::iterator itr, next;
for (itr = m_Players.begin(); itr != m_Players.end(); itr = next)
{
@@ -711,6 +746,7 @@ void Battleground::EndBattleground(uint32 winner)
RemoveFromBGFreeSlotQueue();
int32 winmsg_id = 0;
+ bool guildAwarded = false;
if (winner == ALLIANCE)
{
@@ -735,7 +771,7 @@ void Battleground::EndBattleground(uint32 winner)
SetStatus(STATUS_WAIT_LEAVE);
//we must set it this way, because end time is sent in packet!
- m_EndTime = TIME_TO_AUTOREMOVE;
+ SetRemainingTime(TIME_AUTOCLOSE_BATTLEGROUND);
WorldPacket pvpLogData;
BuildPvPLogDataPacket(pvpLogData);
@@ -766,28 +802,44 @@ void Battleground::EndBattleground(uint32 winner)
player->getHostileRefManager().deleteReferences();
}
- uint32 winner_kills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_FIRST);
- uint32 loser_kills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST);
- uint32 winner_arena = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_ARENA_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_ARENA_FIRST);
+ // remove temporary currency bonus auras before rewarding player
+ player->RemoveAura(SPELL_HONORABLE_DEFENDER_25Y);
+ player->RemoveAura(SPELL_HONORABLE_DEFENDER_60Y);
+
+ uint32 winnerKills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_FIRST);
+ uint32 loserKills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST);
// Reward winner team
if (team == winner)
{
if (IsRandom() || BattlegroundMgr::IsBGWeekend(GetTypeID()))
{
- UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(winner_kills));
- if (CanAwardArenaPoints())
- player->ModifyArenaPoints(winner_arena);
+ UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(winnerKills));
if (!player->GetRandomWinner())
+ {
+ // 100cp awarded for the first random battleground won each day
+ player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST));
player->SetRandomWinner(true);
+ }
}
+ else // 50cp awarded for each non-rated battleground won
+ player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_CONQUEST_LAST));
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1);
+ if (!guildAwarded)
+ {
+ guildAwarded = true;
+ if (uint32 guildId = GetBgMap()->GetOwnerGuildId(player->GetBGTeam()))
+ {
+ if (Guild* guild = sGuildMgr->GetGuildById(guildId))
+ guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1, 0, 0, NULL, player);
+ }
+ }
}
else
{
if (IsRandom() || BattlegroundMgr::IsBGWeekend(GetTypeID()))
- UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(loser_kills));
+ UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(loserKills));
}
player->ResetAllPowers();
@@ -798,8 +850,9 @@ void Battleground::EndBattleground(uint32 winner)
player->SendDirectMessage(&pvpLogData);
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType(), player->GetBGTeam());
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(GetTypeID()), GetElapsedTime(), GetArenaType());
player->SendDirectMessage(&data);
+
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
}
@@ -861,10 +914,11 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
RemovePlayer(player, guid, team); // BG subclass specific code
+ BattlegroundTypeId bgTypeId = GetTypeID();
+ BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
+
if (participant) // if the player was a match participant, remove auras, calc rating, update queue
{
- BattlegroundTypeId bgTypeId = GetTypeID();
- BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
if (player)
{
player->ClearAfkReports();
@@ -882,7 +936,7 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
if (SendPacket)
{
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0, 0, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_NONE, player->GetBattlegroundQueueJoinTime(bgTypeId), 0, 0);
player->SendDirectMessage(&data);
}
@@ -916,6 +970,7 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG.
// reset destination bg team
player->SetBGTeam(0);
+ player->RemoveBattlegroundQueueJoinTime(bgTypeId);
if (Transport)
player->TeleportToBGEntryPoint();
@@ -931,8 +986,8 @@ void Battleground::Reset()
{
SetWinner(BG_TEAM_NEUTRAL);
SetStatus(STATUS_WAIT_QUEUE);
- SetStartTime(0);
- SetEndTime(0);
+ SetElapsedTime(0);
+ SetRemainingTime(0);
SetLastResurrectTime(0);
m_Events = 0;
@@ -958,7 +1013,7 @@ void Battleground::Reset()
void Battleground::StartBattleground()
{
- SetStartTime(0);
+ SetElapsedTime(0);
SetLastResurrectTime(0);
// add BG to free slot queue
AddToBGFreeSlotQueue();
@@ -982,10 +1037,12 @@ void Battleground::AddPlayer(Player* player)
uint64 guid = player->GetGUID();
uint32 team = player->GetBGTeam();
+ int32 primaryTree = player->GetPrimaryTalentTree(player->GetActiveSpec());
BattlegroundPlayer bp;
bp.OfflineRemoveTime = 0;
bp.Team = team;
+ bp.PrimaryTree = primaryTree;
// Add to list/maps
m_Players[guid] = bp;
@@ -993,9 +1050,16 @@ void Battleground::AddPlayer(Player* player)
UpdatePlayersCountByTeam(team, false); // +1 player
WorldPacket data;
- sBattlegroundMgr->BuildPlayerJoinedBattlegroundPacket(&data, player);
+ sBattlegroundMgr->BuildPlayerJoinedBattlegroundPacket(&data, player->GetGUID());
SendPacketToTeam(team, &data, player, false);
+ // BG Status packet
+ BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(m_TypeID, GetArenaType());
+ uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
+
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, queueSlot, STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(m_TypeID), GetElapsedTime(), GetArenaType());
+ player->GetSession()->SendPacket(&data);
+
player->RemoveAurasByType(SPELL_AURA_MOUNTED);
// add arena specific auras
@@ -1014,7 +1078,16 @@ void Battleground::AddPlayer(Player* player)
else
{
if (GetStatus() == STATUS_WAIT_JOIN) // not started yet
+ {
player->CastSpell(player, SPELL_PREPARATION, true); // reduces all mana cost of spells.
+
+ int32 countdownMaxForBGType = isArena() ? ARENA_COUNTDOWN_MAX : BATTLEGROUND_COUNTDOWN_MAX;
+ WorldPacket data(SMSG_START_TIMER, 4+4+4);
+ data << uint32(0); // unk
+ data << uint32(countdownMaxForBGType - (GetElapsedTime() / 1000));
+ data << uint32(countdownMaxForBGType);
+ player->GetSession()->SendPacket(&data);
+ }
}
player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
@@ -1190,31 +1263,51 @@ bool Battleground::HasFreeSlots() const
void Battleground::BuildPvPLogDataPacket(WorldPacket& data)
{
- uint8 type = (isArena() ? 1 : 0);
+ ByteBuffer buff;
+
+ data.Initialize(SMSG_PVP_LOG_DATA, (1 + 1 + 4 + 40 * GetPlayerScoresSize()));
- data.Initialize(MSG_PVP_LOG_DATA, 1 + 1 + 4 + 40 * GetPlayerScoresSize());
- data << uint8(type); // type (battleground = 0 / arena = 1)
+ data.WriteBit(isRated());
+ data.WriteBit(isArena());
- if (type) // arena
+ if (isArena())
{
+ // it seems this must be according to BG_WINNER_A/H and _NOT_ TEAM_A/H
+ for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
+ _arenaTeamScores[i].BuildTeamInfoLengthBlock(data);
+ }
+
+ size_t countPos = data.bitwpos();
+ data.WriteBits(0, 21);
+ for (auto const& score : PlayerScores)
+ score.second->AppendToPacket(data, buff);
+
+ data.PutBits(countPos, GetPlayerScoresSize(), 21);
+ data.WriteBit(GetStatus() == STATUS_WAIT_LEAVE); // If Ended
+
+ if (isRated())
+ {
+ // it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
_arenaTeamScores[i].BuildRatingInfoBlock(data);
+ }
+ data.FlushBits();
+ data.append(buff);
+
+ if (isArena())
+ {
+ // it seems this must be according to BG_WINNER_A/H and _NOT_ TEAM_A/H
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
_arenaTeamScores[i].BuildTeamInfoBlock(data);
}
+ data << uint8(GetPlayersCountByTeam(HORDE));
+
if (GetStatus() == STATUS_WAIT_LEAVE)
- {
- data << uint8(1); // bg ended
- data << uint8(GetWinner()); // who win
- }
- else
- data << uint8(0); // bg not ended
+ data << uint8(GetWinner());
- data << uint32(GetPlayerScoresSize());
- for (auto const& score : PlayerScores)
- score.second->AppendToPacket(data);
+ data << uint8(GetPlayersCountByTeam(ALLIANCE));
}
bool Battleground::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
@@ -1302,6 +1395,7 @@ bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float
delete go;
return false;
}
+
/*
uint32 guid = go->GetGUIDLow();
@@ -1514,6 +1608,7 @@ bool Battleground::AddSpiritGuide(uint32 type, float x, float y, float z, float
creature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL);
// correct cast speed
creature->SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
+ creature->SetFloatValue(UNIT_MOD_CAST_HASTE, 1.0f);
//creature->CastSpell(creature, SPELL_SPIRIT_HEAL_CHANNEL, true);
return true;
}
@@ -1590,7 +1685,7 @@ void Battleground::EndNow()
{
RemoveFromBGFreeSlotQueue();
SetStatus(STATUS_WAIT_LEAVE);
- SetEndTime(0);
+ SetRemainingTime(0);
}
// To be removed
@@ -1710,7 +1805,7 @@ void Battleground::PlayerAddedToBGCheckIfBGIsRunning(Player* player)
BuildPvPLogDataPacket(data);
player->SendDirectMessage(&data);
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), player->GetBGTeam());
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(GetTypeID()), GetElapsedTime(), GetArenaType());
player->SendDirectMessage(&data);
}
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index c2e5b03e3ae..d04ff5171aa 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -118,12 +118,14 @@ enum BattlegroundTimeIntervals
RESURRECTION_INTERVAL = 30000, // ms
//REMIND_INTERVAL = 10000, // ms
INVITATION_REMIND_TIME = 20000, // ms
- INVITE_ACCEPT_WAIT_TIME = 60000, // ms
- TIME_TO_AUTOREMOVE = 120000, // ms
+ INVITE_ACCEPT_WAIT_TIME = 90000, // ms
+ TIME_AUTOCLOSE_BATTLEGROUND = 120000, // ms
MAX_OFFLINE_TIME = 300, // secs
RESPAWN_ONE_DAY = 86400, // secs
RESPAWN_IMMEDIATELY = 0, // secs
- BUFF_RESPAWN_TIME = 180 // secs
+ BUFF_RESPAWN_TIME = 180, // secs
+ BATTLEGROUND_COUNTDOWN_MAX = 120, // secs
+ ARENA_COUNTDOWN_MAX = 60 // secs
};
enum BattlegroundStartTimeIntervals
@@ -142,7 +144,7 @@ enum BattlegroundBuffObjects
BG_OBJECTID_BERSERKERBUFF_ENTRY = 179905
};
-const uint32 Buff_Entries[3] = { BG_OBJECTID_SPEEDBUFF_ENTRY, BG_OBJECTID_REGENBUFF_ENTRY, BG_OBJECTID_BERSERKERBUFF_ENTRY };
+uint32 const Buff_Entries[3] = { BG_OBJECTID_SPEEDBUFF_ENTRY, BG_OBJECTID_REGENBUFF_ENTRY, BG_OBJECTID_BERSERKERBUFF_ENTRY };
enum BattlegroundStatus
{
@@ -157,6 +159,7 @@ struct BattlegroundPlayer
{
time_t OfflineRemoveTime; // for tracking and removing offline players from queue after 5 minutes
uint32 Team; // Player's team
+ int32 PrimaryTree; // Player's primary tree
};
struct BattlegroundObjectInfo
@@ -237,13 +240,14 @@ class Battleground
/* Battleground */
// Get methods:
std::string const& GetName() const { return m_Name; }
+ uint64 GetGUID() { return m_Guid; }
BattlegroundTypeId GetTypeID(bool GetRandom = false) const { return GetRandom ? m_RandomTypeID : m_TypeID; }
BattlegroundBracketId GetBracketId() const { return m_BracketId; }
uint32 GetInstanceID() const { return m_InstanceID; }
BattlegroundStatus GetStatus() const { return m_Status; }
uint32 GetClientInstanceID() const { return m_ClientInstanceID; }
- uint32 GetStartTime() const { return m_StartTime; }
- uint32 GetEndTime() const { return m_EndTime; }
+ uint32 GetElapsedTime() const { return m_StartTime; }
+ uint32 GetRemainingTime() const { return m_EndTime; }
uint32 GetLastResurrectTime() const { return m_LastResurrectTime; }
uint32 GetMaxPlayers() const { return m_MaxPlayers; }
uint32 GetMinPlayers() const { return m_MinPlayers; }
@@ -262,6 +266,7 @@ class Battleground
bool IsRandom() const { return m_IsRandom; }
// Set methods:
+ void SetGuid(uint64 newGuid) { m_Guid = newGuid; }
void SetName(std::string const& name) { m_Name = name; }
void SetTypeID(BattlegroundTypeId TypeID) { m_TypeID = TypeID; }
void SetRandomTypeID(BattlegroundTypeId TypeID) { m_RandomTypeID = TypeID; }
@@ -270,8 +275,8 @@ class Battleground
void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; }
void SetStatus(BattlegroundStatus Status) { m_Status = Status; }
void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; }
- void SetStartTime(uint32 Time) { m_StartTime = Time; }
- void SetEndTime(uint32 Time) { m_EndTime = Time; }
+ void SetElapsedTime(uint32 Time) { m_StartTime = Time; }
+ void SetRemainingTime(uint32 Time) { m_EndTime = Time; }
void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; }
void SetMaxPlayers(uint32 MaxPlayers) { m_MaxPlayers = MaxPlayers; }
void SetMinPlayers(uint32 MinPlayers) { m_MinPlayers = MinPlayers; }
@@ -519,6 +524,7 @@ class Battleground
BattlegroundStatus m_Status;
uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;
+ uint32 m_CountdownTimer;
uint32 m_ResetStatTimer;
uint32 m_ValidStartPositionTimer;
int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
@@ -534,6 +540,7 @@ class Battleground
bool m_PrematureCountDown;
uint32 m_PrematureCountDownTimer;
std::string m_Name;
+ uint64 m_Guid;
/* Pre- and post-update hooks */
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index 82ea0901875..45111a80bc5 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -35,6 +35,8 @@
#include "BattlegroundDS.h"
#include "BattlegroundRV.h"
#include "BattlegroundIC.h"
+#include "BattlegroundTP.h"
+#include "BattlegroundBFG.h"
#include "Chat.h"
#include "Map.h"
#include "MapInstanced.h"
@@ -52,8 +54,7 @@
BattlegroundMgr::BattlegroundMgr() :
m_NextRatedArenaUpdate(sWorld->getIntConfig(CONFIG_ARENA_RATED_UPDATE_TIMER)),
- m_NextAutoDistributionTime(0),
- m_AutoDistributionTimeChecker(0), m_ArenaTesting(false), m_Testing(false)
+ m_ArenaTesting(false), m_Testing(false)
{ }
BattlegroundMgr::~BattlegroundMgr()
@@ -145,83 +146,284 @@ void BattlegroundMgr::Update(uint32 diff)
else
m_NextRatedArenaUpdate -= diff;
}
-
- if (sWorld->getBoolConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
- {
- if (m_AutoDistributionTimeChecker < diff)
- {
- if (time(NULL) > m_NextAutoDistributionTime)
- {
- sArenaTeamMgr->DistributeArenaPoints();
- m_NextAutoDistributionTime = m_NextAutoDistributionTime + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld->getIntConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS);
- sWorld->setWorldState(WS_ARENA_DISTRIBUTION_TIME, uint64(m_NextAutoDistributionTime));
- }
- m_AutoDistributionTimeChecker = 600000; // check 10 minutes
- }
- else
- m_AutoDistributionTimeChecker -= diff;
- }
}
-void BattlegroundMgr::BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype, uint32 arenaFaction)
+void BattlegroundMgr::BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, Player* player, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype)
{
- // we can be in 2 queues in same time...
+ ObjectGuid playerGuid = player->GetGUID();
+ ObjectGuid bgGuid;
- if (StatusID == 0 || !bg)
- {
- data->Initialize(SMSG_BATTLEFIELD_STATUS, 4+8);
- *data << uint32(QueueSlot); // queue id (0...1)
- *data << uint64(0);
- return;
- }
+ if (bg)
+ bgGuid = bg->GetGUID();
+ else
+ StatusID = STATUS_NONE;
- data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+8+1+1+4+1+4+4+4));
- *data << uint32(QueueSlot); // queue id (0...1) - player can be in 2 queues in time
- // The following segment is read as uint64 in client but can be appended as their original type.
- *data << uint8(arenatype);
- TC_LOG_DEBUG("network", "BattlegroundMgr::BuildBattlegroundStatusPacket: arenatype = %u for bg instanceID %u, TypeID %u.", arenatype, bg->GetClientInstanceID(), bg->GetTypeID());
- *data << uint8(bg->isArena() ? 0xE : 0x0);
- *data << uint32(bg->GetTypeID());
- *data << uint16(0x1F90);
- // End of uint64 segment, decomposed this way for simplicity
- *data << uint8(bg->GetMinLevel());
- *data << uint8(bg->GetMaxLevel());
- *data << uint32(bg->GetClientInstanceID());
- // alliance/horde for BG and skirmish/rated for Arenas
- // following displays the minimap-icon 0 = faction icon 1 = arenaicon
- *data << uint8(bg->isRated()); // 1 for rated match, 0 for bg or non rated match
-
- *data << uint32(StatusID); // status
switch (StatusID)
{
- case STATUS_WAIT_QUEUE: // status_in_queue
- *data << uint32(Time1); // average wait time, milliseconds
- *data << uint32(Time2); // time in queue, updated every minute!, milliseconds
+ case STATUS_NONE:
+ {
+ data->Initialize(SMSG_BATTLEFIELD_STATUS);
+
+ data->WriteBit(playerGuid[0]);
+ data->WriteBit(playerGuid[4]);
+ data->WriteBit(playerGuid[7]);
+ data->WriteBit(playerGuid[1]);
+ data->WriteBit(playerGuid[6]);
+ data->WriteBit(playerGuid[3]);
+ data->WriteBit(playerGuid[5]);
+ data->WriteBit(playerGuid[2]);
+
+ data->WriteByteSeq(playerGuid[5]);
+ data->WriteByteSeq(playerGuid[6]);
+ data->WriteByteSeq(playerGuid[7]);
+ data->WriteByteSeq(playerGuid[2]);
+ *data << uint32(1); // unk, always 1
+ data->WriteByteSeq(playerGuid[3]);
+ data->WriteByteSeq(playerGuid[1]);
+ *data << uint32(QueueSlot); // Queue slot
+ *data << uint32(Time1); // Join Time
+ data->WriteByteSeq(playerGuid[0]);
+ data->WriteByteSeq(playerGuid[4]);
break;
- case STATUS_WAIT_JOIN: // status_invite
- *data << uint32(bg->GetMapId()); // map id
- *data << uint64(0); // 3.3.5, unknown
- *data << uint32(Time1); // time to remove from queue, milliseconds
+ }
+ case STATUS_WAIT_QUEUE:
+ {
+ data->Initialize(SMSG_BATTLEFIELD_STATUS_QUEUED);
+
+ data->WriteBit(playerGuid[3]);
+ data->WriteBit(playerGuid[0]);
+ data->WriteBit(bgGuid[3]);
+ data->WriteBit(playerGuid[2]);
+ data->WriteBit(1); // Eligible In Queue
+ data->WriteBit(0); // Join Failed, 1 when it's arena ...
+ data->WriteBit(bgGuid[2]);
+ data->WriteBit(playerGuid[1]);
+ data->WriteBit(bgGuid[0]);
+ data->WriteBit(bgGuid[6]);
+ data->WriteBit(bgGuid[4]);
+ data->WriteBit(playerGuid[6]);
+ data->WriteBit(playerGuid[7]);
+ data->WriteBit(bgGuid[7]);
+ data->WriteBit(bgGuid[5]);
+ data->WriteBit(playerGuid[4]);
+ data->WriteBit(playerGuid[5]);
+ data->WriteBit(bg->isRated()); // Is Rated
+ data->WriteBit(0); // Waiting On Other Activity
+ data->WriteBit(bgGuid[1]);
+
+ data->FlushBits();
+
+ data->WriteByteSeq(playerGuid[0]);
+ *data << uint32(bg->isArena() ? arenatype : 1); // Player count, 1 for bgs, 2-3-5 for arena (2v2, 3v3, 5v5)
+ data->WriteByteSeq(bgGuid[5]);
+ data->WriteByteSeq(playerGuid[3]);
+ *data << uint32(Time1); // Estimated Wait Time
+ data->WriteByteSeq(bgGuid[7]);
+ data->WriteByteSeq(bgGuid[1]);
+ data->WriteByteSeq(bgGuid[2]);
+ *data << uint8(0); // unk
+ data->WriteByteSeq(bgGuid[4]);
+ data->WriteByteSeq(playerGuid[2]);
+ *data << uint8(0); // unk
+ data->WriteByteSeq(bgGuid[6]);
+ data->WriteByteSeq(playerGuid[7]);
+ data->WriteByteSeq(bgGuid[3]);
+ data->WriteByteSeq(playerGuid[6]);
+ data->WriteByteSeq(bgGuid[0]);
+ *data << uint32(Time2); // Join Time
+ *data << uint32(QueueSlot); // Queue slot
+ *data << uint8(bg->GetMinLevel()); // Min Level
+ *data << uint32(GetMSTimeDiffToNow(Time2)); // Time since joined
+ data->WriteByteSeq(playerGuid[1]);
+ data->WriteByteSeq(playerGuid[5]);
+ *data << uint32(bg->GetClientInstanceID()); // Client Instance ID
+ data->WriteByteSeq(playerGuid[4]);
break;
- case STATUS_IN_PROGRESS: // status_in_progress
- *data << uint32(bg->GetMapId()); // map id
- *data << uint64(0); // 3.3.5, unknown
- *data << uint32(Time1); // time to bg auto leave, 0 at bg start, 120000 after bg end, milliseconds
- *data << uint32(Time2); // time from bg start, milliseconds
- *data << uint8(arenaFaction == ALLIANCE ? 1 : 0); // arenafaction (0 for horde, 1 for alliance)
+ }
+ case STATUS_WAIT_JOIN:
+ {
+ data->Initialize(SMSG_BATTLEFIELD_STATUS_NEEDCONFIRMATION);
+
+ *data << uint32(bg->GetClientInstanceID()); // Client Instance ID
+ *data << uint32(Time1); // Time until closed
+ *data << uint8(0); // unk
+ *data << uint32(QueueSlot); // Queue slot
+ *data << uint32(Time2); // Join Time
+ *data << uint8(bg->GetMinLevel()); // Min Level
+ *data << uint32(bg->isArena() ? arenatype : 1); // Player count, 1 for bgs, 2-3-5 for arena (2v2, 3v3, 5v5)
+ *data << uint32(bg->GetMapId()); // Map Id
+ *data << uint8(0); // unk
+
+ data->WriteBit(playerGuid[5]);
+ data->WriteBit(playerGuid[2]);
+ data->WriteBit(playerGuid[1]);
+ data->WriteBit(bgGuid[2]);
+ data->WriteBit(playerGuid[4]);
+ data->WriteBit(bgGuid[6]);
+ data->WriteBit(bgGuid[3]);
+ data->WriteBit(bg->isRated()); // Is Rated
+ data->WriteBit(playerGuid[7]);
+ data->WriteBit(playerGuid[3]);
+ data->WriteBit(bgGuid[7]);
+ data->WriteBit(bgGuid[0]);
+ data->WriteBit(bgGuid[4]);
+ data->WriteBit(playerGuid[6]);
+ data->WriteBit(bgGuid[1]);
+ data->WriteBit(bgGuid[5]);
+ data->WriteBit(playerGuid[0]);
+
+ data->WriteByteSeq(bgGuid[6]);
+ data->WriteByteSeq(bgGuid[5]);
+ data->WriteByteSeq(bgGuid[7]);
+ data->WriteByteSeq(bgGuid[2]);
+ data->WriteByteSeq(playerGuid[0]);
+ data->WriteByteSeq(playerGuid[7]);
+ data->WriteByteSeq(bgGuid[4]);
+ data->WriteByteSeq(playerGuid[1]);
+ data->WriteByteSeq(bgGuid[0]);
+ data->WriteByteSeq(playerGuid[4]);
+ data->WriteByteSeq(bgGuid[1]);
+ data->WriteByteSeq(playerGuid[5]);
+ data->WriteByteSeq(bgGuid[3]);
+ data->WriteByteSeq(playerGuid[6]);
+ data->WriteByteSeq(playerGuid[2]);
+ data->WriteByteSeq(playerGuid[3]);
break;
- default:
- TC_LOG_ERROR("bg.battleground", "Unknown BG status!");
+ }
+ case STATUS_IN_PROGRESS:
+ {
+ data->Initialize(SMSG_BATTLEFIELD_STATUS_ACTIVE);
+
+ data->WriteBit(playerGuid[2]);
+ data->WriteBit(playerGuid[7]);
+ data->WriteBit(bgGuid[7]);
+ data->WriteBit(bgGuid[1]);
+ data->WriteBit(playerGuid[5]);
+ data->WriteBit(player->GetBGTeam() == HORDE ? 0 : 1);
+ data->WriteBit(bgGuid[0]);
+ data->WriteBit(playerGuid[1]);
+ data->WriteBit(bgGuid[3]);
+ data->WriteBit(playerGuid[6]);
+ data->WriteBit(bgGuid[5]);
+ data->WriteBit(bg->isRated()); // Is Rated
+ data->WriteBit(playerGuid[4]);
+ data->WriteBit(bgGuid[6]);
+ data->WriteBit(bgGuid[4]);
+ data->WriteBit(bgGuid[2]);
+ data->WriteBit(playerGuid[3]);
+ data->WriteBit(playerGuid[0]);
+
+ data->FlushBits();
+
+ data->WriteByteSeq(bgGuid[4]);
+ data->WriteByteSeq(bgGuid[5]);
+ data->WriteByteSeq(playerGuid[5]);
+ data->WriteByteSeq(bgGuid[1]);
+ data->WriteByteSeq(bgGuid[6]);
+ data->WriteByteSeq(bgGuid[3]);
+ data->WriteByteSeq(bgGuid[7]);
+ data->WriteByteSeq(playerGuid[6]);
+
+ *data << uint32(Time1); // Join Time
+ *data << uint8(0); // unk
+
+ data->WriteByteSeq(playerGuid[4]);
+ data->WriteByteSeq(playerGuid[1]);
+
+ *data << uint32(QueueSlot); // Queue slot
+ *data << uint8(0); // unk
+ *data << uint32(bg->isArena() ? arenatype : 1); // Player count, 1 for bgs, 2-3-5 for arena (2v2, 3v3, 5v5)
+ *data << uint32(bg->GetMapId()); // Map Id
+ *data << uint8(bg->GetMinLevel()); // Min Level
+ *data << uint32(Time2); // Elapsed Time
+
+ data->WriteByteSeq(playerGuid[2]);
+ *data << uint32(bg->GetRemainingTime()); // Remaining Time
+
+ data->WriteByteSeq(playerGuid[0]);
+ data->WriteByteSeq(playerGuid[3]);
+ data->WriteByteSeq(bgGuid[2]);
+
+ *data << uint32(bg->GetClientInstanceID()); // Client Instance ID or faction ?
+
+ data->WriteByteSeq(bgGuid[0]);
+ data->WriteByteSeq(playerGuid[7]);
+ break;
+ }
+ case STATUS_WAIT_LEAVE:
break;
}
}
-void BattlegroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result)
+void BattlegroundMgr::BuildStatusFailedPacket(WorldPacket* data, Battleground* bg, Player* player, uint8 QueueSlot, GroupJoinBattlegroundResult result)
{
- data->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
- *data << int32(result);
- if (result == ERR_BATTLEGROUND_JOIN_TIMED_OUT || result == ERR_BATTLEGROUND_JOIN_FAILED)
- *data << uint64(0); // player guid
+ ObjectGuid guidBytes1 = player->GetGUID(); // player who caused the error
+ ObjectGuid guidBytes2 = bg->GetGUID();
+ ObjectGuid unkGuid3 = 0;
+
+ data->Initialize(SMSG_BATTLEFIELD_STATUS_FAILED);
+
+ data->WriteBit(guidBytes2[3]);
+ data->WriteBit(unkGuid3[3]);
+ data->WriteBit(guidBytes1[3]);
+ data->WriteBit(unkGuid3[0]);
+ data->WriteBit(guidBytes2[6]);
+ data->WriteBit(guidBytes1[5]);
+ data->WriteBit(guidBytes1[6]);
+ data->WriteBit(guidBytes1[4]);
+
+ data->WriteBit(guidBytes1[2]);
+ data->WriteBit(unkGuid3[1]);
+ data->WriteBit(guidBytes2[1]);
+ data->WriteBit(unkGuid3[5]);
+ data->WriteBit(unkGuid3[6]);
+ data->WriteBit(guidBytes1[1]);
+ data->WriteBit(guidBytes2[7]);
+ data->WriteBit(unkGuid3[4]);
+
+ data->WriteBit(guidBytes2[2]);
+ data->WriteBit(guidBytes2[5]);
+ data->WriteBit(unkGuid3[7]);
+ data->WriteBit(guidBytes2[4]);
+ data->WriteBit(guidBytes2[0]);
+ data->WriteBit(guidBytes1[0]);
+ data->WriteBit(unkGuid3[2]);
+ data->WriteBit(guidBytes1[7]);
+
+ data->WriteByteSeq(guidBytes2[1]);
+
+ *data << uint32(1); // Unk, always 1
+ *data << uint32(QueueSlot); // Queue slot
+
+ data->WriteByteSeq(guidBytes1[6]);
+ data->WriteByteSeq(guidBytes1[3]);
+ data->WriteByteSeq(guidBytes1[7]);
+ data->WriteByteSeq(guidBytes1[4]);
+ data->WriteByteSeq(guidBytes2[0]);
+ data->WriteByteSeq(guidBytes1[5]);
+ data->WriteByteSeq(guidBytes2[7]);
+ data->WriteByteSeq(guidBytes2[6]);
+ data->WriteByteSeq(guidBytes2[2]);
+ data->WriteByteSeq(unkGuid3[6]);
+ data->WriteByteSeq(unkGuid3[3]);
+ data->WriteByteSeq(guidBytes1[1]);
+ data->WriteByteSeq(guidBytes2[3]);
+ data->WriteByteSeq(unkGuid3[0]);
+ data->WriteByteSeq(unkGuid3[1]);
+ data->WriteByteSeq(unkGuid3[4]);
+ data->WriteByteSeq(guidBytes1[0]);
+ data->WriteByteSeq(guidBytes2[5]);
+ data->WriteByteSeq(unkGuid3[7]);
+ data->WriteByteSeq(guidBytes2[4]);
+ data->WriteByteSeq(guidBytes1[2]);
+
+ *data << uint32(result); // Result
+
+ data->WriteByteSeq(unkGuid3[2]);
+
+ *data << uint32(player->GetBattlegroundQueueJoinTime(bg->GetTypeID())); // Join Time
+
+ data->WriteByteSeq(unkGuid3[5]);
}
void BattlegroundMgr::BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value)
@@ -235,18 +437,57 @@ void BattlegroundMgr::BuildPlaySoundPacket(WorldPacket* data, uint32 soundid)
{
data->Initialize(SMSG_PLAY_SOUND, 4);
*data << uint32(soundid);
+ *data << uint64(0);
}
void BattlegroundMgr::BuildPlayerLeftBattlegroundPacket(WorldPacket* data, uint64 guid)
{
+ ObjectGuid guidBytes = guid;
+
data->Initialize(SMSG_BATTLEGROUND_PLAYER_LEFT, 8);
- *data << uint64(guid);
+
+ data->WriteBit(guidBytes[7]);
+ data->WriteBit(guidBytes[6]);
+ data->WriteBit(guidBytes[2]);
+ data->WriteBit(guidBytes[4]);
+ data->WriteBit(guidBytes[5]);
+ data->WriteBit(guidBytes[1]);
+ data->WriteBit(guidBytes[3]);
+ data->WriteBit(guidBytes[0]);
+
+ data->WriteByteSeq(guidBytes[4]);
+ data->WriteByteSeq(guidBytes[2]);
+ data->WriteByteSeq(guidBytes[5]);
+ data->WriteByteSeq(guidBytes[7]);
+ data->WriteByteSeq(guidBytes[0]);
+ data->WriteByteSeq(guidBytes[6]);
+ data->WriteByteSeq(guidBytes[1]);
+ data->WriteByteSeq(guidBytes[3]);
}
-void BattlegroundMgr::BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, Player* player)
+void BattlegroundMgr::BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, uint64 guid)
{
+ ObjectGuid guidBytes = guid;
+
data->Initialize(SMSG_BATTLEGROUND_PLAYER_JOINED, 8);
- *data << uint64(player->GetGUID());
+
+ data->WriteBit(guidBytes[0]);
+ data->WriteBit(guidBytes[4]);
+ data->WriteBit(guidBytes[3]);
+ data->WriteBit(guidBytes[5]);
+ data->WriteBit(guidBytes[7]);
+ data->WriteBit(guidBytes[6]);
+ data->WriteBit(guidBytes[2]);
+ data->WriteBit(guidBytes[1]);
+
+ data->WriteByteSeq(guidBytes[1]);
+ data->WriteByteSeq(guidBytes[5]);
+ data->WriteByteSeq(guidBytes[3]);
+ data->WriteByteSeq(guidBytes[2]);
+ data->WriteByteSeq(guidBytes[0]);
+ data->WriteByteSeq(guidBytes[7]);
+ data->WriteByteSeq(guidBytes[4]);
+ data->WriteByteSeq(guidBytes[6]);
}
Battleground* BattlegroundMgr::GetBattlegroundThroughClientInstance(uint32 instanceId, BattlegroundTypeId bgTypeId)
@@ -311,7 +552,7 @@ Battleground* BattlegroundMgr::GetBattlegroundTemplate(BattlegroundTypeId bgType
return NULL;
BattlegroundContainer const& bgs = itr->second.m_Battlegrounds;
- //map is sorted and we can be sure that lowest instance id has only BG template
+ // map is sorted and we can be sure that lowest instance id has only BG template
return bgs.empty() ? NULL : bgs.begin()->second;
}
@@ -391,6 +632,12 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original
case BATTLEGROUND_IC:
bg = new BattlegroundIC(*(BattlegroundIC*)bg_template);
break;
+ case BATTLEGROUND_TP:
+ bg = new BattlegroundTP(*(BattlegroundTP*)bg_template);
+ break;
+ case BATTLEGROUND_BFG:
+ bg = new BattlegroundBFG(*(BattlegroundBFG*)bg_template);
+ break;
case BATTLEGROUND_RB:
case BATTLEGROUND_AA:
default:
@@ -409,6 +656,7 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original
bg->SetRandomTypeID(bgTypeId);
bg->SetRated(isRated);
bg->SetRandom(isRandom);
+ bg->SetGuid(MAKE_NEW_GUID(bgTypeId, 0, HIGHGUID_BATTLEGROUND));
// Set up correct min/max player counts for scoreboards
if (bg->isArena())
@@ -444,45 +692,51 @@ bool BattlegroundMgr::CreateBattleground(BattlegroundTemplate const* bgTemplate)
switch (bgTemplate->Id)
{
case BATTLEGROUND_AV:
- bg = new BattlegroundAV();
+ bg = new BattlegroundAV;
break;
case BATTLEGROUND_WS:
- bg = new BattlegroundWS();
+ bg = new BattlegroundWS;
break;
case BATTLEGROUND_AB:
- bg = new BattlegroundAB();
+ bg = new BattlegroundAB;
break;
case BATTLEGROUND_NA:
- bg = new BattlegroundNA();
+ bg = new BattlegroundNA;
break;
case BATTLEGROUND_BE:
- bg = new BattlegroundBE();
+ bg = new BattlegroundBE;
break;
case BATTLEGROUND_EY:
- bg = new BattlegroundEY();
+ bg = new BattlegroundEY;
break;
case BATTLEGROUND_RL:
- bg = new BattlegroundRL();
+ bg = new BattlegroundRL;
break;
case BATTLEGROUND_SA:
- bg = new BattlegroundSA();
+ bg = new BattlegroundSA;
break;
case BATTLEGROUND_DS:
- bg = new BattlegroundDS();
+ bg = new BattlegroundDS;
break;
case BATTLEGROUND_RV:
- bg = new BattlegroundRV();
+ bg = new BattlegroundRV;
break;
case BATTLEGROUND_IC:
- bg = new BattlegroundIC();
+ bg = new BattlegroundIC;
break;
case BATTLEGROUND_AA:
- bg = new Battleground();
+ bg = new Battleground;
break;
case BATTLEGROUND_RB:
- bg = new Battleground();
+ bg = new Battleground;
bg->SetRandom(true);
break;
+ case BATTLEGROUND_TP:
+ bg = new BattlegroundTP;
+ break;
+ case BATTLEGROUND_BFG:
+ bg = new BattlegroundBFG;
+ break;
default:
return false;
}
@@ -493,17 +747,21 @@ bool BattlegroundMgr::CreateBattleground(BattlegroundTemplate const* bgTemplate)
}
bg->SetMapId(bgTemplate->BattlemasterEntry->mapid[0]);
- bg->SetName(bgTemplate->BattlemasterEntry->name[sWorld->GetDefaultDbcLocale()]);
+ bg->SetName(bgTemplate->BattlemasterEntry->name);
+ bg->SetInstanceID(0);
bg->SetArenaorBGType(bgTemplate->IsArena());
bg->SetMinPlayersPerTeam(bgTemplate->MinPlayersPerTeam);
bg->SetMaxPlayersPerTeam(bgTemplate->MaxPlayersPerTeam);
bg->SetMinPlayers(bgTemplate->MinPlayersPerTeam * 2);
bg->SetMaxPlayers(bgTemplate->MaxPlayersPerTeam * 2);
bg->SetTeamStartPosition(TEAM_ALLIANCE, bgTemplate->StartLocation[TEAM_ALLIANCE]);
- bg->SetTeamStartPosition(TEAM_HORDE, bgTemplate->StartLocation[TEAM_HORDE]);
+ bg->SetTeamStartPosition(TEAM_HORDE, bgTemplate->StartLocation[TEAM_HORDE]);
bg->SetStartMaxDist(bgTemplate->MaxStartDistSq);
bg->SetLevelRange(bgTemplate->MinLevel, bgTemplate->MaxLevel);
bg->SetScriptId(bgTemplate->ScriptId);
+ bg->SetGuid(MAKE_NEW_GUID(bgTemplate->Id, 0, HIGHGUID_BATTLEGROUND));
+
+ AddBattleground(bg);
return true;
}
@@ -608,86 +866,75 @@ void BattlegroundMgr::LoadBattlegroundTemplates()
TC_LOG_INFO("server.loading", ">> Loaded %u battlegrounds in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-void BattlegroundMgr::InitAutomaticArenaPointDistribution()
+void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId)
{
- if (!sWorld->getBoolConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
+ if (!player)
return;
- time_t wstime = time_t(sWorld->getWorldState(WS_ARENA_DISTRIBUTION_TIME));
- time_t curtime = time(NULL);
- TC_LOG_DEBUG("bg.battleground", "Initializing Automatic Arena Point Distribution");
- if (wstime < curtime)
- {
- m_NextAutoDistributionTime = curtime; // reset will be called in the next update
- TC_LOG_DEBUG("bg.battleground", "Battleground: Next arena point distribution time in the past, reseting it now.");
- }
- else
- m_NextAutoDistributionTime = wstime;
- TC_LOG_DEBUG("bg.battleground", "Automatic Arena Point Distribution initialized.");
-}
+ BattlegroundDataContainer::iterator it = bgDataStore.find(bgTypeId);
+ if (it == bgDataStore.end())
+ return;
-void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere)
-{
- if (!player)
+ PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(it->second.m_Battlegrounds.begin()->second->GetMapId(), player->getLevel());
+ if (!bracketEntry)
return;
- uint32 winner_kills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_FIRST);
- uint32 winner_arena = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_ARENA_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_ARENA_FIRST);
- uint32 loser_kills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST);
+ uint32 winnerConquest = (player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_CONQUEST_LAST)) / CURRENCY_PRECISION;
+ uint32 winnerHonor = (player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_FIRST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_LAST)) / CURRENCY_PRECISION;
+ uint32 loserHonor = (!player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST)) / CURRENCY_PRECISION;
- winner_kills = Trinity::Honor::hk_honor_at_level(player->getLevel(), float(winner_kills));
- loser_kills = Trinity::Honor::hk_honor_at_level(player->getLevel(), float(loser_kills));
+ ObjectGuid guidBytes = guid;
data->Initialize(SMSG_BATTLEFIELD_LIST);
- *data << uint64(guid); // battlemaster guid
- *data << uint8(fromWhere); // from where you joined
- *data << uint32(bgTypeId); // battleground id
- *data << uint8(0); // unk
- *data << uint8(0); // unk
-
- // Rewards
- *data << uint8(player->GetRandomWinner()); // 3.3.3 hasWin
- *data << uint32(winner_kills); // 3.3.3 winHonor
- *data << uint32(winner_arena); // 3.3.3 winArena
- *data << uint32(loser_kills); // 3.3.3 lossHonor
-
- uint8 isRandom = bgTypeId == BATTLEGROUND_RB;
-
- *data << uint8(isRandom); // 3.3.3 isRandom
- if (isRandom)
- {
- // Rewards (random)
- *data << uint8(player->GetRandomWinner()); // 3.3.3 hasWin_Random
- *data << uint32(winner_kills); // 3.3.3 winHonor_Random
- *data << uint32(winner_arena); // 3.3.3 winArena_Random
- *data << uint32(loser_kills); // 3.3.3 lossHonor_Random
- }
+ *data << uint32(winnerConquest) // Winner Conquest Reward or Random Winner Conquest Reward
+ << uint32(winnerConquest) // Winner Conquest Reward or Random Winner Conquest Reward
+ << uint32(loserHonor) // Loser Honor Reward or Random Loser Honor Reward
+ << uint32(bgTypeId) // battleground id
+ << uint32(loserHonor) // Loser Honor Reward or Random Loser Honor Reward
+ << uint32(winnerHonor) // Winner Honor Reward or Random Winner Honor Reward
+ << uint32(winnerHonor) // Winner Honor Reward or Random Winner Honor Reward
+ << uint8(bracketEntry->maxLevel) // max level
+ << uint8(bracketEntry->minLevel); // min level
+
+ data->WriteBit(guidBytes[0]);
+ data->WriteBit(guidBytes[1]);
+ data->WriteBit(guidBytes[7]);
+ data->WriteBit(0); // unk
+ data->WriteBit(0); // unk
+
+ data->FlushBits();
+ size_t count_pos = data->bitwpos();
+ data->WriteBits(0, 24); // placeholder
+
+ data->WriteBit(guidBytes[6]);
+ data->WriteBit(guidBytes[4]);
+ data->WriteBit(guidBytes[2]);
+ data->WriteBit(guidBytes[3]);
+ data->WriteBit(0); // unk
+ data->WriteBit(guidBytes[5]);
+ data->WriteBit(0); // unk
+
+ data->FlushBits();
+
+ data->WriteByteSeq(guidBytes[6]);
+ data->WriteByteSeq(guidBytes[1]);
+ data->WriteByteSeq(guidBytes[7]);
+ data->WriteByteSeq(guidBytes[5]);
- if (bgTypeId == BATTLEGROUND_AA) // arena
- *data << uint32(0); // unk (count?)
- else // battleground
+ uint32 count = 0;
+ BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
+ BattlegroundClientIdsContainer& clientIds = it->second.m_ClientBattlegroundIds[bracketId];
+ for (BattlegroundClientIdsContainer::const_iterator itr = clientIds.begin(); itr != clientIds.end(); ++itr)
{
- size_t count_pos = data->wpos();
- *data << uint32(0); // number of bg instances
-
- BattlegroundDataContainer::iterator it = bgDataStore.find(bgTypeId);
- if (it != bgDataStore.end())
- {
- // expected bracket entry
- if (PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(it->second.m_Battlegrounds.begin()->second->GetMapId(), player->getLevel()))
- {
- uint32 count = 0;
- BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
- BattlegroundClientIdsContainer& clientIds = it->second.m_ClientBattlegroundIds[bracketId];
- for (BattlegroundClientIdsContainer::const_iterator itr = clientIds.begin(); itr != clientIds.end(); ++itr)
- {
- *data << uint32(*itr);
- ++count;
- }
- data->put<uint32>(count_pos, count);
- }
- }
+ *data << uint32(*itr);
+ ++count;
}
+ data->PutBits(count_pos, count, 24); // bg instance count
+
+ data->WriteByteSeq(guidBytes[0]);
+ data->WriteByteSeq(guidBytes[2]);
+ data->WriteByteSeq(guidBytes[4]);
+ data->WriteByteSeq(guidBytes[3]);
}
void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, BattlegroundTypeId bgTypeId)
@@ -696,8 +943,6 @@ void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, Batt
{
uint32 mapid = bg->GetMapId();
uint32 team = player->GetBGTeam();
- if (team == 0)
- team = player->GetTeam();
Position const* pos = bg->GetTeamStartPosition(Battleground::GetTeamIndexByTeamId(team));
TC_LOG_DEBUG("bg.battleground", "BattlegroundMgr::SendToBattleground: Sending %s to map %u, %s (bgType %u)", player->GetName().c_str(), mapid, pos->ToString().c_str(), bgTypeId);
@@ -739,6 +984,10 @@ BattlegroundQueueTypeId BattlegroundMgr::BGQueueTypeId(BattlegroundTypeId bgType
return BATTLEGROUND_QUEUE_EY;
case BATTLEGROUND_IC:
return BATTLEGROUND_QUEUE_IC;
+ case BATTLEGROUND_TP:
+ return BATTLEGROUND_QUEUE_TP;
+ case BATTLEGROUND_BFG:
+ return BATTLEGROUND_QUEUE_BFG;
case BATTLEGROUND_RB:
return BATTLEGROUND_QUEUE_RB;
case BATTLEGROUND_SA:
@@ -783,6 +1032,10 @@ BattlegroundTypeId BattlegroundMgr::BGTemplateId(BattlegroundQueueTypeId bgQueue
return BATTLEGROUND_SA;
case BATTLEGROUND_QUEUE_IC:
return BATTLEGROUND_IC;
+ case BATTLEGROUND_QUEUE_TP:
+ return BATTLEGROUND_TP;
+ case BATTLEGROUND_QUEUE_BFG:
+ return BATTLEGROUND_BFG;
case BATTLEGROUND_QUEUE_RB:
return BATTLEGROUND_RB;
case BATTLEGROUND_QUEUE_2v2:
@@ -929,6 +1182,8 @@ HolidayIds BattlegroundMgr::BGTypeToWeekendHolidayId(BattlegroundTypeId bgTypeId
case BATTLEGROUND_SA: return HOLIDAY_CALL_TO_ARMS_SA;
case BATTLEGROUND_AB: return HOLIDAY_CALL_TO_ARMS_AB;
case BATTLEGROUND_IC: return HOLIDAY_CALL_TO_ARMS_IC;
+ case BATTLEGROUND_TP: return HOLIDAY_CALL_TO_ARMS_TP;
+ case BATTLEGROUND_BFG: return HOLIDAY_CALL_TO_ARMS_BFG;
default: return HOLIDAY_NONE;
}
}
@@ -943,6 +1198,8 @@ BattlegroundTypeId BattlegroundMgr::WeekendHolidayIdToBGType(HolidayIds holiday)
case HOLIDAY_CALL_TO_ARMS_SA: return BATTLEGROUND_SA;
case HOLIDAY_CALL_TO_ARMS_AB: return BATTLEGROUND_AB;
case HOLIDAY_CALL_TO_ARMS_IC: return BATTLEGROUND_IC;
+ case HOLIDAY_CALL_TO_ARMS_TP: return BATTLEGROUND_TP;
+ case HOLIDAY_CALL_TO_ARMS_BFG: return BATTLEGROUND_BFG;
default: return BATTLEGROUND_TYPE_NONE;
}
}
@@ -1024,4 +1281,3 @@ void BattlegroundMgr::RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 ins
{
bgDataStore[bgTypeId].m_Battlegrounds.erase(instanceId);
}
-
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index c21c34d1a10..e6f8eee354e 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -29,8 +29,7 @@ typedef std::set<uint32> BattlegroundClientIdsContainer;
typedef std::unordered_map<uint32, BattlegroundTypeId> BattleMastersMap;
-#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
-#define WS_ARENA_DISTRIBUTION_TIME 20001 // Custom worldstate
+#define WS_CURRENCY_RESET_TIME 20001 // Custom worldstate
struct BattlegroundData
{
@@ -71,12 +70,12 @@ class BattlegroundMgr
void Update(uint32 diff);
/* Packet Building */
- void BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, Player* player);
+ void BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, uint64 guid);
void BuildPlayerLeftBattlegroundPacket(WorldPacket* data, uint64 guid);
- void BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere);
- void BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result);
+ void BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId);
+ void BuildStatusFailedPacket(WorldPacket* data, Battleground* bg, Player* pPlayer, uint8 QueueSlot, GroupJoinBattlegroundResult result);
void BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value);
- void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType, uint32 arenaFaction);
+ void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, Player* player, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType);
void BuildPlaySoundPacket(WorldPacket* data, uint32 soundId);
void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, uint64 guid);
@@ -120,7 +119,6 @@ class BattlegroundMgr
uint32 GetMaxRatingDifference() const;
uint32 GetRatingDiscardTimer() const;
- void InitAutomaticArenaPointDistribution();
void LoadBattleMastersEntry();
void CheckBattleMasters();
BattlegroundTypeId GetBattleMasterBG(uint32 entry) const
@@ -144,8 +142,6 @@ class BattlegroundMgr
std::vector<uint64> m_QueueUpdateScheduler;
uint32 m_NextRatedArenaUpdate;
- time_t m_NextAutoDistributionTime;
- uint32 m_AutoDistributionTimeChecker;
bool m_ArenaTesting;
bool m_Testing;
BattleMastersMap mBattleMastersMap;
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
index e52f75a1c41..2b9713157c9 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
@@ -390,10 +390,11 @@ void BattlegroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount)
Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(group->BgTypeId);
BattlegroundQueueTypeId 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;
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, plr2, queueSlot, STATUS_NONE, plr2->GetBattlegroundQueueJoinTime(group->BgTypeId), 0, 0);
plr2->GetSession()->SendPacket(&data);
}
// then actually delete, this may delete the group as well!
@@ -478,7 +479,7 @@ bool BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg,
player->GetName().c_str(), player->GetGUIDLow(), bg->GetInstanceID(), queueSlot, bg->GetTypeID());
// send status packet
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0, ginfo->ArenaType, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, player->GetBattlegroundQueueJoinTime(bgTypeId), ginfo->ArenaType);
player->GetSession()->SendPacket(&data);
}
return true;
@@ -628,7 +629,7 @@ bool BattlegroundQueue::CheckPremadeMatch(BattlegroundBracketId bracket_id, uint
}
// this method tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam
-bool BattlegroundQueue::CheckNormalMatch(Battleground* bg_template, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers)
+bool BattlegroundQueue::CheckNormalMatch(Battleground* /*bg_template*/, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers)
{
GroupsQueueType::const_iterator itr_team[BG_TEAMS_COUNT];
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
@@ -664,7 +665,7 @@ bool BattlegroundQueue::CheckNormalMatch(Battleground* bg_template, Battleground
return false;
}
//allow 1v0 if debug bg
- if (sBattlegroundMgr->isTesting() && bg_template->isBattleground() && (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[TEAM_HORDE].GetPlayerCount()))
+ if (sBattlegroundMgr->isTesting() && (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[TEAM_HORDE].GetPlayerCount()))
return true;
//return true if there are enough players in selection pools - enable to work .debug bg command correctly
return m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[TEAM_HORDE].GetPlayerCount() >= minPlayers;
@@ -1000,7 +1001,7 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
WorldPacket data;
//we must send remaining time in queue
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, 0, m_ArenaType, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, player->GetBattlegroundQueueJoinTime(m_BgTypeId), m_ArenaType);
player->GetSession()->SendPacket(&data);
}
}
@@ -1048,7 +1049,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
sBattlegroundMgr->ScheduleQueueUpdate(0, 0, m_BgQueueTypeId, m_BgTypeId, bg->GetBracketId());
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_NONE, player->GetBattlegroundQueueJoinTime(m_BgTypeId), 0, 0);
player->GetSession()->SendPacket(&data);
}
}
diff --git a/src/server/game/Battlegrounds/BattlegroundScore.h b/src/server/game/Battlegrounds/BattlegroundScore.h
index 81aca355be8..23e06693e56 100644
--- a/src/server/game/Battlegrounds/BattlegroundScore.h
+++ b/src/server/game/Battlegrounds/BattlegroundScore.h
@@ -19,6 +19,8 @@
#define TRINITY_BATTLEGROUND_SCORE_H
#include "WorldPacket.h"
+#include "Player.h"
+#include "ObjectAccessor.h"
enum ScoreType
{
@@ -29,7 +31,7 @@ enum ScoreType
SCORE_DAMAGE_DONE = 5,
SCORE_HEALING_DONE = 6,
- // WS and EY
+ // WS, EY and TP
SCORE_FLAG_CAPTURES = 7,
SCORE_FLAG_RETURNS = 8,
@@ -55,8 +57,8 @@ struct BattlegroundScore
friend class Battleground;
protected:
- BattlegroundScore(uint64 playerGuid) : PlayerGuid(playerGuid), KillingBlows(0), Deaths(0),
- HonorableKills(0), BonusHonor(0), DamageDone(0), HealingDone(0) { }
+ BattlegroundScore(uint64 playerGuid, uint32 team) : PlayerGuid(playerGuid), TeamId(team == ALLIANCE ? 1 : 0),
+ KillingBlows(0), Deaths(0), HonorableKills(0), BonusHonor(0), DamageDone(0), HealingDone(0) { }
virtual ~BattlegroundScore() { }
@@ -88,26 +90,77 @@ struct BattlegroundScore
}
}
- virtual void AppendToPacket(WorldPacket& data)
+ virtual void AppendToPacket(WorldPacket& data, ByteBuffer& content)
{
- data << uint64(PlayerGuid);
+ uint32 primaryTree = 0;
+ if (Player* player = ObjectAccessor::FindPlayer(PlayerGuid))
+ primaryTree = player->GetPrimaryTalentTree(player->GetActiveSpec());
- data << uint32(KillingBlows);
- data << uint32(HonorableKills);
- data << uint32(Deaths);
- data << uint32(BonusHonor);
- data << uint32(DamageDone);
- data << uint32(HealingDone);
+ data.WriteBit(0); // Unk 1
+ data.WriteBit(0); // Unk 2
+ data.WriteBit(PlayerGuid[2]);
+ data.WriteBit(/*!IsArena*/ 1); // IsArena
+ data.WriteBit(0); // Unk 4
+ data.WriteBit(0); // Unk 5
+ data.WriteBit(0); // Unk 6
+ data.WriteBit(PlayerGuid[3]);
+ data.WriteBit(PlayerGuid[0]);
+ data.WriteBit(PlayerGuid[5]);
+ data.WriteBit(PlayerGuid[1]);
+ data.WriteBit(PlayerGuid[6]);
+ data.WriteBit(TeamId);
+ data.WriteBit(PlayerGuid[7]);
- BuildObjectivesBlock(data);
+ content << uint32(HealingDone); // healing done
+ content << uint32(DamageDone); // damage done
+
+ //if (!IsArena)
+ //{
+ content << uint32(BonusHonor / 100);
+ content << uint32(Deaths);
+ content << uint32(HonorableKills);
+ //}
+
+ content.WriteByteSeq(PlayerGuid[4]);
+ content << uint32(KillingBlows);
+
+ //if (unk 5)
+ // data << uint32() unk
+
+ content.WriteByteSeq(PlayerGuid[5]);
+
+ //if (unk 6)
+ // data << uint32() unk
+
+ //if (unk 2)
+ // data << uint32() unk
+
+ content.WriteByteSeq(PlayerGuid[1]);
+ content.WriteByteSeq(PlayerGuid[6]);
+
+ content << int32(primaryTree);
+
+ BuildObjectivesBlock(data, content);
+
+ data.WriteBit(PlayerGuid[4]);
+
+ content.WriteByteSeq(PlayerGuid[0]);
+ content.WriteByteSeq(PlayerGuid[3]);
+
+ //if (unk 4)
+ // data << uint32() unk
+
+ content.WriteByteSeq(PlayerGuid[7]);
+ content.WriteByteSeq(PlayerGuid[2]);
}
- virtual void BuildObjectivesBlock(WorldPacket& /*data*/) = 0;
+ virtual void BuildObjectivesBlock(WorldPacket& /*data*/, ByteBuffer& /*content*/) = 0;
// For Logging purpose
virtual std::string ToString() const { return ""; }
- uint64 PlayerGuid;
+ ObjectGuid PlayerGuid;
+ uint8 TeamId;
// Default score, present in every type
uint32 KillingBlows;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
index 2622ab9501f..91174682218 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
@@ -224,7 +224,7 @@ void BattlegroundAB::StartingEventOpenDoors()
void BattlegroundAB::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundABScore(player->GetGUID());
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundABScore(player->GetGUID(), player->GetBGTeam());
}
void BattlegroundAB::RemovePlayer(Player* /*player*/, uint64 /*guid*/, uint32 /*team*/)
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
index a6b4be10fdf..74efe421d35 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
@@ -242,7 +242,7 @@ struct BattlegroundABScore final : public BattlegroundScore
friend class BattlegroundAB;
protected:
- BattlegroundABScore(uint64 playerGuid) : BattlegroundScore(playerGuid), BasesAssaulted(0), BasesDefended(0) { }
+ BattlegroundABScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid, team), BasesAssaulted(0), BasesDefended(0) { }
void UpdateScore(uint32 type, uint32 value) override
{
@@ -260,11 +260,11 @@ struct BattlegroundABScore final : public BattlegroundScore
}
}
- void BuildObjectivesBlock(WorldPacket& data) final
+ void BuildObjectivesBlock(WorldPacket& data, ByteBuffer& content) final
{
- data << uint32(2);
- data << uint32(BasesAssaulted);
- data << uint32(BasesDefended);
+ data.WriteBits(2, 24); // Objectives Count
+ content << uint32(BasesAssaulted);
+ content << uint32(BasesDefended);
}
uint32 BasesAssaulted;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index eafb02f031d..9d55e44d491 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -438,7 +438,7 @@ void BattlegroundAV::StartingEventOpenDoors()
void BattlegroundAV::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundAVScore(player->GetGUID());
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundAVScore(player->GetGUID(), player->GetBGTeam());
}
void BattlegroundAV::EndBattleground(uint32 winner)
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
index feb3c016e55..5255caeda18 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
@@ -1531,7 +1531,7 @@ struct BattlegroundAVScore final : public BattlegroundScore
friend class BattlegroundAV;
protected:
- BattlegroundAVScore(uint64 playerGuid) : BattlegroundScore(playerGuid), GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), MinesCaptured(0) { }
+ BattlegroundAVScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid, team), GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), MinesCaptured(0) { }
void UpdateScore(uint32 type, uint32 value) override
{
@@ -1558,14 +1558,14 @@ struct BattlegroundAVScore final : public BattlegroundScore
}
}
- void BuildObjectivesBlock(WorldPacket& data) final
+ void BuildObjectivesBlock(WorldPacket& data, ByteBuffer& content) final
{
- data << uint32(5); // Objectives Count
- data << uint32(GraveyardsAssaulted);
- data << uint32(GraveyardsDefended);
- data << uint32(TowersAssaulted);
- data << uint32(TowersDefended);
- data << uint32(MinesCaptured);
+ data.WriteBits(5, 24); // Objectives Count
+ content << uint32(GraveyardsAssaulted);
+ content << uint32(GraveyardsDefended);
+ content << uint32(TowersAssaulted);
+ content << uint32(TowersDefended);
+ content << uint32(MinesCaptured);
}
uint32 GraveyardsAssaulted;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp
new file mode 100644
index 00000000000..b7e97b406e3
--- /dev/null
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Battleground.h"
+#include "BattlegroundBFG.h"
+#include "Creature.h"
+#include "GameObject.h"
+#include "Language.h"
+#include "Object.h"
+#include "ObjectMgr.h"
+#include "BattlegroundMgr.h"
+#include "Player.h"
+#include "World.h"
+#include "WorldPacket.h"
+
+BattlegroundBFG::BattlegroundBFG()
+{
+}
+
+BattlegroundBFG::~BattlegroundBFG()
+{
+}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h
new file mode 100644
index 00000000000..1f539a414b2
--- /dev/null
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BATTLEGROUNDBFG_H
+#define __BATTLEGROUNDBFG_H
+
+#include "Battleground.h"
+#include "BattlegroundScore.h"
+
+class BattlegroundBFGScore final : public BattlegroundScore
+{
+ protected:
+ BattlegroundBFGScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid, team), BasesAssaulted(0), BasesDefended(0) { }
+
+ void UpdateScore(uint32 type, uint32 value) override
+ {
+ switch (type)
+ {
+ case SCORE_BASES_ASSAULTED:
+ BasesAssaulted += value;
+ break;
+ case SCORE_BASES_DEFENDED:
+ BasesDefended += value;
+ break;
+ default:
+ BattlegroundScore::UpdateScore(type, value);
+ break;
+ }
+ }
+
+ void BuildObjectivesBlock(WorldPacket& data, ByteBuffer& content) final
+ {
+ data.WriteBits(2, 24); // Objectives Count
+ content << uint32(BasesAssaulted);
+ content << uint32(BasesDefended);
+ }
+
+ uint32 BasesAssaulted;
+ uint32 BasesDefended;
+};
+
+class BattlegroundBFG : public Battleground
+{
+ public:
+ BattlegroundBFG();
+ ~BattlegroundBFG();
+};
+
+#endif
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
index ca96140f5da..c25c915dd7a 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
@@ -363,7 +363,7 @@ void BattlegroundEY::UpdatePointsIcons(uint32 Team, uint32 Point)
void BattlegroundEY::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundEYScore(player->GetGUID());
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundEYScore(player->GetGUID(), player->GetBGTeam());
m_PlayersNearPoint[EY_POINTS_MAX].push_back(player->GetGUID());
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h
index 056deb3498b..9ea6d30fe51 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h
@@ -328,7 +328,7 @@ struct BattlegroundEYScore final : public BattlegroundScore
friend class BattlegroundEY;
protected:
- BattlegroundEYScore(uint64 playerGuid) : BattlegroundScore(playerGuid), FlagCaptures(0) { }
+ BattlegroundEYScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid, team), FlagCaptures(0) { }
void UpdateScore(uint32 type, uint32 value) override
{
@@ -343,10 +343,10 @@ struct BattlegroundEYScore final : public BattlegroundScore
}
}
- void BuildObjectivesBlock(WorldPacket& data) final
+ void BuildObjectivesBlock(WorldPacket& data, ByteBuffer& content) final
{
- data << uint32(1); // Objectives Count
- data << uint32(FlagCaptures);
+ data.WriteBits(1, 24); // Objectives Count
+ content << uint32(FlagCaptures);
}
uint32 FlagCaptures;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
index 41a37a8962f..e5de2e86a2e 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
@@ -273,7 +273,7 @@ void BattlegroundIC::StartingEventOpenDoors()
void BattlegroundIC::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundICScore(player->GetGUID());
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundICScore(player->GetGUID(), player->GetBGTeam());
if (nodePoint[NODE_TYPE_QUARRY].nodeState == (player->GetTeamId() == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H))
player->CastSpell(player, SPELL_QUARRY, true);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
index 0b317cabef3..5153a6fb9cf 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
@@ -853,7 +853,7 @@ struct BattlegroundICScore final : public BattlegroundScore
friend class BattlegroundIC;
protected:
- BattlegroundICScore(uint64 playerGuid) : BattlegroundScore(playerGuid), BasesAssaulted(0), BasesDefended(0) { }
+ BattlegroundICScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid, team), BasesAssaulted(0), BasesDefended(0) { }
void UpdateScore(uint32 type, uint32 value) override
{
@@ -871,11 +871,11 @@ struct BattlegroundICScore final : public BattlegroundScore
}
}
- void BuildObjectivesBlock(WorldPacket& data) final
+ void BuildObjectivesBlock(WorldPacket& data, ByteBuffer& content) final
{
- data << uint32(2); // Objectives Count
- data << uint32(BasesAssaulted);
- data << uint32(BasesDefended);
+ data.WriteBits(2, 24); // Objectives Count
+ content << uint32(BasesAssaulted);
+ content << uint32(BasesDefended);
}
uint32 BasesAssaulted;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
index 15c72b6ac00..10ede74685c 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
@@ -301,7 +301,7 @@ void BattlegroundSA::StartShips()
{
if (Player* p = ObjectAccessor::FindPlayer(itr->first))
{
- UpdateData data;
+ UpdateData data(p->GetMapId());
WorldPacket pkt;
GetBGObject(i)->BuildValuesUpdateBlockForPlayer(&data, p);
data.BuildPacket(&pkt);
@@ -478,7 +478,7 @@ void BattlegroundSA::FillInitialWorldStates(WorldPacket& data)
void BattlegroundSA::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundSAScore(player->GetGUID());
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundSAScore(player->GetGUID(), player->GetBGTeam());
SendTransportInit(player);
@@ -486,7 +486,7 @@ void BattlegroundSA::AddPlayer(Player* player)
{
if (player->GetTeamId() == Attackers)
{
- player->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
+ //player->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
if (urand(0, 1))
player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
@@ -540,7 +540,7 @@ void BattlegroundSA::TeleportPlayers()
if (player->GetTeamId() == Attackers)
{
- player->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
+ //player->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
if (urand(0, 1))
player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
@@ -977,8 +977,9 @@ void BattlegroundSA::SendTransportInit(Player* player)
{
if (BgObjects[BG_SA_BOAT_ONE] || BgObjects[BG_SA_BOAT_TWO])
{
- UpdateData transData;
+ UpdateData transData(player->GetMapId());
if (BgObjects[BG_SA_BOAT_ONE])
+
GetBGObject(BG_SA_BOAT_ONE)->BuildCreateUpdateBlockForPlayer(&transData, player);
if (BgObjects[BG_SA_BOAT_TWO])
GetBGObject(BG_SA_BOAT_TWO)->BuildCreateUpdateBlockForPlayer(&transData, player);
@@ -992,7 +993,7 @@ void BattlegroundSA::SendTransportsRemove(Player* player)
{
if (BgObjects[BG_SA_BOAT_ONE] || BgObjects[BG_SA_BOAT_TWO])
{
- UpdateData transData;
+ UpdateData transData(player->GetMapId());
if (BgObjects[BG_SA_BOAT_ONE])
GetBGObject(BG_SA_BOAT_ONE)->BuildOutOfRangeUpdateBlock(&transData);
if (BgObjects[BG_SA_BOAT_TWO])
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
index a3947334417..474a2ff8dc3 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
@@ -513,7 +513,7 @@ struct BattlegroundSAScore final : public BattlegroundScore
friend class BattlegroundSA;
protected:
- BattlegroundSAScore(uint64 playerGuid) : BattlegroundScore(playerGuid), DemolishersDestroyed(0), GatesDestroyed(0) { }
+ BattlegroundSAScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid, team), DemolishersDestroyed(0), GatesDestroyed(0) { }
void UpdateScore(uint32 type, uint32 value) override
{
@@ -531,11 +531,11 @@ struct BattlegroundSAScore final : public BattlegroundScore
}
}
- void BuildObjectivesBlock(WorldPacket& data) final
+ void BuildObjectivesBlock(WorldPacket& data, ByteBuffer& content) final
{
- data << uint32(2); // Objectives Count
- data << uint32(DemolishersDestroyed);
- data << uint32(GatesDestroyed);
+ data.WriteBits(2, 24); // Objectives Count
+ content << uint32(DemolishersDestroyed);
+ content << uint32(GatesDestroyed);
}
uint32 DemolishersDestroyed;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp
new file mode 100644
index 00000000000..6d4c6ce0bac
--- /dev/null
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Battleground.h"
+#include "BattlegroundTP.h"
+#include "Creature.h"
+#include "GameObject.h"
+#include "Language.h"
+#include "Object.h"
+#include "ObjectMgr.h"
+#include "BattlegroundMgr.h"
+#include "Player.h"
+#include "World.h"
+#include "WorldPacket.h"
+
+BattlegroundTP::BattlegroundTP()
+{
+}
+
+BattlegroundTP::~BattlegroundTP()
+{
+}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundTP.h b/src/server/game/Battlegrounds/Zones/BattlegroundTP.h
new file mode 100644
index 00000000000..3d34974d845
--- /dev/null
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundTP.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BATTLEGROUNDTP_H
+#define __BATTLEGROUNDTP_H
+
+#include "Battleground.h"
+#include "BattlegroundScore.h"
+
+class BattlegroundTPScore final : public BattlegroundScore
+{
+ protected:
+ BattlegroundTPScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid, team), FlagCaptures(0), FlagReturns(0) { }
+
+ void UpdateScore(uint32 type, uint32 value) override
+ {
+ switch (type)
+ {
+ case SCORE_FLAG_CAPTURES:
+ FlagCaptures += value;
+ break;
+ case SCORE_FLAG_RETURNS:
+ FlagReturns += value;
+ break;
+ default:
+ BattlegroundScore::UpdateScore(type, value);
+ break;
+ }
+ }
+
+ void BuildObjectivesBlock(WorldPacket& data, ByteBuffer& content) final
+ {
+ data.WriteBits(2, 24); // Objectives Count
+ content << uint32(FlagCaptures);
+ content << uint32(FlagReturns);
+ }
+
+ uint32 FlagCaptures;
+ uint32 FlagReturns;
+};
+
+class BattlegroundTP : public Battleground
+{
+ public:
+ BattlegroundTP();
+ ~BattlegroundTP();
+};
+
+#endif
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
index c50669b137e..bcf7093a640 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
@@ -77,7 +77,7 @@ void BattlegroundWS::PostUpdateImpl(uint32 diff)
{
if (GetStatus() == STATUS_IN_PROGRESS)
{
- if (GetStartTime() >= 27*MINUTE*IN_MILLISECONDS)
+ if (GetElapsedTime() >= 27*MINUTE*IN_MILLISECONDS)
{
if (GetTeamScore(TEAM_ALLIANCE) == 0)
{
@@ -96,7 +96,7 @@ void BattlegroundWS::PostUpdateImpl(uint32 diff)
EndBattleground(ALLIANCE);
}
// first update needed after 1 minute of game already in progress
- else if (GetStartTime() > uint32(_minutesElapsed * MINUTE * IN_MILLISECONDS) + 3 * MINUTE * IN_MILLISECONDS)
+ else if (GetElapsedTime() > uint32(_minutesElapsed * MINUTE * IN_MILLISECONDS) + 3 * MINUTE * IN_MILLISECONDS)
{
++_minutesElapsed;
UpdateWorldState(BG_WS_STATE_TIMER, 25 - _minutesElapsed);
@@ -229,7 +229,7 @@ void BattlegroundWS::StartingEventOpenDoors()
void BattlegroundWS::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUIDLow()] = new BattlegroundWGScore(player->GetGUID());
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundWGScore(player->GetGUID(), player->GetBGTeam());
}
void BattlegroundWS::RespawnFlag(uint32 Team, bool captured)
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
index 3d449580fb9..1c3ee932b76 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
@@ -152,7 +152,7 @@ struct BattlegroundWGScore final : public BattlegroundScore
friend class BattlegroundWS;
protected:
- BattlegroundWGScore(uint64 playerGuid) : BattlegroundScore(playerGuid), FlagCaptures(0), FlagReturns(0) { }
+ BattlegroundWGScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid, team), FlagCaptures(0), FlagReturns(0) { }
void UpdateScore(uint32 type, uint32 value) override
{
@@ -170,11 +170,11 @@ struct BattlegroundWGScore final : public BattlegroundScore
}
}
- void BuildObjectivesBlock(WorldPacket& data) final
+ void BuildObjectivesBlock(WorldPacket& data, ByteBuffer& content) final
{
- data << uint32(2); // Objectives Count
- data << uint32(FlagCaptures);
- data << uint32(FlagReturns);
+ data.WriteBits(2, 24); // Objectives Count
+ content << uint32(FlagCaptures);
+ content << uint32(FlagReturns);
}
uint32 FlagCaptures;
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index 532900c0438..abb415e0f64 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -148,6 +148,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/DataStores
${CMAKE_CURRENT_SOURCE_DIR}/DungeonFinding
${CMAKE_CURRENT_SOURCE_DIR}/Entities
+ ${CMAKE_CURRENT_SOURCE_DIR}/Entities/AreaTrigger
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Creature
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Corpse
${CMAKE_CURRENT_SOURCE_DIR}/Entities/DynamicObject
diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp
index 92f19c0adeb..64116b8f8c1 100644
--- a/src/server/game/Calendar/CalendarMgr.cpp
+++ b/src/server/game/Calendar/CalendarMgr.cpp
@@ -527,6 +527,10 @@ void CalendarMgr::SendCalendarEventInviteAlert(CalendarEvent const& calendarEven
data << uint32(calendarEvent.GetType());
data << int32(calendarEvent.GetDungeonId());
data << uint64(invite.GetInviteId());
+
+ Guild* guild = sGuildMgr->GetGuildById(calendarEvent.GetGuildId());
+ data << uint64(guild ? guild->GetGUID() : 0);
+
data << uint8(invite.GetStatus());
data << uint8(invite.GetRank());
data.appendPackGUID(calendarEvent.GetCreatorGUID());
@@ -563,7 +567,9 @@ void CalendarMgr::SendCalendarEvent(uint64 guid, CalendarEvent const& calendarEv
data << uint32(calendarEvent.GetFlags());
data.AppendPackedTime(calendarEvent.GetEventTime());
data.AppendPackedTime(calendarEvent.GetTimeZoneTime());
- data << uint32(calendarEvent.GetGuildId());
+
+ Guild* guild = sGuildMgr->GetGuildById(calendarEvent.GetGuildId());
+ data << uint64(guild ? guild->GetGUID() : 0);
data << uint32(eventInviteeList.size());
for (CalendarInviteStore::const_iterator itr = eventInviteeList.begin(); itr != eventInviteeList.end(); ++itr)
diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h
index 9bdb7c0a187..cd527a7373e 100644
--- a/src/server/game/Calendar/CalendarMgr.h
+++ b/src/server/game/Calendar/CalendarMgr.h
@@ -58,7 +58,8 @@ enum CalendarEventType
CALENDAR_TYPE_DUNGEON = 1,
CALENDAR_TYPE_PVP = 2,
CALENDAR_TYPE_MEETING = 3,
- CALENDAR_TYPE_OTHER = 4
+ CALENDAR_TYPE_OTHER = 4,
+ CALENDAR_TYPE_HEROIC = 5
};
enum CalendarRepeatType
diff --git a/src/server/game/Chat/Channels/ChannelMgr.cpp b/src/server/game/Chat/Channels/ChannelMgr.cpp
index 00824ae2056..366b0eee59f 100644
--- a/src/server/game/Chat/Channels/ChannelMgr.cpp
+++ b/src/server/game/Chat/Channels/ChannelMgr.cpp
@@ -19,6 +19,7 @@
#include "ChannelMgr.h"
#include "Player.h"
#include "World.h"
+#include "WorldSession.h"
ChannelMgr::~ChannelMgr()
{
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index d77ee5b7f61..0686272f191 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -351,10 +351,9 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
std::string zoneName = "Unknown";
if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId))
{
- int locale = GetSessionDbcLocale();
- areaName = area->area_name[locale];
+ areaName = area->area_name;
if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone))
- zoneName = zone->area_name[locale];
+ zoneName = zone->area_name;
}
sLog->outCommand(m_session->GetAccountId(), "Command: %s [Player: %s (Guid: %u) (Account: %u) X: %f Y: %f Z: %f Map: %u (%s) Area: %u (%s) Zone: %s Selected %s: %s (GUID: %u)]",
@@ -631,7 +630,8 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd)
size_t ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg chatType, Language language, uint64 senderGUID, uint64 receiverGUID, std::string const& message, uint8 chatTag,
std::string const& senderName /*= ""*/, std::string const& receiverName /*= ""*/,
- uint32 achievementId /*= 0*/, bool gmMessage /*= false*/, std::string const& channelName /*= ""*/)
+ uint32 achievementId /*= 0*/, bool gmMessage /*= false*/, std::string const& channelName /*= ""*/,
+ std::string const& addonPrefix /*= ""*/)
{
size_t receiverGUIDPos = 0;
data.Initialize(!gmMessage ? SMSG_MESSAGECHAT : SMSG_GM_MESSAGECHAT);
@@ -658,12 +658,17 @@ size_t ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg chatType, Languag
data << uint32(receiverName.length() + 1);
data << receiverName;
}
+
+ if (language == LANG_ADDON)
+ data << addonPrefix;
break;
case CHAT_MSG_WHISPER_FOREIGN:
data << uint32(senderName.length() + 1);
data << senderName;
receiverGUIDPos = data.wpos();
data << uint64(receiverGUID);
+ if (language == LANG_ADDON)
+ data << addonPrefix;
break;
case CHAT_MSG_BG_SYSTEM_NEUTRAL:
case CHAT_MSG_BG_SYSTEM_ALLIANCE:
@@ -675,11 +680,16 @@ size_t ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg chatType, Languag
data << uint32(receiverName.length() + 1);
data << receiverName;
}
+
+ if (language == LANG_ADDON)
+ data << addonPrefix;
break;
case CHAT_MSG_ACHIEVEMENT:
case CHAT_MSG_GUILD_ACHIEVEMENT:
receiverGUIDPos = data.wpos();
data << uint64(receiverGUID);
+ if (language == LANG_ADDON)
+ data << addonPrefix;
break;
default:
if (gmMessage)
@@ -696,6 +706,9 @@ size_t ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg chatType, Languag
receiverGUIDPos = data.wpos();
data << uint64(receiverGUID);
+
+ if (language == LANG_ADDON)
+ data << addonPrefix;
break;
}
@@ -705,12 +718,17 @@ size_t ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg chatType, Languag
if (chatType == CHAT_MSG_ACHIEVEMENT || chatType == CHAT_MSG_GUILD_ACHIEVEMENT)
data << uint32(achievementId);
+ else if (chatType == CHAT_MSG_RAID_BOSS_WHISPER || chatType == CHAT_MSG_RAID_BOSS_EMOTE)
+ {
+ data << float(0.0f); // Display time in middle of the screen (in seconds), defaults to 10 if not set (cannot be below 1)
+ data << uint8(0); // Hide in chat frame (only shows in middle of the screen)
+ }
return receiverGUIDPos;
}
size_t ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string const& message,
- uint32 achievementId /*= 0*/, std::string const& channelName /*= ""*/, LocaleConstant locale /*= DEFAULT_LOCALE*/)
+ uint32 achievementId /*= 0*/, std::string const& channelName /*= ""*/, LocaleConstant locale /*= DEFAULT_LOCALE*/, std::string const& addonPrefix /*= ""*/)
{
uint64 senderGUID = 0;
std::string senderName = "";
@@ -735,7 +753,7 @@ size_t ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg chatType, Languag
receiverName = receiver->GetNameForLocaleIdx(locale);
}
- return BuildChatPacket(data, chatType, language, senderGUID, receiverGUID, message, chatTag, senderName, receiverName, achievementId, gmMessage, channelName);
+ return BuildChatPacket(data, chatType, language, senderGUID, receiverGUID, message, chatTag, senderName, receiverName, achievementId, gmMessage, channelName, addonPrefix);
}
Player* ChatHandler::getSelectedPlayer()
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index a56b79077d7..5c541d07b5a 100644
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -56,10 +56,11 @@ class ChatHandler
// Builds chat packet and returns receiver guid position in the packet to substitute in whisper builders
static size_t BuildChatPacket(WorldPacket& data, ChatMsg chatType, Language language, uint64 senderGUID, uint64 receiverGUID, std::string const& message, uint8 chatTag,
std::string const& senderName = "", std::string const& receiverName = "",
- uint32 achievementId = 0, bool gmMessage = false, std::string const& channelName = "");
+ uint32 achievementId = 0, bool gmMessage = false, std::string const& channelName = "",
+ std::string const& addonPrefix = "");
// Builds chat packet and returns receiver guid position in the packet to substitute in whisper builders
- static size_t BuildChatPacket(WorldPacket& data, ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string const& message, uint32 achievementId = 0, std::string const& channelName = "", LocaleConstant locale = DEFAULT_LOCALE);
+ static size_t BuildChatPacket(WorldPacket& data, ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string const& message, uint32 achievementId = 0, std::string const& channelName = "", LocaleConstant locale = DEFAULT_LOCALE, std::string const& addonPrefix = "");
static char* LineFromMessage(char*& pos) { char* start = strtok(pos, "\n"); pos = NULL; return start; }
diff --git a/src/server/game/Chat/ChatLink.cpp b/src/server/game/Chat/ChatLink.cpp
index 12f4b082a9c..3f32447a31f 100644
--- a/src/server/game/Chat/ChatLink.cpp
+++ b/src/server/game/Chat/ChatLink.cpp
@@ -167,7 +167,7 @@ bool ItemChatLink::Initialize(std::istringstream& iss)
return true;
}
-inline std::string ItemChatLink::FormatName(uint8 index, ItemLocale const* locale, char* const* suffixStrings) const
+inline std::string ItemChatLink::FormatName(uint8 index, ItemLocale const* locale, char* suffixStrings) const
{
std::stringstream ss;
if (locale == NULL || index >= locale->Name.size())
@@ -183,7 +183,7 @@ bool ItemChatLink::ValidateName(char* buffer, const char* context)
{
ChatLink::ValidateName(buffer, context);
- char* const* suffixStrings = _suffix ? _suffix->nameSuffix : (_property ? _property->nameSuffix : NULL);
+ char* suffixStrings = _suffix ? _suffix->nameSuffix : (_property ? _property->nameSuffix : NULL);
bool res = (FormatName(LOCALE_enUS, NULL, suffixStrings) == buffer);
if (!res)
@@ -306,23 +306,18 @@ bool SpellChatLink::ValidateName(char* buffer, const char* context)
return false;
}
- for (uint8 i = 0; i < TOTAL_LOCALES; ++i)
+ uint32 skillLineNameLength = strlen(skillLine->name);
+ if (skillLineNameLength > 0 && strncmp(skillLine->name, buffer, skillLineNameLength) == 0)
{
- uint32 skillLineNameLength = strlen(skillLine->name[i]);
- if (skillLineNameLength > 0 && strncmp(skillLine->name[i], buffer, skillLineNameLength) == 0)
- {
- // found the prefix, remove it to perform spellname validation below
- // -2 = strlen(": ")
- uint32 spellNameLength = strlen(buffer) - skillLineNameLength - 2;
- memmove(buffer, buffer + skillLineNameLength + 2, spellNameLength + 1);
- break;
- }
+ // found the prefix, remove it to perform spellname validation below
+ // -2 = strlen(": ")
+ uint32 spellNameLength = strlen(buffer) - skillLineNameLength - 2;
+ memmove(buffer, buffer + skillLineNameLength + 2, spellNameLength + 1);
}
}
- for (uint8 i = 0; i < TOTAL_LOCALES; ++i)
- if (*_spell->SpellName[i] && strcmp(_spell->SpellName[i], buffer) == 0)
- return true;
+ if (*_spell->SpellName && strcmp(_spell->SpellName, buffer) == 0)
+ return true;
TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): linked spell (id: %u) name wasn't found in any localization", context, _spell->Id);
return false;
@@ -377,9 +372,8 @@ bool AchievementChatLink::ValidateName(char* buffer, const char* context)
{
ChatLink::ValidateName(buffer, context);
- for (uint8 i = 0; i < TOTAL_LOCALES; ++i)
- if (*_achievement->name[i] && strcmp(_achievement->name[i], buffer) == 0)
- return true;
+ if (*_achievement->name && strcmp(_achievement->name, buffer) == 0)
+ return true;
TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): linked achievement (id: %u) name wasn't found in any localization", context, _achievement->ID);
return false;
diff --git a/src/server/game/Chat/ChatLink.h b/src/server/game/Chat/ChatLink.h
index 4cfa9c34bf7..ebe2583dc1c 100644
--- a/src/server/game/Chat/ChatLink.h
+++ b/src/server/game/Chat/ChatLink.h
@@ -65,7 +65,7 @@ public:
virtual bool ValidateName(char* buffer, const char* context);
protected:
- std::string FormatName(uint8 index, ItemLocale const* locale, char* const* suffixStrings) const;
+ std::string FormatName(uint8 index, ItemLocale const* locale, char* suffixStrings) const;
ItemTemplate const* _item;
int32 _data[8];
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index 339ec579b1a..edf15aaf1ff 100644
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -75,7 +75,7 @@ bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellIn
return false;
// not in same map or phase
- if (!hatedUnit->IsInMap(hatingUnit) || !hatedUnit->InSamePhase(hatingUnit))
+ if (!hatedUnit->IsInMap(hatingUnit) || !hatedUnit->IsInPhase(hatingUnit))
return false;
// spell not causing threat
@@ -182,7 +182,7 @@ void HostileReference::updateOnlineStatus()
&& (getTarget()->GetTypeId() != TYPEID_PLAYER || !getTarget()->ToPlayer()->IsGameMaster())
&& !getTarget()->HasUnitState(UNIT_STATE_IN_FLIGHT)
&& getTarget()->IsInMap(GetSourceUnit())
- && getTarget()->InSamePhase(GetSourceUnit())
+ && getTarget()->IsInPhase(GetSourceUnit())
)
{
Creature* creature = GetSourceUnit()->ToCreature();
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index c77b34a39a3..04ceaefb0d5 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -30,7 +30,7 @@
#include "Spell.h"
// Checks if object meets the condition
-// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI)
+// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: SmartAI)
bool Condition::Meets(ConditionSourceInfo& sourceInfo)
{
ASSERT(ConditionTarget < MAX_CONDITION_TARGETS);
@@ -295,9 +295,9 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
condMeets = ConditionValue2 == sWorld->getWorldState(ConditionValue1);
break;
}
- case CONDITION_PHASEMASK:
+ case CONDITION_PHASEID:
{
- condMeets = (object->GetPhaseMask() & ConditionValue1) != 0;
+ condMeets = object->IsInPhase(ConditionValue1);
break;
}
case CONDITION_TITLE:
@@ -434,6 +434,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
case TYPEID_CORPSE:
mask |= GRID_MAP_TYPE_MASK_CORPSE;
break;
+ case TYPEID_AREATRIGGER:
+ mask |= GRID_MAP_TYPE_MASK_AREATRIGGER;
+ break;
default:
break;
}
@@ -447,6 +450,8 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
mask |= GRID_MAP_TYPE_MASK_GAMEOBJECT;
if (ConditionValue1 & TYPEMASK_CORPSE)
mask |= GRID_MAP_TYPE_MASK_CORPSE;
+ if (ConditionValue1 & TYPEMASK_AREATRIGGER)
+ mask |= GRID_MAP_TYPE_MASK_AREATRIGGER;
break;
case CONDITION_RELATION_TO:
mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
@@ -469,7 +474,7 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
case CONDITION_WORLD_STATE:
mask |= GRID_MAP_TYPE_MASK_ALL;
break;
- case CONDITION_PHASEMASK:
+ case CONDITION_PHASEID:
mask |= GRID_MAP_TYPE_MASK_ALL;
break;
case CONDITION_TITLE:
@@ -658,6 +663,7 @@ bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const
sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET ||
sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT ||
sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT ||
+ sourceType == CONDITION_SOURCE_TYPE_PHASE_DEFINITION ||
sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR);
}
@@ -733,6 +739,22 @@ ConditionList ConditionMgr::GetConditionsForSmartEvent(int32 entryOrGuid, uint32
return cond;
}
+ConditionList const* ConditionMgr::GetConditionsForPhaseDefinition(uint32 zone, uint32 entry)
+{
+ PhaseDefinitionConditionContainer::const_iterator itr = PhaseDefinitionsConditionStore.find(zone);
+ if (itr != PhaseDefinitionsConditionStore.end())
+ {
+ ConditionTypeContainer::const_iterator i = itr->second.find(entry);
+ if (i != itr->second.end())
+ {
+ TC_LOG_DEBUG("condition", "GetConditionsForPhaseDefinition: found conditions for zone %u entry %u", zone, entry);
+ return &i->second;
+ }
+ }
+
+ return NULL;
+}
+
ConditionList ConditionMgr::GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId)
{
ConditionList cond;
@@ -972,6 +994,13 @@ void ConditionMgr::LoadConditions(bool isReload)
++count;
continue;
}
+ case CONDITION_SOURCE_TYPE_PHASE_DEFINITION:
+ {
+ PhaseDefinitionsConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
+ valid = true;
+ ++count;
+ continue;
+ }
case CONDITION_SOURCE_TYPE_NPC_VENDOR:
{
NpcVendorConditionContainerStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
@@ -1482,6 +1511,13 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
return false;
}
break;
+ case CONDITION_SOURCE_TYPE_PHASE_DEFINITION:
+ /*if (!PhaseMgr::IsConditionTypeSupported(cond->ConditionType))
+ {
+ TC_LOG_ERROR("sql.sql", "Condition source type `CONDITION_SOURCE_TYPE_PHASE_DEFINITION` does not support condition type %u, ignoring.", cond->ConditionType);
+ return false;
+ }*/
+ break;
case CONDITION_SOURCE_TYPE_NPC_VENDOR:
{
if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
@@ -1497,11 +1533,6 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
}
break;
}
- case CONDITION_SOURCE_TYPE_PHASE_DEFINITION:
- {
- TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_PHASE_DEFINITION:: is only for 4.3.4 branch, skipped");
- return false;
- }
case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
case CONDITION_SOURCE_TYPE_SMART_EVENT:
@@ -1964,12 +1995,17 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
TC_LOG_ERROR("sql.sql", "World state condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_PHASEMASK:
+ case CONDITION_PHASEID:
{
+ if (!sPhaseStore.LookupEntry(cond->ConditionValue1))
+ {
+ TC_LOG_ERROR("sql.sql", "Phase condition has nonexistent phaseid in value1 (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
if (cond->ConditionValue2)
- TC_LOG_ERROR("sql.sql", "Phasemask condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ TC_LOG_ERROR("sql.sql", "Phase condition has useless data in value2 (%u)!", cond->ConditionValue2);
if (cond->ConditionValue3)
- TC_LOG_ERROR("sql.sql", "Phasemask condition has useless data in value3 (%u)!", cond->ConditionValue3);
+ TC_LOG_ERROR("sql.sql", "Phase condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_TITLE:
@@ -2078,6 +2114,19 @@ void ConditionMgr::Clean()
SpellClickEventConditionStore.clear();
+ for (PhaseDefinitionConditionContainer::iterator itr = PhaseDefinitionsConditionStore.begin(); itr != PhaseDefinitionsConditionStore.end(); ++itr)
+ {
+ for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ {
+ for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
+ delete *i;
+ it->second.clear();
+ }
+ itr->second.clear();
+ }
+
+ PhaseDefinitionsConditionStore.clear();
+
for (NpcVendorConditionContainer::iterator itr = NpcVendorConditionContainerStore.begin(); itr != NpcVendorConditionContainerStore.end(); ++itr)
{
for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index d5428ed2d14..9a48985b90d 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -58,7 +58,7 @@ enum ConditionTypes
CONDITION_AREAID = 23, // area_id 0 0 true if in area_id
CONDITION_CREATURE_TYPE = 24, // cinfo.type 0 0 true if creature_template.type = value1
CONDITION_SPELL = 25, // spell_id 0 0 true if player has learned spell
- CONDITION_PHASEMASK = 26, // phasemask 0 0 true if object is in phasemask
+ CONDITION_PHASEID = 26, // phaseid 0 0 true if object is in phaseid
CONDITION_LEVEL = 27, // level ComparisonType 0 true if unit's level is equal to param1 (param2 can modify the statement)
CONDITION_QUEST_COMPLETE = 28, // quest_id 0 0 true if player has quest_id with all objectives complete, but not yet rewarded
CONDITION_NEAR_CREATURE = 29, // creature entry distance 0 true if there is a creature of entry in range
@@ -217,6 +217,7 @@ typedef std::map<ConditionSourceType, ConditionTypeContainer> ConditionContainer
typedef std::map<uint32, ConditionTypeContainer> CreatureSpellConditionContainer;
typedef std::map<uint32, ConditionTypeContainer> NpcVendorConditionContainer;
typedef std::map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionTypeContainer> SmartEventConditionContainer;
+typedef std::map<int32 /*zoneId*/, ConditionTypeContainer> PhaseDefinitionConditionContainer;
typedef std::map<uint32, ConditionList> ConditionReferenceContainer;//only used for references
@@ -248,6 +249,7 @@ class ConditionMgr
ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId);
ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType);
ConditionList GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId);
+ ConditionList const* GetConditionsForPhaseDefinition(uint32 zone, uint32 entry);
ConditionList GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId);
private:
@@ -267,6 +269,7 @@ class ConditionMgr
CreatureSpellConditionContainer SpellClickEventConditionStore;
NpcVendorConditionContainer NpcVendorConditionContainerStore;
SmartEventConditionContainer SmartEventConditionStore;
+ PhaseDefinitionConditionContainer PhaseDefinitionsConditionStore;
};
#define sConditionMgr ConditionMgr::instance()
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
new file mode 100644
index 00000000000..f1436dd90e3
--- /dev/null
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "DB2Stores.h"
+#include "DB2fmt.h"
+#include "DB2Utility.h"
+#include "Common.h"
+#include "Log.h"
+#include "World.h"
+
+DB2Storage<ItemEntry> sItemStore(Itemfmt, &DB2Utilities::HasItemEntry, &DB2Utilities::WriteItemDbReply);
+DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore(ItemCurrencyCostfmt);
+DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
+DB2Storage<ItemSparseEntry> sItemSparseStore(ItemSparsefmt, &DB2Utilities::HasItemSparseEntry, &DB2Utilities::WriteItemSparseDbReply);
+DB2Storage<KeyChainEntry> sKeyChainStore(KeyChainfmt);
+
+typedef std::list<std::string> DB2StoreProblemList;
+
+typedef std::map<uint32 /*hash*/, DB2StorageBase*> DB2StorageMap;
+DB2StorageMap DB2Stores;
+
+uint32 DB2FilesCount = 0;
+
+static bool LoadDB2_assert_print(uint32 fsize, uint32 rsize, std::string const& filename)
+{
+ TC_LOG_ERROR("misc", "Size of '%s' setted by format string (%u) not equal size of C++ structure (%u).", filename.c_str(), fsize, rsize);
+
+ // ASSERT must fail after function call
+ return false;
+}
+
+template<class T>
+inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, DB2Storage<T>& storage, std::string const& db2_path, std::string const& filename)
+{
+ // compatibility format and C++ structure sizes
+ ASSERT(DB2FileLoader::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDB2_assert_print(DB2FileLoader::GetFormatRecordSize(storage.GetFormat()), sizeof(T), filename));
+
+ ++DB2FilesCount;
+
+ std::string db2_filename = db2_path + filename;
+ if (storage.Load(db2_filename.c_str(), uint32(sWorld->GetDefaultDbcLocale())))
+ {
+ for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
+ {
+ if (!(availableDb2Locales & (1 << i)))
+ continue;
+
+ if (uint32(sWorld->GetDefaultDbcLocale()) == i)
+ continue;
+
+ std::string localizedName(db2_path);
+ localizedName.append(localeNames[i]);
+ localizedName.push_back('/');
+ localizedName.append(filename);
+
+ if (!storage.LoadStringsFrom(localizedName.c_str(), i))
+ availableDb2Locales &= ~(1<<i); // mark as not available for speedup next checks
+ }
+ }
+ else
+ {
+ // sort problematic db2 to (1) non compatible and (2) nonexistent
+ if (FILE* f = fopen(db2_filename.c_str(), "rb"))
+ {
+ std::ostringstream stream;
+ stream << db2_filename << " exists, and has " << storage.GetFieldCount() << " field(s) (expected " << strlen(storage.GetFormat()) << "). Extracted file might be from wrong client version.";
+ std::string buf = stream.str();
+ errlist.push_back(buf);
+ fclose(f);
+ }
+ else
+ errlist.push_back(db2_filename);
+ }
+
+ DB2Stores[storage.GetHash()] = &storage;
+}
+
+void LoadDB2Stores(std::string const& dataPath)
+{
+ std::string db2Path = dataPath + "dbc/";
+
+ DB2StoreProblemList bad_db2_files;
+ uint32 availableDb2Locales = 0xFF;
+
+ LoadDB2(availableDb2Locales, bad_db2_files, sItemStore, db2Path, "Item.db2");
+ LoadDB2(availableDb2Locales, bad_db2_files, sItemCurrencyCostStore, db2Path, "ItemCurrencyCost.db2");
+ LoadDB2(availableDb2Locales, bad_db2_files, sItemSparseStore, db2Path, "Item-sparse.db2");
+ LoadDB2(availableDb2Locales, bad_db2_files, sItemExtendedCostStore, db2Path, "ItemExtendedCost.db2");
+ LoadDB2(availableDb2Locales, bad_db2_files, sKeyChainStore, db2Path, "KeyChain.db2");
+
+ // error checks
+ if (bad_db2_files.size() >= DB2FilesCount)
+ {
+ TC_LOG_ERROR("misc", "\nIncorrect DataDir value in worldserver.conf or ALL required *.db2 files (%d) not found by path: %sdb2", DB2FilesCount, dataPath.c_str());
+ exit(1);
+ }
+ else if (!bad_db2_files.empty())
+ {
+ std::string str;
+ for (std::list<std::string>::iterator i = bad_db2_files.begin(); i != bad_db2_files.end(); ++i)
+ str += *i + "\n";
+
+ TC_LOG_ERROR("misc", "\nSome required *.db2 files (%u from %d) not found or not compatible:\n%s", (uint32)bad_db2_files.size(), DB2FilesCount, str.c_str());
+ exit(1);
+ }
+
+ // Check loaded DB2 files proper version
+ if (!sItemStore.LookupEntry(83086) || // last item added in 4.3.4 (15595)
+ !sItemExtendedCostStore.LookupEntry(3872) ) // last item extended cost added in 4.3.4 (15595)
+ {
+ TC_LOG_ERROR("misc", "Please extract correct db2 files from client 4.3.4 15595.");
+ exit(1);
+ }
+
+ TC_LOG_INFO("misc", ">> Initialized %d DB2 data stores.", DB2FilesCount);
+}
+
+DB2StorageBase const* GetDB2Storage(uint32 type)
+{
+ DB2StorageMap::const_iterator itr = DB2Stores.find(type);
+ if (itr != DB2Stores.end())
+ return itr->second;
+
+ return NULL;
+}
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
new file mode 100644
index 00000000000..17a92f98cde
--- /dev/null
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_DB2STORES_H
+#define TRINITY_DB2STORES_H
+
+#include "DB2Store.h"
+#include "DB2Structure.h"
+#include <string>
+
+extern DB2Storage<ItemEntry> sItemStore;
+extern DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore;
+extern DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore;
+extern DB2Storage<ItemSparseEntry> sItemSparseStore;
+extern DB2Storage<KeyChainEntry> sKeyChainStore;
+
+void LoadDB2Stores(std::string const& dataPath);
+
+DB2StorageBase const* GetDB2Storage(uint32 type);
+
+#endif
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
new file mode 100644
index 00000000000..0a60d0b860f
--- /dev/null
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_DB2STRUCTURE_H
+#define TRINITY_DB2STRUCTURE_H
+
+#include "Common.h"
+#include "ItemPrototype.h"
+
+// GCC has alternative #pragma pack(N) syntax and old gcc version does not support pack(push, N), also any gcc version does not support it at some platform
+#if defined(__GNUC__)
+#pragma pack(1)
+#else
+#pragma pack(push, 1)
+#endif
+
+// Structures used to access raw DB2 data and required packing to portability
+struct ItemEntry
+{
+ uint32 ID; // 0
+ uint32 Class; // 1
+ uint32 SubClass; // 2
+ int32 SoundOverrideSubclass; // 3
+ int32 Material; // 4
+ uint32 DisplayId; // 5
+ uint32 InventoryType; // 6
+ uint32 Sheath; // 7
+};
+
+struct ItemCurrencyCostEntry
+{
+ //uint32 Id;
+ uint32 ItemId;
+};
+
+struct ItemSparseEntry
+{
+ uint32 ID; // 0
+ uint32 Quality; // 1
+ uint32 Flags; // 2
+ uint32 Flags2; // 3
+ float Unk430_1;
+ float Unk430_2;
+ uint32 BuyCount;
+ uint32 BuyPrice; // 4
+ uint32 SellPrice; // 5
+ uint32 InventoryType; // 6
+ int32 AllowableClass; // 7
+ int32 AllowableRace; // 8
+ uint32 ItemLevel; // 9
+ int32 RequiredLevel; // 10
+ uint32 RequiredSkill; // 11
+ uint32 RequiredSkillRank; // 12
+ uint32 RequiredSpell; // 13
+ uint32 RequiredHonorRank; // 14
+ uint32 RequiredCityRank; // 15
+ uint32 RequiredReputationFaction; // 16
+ uint32 RequiredReputationRank; // 17
+ uint32 MaxCount; // 18
+ uint32 Stackable; // 19
+ uint32 ContainerSlots; // 20
+ int32 ItemStatType[MAX_ITEM_PROTO_STATS]; // 21 - 30
+ uint32 ItemStatValue[MAX_ITEM_PROTO_STATS]; // 31 - 40
+ int32 ItemStatUnk1[MAX_ITEM_PROTO_STATS]; // 41 - 50
+ int32 ItemStatUnk2[MAX_ITEM_PROTO_STATS]; // 51 - 60
+ uint32 ScalingStatDistribution; // 61
+ uint32 DamageType; // 62
+ uint32 Delay; // 63
+ float RangedModRange; // 64
+ int32 SpellId[MAX_ITEM_PROTO_SPELLS]; // 65 - 69
+ int32 SpellTrigger[MAX_ITEM_PROTO_SPELLS]; // 70 - 74
+ int32 SpellCharges[MAX_ITEM_PROTO_SPELLS]; // 75 - 79
+ int32 SpellCooldown[MAX_ITEM_PROTO_SPELLS]; // 80 - 84
+ int32 SpellCategory[MAX_ITEM_PROTO_SPELLS]; // 85 - 89
+ int32 SpellCategoryCooldown[MAX_ITEM_PROTO_SPELLS]; // 90 - 94
+ uint32 Bonding; // 95
+ LocalizedString* Name; // 96
+ LocalizedString* Name2; // 97
+ LocalizedString* Name3; // 98
+ LocalizedString* Name4; // 99
+ LocalizedString* Description; // 100
+ uint32 PageText; // 101
+ uint32 LanguageID; // 102
+ uint32 PageMaterial; // 103
+ uint32 StartQuest; // 104
+ uint32 LockID; // 105
+ int32 Material; // 106
+ uint32 Sheath; // 107
+ uint32 RandomProperty; // 108
+ uint32 RandomSuffix; // 109
+ uint32 ItemSet; // 110
+ uint32 Area; // 112
+ uint32 Map; // 113
+ uint32 BagFamily; // 114
+ uint32 TotemCategory; // 115
+ uint32 Color[MAX_ITEM_PROTO_SOCKETS]; // 116 - 118
+ uint32 Content[MAX_ITEM_PROTO_SOCKETS]; // 119 - 121
+ int32 SocketBonus; // 122
+ uint32 GemProperties; // 123
+ float ArmorDamageModifier; // 124
+ uint32 Duration; // 125
+ uint32 ItemLimitCategory; // 126
+ uint32 HolidayId; // 127
+ float StatScalingFactor; // 128
+ int32 CurrencySubstitutionId; // 129
+ int32 CurrencySubstitutionCount; // 130
+};
+
+#define MAX_ITEM_EXT_COST_ITEMS 5
+#define MAX_ITEM_EXT_COST_CURRENCIES 5
+
+struct ItemExtendedCostEntry
+{
+ uint32 ID; // 0 extended-cost entry id
+ //uint32 reqhonorpoints; // 1 required honor points
+ //uint32 reqarenapoints; // 2 required arena points
+ uint32 RequiredArenaSlot; // 3 arena slot restrictions (min slot value)
+ uint32 RequiredItem[MAX_ITEM_EXT_COST_ITEMS]; // 4-8 required item id
+ uint32 RequiredItemCount[MAX_ITEM_EXT_COST_ITEMS]; // 9-13 required count of 1st item
+ uint32 RequiredPersonalArenaRating; // 14 required personal arena rating
+ //uint32 ItemPurchaseGroup; // 15
+ uint32 RequiredCurrency[MAX_ITEM_EXT_COST_CURRENCIES];// 16-20 required curency id
+ uint32 RequiredCurrencyCount[MAX_ITEM_EXT_COST_CURRENCIES];// 21-25 required curency count
+ uint32 RequiredFactionId;
+ uint32 RequiredFactionStanding;
+ uint32 RequirementFlags;
+ uint32 RequiredGuildLevel;
+ uint32 RequiredAchievement;
+};
+
+#define KEYCHAIN_SIZE 32
+
+struct KeyChainEntry
+{
+ uint32 Id;
+ uint8 Key[KEYCHAIN_SIZE];
+};
+
+// GCC has alternative #pragma pack(N) syntax and old gcc version does not support pack(push, N), also any gcc version does not support it at some platform
+#if defined(__GNUC__)
+#pragma pack()
+#else
+#pragma pack(pop)
+#endif
+
+#endif \ No newline at end of file
diff --git a/src/server/game/DataStores/DB2Utility.cpp b/src/server/game/DataStores/DB2Utility.cpp
new file mode 100644
index 00000000000..5a0174c3a74
--- /dev/null
+++ b/src/server/game/DataStores/DB2Utility.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "DB2Utility.h"
+#include "ObjectMgr.h"
+
+inline bool ItemExists(uint32 id)
+{
+ return sObjectMgr->GetItemTemplate(id) != NULL;
+}
+
+bool DB2Utilities::HasItemEntry(DB2Storage<ItemEntry> const& /*store*/, uint32 id)
+{
+ return ItemExists(id);
+}
+
+bool DB2Utilities::HasItemSparseEntry(DB2Storage<ItemSparseEntry> const& /*store*/, uint32 id)
+{
+ return ItemExists(id);
+}
+
+void DB2Utilities::WriteItemDbReply(DB2Storage<ItemEntry> const& /*store*/, uint32 id, uint32 /*locale*/, ByteBuffer& buffer)
+{
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(id);
+ ASSERT(proto);
+
+ buffer << uint32(proto->ItemId);
+ buffer << uint32(proto->Class);
+ buffer << uint32(proto->SubClass);
+ buffer << int32(proto->SoundOverrideSubclass);
+ buffer << uint32(proto->Material);
+ buffer << uint32(proto->DisplayInfoID);
+ buffer << uint32(proto->InventoryType);
+ buffer << uint32(proto->Sheath);
+}
+
+void DB2Utilities::WriteItemSparseDbReply(DB2Storage<ItemSparseEntry> const& /*store*/, uint32 id, uint32 locale, ByteBuffer& buffer)
+{
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(id);
+ ASSERT(proto);
+
+ ItemLocale const* localeData = locale ? sObjectMgr->GetItemLocale(id) : NULL;
+
+ buffer << uint32(proto->ItemId);
+ buffer << uint32(proto->Quality);
+ buffer << uint32(proto->Flags);
+ buffer << uint32(proto->Flags2);
+ buffer << float(proto->Unk430_1);
+ buffer << float(proto->Unk430_2);
+ buffer << uint32(proto->BuyCount);
+ buffer << int32(proto->BuyPrice);
+ buffer << uint32(proto->SellPrice);
+ buffer << uint32(proto->InventoryType);
+ buffer << int32(proto->AllowableClass);
+ buffer << int32(proto->AllowableRace);
+ buffer << uint32(proto->ItemLevel);
+ buffer << uint32(proto->RequiredLevel);
+ buffer << uint32(proto->RequiredSkill);
+ buffer << uint32(proto->RequiredSkillRank);
+ buffer << uint32(proto->RequiredSpell);
+ buffer << uint32(proto->RequiredHonorRank);
+ buffer << uint32(proto->RequiredCityRank);
+ buffer << uint32(proto->RequiredReputationFaction);
+ buffer << uint32(proto->RequiredReputationRank);
+ buffer << int32(proto->MaxCount);
+ buffer << int32(proto->Stackable);
+ buffer << uint32(proto->ContainerSlots);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ buffer << uint32(proto->ItemStat[x].ItemStatType);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ buffer << int32(proto->ItemStat[x].ItemStatValue);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ buffer << int32(proto->ItemStat[x].ItemStatUnk1);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ buffer << int32(proto->ItemStat[x].ItemStatUnk2);
+
+ buffer << uint32(proto->ScalingStatDistribution);
+ buffer << uint32(proto->DamageType);
+ buffer << uint32(proto->Delay);
+ buffer << float(proto->RangedModRange);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << int32(proto->Spells[x].SpellId);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << uint32(proto->Spells[x].SpellTrigger);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << int32(proto->Spells[x].SpellCharges);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << int32(proto->Spells[x].SpellCooldown);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << uint32(proto->Spells[x].SpellCategory);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ buffer << int32(proto->Spells[x].SpellCategoryCooldown);
+
+ buffer << uint32(proto->Bonding);
+
+ // item name
+ std::string name = proto->Name1;
+ if (localeData)
+ ObjectMgr::GetLocaleString(localeData->Name, locale, name);
+
+ buffer << uint16(name.length());
+ if (name.length())
+ buffer << name;
+
+ for (uint32 i = 0; i < 3; ++i) // other 3 names
+ buffer << uint16(0);
+
+ std::string desc = proto->Description;
+ if (localeData)
+ ObjectMgr::GetLocaleString(localeData->Description, locale, desc);
+
+ buffer << uint16(desc.length());
+ if (desc.length())
+ buffer << desc;
+
+ buffer << uint32(proto->PageText);
+ buffer << uint32(proto->LanguageID);
+ buffer << uint32(proto->PageMaterial);
+ buffer << uint32(proto->StartQuest);
+ buffer << uint32(proto->LockID);
+ buffer << int32(proto->Material);
+ buffer << uint32(proto->Sheath);
+ buffer << int32(proto->RandomProperty);
+ buffer << int32(proto->RandomSuffix);
+ buffer << uint32(proto->ItemSet);
+
+ buffer << uint32(proto->Area);
+ buffer << uint32(proto->Map);
+ buffer << uint32(proto->BagFamily);
+ buffer << uint32(proto->TotemCategory);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x)
+ buffer << uint32(proto->Socket[x].Color);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x)
+ buffer << uint32(proto->Socket[x].Content);
+
+ buffer << uint32(proto->socketBonus);
+ buffer << uint32(proto->GemProperties);
+ buffer << float(proto->ArmorDamageModifier);
+ buffer << int32(proto->Duration);
+ buffer << uint32(proto->ItemLimitCategory);
+ buffer << uint32(proto->HolidayId);
+ buffer << float(proto->StatScalingFactor); // StatScalingFactor
+ buffer << uint32(proto->CurrencySubstitutionId);
+ buffer << uint32(proto->CurrencySubstitutionCount);
+}
diff --git a/src/server/game/DataStores/DB2Utility.h b/src/server/game/DataStores/DB2Utility.h
new file mode 100644
index 00000000000..f2d58de91ca
--- /dev/null
+++ b/src/server/game/DataStores/DB2Utility.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DB2PACKETWRITER_H
+#define DB2PACKETWRITER_H
+
+#include "Define.h"
+
+template<class T>
+class DB2Storage;
+class ByteBuffer;
+struct ItemEntry;
+struct ItemSparseEntry;
+
+namespace DB2Utilities
+{
+ //
+ bool HasItemEntry(DB2Storage<ItemEntry> const& store, uint32 id);
+ bool HasItemSparseEntry(DB2Storage<ItemSparseEntry> const& store, uint32 id);
+
+ //
+ void WriteItemDbReply(DB2Storage<ItemEntry> const& store, uint32 id, uint32 locale, ByteBuffer& buffer);
+ void WriteItemSparseDbReply(DB2Storage<ItemSparseEntry> const& store, uint32 id, uint32 locale, ByteBuffer& buffer);
+}
+
+#endif // DB2PACKETWRITER_H
diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h
new file mode 100644
index 00000000000..e2904aed51e
--- /dev/null
+++ b/src/server/game/DataStores/DB2fmt.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 TrintiyCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_DB2SFRM_H
+#define TRINITY_DB2SFRM_H
+
+char const Itemfmt[]="niiiiiii";
+char const ItemCurrencyCostfmt[]="xn";
+char const ItemSparsefmt[]="niiiffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisssssiiiiiiiiiiiiiiiiiiiiiifiiifii";
+char const ItemExtendedCostEntryfmt[]="nxxiiiiiiiiiiiixiiiiiiiiiiiiiii";
+char const KeyChainfmt[]="nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
+
+#endif
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 03180b35cb5..2ba5a236f95 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -24,7 +24,7 @@ enum LevelLimit
// Client expected level limitation, like as used in DBC item max levels for "until max player level"
// use as default max player level, must be fit max level for used client
// also see MAX_LEVEL and STRONG_MAX_LEVEL define
- DEFAULT_MAX_LEVEL = 80,
+ DEFAULT_MAX_LEVEL = 85,
// client supported max level for player/pets/etc. Avoid overflow or client stability affected.
// also see GT_MAX_LEVEL define
@@ -63,17 +63,28 @@ enum AchievementFlags
{
ACHIEVEMENT_FLAG_COUNTER = 0x00000001, // Just count statistic (never stop and complete)
ACHIEVEMENT_FLAG_HIDDEN = 0x00000002, // Not sent to client - internal use only
- ACHIEVEMENT_FLAG_STORE_MAX_VALUE = 0x00000004, // Store only max value? used only in "Reach level xx"
+ ACHIEVEMENT_FLAG_PLAY_NO_VISUAL = 0x00000004, // Client does not play achievement earned visual
ACHIEVEMENT_FLAG_SUMM = 0x00000008, // Use summ criteria value from all requirements (and calculate max value)
ACHIEVEMENT_FLAG_MAX_USED = 0x00000010, // Show max criteria (and calculate max value ??)
ACHIEVEMENT_FLAG_REQ_COUNT = 0x00000020, // Use not zero req count (and calculate max value)
ACHIEVEMENT_FLAG_AVERAGE = 0x00000040, // Show as average value (value / time_in_days) depend from other flag (by def use last criteria value)
ACHIEVEMENT_FLAG_BAR = 0x00000080, // Show as progress bar (value / max vale) depend from other flag (by def use last criteria value)
ACHIEVEMENT_FLAG_REALM_FIRST_REACH = 0x00000100, //
- ACHIEVEMENT_FLAG_REALM_FIRST_KILL = 0x00000200 //
+ ACHIEVEMENT_FLAG_REALM_FIRST_KILL = 0x00000200, //
+ ACHIEVEMENT_FLAG_UNK3 = 0x00000400, // ACHIEVEMENT_FLAG_HIDE_NAME_IN_TIE
+ ACHIEVEMENT_FLAG_REALM_FIRST_GUILD = 0x00000800, // first guild on realm done something
+ ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS = 0x00001000, // Shows in guild news
+ ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER = 0x00002000, // Shows in guild news header
+ ACHIEVEMENT_FLAG_GUILD = 0x00004000, //
+ ACHIEVEMENT_FLAG_SHOW_GUILD_MEMBERS = 0x00008000, //
+ ACHIEVEMENT_FLAG_SHOW_CRITERIA_MEMBERS = 0x00010000 //
};
-#define MAX_CRITERIA_REQUIREMENTS 2
+enum AchievementCriteriaLimits
+{
+ MAX_CRITERIA_REQUIREMENTS = 2,
+ MAX_ADDITIONAL_CRITERIA_CONDITIONS = 3
+};
enum AchievementCriteriaCondition
{
@@ -82,11 +93,60 @@ enum AchievementCriteriaCondition
ACHIEVEMENT_CRITERIA_CONDITION_UNK2 = 2, // only used in "Complete a daily quest every day for five consecutive days"
ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP = 3, // requires you to be on specific map, reset at change
ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE = 4, // only used in "Win 10 arenas without losing"
+ ACHIEVEMENT_CRITERIA_CONDITION_UNK5 = 5, // Have spell?
+ ACHIEVEMENT_CRITERIA_CONDITION_UNK8 = 8,
ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT = 9, // requires the player not to be hit by specific spell
ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP = 10, // requires the player not to be in group
ACHIEVEMENT_CRITERIA_CONDITION_UNK13 = 13 // unk
};
+enum AchievementCriteriaAdditionalCondition
+{
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_DRUNK_VALUE = 1, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK2 = 2,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_LEVEL = 3, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY = 4,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER = 5,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD = 6,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY = 7,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA = 8,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA = 10,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE = 11,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN = 14,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS = 15,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK16 = 16,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE = 17,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE = 18,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY = 20,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_YIELDS_XP = 21, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ARENA_TYPE = 24, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE = 25,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS = 26,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE = 27,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS = 28,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS = 29,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE = 30,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP = 32,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_CLASS = 33, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_SUBCLASS = 34, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_COMPLETE_QUEST_NOT_IN_GROUP = 35, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MIN_PERSONAL_RATING = 37, // NYI (when implementing don't forget about ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE)
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX = 38,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL = 39,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL = 40,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE = 41,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW = 46,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK55 = 55,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MIN_ACHIEVEMENT_POINTS = 56, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_REQUIRES_LFG_GROUP = 58, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK60 = 60,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_REQUIRES_GUILD_GROUP = 61, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GUILD_REPUTATION = 62, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_RATED_BATTLEGROUND = 63, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RARITY = 65,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RACE = 66,
+};
+
enum AchievementCriteriaFlags
{
ACHIEVEMENT_CRITERIA_FLAG_SHOW_PROGRESS_BAR = 0x00000001, // Show progress as bar
@@ -105,6 +165,7 @@ enum AchievementCriteriaTimedTypes
ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET = 6, // Timer is started by being target of spell with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_CREATURE = 7, // Timer is started by killing creature with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_ITEM = 9, // Timer is started by using item with entry in timerStartEvent
+ ACHIEVEMENT_TIMED_TYPE_UNK = 10, // Unknown
ACHIEVEMENT_TIMED_TYPE_MAX
};
@@ -113,12 +174,14 @@ enum AchievementCriteriaTypes
{
ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0,
ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS = 3, // struct { uint32 itemCount; }
ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5,
ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7,
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8,
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9,
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, // you have to complete a daily quest x times in a row
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11,
+ ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12,
ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13,
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14,
ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15,
@@ -192,12 +255,6 @@ enum AchievementCriteriaTypes
ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91,
ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93,
ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH = 95,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT = 97,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR = 99,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING = 100,
ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101,
ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102,
ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103,
@@ -213,46 +270,56 @@ enum AchievementCriteriaTypes
ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114,
ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS = 115,
ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS = 119,
+ ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS = 124,
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL = 125,
+ ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD = 126,
+ ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL = 127,
+ ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS = 128,
+ ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS = 129,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND = 130,
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING = 132,
+ ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD = 133,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD = 134,
+ ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD = 135,
+ ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD = 136,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE = 138, //struct { Flag flag; uint32 count; } 1: Guild Dungeon, 2:Guild Challenge, 3:Guild battlefield
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE = 139 //struct { uint32 count; } Guild Challenge
};
-#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 120
-
-enum AchievementCategory
-{
- CATEGORY_CHILDRENS_WEEK = 163
-};
+#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 140
enum AreaFlags
{
- AREA_FLAG_UNK0 = 0x00000001, // Unknown
- AREA_FLAG_UNK1 = 0x00000002, // Razorfen Downs, Naxxramas and Acherus: The Ebon Hold (3.3.5a)
- AREA_FLAG_UNK2 = 0x00000004, // Only used for areas on map 571 (development before)
- AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones
- AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning
- AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag?
- AREA_FLAG_ALLOW_DUELS = 0x00000040, // allow to duel here
- AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas
- AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag
- AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?)
- AREA_FLAG_OUTLAND = 0x00000400, // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag)
- AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled)
- AREA_FLAG_NEED_FLY = 0x00001000, // Respawn alive at the graveyard without corpse
- AREA_FLAG_UNUSED1 = 0x00002000, // Unused in 3.3.5a
- AREA_FLAG_OUTLAND2 = 0x00004000, // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag)
- AREA_FLAG_OUTDOOR_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area)
- AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only
- AREA_FLAG_UNUSED2 = 0x00020000, // Unused in 3.3.5a
- AREA_FLAG_CONTESTED_AREA = 0x00040000, // On PvP servers these areas are considered contested, even though the zone it is contained in is a Horde/Alliance territory.
- AREA_FLAG_UNK4 = 0x00080000, // Valgarde and Acherus: The Ebon Hold
- AREA_FLAG_LOWLEVEL = 0x00100000, // used for some starting areas with area_level <= 15
- AREA_FLAG_TOWN = 0x00200000, // small towns with Inn
- AREA_FLAG_REST_ZONE_HORDE = 0x00400000, // Instead of using areatriggers, the zone will act as one for Horde players (Warsong Hold, Acherus: The Ebon Hold, New Agamand Inn, Vengeance Landing Inn, Sunreaver Pavilion, etc)
- AREA_FLAG_REST_ZONE_ALLIANCE = 0x00800000, // Instead of using areatriggers, the zone will act as one for Alliance players (Valgarde, Acherus: The Ebon Hold, Westguard Inn, Silver Covenant Pavilion, etc)
- AREA_FLAG_WINTERGRASP = 0x01000000, // Wintergrasp and it's subzones
- AREA_FLAG_INSIDE = 0x02000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
- AREA_FLAG_OUTSIDE = 0x04000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
- AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Can Hearth And Resurrect From Area
- AREA_FLAG_NO_FLY_ZONE = 0x20000000 // Marks zones where you cannot fly
+ AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring)
+ AREA_FLAG_UNK1 = 0x00000002, // Razorfen Downs, Naxxramas and Acherus: The Ebon Hold (3.3.5a)
+ AREA_FLAG_UNK2 = 0x00000004, // Only used for areas on map 571 (development before)
+ AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones
+ AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning
+ AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag?
+ AREA_FLAG_ALLOW_DUELS = 0x00000040, // allow to duel here
+ AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas
+ AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag
+ AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?)
+ AREA_FLAG_OUTLAND = 0x00000400, // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag)
+ AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled)
+ AREA_FLAG_NEED_FLY = 0x00001000, // Respawn alive at the graveyard without corpse
+ AREA_FLAG_UNUSED1 = 0x00002000, // Unused in 3.3.5a
+ AREA_FLAG_OUTLAND2 = 0x00004000, // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag)
+ AREA_FLAG_OUTDOOR_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area)
+ AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only
+ AREA_FLAG_UNUSED2 = 0x00020000, // Unused in 3.3.5a
+ AREA_FLAG_CONTESTED_AREA = 0x00040000, // On PvP servers these areas are considered contested, even though the zone it is contained in is a Horde/Alliance territory.
+ AREA_FLAG_UNK6 = 0x00080000, // Valgarde and Acherus: The Ebon Hold
+ AREA_FLAG_LOWLEVEL = 0x00100000, // used for some starting areas with area_level <= 15
+ AREA_FLAG_TOWN = 0x00200000, // small towns with Inn
+ AREA_FLAG_REST_ZONE_HORDE = 0x00400000, // Warsong Hold, Acherus: The Ebon Hold, New Agamand Inn, Vengeance Landing Inn, Sunreaver Pavilion (Something to do with team?)
+ AREA_FLAG_REST_ZONE_ALLIANCE = 0x00800000, // Valgarde, Acherus: The Ebon Hold, Westguard Inn, Silver Covenant Pavilion (Something to do with team?)
+ AREA_FLAG_WINTERGRASP = 0x01000000, // Wintergrasp and it's subzones
+ AREA_FLAG_INSIDE = 0x02000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
+ AREA_FLAG_OUTSIDE = 0x04000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
+ AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Can Hearth And Resurrect From Area
+ AREA_FLAG_NO_FLY_ZONE = 0x20000000, // Marks zones where you cannot fly
+ AREA_FLAG_UNK9 = 0x40000000
};
enum Difficulty
@@ -343,12 +410,28 @@ enum ItemEnchantmentType
ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET = 8
};
+enum ItemExtendedCostFlags
+{
+ ITEM_EXT_COST_FLAG_REQUIRE_GUILD = 0x01,
+ ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 = 0x02,
+ ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_2 = 0x04,
+ ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_3 = 0x08,
+ ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_4 = 0x10,
+ ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_5 = 0x20,
+};
+
enum ItemLimitCategoryMode
{
ITEM_LIMIT_CATEGORY_MODE_HAVE = 0, // limit applied to amount items in inventory/bank
ITEM_LIMIT_CATEGORY_MODE_EQUIP = 1 // limit applied to amount equipped items (including used gems)
};
+enum MountFlags
+{
+ MOUNT_FLAG_CAN_PITCH = 0x4, // client checks MOVEMENTFLAG2_FULL_SPEED_PITCHING
+ MOUNT_FLAG_CAN_SWIM = 0x8, // client checks MOVEMENTFLAG_SWIMMING
+};
+
enum SkillRaceClassInfoFlags
{
SKILL_FLAG_NO_SKILLUP_MESSAGE = 0x2,
@@ -362,7 +445,19 @@ enum SkillRaceClassInfoFlags
enum SpellCategoryFlags
{
SPELL_CATEGORY_FLAG_COOLDOWN_SCALES_WITH_WEAPON_SPEED = 0x01, // unused
- SPELL_CATEGORY_FLAG_COOLDOWN_STARTS_ON_EVENT = 0x04
+ SPELL_CATEGORY_FLAG_COOLDOWN_STARTS_ON_EVENT = 0x04,
+ SPELL_CATEGORY_FLAG_COOLDOWN_EXPIRES_AT_MIDNIGHT = 0x08
+};
+
+enum TotemCategoryType
+{
+ TOTEM_CATEGORY_TYPE_KNIFE = 1,
+ TOTEM_CATEGORY_TYPE_TOTEM = 2,
+ TOTEM_CATEGORY_TYPE_ROD = 3,
+ TOTEM_CATEGORY_TYPE_PICK = 21,
+ TOTEM_CATEGORY_TYPE_STONE = 22,
+ TOTEM_CATEGORY_TYPE_HAMMER = 23,
+ TOTEM_CATEGORY_TYPE_SPANNER = 24
};
// SummonProperties.dbc, col 1
@@ -375,6 +470,25 @@ enum SummonPropGroup
SUMMON_PROP_GROUP_UNKNOWN3 = 4 // 86 spells in 3.0.3, taxi/mounts
};
+// SummonProperties.dbc, col 3
+enum SummonPropType
+{
+ SUMMON_PROP_TYPE_UNKNOWN = 0, // different summons, 1330 spells in 3.0.3
+ SUMMON_PROP_TYPE_SUMMON = 1, // generic summons, 49 spells in 3.0.3
+ SUMMON_PROP_TYPE_GUARDIAN = 2, // summon guardian, 393 spells in 3.0.3
+ SUMMON_PROP_TYPE_ARMY = 3, // summon army, 5 spells in 3.0.3
+ SUMMON_PROP_TYPE_TOTEM = 4, // summon totem, 169 spells in 3.0.3
+ SUMMON_PROP_TYPE_CRITTER = 5, // critter/minipet, 195 spells in 3.0.3
+ SUMMON_PROP_TYPE_DK = 6, // summon DRW/Ghoul, 2 spells in 3.0.3
+ SUMMON_PROP_TYPE_BOMB = 7, // summon bot/bomb, 4 spells in 3.0.3
+ SUMMON_PROP_TYPE_PHASING = 8, // something todo with DK prequest line, 2 spells in 3.0.3
+ SUMMON_PROP_TYPE_SIEGE_VEH = 9, // summon different vehicles, 14 spells in 3.0.3
+ SUMMON_PROP_TYPE_DRAKE_VEH = 10, // summon drake (vehicle), 3 spells
+ SUMMON_PROP_TYPE_LIGHTWELL = 11, // summon lightwell, 6 spells in 3.0.3
+ SUMMON_PROP_TYPE_JEEVES = 12, // summon Jeeves, 1 spell in 3.3.5a
+ SUMMON_PROP_TYPE_LASHTAIL = 13 // Lashtail Hatchling, 1 spell in 4.2.2
+};
+
// SummonProperties.dbc, col 5
enum SummonPropFlags
{
@@ -394,18 +508,12 @@ enum SummonPropFlags
SUMMON_PROP_FLAG_UNK13 = 0x00001000, // Lightwell, Jeeves, Gnomish Alarm-o-bot, Build vehicles(wintergrasp)
SUMMON_PROP_FLAG_UNK14 = 0x00002000, // Guides, player follows
SUMMON_PROP_FLAG_UNK15 = 0x00004000, // Force of Nature, Shadowfiend, Feral Spirit, Summon Water Elemental
- SUMMON_PROP_FLAG_UNK16 = 0x00008000 // Light/Dark Bullet, Soul/Fiery Consumption, Twisted Visage, Twilight Whelp. Phase related?
-};
-
-enum TotemCategoryType
-{
- TOTEM_CATEGORY_TYPE_KNIFE = 1,
- TOTEM_CATEGORY_TYPE_TOTEM = 2,
- TOTEM_CATEGORY_TYPE_ROD = 3,
- TOTEM_CATEGORY_TYPE_PICK = 21,
- TOTEM_CATEGORY_TYPE_STONE = 22,
- TOTEM_CATEGORY_TYPE_HAMMER = 23,
- TOTEM_CATEGORY_TYPE_SPANNER = 24
+ SUMMON_PROP_FLAG_UNK16 = 0x00008000, // Light/Dark Bullet, Soul/Fiery Consumption, Twisted Visage, Twilight Whelp. Phase related?
+ SUMMON_PROP_FLAG_UNK17 = 0x00010000,
+ SUMMON_PROP_FLAG_UNK18 = 0x00020000,
+ SUMMON_PROP_FLAG_UNK19 = 0x00040000,
+ SUMMON_PROP_FLAG_UNK20 = 0x00080000,
+ SUMMON_PROP_FLAG_UNK21 = 0x00100000 // Totems
};
enum VehicleSeatFlags
@@ -458,4 +566,15 @@ enum VehicleSeatFlagsB
VEHICLE_SEAT_FLAG_B_VEHICLE_PLAYERFRAME_UI = 0x80000000 // Lua_UnitHasVehiclePlayerFrameUI - actually checked for flagsb &~ 0x80000000
};
+// CurrencyTypes.dbc
+enum CurrencyTypes
+{
+ CURRENCY_TYPE_CONQUEST_POINTS = 390,
+ CURRENCY_TYPE_HONOR_POINTS = 392,
+ CURRENCY_TYPE_JUSTICE_POINTS = 395,
+ CURRENCY_TYPE_VALOR_POINTS = 396,
+ CURRENCY_TYPE_CONQUEST_META_ARENA = 483,
+ CURRENCY_TYPE_CONQUEST_META_RBG = 484,
+};
+
#endif
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index e960422cbbc..05a1eb71e90 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -22,6 +22,7 @@
#include "SpellMgr.h"
#include "TransportMgr.h"
#include "DBCfmt.h"
+#include "ItemPrototype.h"
#include "Timer.h"
#include "ObjectDefines.h"
@@ -60,6 +61,7 @@ static WMOAreaInfoByTripple sWMOAreaInfoByTripple;
DBCStorage <AchievementEntry> sAchievementStore(Achievementfmt);
DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore(AchievementCriteriafmt);
DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt);
+DBCStorage <ArmorLocationEntry> sArmorLocationStore(ArmorLocationfmt);
DBCStorage <AuctionHouseEntry> sAuctionHouseStore(AuctionHouseEntryfmt);
DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt);
DBCStorage <BannedAddOnsEntry> sBannedAddOnsStore(BannedAddOnsfmt);
@@ -71,6 +73,7 @@ DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt);
DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt);
DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt);
DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt);
+DBCStorage <ChrPowerTypesEntry> sChrPowerTypesStore(ChrClassesXPowerTypesfmt);
DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore(CinematicSequencesEntryfmt);
DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt);
DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore(CreatureDisplayInfoExtrafmt);
@@ -79,6 +82,7 @@ DBCStorage <CreatureModelDataEntry> sCreatureModelDataStore(CreatureModelDatafmt
DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt);
DBCStorage <CreatureTypeEntry> sCreatureTypeStore(CreatureTypefmt);
DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore(CurrencyTypesfmt);
+uint32 PowersByClass[MAX_CLASSES][MAX_POWERS];
DBCStorage <DestructibleModelDataEntry> sDestructibleModelDataStore(DestructibleModelDatafmt);
DBCStorage <DungeonEncounterEntry> sDungeonEncounterStore(DungeonEncounterfmt);
@@ -108,16 +112,36 @@ DBCStorage <GtNPCManaCostScalerEntry> sGtNPCManaCostScalerStore(GtNPCManaCos
DBCStorage <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStore(GtOCTClassCombatRatingScalarfmt);
DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore(GtOCTRegenHPfmt);
//DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently
-DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore(GtRegenHPPerSptfmt);
+DBCStorage <gtOCTHpPerStaminaEntry> sGtOCTHpPerStaminaStore(GtOCTHpPerStaminafmt);
DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptfmt);
+DBCStorage <GtSpellScalingEntry> sGtSpellScalingStore(GtSpellScalingfmt);
+DBCStorage <GtOCTBaseHPByClassEntry> sGtOCTBaseHPByClassStore(GtOCTBaseHPByClassfmt);
+DBCStorage <GtOCTBaseMPByClassEntry> sGtOCTBaseMPByClassStore(GtOCTBaseMPByClassfmt);
+DBCStorage <GuildPerkSpellsEntry> sGuildPerkSpellsStore(GuildPerkSpellsfmt);
DBCStorage <HolidaysEntry> sHolidaysStore(Holidaysfmt);
-DBCStorage <ItemEntry> sItemStore(Itemfmt);
+DBCStorage <ImportPriceArmorEntry> sImportPriceArmorStore(ImportPriceArmorfmt);
+DBCStorage <ImportPriceQualityEntry> sImportPriceQualityStore(ImportPriceQualityfmt);
+DBCStorage <ImportPriceShieldEntry> sImportPriceShieldStore(ImportPriceShieldfmt);
+DBCStorage <ImportPriceWeaponEntry> sImportPriceWeaponStore(ImportPriceWeaponfmt);
+DBCStorage <ItemPriceBaseEntry> sItemPriceBaseStore(ItemPriceBasefmt);
+DBCStorage <ItemReforgeEntry> sItemReforgeStore(ItemReforgefmt);
+DBCStorage <ItemArmorQualityEntry> sItemArmorQualityStore(ItemArmorQualityfmt);
+DBCStorage <ItemArmorShieldEntry> sItemArmorShieldStore(ItemArmorShieldfmt);
+DBCStorage <ItemArmorTotalEntry> sItemArmorTotalStore(ItemArmorTotalfmt);
+DBCStorage <ItemClassEntry> sItemClassStore(ItemClassfmt);
DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore(ItemBagFamilyfmt);
-//DBCStorage <ItemCondExtCostsEntry> sItemCondExtCostsStore(ItemCondExtCostsEntryfmt);
+DBCStorage <ItemDamageEntry> sItemDamageAmmoStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageOneHandStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageOneHandCasterStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageRangedStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageThrownStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageTwoHandStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageTwoHandCasterStore(ItemDamagefmt);
+DBCStorage <ItemDamageEntry> sItemDamageWandStore(ItemDamagefmt);
+DBCStorage <ItemDisenchantLootEntry> sItemDisenchantLootStore(ItemDisenchantLootfmt);
//DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently
-DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore(ItemLimitCategoryEntryfmt);
DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomPropertiesfmt);
DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
@@ -136,6 +160,12 @@ DBCStorage <MapDifficultyEntry> sMapDifficultyStore(MapDifficultyEntryfmt); // o
MapDifficultyMap sMapDifficultyMap;
DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt);
+DBCStorage <MountCapabilityEntry> sMountCapabilityStore(MountCapabilityfmt);
+DBCStorage <MountTypeEntry> sMountTypeStore(MountTypefmt);
+
+DBCStorage <NameGenEntry> sNameGenStore(NameGenfmt);
+NameGenVectorArraysMap sGenNameVectoArraysMap;
+DBCStorage <NumTalentsAtLevelEntry> sNumTalentsAtLevelStore(NumTalentsAtLevelfmt);
DBCStorage <OverrideSpellDataEntry> sOverrideSpellDataStore(OverrideSpellDatafmt);
@@ -163,20 +193,40 @@ DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt);
SpellCategoryStore sSpellsByCategoryStore;
PetFamilySpellsStore sPetFamilySpellsStore;
+
+DBCStorage <SpellReagentsEntry> sSpellReagentsStore(SpellReagentsEntryfmt);
+DBCStorage <SpellScalingEntry> sSpellScalingStore(SpellScalingEntryfmt);
+DBCStorage <SpellTotemsEntry> sSpellTotemsStore(SpellTotemsEntryfmt);
+DBCStorage <SpellTargetRestrictionsEntry> sSpellTargetRestrictionsStore(SpellTargetRestrictionsEntryfmt);
+DBCStorage <SpellPowerEntry> sSpellPowerStore(SpellPowerEntryfmt);
+DBCStorage <SpellLevelsEntry> sSpellLevelsStore(SpellLevelsEntryfmt);
+DBCStorage <SpellInterruptsEntry> sSpellInterruptsStore(SpellInterruptsEntryfmt);
+DBCStorage <SpellEquippedItemsEntry> sSpellEquippedItemsStore(SpellEquippedItemsEntryfmt);
+DBCStorage <SpellClassOptionsEntry> sSpellClassOptionsStore(SpellClassOptionsEntryfmt);
+DBCStorage <SpellCooldownsEntry> sSpellCooldownsStore(SpellCooldownsEntryfmt);
+DBCStorage <SpellAuraOptionsEntry> sSpellAuraOptionsStore(SpellAuraOptionsEntryfmt);
+DBCStorage <SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore(SpellAuraRestrictionsEntryfmt);
+DBCStorage <SpellCastingRequirementsEntry> sSpellCastingRequirementsStore(SpellCastingRequirementsEntryfmt);
DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore(SpellCastTimefmt);
+DBCStorage <SpellCategoriesEntry> sSpellCategoriesStore(SpellCategoriesEntryfmt);
DBCStorage <SpellCategoryEntry> sSpellCategoryStore(SpellCategoryfmt);
+DBCStorage <SpellEffectEntry> sSpellEffectStore(SpellEffectEntryfmt);
DBCStorage <SpellDifficultyEntry> sSpellDifficultyStore(SpellDifficultyfmt);
DBCStorage <SpellDurationEntry> sSpellDurationStore(SpellDurationfmt);
DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore(SpellFocusObjectfmt);
DBCStorage <SpellRadiusEntry> sSpellRadiusStore(SpellRadiusfmt);
DBCStorage <SpellRangeEntry> sSpellRangeStore(SpellRangefmt);
DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore(SpellRuneCostfmt);
-DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore(SpellShapeshiftfmt);
+DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore(SpellShapeshiftEntryfmt);
+DBCStorage <SpellShapeshiftFormEntry> sSpellShapeshiftFormStore(SpellShapeshiftFormfmt);
DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore(StableSlotPricesfmt);
DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore(SummonPropertiesfmt);
DBCStorage <TalentEntry> sTalentStore(TalentEntryfmt);
TalentSpellPosMap sTalentSpellPosMap;
DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt);
+DBCStorage <TalentTreePrimarySpellsEntry> sTalentTreePrimarySpellsStore(TalentTreePrimarySpellsfmt);
+typedef std::map<uint32, std::vector<uint32> > TalentTreePrimarySpellsMap;
+TalentTreePrimarySpellsMap sTalentTreePrimarySpellsMap;
// store absolute bit position for first rank for talent inspect
static uint32 sTalentTabPages[MAX_CLASSES][3];
@@ -196,16 +246,20 @@ DBCStorage <TaxiPathEntry> sTaxiPathStore(TaxiPathEntryfmt);
TaxiPathNodesByPath sTaxiPathNodesByPath;
static DBCStorage <TaxiPathNodeEntry> sTaxiPathNodeStore(TaxiPathNodeEntryfmt);
-DBCStorage <TeamContributionPointsEntry> sTeamContributionPointsStore(TeamContributionPointsfmt);
DBCStorage <TotemCategoryEntry> sTotemCategoryStore(TotemCategoryEntryfmt);
DBCStorage <TransportAnimationEntry> sTransportAnimationStore(TransportAnimationfmt);
DBCStorage <TransportRotationEntry> sTransportRotationStore(TransportRotationfmt);
+DBCStorage <UnitPowerBarEntry> sUnitPowerBarStore(UnitPowerBarfmt);
DBCStorage <VehicleEntry> sVehicleStore(VehicleEntryfmt);
DBCStorage <VehicleSeatEntry> sVehicleSeatStore(VehicleSeatEntryfmt);
DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore(WMOAreaTableEntryfmt);
DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt);
DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore(WorldMapOverlayEntryfmt);
DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt);
+DBCStorage <PhaseEntry> sPhaseStore(PhaseEntryfmt);
+DBCStorage <PhaseGroupEntry> sPhaseGroupStore(PhaseGroupfmt);
+
+PhaseGroupContainer sPhasesByGroup;
typedef std::list<std::string> StoreProblemList;
@@ -290,40 +344,59 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementStore, dbcPath, "Achievement.dbc", &CustomAchievementfmt, &CustomAchievementIndex);
- LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementCriteriaStore, dbcPath, "Achievement_Criteria.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTriggerStore, dbcPath, "AreaTrigger.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sAreaGroupStore, dbcPath, "AreaGroup.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sAreaPOIStore, dbcPath, "AreaPOI.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sAuctionHouseStore, dbcPath, "AuctionHouse.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sBankBagSlotPricesStore, dbcPath, "BankBagSlotPrices.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementStore, dbcPath, "Achievement.dbc", &CustomAchievementfmt, &CustomAchievementIndex);//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementCriteriaStore, dbcPath, "Achievement_Criteria.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTriggerStore, dbcPath, "AreaTrigger.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAreaGroupStore, dbcPath, "AreaGroup.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAreaPOIStore, dbcPath, "AreaPOI.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAuctionHouseStore, dbcPath, "AuctionHouse.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sArmorLocationStore, dbcPath, "ArmorLocation.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sBankBagSlotPricesStore, dbcPath, "BankBagSlotPrices.dbc");//15595
LoadDBC(availableDbcLocales, bad_dbc_files, sBannedAddOnsStore, dbcPath, "BannedAddOns.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sBattlemasterListStore, dbcPath, "BattlemasterList.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sBarberShopStyleStore, dbcPath, "BarberShopStyle.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCharStartOutfitStore, dbcPath, "CharStartOutfit.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sBattlemasterListStore, dbcPath, "BattlemasterList.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sBarberShopStyleStore, dbcPath, "BarberShopStyle.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCharStartOutfitStore, dbcPath, "CharStartOutfit.dbc");//15595
for (uint32 i = 0; i < sCharStartOutfitStore.GetNumRows(); ++i)
if (CharStartOutfitEntry const* outfit = sCharStartOutfitStore.LookupEntry(i))
sCharStartOutfitMap[outfit->Race | (outfit->Class << 8) | (outfit->Gender << 16)] = outfit;
- LoadDBC(availableDbcLocales, bad_dbc_files, sCharTitlesStore, dbcPath, "CharTitles.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sChrRacesStore, dbcPath, "ChrRaces.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoExtraStore, dbcPath, "CreatureDisplayInfoExtra.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureFamilyStore, dbcPath, "CreatureFamily.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureModelDataStore, dbcPath, "CreatureModelData.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureSpellDataStore, dbcPath, "CreatureSpellData.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureTypeStore, dbcPath, "CreatureType.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sCurrencyTypesStore, dbcPath, "CurrencyTypes.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sDestructibleModelDataStore, dbcPath, "DestructibleModelData.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sDungeonEncounterStore, dbcPath, "DungeonEncounter.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityCostsStore, dbcPath, "DurabilityCosts.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityQualityStore, dbcPath, "DurabilityQuality.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesStore, dbcPath, "Emotes.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesTextStore, dbcPath, "EmotesText.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sFactionStore, dbcPath, "Faction.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCharTitlesStore, dbcPath, "CharTitles.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sChrRacesStore, dbcPath, "ChrRaces.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sChrPowerTypesStore, dbcPath, "ChrClassesXPowerTypes.dbc");//15595
+ for (uint32 i = 0; i < MAX_CLASSES; ++i)
+ for (uint32 j = 0; j < MAX_POWERS; ++j)
+ PowersByClass[i][j] = MAX_POWERS;
+
+ for (uint32 i = 0; i < sChrPowerTypesStore.GetNumRows(); ++i)
+ {
+ if (ChrPowerTypesEntry const* power = sChrPowerTypesStore.LookupEntry(i))
+ {
+ uint32 index = 0;
+ for (uint32 j = 0; j < MAX_POWERS; ++j)
+ if (PowersByClass[power->classId][j] != MAX_POWERS)
+ ++index;
+
+ PowersByClass[power->classId][power->power] = index;
+ }
+ }
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoExtraStore, dbcPath, "CreatureDisplayInfoExtra.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureFamilyStore, dbcPath, "CreatureFamily.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureModelDataStore, dbcPath, "CreatureModelData.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureSpellDataStore, dbcPath, "CreatureSpellData.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureTypeStore, dbcPath, "CreatureType.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCurrencyTypesStore, dbcPath, "CurrencyTypes.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sDestructibleModelDataStore, dbcPath, "DestructibleModelData.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sDungeonEncounterStore, dbcPath, "DungeonEncounter.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityCostsStore, dbcPath, "DurabilityCosts.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityQualityStore, dbcPath, "DurabilityQuality.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesStore, dbcPath, "Emotes.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesTextStore, dbcPath, "EmotesText.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sFactionStore, dbcPath, "Faction.dbc");//15595
for (uint32 i=0; i<sFactionStore.GetNumRows(); ++i)
{
FactionEntry const* faction = sFactionStore.LookupEntry(i);
@@ -334,8 +407,8 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sFactionTemplateStore, dbcPath, "FactionTemplate.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGameObjectDisplayInfoStore, dbcPath, "GameObjectDisplayInfo.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sFactionTemplateStore, dbcPath, "FactionTemplate.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGameObjectDisplayInfoStore, dbcPath, "GameObjectDisplayInfo.dbc");//15595
for (uint32 i = 0; i < sGameObjectDisplayInfoStore.GetNumRows(); ++i)
{
if (GameObjectDisplayInfoEntry const* info = sGameObjectDisplayInfoStore.LookupEntry(i))
@@ -349,69 +422,110 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sGemPropertiesStore, dbcPath, "GemProperties.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphPropertiesStore, dbcPath, "GlyphProperties.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphSlotStore, dbcPath, "GlyphSlot.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtBarberShopCostBaseStore, dbcPath, "gtBarberShopCostBase.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtCombatRatingsStore, dbcPath, "gtCombatRatings.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritBaseStore, dbcPath, "gtChanceToMeleeCritBase.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritStore, dbcPath, "gtChanceToMeleeCrit.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritBaseStore, dbcPath, "gtChanceToSpellCritBase.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritStore, dbcPath, "gtChanceToSpellCrit.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGemPropertiesStore, dbcPath, "GemProperties.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphPropertiesStore, dbcPath, "GlyphProperties.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphSlotStore, dbcPath, "GlyphSlot.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtBarberShopCostBaseStore, dbcPath, "gtBarberShopCostBase.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtCombatRatingsStore, dbcPath, "gtCombatRatings.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritBaseStore, dbcPath, "gtChanceToMeleeCritBase.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritStore, dbcPath, "gtChanceToMeleeCrit.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritBaseStore, dbcPath, "gtChanceToSpellCritBase.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritStore, dbcPath, "gtChanceToSpellCrit.dbc");//15595
LoadDBC(availableDbcLocales, bad_dbc_files, sGtNPCManaCostScalerStore, dbcPath, "gtNPCManaCostScaler.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTClassCombatRatingScalarStore, dbcPath, "gtOCTClassCombatRatingScalar.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTRegenHPStore, dbcPath, "gtOCTRegenHP.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTClassCombatRatingScalarStore, dbcPath, "gtOCTClassCombatRatingScalar.dbc");//15595
+ //LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTRegenHPStore, dbcPath, "gtOCTRegenHP.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTHpPerStaminaStore, dbcPath, "gtOCTHpPerStamina.dbc");//15595
//LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sGtOCTRegenMPStore, dbcPath, "gtOCTRegenMP.dbc"); -- not used currently
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenHPPerSptStore, dbcPath, "gtRegenHPPerSpt.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenMPPerSptStore, dbcPath, "gtRegenMPPerSpt.dbc");
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sHolidaysStore, dbcPath, "Holidays.dbc");
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemStore, dbcPath, "Item.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemBagFamilyStore, dbcPath, "ItemBagFamily.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenMPPerSptStore, dbcPath, "gtRegenMPPerSpt.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtSpellScalingStore, dbcPath, "gtSpellScaling.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTBaseHPByClassStore, dbcPath, "gtOCTBaseHPByClass.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTBaseMPByClassStore, dbcPath, "gtOCTBaseMPByClass.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGuildPerkSpellsStore, dbcPath, "GuildPerkSpells.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sHolidaysStore, dbcPath, "Holidays.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceArmorStore, dbcPath, "ImportPriceArmor.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceQualityStore, dbcPath, "ImportPriceQuality.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceShieldStore, dbcPath, "ImportPriceShield.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceWeaponStore, dbcPath, "ImportPriceWeapon.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemPriceBaseStore, dbcPath, "ItemPriceBase.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemReforgeStore, dbcPath, "ItemReforge.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemBagFamilyStore, dbcPath, "ItemBagFamily.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemClassStore, dbcPath, "ItemClass.dbc"); // 15595
//LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sItemDisplayInfoStore, dbcPath, "ItemDisplayInfo.dbc"); -- not used currently
- //LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sItemCondExtCostsStore, dbcPath, "ItemCondExtCosts.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemExtendedCostStore, dbcPath, "ItemExtendedCost.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemLimitCategoryStore, dbcPath, "ItemLimitCategory.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomPropertiesStore, dbcPath, "ItemRandomProperties.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomSuffixStore, dbcPath, "ItemRandomSuffix.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sItemSetStore, dbcPath, "ItemSet.dbc");
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sLFGDungeonStore, dbcPath, "LFGDungeons.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sLightStore, dbcPath, "Light.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sLiquidTypeStore, dbcPath, "LiquidType.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sLockStore, dbcPath, "Lock.dbc");
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sMailTemplateStore, dbcPath, "MailTemplate.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sMapStore, dbcPath, "Map.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sMapDifficultyStore, dbcPath, "MapDifficulty.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemLimitCategoryStore, dbcPath, "ItemLimitCategory.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomPropertiesStore, dbcPath, "ItemRandomProperties.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomSuffixStore, dbcPath, "ItemRandomSuffix.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemSetStore, dbcPath, "ItemSet.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorQualityStore, dbcPath, "ItemArmorQuality.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorShieldStore, dbcPath, "ItemArmorShield.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorTotalStore, dbcPath, "ItemArmorTotal.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageAmmoStore, dbcPath, "ItemDamageAmmo.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageOneHandStore, dbcPath, "ItemDamageOneHand.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageOneHandCasterStore, dbcPath, "ItemDamageOneHandCaster.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageRangedStore, dbcPath, "ItemDamageRanged.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageThrownStore, dbcPath, "ItemDamageThrown.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageTwoHandStore, dbcPath, "ItemDamageTwoHand.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageTwoHandCasterStore, dbcPath, "ItemDamageTwoHandCaster.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageWandStore, dbcPath, "ItemDamageWand.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDisenchantLootStore, dbcPath, "ItemDisenchantLoot.dbc");
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sLFGDungeonStore, dbcPath, "LFGDungeons.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sLightStore, dbcPath, "Light.dbc"); //15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sLiquidTypeStore, dbcPath, "LiquidType.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sLockStore, dbcPath, "Lock.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMailTemplateStore, dbcPath, "MailTemplate.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMapStore, dbcPath, "Map.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMapDifficultyStore, dbcPath, "MapDifficulty.dbc");//15595
// fill data
- for (uint32 i = 1; i < sMapDifficultyStore.GetNumRows(); ++i)
+ sMapDifficultyMap[MAKE_PAIR32(0, 0)] = MapDifficulty(0, 0, false);//map 0 is missingg from MapDifficulty.dbc use this till its ported to sql
+ for (uint32 i = 0; i < sMapDifficultyStore.GetNumRows(); ++i)
if (MapDifficultyEntry const* entry = sMapDifficultyStore.LookupEntry(i))
- sMapDifficultyMap[MAKE_PAIR32(entry->MapId, entry->Difficulty)] = MapDifficulty(entry->resetTime, entry->maxPlayers, entry->areaTriggerText[0] != '\0');
+ sMapDifficultyMap[MAKE_PAIR32(entry->MapId, entry->Difficulty)] = MapDifficulty(entry->resetTime, entry->maxPlayers, entry->areaTriggerText[0] > 0);
sMapDifficultyStore.Clear();
- LoadDBC(availableDbcLocales, bad_dbc_files, sMovieStore, dbcPath, "Movie.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMountCapabilityStore, dbcPath, "MountCapability.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMountTypeStore, dbcPath, "MountType.dbc");//15595
- LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sNameGenStore, dbcPath, "NameGen.dbc");//15595
+ for (uint32 i = 0; i < sNameGenStore.GetNumRows(); ++i)
+ if (NameGenEntry const* entry = sNameGenStore.LookupEntry(i))
+ sGenNameVectoArraysMap[entry->race].stringVectorArray[entry->gender].push_back(std::string(entry->name));
+ sNameGenStore.Clear();
+ LoadDBC(availableDbcLocales, bad_dbc_files, sNumTalentsAtLevelStore, dbcPath, "NumTalentsAtLevel.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMovieStore, dbcPath, "Movie.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sPhaseStore, dbcPath, "Phase.dbc"); // 15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sPhaseGroupStore, dbcPath, "PhaseXPhaseGroup.dbc"); // 15595
+
+ for (uint32 i = 0; i < sPhaseGroupStore.GetNumRows(); ++i)
+ if (PhaseGroupEntry const* group = sPhaseGroupStore.LookupEntry(i))
+ if (PhaseEntry const* phase = sPhaseStore.LookupEntry(group->PhaseId))
+ sPhasesByGroup[group->GroupId].insert(phase->ID);
LoadDBC(availableDbcLocales, bad_dbc_files, sPowerDisplayStore, dbcPath, "PowerDisplay.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc");
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc");//15595
+
for (uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i)
if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i))
if (entry->bracketId > MAX_BATTLEGROUND_BRACKETS)
ASSERT(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data");
- LoadDBC(availableDbcLocales, bad_dbc_files, sQuestXPStore, dbcPath, "QuestXP.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sQuestFactionRewardStore, dbcPath, "QuestFactionReward.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sQuestSortStore, dbcPath, "QuestSort.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sQuestXPStore, dbcPath, "QuestXP.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sQuestFactionRewardStore, dbcPath, "QuestFactionReward.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sQuestSortStore, dbcPath, "QuestSort.dbc");//15595
- LoadDBC(availableDbcLocales, bad_dbc_files, sRandomPropertiesPointsStore, dbcPath, "RandPropPoints.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sRandomPropertiesPointsStore, dbcPath, "RandPropPoints.dbc");//15595
- LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatDistributionStore, dbcPath, "ScalingStatDistribution.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatValuesStore, dbcPath, "ScalingStatValues.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineStore, dbcPath, "SkillLine.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineAbilityStore, dbcPath, "SkillLineAbility.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatDistributionStore, dbcPath, "ScalingStatDistribution.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatValuesStore, dbcPath, "ScalingStatValues.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineStore, dbcPath, "SkillLine.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineAbilityStore, dbcPath, "SkillLineAbility.dbc");//15595
LoadDBC(availableDbcLocales, bad_dbc_files, sSkillRaceClassInfoStore, dbcPath, "SkillRaceClassInfo.dbc");
for (uint32 i = 0; i < sSkillRaceClassInfoStore.GetNumRows(); ++i)
if (SkillRaceClassInfoEntry const* entry = sSkillRaceClassInfoStore.LookupEntry(i))
@@ -419,23 +533,62 @@ void LoadDBCStores(const std::string& dataPath)
SkillRaceClassInfoBySkill.emplace(entry->SkillId, entry);
LoadDBC(availableDbcLocales, bad_dbc_files, sSkillTiersStore, dbcPath, "SkillTiers.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex);
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex);//
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoriesStore, dbcPath,"SpellCategories.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoryStore, dbcPath, "SpellCategory.dbc");
for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
{
SpellEntry const* spell = sSpellStore.LookupEntry(i);
- if (spell && spell->Category)
- sSpellsByCategoryStore[spell->Category].insert(i);
+ if (!spell)
+ continue;
+
+ if (SpellCategoriesEntry const* category = sSpellCategoriesStore.LookupEntry(spell->SpellCategoriesId))
+ sSpellsByCategoryStore[category->Category].insert(i);
}
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellReagentsStore, dbcPath,"SpellReagents.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellScalingStore, dbcPath,"SpellScaling.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellTotemsStore, dbcPath,"SpellTotems.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellTargetRestrictionsStore, dbcPath,"SpellTargetRestrictions.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellPowerStore, dbcPath,"SpellPower.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellLevelsStore, dbcPath,"SpellLevels.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellInterruptsStore, dbcPath,"SpellInterrupts.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellEquippedItemsStore, dbcPath,"SpellEquippedItems.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellClassOptionsStore, dbcPath,"SpellClassOptions.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCooldownsStore, dbcPath,"SpellCooldowns.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellAuraOptionsStore, dbcPath,"SpellAuraOptions.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellAuraRestrictionsStore, dbcPath,"SpellAuraRestrictions.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastingRequirementsStore, dbcPath,"SpellCastingRequirements.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellEffectStore, dbcPath,"SpellEffect.dbc", &CustomSpellEffectEntryfmt, &CustomSpellEffectEntryIndex);//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastTimesStore, dbcPath, "SpellCastTimes.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDifficultyStore, dbcPath, "SpellDifficulty.dbc", &CustomSpellDifficultyfmt, &CustomSpellDifficultyIndex);//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDurationStore, dbcPath, "SpellDuration.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellFocusObjectStore, dbcPath, "SpellFocusObject.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentStore, dbcPath, "SpellItemEnchantment.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentConditionStore, dbcPath, "SpellItemEnchantmentCondition.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRadiusStore, dbcPath, "SpellRadius.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRangeStore, dbcPath, "SpellRange.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRuneCostStore, dbcPath, "SpellRuneCost.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftStore, dbcPath, "SpellShapeshift.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftFormStore, dbcPath, "SpellShapeshiftForm.dbc");//15595
+ //LoadDBC(availableDbcLocales, bad_dbc_files, sStableSlotPricesStore, dbcPath, "StableSlotPrices.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSummonPropertiesStore, dbcPath, "SummonProperties.dbc");//15595
+
+ // Must be done when sSkillLineAbilityStore, sSpellStore, sSpellLevelsStore and sCreatureFamilyStore are all loaded
for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
{
SkillLineAbilityEntry const* skillLine = sSkillLineAbilityStore.LookupEntry(j);
-
if (!skillLine)
continue;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
+ if (!spellInfo)
+ continue;
+
+ SpellLevelsEntry const* levels = sSpellLevelsStore.LookupEntry(spellInfo->SpellLevelsId);
+ if (spellInfo->SpellLevelsId && (!levels || levels->spellLevel))
+ continue;
if (spellInfo && spellInfo->Attributes & SPELL_ATTR0_PASSIVE)
{
@@ -447,8 +600,6 @@ void LoadDBCStores(const std::string& dataPath)
if (skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1])
continue;
- if (spellInfo->spellLevel)
- continue;
if (skillLine->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN)
continue;
@@ -458,21 +609,7 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastTimesStore, dbcPath, "SpellCastTimes.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoryStore, dbcPath, "SpellCategory.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDifficultyStore, dbcPath, "SpellDifficulty.dbc", &CustomSpellDifficultyfmt, &CustomSpellDifficultyIndex);
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDurationStore, dbcPath, "SpellDuration.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellFocusObjectStore, dbcPath, "SpellFocusObject.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentStore, dbcPath, "SpellItemEnchantment.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentConditionStore, dbcPath, "SpellItemEnchantmentCondition.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRadiusStore, dbcPath, "SpellRadius.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRangeStore, dbcPath, "SpellRange.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRuneCostStore, dbcPath, "SpellRuneCost.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftStore, dbcPath, "SpellShapeshiftForm.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sStableSlotPricesStore, dbcPath, "StableSlotPrices.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSummonPropertiesStore, dbcPath, "SummonProperties.dbc");
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sTalentStore, dbcPath, "Talent.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTalentStore, dbcPath, "Talent.dbc");//15595
// Create Spelldifficulty searcher
for (uint32 i = 0; i < sSpellDifficultyStore.GetNumRows(); ++i)
@@ -483,7 +620,7 @@ void LoadDBCStores(const std::string& dataPath)
SpellDifficultyEntry newEntry;
memset(newEntry.SpellID, 0, 4*sizeof(uint32));
- for (int x = 0; x < MAX_DIFFICULTY; ++x)
+ for (uint32 x = 0; x < MAX_DIFFICULTY; ++x)
{
if (spellDiff->SpellID[x] <= 0 || !sSpellStore.LookupEntry(spellDiff->SpellID[x]))
{
@@ -494,10 +631,11 @@ void LoadDBCStores(const std::string& dataPath)
else
newEntry.SpellID[x] = spellDiff->SpellID[x];
}
+
if (newEntry.SpellID[0] <= 0 || newEntry.SpellID[1] <= 0)//id0-1 must be always set!
continue;
- for (int x = 0; x < MAX_DIFFICULTY; ++x)
+ for (uint32 x = 0; x < MAX_DIFFICULTY; ++x)
if (newEntry.SpellID[x])
sSpellMgr->SetSpellDifficultyId(uint32(newEntry.SpellID[x]), spellDiff->ID);
}
@@ -514,7 +652,7 @@ void LoadDBCStores(const std::string& dataPath)
sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(i, j);
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sTalentTabStore, dbcPath, "TalentTab.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTalentTabStore, dbcPath, "TalentTab.dbc");//15595
// prepare fast data access to bit pos of talent ranks for use at inspecting
{
@@ -536,15 +674,21 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiNodesStore, dbcPath, "TaxiNodes.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathStore, dbcPath, "TaxiPath.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTalentTreePrimarySpellsStore, dbcPath, "TalentTreePrimarySpells.dbc");
+ for (uint32 i = 0; i < sTalentTreePrimarySpellsStore.GetNumRows(); ++i)
+ if (TalentTreePrimarySpellsEntry const* talentSpell = sTalentTreePrimarySpellsStore.LookupEntry(i))
+ sTalentTreePrimarySpellsMap[talentSpell->TalentTree].push_back(talentSpell->SpellId);
+ sTalentTreePrimarySpellsStore.Clear();
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiNodesStore, dbcPath, "TaxiNodes.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathStore, dbcPath, "TaxiPath.dbc");//15595
for (uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i)
if (TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i))
sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID, entry->price);
uint32 pathCount = sTaxiPathStore.GetNumRows();
//## TaxiPathNode.dbc ## Loaded only for initialization different structures
- LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathNodeStore, dbcPath, "TaxiPathNode.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathNodeStore, dbcPath, "TaxiPathNode.dbc");//15595
// Calculate path nodes count
std::vector<uint32> pathLength;
pathLength.resize(pathCount); // 0 and some other indexes not used
@@ -567,11 +711,10 @@ void LoadDBCStores(const std::string& dataPath)
// include existed nodes that have at least single not spell base (scripted) path
{
std::set<uint32> spellPaths;
- for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
- if (SpellEntry const* sInfo = sSpellStore.LookupEntry (i))
- for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
- if (sInfo->Effect[j] == SPELL_EFFECT_SEND_TAXI)
- spellPaths.insert(sInfo->EffectMiscValue[j]);
+ for (uint32 i = 1; i < sSpellEffectStore.GetNumRows(); ++i)
+ if (SpellEffectEntry const* sInfo = sSpellEffectStore.LookupEntry (i))
+ if (sInfo->Effect == SPELL_EFFECT_SEND_TAXI)
+ spellPaths.insert(sInfo->EffectMiscValue);
memset(sTaxiNodesMask, 0, sizeof(sTaxiNodesMask));
memset(sOldContinentsNodesMask, 0, sizeof(sOldContinentsNodesMask));
@@ -603,10 +746,10 @@ void LoadDBCStores(const std::string& dataPath)
}
// valid taxi network node
- uint8 field = (uint8)((i - 1) / 32);
- uint32 submask = 1<<((i-1)%32);
- sTaxiNodesMask[field] |= submask;
+ uint8 field = (uint8)((i - 1) / 8);
+ uint32 submask = 1 << ((i-1) % 8);
+ sTaxiNodesMask[field] |= submask;
if (node->MountCreatureID[0] && node->MountCreatureID[0] != 32981)
sHordeTaxiNodesMask[field] |= submask;
if (node->MountCreatureID[1] && node->MountCreatureID[1] != 32981)
@@ -624,8 +767,8 @@ void LoadDBCStores(const std::string& dataPath)
}
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sTeamContributionPointsStore, dbcPath, "TeamContributionPoints.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sTotemCategoryStore, dbcPath, "TotemCategory.dbc");
+ //LoadDBC(availableDbcLocales, bad_dbc_files, sTeamContributionPointsStore, dbcPath, "TeamContributionPoints.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTotemCategoryStore, dbcPath, "TotemCategory.dbc");//15595
LoadDBC(availableDbcLocales, bad_dbc_files, sTransportAnimationStore, dbcPath, "TransportAnimation.dbc");
for (uint32 i = 0; i < sTransportAnimationStore.GetNumRows(); ++i)
{
@@ -646,16 +789,18 @@ void LoadDBCStores(const std::string& dataPath)
sTransportMgr->AddPathRotationToTransport(rot->TransportEntry, rot->TimeSeg, rot);
}
- LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleStore, dbcPath, "Vehicle.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleSeatStore, dbcPath, "VehicleSeat.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sUnitPowerBarStore, dbcPath, "UnitPowerBar.dbc");//15595
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleStore, dbcPath, "Vehicle.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleSeatStore, dbcPath, "VehicleSeat.dbc");//15595
- LoadDBC(availableDbcLocales, bad_dbc_files, sWMOAreaTableStore, dbcPath, "WMOAreaTable.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sWMOAreaTableStore, dbcPath, "WMOAreaTable.dbc");//15595
for (uint32 i = 0; i < sWMOAreaTableStore.GetNumRows(); ++i)
if (WMOAreaTableEntry const* entry = sWMOAreaTableStore.LookupEntry(i))
sWMOAreaInfoByTripple.insert(WMOAreaInfoByTripple::value_type(WMOAreaTableTripple(entry->rootId, entry->adtId, entry->groupId), entry));
- LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapAreaStore, dbcPath, "WorldMapArea.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapOverlayStore, dbcPath, "WorldMapOverlay.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sWorldSafeLocsStore, dbcPath, "WorldSafeLocs.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapAreaStore, dbcPath, "WorldMapArea.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapOverlayStore, dbcPath, "WorldMapOverlay.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sWorldSafeLocsStore, dbcPath, "WorldSafeLocs.dbc");//15595
// error checks
if (bad_dbc_files.size() >= DBCFileCount)
@@ -674,20 +819,25 @@ void LoadDBCStores(const std::string& dataPath)
}
// Check loaded DBC files proper version
- if (!sAreaStore.LookupEntry(3617) || // last area (areaflag) added in 3.3.5a
- !sCharTitlesStore.LookupEntry(177) || // last char title added in 3.3.5a
- !sGemPropertiesStore.LookupEntry(1629) || // last added spell in 3.3.5a
- !sItemStore.LookupEntry(56806) || // last gem property added in 3.3.5a
- !sItemExtendedCostStore.LookupEntry(2997) || // last item extended cost added in 3.3.5a
- !sMapStore.LookupEntry(724) || // last map added in 3.3.5a
- !sSpellStore.LookupEntry(80864) ) // last client known item added in 3.3.5a
+ if (!sAreaStore.LookupEntry(4713) || // last area (areaflag) added in 4.3.4 (15595)
+ !sCharTitlesStore.LookupEntry(287) || // last char title added in 4.3.4 (15595)
+ !sGemPropertiesStore.LookupEntry(2250) || // last gem property added in 4.3.4 (15595)
+ !sMapStore.LookupEntry(980) || // last map added in 4.3.4 (15595)
+ !sSpellStore.LookupEntry(121820) ) // last spell added in 4.3.4 (15595)
{
TC_LOG_ERROR("misc", "You have _outdated_ DBC files. Please extract correct versions from current using client.");
exit(1);
}
- TC_LOG_INFO("server.loading", ">> Initialized %d data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Initialized %d DBC data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime));
+}
+
+const std::string* GetRandomCharacterName(uint8 race, uint8 gender)
+{
+ uint32 size = sGenNameVectoArraysMap[race].stringVectorArray[gender].size();
+ uint32 randPos = urand(0, size-1);
+ return &sGenNameVectoArraysMap[race].stringVectorArray[gender][randPos];
}
SimpleFactionsList const* GetFactionTeamList(uint32 faction)
@@ -699,14 +849,14 @@ SimpleFactionsList const* GetFactionTeamList(uint32 faction)
return NULL;
}
-char* GetPetName(uint32 petfamily, uint32 dbclang)
+char const* GetPetName(uint32 petfamily, uint32 /*dbclang*/)
{
if (!petfamily)
return NULL;
CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(petfamily);
if (!pet_family)
return NULL;
- return pet_family->Name[dbclang]?pet_family->Name[dbclang]:NULL;
+ return pet_family->Name ? pet_family->Name : NULL;
}
TalentSpellPos const* GetTalentSpellPos(uint32 spellId)
@@ -763,16 +913,16 @@ AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag, uint32 map_
return NULL;
}
-char const* GetRaceName(uint8 race, uint8 locale)
+char const* GetRaceName(uint8 race, uint8 /*locale*/)
{
ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race);
- return raceEntry ? raceEntry->name[locale] : NULL;
+ return raceEntry ? raceEntry->name : NULL;
}
-char const* GetClassName(uint8 class_, uint8 locale)
+char const* GetClassName(uint8 class_, uint8 /*locale*/)
{
ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_);
- return classEntry ? classEntry->name[locale] : NULL;
+ return classEntry ? classEntry->name : NULL;
}
uint32 GetAreaFlagByMapId(uint32 mapid)
@@ -786,7 +936,7 @@ uint32 GetAreaFlagByMapId(uint32 mapid)
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
{
- if (mapid != 530 && mapid != 571) // speed for most cases
+ if (mapid != 530 && mapid != 571 && mapid != 732) // speed for most cases
return mapid;
if (WorldMapAreaEntry const* wma = sWorldMapAreaStore.LookupEntry(zoneId))
@@ -795,6 +945,28 @@ uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
return mapid;
}
+uint32 GetMaxLevelForExpansion(uint32 expansion)
+{
+ switch (expansion)
+ {
+ case CONTENT_1_60:
+ return 60;
+ case CONTENT_61_70:
+ return 70;
+ case CONTENT_71_80:
+ return 80;
+ case CONTENT_81_85:
+ return 85;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*
+Used only for calculate xp gain by content lvl.
+Calculation on Gilneas and group maps of LostIslands calculated as CONTENT_1_60.
+*/
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId)
{
mapid = GetVirtualMapForMapAndZone(mapid, zoneId);
@@ -805,11 +977,17 @@ ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId)
if (!mapEntry)
return CONTENT_1_60;
- switch (mapEntry->Expansion())
+ // no need enum all maps from phasing
+ if (mapEntry->rootPhaseMap >= 0)
+ mapid = mapEntry->rootPhaseMap;
+
+ switch (mapid)
{
- default: return CONTENT_1_60;
- case 1: return CONTENT_61_70;
- case 2: return CONTENT_71_80;
+ case 648: //LostIslands
+ case 654: //Gilneas
+ return CONTENT_1_60;
+ default:
+ return ContentLevels(mapEntry->Expansion());
}
}
@@ -928,6 +1106,15 @@ uint32 const* GetTalentTabPages(uint8 cls)
return sTalentTabPages[cls];
}
+std::vector<uint32> const* GetTalentTreePrimarySpells(uint32 talentTree)
+{
+ TalentTreePrimarySpellsMap::const_iterator itr = sTalentTreePrimarySpellsMap.find(talentTree);
+ if (itr == sTalentTreePrimarySpellsMap.end())
+ return NULL;
+
+ return &itr->second;
+}
+
uint32 GetLiquidFlags(uint32 liquidType)
{
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquidType))
@@ -945,6 +1132,163 @@ CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, ui
return itr->second;
}
+uint32 GetPowerIndexByClass(uint32 powerType, uint32 classId)
+{
+ return PowersByClass[classId][powerType];
+}
+
+uint32 ScalingStatValuesEntry::GetStatMultiplier(uint32 inventoryType) const
+{
+ if (inventoryType < MAX_INVTYPE)
+ {
+ switch (inventoryType)
+ {
+ case INVTYPE_NON_EQUIP:
+ case INVTYPE_BODY:
+ case INVTYPE_BAG:
+ case INVTYPE_TABARD:
+ case INVTYPE_AMMO:
+ case INVTYPE_QUIVER:
+ return 0;
+ case INVTYPE_HEAD:
+ case INVTYPE_CHEST:
+ case INVTYPE_LEGS:
+ case INVTYPE_2HWEAPON:
+ case INVTYPE_ROBE:
+ return StatMultiplier[0];
+ case INVTYPE_SHOULDERS:
+ case INVTYPE_WAIST:
+ case INVTYPE_FEET:
+ case INVTYPE_HANDS:
+ case INVTYPE_TRINKET:
+ return StatMultiplier[1];
+ case INVTYPE_NECK:
+ case INVTYPE_WRISTS:
+ case INVTYPE_FINGER:
+ case INVTYPE_SHIELD:
+ case INVTYPE_CLOAK:
+ case INVTYPE_HOLDABLE:
+ return StatMultiplier[2];
+ case INVTYPE_RANGED:
+ case INVTYPE_THROWN:
+ case INVTYPE_RANGEDRIGHT:
+ case INVTYPE_RELIC:
+ return StatMultiplier[3];
+ case INVTYPE_WEAPON:
+ case INVTYPE_WEAPONMAINHAND:
+ case INVTYPE_WEAPONOFFHAND:
+ return StatMultiplier[4];
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+uint32 ScalingStatValuesEntry::GetArmor(uint32 inventoryType, uint32 armorType) const
+{
+ if (inventoryType <= INVTYPE_ROBE && armorType < 4)
+ {
+ switch (inventoryType)
+ {
+ case INVTYPE_NON_EQUIP:
+ case INVTYPE_NECK:
+ case INVTYPE_BODY:
+ case INVTYPE_FINGER:
+ case INVTYPE_TRINKET:
+ case INVTYPE_WEAPON:
+ case INVTYPE_SHIELD:
+ case INVTYPE_RANGED:
+ case INVTYPE_2HWEAPON:
+ case INVTYPE_BAG:
+ case INVTYPE_TABARD:
+ break;
+ case INVTYPE_SHOULDERS:
+ return Armor[0][armorType];
+ case INVTYPE_CHEST:
+ case INVTYPE_ROBE:
+ return Armor[1][armorType];
+ case INVTYPE_HEAD:
+ return Armor[2][armorType];
+ case INVTYPE_LEGS:
+ return Armor[3][armorType];
+ case INVTYPE_FEET:
+ return Armor[4][armorType];
+ case INVTYPE_WAIST:
+ return Armor[5][armorType];
+ case INVTYPE_HANDS:
+ return Armor[6][armorType];
+ case INVTYPE_WRISTS:
+ return Armor[7][armorType];
+ case INVTYPE_CLOAK:
+ return CloakArmor;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+uint32 ScalingStatValuesEntry::GetDPSAndDamageMultiplier(uint32 subClass, bool isCasterWeapon, float* damageMultiplier) const
+{
+ if (!isCasterWeapon)
+ {
+ switch (subClass)
+ {
+ case ITEM_SUBCLASS_WEAPON_AXE:
+ case ITEM_SUBCLASS_WEAPON_MACE:
+ case ITEM_SUBCLASS_WEAPON_SWORD:
+ case ITEM_SUBCLASS_WEAPON_DAGGER:
+ case ITEM_SUBCLASS_WEAPON_THROWN:
+ *damageMultiplier = 0.3f;
+ return dpsMod[0];
+ case ITEM_SUBCLASS_WEAPON_AXE2:
+ case ITEM_SUBCLASS_WEAPON_MACE2:
+ case ITEM_SUBCLASS_WEAPON_POLEARM:
+ case ITEM_SUBCLASS_WEAPON_SWORD2:
+ case ITEM_SUBCLASS_WEAPON_STAFF:
+ case ITEM_SUBCLASS_WEAPON_FISHING_POLE:
+ *damageMultiplier = 0.2f;
+ return dpsMod[1];
+ case ITEM_SUBCLASS_WEAPON_BOW:
+ case ITEM_SUBCLASS_WEAPON_GUN:
+ case ITEM_SUBCLASS_WEAPON_CROSSBOW:
+ *damageMultiplier = 0.3f;
+ return dpsMod[4];
+ case ITEM_SUBCLASS_WEAPON_Obsolete:
+ case ITEM_SUBCLASS_WEAPON_EXOTIC:
+ case ITEM_SUBCLASS_WEAPON_EXOTIC2:
+ case ITEM_SUBCLASS_WEAPON_FIST_WEAPON:
+ case ITEM_SUBCLASS_WEAPON_MISCELLANEOUS:
+ case ITEM_SUBCLASS_WEAPON_SPEAR:
+ case ITEM_SUBCLASS_WEAPON_WAND:
+ break;
+ }
+ }
+ else
+ {
+ if (subClass <= ITEM_SUBCLASS_WEAPON_WAND)
+ {
+ uint32 mask = 1 << subClass;
+ // two-handed weapons
+ if (mask & 0x562)
+ {
+ *damageMultiplier = 0.2f;
+ return dpsMod[3];
+ }
+
+ if (mask & (1 << ITEM_SUBCLASS_WEAPON_WAND))
+ {
+ *damageMultiplier = 0.3f;
+ return dpsMod[5];
+ }
+ }
+ *damageMultiplier = 0.3f;
+ return dpsMod[2];
+ }
+ return 0;
+}
+
/// Returns LFGDungeonEntry for a specific map and difficulty. Will return first found entry if multiple dungeons use the same map (such as Scarlet Monastery)
LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty)
{
@@ -991,3 +1335,8 @@ SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, u
return NULL;
}
+
+std::set<uint32> const& GetPhasesForGroup(uint32 group)
+{
+ return sPhasesByGroup[group];
+}
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index 8b89a86fafe..eeaa45c9042 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -28,7 +28,7 @@
typedef std::list<uint32> SimpleFactionsList;
SimpleFactionsList const* GetFactionTeamList(uint32 faction);
-char* GetPetName(uint32 petfamily, uint32 dbclang);
+char const* GetPetName(uint32 petfamily, uint32 dbclang);
uint32 GetTalentSpellCost(uint32 spellId);
TalentSpellPos const* GetTalentSpellPos(uint32 spellId);
@@ -44,12 +44,19 @@ WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId);
+const std::string* GetRandomCharacterName(uint8 race, uint8 gender);
+
enum ContentLevels
{
- CONTENT_1_60 = 0,
- CONTENT_61_70,
- CONTENT_71_80
+ CONTENT_1_60 = 0,
+ CONTENT_61_70 = 1,
+ CONTENT_71_80 = 2,
+ CONTENT_81_85 = 3,
+ MAX_CONTENT
};
+
+uint32 GetMaxLevelForExpansion(uint32 expansion);
+
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId);
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId);
@@ -62,6 +69,7 @@ MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty);
MapDifficulty const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty);
uint32 const* /*[MAX_TALENT_TABS]*/ GetTalentTabPages(uint8 cls);
+std::vector<uint32> const* GetTalentTreePrimarySpells(uint32 talentTree);
uint32 GetLiquidFlags(uint32 liquidType);
@@ -70,10 +78,13 @@ PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundB
CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender);
+uint32 GetPowerIndexByClass(uint32 powerType, uint32 classId);
LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty);
uint32 GetDefaultMapLight(uint32 mapId);
+std::set<uint32> const& GetPhasesForGroup(uint32 group);
+
typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRaceClassInfoMap;
typedef std::pair<SkillRaceClassInfoMap::iterator, SkillRaceClassInfoMap::iterator> SkillRaceClassInfoBounds;
SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_);
@@ -84,6 +95,7 @@ extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access
extern DBCStorage <AreaGroupEntry> sAreaGroupStore;
extern DBCStorage <AreaPOIEntry> sAreaPOIStore;
extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore;
+extern DBCStorage <ArmorLocationEntry> sArmorLocationStore;
extern DBCStorage <AuctionHouseEntry> sAuctionHouseStore;
extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore;
extern DBCStorage <BannedAddOnsEntry> sBannedAddOnsStore;
@@ -94,6 +106,7 @@ extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore;
extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
extern DBCStorage <ChrClassesEntry> sChrClassesStore;
extern DBCStorage <ChrRacesEntry> sChrRacesStore;
+extern DBCStorage <ChrPowerTypesEntry> sChrPowerTypesStore;
extern DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore;
extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore;
extern DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore;
@@ -123,15 +136,35 @@ extern DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore;
extern DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore;
extern DBCStorage <GtNPCManaCostScalerEntry> sGtNPCManaCostScalerStore;
extern DBCStorage <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStore;
-extern DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore;
//extern DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore; -- not used currently
-extern DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore;
+extern DBCStorage <gtOCTHpPerStaminaEntry> sGtOCTHpPerStaminaStore;
extern DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore;
+extern DBCStorage <GtSpellScalingEntry> sGtSpellScalingStore;
+extern DBCStorage <GtOCTBaseHPByClassEntry> sGtOCTBaseHPByClassStore;
+extern DBCStorage <GtOCTBaseMPByClassEntry> sGtOCTBaseMPByClassStore;
+extern DBCStorage <GuildPerkSpellsEntry> sGuildPerkSpellsStore;
extern DBCStorage <HolidaysEntry> sHolidaysStore;
-extern DBCStorage <ItemEntry> sItemStore;
+extern DBCStorage <ImportPriceArmorEntry> sImportPriceArmorStore;
+extern DBCStorage <ImportPriceQualityEntry> sImportPriceQualityStore;
+extern DBCStorage <ImportPriceShieldEntry> sImportPriceShieldStore;
+extern DBCStorage <ImportPriceWeaponEntry> sImportPriceWeaponStore;
+extern DBCStorage <ItemPriceBaseEntry> sItemPriceBaseStore;
+extern DBCStorage <ItemReforgeEntry> sItemReforgeStore;
+extern DBCStorage <ItemArmorQualityEntry> sItemArmorQualityStore;
+extern DBCStorage <ItemArmorShieldEntry> sItemArmorShieldStore;
+extern DBCStorage <ItemArmorTotalEntry> sItemArmorTotalStore;
+extern DBCStorage <ItemClassEntry> sItemClassStore;
extern DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageAmmoStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageOneHandStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageOneHandCasterStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageRangedStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageThrownStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageTwoHandStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageTwoHandCasterStore;
+extern DBCStorage <ItemDamageEntry> sItemDamageWandStore;
//extern DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore; -- not used currently
-extern DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore;
+extern DBCStorage <ItemDisenchantLootEntry> sItemDisenchantLootStore;
extern DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore;
extern DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore;
extern DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore;
@@ -141,6 +174,12 @@ extern DBCStorage <LiquidTypeEntry> sLiquidTypeStore;
extern DBCStorage <LockEntry> sLockStore;
extern DBCStorage <MailTemplateEntry> sMailTemplateStore;
extern DBCStorage <MapEntry> sMapStore;
+extern DBCStorage <MountCapabilityEntry> sMountCapabilityStore;
+extern DBCStorage <MountTypeEntry> sMountTypeStore;
+extern DBCStorage <NameGenEntry> sNameGenStore;
+extern DBCStorage <NumTalentsAtLevelEntry> sNumTalentsAtLevelStore;
+extern DBCStorage <PhaseEntry> sPhaseStore;
+extern DBCStorage <PhaseGroupEntry> sPhaseGroupStore;
//extern DBCStorage <MapDifficultyEntry> sMapDifficultyStore; -- use GetMapDifficultyData insteed
extern MapDifficultyMap sMapDifficultyMap;
extern DBCStorage <MovieEntry> sMovieStore;
@@ -169,8 +208,24 @@ extern DBCStorage <SpellRadiusEntry> sSpellRadiusStore;
extern DBCStorage <SpellRangeEntry> sSpellRangeStore;
extern DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore;
extern DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore;
+extern DBCStorage <SpellShapeshiftFormEntry> sSpellShapeshiftFormStore;
extern DBCStorage <SpellEntry> sSpellStore;
-extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore;
+extern DBCStorage <SpellAuraOptionsEntry> sSpellAuraOptionsStore;
+extern DBCStorage <SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore;
+extern DBCStorage <SpellCastingRequirementsEntry> sSpellCastingRequirementsStore;
+extern DBCStorage <SpellCategoriesEntry> sSpellCategoriesStore;
+extern DBCStorage <SpellClassOptionsEntry> sSpellClassOptionsStore;
+extern DBCStorage <SpellCooldownsEntry> sSpellCooldownsStore;
+extern DBCStorage <SpellEffectEntry> sSpellEffectStore;
+extern DBCStorage <SpellEquippedItemsEntry> sSpellEquippedItemsStore;
+extern DBCStorage <SpellInterruptsEntry> sSpellInterruptsStore;
+extern DBCStorage <SpellLevelsEntry> sSpellLevelsStore;
+extern DBCStorage <SpellPowerEntry> sSpellPowerStore;
+extern DBCStorage <SpellReagentsEntry> sSpellReagentsStore;
+extern DBCStorage <SpellScalingEntry> sSpellScalingStore;
+extern DBCStorage <SpellTargetRestrictionsEntry> sSpellTargetRestrictionsStore;
+extern DBCStorage <SpellTotemsEntry> sSpellTotemsStore;
+//extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore;
extern DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore;
extern DBCStorage <TalentEntry> sTalentStore;
extern DBCStorage <TalentTabEntry> sTalentTabStore;
@@ -183,8 +238,8 @@ extern TaxiMask sAllianceTaxiNodesMask;
extern TaxiMask sDeathKnightTaxiNodesMask;
extern TaxiPathSetBySource sTaxiPathSetBySource;
extern TaxiPathNodesByPath sTaxiPathNodesByPath;
-extern DBCStorage <TeamContributionPointsEntry> sTeamContributionPointsStore;
extern DBCStorage <TotemCategoryEntry> sTotemCategoryStore;
+extern DBCStorage <UnitPowerBarEntry> sUnitPowerBarStore;
extern DBCStorage <VehicleEntry> sVehicleStore;
extern DBCStorage <VehicleSeatEntry> sVehicleSeatStore;
extern DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 1e1cd6dd9d6..001392aee4c 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -44,35 +44,31 @@ struct AchievementEntry
int32 requiredFaction; // 1 -1=all, 0=horde, 1=alliance
int32 mapID; // 2 -1=none
//uint32 parentAchievement; // 3 its Achievement parent (can`t start while parent uncomplete, use its Criteria if don`t have own, use its progress on begin)
- char *name[16]; // 4-19
- //uint32 name_flags; // 20
- //char *description[16]; // 21-36
- //uint32 desc_flags; // 37
- uint32 categoryId; // 38
- uint32 points; // 39 reward points
- //uint32 OrderInCategory; // 40
- uint32 flags; // 41
- //uint32 icon; // 42 icon (from SpellIcon.dbc)
- //char *titleReward[16]; // 43-58
- //uint32 titleReward_flags; // 59
- uint32 count; // 60 - need this count of completed criterias (own or referenced achievement criterias)
- uint32 refAchievement; // 61 - referenced achievement (counting of all completed criterias)
+ char* name; // 4
+ //char* description; // 5
+ uint32 categoryId; // 6
+ uint32 points; // 7 reward points
+ //uint32 OrderInCategory; // 8
+ uint32 flags; // 9
+ //uint32 icon; // 10 icon (from SpellIcon.dbc)
+ //char* reward; // 11
+ uint32 count; // 12 - need this count of completed criterias (own or referenced achievement criterias)
+ uint32 refAchievement; // 13 - referenced achievement (counting of all completed criterias)
};
struct AchievementCategoryEntry
{
uint32 ID; // 0
uint32 parentCategory; // 1 -1 for main category
- //char *name[16]; // 2-17
- //uint32 name_flags; // 18
- //uint32 sortOrder; // 19
+ //char* name; // 2
+ //uint32 sortOrder; // 3
};
struct AchievementCriteriaEntry
{
uint32 ID; // 0
- uint32 referredAchievement; // 1
- uint32 requiredType; // 2
+ uint32 achievement; // 1
+ uint32 type; // 2
union
{
// ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0
@@ -80,28 +76,29 @@ struct AchievementCriteriaEntry
struct
{
uint32 creatureID; // 3
- uint32 creatureCount; // 4
+ uint64 creatureCount; // 4
} kill_creature;
// ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1
struct
{
uint32 bgMapID; // 3
- uint32 winCount; // 4
+ uint64 winCount; // 4
} win_bg;
// ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5
+ // ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL = 125
struct
{
uint32 unused; // 3
- uint32 level; // 4
+ uint64 level; // 4
} reach_level;
// ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7
struct
{
uint32 skillID; // 3
- uint32 skillLevel; // 4
+ uint64 skillLevel; // 4
} reach_skill_level;
// ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8
@@ -114,28 +111,35 @@ struct AchievementCriteriaEntry
struct
{
uint32 unused; // 3
- uint32 totalQuestCount; // 4
+ uint64 totalQuestCount; // 4
} complete_quest_count;
// ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10
struct
{
uint32 unused; // 3
- uint32 numberOfDays; // 4
+ uint64 numberOfDays; // 4
} complete_daily_quest_daily;
// ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11
struct
{
uint32 zoneID; // 3
- uint32 questCount; // 4
+ uint64 questCount; // 4
} complete_quests_in_zone;
+ // ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12
+ struct
+ {
+ uint32 currency;
+ uint64 count;
+ } currencyGain;
+
// ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14
struct
{
uint32 unused; // 3
- uint32 questCount; // 4
+ uint64 questCount; // 4
} complete_daily_quest;
// ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15
@@ -172,7 +176,7 @@ struct AchievementCriteriaEntry
struct
{
uint32 unused; // 3
- uint32 fallHeight; // 4
+ uint64 fallHeight; // 4
} fall_without_dying;
// ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26
@@ -185,7 +189,7 @@ struct AchievementCriteriaEntry
struct
{
uint32 questID; // 3
- uint32 questCount; // 4
+ uint64 questCount; // 4
} complete_quest;
// ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28
@@ -193,7 +197,7 @@ struct AchievementCriteriaEntry
struct
{
uint32 spellID; // 3
- uint32 spellCount; // 4
+ uint64 spellCount; // 4
} be_spell_target;
// ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL = 29
@@ -201,28 +205,28 @@ struct AchievementCriteriaEntry
struct
{
uint32 spellID; // 3
- uint32 castCount; // 4
+ uint64 castCount; // 4
} cast_spell;
// ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE
struct
{
uint32 objectiveId; // 3
- uint32 completeCount; // 4
+ uint64 completeCount; // 4
} bg_objective;
// ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31
struct
{
uint32 areaID; // 3 Reference to AreaTable.dbc
- uint32 killCount; // 4
+ uint64 killCount; // 4
} honorable_kill_at_area;
// ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32
struct
{
uint32 mapID; // 3 Reference to Map.dbc
- uint32 count; // 4 Number of times that the arena must be won.
+ uint64 count; // 4 Number of times that the arena must be won.
} win_arena;
// ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33
@@ -241,14 +245,14 @@ struct AchievementCriteriaEntry
struct
{
uint32 itemID; // 3
- uint32 itemCount; // 4
+ uint64 itemCount; // 4
} own_item;
// ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37
struct
{
uint32 unused; // 3
- uint32 count; // 4
+ uint64 count; // 4
} win_rated_arena;
// ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38
@@ -261,28 +265,35 @@ struct AchievementCriteriaEntry
struct
{
uint32 teamtype; // 3 {2, 3, 5}
- uint32 PersonalRating; // 4
+ uint64 teamrating; // 4
+ } reach_team_rating;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39
+ struct
+ {
+ uint32 teamtype; // 3 {2, 3, 5}
+ uint64 PersonalRating; // 4
} highest_personal_rating;
// ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40
struct
{
uint32 skillID; // 3
- uint32 skillLevel; // 4 apprentice=1, journeyman=2, expert=3, artisan=4, master=5, grand master=6
+ uint64 skillLevel; // 4 apprentice=1, journeyman=2, expert=3, artisan=4, master=5, grand master=6
} learn_skill_level;
// ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41
struct
{
uint32 itemID; // 3
- uint32 itemCount; // 4
+ uint64 itemCount; // 4
} use_item;
// ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42
struct
{
uint32 itemID; // 3
- uint32 itemCount; // 4
+ uint64 itemCount; // 4
} loot_item;
// ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43
@@ -303,28 +314,28 @@ struct AchievementCriteriaEntry
struct
{
uint32 unused; // 3
- uint32 numberOfSlots; // 4
+ uint64 numberOfSlots; // 4
} buy_bank_slot;
// ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION = 46
struct
{
uint32 factionID; // 3
- uint32 reputationAmount; // 4 Total reputation amount, so 42000 = exalted
+ uint64 reputationAmount; // 4 Total reputation amount, so 42000 = exalted
} gain_reputation;
// ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION= 47
struct
{
uint32 unused; // 3
- uint32 numberOfExaltedFactions; // 4
+ uint64 numberOfExaltedFactions; // 4
} gain_exalted_reputation;
// ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48
struct
{
uint32 unused; // 3
- uint32 numberOfVisits; // 4
+ uint64 numberOfVisits; // 4
} visit_barber;
// ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49
@@ -332,34 +343,34 @@ struct AchievementCriteriaEntry
struct
{
uint32 itemSlot; // 3
- uint32 count; // 4
+ uint64 count; // 4
} equip_epic_item;
// ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50
struct
{
uint32 rollValue; // 3
- uint32 count; // 4
+ uint64 count; // 4
} roll_need_on_loot;
// ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51
struct
{
uint32 rollValue; // 3
- uint32 count; // 4
+ uint64 count; // 4
} roll_greed_on_loot;
// ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52
struct
{
uint32 classID; // 3
- uint32 count; // 4
+ uint64 count; // 4
} hk_class;
// ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53
struct
{
uint32 raceID; // 3
- uint32 count; // 4
+ uint64 count; // 4
} hk_race;
// ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54
@@ -367,49 +378,50 @@ struct AchievementCriteriaEntry
struct
{
uint32 emoteID; // 3 enum TextEmotes
- uint32 count; // 4 count of emotes, always required special target or requirements
+ uint64 count; // 4 count of emotes, always required special target or requirements
} do_emote;
// ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13
// ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55
+ // ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56
struct
{
uint32 unused; // 3
- uint32 count; // 4
+ uint64 count; // 4
} healing_done;
// ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56
struct
{
uint32 unused;
- uint32 killCount;
+ uint64 killCount;
} get_killing_blow;
// ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57
struct
{
uint32 itemID; // 3
- uint32 count; // 4
+ uint64 count; // 4
} equip_item;
// ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD= 62
struct
{
uint32 unused; // 3
- uint32 goldInCopper; // 4
+ uint64 goldInCopper; // 4
} quest_reward_money;
// ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67
struct
{
uint32 unused; // 3
- uint32 goldInCopper; // 4
+ uint64 goldInCopper; // 4
} loot_money;
// ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68
struct
{
uint32 goEntry; // 3
- uint32 useCount; // 4
+ uint64 useCount; // 4
} use_gameobject;
// ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL = 70
@@ -417,28 +429,28 @@ struct AchievementCriteriaEntry
struct
{
uint32 unused; // 3
- uint32 killCount; // 4
+ uint64 killCount; // 4
} special_pvp_kill;
// ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72
struct
{
uint32 goEntry; // 3
- uint32 lootCount; // 4
+ uint64 lootCount; // 4
} fish_in_gameobject;
// ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75
struct
{
uint32 skillLine; // 3
- uint32 spellCount; // 4
+ uint64 spellCount; // 4
} learn_skillline_spell;
// ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76
struct
{
uint32 unused; // 3
- uint32 duelCount; // 4
+ uint64 duelCount; // 4
} win_duel;
// ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96
@@ -469,33 +481,33 @@ struct AchievementCriteriaEntry
struct
{
uint32 lootType; // 3 3=fishing, 2=pickpocket, 4=disentchant
- uint32 lootTypeCount; // 4
+ uint64 lootTypeCount; // 4
} loot_type;
// ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE = 112
struct
{
uint32 skillLine; // 3
- uint32 spellCount; // 4
+ uint64 spellCount; // 4
} learn_skill_line;
// ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113
struct
{
uint32 unused; // 3
- uint32 killCount; // 4
+ uint64 killCount; // 4
} honorable_kill;
struct
{
uint32 unused;
- uint32 dungeonsComplete;
+ uint64 dungeonsComplete;
} use_lfg;
struct
{
uint32 field3; // 3 main requirement
- uint32 count; // 4 main requirement count
+ uint64 count; // 4 main requirement count
} raw;
};
@@ -505,15 +517,19 @@ struct AchievementCriteriaEntry
uint32 additionalRequirement_value;
} additionalRequirements[MAX_CRITERIA_REQUIREMENTS];
- //char* name[16]; // 9-24
- //uint32 name_flags; // 25
- uint32 flags; // 26
- uint32 timedType; // 27
- uint32 timerStartEvent; // 28 Alway appears with timed events
- // for timed spells it is spell id for
- // timed kills it is creature id
- uint32 timeLimit; // 29 time limit in seconds
- //uint32 showOrder; // 30 show order
+ char* name; // 9 m_description_lang
+ uint32 completionFlag; // 10 m_flags
+ uint32 timedCriteriaStartType; // 11 m_timer_start_event Only appears with timed achievements, seems to be the type of starting a timed Achievement, only type 1 and some of type 6 need manual starting
+ // 1: ByEventId(?) (serverside IDs), 2: ByQuestId, 5: ByCastSpellId(?)
+ // 6: BySpellIdTarget(some of these are unknown spells, some not, some maybe spells)
+ // 7: ByKillNpcId, 9: ByUseItemId
+ uint32 timedCriteriaMiscId; // 12 m_timer_asset_id Alway appears with timed events, used internally to start the achievement, store
+ uint32 timeLimit; // 13 m_timer_time time limit in seconds
+ uint32 showOrder; // 14 m_ui_order also used in achievement shift-links as index in state bitmask
+ //uint32 unk1; // 15 only one value, still unknown
+ //uint32 unk2; // 16 all zeros
+ uint32 additionalConditionType[MAX_ADDITIONAL_CRITERIA_CONDITIONS]; // 17-19
+ uint32 additionalConditionValue[MAX_ADDITIONAL_CRITERIA_CONDITIONS]; // 20-22
};
struct AreaTableEntry
@@ -522,13 +538,25 @@ struct AreaTableEntry
uint32 mapid; // 1
uint32 zone; // 2 if 0 then it's zone, else it's zone id of this area
uint32 exploreFlag; // 3, main index
- uint32 flags; // 4, unknown value but 312 for all cities
- // 5-9 unused
+ uint32 flags; // 4,
+ //uint32 unk5; // 5,
+ //uint32 unk6; // 6,
+ //uint32 unk7; // 7,
+ //uint32 unk8; // 8,
+ //uint32 unk9; // 9,
int32 area_level; // 10
- char* area_name[16]; // 11-26
- // 27, string flags, unused
- uint32 team; // 28
- uint32 LiquidTypeOverride[4]; // 29-32 liquid override by type
+ char* area_name; // 11
+ uint32 team; // 12
+ uint32 LiquidTypeOverride[4]; // 13-16 liquid override by type
+ float MaxDepth; // 17,
+ float AmbientMultiplier; // 18 client only?
+ uint32 LightId; // 19
+ //uint32 unk20; // 20 4.0.0 - Mounting related
+ //uint32 unk21; // 21 4.0.0
+ //uint32 unk22; // 22 4.0.0
+ //uint32 unk23; // 23 4.0.0
+ //uint32 unk24; // 24 - worldStateId
+ //uint32 unk25 // 25
// helpers
bool IsSanctuary() const
@@ -554,16 +582,14 @@ struct AreaPOIEntry
uint32 icon[11]; //1-11
float x; //12
float y; //13
- float z; //14
- uint32 mapId; //15
- //uint32 val1; //16
- uint32 zoneId; //17
- //char* name[16]; //18-33
- //uint32 name_flag; //34
- //char* name2[16]; //35-50
- //uint32 name_flag2; //51
- uint32 worldState; //52
- //uint32 val2; //53
+ uint32 mapId; //14
+ //uint32 val1; //15
+ uint32 zoneId; //16
+ //char* name; //17 - name
+ //char* name2; //18 - name2
+ uint32 worldState; //19
+ //uint32 val2; //20
+ //uint32 unk; //21
};
struct AreaTriggerEntry
@@ -573,11 +599,20 @@ struct AreaTriggerEntry
float x; // 2 m_x
float y; // 3 m_y
float z; // 4 m_z
- float radius; // 5 m_radius
- float box_x; // 6 m_box_length
- float box_y; // 7 m_box_width
- float box_z; // 8 m_box_heigh
- float box_orientation; // 9 m_box_yaw
+ //uint32 // 5
+ //uint32 // 6
+ //uint32 // 7
+ float radius; // 8 m_radius
+ float box_x; // 9 m_box_length
+ float box_y; // 10 m_box_width
+ float box_z; // 11 m_box_heigh
+ float box_orientation; // 12 m_box_yaw
+};
+
+struct ArmorLocationEntry
+{
+ uint32 InventoryType; // 0
+ float Value[5]; // 1-5 multiplier for armor types (cloth...plate, no armor?)
};
struct AuctionHouseEntry
@@ -586,8 +621,7 @@ struct AuctionHouseEntry
uint32 faction; // 1 id of faction.dbc for player factions associated with city
uint32 depositPercent; // 2 1/3 from real
uint32 cutPercent; // 3
- //char* name[16]; // 4-19
- // 20 string flag, unused
+ //char* name; // 4
};
struct BankBagSlotPricesEntry
@@ -609,14 +643,12 @@ struct BarberShopStyleEntry
{
uint32 Id; // 0
uint32 type; // 1 value 0 -> hair, value 2 -> facialhair
- //char* name[16]; // 2-17 name of hair style
- //uint32 name_flags; // 18
- //uint32 unk_name[16]; // 19-34, all empty
- //uint32 unk_flags; // 35
- //float CostMultiplier; // 36 values 1 and 0.75
- uint32 race; // 37 race
- uint32 gender; // 38 0 -> male, 1 -> female
- uint32 hair_id; // 39 real ID to hair/facial hair
+ //char* name; // 2 m_DisplayName_lang
+ //uint32 unk_name; // 3 m_Description_lang
+ //float CostMultiplier; // 4 m_Cost_Modifier
+ uint32 race; // 5 m_race
+ uint32 gender; // 6 m_sex
+ uint32 hair_id; // 7 m_data (real ID to hair/facial hair)
};
struct BattlemasterListEntry
@@ -625,12 +657,15 @@ struct BattlemasterListEntry
int32 mapid[8]; // 1-8 mapid
uint32 type; // 9 map type (3 - BG, 4 - arena)
//uint32 canJoinAsGroup; // 10 (0 or 1)
- char* name[16]; // 11-26
- //uint32 nameFlags // 27 string flag, unused
- uint32 maxGroupSize; // 28 maxGroupSize, used for checking if queue as group
- uint32 HolidayWorldStateId; // 29 new 3.1
- //uint32 MinLevel; // 30
- //uint32 SomeLevel; // 31, may be max level
+ char* name; // 11
+ uint32 maxGroupSize; // 12 maxGroupSize, used for checking if queue as group
+ uint32 HolidayWorldStateId; // 13 new 3.1
+ uint32 minLevel; // 14, min level (sync with PvPDifficulty.dbc content)
+ uint32 maxLevel; // 15, max level (sync with PvPDifficulty.dbc content)
+ //uint32 maxGroupSizeRated; // 16 4.0.1
+ //uint32 unk; // 17 - 4.0.6.13596
+ //uint32 maxPlayers; // 18 4.0.1
+ //uint32 unk1; // 19 4.0.3, value 2 for Rated Battlegrounds
};
#define MAX_OUTFIT_ITEMS 24
@@ -645,46 +680,45 @@ struct CharStartOutfitEntry
int32 ItemId[MAX_OUTFIT_ITEMS]; // 5-28
//int32 ItemDisplayId[MAX_OUTFIT_ITEMS]; // 29-52 not required at server side
//int32 ItemInventorySlot[MAX_OUTFIT_ITEMS]; // 53-76 not required at server side
+ uint32 PetDisplayId; // 77 Pet Model ID for starting pet
+ uint32 PetFamilyEntry; // 78 Pet Family Entry for starting pet
};
struct CharTitlesEntry
{
uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId()
//uint32 unk1; // 1 flags?
- char* nameMale[16]; // 2-17
- // 18 string flag, unused
- char* nameFemale[16]; // 19-34
- // 35 string flag, unused
- uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES
+ char* nameMale; // 2 m_name_lang
+ char* nameFemale; // 3 m_name1_lang
+ uint32 bit_index; // 4 m_mask_ID used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES
+ //uint32 // 5
};
struct ChatChannelsEntry
{
uint32 ChannelID; // 0
uint32 flags; // 1
- char* pattern[16]; // 3-18
- // 19 string flags, unused
- //char* name[16]; // 20-35 unused
- // 36 string flag, unused
+ //uint32 // 2 m_factionGroup
+ char* pattern; // 3 m_name_lang
+ //char* name; // 4 m_shortcut_lang
};
struct ChrClassesEntry
{
uint32 ClassID; // 0
- // 1, unused
- uint32 powerType; // 2
- // 3-4, unused
- char* name[16]; // 5-20 unused
- // 21 string flag, unused
- //char* nameFemale[16]; // 21-36 unused, if different from base (male) case
- // 37 string flag, unused
- //char* nameNeutralGender[16]; // 38-53 unused, if different from base (male) case
- // 54 string flag, unused
- // 55, unused
- uint32 spellfamily; // 56
- // 57, unused
- uint32 CinematicSequence; // 58 id from CinematicSequences.dbc
- uint32 expansion; // 59 (0 - original race, 1 - tbc addon, ...)
+ uint32 powerType; // 1 m_DisplayPower
+ // 2 m_petNameToken
+ char* name; // 3 m_name_lang
+ //char* nameFemale; // 4 m_name_female_lang
+ //char* nameNeutralGender; // 5 m_name_male_lang
+ //char* capitalizedName // 6, m_filename
+ uint32 spellfamily; // 7 m_spellClassSet
+ //uint32 flags2; // 8 m_flags (0x08 HasRelicSlot)
+ uint32 CinematicSequence; // 9 m_cinematicSequenceID
+ uint32 expansion; // 10 m_required_expansion
+ uint32 APPerStrenth; // 11 Attack Power bonus per point of strength
+ uint32 APPerAgility; // 12 Attack Power bonus per point of agility
+ uint32 RAPPerAgility; // 13 Ranged Attack Power bonus per point of agility
};
struct ChrRacesEntry
@@ -699,15 +733,23 @@ struct ChrRacesEntry
uint32 TeamID; // 7 (7-Alliance 1-Horde)
// 8-11 unused
uint32 CinematicSequence; // 12 id from CinematicSequences.dbc
- //uint32 unk_322; // 13 faction (0 alliance, 1 horde, 2 not available?)
- char* name[16]; // 14-29 used for DBC language detection/selection
- // 30 string flags, unused
- //char* nameFemale[16]; // 31-46, if different from base (male) case
- // 47 string flags, unused
- //char* nameNeutralGender[16]; // 48-63, if different from base (male) case
- // 64 string flags, unused
- // 65-67 unused
- uint32 expansion; // 68 (0 - original race, 1 - tbc addon, ...)
+ //uint32 unk_322; // 13 m_alliance (0 alliance, 1 horde, 2 not available?)
+ char* name; // 14 m_name_lang used for DBC language detection/selection
+ //char* nameFemale; // 15 m_name_female_lang
+ //char* nameNeutralGender; // 16 m_name_male_lang
+ // 17-18 m_facialHairCustomization[2]
+ // 19 m_hairCustomization
+ uint32 expansion; // 20 m_required_expansion
+ //uint32 // 21 (23 for worgens)
+ //uint32 // 22 4.0.0
+ //uint32 // 23 4.0.0
+};
+
+struct ChrPowerTypesEntry
+{
+ uint32 entry; // 0
+ uint32 classId; // 1
+ uint32 power; // 2
};
/* not used
@@ -747,6 +789,7 @@ struct CreatureDisplayInfoEntry
// 13 m_particleColorID
// 14 m_creatureGeosetData
// 15 m_objectEffectPackageID
+ // 16
};
struct CreatureDisplayInfoExtraEntry
@@ -785,18 +828,17 @@ struct CreatureFamilyEntry
uint32 petFoodMask; // 7 m_petFoodMask
int32 petTalentType; // 8 m_petTalentType
// 9 m_categoryEnumID
- char* Name[16]; // 10-25 m_name_lang
- // 26 string flags
- // 27 m_iconFile
+ char* Name; // 10 m_name_lang
+ // 11 m_iconFile
};
struct CreatureModelDataEntry
{
uint32 Id;
uint32 Flags;
- //char* ModelPath[16]
+ //char* ModelPath
//uint32 Unk1;
- float Scale; // Used in calculation of unit collision data
+ //float Scale; // Used in calculation of unit collision data
//int32 Unk2
//int32 Unk3
//uint32 Unk4
@@ -824,9 +866,8 @@ struct CreatureSpellDataEntry
struct CreatureTypeEntry
{
uint32 ID; // 0 m_ID
- //char* Name[16]; // 1-16 name
- // 17 string flags
- //uint32 no_expirience; // 18 no exp? critters, non-combat pets, gas cloud.
+ //char* Name; // 1 m_name_lang
+ //uint32 no_expirience; // 2 m_flags no exp? critters, non-combat pets, gas cloud.
};
/* not used
@@ -841,43 +882,55 @@ struct CurrencyCategoryEntry
struct CurrencyTypesEntry
{
- //uint32 ID; // 0 not used
- uint32 ItemId; // 1 used as real index
- //uint32 Category; // 2 may be category
- uint32 BitIndex; // 3 bit index in PLAYER_FIELD_KNOWN_CURRENCIES (1 << (index-1))
+ uint32 ID; // 0 not used
+ uint32 Category; // 1 may be category
+ //char* name; // 2
+ //char* iconName; // 3
+ //uint32 unk4; // 4 all 0
+ uint32 HasSubstitution; // 5 archaeology-related (?)
+ uint32 SubstitutionId; // 6
+ uint32 TotalCap; // 7
+ uint32 WeekCap; // 8
+ uint32 Flags; // 9
+ //char* description; // 10
};
struct DestructibleModelDataEntry
{
uint32 Id;
+ uint32 DamagedDisplayId;
//uint32 DamagedUnk1;
//uint32 DamagedUnk2;
- uint32 DamagedDisplayId;
//uint32 DamagedUnk3;
+ uint32 DestroyedDisplayId;
//uint32 DestroyedUnk1;
//uint32 DestroyedUnk2;
- uint32 DestroyedDisplayId;
//uint32 DestroyedUnk3;
+ //uint32 DestroyedUnk4;
+ uint32 RebuildingDisplayId;
//uint32 RebuildingUnk1;
//uint32 RebuildingUnk2;
- uint32 RebuildingDisplayId;
//uint32 RebuildingUnk3;
+ //uint32 RebuildingUnk4;
+ uint32 SmokeDisplayId;
//uint32 SmokeUnk1;
//uint32 SmokeUnk2;
- uint32 SmokeDisplayId;
//uint32 SmokeUnk3;
- //uint32 Unk4;
- //uint32 Unk5;
+ //uint32 SmokeUnk4;
+ //uint32 UnkDisplayid;
+ //uint32 Unk6;
+ //uint32 Unk7;
+ //uint32 Unk8;
};
struct DungeonEncounterEntry
{
uint32 id; // 0 unique id
uint32 mapId; // 1 map id
- uint32 difficulty; // 2 instance mode
+ int32 difficulty; // 2 instance mode
//uint32 unk0; // 3
uint32 encounterIndex; // 4 encounter index for creating completed mask
- char* encounterName[16]; // 5-20 encounter name
+ char* encounterName; // 5 encounter name
//uint32 nameFlags; // 21
//uint32 unk1; // 22
};
@@ -897,12 +950,13 @@ struct DurabilityQualityEntry
struct EmotesEntry
{
uint32 Id; // 0
- //char* Name; // 1, internal name
- //uint32 AnimationId; // 2, ref to animationData
+ //char* Name; // 1, internal name
+ //uint32 AnimationId; // 2, ref to animationData
uint32 Flags; // 3, bitmask, may be unit_flags
uint32 EmoteType; // 4, Can be 0, 1 or 2 (determine how emote are shown)
uint32 UnitStandState; // 5, uncomfirmed, may be enum UnitStandStateType
- //uint32 SoundId; // 6, ref to soundEntries
+ //uint32 SoundId; // 6, ref to soundEntries
+ //uint32 unk7 // 7
};
struct EmotesTextEntry
@@ -924,10 +978,9 @@ struct FactionEntry
float spilloverRateOut; // 20 Faction outputs rep * spilloverRateOut as spillover reputation
uint32 spilloverMaxRankIn; // 21 The highest rank the faction will profit from incoming spillover
//uint32 spilloverRank_unk; // 22 It does not seem to be the max standing at which a faction outputs spillover ...so no idea
- char* name[16]; // 23-38 m_name_lang
- // 39 string flags
- //char* description[16]; // 40-55 m_description_lang
- // 56 string flags
+ char* name; // 23 m_name_lang
+ //char* description; // 24 m_description_lang
+ uint32 GroupExpansion; // 25 m_factionGroupExpansion
// helpers
bool CanHaveReputation() const
@@ -953,6 +1006,8 @@ struct FactionTemplateEntry
// helpers
bool IsFriendlyTo(FactionTemplateEntry const& entry) const
{
+ if (ID == entry.ID)
+ return true;
if (entry.faction)
{
for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
@@ -966,6 +1021,8 @@ struct FactionTemplateEntry
}
bool IsHostileTo(FactionTemplateEntry const& entry) const
{
+ if (ID == entry.ID)
+ return false;
if (entry.faction)
{
for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
@@ -991,22 +1048,25 @@ struct FactionTemplateEntry
struct GameObjectDisplayInfoEntry
{
uint32 Displayid; // 0 m_ID
- char* filename; // 1
- //uint32 unk1[10]; //2-11
+ char* filename; // 1
+ //uint32 unk1[10]; //2-11
float minX;
float minY;
float minZ;
float maxX;
float maxY;
float maxZ;
- //uint32 transport; //18
+ //uint32 transport; //18
};
struct GemPropertiesEntry
{
- uint32 ID;
- uint32 spellitemenchantement;
- uint32 color;
+ uint32 ID; // 0 m_id
+ uint32 spellitemenchantement; // 1 m_enchant_id
+ // 2 m_maxcount_inv
+ // 3 m_maxcount_item
+ uint32 color; // 4 m_type
+ uint32 minJewelCraftingSkill; // 5 m_minJewelCraftingSkill
};
struct GlyphPropertiesEntry
@@ -1014,7 +1074,7 @@ struct GlyphPropertiesEntry
uint32 Id;
uint32 SpellId;
uint32 TypeFlags;
- uint32 Unk1; // GlyphIconId (SpellIcon.dbc)
+ uint32 IconId; // GlyphIconId (SpellIcon.dbc)
};
struct GlyphSlotEntry
@@ -1031,21 +1091,25 @@ struct GlyphSlotEntry
struct GtBarberShopCostBaseEntry
{
+ //uint32 level;
float cost;
};
struct GtCombatRatingsEntry
{
+ //uint32 level;
float ratio;
};
struct GtChanceToMeleeCritBaseEntry
{
+ //uint32 level;
float base;
};
struct GtChanceToMeleeCritEntry
{
+ //uint32 level;
float ratio;
};
@@ -1074,10 +1138,15 @@ struct GtOCTRegenHPEntry
float ratio;
};
-//struct GtOCTRegenMPEntry
-//{
-// float ratio;
-//};
+struct GtOCTRegenMPEntry
+{
+ float ratio;
+};
+
+struct gtOCTHpPerStaminaEntry
+{
+ float ratio;
+};
struct GtRegenHPPerSptEntry
{
@@ -1089,12 +1158,33 @@ struct GtRegenMPPerSptEntry
float ratio;
};
+struct GtSpellScalingEntry
+{
+ float value;
+};
+
+struct GtOCTBaseHPByClassEntry
+{
+ float ratio;
+};
+
+struct GtOCTBaseMPByClassEntry
+{
+ float ratio;
+};
+
+struct GuildPerkSpellsEntry
+{
+ //uint32 Id;
+ uint32 Level;
+ uint32 SpellId;
+};
+
/* no used
struct HolidayDescriptionsEntry
{
uint32 ID; // 0, m_holidayDescriptionID
- //char* name[16] // 1-16 m_name_lang
- // 17 name flags
+ //char* name // 1 m_name_lang
};
*/
@@ -1102,8 +1192,7 @@ struct HolidayDescriptionsEntry
struct HolidayNamesEntry
{
uint32 ID; // 0, m_holidayNameID
- //char* name[16] // 1-16 m_name_lang
- // 17 name flags
+ //char* name // 1 m_name_lang
};
*/
@@ -1127,23 +1216,105 @@ struct HolidaysEntry
//uint32 flags; // 54 m_flags (0 = Darkmoon Faire, Fishing Contest and Wotlk Launch, rest is 1)
};
-struct ItemEntry
+// ImportPriceArmor.dbc
+struct ImportPriceArmorEntry
{
- uint32 ID; // 0
- uint32 Class; // 1
- uint32 SubClass; // 2 some items have strange subclasses
- int32 SoundOverrideSubclass; // 3
- int32 Material; // 4
- uint32 DisplayId; // 5
- uint32 InventoryType; // 6
- uint32 Sheath; // 7
+ uint32 InventoryType; // 1 Id/InventoryType
+ float ClothFactor; // 2 Price factor cloth
+ float LeatherFactor; // 3 Price factor leather
+ float MailFactor; // 4 Price factor mail
+ float PlateFactor; // 5 Price factor plate
+};
+
+// ImportPriceQuality.dbc
+struct ImportPriceQualityEntry
+{
+ uint32 QualityId; // 1 Quality Id (+1?)
+ float Factor; // 2 Price factor
+};
+
+// ImportPriceShield.dbc
+struct ImportPriceShieldEntry
+{
+ uint32 Id; // 1 Unk id (only 1 and 2)
+ float Factor; // 2 Price factor
+};
+
+// ImportPriceWeapon.dbc
+struct ImportPriceWeaponEntry
+{
+ uint32 Id; // 1 Unk id (mainhand - 0, offhand - 1, weapon - 2, 2hweapon - 3, ranged/rangedright/relic - 4)
+ float Factor; // 2 Price factor
+};
+
+// ItemPriceBase.dbc
+struct ItemPriceBaseEntry
+{
+ uint32 ItemLevel; // 2 Item level (1 - 1000)
+ float ArmorFactor; // 3 Price factor for armor
+ float WeaponFactor; // 4 Price factor for weapons
+};
+
+struct ItemReforgeEntry
+{
+ uint32 Id;
+ uint32 SourceStat;
+ float SourceMultiplier;
+ uint32 FinalStat;
+ float FinalMultiplier;
+};
+
+// common struct for:
+// ItemDamageAmmo.dbc
+// ItemDamageOneHand.dbc
+// ItemDamageOneHandCaster.dbc
+// ItemDamageRanged.dbc
+// ItemDamageThrown.dbc
+// ItemDamageTwoHand.dbc
+// ItemDamageTwoHandCaster.dbc
+// ItemDamageWand.dbc
+struct ItemDamageEntry
+{
+ uint32 Id; // 0 item level
+ float DPS[7]; // 1-7 multiplier for item quality
+ uint32 Id2; // 8 item level
+};
+
+struct ItemArmorQualityEntry
+{
+ uint32 Id; // 0 item level
+ float Value[7]; // 1-7 multiplier for item quality
+ uint32 Id2; // 8 item level
+};
+
+struct ItemArmorShieldEntry
+{
+ uint32 Id; // 0 item level
+ uint32 Id2; // 1 item level
+ float Value[7]; // 2-8 multiplier for item quality
+};
+
+struct ItemArmorTotalEntry
+{
+ uint32 Id; // 0 item level
+ uint32 Id2; // 1 item level
+ float Value[4]; // 2-5 multiplier for armor types (cloth...plate)
+};
+
+// ItemClass.dbc
+struct ItemClassEntry
+{
+ uint32 Class; // 1 item class id
+ //uint32 Unk; // 2 unk
+ //uint32 IsWeapon; // 3 1 for weapon, 0 for everything else
+ float PriceFactor; // 4 used to calculate certain prices
+ //char* Name; // class name
};
struct ItemBagFamilyEntry
{
uint32 ID; // 0
- //char* name[16] // 1-16 m_name_lang
- // // 17 name flags
+ //char* name; // 1 m_name_lang
};
struct ItemDisplayInfoEntry
@@ -1162,34 +1333,23 @@ struct ItemDisplayInfoEntry
// 11 m_particleColorID
};
-//struct ItemCondExtCostsEntry
-//{
-// uint32 ID;
-// uint32 condExtendedCost; // ItemTemplate::CondExtendedCost
-// uint32 itemextendedcostentry; // ItemTemplate::ExtendedCost
-// uint32 arenaseason; // arena season number(1-4)
-//};
-
-#define MAX_ITEM_EXTENDED_COST_REQUIREMENTS 5
-
-struct ItemExtendedCostEntry
+struct ItemDisenchantLootEntry
{
- uint32 ID; // 0 extended-cost entry id
- uint32 reqhonorpoints; // 1 required honor points
- uint32 reqarenapoints; // 2 required arena points
- uint32 reqarenaslot; // 3 arena slot restrctions (min slot value)
- uint32 reqitem[MAX_ITEM_EXTENDED_COST_REQUIREMENTS]; // 4-8 required item id
- uint32 reqitemcount[MAX_ITEM_EXTENDED_COST_REQUIREMENTS]; // 9-14 required count of 1st item
- uint32 reqpersonalarenarating; // 15 required personal arena rating};
+ uint32 Id;
+ uint32 ItemClass;
+ int32 ItemSubClass;
+ uint32 ItemQuality;
+ uint32 MinItemLevel;
+ uint32 MaxItemLevel;
+ uint32 RequiredDisenchantSkill;
};
struct ItemLimitCategoryEntry
{
uint32 ID; // 0 Id
- //char* name[16] // 1-16 m_name_lang
- // 17 name flags
- uint32 maxCount; // 18, max allowed equipped as item or in gem slot
- uint32 mode; // 19, 0 = have, 1 = equip (enum ItemLimitCategoryMode)
+ //char* name; // 1 m_name_lang
+ uint32 maxCount; // 2, m_quantity max allowed equipped as item or in gem slot
+ uint32 mode; // 3, m_flags 0 = have, 1 = equip (enum ItemLimitCategoryMode)
};
#define MAX_ITEM_ENCHANTMENT_EFFECTS 3
@@ -1197,23 +1357,19 @@ struct ItemLimitCategoryEntry
struct ItemRandomPropertiesEntry
{
uint32 ID; // 0 m_ID
- //char* internalName // 1 m_Name
+ //char* internalName // 1 m_Name
uint32 enchant_id[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 2-4 m_Enchantment
// 5-6 unused
- char* nameSuffix[16]; // 7-22 m_name_lang
- // 23 name flags
+ char* nameSuffix; // 7 m_name_lang
};
struct ItemRandomSuffixEntry
{
uint32 ID; // 0 m_ID
- char* nameSuffix[16]; // 1-16 m_name_lang
- // 17, name flags
- // 18 m_internalName
- uint32 enchant_id[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 19-21 m_enchantment
- //uint32 unk1[2] // 22-23 unknown
- uint32 prefix[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 24-26 m_allocationPct
- //uint32 unk2[2] // 27-28 unknown
+ char* nameSuffix; // 1 m_name_lang
+ // 2 m_internalName
+ uint32 enchant_id[5]; // 3-7 m_enchantment
+ uint32 prefix[5]; // 8-12 m_allocationPct
};
#define MAX_ITEM_SET_ITEMS 10
@@ -1222,35 +1378,34 @@ struct ItemRandomSuffixEntry
struct ItemSetEntry
{
//uint32 id // 0 m_ID
- char* name[16]; // 1-16 m_name_lang
- // 17 string flags, unused
- uint32 itemId[MAX_ITEM_SET_ITEMS]; // 18-27 m_itemID
- //uint32 unknown[7]; // 28-34 unk, all 0
- uint32 spells[MAX_ITEM_SET_SPELLS]; // 35-42 m_setSpellID
- uint32 items_to_triggerspell[MAX_ITEM_SET_SPELLS]; // 43-50 m_setThreshold
- uint32 required_skill_id; // 51 m_requiredSkill
- uint32 required_skill_value; // 52 m_requiredSkillRank
+ char* name; // 1 m_name_lang
+ uint32 itemId[MAX_ITEM_SET_ITEMS]; // 2-18 m_itemID
+ uint32 spells[MAX_ITEM_SET_SPELLS]; // 19-26 m_setSpellID
+ uint32 items_to_triggerspell[MAX_ITEM_SET_SPELLS]; // 27-34 m_setThreshold
+ uint32 required_skill_id; // 35 m_requiredSkill
+ uint32 required_skill_value; // 36 m_requiredSkillRank
};
struct LFGDungeonEntry
{
uint32 ID; // 0
- char* name[16]; // 1-17 Name lang
- uint32 minlevel; // 18
- uint32 maxlevel; // 19
- uint32 reclevel; // 20
- uint32 recminlevel; // 21
- uint32 recmaxlevel; // 22
- int32 map; // 23
- uint32 difficulty; // 24
- uint32 flags; // 25
- uint32 type; // 26
- //uint32 unk; // 27
- //char* iconname; // 28
- uint32 expansion; // 29
- //uint32 unk4; // 30
- uint32 grouptype; // 31
- //char* desc[16]; // 32-47 Description
+ char* name; // 1
+ uint32 minlevel; // 2
+ uint32 maxlevel; // 3
+ uint32 reclevel; // 4
+ uint32 recminlevel; // 5
+ uint32 recmaxlevel; // 6
+ int32 map; // 7
+ uint32 difficulty; // 8
+ uint32 flags; // 9
+ uint32 type; // 10
+ //uint32 unk2; // 11
+ //char* iconname; // 12
+ uint32 expansion; // 13
+ //uint32 unk4; // 14
+ uint32 grouptype; // 15
+ //char* desc; // 16 Description
+ uint32 randomCategoryId; // 17 RandomDungeonID assigned for this dungeon
// Helpers
uint32 Entry() const { return ID + (type << 24); }
};
@@ -1308,12 +1463,25 @@ struct LockEntry
//uint32 Action[MAX_LOCK_CASE]; // 25-32 m_Action
};
+struct PhaseEntry
+{
+ uint32 ID; // 0
+ char* Name; // 1
+ uint32 flag; // 2
+};
+
+struct PhaseGroupEntry
+{
+ uint32 ID;
+ uint32 PhaseId;
+ uint32 GroupId;
+};
+
struct MailTemplateEntry
{
uint32 ID; // 0
- //char* subject[16]; // 1-16
- // 17 name flags, unused
- char* content[16]; // 18-33
+ //char* subject; // 1 m_subject_lang
+ char* content; // 2 m_body_lang
};
struct MapEntry
@@ -1322,23 +1490,22 @@ struct MapEntry
//char* internalname; // 1 unused
uint32 map_type; // 2
uint32 Flags; // 3
- // 4 0 or 1 for battlegrounds (not arenas)
- char* name[16]; // 5-20
- // 21 name flags, unused
- uint32 linked_zone; // 22 common zone for instance and continent map
- //char* hordeIntro[16]; // 23-38 text for PvP Zones
- // 39 intro text flags
- //char* allianceIntro[16]; // 40-55 text for PvP Zones
- // 56 intro text flags
- uint32 multimap_id; // 57
- //float BattlefieldMapIconScale; // 58
- int32 entrance_map; // 59 map_id of entrance map
- float entrance_x; // 60 entrance x coordinate (if exist single entry)
- float entrance_y; // 61 entrance y coordinate (if exist single entry)
- //uint32 TimeOfDayOverride; // 62 -1, 0 and 720
- uint32 addon; // 63 (0-original maps, 1-tbc addon)
- uint32 unk_time; // 64 some kind of time?
- uint32 maxPlayers; // 65 max players, fallback if not present in MapDifficulty.dbc
+ //uint32 unk4; // 4 4.0.1
+ //uint32 isPvP; // 5 m_PVP 0 or 1 for battlegrounds (not arenas)
+ char* name; // 6 m_MapName_lang
+ uint32 linked_zone; // 7 m_areaTableID
+ //char* hordeIntro; // 8 m_MapDescription0_lang
+ //char* allianceIntro; // 9 m_MapDescription1_lang
+ uint32 multimap_id; // 10 m_LoadingScreenID (LoadingScreens.dbc)
+ //float BattlefieldMapIconScale; // 11 m_minimapIconScale
+ int32 entrance_map; // 12 m_corpseMapID map_id of entrance map in ghost mode (continent always and in most cases = normal entrance)
+ float entrance_x; // 13 m_corpseX entrance x coordinate in ghost mode (in most cases = normal entrance)
+ float entrance_y; // 14 m_corpseY entrance y coordinate in ghost mode (in most cases = normal entrance)
+ //uint32 timeOfDayOverride; // 15 m_timeOfDayOverride
+ uint32 addon; // 16 m_expansionID
+ uint32 expireTime; // 17 m_raidOffset
+ uint32 maxPlayers; // 18 m_maxPlayers
+ int32 rootPhaseMap; // 19 new 4.0.0, mapid, related to phasing
// Helpers
uint32 Expansion() const { return addon; }
@@ -1375,18 +1542,52 @@ struct MapDifficultyEntry
//uint32 Id; // 0
uint32 MapId; // 1
uint32 Difficulty; // 2 (for arenas: arena slot)
- char* areaTriggerText; // 3-18 text showed when transfer to map failed (missing requirements)
- //uint32 textFlags; // 19
- uint32 resetTime; // 20
- uint32 maxPlayers; // 21
- //char* difficultyString; // 22
+ char* areaTriggerText; // 3 m_message_lang (text showed when transfer to map failed)
+ uint32 resetTime; // 4, m_raidDuration in secs, 0 if no fixed reset time
+ uint32 maxPlayers; // 5, m_maxPlayers some heroic versions have 0 when expected same amount as in normal version
+ //char* difficultyString; // 6 m_difficultystring
+};
+
+struct MountCapabilityEntry
+{
+ uint32 Id;
+ uint32 Flags;
+ uint32 RequiredRidingSkill;
+ uint32 RequiredArea;
+ uint32 RequiredAura;
+ uint32 RequiredSpell;
+ uint32 SpeedModSpell;
+ int32 RequiredMap;
+};
+
+#define MAX_MOUNT_CAPABILITIES 24
+
+struct MountTypeEntry
+{
+ uint32 Id;
+ uint32 MountCapability[MAX_MOUNT_CAPABILITIES];
};
struct MovieEntry
{
uint32 Id; // 0 index
//char* filename; // 1
- //uint32 unk2; // 2 always 100
+ //uint32 unk1; // 2 m_volume
+ //uint32 unk2; // 3 4.0.0
+};
+
+struct NameGenEntry
+{
+ //uint32 id;
+ char* name;
+ uint32 race;
+ uint32 gender;
+};
+
+struct NumTalentsAtLevelEntry
+{
+ //uint32 Level; // 0 index
+ float Talents; // 1 talent count
};
#define MAX_OVERRIDE_SPELL 10
@@ -1396,6 +1597,7 @@ struct OverrideSpellDataEntry
uint32 id; // 0
uint32 spellId[MAX_OVERRIDE_SPELL]; // 1-10
//uint32 unk0; // 11
+ //char* SpellBarName; // 12
};
struct PowerDisplayEntry
@@ -1424,8 +1626,7 @@ struct PvPDifficultyEntry
struct QuestSortEntry
{
uint32 id; // 0 m_ID
- //char* name[16]; // 1-16 m_SortName_lang
- // 17 name flags
+ //char* name; // 1 m_SortName_lang
};
struct QuestXPEntry
@@ -1454,78 +1655,23 @@ struct ScalingStatDistributionEntry
uint32 Id; // 0
int32 StatMod[10]; // 1-10
uint32 Modifier[10]; // 11-20
- uint32 MaxLevel; // 21
+ //uint32 unk1; // 21
+ uint32 MaxLevel; // 22 m_maxlevel
};
struct ScalingStatValuesEntry
{
- uint32 Id; // 0
- uint32 Level; // 1
- uint32 ssdMultiplier[4]; // 2-5 Multiplier for ScalingStatDistribution
- uint32 armorMod[4]; // 6-9 Armor for level
- uint32 dpsMod[6]; // 10-15 DPS mod for level
- uint32 spellPower; // 16 spell power for level
- uint32 ssdMultiplier2; // 17 there's data from 3.1 dbc ssdMultiplier[3]
- uint32 ssdMultiplier3; // 18 3.3
- uint32 armorMod2[5]; // 19-23 Armor for level
-
- uint32 getssdMultiplier(uint32 mask) const
- {
- if (mask & 0x4001F)
- {
- if (mask & 0x00000001) return ssdMultiplier[0]; // Shoulder
- if (mask & 0x00000002) return ssdMultiplier[1]; // Trinket
- if (mask & 0x00000004) return ssdMultiplier[2]; // Weapon1H
- if (mask & 0x00000008) return ssdMultiplier2;
- if (mask & 0x00000010) return ssdMultiplier[3]; // Ranged
- if (mask & 0x00040000) return ssdMultiplier3;
- }
- return 0;
- }
-
- uint32 getArmorMod(uint32 mask) const
- {
- if (mask & 0x00F001E0)
- {
- if (mask & 0x00000020) return armorMod[0]; // Cloth shoulder
- if (mask & 0x00000040) return armorMod[1]; // Leather shoulder
- if (mask & 0x00000080) return armorMod[2]; // Mail shoulder
- if (mask & 0x00000100) return armorMod[3]; // Plate shoulder
-
- if (mask & 0x00080000) return armorMod2[0]; // cloak
- if (mask & 0x00100000) return armorMod2[1]; // cloth
- if (mask & 0x00200000) return armorMod2[2]; // leather
- if (mask & 0x00400000) return armorMod2[3]; // mail
- if (mask & 0x00800000) return armorMod2[4]; // plate
- }
- return 0;
- }
-
- uint32 getDPSMod(uint32 mask) const
- {
- if (mask & 0x7E00)
- {
- if (mask & 0x00000200) return dpsMod[0]; // Weapon 1h
- if (mask & 0x00000400) return dpsMod[1]; // Weapon 2h
- if (mask & 0x00000800) return dpsMod[2]; // Caster dps 1h
- if (mask & 0x00001000) return dpsMod[3]; // Caster dps 2h
- if (mask & 0x00002000) return dpsMod[4]; // Ranged
- if (mask & 0x00004000) return dpsMod[5]; // Wand
- }
- return 0;
- }
-
- uint32 getSpellBonus(uint32 mask) const
- {
- if (mask & 0x00008000) return spellPower;
- return 0;
- }
+ uint32 Id; // 0
+ uint32 Level; // 1
+ uint32 dpsMod[6]; // 2-7 DPS mod for level
+ uint32 Spellpower; // 8 spell power for level
+ uint32 StatMultiplier[5]; // 9-13 Multiplier for ScalingStatDistribution
+ uint32 Armor[8][4]; // 14-46 Armor for level
+ uint32 CloakArmor; // 47 armor for cloak
- uint32 getFeralBonus(uint32 mask) const // removed in 3.2.x?
- {
- if (mask & 0x00010000) return 0; // not used?
- return 0;
- }
+ uint32 GetStatMultiplier(uint32 inventoryType) const;
+ uint32 GetArmor(uint32 inventoryType, uint32 armorType) const;
+ uint32 GetDPSAndDamageMultiplier(uint32 subClass, bool isCasterWeapon, float* damageMultiplier) const;
};
//struct SkillLineCategoryEntry{
@@ -1540,14 +1686,11 @@ struct SkillLineEntry
uint32 id; // 0 m_ID
int32 categoryId; // 1 m_categoryID
//uint32 skillCostID; // 2 m_skillCostsID
- char* name[16]; // 3-18 m_displayName_lang
- // 19 string flags
- //char* description[16]; // 20-35 m_description_lang
- // 36 string flags
- uint32 spellIcon; // 37 m_spellIconID
- //char* alternateVerb[16]; // 38-53 m_alternateVerb_lang
- // 54 string flags
- uint32 canLink; // 55 m_canLink (prof. with recipes
+ char* name; // 3 m_displayName_lang
+ //char* description; // 4 m_description_lang
+ uint32 spellIcon; // 5 m_spellIconID
+ //char* alternateVerb; // 6 m_alternateVerb_lang
+ uint32 canLink; // 7 m_canLink (prof. with recipes)
};
struct SkillLineAbilityEntry
@@ -1564,28 +1707,29 @@ struct SkillLineAbilityEntry
uint32 AutolearnType; // 9 m_acquireMethod
uint32 max_value; // 10 m_trivialSkillLineRankHigh
uint32 min_value; // 11 m_trivialSkillLineRankLow
- //uint32 characterPoints[2]; // 12-13 m_characterPoints[2]
+ uint32 character_points[2]; // 12-13 m_characterPoints
};
struct SkillRaceClassInfoEntry
{
- //uint32 Id; // 0
- uint32 SkillId; // 1
- uint32 RaceMask; // 2
- uint32 ClassMask; // 3
- uint32 Flags; // 4
- //uint32 MinLevel; // 5
- uint32 SkillTier; // 6
- //uint32 SkillCostType; // 7
+ //uint32 Id; // 0 m_ID
+ uint32 SkillId; // 1 m_skillID
+ uint32 RaceMask; // 2 m_raceMask
+ uint32 ClassMask; // 3 m_classMask
+ uint32 Flags; // 4 m_flags
+ //uint32 Unk; // 5 m_unk
+ //uint32 MinLevel; // 6 m_minLevel
+ uint32 SkillTier; // 7 m_skillTierID
+ //uint32 SkillCostType; // 8 m_skillCostIndex
};
#define MAX_SKILL_STEP 16
struct SkillTiersEntry
{
- uint32 Id; // 0
- //uint32 StepCost[MAX_SKILL_STEP]; // 1-16
- uint32 MaxSkill[MAX_SKILL_STEP]; // 17-32
+ uint32 Id; // 0 m_ID
+ //uint32 StepCost[MAX_SKILL_STEP]; // 1-16 m_cost
+ uint32 MaxSkill[MAX_SKILL_STEP]; // 17-32 m_valueMax
};
struct SoundEntriesEntry
@@ -1601,124 +1745,155 @@ struct SoundEntriesEntry
// 26 m_minDistance
// 27 m_distanceCutoff
// 28 m_EAXDef
- // 29 new in 3.1
+ // 29 m_soundEntriesAdvancedID, new in 3.1
+ //unk // 30 4.0.0
+ //unk // 31 4.0.0
+ //unk // 32 4.0.0
+ //unk // 33 4.0.0
+};
+
+// SpellEffect.dbc
+struct SpellEffectEntry
+{
+ uint32 Id; // 0 m_ID
+ uint32 Effect; // 1 m_effect
+ float EffectValueMultiplier; // 2 m_effectAmplitude
+ uint32 EffectApplyAuraName; // 3 m_effectAura
+ uint32 EffectAmplitude; // 4 m_effectAuraPeriod
+ int32 EffectBasePoints; // 5 m_effectBasePoints (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints)
+ float EffectBonusMultiplier; // 6 m_effectBonus
+ float EffectDamageMultiplier; // 7 m_effectChainAmplitude
+ uint32 EffectChainTarget; // 8 m_effectChainTargets
+ int32 EffectDieSides; // 9 m_effectDieSides
+ uint32 EffectItemType; // 10 m_effectItemType
+ uint32 EffectMechanic; // 11 m_effectMechanic
+ int32 EffectMiscValue; // 12 m_effectMiscValue
+ int32 EffectMiscValueB; // 13 m_effectMiscValueB
+ float EffectPointsPerComboPoint; // 14 m_effectPointsPerCombo
+ uint32 EffectRadiusIndex; // 15 m_effectRadiusIndex - spellradius.dbc
+ uint32 EffectRadiusMaxIndex; // 16 4.0.0
+ float EffectRealPointsPerLevel; // 17 m_effectRealPointsPerLevel
+ flag96 EffectSpellClassMask; // 18 19 20 m_effectSpellClassMask1(2/3), effect 0
+ uint32 EffectTriggerSpell; // 21 m_effectTriggerSpell
+ uint32 EffectImplicitTargetA; // 22 m_implicitTargetA
+ uint32 EffectImplicitTargetB; // 23 m_implicitTargetB
+ uint32 EffectSpellId; // 24 new 4.0.0
+ uint32 EffectIndex; // 25 new 4.0.0
+ //uint32 Unk0 // 26 4.2.0 only 0 or 1
};
#define MAX_SPELL_EFFECTS 3
#define MAX_EFFECT_MASK 7
#define MAX_SPELL_REAGENTS 8
+// SpellAuraOptions.dbc
+struct SpellAuraOptionsEntry
+{
+ uint32 Id; // 0 m_ID
+ uint32 StackAmount; // 1 m_cumulativeAura
+ uint32 procChance; // 2 m_procChance
+ uint32 procCharges; // 3 m_procCharges
+ uint32 procFlags; // 4 m_procTypeMask
+};
+
+// SpellAuraRestrictions.dbc/
+struct SpellAuraRestrictionsEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 CasterAuraState; // 1 m_casterAuraState
+ uint32 TargetAuraState; // 2 m_targetAuraState
+ uint32 CasterAuraStateNot; // 3 m_excludeCasterAuraState
+ uint32 TargetAuraStateNot; // 4 m_excludeTargetAuraState
+ uint32 casterAuraSpell; // 5 m_casterAuraSpell
+ uint32 targetAuraSpell; // 6 m_targetAuraSpell
+ uint32 excludeCasterAuraSpell; // 7 m_excludeCasterAuraSpell
+ uint32 excludeTargetAuraSpell; // 8 m_excludeTargetAuraSpell
+};
+
+// SpellCastingRequirements.dbc
+struct SpellCastingRequirementsEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 FacingCasterFlags; // 1 m_facingCasterFlags
+ //uint32 MinFactionId; // 2 m_minFactionID not used
+ //uint32 MinReputation; // 3 m_minReputation not used
+ int32 AreaGroupId; // 4 m_requiredAreaGroupId
+ //uint32 RequiredAuraVision; // 5 m_requiredAuraVision not used
+ uint32 RequiresSpellFocus; // 6 m_requiresSpellFocus
+};
+
+#define MAX_SPELL_TOTEMS 2
+
+// SpellTotems.dbc
+struct SpellTotemsEntry
+{
+ uint32 Id; // 0 m_ID
+ uint32 TotemCategory[MAX_SPELL_TOTEMS]; // 1 m_requiredTotemCategoryID
+ uint32 Totem[MAX_SPELL_TOTEMS]; // 2 m_totem
+};
+
+// Spell.dbc
struct SpellEntry
{
uint32 Id; // 0 m_ID
+ uint32 Attributes; // 1 m_attribute
+ uint32 AttributesEx; // 2 m_attributesEx
+ uint32 AttributesEx2; // 3 m_attributesExB
+ uint32 AttributesEx3; // 4 m_attributesExC
+ uint32 AttributesEx4; // 5 m_attributesExD
+ uint32 AttributesEx5; // 6 m_attributesExE
+ uint32 AttributesEx6; // 7 m_attributesExF
+ uint32 AttributesEx7; // 8 m_attributesExG
+ uint32 AttributesEx8; // 9 m_attributesExH
+ uint32 AttributesEx9; // 10 m_attributesExI
+ uint32 AttributesEx10; // 11 m_attributesExJ
+ uint32 CastingTimeIndex; // 12 m_castingTimeIndex
+ uint32 DurationIndex; // 13 m_durationIndex
+ uint32 powerType; // 14 m_powerType
+ uint32 rangeIndex; // 15 m_rangeIndex
+ float speed; // 16 m_speed
+ uint32 SpellVisual[2]; // 17-18 m_spellVisualID
+ uint32 SpellIconID; // 19 m_spellIconID
+ uint32 activeIconID; // 20 m_activeIconID
+ char* SpellName; // 21 m_name_lang
+ char* Rank; // 22 m_nameSubtext_lang
+ //char* Description; // 23 m_description_lang not used
+ //char* ToolTip; // 24 m_auraDescription_lang not used
+ uint32 SchoolMask; // 25 m_schoolMask
+ uint32 runeCostID; // 26 m_runeCostID
+ //uint32 spellMissileID; // 27 m_spellMissileID not used
+ //uint32 spellDescriptionVariableID; // 28 m_spellDescriptionVariableID, 3.2.0
+ uint32 SpellDifficultyId; // 29 m_spellDifficultyID - id from SpellDifficulty.dbc
+ float SpellCoef; // 30
+ uint32 SpellScalingId; // 31 SpellScaling.dbc
+ uint32 SpellAuraOptionsId; // 32 SpellAuraOptions.dbc
+ uint32 SpellAuraRestrictionsId; // 33 SpellAuraRestrictions.dbc
+ uint32 SpellCastingRequirementsId; // 34 SpellCastingRequirements.dbc
+ uint32 SpellCategoriesId; // 35 SpellCategories.dbc
+ uint32 SpellClassOptionsId; // 36 SpellClassOptions.dbc
+ uint32 SpellCooldownsId; // 37 SpellCooldowns.dbc
+ //uint32 unkIndex7; // 38 all zeros...
+ uint32 SpellEquippedItemsId; // 39 SpellEquippedItems.dbc
+ uint32 SpellInterruptsId; // 40 SpellInterrupts.dbc
+ uint32 SpellLevelsId; // 41 SpellLevels.dbc
+ uint32 SpellPowerId; // 42 SpellPower.dbc
+ uint32 SpellReagentsId; // 43 SpellReagents.dbc
+ uint32 SpellShapeshiftId; // 44 SpellShapeshift.dbc
+ uint32 SpellTargetRestrictionsId; // 45 SpellTargetRestrictions.dbc
+ uint32 SpellTotemsId; // 46 SpellTotems.dbc
+ //uint32 ResearchProject; // 47 ResearchProject.dbc
+};
+
+// SpellCategories.dbc
+struct SpellCategoriesEntry
+{
+ //uint32 Id; // 0 m_ID
uint32 Category; // 1 m_category
+ uint32 DmgClass; // 153 m_defenseType
uint32 Dispel; // 2 m_dispelType
uint32 Mechanic; // 3 m_mechanic
- uint32 Attributes; // 4 m_attributes
- uint32 AttributesEx; // 5 m_attributesEx
- uint32 AttributesEx2; // 6 m_attributesExB
- uint32 AttributesEx3; // 7 m_attributesExC
- uint32 AttributesEx4; // 8 m_attributesExD
- uint32 AttributesEx5; // 9 m_attributesExE
- uint32 AttributesEx6; // 10 m_attributesExF
- uint32 AttributesEx7; // 11 m_attributesExG
- uint32 Stances; // 12 m_shapeshiftMask
- // uint32 unk_320_2; // 13 3.2.0
- uint32 StancesNot; // 14 m_shapeshiftExclude
- // uint32 unk_320_3; // 15 3.2.0
- uint32 Targets; // 16 m_targets
- uint32 TargetCreatureType; // 17 m_targetCreatureType
- uint32 RequiresSpellFocus; // 18 m_requiresSpellFocus
- uint32 FacingCasterFlags; // 19 m_facingCasterFlags
- uint32 CasterAuraState; // 20 m_casterAuraState
- uint32 TargetAuraState; // 21 m_targetAuraState
- uint32 CasterAuraStateNot; // 22 m_excludeCasterAuraState
- uint32 TargetAuraStateNot; // 23 m_excludeTargetAuraState
- uint32 casterAuraSpell; // 24 m_casterAuraSpell
- uint32 targetAuraSpell; // 25 m_targetAuraSpell
- uint32 excludeCasterAuraSpell; // 26 m_excludeCasterAuraSpell
- uint32 excludeTargetAuraSpell; // 27 m_excludeTargetAuraSpell
- uint32 CastingTimeIndex; // 28 m_castingTimeIndex
- uint32 RecoveryTime; // 29 m_recoveryTime
- uint32 CategoryRecoveryTime; // 30 m_categoryRecoveryTime
- uint32 InterruptFlags; // 31 m_interruptFlags
- uint32 AuraInterruptFlags; // 32 m_auraInterruptFlags
- uint32 ChannelInterruptFlags; // 33 m_channelInterruptFlags
- uint32 procFlags; // 34 m_procTypeMask
- uint32 procChance; // 35 m_procChance
- uint32 procCharges; // 36 m_procCharges
- uint32 maxLevel; // 37 m_maxLevel
- uint32 baseLevel; // 38 m_baseLevel
- uint32 spellLevel; // 39 m_spellLevel
- uint32 DurationIndex; // 40 m_durationIndex
- uint32 powerType; // 41 m_powerType
- uint32 manaCost; // 42 m_manaCost
- uint32 manaCostPerlevel; // 43 m_manaCostPerLevel
- uint32 manaPerSecond; // 44 m_manaPerSecond
- uint32 manaPerSecondPerLevel; // 45 m_manaPerSecondPerLeve
- uint32 rangeIndex; // 46 m_rangeIndex
- float speed; // 47 m_speed
- //uint32 modalNextSpell; // 48 m_modalNextSpell not used
- uint32 StackAmount; // 49 m_cumulativeAura
- uint32 Totem[2]; // 50-51 m_totem
- int32 Reagent[MAX_SPELL_REAGENTS]; // 52-59 m_reagent
- uint32 ReagentCount[MAX_SPELL_REAGENTS]; // 60-67 m_reagentCount
- int32 EquippedItemClass; // 68 m_equippedItemClass (value)
- int32 EquippedItemSubClassMask; // 69 m_equippedItemSubclass (mask)
- int32 EquippedItemInventoryTypeMask; // 70 m_equippedItemInvTypes (mask)
- uint32 Effect[MAX_SPELL_EFFECTS]; // 71-73 m_effect
- int32 EffectDieSides[MAX_SPELL_EFFECTS]; // 74-76 m_effectDieSides
- float EffectRealPointsPerLevel[MAX_SPELL_EFFECTS]; // 77-79 m_effectRealPointsPerLevel
- int32 EffectBasePoints[MAX_SPELL_EFFECTS]; // 80-82 m_effectBasePoints (must not be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints)
- uint32 EffectMechanic[MAX_SPELL_EFFECTS]; // 83-85 m_effectMechanic
- uint32 EffectImplicitTargetA[MAX_SPELL_EFFECTS]; // 86-88 m_implicitTargetA
- uint32 EffectImplicitTargetB[MAX_SPELL_EFFECTS]; // 89-91 m_implicitTargetB
- uint32 EffectRadiusIndex[MAX_SPELL_EFFECTS]; // 92-94 m_effectRadiusIndex - spellradius.dbc
- uint32 EffectApplyAuraName[MAX_SPELL_EFFECTS]; // 95-97 m_effectAura
- uint32 EffectAmplitude[MAX_SPELL_EFFECTS]; // 98-100 m_effectAuraPeriod
- float EffectValueMultiplier[MAX_SPELL_EFFECTS]; // 101-103
- uint32 EffectChainTarget[MAX_SPELL_EFFECTS]; // 104-106 m_effectChainTargets
- uint32 EffectItemType[MAX_SPELL_EFFECTS]; // 107-109 m_effectItemType
- int32 EffectMiscValue[MAX_SPELL_EFFECTS]; // 110-112 m_effectMiscValue
- int32 EffectMiscValueB[MAX_SPELL_EFFECTS]; // 113-115 m_effectMiscValueB
- uint32 EffectTriggerSpell[MAX_SPELL_EFFECTS]; // 116-118 m_effectTriggerSpell
- float EffectPointsPerComboPoint[MAX_SPELL_EFFECTS]; // 119-121 m_effectPointsPerCombo
- flag96 EffectSpellClassMask[MAX_SPELL_EFFECTS]; // 122-130
- uint32 SpellVisual[2]; // 131-132 m_spellVisualID
- uint32 SpellIconID; // 133 m_spellIconID
- uint32 activeIconID; // 134 m_activeIconID
- //uint32 spellPriority; // 135 not used
- char* SpellName[16]; // 136-151 m_name_lang
- //uint32 SpellNameFlag; // 152 not used
- char* Rank[16]; // 153-168 m_nameSubtext_lang
- //uint32 RankFlags; // 169 not used
- //char* Description[16]; // 170-185 m_description_lang not used
- //uint32 DescriptionFlags; // 186 not used
- //char* ToolTip[16]; // 187-202 m_auraDescription_lang not used
- //uint32 ToolTipFlags; // 203 not used
- uint32 ManaCostPercentage; // 204 m_manaCostPct
- uint32 StartRecoveryCategory; // 205 m_startRecoveryCategory
- uint32 StartRecoveryTime; // 206 m_startRecoveryTime
- uint32 MaxTargetLevel; // 207 m_maxTargetLevel
- uint32 SpellFamilyName; // 208 m_spellClassSet
- flag96 SpellFamilyFlags; // 209-211
- uint32 MaxAffectedTargets; // 212 m_maxTargets
- uint32 DmgClass; // 213 m_defenseType
- uint32 PreventionType; // 214 m_preventionType
- //uint32 StanceBarOrder; // 215 m_stanceBarOrder not used
- float EffectDamageMultiplier[MAX_SPELL_EFFECTS]; // 216-218 m_effectChainAmplitude
- //uint32 MinFactionId; // 219 m_minFactionID not used
- //uint32 MinReputation; // 220 m_minReputation not used
- //uint32 RequiredAuraVision; // 221 m_requiredAuraVision not used
- uint32 TotemCategory[2]; // 222-223 m_requiredTotemCategoryID
- int32 AreaGroupId; // 224 m_requiredAreaGroupId
- uint32 SchoolMask; // 225 m_schoolMask
- uint32 runeCostID; // 226 m_runeCostID
- //uint32 spellMissileID; // 227 m_spellMissileID not used
- //uint32 PowerDisplayId; // 228 PowerDisplay.dbc, new in 3.1
- float EffectBonusMultiplier[MAX_SPELL_EFFECTS]; // 229-231 3.2.0
- //uint32 spellDescriptionVariableID; // 232 3.2.0
- //uint32 SpellDifficultyId; // 233 3.3.0
+ uint32 PreventionType; // 154 m_preventionType
+ uint32 StartRecoveryCategory; // 145 m_startRecoveryCategory
};
typedef std::set<uint32> SpellCategorySet;
@@ -1738,6 +1913,8 @@ struct SpellCategoryEntry
{
uint32 Id;
uint32 Flags;
+ // uint32 unk;
+ // char* Name;
};
struct SpellDifficultyEntry
@@ -1749,8 +1926,7 @@ struct SpellDifficultyEntry
struct SpellFocusObjectEntry
{
uint32 ID; // 0
- //char* Name[16]; // 1-15 unused
- // 16 string flags, unused
+ //char* Name; // 1 m_name_lang
};
struct SpellRadiusEntry
@@ -1767,12 +1943,71 @@ struct SpellRangeEntry
float minRangeHostile;
float minRangeFriend;
float maxRangeHostile;
- float maxRangeFriend;
+ float maxRangeFriend; //friend means unattackable unit here
uint32 type;
- //char* Name[16]; // 7-23 unused
- // 24 string flags, unused
- //char* Name2[16]; // 25-40 unused
- // 41 string flags, unused
+ //char* Name; // 6-21 m_displayName_lang
+ //char* ShortName; // 23-38 m_displayNameShort_lang
+};
+
+// SpellEquippedItems.dbc
+struct SpellEquippedItemsEntry
+{
+ //uint32 Id; // 0 m_ID
+ int32 EquippedItemClass; // 70 m_equippedItemClass (value)
+ int32 EquippedItemInventoryTypeMask; // 72 m_equippedItemInvTypes (mask)
+ int32 EquippedItemSubClassMask; // 71 m_equippedItemSubclass (mask)
+};
+
+// SpellCooldowns.dbc
+struct SpellCooldownsEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 CategoryRecoveryTime; // 31 m_categoryRecoveryTime
+ uint32 RecoveryTime; // 30 m_recoveryTime
+ uint32 StartRecoveryTime; // 146 m_startRecoveryTime
+};
+
+// SpellClassOptions.dbc
+struct SpellClassOptionsEntry
+{
+ //uint32 Id; // 0 m_ID
+ //uint32 modalNextSpell; // 1 m_modalNextSpell not used
+ flag96 SpellFamilyFlags; // 2-4
+ uint32 SpellFamilyName; // 5 m_spellClassSet
+ //char* Description; // 6 4.0.0
+};
+
+// SpellInterrupts.dbc
+struct SpellInterruptsEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 AuraInterruptFlags; // 1 m_auraInterruptFlags
+ //uint32 // 2 4.0.0
+ uint32 ChannelInterruptFlags; // 3 m_channelInterruptFlags
+ //uint32 // 4 4.0.0
+ uint32 InterruptFlags; // 5 m_interruptFlags
+};
+
+// SpellLevels.dbc
+struct SpellLevelsEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 baseLevel; // 1 m_baseLevel
+ uint32 maxLevel; // 2 m_maxLevel
+ uint32 spellLevel; // 3 m_spellLevel
+};
+
+// SpellPower.dbc
+struct SpellPowerEntry
+{
+ //uint32 Id; // 0 m_ID
+ uint32 manaCost; // 1 m_manaCost
+ uint32 manaCostPerlevel; // 2 m_manaCostPerLevel
+ uint32 ManaCostPercentage; // 3 m_manaCostPct
+ uint32 manaPerSecond; // 4 m_manaPerSecond
+ uint32 manaPerSecondPerLevel; // 5 m_manaPerSecondPerLevel
+ //uint32 PowerDisplayId; // 6 m_powerDisplayID - id from PowerDisplay.dbc, new in 3.1
+ float ManaCostPercentageFloat; // 7 4.3.0
};
struct SpellRuneCostEntry
@@ -1787,21 +2022,67 @@ struct SpellRuneCostEntry
#define MAX_SHAPESHIFT_SPELLS 8
-struct SpellShapeshiftEntry
+struct SpellShapeshiftFormEntry
{
uint32 ID; // 0
//uint32 buttonPosition; // 1 unused
- //char* Name[16]; // 2-17 unused
- //uint32 NameFlags; // 18 unused
- uint32 flags1; // 19
- int32 creatureType; // 20 <= 0 humanoid, other normal creature types
- //uint32 unk1; // 21 unused
- uint32 attackSpeed; // 22
- uint32 modelID_A; // 23 alliance modelid
- uint32 modelID_H; // 24 horde modelid (only one form)
- //uint32 unk3; // 25 unused
- //uint32 unk4; // 26 unused
- uint32 stanceSpell[MAX_SHAPESHIFT_SPELLS]; // 27 - 34 unused
+ //char* Name; // 2 unused
+ uint32 flags1; // 3
+ int32 creatureType; // 4 <=0 humanoid, other normal creature types
+ //uint32 spellIcon; // 5 unused, related to next field
+ uint32 attackSpeed; // 6
+ // Models changed, 0 is main model, the rest 3 are unused.
+ uint32 modelID_A; // 7 alliance modelid (0 means no model)
+ uint32 modelID_H; // 8 horde modelid (but only for one form)
+ //uint32 unk3; // 9 unused always 0
+ //uint32 unk4; // 10 unused always 0
+ uint32 stanceSpell[MAX_SHAPESHIFT_SPELLS]; // 11-18 spells which appear in the bar after shapeshifting
+ //uint32 unk5; // 19
+ //uint32 unk6; // 20
+};
+
+// SpellShapeshift.dbc
+struct SpellShapeshiftEntry
+{
+ uint32 Id; // 0 - m_ID
+ uint32 StancesNot; // 3 - m_shapeshiftExclude
+ // uint32 unk_320_2; // 2 - 3.2.0
+ uint32 Stances; // 1 - m_shapeshiftMask
+ // uint32 unk_320_3; // 4 - 3.2.0
+ // uint32 StanceBarOrder; // 5 - m_stanceBarOrder not used
+};
+
+// SpellTargetRestrictions.dbc
+struct SpellTargetRestrictionsEntry
+{
+ uint32 Id; // 0 m_ID
+ uint32 MaxAffectedTargets; // 1 m_maxTargets
+ uint32 MaxTargetLevel; // 2 m_maxTargetLevel
+ uint32 TargetCreatureType; // 3 m_targetCreatureType
+ uint32 Targets; // 4 m_targets
+};
+
+// SpellReagents.dbc
+struct SpellReagentsEntry
+{
+ //uint32 Id; // 0 m_ID
+ int32 Reagent[MAX_SPELL_REAGENTS]; // 54-61 m_reagent
+ uint32 ReagentCount[MAX_SPELL_REAGENTS]; // 62-69 m_reagentCount
+};
+
+// SpellScaling.dbc
+struct SpellScalingEntry
+{
+ //uint32 Id; // 0 m_ID
+ int32 CastTimeMin; // 1
+ int32 CastTimeMax; // 2
+ int32 CastTimeMaxLevel; // 3
+ int32 ScalingClass; // 4 (index * 100) + charLevel - 1 => gtSpellScaling.dbc
+ float Multiplier[3]; // 5-7
+ float RandomMultiplier[3]; // 8-10
+ float OtherMultiplier[3]; // 11-13
+ float CoefBase; // 14 some coefficient, mostly 1.0f
+ int32 CoefLevelBase; // 15 some level
};
struct SpellDurationEntry
@@ -1818,15 +2099,15 @@ struct SpellItemEnchantmentEntry
uint32 amount[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 5-7 m_effectPointsMin[MAX_ITEM_ENCHANTMENT_EFFECTS]
//uint32 amount2[MAX_ITEM_ENCHANTMENT_EFFECTS] // 8-10 m_effectPointsMax[MAX_ITEM_ENCHANTMENT_EFFECTS]
uint32 spellid[MAX_ITEM_ENCHANTMENT_EFFECTS]; // 11-13 m_effectArg[MAX_ITEM_ENCHANTMENT_EFFECTS]
- char* description[16]; // 14-29 m_name_lang[16]
- //uint32 descriptionFlags; // 30 name flags
- uint32 aura_id; // 31 m_itemVisual
- uint32 slot; // 32 m_flags
- uint32 GemID; // 33 m_src_itemID
- uint32 EnchantmentCondition; // 34 m_condition_id
- uint32 requiredSkill; // 35 m_requiredSkillID
- uint32 requiredSkillValue; // 36 m_requiredSkillRank
- uint32 requiredLevel; // 37 m_requiredLevel
+ char* description; // 14 m_name_lang
+ uint32 aura_id; // 15 m_itemVisual
+ uint32 slot; // 16 m_flags
+ uint32 GemID; // 17 m_src_itemID
+ uint32 EnchantmentCondition; // 18 m_condition_id
+ uint32 requiredSkill; // 19 m_requiredSkillID
+ uint32 requiredSkillValue; // 20 m_requiredSkillRank
+ uint32 requiredLevel; // 21 new in 3.1
+ // 22 new in 3.1
};
struct SpellItemEnchantmentConditionEntry
@@ -1852,7 +2133,7 @@ struct SummonPropertiesEntry
uint32 Category; // 1, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount?
uint32 Faction; // 2, 14 rows > 0
uint32 Type; // 3, see enum
- uint32 Slot; // 4, 0-6
+ int32 Slot; // 4, 0-6
uint32 Flags; // 5
};
@@ -1867,27 +2148,37 @@ struct TalentEntry
uint32 Row; // 2
uint32 Col; // 3
uint32 RankID[MAX_TALENT_RANK]; // 4-8
- // 9-12 not used, always 0, maybe not used high ranks
- uint32 DependsOn; // 13 index in Talent.dbc (TalentEntry)
- // 14-15 not used
- uint32 DependsOnRank; // 16
- // 17-18 not used
- //uint32 needAddInSpellBook; // 19 also need disable higest ranks on reset talent tree
- //uint32 unk2; // 20, all 0
- //uint64 allowForPet; // 21 its a 64 bit mask for pet 1<<m_categoryEnumID in CreatureFamily.dbc
+ uint32 DependsOn; // 9 m_prereqTalent (Talent.dbc)
+ // 10-11 part of prev field
+ uint32 DependsOnRank; // 12 m_prereqRank
+ // 13-14 part of prev field
+ //uint32 needAddInSpellBook; // 15 m_flags also need disable higest ranks on reset talent tree
+ //uint32 unk2; // 16 m_requiredSpellID
+ //uint64 allowForPet; // 17 m_categoryMask its a 64 bit mask for pet 1<<m_categoryEnumID in CreatureFamily.dbc
};
+#define MAX_MASTERY_SPELLS 2
+
struct TalentTabEntry
{
uint32 TalentTabID; // 0
- //char* name[16]; // 1-16, unused
- //uint32 nameFlags; // 17, unused
- //unit32 spellicon; // 18
- // 19 not used
- uint32 ClassMask; // 20
- uint32 petTalentMask; // 21
- uint32 tabpage; // 22
- //char* internalname; // 23
+ //char* name; // 1 m_name_lang
+ //unit32 spellicon; // 2 m_spellIconID
+ uint32 ClassMask; // 3 m_classMask
+ uint32 petTalentMask; // 4 m_petTalentMask
+ uint32 tabpage; // 5 m_orderIndex
+ //char* internalname; // 6 m_backgroundFile
+ //char* description; // 7
+ //uint32 rolesMask; // 8 4.0.0
+ uint32 MasterySpellId[MAX_MASTERY_SPELLS]; // 9-10 passive mastery bonus spells?
+};
+
+struct TalentTreePrimarySpellsEntry
+{
+ //uint32 Id; // 0 index
+ uint32 TalentTree; // 1 entry from TalentTab.dbc
+ uint32 SpellId; // 2 spell id to learn
+ //uint32 Flags; // 3 some kind of flags
};
struct TaxiNodesEntry
@@ -1897,9 +2188,9 @@ struct TaxiNodesEntry
float x; // 2 m_x
float y; // 3 m_y
float z; // 4 m_z
- char* name[16]; // 5-21 m_Name_lang
- // 22 string flags
- uint32 MountCreatureID[2]; // 23-24 m_MountCreatureID[2]
+ char* name; // 5 m_Name_lang
+ uint32 MountCreatureID[2]; // 6-7 m_MountCreatureID[2]
+ uint32 Flags; // 8 m_Flags
};
struct TaxiPathEntry
@@ -1925,19 +2216,33 @@ struct TaxiPathNodeEntry
uint32 departureEventID; // 10 m_departureEventID
};
-struct TeamContributionPointsEntry
+struct TotemCategoryEntry
{
- //uint32 entry; // 0
- float value; // 1 (???)
+ uint32 ID; // 0
+ //char* name; // 1 m_name_lang
+ uint32 categoryType; // 2 m_totemCategoryType (one for specialization)
+ uint32 categoryMask; // 3 m_totemCategoryMask (compatibility mask for same type: different for totems, compatible from high to low for rods)
};
-struct TotemCategoryEntry
+struct UnitPowerBarEntry
{
- uint32 ID; // 0
- //char* name[16]; // 1-16
- // 17 string flags, unused
- uint32 categoryType; // 18 (one for specialization)
- uint32 categoryMask; // 19 (compatibility mask for same type: different for totems, compatible from high to low for rods)
+ uint32 Id;
+ uint32 MinPower;
+ uint32 MaxPower;
+ //uint32 Unk0;
+ //uint32 Unk1;
+ //float Unk2;
+ //float Unk3;
+ //uint32 BarType;
+ //uint32 TextureFile[6];
+ //uint32 Unk4[6];
+ //uint32 DisplayFlags;
+ //char* PowerName;
+ //char* CostString;
+ //char* EmptyMessage;
+ //char* Tooltip;
+ //float StartInset;
+ //float EndInset;
};
struct TransportAnimationEntry
@@ -1989,9 +2294,9 @@ struct VehicleEntry
float m_msslTrgtArcRepeat; // 25
float m_msslTrgtArcWidth; // 26
float m_msslTrgtImpactRadius[2]; // 27-28
- char* m_msslTrgtArcTexture; // 29
- char* m_msslTrgtImpactTexture; // 30
- char* m_msslTrgtImpactModel[2]; // 31-32
+ char* m_msslTrgtArcTexture; // 29
+ char* m_msslTrgtImpactTexture; // 30
+ char* m_msslTrgtImpactModel[2]; // 31-32
float m_cameraYawOffset; // 33
uint32 m_uiLocomotionType; // 34
float m_msslTrgtImpactTexRadius; // 35
@@ -2072,8 +2377,10 @@ struct WMOAreaTableEntry
//uint32 field8;
uint32 Flags; // 9 used for indoor/outdoor determination
uint32 areaId; // 10 link to AreaTableEntry.ID
- //char *Name[16];
- //uint32 nameFlags;
+ //char *Name; // 11 m_AreaName_lang
+ //uint32 field12; // 12
+ //uint32 field13; // 13
+ //uint32 field14; // 14
};
struct WorldMapAreaEntry
@@ -2089,6 +2396,9 @@ struct WorldMapAreaEntry
int32 virtual_map_id; // 8 -1 (map_id have correct map) other: virtual map where zone show (map_id - where zone in fact internally)
// int32 dungeonMap_id; // 9 pointer to DungeonMap.dbc (owerride x1, x2, y1, y2 coordinates)
// uint32 parentMapID; // 10
+
+ // uint32 minRecommendedLevel; // 12 Minimum recommended level displayed on world map
+ // uint32 maxRecommendedLevel; // 13 Maximum recommended level displayed on world map
};
#define MAX_WORLD_MAP_OVERLAY_AREA_IDX 4
@@ -2098,9 +2408,15 @@ struct WorldMapOverlayEntry
uint32 ID; // 0
//uint32 worldMapAreaId; // 1 idx in WorldMapArea.dbc
uint32 areatableID[MAX_WORLD_MAP_OVERLAY_AREA_IDX]; // 2-5
- // 6-7 always 0, possible part of areatableID[]
- //char* internal_name // 8
- // 9-16 some ints
+ //char* internal_name // 6 m_textureName
+ // 7 m_textureWidth
+ // 8 m_textureHeight
+ // 9 m_offsetX
+ // 10 m_offsetY
+ // 11 m_hitRectTop
+ // 12 m_hitRectLeft
+ // 13 m_hitRectBottom
+ // 14 m_hitRectRight
};
struct WorldSafeLocsEntry
@@ -2110,8 +2426,7 @@ struct WorldSafeLocsEntry
float x; // 2
float y; // 3
float z; // 4
- //char* name[16] // 5-20 name, unused
- // 21 name flags, unused
+ //char* name; // 5 m_AreaName_lang
};
/*
@@ -2157,6 +2472,13 @@ struct WorldStateUI
#pragma pack(pop)
#endif
+struct VectorArray
+{
+ std::vector<std::string> stringVectorArray[2];
+};
+
+typedef std::map<uint32, VectorArray> NameGenVectorArraysMap;
+
// Structures not used for casting to loaded DBC data and not required then packing
struct MapDifficulty
{
@@ -2201,7 +2523,8 @@ struct TaxiPathNodePtr
typedef Path<TaxiPathNodePtr, TaxiPathNodeEntry const> TaxiPathNodeList;
typedef std::vector<TaxiPathNodeList> TaxiPathNodesByPath;
-#define TaxiMaskSize 14
-typedef uint32 TaxiMask[TaxiMaskSize];
-#endif
+#define TaxiMaskSize 114
+typedef uint8 TaxiMask[TaxiMaskSize];
+typedef std::unordered_map<uint32, std::set<uint32>> PhaseGroupContainer;
+#endif
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index a90cc48c5af..83f18050710 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -19,120 +19,165 @@
#ifndef TRINITY_DBCSFRM_H
#define TRINITY_DBCSFRM_H
-char const Achievementfmt[] = "niixssssssssssssssssxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxii";
-const std::string CustomAchievementfmt = "pppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaapapaaaaaaaaaaaaaaaaaapp";
+// x - skip<uint32>, X - skip<uint8>, s - char*, f - float, i - uint32, b - uint8, d - index (not included)
+// n - index (included), l - bool, p - field present in sql dbc, a - field absent in sql dbc
+
+char const Achievementfmt[] = "niixsxiixixxii";
+const std::string CustomAchievementfmt = "pppaaaapapaapp";
const std::string CustomAchievementIndex = "ID";
-char const AchievementCriteriafmt[] = "niiiiiiiixxxxxxxxxxxxxxxxxiiiix";
-char const AreaTableEntryfmt[] = "iiinixxxxxissssssssssssssssxiiiiixxx";
+char const AchievementCriteriafmt[] = "niiiliiiisiiiiixxiiiiii";
+char const AreaTableEntryfmt[] = "iiinixxxxxisiiiiiffixxxxxx";
char const AreaGroupEntryfmt[] = "niiiiiii";
-char const AreaPOIEntryfmt[] = "niiiiiiiiiiifffixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix";
-char const AreaTriggerEntryfmt[] = "niffffffff";
-char const AuctionHouseEntryfmt[] = "niiixxxxxxxxxxxxxxxxx";
+char const AreaPOIEntryfmt[] = "niiiiiiiiiiiffixixxixx";
+char const AreaTriggerEntryfmt[] = "nifffxxxfffff";
+char const ArmorLocationfmt[] = "nfffff";
+char const AuctionHouseEntryfmt[] = "niiix";
char const BankBagSlotPricesEntryfmt[] = "ni";
char const BannedAddOnsfmt[] = "nxxxxxxxxxx";
-char const BarberShopStyleEntryfmt[] = "nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii";
-char const BattlemasterListEntryfmt[] = "niiiiiiiiixssssssssssssssssxiixx";
-char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
-char const CharTitlesEntryfmt[] = "nxssssssssssssssssxssssssssssssssssxi";
-char const ChatChannelsEntryfmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxx";
-char const ChrClassesEntryfmt[] = "nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
-char const ChrRacesEntryfmt[] = "niixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
+char const BarberShopStyleEntryfmt[] = "nixxxiii";
+char const BattlemasterListEntryfmt[] = "niiiiiiiiixsiiiixxxx";
+char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxii";
+char const CharTitlesEntryfmt[] = "nxssix";
+char const ChatChannelsEntryfmt[] = "nixsx";
+char const ChrClassesEntryfmt[] = "nixsxxxixiiiii";
+char const ChrRacesEntryfmt[] = "niixiixixxxxixsxxxxxixxx";
+char const ChrClassesXPowerTypesfmt[] = "nii";
char const CinematicSequencesEntryfmt[] = "nxxxxxxxxx";
-char const CreatureDisplayInfofmt[] = "nixifxxxxxxxxxxx";
+char const CreatureDisplayInfofmt[] = "nixifxxxxxxxxxxxx";
char const CreatureDisplayInfoExtrafmt[] = "diixxxxxxxxxxxxxxxxxx";
-char const CreatureFamilyfmt[] = "nfifiiiiixssssssssssssssssxx";
-char const CreatureModelDatafmt[] = "nixxfxxxxxxxxxxffxxxxxxxxxxx";
+char const CreatureModelDatafmt[] = "nixxxxxxxxxxxxffxxxxxxxxxxxxxxx";
+char const CreatureFamilyfmt[] = "nfifiiiiixsx";
char const CreatureSpellDatafmt[] = "niiiixxxx";
-char const CreatureTypefmt[] = "nxxxxxxxxxxxxxxxxxx";
-char const CurrencyTypesfmt[] = "xnxi";
-char const DestructibleModelDatafmt[] = "nxxixxxixxxixxxixxx";
-char const DungeonEncounterfmt[] = "niixissssssssssssssssxx";
+char const CreatureTypefmt[] = "nxx";
+char const CurrencyTypesfmt[] = "nixxxiiiiix";
+char const DestructibleModelDatafmt[] = "ixxixxxixxxixxxixxxxxxxx";
+char const DungeonEncounterfmt[] = "iiixisxx";
char const DurabilityCostsfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
char const DurabilityQualityfmt[] = "nf";
-char const EmotesEntryfmt[] = "nxxiiix";
+char const EmotesEntryfmt[] = "nxxiiixx";
char const EmotesTextEntryfmt[] = "nxixxxxxxxxxxxxxxxx";
-char const FactionEntryfmt[] = "niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx";
+char const FactionEntryfmt[] = "niiiiiiiiiiiiiiiiiiffixsxi";
char const FactionTemplateEntryfmt[] = "niiiiiiiiiiiii";
-char const GameObjectDisplayInfofmt[] = "nsxxxxxxxxxxffffffx";
-char const GemPropertiesEntryfmt[] = "nixxi";
+char const GameObjectDisplayInfofmt[] = "nsxxxxxxxxxxffffffxxx";
+char const GemPropertiesEntryfmt[] = "nixxii";
char const GlyphPropertiesfmt[] = "niii";
char const GlyphSlotfmt[] = "nii";
-char const GtBarberShopCostBasefmt[] = "f";
-char const GtCombatRatingsfmt[] = "f";
-char const GtChanceToMeleeCritBasefmt[] = "f";
-char const GtChanceToMeleeCritfmt[] = "f";
-char const GtChanceToSpellCritBasefmt[] = "f";
-char const GtChanceToSpellCritfmt[] = "f";
-char const GtNPCManaCostScalerfmt[] = "f";
+char const GtBarberShopCostBasefmt[] = "xf";
+char const GtCombatRatingsfmt[] = "xf";
+char const GtOCTHpPerStaminafmt[] = "df";
+char const GtChanceToMeleeCritBasefmt[] = "xf";
+char const GtChanceToMeleeCritfmt[] = "xf";
+char const GtChanceToSpellCritBasefmt[] = "xf";
+char const GtChanceToSpellCritfmt[] = "xf";
+char const GtNPCManaCostScalerfmt[] = "xf";
char const GtOCTClassCombatRatingScalarfmt[] = "df";
char const GtOCTRegenHPfmt[] = "f";
//char const GtOCTRegenMPfmt[] = "f";
-char const GtRegenHPPerSptfmt[] = "f";
-char const GtRegenMPPerSptfmt[] = "f";
+char const GtRegenMPPerSptfmt[] = "xf";
+char const GtSpellScalingfmt[] = "df";
+char const GtOCTBaseHPByClassfmt[] = "df";
+char const GtOCTBaseMPByClassfmt[] = "df";
+char const GuildPerkSpellsfmt[] = "dii";
char const Holidaysfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiixxsiix";
-char const Itemfmt[] = "niiiiiii";
-char const ItemBagFamilyfmt[] = "nxxxxxxxxxxxxxxxxx";
+char const ImportPriceArmorfmt[] = "nffff";
+char const ImportPriceQualityfmt[] = "nf";
+char const ImportPriceShieldfmt[] = "nf";
+char const ImportPriceWeaponfmt[] = "nf";
+char const ItemPriceBasefmt[] = "diff";
+char const ItemReforgefmt[] = "nifif";
+char const ItemBagFamilyfmt[] = "nx";
+char const ItemArmorQualityfmt[] = "nfffffffi";
+char const ItemArmorShieldfmt[] = "nifffffff";
+char const ItemArmorTotalfmt[] = "niffff";
+char const ItemClassfmt[] = "dixxfx";
+char const ItemDamagefmt[] = "nfffffffi";
+char const ItemDisenchantLootfmt[] = "niiiiii";
//char const ItemDisplayTemplateEntryfmt[] = "nxxxxxxxxxxixxxxxxxxxxx";
-//char const ItemCondExtCostsEntryfmt[] = "xiii";
-char const ItemExtendedCostEntryfmt[] = "niiiiiiiiiiiiiix";
-char const ItemLimitCategoryEntryfmt[] = "nxxxxxxxxxxxxxxxxxii";
-char const ItemRandomPropertiesfmt[] = "nxiiixxssssssssssssssssx";
-char const ItemRandomSuffixfmt[] = "nssssssssssssssssxxiiixxiiixx";
-char const ItemSetEntryfmt[] = "dssssssssssssssssxiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii";
-char const LFGDungeonEntryfmt[] = "nssssssssssssssssxiiiiiiiiixxixixxxxxxxxxxxxxxxxx";
+char const ItemLimitCategoryEntryfmt[] = "nxii";
+char const ItemRandomPropertiesfmt[] = "nxiiixxs";
+char const ItemRandomSuffixfmt[] = "nsxiiiiiiiiii";
+char const ItemSetEntryfmt[] = "dsiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii";
+char const LFGDungeonEntryfmt[] = "nsiiiiiiiiixxixixixxx";
char const LightEntryfmt[] = "nifffxxxxxxxxxx";
char const LiquidTypefmt[] = "nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const LockEntryfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx";
-char const MailTemplateEntryfmt[] = "nxxxxxxxxxxxxxxxxxssssssssssssssssx";
-char const MapEntryfmt[] = "nxiixssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxiii";
-char const MapDifficultyEntryfmt[] = "diisxxxxxxxxxxxxxxxxiix";
-char const MovieEntryfmt[] = "nxx";
-char const OverrideSpellDatafmt[] = "niiiiiiiiiix";
+char const PhaseEntryfmt[] = "nsi";
+char const PhaseGroupfmt[] = "nii";
+char const MailTemplateEntryfmt[] = "nxs";
+char const MapEntryfmt[] = "nxiixxsixxixiffxiiii";
+char const MapDifficultyEntryfmt[] = "diisiix";
+char const MovieEntryfmt[] = "nxxx";
+char const MountCapabilityfmt[] = "niiiiiii";
+char const MountTypefmt[] = "niiiiiiiiiiiiiiiiiiiiiiii";
+char const NameGenfmt[] = "dsii";
+char const NumTalentsAtLevelfmt[] = "df";
+char const OverrideSpellDatafmt[] = "niiiiiiiiiixx";
char const QuestFactionRewardfmt[] = "niiiiiiiiii";
-char const QuestSortEntryfmt[] = "nxxxxxxxxxxxxxxxxx";
+char const QuestSortEntryfmt[] = "nx";
char const QuestXPfmt[] = "niiiiiiiiii";
char const PowerDisplayfmt[] = "nixxxx";
char const PvPDifficultyfmt[] = "diiiii";
char const RandomPropertiesPointsfmt[] = "niiiiiiiiiiiiiii";
-char const ScalingStatDistributionfmt[] = "niiiiiiiiiiiiiiiiiiiii";
-char const ScalingStatValuesfmt[] = "iniiiiiiiiiiiiiiiiiiiiii";
-char const SkillLinefmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi";
-char const SkillLineAbilityfmt[] = "niiiixxiiiiixx";
-char const SkillRaceClassInfofmt[] = "diiiixix";
+char const ScalingStatDistributionfmt[] = "niiiiiiiiiiiiiiiiiiiixi";
+char const ScalingStatValuesfmt[] = "iniiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii";
+char const SkillLinefmt[] = "nisxixi";
+char const SkillLineAbilityfmt[] = "niiiixxiiiiiii";
+char const SkillRaceClassInfofmt[] = "diiiixxix";
char const SkillTiersfmt[] = "nxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiii";
-char const SoundEntriesfmt[] = "nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+char const SoundEntriesfmt[] = "nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const SpellCastTimefmt[] = "nixx";
-char const SpellCategoryfmt[] = "ni";
+char const SpellCategoriesEntryfmt[] = "diiiiii";
+char const SpellCategoryfmt[] = "nixx";
char const SpellDifficultyfmt[] = "niiii";
const std::string CustomSpellDifficultyfmt = "ppppp";
const std::string CustomSpellDifficultyIndex = "id";
char const SpellDurationfmt[] = "niii";
-char const SpellEntryfmt[] = "niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx";
-const std::string CustomSpellEntryfmt = "papppppppppppapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa";
+// 0 10 20 26
+char const SpellEffectEntryfmt[] = "nifiiiffiiiiiifiifiiiiiiiix";
+const std::string CustomSpellEffectEntryfmt = "ppppppppppapppappppppppppp";
+const std::string CustomSpellEffectEntryIndex = "Id";
+// 0 10 20 30 40 47
+char const SpellEntryfmt[] = "niiiiiiiiiiiiiiifiiiissxxiixxifiiiiiiixiiiiiiiix";
+const std::string CustomSpellEntryfmt = "ppppppppppppppapaaaaaaaaapaaaaaapapppaapppaaapa";
const std::string CustomSpellEntryIndex = "Id";
-char const SpellFocusObjectfmt[] = "nxxxxxxxxxxxxxxxxx";
-char const SpellItemEnchantmentfmt[] = "nxiiiiiixxxiiissssssssssssssssxiiiiiii";
+char const SpellFocusObjectfmt[] = "nx";
+char const SpellItemEnchantmentfmt[] = "nxiiiiiixxxiiisiiiiiiix";
char const SpellItemEnchantmentConditionfmt[] = "nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";
char const SpellRadiusfmt[] = "nfff";
-char const SpellRangefmt[] = "nffffixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+char const SpellRangefmt[] = "nffffixx";
+char const SpellReagentsEntryfmt[] = "diiiiiiiiiiiiiiii";
+char const SpellScalingEntryfmt[] = "diiiiffffffffffi";
+char const SpellTotemsEntryfmt[] = "niiii";
+char const SpellTargetRestrictionsEntryfmt[] = "nxiiii";
+char const SpellPowerEntryfmt[] = "diiiiixf";
+char const SpellInterruptsEntryfmt[] = "dixixi";
+char const SpellEquippedItemsEntryfmt[] = "diii";
+char const SpellAuraOptionsEntryfmt[] = "niiii";
+char const SpellAuraRestrictionsEntryfmt[] = "diiiiiiii";
+char const SpellCastingRequirementsEntryfmt[] = "dixxixi";
+char const SpellClassOptionsEntryfmt[] = "dxiiiix";
+char const SpellCooldownsEntryfmt[] = "diii";
+char const SpellLevelsEntryfmt[] = "diii";
char const SpellRuneCostfmt[] = "niiii";
-char const SpellShapeshiftfmt[] = "nxxxxxxxxxxxxxxxxxxiixiiixxiiiiiiii";
+char const SpellShapeshiftEntryfmt[] = "nixixx";
+char const SpellShapeshiftFormfmt[] = "nxxiixiiixxiiiiiiiixx";
char const StableSlotPricesfmt[] = "ni";
char const SummonPropertiesfmt[] = "niiiii";
-char const TalentEntryfmt[] = "niiiiiiiixxxxixxixxxxxx";
-char const TalentTabEntryfmt[] = "nxxxxxxxxxxxxxxxxxxxiiix";
-char const TaxiNodesEntryfmt[] = "nifffssssssssssssssssxii";
+char const TalentEntryfmt[] = "niiiiiiiiixxixxxxxx";
+char const TalentTabEntryfmt[] = "nxxiiixxxii";
+char const TalentTreePrimarySpellsfmt[] = "diix";
+char const TaxiNodesEntryfmt[] = "nifffsiiixx";
char const TaxiPathEntryfmt[] = "niii";
char const TaxiPathNodeEntryfmt[] = "diiifffiiii";
-char const TeamContributionPointsfmt[] = "df";
-char const TotemCategoryEntryfmt[] = "nxxxxxxxxxxxxxxxxxii";
+char const TotemCategoryEntryfmt[] = "nxii";
+char const UnitPowerBarfmt[] = "niixxxxxxxxxxxxxxxxxxxxxxxx";
char const TransportAnimationfmt[] = "diifffx";
char const TransportRotationfmt[] = "diiffff";
char const VehicleEntryfmt[] = "niffffiiiiiiiifffffffffffffffssssfifiixx";
-char const VehicleSeatEntryfmt[] = "niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx";
-char const WMOAreaTableEntryfmt[] = "niiixxxxxiixxxxxxxxxxxxxxxxx";
-char const WorldMapAreaEntryfmt[] = "xinxffffixx";
-char const WorldMapOverlayEntryfmt[] = "nxiiiixxxxxxxxxxx";
-char const WorldSafeLocsEntryfmt[] = "nifffxxxxxxxxxxxxxxxxx";
+char const VehicleSeatEntryfmt[] = "niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxxxxxxxxxx";
+char const WMOAreaTableEntryfmt[] = "niiixxxxxiixxxx";
+char const WorldMapAreaEntryfmt[] = "xinxffffixxxxx";
+char const WorldMapOverlayEntryfmt[] = "nxiiiixxxxxxxxx";
+char const WorldSafeLocsEntryfmt[] = "nifffx";
#endif
diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h
index 0030dfa6c4b..efafd5d3afd 100644
--- a/src/server/game/DungeonFinding/LFG.h
+++ b/src/server/game/DungeonFinding/LFG.h
@@ -44,17 +44,21 @@ enum LfgUpdateType
LFG_UPDATETYPE_DEFAULT = 0, // Internal Use
LFG_UPDATETYPE_LEADER_UNK1 = 1, // FIXME: At group leave
LFG_UPDATETYPE_ROLECHECK_ABORTED = 4,
- LFG_UPDATETYPE_JOIN_QUEUE = 5,
- LFG_UPDATETYPE_ROLECHECK_FAILED = 6,
- LFG_UPDATETYPE_REMOVED_FROM_QUEUE = 7,
- LFG_UPDATETYPE_PROPOSAL_FAILED = 8,
- LFG_UPDATETYPE_PROPOSAL_DECLINED = 9,
- LFG_UPDATETYPE_GROUP_FOUND = 10,
- LFG_UPDATETYPE_ADDED_TO_QUEUE = 12,
- LFG_UPDATETYPE_PROPOSAL_BEGIN = 13,
- LFG_UPDATETYPE_UPDATE_STATUS = 14,
- LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE = 15,
- LFG_UPDATETYPE_GROUP_DISBAND_UNK16 = 16, // FIXME: Sometimes at group disband
+ LFG_UPDATETYPE_JOIN_QUEUE = 6,
+ LFG_UPDATETYPE_ROLECHECK_FAILED = 7,
+ LFG_UPDATETYPE_REMOVED_FROM_QUEUE = 8,
+ LFG_UPDATETYPE_PROPOSAL_FAILED = 9,
+ LFG_UPDATETYPE_PROPOSAL_DECLINED = 10,
+ LFG_UPDATETYPE_GROUP_FOUND = 11,
+ LFG_UPDATETYPE_ADDED_TO_QUEUE = 13,
+ LFG_UPDATETYPE_PROPOSAL_BEGIN = 14,
+ LFG_UPDATETYPE_UPDATE_STATUS = 15,
+ LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE = 16,
+ LFG_UPDATETYPE_GROUP_DISBAND_UNK16 = 17, // FIXME: Sometimes at group disband
+ LFG_UPDATETYPE_JOIN_QUEUE_INITIAL = 24,
+ LFG_UPDATETYPE_DUNGEON_FINISHED = 25,
+ LFG_UPDATETYPE_PARTY_ROLE_NOT_AVAILABLE = 43,
+ LFG_UPDATETYPE_JOIN_LFG_OBJECT_FAILED = 45,
};
enum LfgState
@@ -94,8 +98,18 @@ enum LfgAnswer
LFG_ANSWER_AGREE = 1
};
+struct LfgLockInfoData
+{
+ LfgLockInfoData(uint32 _lockStatus = 0, uint16 _requiredItemLevel = 0, float _currentItemLevel = 0) :
+ lockStatus(_lockStatus), requiredItemLevel(_requiredItemLevel), currentItemLevel(_currentItemLevel) { }
+
+ uint32 lockStatus;
+ uint16 requiredItemLevel;
+ float currentItemLevel;
+};
+
typedef std::set<uint32> LfgDungeonSet;
-typedef std::map<uint32, uint32> LfgLockMap;
+typedef std::map<uint32, LfgLockInfoData> LfgLockMap;
typedef std::map<uint64, LfgLockMap> LfgLockPartyMap;
typedef std::set<uint64> LfgGuidSet;
typedef std::list<uint64> LfgGuidList;
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 076ac7982ec..0efc7fd6230 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -194,11 +194,10 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */)
}
// Fill teleport locations from DB
- QueryResult result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation FROM lfg_entrances");
-
+ QueryResult result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation, requiredItemLevel FROM lfg_dungeon_template");
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 lfg entrance positions. DB table `lfg_entrances` is empty!");
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 lfg dungeon templates. DB table `lfg_dungeon_template` is empty!");
return;
}
@@ -215,17 +214,18 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */)
continue;
}
- LFGDungeonData& data = dungeonItr->second;
- data.x = fields[1].GetFloat();
- data.y = fields[2].GetFloat();
- data.z = fields[3].GetFloat();
- data.o = fields[4].GetFloat();
+ LFGDungeonData& data = dungeonItr->second;
+ data.x = fields[1].GetFloat();
+ data.y = fields[2].GetFloat();
+ data.z = fields[3].GetFloat();
+ data.o = fields[4].GetFloat();
+ data.requiredItemLevel = fields[5].GetUInt16();
++count;
}
while (result->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded %u lfg entrance positions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded %u lfg dungeon templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
// Fill all other teleport coords from areatriggers
for (LFGDungeonContainer::iterator itr = LfgDungeonStore.begin(); itr != LfgDungeonStore.end(); ++itr)
@@ -235,10 +235,10 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */)
// No teleport coords in database, load from areatriggers
if (dungeon.type != LFG_TYPE_RANDOM && dungeon.x == 0.0f && dungeon.y == 0.0f && dungeon.z == 0.0f)
{
- AreaTrigger const* at = sObjectMgr->GetMapEntranceTrigger(dungeon.map);
+ AreaTriggerStruct const* at = sObjectMgr->GetMapEntranceTrigger(dungeon.map);
if (!at)
{
- TC_LOG_ERROR("sql.sql", "Failed to load dungeon %s, cant find areatrigger for map %u", dungeon.name.c_str(), dungeon.map);
+ TC_LOG_ERROR("sql.sql", "Failed to load dungeon %s (Id: %u), cant find areatrigger for map %u", dungeon.name.c_str(), dungeon.id, dungeon.map);
continue;
}
@@ -255,9 +255,7 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */)
}
if (reload)
- {
CachedDungeonMapStore.clear();
- }
}
void LFGMgr::Update(uint32 diff)
@@ -282,7 +280,7 @@ void LFGMgr::Update(uint32 diff)
RestoreState(guid, "Remove Obsolete RoleCheck");
SendLfgRoleCheckUpdate(guid, roleCheck);
if (guid == roleCheck.leader)
- SendLfgJoinResult(guid, LfgJoinResultData(LFG_JOIN_FAILED, LFG_ROLECHECK_MISSING_ROLE));
+ SendLfgJoinResult(guid, LfgJoinResultData(LFG_JOIN_ROLE_CHECK_FAILED, LFG_ROLECHECK_MISSING_ROLE));
}
RestoreState(itRoleCheck->first, "Remove Obsolete RoleCheck");
@@ -339,10 +337,10 @@ void LFGMgr::Update(uint32 diff)
if (uint64 gguid = GetGroup(guid))
{
SetState(gguid, LFG_STATE_PROPOSAL);
- SendLfgUpdateParty(guid, LfgUpdateData(LFG_UPDATETYPE_PROPOSAL_BEGIN, GetSelectedDungeons(guid), GetComment(guid)));
+ SendLfgUpdateStatus(guid, LfgUpdateData(LFG_UPDATETYPE_PROPOSAL_BEGIN, GetSelectedDungeons(guid), GetComment(guid)), true);
}
else
- SendLfgUpdatePlayer(guid, LfgUpdateData(LFG_UPDATETYPE_PROPOSAL_BEGIN, GetSelectedDungeons(guid), GetComment(guid)));
+ SendLfgUpdateStatus(guid, LfgUpdateData(LFG_UPDATETYPE_PROPOSAL_BEGIN, GetSelectedDungeons(guid), GetComment(guid)), false);
SendLfgUpdateProposal(guid, proposal);
}
@@ -356,7 +354,7 @@ void LFGMgr::Update(uint32 diff)
{
m_QueueTimer = 0;
for (LfgQueueContainer::iterator it = QueuesStore.begin(); it != QueuesStore.end(); ++it)
- it->second.UpdateQueueTimers(currTime);
+ it->second.UpdateQueueTimers(it->first, currTime);
}
else
m_QueueTimer += diff;
@@ -423,7 +421,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
if (Player* plrg = itr->GetSource())
{
if (!plrg->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER))
- joinData.result = LFG_JOIN_PARTY_NOT_MEET_REQS;
+ joinData.result = LFG_JOIN_INTERNAL_ERROR;
if (plrg->HasAura(LFG_SPELL_DUNGEON_DESERTER))
joinData.result = LFG_JOIN_PARTY_DESERTER;
else if (plrg->HasAura(LFG_SPELL_DUNGEON_COOLDOWN))
@@ -485,7 +483,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
// if we have lockmap then there are no compatible dungeons
GetCompatibleDungeons(dungeons, players, joinData.lockmap);
if (dungeons.empty())
- joinData.result = grp ? LFG_JOIN_PARTY_NOT_MEET_REQS : LFG_JOIN_NOT_MEET_REQS;
+ joinData.result = grp ? LFG_JOIN_INTERNAL_ERROR : LFG_JOIN_NOT_MEET_REQS;
}
}
@@ -534,7 +532,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
if (Player* plrg = itr->GetSource())
{
uint64 pguid = plrg->GetGUID();
- plrg->GetSession()->SendLfgUpdateParty(updateData);
+ plrg->GetSession()->SendLfgUpdateStatus(updateData, true);
SetState(pguid, LFG_STATE_ROLECHECK);
if (!isContinue)
SetSelectedDungeons(pguid, dungeons);
@@ -565,7 +563,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
}
// Send update to player
player->GetSession()->SendLfgJoinResult(joinData);
- player->GetSession()->SendLfgUpdatePlayer(LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE, dungeons, comment));
+ player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE, dungeons, comment), false);
SetState(gguid, LFG_STATE_QUEUED);
SetRoles(guid, roles);
debugNames.append(player->GetName());
@@ -600,14 +598,14 @@ void LFGMgr::LeaveLfg(uint64 guid)
for (LfgGuidSet::const_iterator it = players.begin(); it != players.end(); ++it)
{
SetState(*it, LFG_STATE_NONE);
- SendLfgUpdateParty(*it, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE));
+ SendLfgUpdateStatus(*it, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE), true);
}
}
else
{
LFGQueue& queue = GetQueue(guid);
queue.RemoveFromQueue(guid);
- SendLfgUpdatePlayer(guid, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE));
+ SendLfgUpdateStatus(guid, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE), false);
SetState(guid, LFG_STATE_NONE);
}
break;
@@ -696,7 +694,11 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /*
else
dungeons = roleCheck.dungeons;
- LfgJoinResultData joinData = LfgJoinResultData(LFG_JOIN_FAILED, roleCheck.state);
+ LfgJoinResult joinResult = LFG_JOIN_FAILED;
+ if (roleCheck.state == LFG_ROLECHECK_MISSING_ROLE || roleCheck.state == LFG_ROLECHECK_WRONG_ROLES)
+ joinResult = LFG_JOIN_ROLE_CHECK_FAILED;
+
+ LfgJoinResultData joinData = LfgJoinResultData(joinResult, roleCheck.state);
for (LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it)
{
uint64 pguid = it->first;
@@ -712,12 +714,12 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /*
case LFG_ROLECHECK_FINISHED:
SetState(pguid, LFG_STATE_QUEUED);
SetRoles(pguid, it->second);
- SendLfgUpdateParty(pguid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, dungeons, GetComment(pguid)));
+ SendLfgUpdateStatus(pguid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, dungeons, GetComment(pguid)), true);
break;
default:
if (roleCheck.leader == pguid)
SendLfgJoinResult(pguid, joinData);
- SendLfgUpdateParty(pguid, LfgUpdateData(LFG_UPDATETYPE_ROLECHECK_FAILED));
+ SendLfgUpdateStatus(pguid, LfgUpdateData(LFG_UPDATETYPE_ROLECHECK_FAILED), true);
RestoreState(pguid, "Rolecheck Failed");
break;
}
@@ -982,16 +984,16 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept)
if (gguid)
{
waitTime = int32((joinTime - queue.GetJoinTime(gguid)) / IN_MILLISECONDS);
- SendLfgUpdateParty(pguid, updateData);
+ SendLfgUpdateStatus(pguid, updateData, false);
}
else
{
waitTime = int32((joinTime - queue.GetJoinTime(pguid)) / IN_MILLISECONDS);
- SendLfgUpdatePlayer(pguid, updateData);
+ SendLfgUpdateStatus(pguid, updateData, false);
}
updateData.updateType = LFG_UPDATETYPE_REMOVED_FROM_QUEUE;
- SendLfgUpdatePlayer(pguid, updateData);
- SendLfgUpdateParty(pguid, updateData);
+ SendLfgUpdateStatus(pguid, updateData, true);
+ SendLfgUpdateStatus(pguid, updateData, false);
// Update timers
uint8 role = GetRoles(pguid);
@@ -1083,10 +1085,10 @@ void LFGMgr::RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdate
if (gguid != guid)
{
RestoreState(it->second.group, "Proposal Fail (someone in group didn't accepted)");
- SendLfgUpdateParty(guid, updateData);
+ SendLfgUpdateStatus(guid, updateData, true);
}
else
- SendLfgUpdatePlayer(guid, updateData);
+ SendLfgUpdateStatus(guid, updateData, false);
}
else
{
@@ -1095,10 +1097,10 @@ void LFGMgr::RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdate
if (gguid != guid)
{
SetState(gguid, LFG_STATE_QUEUED);
- SendLfgUpdateParty(guid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid)));
+ SendLfgUpdateStatus(guid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid)), true);
}
else
- SendLfgUpdatePlayer(guid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid)));
+ SendLfgUpdateStatus(guid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid)), false);
}
}
@@ -1559,39 +1561,39 @@ LfgLockMap const LFGMgr::GetLockedDungeons(uint64 guid)
if (!dungeon) // should never happen - We provide a list from sLFGDungeonStore
continue;
- uint32 lockData = 0;
+ uint32 lockStatus = 0;
if (denyJoin)
- lockData = LFG_LOCKSTATUS_RAID_LOCKED;
+ lockStatus = LFG_LOCKSTATUS_RAID_LOCKED;
else if (dungeon->expansion > expansion)
- lockData = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION;
+ lockStatus = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION;
else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player))
- lockData = LFG_LOCKSTATUS_RAID_LOCKED;
+ lockStatus = LFG_LOCKSTATUS_RAID_LOCKED;
else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty)))
- lockData = LFG_LOCKSTATUS_RAID_LOCKED;
+ lockStatus = LFG_LOCKSTATUS_RAID_LOCKED;
else if (dungeon->minlevel > level)
- lockData = LFG_LOCKSTATUS_TOO_LOW_LEVEL;
+ lockStatus = LFG_LOCKSTATUS_TOO_LOW_LEVEL;
else if (dungeon->maxlevel < level)
- lockData = LFG_LOCKSTATUS_TOO_HIGH_LEVEL;
+ lockStatus = LFG_LOCKSTATUS_TOO_HIGH_LEVEL;
else if (dungeon->seasonal && !IsSeasonActive(dungeon->id))
- lockData = LFG_LOCKSTATUS_NOT_IN_SEASON;
+ lockStatus = LFG_LOCKSTATUS_NOT_IN_SEASON;
+ else if (dungeon->requiredItemLevel > player->GetAverageItemLevel())
+ lockStatus = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE;
else if (AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty)))
{
- if (ar->item_level && player->GetAverageItemLevel() < ar->item_level)
- lockData = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE;
- else if (ar->achievement && !player->HasAchieved(ar->achievement))
- lockData = LFG_LOCKSTATUS_MISSING_ACHIEVEMENT;
+ if (ar->achievement && !player->HasAchieved(ar->achievement))
+ lockStatus = LFG_LOCKSTATUS_MISSING_ACHIEVEMENT;
else if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A))
- lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED;
+ lockStatus = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED;
else if (player->GetTeam() == HORDE && ar->quest_H && !player->GetQuestRewardStatus(ar->quest_H))
- lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED;
+ lockStatus = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED;
else
if (ar->item)
{
if (!player->HasItemCount(ar->item) && (!ar->item2 || !player->HasItemCount(ar->item2)))
- lockData = LFG_LOCKSTATUS_MISSING_ITEM;
+ lockStatus = LFG_LOCKSTATUS_MISSING_ITEM;
}
else if (ar->item2 && !player->HasItemCount(ar->item2))
- lockData = LFG_LOCKSTATUS_MISSING_ITEM;
+ lockStatus = LFG_LOCKSTATUS_MISSING_ITEM;
}
/* @todo VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED)
@@ -1600,8 +1602,8 @@ LfgLockMap const LFGMgr::GetLockedDungeons(uint64 guid)
lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL;
*/
- if (lockData)
- lock[dungeon->Entry()] = lockData;
+ if (lockStatus)
+ lock[dungeon->Entry()] = LfgLockInfoData(lockStatus, dungeon->requiredItemLevel, player->GetAverageItemLevel());
}
return lock;
@@ -1712,7 +1714,7 @@ void LFGMgr::RemoveGroupData(uint64 guid)
if (state != LFG_STATE_PROPOSAL)
{
SetState(playerGUID, LFG_STATE_NONE);
- SendLfgUpdateParty(playerGUID, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE));
+ SendLfgUpdateStatus(playerGUID, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE), true);
}
}
GroupsStore.erase(it);
@@ -1794,16 +1796,10 @@ void LFGMgr::SendLfgRoleCheckUpdate(uint64 guid, LfgRoleCheck const& roleCheck)
player->GetSession()->SendLfgRoleCheckUpdate(roleCheck);
}
-void LFGMgr::SendLfgUpdatePlayer(uint64 guid, LfgUpdateData const& data)
-{
- if (Player* player = ObjectAccessor::FindPlayer(guid))
- player->GetSession()->SendLfgUpdatePlayer(data);
-}
-
-void LFGMgr::SendLfgUpdateParty(uint64 guid, LfgUpdateData const& data)
+void LFGMgr::SendLfgUpdateStatus(uint64 guid, LfgUpdateData const& data, bool party)
{
if (Player* player = ObjectAccessor::FindPlayer(guid))
- player->GetSession()->SendLfgUpdateParty(data);
+ player->GetSession()->SendLfgUpdateStatus(data, party);
}
void LFGMgr::SendLfgJoinResult(uint64 guid, LfgJoinResultData const& data)
@@ -1835,18 +1831,22 @@ bool LFGMgr::IsLfgGroup(uint64 guid)
return guid && IS_GROUP_GUID(guid) && GroupsStore[guid].IsLfgGroup();
}
-LFGQueue& LFGMgr::GetQueue(uint64 guid)
+uint8 LFGMgr::GetQueueId(uint64 guid)
{
- uint8 queueId = 0;
if (IS_GROUP_GUID(guid))
{
LfgGuidSet const& players = GetPlayers(guid);
uint64 pguid = players.empty() ? 0 : (*players.begin());
if (pguid)
- queueId = GetTeam(pguid);
+ return GetTeam(pguid);
}
- else
- queueId = GetTeam(guid);
+
+ return GetTeam(guid);
+}
+
+LFGQueue& LFGMgr::GetQueue(uint64 guid)
+{
+ uint8 queueId = GetQueueId(guid);
return QueuesStore[queueId];
}
@@ -1861,6 +1861,16 @@ bool LFGMgr::AllQueued(LfgGuidList const& check)
return true;
}
+time_t LFGMgr::GetQueueJoinTime(uint64 guid)
+{
+ uint8 queueId = GetQueueId(guid);
+ LfgQueueContainer::const_iterator itr = QueuesStore.find(queueId);
+ if (itr != QueuesStore.end())
+ return itr->second.GetJoinTime(guid);
+
+ return 0;
+}
+
// Only for debugging purposes
void LFGMgr::Clean()
{
diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h
index 547d026dee0..b04b4f1a7ab 100644
--- a/src/server/game/DungeonFinding/LFGMgr.h
+++ b/src/server/game/DungeonFinding/LFGMgr.h
@@ -93,23 +93,24 @@ enum LfgTeleportError
enum LfgJoinResult
{
// 3 = No client reaction | 18 = "Rolecheck failed"
- LFG_JOIN_OK = 0, // Joined (no client msg)
- LFG_JOIN_FAILED = 1, // RoleCheck Failed
- LFG_JOIN_GROUPFULL = 2, // Your group is full
- LFG_JOIN_INTERNAL_ERROR = 4, // Internal LFG Error
- LFG_JOIN_NOT_MEET_REQS = 5, // You do not meet the requirements for the chosen dungeons
- LFG_JOIN_PARTY_NOT_MEET_REQS = 6, // One or more party members do not meet the requirements for the chosen dungeons
- LFG_JOIN_MIXED_RAID_DUNGEON = 7, // You cannot mix dungeons, raids, and random when picking dungeons
- LFG_JOIN_MULTI_REALM = 8, // The dungeon you chose does not support players from multiple realms
- LFG_JOIN_DISCONNECTED = 9, // One or more party members are pending invites or disconnected
- LFG_JOIN_PARTY_INFO_FAILED = 10, // Could not retrieve information about some party members
- LFG_JOIN_DUNGEON_INVALID = 11, // One or more dungeons was not valid
- LFG_JOIN_DESERTER = 12, // You can not queue for dungeons until your deserter debuff wears off
- LFG_JOIN_PARTY_DESERTER = 13, // One or more party members has a deserter debuff
- LFG_JOIN_RANDOM_COOLDOWN = 14, // You can not queue for random dungeons while on random dungeon cooldown
- LFG_JOIN_PARTY_RANDOM_COOLDOWN = 15, // One or more party members are on random dungeon cooldown
- LFG_JOIN_TOO_MUCH_MEMBERS = 16, // You can not enter dungeons with more that 5 party members
- LFG_JOIN_USING_BG_SYSTEM = 17 // You can not use the dungeon system while in BG or arenas
+ LFG_JOIN_OK = 0x00, // Joined (no client msg)
+ LFG_JOIN_FAILED = 0x1B, // RoleCheck Failed
+ LFG_JOIN_GROUPFULL = 0x1C, // Your group is full
+ LFG_JOIN_INTERNAL_ERROR = 0x1E, // Internal LFG Error
+ LFG_JOIN_NOT_MEET_REQS = 0x1F, // You do not meet the requirements for the chosen dungeons
+ //LFG_JOIN_PARTY_NOT_MEET_REQS = 6, // One or more party members do not meet the requirements for the chosen dungeons
+ LFG_JOIN_MIXED_RAID_DUNGEON = 0x20, // You cannot mix dungeons, raids, and random when picking dungeons
+ LFG_JOIN_MULTI_REALM = 0x21, // The dungeon you chose does not support players from multiple realms
+ LFG_JOIN_DISCONNECTED = 0x22, // One or more party members are pending invites or disconnected
+ LFG_JOIN_PARTY_INFO_FAILED = 0x23, // Could not retrieve information about some party members
+ LFG_JOIN_DUNGEON_INVALID = 0x24, // One or more dungeons was not valid
+ LFG_JOIN_DESERTER = 0x25, // You can not queue for dungeons until your deserter debuff wears off
+ LFG_JOIN_PARTY_DESERTER = 0x26, // One or more party members has a deserter debuff
+ LFG_JOIN_RANDOM_COOLDOWN = 0x27, // You can not queue for random dungeons while on random dungeon cooldown
+ LFG_JOIN_PARTY_RANDOM_COOLDOWN = 0x28, // One or more party members are on random dungeon cooldown
+ LFG_JOIN_TOO_MUCH_MEMBERS = 0x29, // You can not enter dungeons with more that 5 party members
+ LFG_JOIN_USING_BG_SYSTEM = 0x2A, // You can not use the dungeon system while in BG or arenas
+ LFG_JOIN_ROLE_CHECK_FAILED = 0x2B // Role check failed, client shows special error
};
/// Role check states
@@ -156,7 +157,7 @@ struct LfgJoinResultData
LfgLockPartyMap lockmap;
};
-// Data needed by SMSG_LFG_UPDATE_PARTY and SMSG_LFG_UPDATE_PLAYER
+// Data needed by SMSG_LFG_UPDATE_STATUS
struct LfgUpdateData
{
LfgUpdateData(LfgUpdateType _type = LFG_UPDATETYPE_DEFAULT): updateType(_type), state(LFG_STATE_NONE), comment("") { }
@@ -174,12 +175,14 @@ struct LfgUpdateData
// Data needed by SMSG_LFG_QUEUE_STATUS
struct LfgQueueStatusData
{
- LfgQueueStatusData(uint32 _dungeonId = 0, int32 _waitTime = -1, int32 _waitTimeAvg = -1, int32 _waitTimeTank = -1, int32 _waitTimeHealer = -1,
+ LfgQueueStatusData(uint8 _queueId = 0, uint32 _dungeonId = 0, time_t _joinTime = 0, int32 _waitTime = -1, int32 _waitTimeAvg = -1, int32 _waitTimeTank = -1, int32 _waitTimeHealer = -1,
int32 _waitTimeDps = -1, uint32 _queuedTime = 0, uint8 _tanks = 0, uint8 _healers = 0, uint8 _dps = 0) :
- dungeonId(_dungeonId), waitTime(_waitTime), waitTimeAvg(_waitTimeAvg), waitTimeTank(_waitTimeTank), waitTimeHealer(_waitTimeHealer),
- waitTimeDps(_waitTimeDps), queuedTime(_queuedTime), tanks(_tanks), healers(_healers), dps(_dps) { }
+ queueId(_queueId), dungeonId(_dungeonId), joinTime(_joinTime), waitTime(_waitTime), waitTimeAvg(_waitTimeAvg), waitTimeTank(_waitTimeTank),
+ waitTimeHealer(_waitTimeHealer), waitTimeDps(_waitTimeDps), queuedTime(_queuedTime), tanks(_tanks), healers(_healers), dps(_dps) { }
+ uint8 queueId;
uint32 dungeonId;
+ time_t joinTime;
int32 waitTime;
int32 waitTimeAvg;
int32 waitTimeTank;
@@ -265,12 +268,14 @@ struct LfgPlayerBoot
struct LFGDungeonData
{
LFGDungeonData(): id(0), name(""), map(0), type(0), expansion(0), group(0), minlevel(0),
- maxlevel(0), difficulty(REGULAR_DIFFICULTY), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f)
+ maxlevel(0), difficulty(REGULAR_DIFFICULTY), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f),
+ requiredItemLevel(0)
{ }
- LFGDungeonData(LFGDungeonEntry const* dbc): id(dbc->ID), name(dbc->name[0]), map(dbc->map),
+ LFGDungeonData(LFGDungeonEntry const* dbc): id(dbc->ID), name(dbc->name), map(dbc->map),
type(dbc->type), expansion(dbc->expansion), group(dbc->grouptype),
minlevel(dbc->minlevel), maxlevel(dbc->maxlevel), difficulty(Difficulty(dbc->difficulty)),
- seasonal((dbc->flags & LFG_FLAG_SEASONAL) != 0), x(0.0f), y(0.0f), z(0.0f), o(0.0f)
+ seasonal((dbc->flags & LFG_FLAG_SEASONAL) != 0), x(0.0f), y(0.0f), z(0.0f), o(0.0f),
+ requiredItemLevel(0)
{ }
uint32 id;
@@ -284,6 +289,7 @@ struct LFGDungeonData
Difficulty difficulty;
bool seasonal;
float x, y, z, o;
+ uint16 requiredItemLevel;
// Helpers
uint32 Entry() const { return id + (type << 24); }
@@ -408,8 +414,12 @@ class LFGMgr
uint8 GetPlayerCount(uint64 guid);
/// Add a new Proposal
uint32 AddProposal(LfgProposal& proposal);
+ /// Returns queue id
+ uint8 GetQueueId(uint64 guid);
/// Checks if all players are queued
bool AllQueued(LfgGuidList const& check);
+ /// Gets queue join time
+ time_t GetQueueJoinTime(uint64 guid);
/// Checks if given roles match, modifies given roles map with new roles
static bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true);
/// Checks if given players are ignoring each other
@@ -435,7 +445,8 @@ class LFGMgr
void MakeNewGroup(LfgProposal const& proposal);
// Generic
- LFGQueue &GetQueue(uint64 guid);
+ LFGQueue& GetQueue(uint64 guid);
+
LfgDungeonSet const& GetDungeonsByRandom(uint32 randomdungeon);
LfgType GetDungeonType(uint32 dungeon);
@@ -443,8 +454,7 @@ class LFGMgr
void SendLfgJoinResult(uint64 guid, LfgJoinResultData const& data);
void SendLfgRoleChosen(uint64 guid, uint64 pguid, uint8 roles);
void SendLfgRoleCheckUpdate(uint64 guid, LfgRoleCheck const& roleCheck);
- void SendLfgUpdateParty(uint64 guid, LfgUpdateData const& data);
- void SendLfgUpdatePlayer(uint64 guid, LfgUpdateData const& data);
+ void SendLfgUpdateStatus(uint64 guid, LfgUpdateData const& data, bool party);
void SendLfgUpdateProposal(uint64 guid, LfgProposal const& proposal);
LfgGuidSet const& GetPlayers(uint64 guid);
diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp
index 67a9f0afc69..a44c7780c6b 100644
--- a/src/server/game/DungeonFinding/LFGQueue.cpp
+++ b/src/server/game/DungeonFinding/LFGQueue.cpp
@@ -537,7 +537,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(LfgGuidList check)
return LFG_COMPATIBLES_MATCH;
}
-void LFGQueue::UpdateQueueTimers(time_t currTime)
+void LFGQueue::UpdateQueueTimers(uint8 queueId, time_t currTime)
{
TC_LOG_TRACE("lfg.queue.timers.update", "Updating queue timers...");
for (LfgQueueDataContainer::iterator itQueue = QueueDataStore.begin(); itQueue != QueueDataStore.end(); ++itQueue)
@@ -578,7 +578,7 @@ void LFGQueue::UpdateQueueTimers(time_t currTime)
if (queueinfo.bestCompatible.empty())
FindBestCompatibleInQueue(itQueue);
- LfgQueueStatusData queueData(dungeonId, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps);
+ LfgQueueStatusData queueData(queueId, dungeonId, queueinfo.joinTime, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps);
for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer)
{
uint64 pguid = itPlayer->first;
@@ -587,9 +587,13 @@ void LFGQueue::UpdateQueueTimers(time_t currTime)
}
}
-time_t LFGQueue::GetJoinTime(uint64 guid)
+time_t LFGQueue::GetJoinTime(uint64 guid) const
{
- return QueueDataStore[guid].joinTime;
+ LfgQueueDataContainer::const_iterator itr = QueueDataStore.find(guid);
+ if (itr != QueueDataStore.end())
+ return itr->second.joinTime;
+
+ return 0;
}
std::string LFGQueue::DumpQueueInfo() const
diff --git a/src/server/game/DungeonFinding/LFGQueue.h b/src/server/game/DungeonFinding/LFGQueue.h
index b66121802c6..0312c926991 100644
--- a/src/server/game/DungeonFinding/LFGQueue.h
+++ b/src/server/game/DungeonFinding/LFGQueue.h
@@ -100,8 +100,8 @@ class LFGQueue
void UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId);
// Update Queue timers
- void UpdateQueueTimers(time_t currTime);
- time_t GetJoinTime(uint64 guid);
+ void UpdateQueueTimers(uint8 queueId, time_t currTime);
+ time_t GetJoinTime(uint64 guid) const;
// Find new group
uint8 FindGroups();
diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp
index 181e04e04fc..6a38afb398d 100644
--- a/src/server/game/DungeonFinding/LFGScripts.cpp
+++ b/src/server/game/DungeonFinding/LFGScripts.cpp
@@ -177,7 +177,7 @@ void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod meth
//else if (state == LFG_STATE_BOOT)
// Update internal kick cooldown of kicked
- player->GetSession()->SendLfgUpdateParty(LfgUpdateData(LFG_UPDATETYPE_LEADER_UNK1));
+ player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(LFG_UPDATETYPE_LEADER_UNK1), true);
if (isLFG && player->GetMap()->IsDungeon()) // Teleport player out the dungeon
sLFGMgr->TeleportPlayer(player, true);
}
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
new file mode 100644
index 00000000000..599f486b949
--- /dev/null
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectAccessor.h"
+#include "Unit.h"
+#include "SpellInfo.h"
+#include "Log.h"
+#include "AreaTrigger.h"
+
+AreaTrigger::AreaTrigger() : WorldObject(false), _duration(0)
+{
+ m_objectType |= TYPEMASK_AREATRIGGER;
+ m_objectTypeId = TYPEID_AREATRIGGER;
+
+ m_updateFlag = UPDATEFLAG_STATIONARY_POSITION;
+
+ m_valuesCount = AREATRIGGER_END;
+}
+
+AreaTrigger::~AreaTrigger()
+{
+}
+
+void AreaTrigger::AddToWorld()
+{
+ ///- Register the AreaTrigger for guid lookup and for caster
+ if (!IsInWorld())
+ {
+ sObjectAccessor->AddObject(this);
+ WorldObject::AddToWorld();
+ }
+}
+
+void AreaTrigger::RemoveFromWorld()
+{
+ ///- Remove the AreaTrigger from the accessor and from all lists of objects in world
+ if (IsInWorld())
+ {
+ WorldObject::RemoveFromWorld();
+ sObjectAccessor->RemoveObject(this);
+ }
+}
+
+bool AreaTrigger::CreateAreaTrigger(uint32 guidlow, uint32 triggerEntry, Unit* caster, SpellInfo const* spell, Position const& pos)
+{
+ SetMap(caster->GetMap());
+ Relocate(pos);
+ if (!IsPositionValid())
+ {
+ TC_LOG_ERROR("misc", "AreaTrigger (spell %u) not created. Invalid coordinates (X: %f Y: %f)", spell->Id, GetPositionX(), GetPositionY());
+ return false;
+ }
+
+ WorldObject::_Create(guidlow, HIGHGUID_AREATRIGGER, caster->GetPhaseMask());
+
+ SetEntry(triggerEntry);
+ SetDuration(spell->GetDuration());
+ SetObjectScale(1);
+
+ SetUInt32Value(AREATRIGGER_SPELLID, spell->Id);
+ SetUInt32Value(AREATRIGGER_SPELLVISUALID, spell->SpellVisual[0]);
+ SetUInt32Value(AREATRIGGER_DURATION, spell->GetDuration());
+ SetFloatValue(AREATRIGGER_FINAL_POS + 0, pos.GetPositionX());
+ SetFloatValue(AREATRIGGER_FINAL_POS + 1, pos.GetPositionY());
+ SetFloatValue(AREATRIGGER_FINAL_POS + 2, pos.GetPositionZ());
+
+ for (auto phase : caster->GetPhases())
+ SetInPhase(phase, false, true);
+
+ if (!GetMap()->AddToMap(this))
+ return false;
+
+ return true;
+}
+
+void AreaTrigger::Update(uint32 p_time)
+{
+ if (GetDuration() > int32(p_time))
+ _duration -= p_time;
+ else
+ Remove(); // expired
+
+ WorldObject::Update(p_time);
+}
+
+void AreaTrigger::Remove()
+{
+ if (IsInWorld())
+ {
+ SendObjectDeSpawnAnim(GetGUID());
+ RemoveFromWorld();
+ AddObjectToRemoveList();
+ }
+}
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.h b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
new file mode 100644
index 00000000000..cbfa4405b0e
--- /dev/null
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITYCORE_AREATRIGGER_H
+#define TRINITYCORE_AREATRIGGER_H
+
+#include "Object.h"
+
+class Unit;
+class SpellInfo;
+
+class AreaTrigger : public WorldObject, public GridObject<AreaTrigger>
+{
+ public:
+ AreaTrigger();
+ ~AreaTrigger();
+
+ void AddToWorld();
+ void RemoveFromWorld();
+
+ bool CreateAreaTrigger(uint32 guidlow, uint32 triggerEntry, Unit* caster, SpellInfo const* spell, Position const& pos);
+ void Update(uint32 p_time);
+ void Remove();
+ uint32 GetSpellId() const { return GetUInt32Value(AREATRIGGER_SPELLID); }
+ int32 GetDuration() const { return _duration; }
+ void SetDuration(int32 newDuration) { _duration = newDuration; }
+ void Delay(int32 delaytime) { SetDuration(GetDuration() - delaytime); }
+
+ protected:
+ int32 _duration;
+};
+#endif
diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp
index e41426edb3d..9c50cec6ab8 100644
--- a/src/server/game/Entities/Corpse/Corpse.cpp
+++ b/src/server/game/Entities/Corpse/Corpse.cpp
@@ -31,7 +31,7 @@ Corpse::Corpse(CorpseType type) : WorldObject(type != CORPSE_BONES), m_type(type
m_objectType |= TYPEMASK_CORPSE;
m_objectTypeId = TYPEID_CORPSE;
- m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_POSITION);
+ m_updateFlag = UPDATEFLAG_STATIONARY_POSITION;
m_valuesCount = CORPSE_END;
@@ -114,7 +114,6 @@ void Corpse::SaveToDB()
stmt->setString(index++, _ConcatFields(CORPSE_FIELD_ITEM, EQUIPMENT_SLOT_END)); // itemCache
stmt->setUInt32(index++, GetUInt32Value(CORPSE_FIELD_BYTES_1)); // bytes1
stmt->setUInt32(index++, GetUInt32Value(CORPSE_FIELD_BYTES_2)); // bytes2
- stmt->setUInt32(index++, GetUInt32Value(CORPSE_FIELD_GUILD)); // guildId
stmt->setUInt8 (index++, GetUInt32Value(CORPSE_FIELD_FLAGS)); // flags
stmt->setUInt8 (index++, GetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS)); // dynFlags
stmt->setUInt32(index++, uint32(m_time)); // time
@@ -160,10 +159,10 @@ void Corpse::DeleteFromDB(SQLTransaction& trans)
bool Corpse::LoadCorpseFromDB(uint32 guid, Field* fields)
{
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0
- uint32 ownerGuid = fields[17].GetUInt32();
+ uint32 ownerGuid = fields[16].GetUInt32();
float posX = fields[0].GetFloat();
float posY = fields[1].GetFloat();
float posZ = fields[2].GetFloat();
@@ -176,20 +175,18 @@ bool Corpse::LoadCorpseFromDB(uint32 guid, Field* fields)
_LoadIntoDataField(fields[6].GetCString(), CORPSE_FIELD_ITEM, EQUIPMENT_SLOT_END);
SetUInt32Value(CORPSE_FIELD_BYTES_1, fields[7].GetUInt32());
SetUInt32Value(CORPSE_FIELD_BYTES_2, fields[8].GetUInt32());
- SetUInt32Value(CORPSE_FIELD_GUILD, fields[9].GetUInt32());
- SetUInt32Value(CORPSE_FIELD_FLAGS, fields[10].GetUInt8());
- SetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS, fields[11].GetUInt8());
+ SetUInt32Value(CORPSE_FIELD_FLAGS, fields[9].GetUInt8());
+ SetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS, fields[10].GetUInt8());
SetUInt64Value(CORPSE_FIELD_OWNER, MAKE_NEW_GUID(ownerGuid, 0, HIGHGUID_PLAYER));
- m_time = time_t(fields[12].GetUInt32());
+ m_time = time_t(fields[11].GetUInt32());
- uint32 instanceId = fields[14].GetUInt32();
- uint32 phaseMask = fields[15].GetUInt32();
+ uint32 instanceId = fields[13].GetUInt32();
+ //uint32 phaseMask = fields[14].GetUInt32();
// place
SetLocationInstanceId(instanceId);
SetLocationMapId(mapId);
- SetPhaseMask(phaseMask, false);
Relocate(posX, posY, posZ, o);
if (!IsPositionValid())
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 52f3a87e7bb..992894a1a3c 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -63,12 +63,12 @@ TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
return NULL;
}
-bool VendorItemData::RemoveItem(uint32 item_id)
+bool VendorItemData::RemoveItem(uint32 item_id, uint8 type)
{
bool found = false;
for (VendorItemList::iterator i = m_items.begin(); i != m_items.end();)
{
- if ((*i)->item == item_id)
+ if ((*i)->item == item_id && (*i)->Type == type)
{
i = m_items.erase(i++);
found = true;
@@ -79,10 +79,10 @@ bool VendorItemData::RemoveItem(uint32 item_id)
return found;
}
-VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint32 extendedCost) const
+VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint32 extendedCost, uint8 type) const
{
for (VendorItemList::const_iterator i = m_items.begin(); i != m_items.end(); ++i)
- if ((*i)->item == item_id && (*i)->ExtendedCost == extendedCost)
+ if ((*i)->item == item_id && (*i)->ExtendedCost == extendedCost && (*i)->Type == type)
return *i;
return NULL;
}
@@ -332,6 +332,7 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
SetName(normalInfo->Name); // at normal entry always
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
+ SetFloatValue(UNIT_MOD_CAST_HASTE, 1.0f);
SetSpeed(MOVE_WALK, cinfo->speed_walk);
SetSpeed(MOVE_RUN, cinfo->speed_run);
@@ -613,13 +614,10 @@ void Creature::RegenerateMana()
// Combat and any controlled creature
if (IsInCombat() || GetCharmerOrOwnerGUID())
{
- if (!IsUnderLastManaUseEffect())
- {
- float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA);
- float Spirit = GetStat(STAT_SPIRIT);
+ float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA);
+ float Spirit = GetStat(STAT_SPIRIT);
- addvalue = uint32((Spirit / 5.0f + 17.0f) * ManaIncreaseRate);
- }
+ addvalue = uint32((Spirit / 5.0f + 17.0f) * ManaIncreaseRate);
}
else
addvalue = maxValue / 3;
@@ -745,11 +743,17 @@ void Creature::Motion_Initialize()
GetMotionMaster()->Initialize();
}
-bool Creature::Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 entry, float x, float y, float z, float ang, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/)
+bool Creature::Create(uint32 guidlow, Map* map, uint32 /*phaseMask*/, uint32 entry, float x, float y, float z, float ang, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/)
{
ASSERT(map);
SetMap(map);
- SetPhaseMask(phaseMask, false);
+
+ if (data && data->phaseid)
+ SetInPhase(data->phaseid, false, true);
+
+ if (data && data->phaseGroup)
+ for (auto ph : GetPhasesForGroup(data->phaseGroup))
+ SetInPhase(ph, false, true);
CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
if (!cinfo)
@@ -1070,12 +1074,21 @@ void Creature::SelectLevel()
// mana
uint32 mana = stats->GenerateMana(cInfo);
-
SetCreateMana(mana);
- SetMaxPower(POWER_MANA, mana); // MAX Mana
- SetPower(POWER_MANA, mana);
- /// @todo set UNIT_FIELD_POWER*, for some creature class case (energy, etc)
+ switch (getClass())
+ {
+ case CLASS_WARRIOR:
+ setPowerType(POWER_RAGE);
+ break;
+ case CLASS_ROGUE:
+ setPowerType(POWER_ENERGY);
+ break;
+ default:
+ SetMaxPower(POWER_MANA, mana); // MAX Mana
+ SetPower(POWER_MANA, mana);
+ break;
+ }
SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana);
@@ -1503,8 +1516,6 @@ void Creature::setDeathState(DeathState s)
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
LoadCreaturesAddon(true);
Motion_Initialize();
- if (GetCreatureData() && GetPhaseMask() != GetCreatureData()->phaseMask)
- SetPhaseMask(GetCreatureData()->phaseMask, false);
Unit::setDeathState(ALIVE);
}
}
@@ -1682,7 +1693,7 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim)
if (bcontinue)
continue;
- if (spellInfo->ManaCost > GetPower(POWER_MANA))
+ if (spellInfo->ManaCost > (uint32)GetPower(POWER_MANA))
continue;
float range = spellInfo->GetMaxRange(false);
float minrange = spellInfo->GetMinRange(false);
@@ -1726,7 +1737,7 @@ SpellInfo const* Creature::reachWithSpellCure(Unit* victim)
if (bcontinue)
continue;
- if (spellInfo->ManaCost > GetPower(POWER_MANA))
+ if (spellInfo->ManaCost > (uint32)GetPower(POWER_MANA))
continue;
float range = spellInfo->GetMaxRange(true);
@@ -2137,11 +2148,6 @@ void Creature::SetInCombatWithZone()
}
}
-uint32 Creature::GetShieldBlockValue() const //dunno mob block value
-{
- return (getLevel()/2 + uint32(GetStat(STAT_STRENGTH)/20));
-}
-
void Creature::_AddCreatureSpellCooldown(uint32 spell_id, time_t end_time)
{
m_CreatureSpellCooldowns[spell_id] = end_time;
@@ -2454,110 +2460,6 @@ bool Creature::IsDungeonBoss() const
return cinfo && (cinfo->flags_extra & CREATURE_FLAG_EXTRA_DUNGEON_BOSS);
}
-bool Creature::SetWalk(bool enable)
-{
- if (!Unit::SetWalk(enable))
- return false;
-
- WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_WALK_MODE : SMSG_SPLINE_MOVE_SET_RUN_MODE, 9);
- data.append(GetPackGUID());
- SendMessageToSet(&data, false);
- return true;
-}
-
-bool Creature::SetDisableGravity(bool disable, bool packetOnly/*=false*/)
-{
- //! It's possible only a packet is sent but moveflags are not updated
- //! Need more research on this
- if (!packetOnly && !Unit::SetDisableGravity(disable))
- return false;
-
- if (!movespline->Initialized())
- return true;
-
- WorldPacket data(disable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
- data.append(GetPackGUID());
- SendMessageToSet(&data, false);
- return true;
-}
-
-bool Creature::SetSwim(bool enable)
-{
- if (!Unit::SetSwim(enable))
- return false;
-
- if (!movespline->Initialized())
- return true;
-
- WorldPacket data(enable ? SMSG_SPLINE_MOVE_START_SWIM : SMSG_SPLINE_MOVE_STOP_SWIM);
- data.append(GetPackGUID());
- SendMessageToSet(&data, true);
- return true;
-}
-
-bool Creature::SetCanFly(bool enable)
-{
- if (!Unit::SetCanFly(enable))
- return false;
-
- if (!movespline->Initialized())
- return true;
-
- WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_FLYING : SMSG_SPLINE_MOVE_UNSET_FLYING, 9);
- data.append(GetPackGUID());
- SendMessageToSet(&data, false);
- return true;
-}
-
-bool Creature::SetWaterWalking(bool enable, bool packetOnly /* = false */)
-{
- if (!packetOnly && !Unit::SetWaterWalking(enable))
- return false;
-
- if (!movespline->Initialized())
- return true;
-
- WorldPacket data(enable ? SMSG_SPLINE_MOVE_WATER_WALK : SMSG_SPLINE_MOVE_LAND_WALK);
- data.append(GetPackGUID());
- SendMessageToSet(&data, true);
- return true;
-}
-
-bool Creature::SetFeatherFall(bool enable, bool packetOnly /* = false */)
-{
- if (!packetOnly && !Unit::SetFeatherFall(enable))
- return false;
-
- if (!movespline->Initialized())
- return true;
-
- WorldPacket data(enable ? SMSG_SPLINE_MOVE_FEATHER_FALL : SMSG_SPLINE_MOVE_NORMAL_FALL);
- data.append(GetPackGUID());
- SendMessageToSet(&data, true);
- return true;
-}
-
-bool Creature::SetHover(bool enable, bool packetOnly /*= false*/)
-{
- if (!packetOnly && !Unit::SetHover(enable))
- return false;
-
- //! Unconfirmed for players:
- if (enable)
- SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_HOVER);
- else
- RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_HOVER);
-
- if (!movespline->Initialized())
- return true;
-
- //! Not always a packet is sent
- WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_HOVER : SMSG_SPLINE_MOVE_UNSET_HOVER, 9);
- data.append(GetPackGUID());
- SendMessageToSet(&data, false);
- return true;
-}
-
float Creature::GetAggroRange(Unit const* target) const
{
// Determines the aggro range for creatures (usually pets), used mainly for aggressive pet target selection.
@@ -2649,7 +2551,7 @@ void Creature::UpdateMovementFlags()
}
if (!isInAir)
- RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING);
+ SetFall(false);
SetSwim(GetCreatureTemplate()->InhabitType & INHABIT_WATER && IsInWater());
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 8ba5fdcb6fb..f5a0abfc469 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -39,22 +39,23 @@ class WorldSession;
enum CreatureFlagsExtra
{
- CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group
- CREATURE_FLAG_EXTRA_CIVILIAN = 0x00000002, // not aggro (ignore faction/reputation hostility)
- CREATURE_FLAG_EXTRA_NO_PARRY = 0x00000004, // creature can't parry
- CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN = 0x00000008, // creature can't counter-attack at parry
- CREATURE_FLAG_EXTRA_NO_BLOCK = 0x00000010, // creature can't block
- CREATURE_FLAG_EXTRA_NO_CRUSH = 0x00000020, // creature can't do crush attacks
- CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP
- CREATURE_FLAG_EXTRA_TRIGGER = 0x00000080, // trigger creature
- CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00000100, // creature is immune to taunt auras and effect attack me
- CREATURE_FLAG_EXTRA_WORLDEVENT = 0x00004000, // custom flag for world event creatures (left room for merging)
- CREATURE_FLAG_EXTRA_GUARD = 0x00008000, // Creature is guard
- CREATURE_FLAG_EXTRA_NO_CRIT = 0x00020000, // creature can't do critical strikes
- CREATURE_FLAG_EXTRA_NO_SKILLGAIN = 0x00040000, // creature won't increase weapon skills
- CREATURE_FLAG_EXTRA_TAUNT_DIMINISH = 0x00080000, // Taunt is a subject to diminishing returns on this creautre
- CREATURE_FLAG_EXTRA_ALL_DIMINISH = 0x00100000, // Creature is subject to all diminishing returns as player are
- CREATURE_FLAG_EXTRA_DUNGEON_BOSS = 0x10000000 // creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)
+ CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group
+ CREATURE_FLAG_EXTRA_CIVILIAN = 0x00000002, // not aggro (ignore faction/reputation hostility)
+ CREATURE_FLAG_EXTRA_NO_PARRY = 0x00000004, // creature can't parry
+ CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN = 0x00000008, // creature can't counter-attack at parry
+ CREATURE_FLAG_EXTRA_NO_BLOCK = 0x00000010, // creature can't block
+ CREATURE_FLAG_EXTRA_NO_CRUSH = 0x00000020, // creature can't do crush attacks
+ CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP
+ CREATURE_FLAG_EXTRA_TRIGGER = 0x00000080, // trigger creature
+ CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00000100, // creature is immune to taunt auras and effect attack me
+ CREATURE_FLAG_EXTRA_WORLDEVENT = 0x00004000, // custom flag for world event creatures (left room for merging)
+ CREATURE_FLAG_EXTRA_GUARD = 0x00008000, // Creature is guard
+ CREATURE_FLAG_EXTRA_NO_CRIT = 0x00020000, // creature can't do critical strikes
+ CREATURE_FLAG_EXTRA_NO_SKILLGAIN = 0x00040000, // creature won't increase weapon skills
+ CREATURE_FLAG_EXTRA_TAUNT_DIMINISH = 0x00080000, // Taunt is a subject to diminishing returns on this creautre
+ CREATURE_FLAG_EXTRA_ALL_DIMINISH = 0x00100000, // Creature is subject to all diminishing returns as player are
+ CREATURE_FLAG_EXTRA_DUNGEON_BOSS = 0x10000000, // creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)
+ CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING = 0x20000000 // creature ignore pathfinding
};
#define CREATURE_FLAG_EXTRA_DB_ALLOWED (CREATURE_FLAG_EXTRA_INSTANCE_BIND | CREATURE_FLAG_EXTRA_CIVILIAN | \
@@ -62,7 +63,7 @@ enum CreatureFlagsExtra
CREATURE_FLAG_EXTRA_NO_CRUSH | CREATURE_FLAG_EXTRA_NO_XP_AT_KILL | CREATURE_FLAG_EXTRA_TRIGGER | \
CREATURE_FLAG_EXTRA_NO_TAUNT | CREATURE_FLAG_EXTRA_WORLDEVENT | CREATURE_FLAG_EXTRA_NO_CRIT | \
CREATURE_FLAG_EXTRA_NO_SKILLGAIN | CREATURE_FLAG_EXTRA_TAUNT_DIMINISH | CREATURE_FLAG_EXTRA_ALL_DIMINISH | \
- CREATURE_FLAG_EXTRA_GUARD)
+ CREATURE_FLAG_EXTRA_GUARD | CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING)
#define MAX_KILL_CREDIT 2
#define CREATURE_REGEN_INTERVAL 2 * IN_MILLISECONDS
@@ -82,12 +83,14 @@ struct CreatureTemplate
uint32 Modelid3;
uint32 Modelid4;
std::string Name;
+ std::string FemaleName;
std::string SubName;
std::string IconName;
uint32 GossipMenuId;
uint8 minlevel;
uint8 maxlevel;
uint32 expansion;
+ uint32 expansionUnknown; // either 0 or 3, sent to the client / wdb
uint32 faction;
uint32 npcflag;
float speed_walk;
@@ -107,7 +110,6 @@ struct CreatureTemplate
uint32 dynamicflags;
uint32 family; // enum CreatureFamily values (optional)
uint32 trainer_type;
- uint32 trainer_spell;
uint32 trainer_class;
uint32 trainer_race;
float minrangedmg;
@@ -115,6 +117,7 @@ struct CreatureTemplate
uint32 rangedattackpower;
uint32 type; // enum CreatureType values
uint32 type_flags; // enum CreatureTypeFlags mask values
+ uint32 type_flags2; // unknown enum, only set for 4 creatures (with value 1)
uint32 lootid;
uint32 pickpocketLootId;
uint32 SkinLootId;
@@ -130,6 +133,7 @@ struct CreatureTemplate
float HoverHeight;
float ModHealth;
float ModMana;
+ float ModManaExtra; // Added in 4.x, this value is usually 2 for a small group of creatures with double mana
float ModArmor;
bool RacialLeader;
uint32 questItems[MAX_CREATURE_QUEST_ITEMS];
@@ -202,7 +206,7 @@ struct CreatureBaseStats
if (!BaseMana)
return 0;
- return uint32(ceil(BaseMana * info->ModMana));
+ return uint32(ceil(BaseMana * info->ModMana * info->ModManaExtra));
}
uint32 GenerateArmor(CreatureTemplate const* info) const
@@ -223,6 +227,7 @@ typedef std::unordered_map<uint16, CreatureBaseStats> CreatureBaseStatsContainer
struct CreatureLocale
{
StringVector Name;
+ StringVector FemaleName;
StringVector SubName;
};
@@ -252,7 +257,7 @@ struct CreatureData
CreatureData() : id(0), mapid(0), phaseMask(0), displayid(0), equipmentId(0),
posX(0.0f), posY(0.0f), posZ(0.0f), orientation(0.0f), spawntimesecs(0),
spawndist(0.0f), currentwaypoint(0), curhealth(0), curmana(0), movementType(0),
- spawnMask(0), npcflag(0), unit_flags(0), dynamicflags(0), dbData(true) { }
+ spawnMask(0), npcflag(0), unit_flags(0), dynamicflags(0), phaseid(0), phaseGroup(0), dbData(true) { }
uint32 id; // entry in creature_template
uint16 mapid;
uint32 phaseMask;
@@ -272,6 +277,8 @@ struct CreatureData
uint32 npcflag;
uint32 unit_flags; // enum UnitFlags mask values
uint32 dynamicflags;
+ uint32 phaseid;
+ uint32 phaseGroup;
bool dbData;
};
@@ -330,13 +337,14 @@ typedef std::unordered_map<uint32, CreatureAddon> CreatureAddonContainer;
// Vendors
struct VendorItem
{
- VendorItem(uint32 _item, int32 _maxcount, uint32 _incrtime, uint32 _ExtendedCost)
- : item(_item), maxcount(_maxcount), incrtime(_incrtime), ExtendedCost(_ExtendedCost) { }
+ VendorItem(uint32 _item, int32 _maxcount, uint32 _incrtime, uint32 _ExtendedCost, uint8 _Type)
+ : item(_item), maxcount(_maxcount), incrtime(_incrtime), ExtendedCost(_ExtendedCost), Type(_Type) { }
uint32 item;
uint32 maxcount; // 0 for infinity item amount
uint32 incrtime; // time for restore items amount if maxcount != 0
uint32 ExtendedCost;
+ uint8 Type;
//helpers
bool IsGoldRequired(ItemTemplate const* pProto) const { return pProto->Flags2 & ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD || !ExtendedCost; }
@@ -355,13 +363,13 @@ struct VendorItemData
return m_items[slot];
}
bool Empty() const { return m_items.empty(); }
- uint8 GetItemCount() const { return m_items.size(); }
- void AddItem(uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost)
+ uint32 GetItemCount() const { return m_items.size(); }
+ void AddItem(uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, uint8 type)
{
- m_items.push_back(new VendorItem(item, maxcount, ptime, ExtendedCost));
+ m_items.push_back(new VendorItem(item, maxcount, ptime, ExtendedCost, type));
}
- bool RemoveItem(uint32 item_id);
- VendorItem const* FindItemCostPair(uint32 item_id, uint32 extendedCost) const;
+ bool RemoveItem(uint32 item_id, uint8 type);
+ VendorItem const* FindItemCostPair(uint32 item_id, uint32 extendedCost, uint8 type) const;
void Clear()
{
for (VendorItemList::const_iterator itr = m_items.begin(); itr != m_items.end(); ++itr)
@@ -419,7 +427,7 @@ typedef std::map<uint32, time_t> CreatureSpellCooldowns;
// max different by z coordinate for creature aggro reaction
#define CREATURE_Z_ATTACK_RANGE 3
-#define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY
+#define MAX_VENDOR_ITEMS 150 // Limitation in 4.x.x item count in SMSG_LIST_INVENTORY
class Creature : public Unit, public GridObject<Creature>, public MapObject
{
@@ -481,16 +489,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
CreatureAI* AI() const { return (CreatureAI*)i_AI; }
- bool SetWalk(bool enable);
- bool SetDisableGravity(bool disable, bool packetOnly = false);
- bool SetSwim(bool enable);
- bool SetCanFly(bool enable);
- bool SetWaterWalking(bool enable, bool packetOnly = false);
- bool SetFeatherFall(bool enable, bool packetOnly = false);
- bool SetHover(bool enable, bool packetOnly = false);
-
- uint32 GetShieldBlockValue() const;
-
SpellSchoolMask GetMeleeDamageSchoolMask() const { return m_meleeDamageSchoolMask; }
void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); }
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index 492d82c5a03..9e72a124ae0 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -371,11 +371,11 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST NPC Guid=%u", GUID_LOPART(npcGUID));
}
-void PlayerMenu::SendQuestGiverStatus(uint8 questStatus, uint64 npcGUID) const
+void PlayerMenu::SendQuestGiverStatus(uint32 questStatus, uint64 npcGUID) const
{
- WorldPacket data(SMSG_QUESTGIVER_STATUS, 9);
+ WorldPacket data(SMSG_QUESTGIVER_STATUS, 8 + 4);
data << uint64(npcGUID);
- data << uint8(questStatus);
+ data << uint32(questStatus);
_session->SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u", GUID_LOPART(npcGUID), questStatus);
@@ -383,10 +383,14 @@ void PlayerMenu::SendQuestGiverStatus(uint8 questStatus, uint64 npcGUID) const
void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID, bool activateAccept) const
{
- std::string questTitle = quest->GetTitle();
- std::string questDetails = quest->GetDetails();
- std::string questObjectives = quest->GetObjectives();
- std::string questEndText = quest->GetEndText();
+ std::string questTitle = quest->GetTitle();
+ std::string questDetails = quest->GetDetails();
+ std::string questObjectives = quest->GetObjectives();
+ std::string questEndText = quest->GetEndText();
+ std::string questGiverTextWindow = quest->GetQuestGiverTextWindow();
+ std::string questGiverTargetName = quest->GetQuestGiverTargetName();
+ std::string questTurnTextWindow = quest->GetQuestTurnTextWindow();
+ std::string questTurnTargetName = quest->GetQuestTurnTargetName();
int32 locale = _session->GetSessionDbLocaleIndex();
if (locale >= 0)
@@ -397,6 +401,10 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID,
ObjectMgr::GetLocaleString(localeData->Details, locale, questDetails);
ObjectMgr::GetLocaleString(localeData->Objectives, locale, questObjectives);
ObjectMgr::GetLocaleString(localeData->EndText, locale, questEndText);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTextWindow, locale, questGiverTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTargetName, locale, questGiverTargetName);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTextWindow, locale, questTurnTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTargetName, locale, questTurnTargetName);
}
}
@@ -410,76 +418,23 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID,
data << questTitle;
data << questDetails;
data << questObjectives;
+ data << questGiverTextWindow; // 4.x
+ data << questGiverTargetName; // 4.x
+ data << questTurnTextWindow; // 4.x
+ data << questTurnTargetName; // 4.x
+ data << uint32(quest->GetQuestGiverPortrait()); // 4.x
+ data << uint32(quest->GetQuestTurnInPortrait()); // 4.x
data << uint8(activateAccept ? 1 : 0); // auto finish
data << uint32(quest->GetFlags()); // 3.3.3 questFlags
data << uint32(quest->GetSuggestedPlayers());
data << uint8(0); // IsFinished? value is sent back to server in quest accept packet
+ data << uint8(0); // 4.x FIXME: Starts at AreaTrigger
+ data << uint32(quest->GetRequiredSpell()); // 4.x
- if (quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
- {
- data << uint32(0); // Rewarded chosen items hidden
- data << uint32(0); // Rewarded items hidden
- data << uint32(0); // Rewarded money hidden
- data << uint32(0); // Rewarded XP hidden
- }
- else
- {
- data << uint32(quest->GetRewChoiceItemsCount());
- for (uint32 i=0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- {
- if (!quest->RewardChoiceItemId[i])
- continue;
-
- data << uint32(quest->RewardChoiceItemId[i]);
- data << uint32(quest->RewardChoiceItemCount[i]);
-
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[i]))
- data << uint32(itemTemplate->DisplayInfoID);
- else
- data << uint32(0x00);
- }
-
- data << uint32(quest->GetRewItemsCount());
-
- for (uint32 i=0; i < QUEST_REWARDS_COUNT; ++i)
- {
- if (!quest->RewardItemId[i])
- continue;
-
- data << uint32(quest->RewardItemId[i]);
- data << uint32(quest->RewardItemIdCount[i]);
-
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardItemId[i]))
- data << uint32(itemTemplate->DisplayInfoID);
- else
- data << uint32(0);
- }
-
- data << uint32(quest->GetRewOrReqMoney());
- data << uint32(quest->XPValue(_session->GetPlayer()) * sWorld->getRate(RATE_XP_QUEST));
- }
-
- // rewarded honor points. Multiply with 10 to satisfy client
- data << uint32(10 * quest->CalculateHonorGain(_session->GetPlayer()->GetQuestLevel(quest)));
- data << float(0.0f); // unk, honor multiplier?
- data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (cast if RewSpellCast == 0)
- data << int32(quest->GetRewSpellCast()); // cast spell
- data << uint32(quest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
- data << uint32(quest->GetBonusTalents()); // bonus talents
- data << uint32(quest->GetRewArenaPoints()); // reward arena points
- data << uint32(0); // unk
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- data << uint32(quest->RewardFactionId[i]);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- data << int32(quest->RewardFactionValueId[i]);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- data << int32(quest->RewardFactionValueIdOverride[i]);
+ quest->BuildExtraQuestInfo(data, _session->GetPlayer());
data << uint32(QUEST_EMOTE_COUNT);
- for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i)
+ for (uint8 i = 0; i < QUEST_EMOTE_COUNT; ++i)
{
data << uint32(quest->DetailsEmote[i]);
data << uint32(quest->DetailsEmoteDelay[i]); // DetailsEmoteDelay (in ms)
@@ -496,6 +451,10 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
std::string questObjectives = quest->GetObjectives();
std::string questEndText = quest->GetEndText();
std::string questCompletedText = quest->GetCompletedText();
+ std::string questGiverTextWindow = quest->GetQuestGiverTextWindow();
+ std::string questGiverTargetName = quest->GetQuestGiverTargetName();
+ std::string questTurnTextWindow = quest->GetQuestTurnTextWindow();
+ std::string questTurnTargetName = quest->GetQuestTurnTargetName();
std::string questObjectiveText[QUEST_OBJECTIVES_COUNT];
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
@@ -511,6 +470,10 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
ObjectMgr::GetLocaleString(localeData->Objectives, locale, questObjectives);
ObjectMgr::GetLocaleString(localeData->EndText, locale, questEndText);
ObjectMgr::GetLocaleString(localeData->CompletedText, locale, questCompletedText);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTextWindow, locale, questGiverTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTargetName, locale, questGiverTargetName);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTextWindow, locale, questTurnTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTargetName, locale, questTurnTargetName);
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ObjectMgr::GetLocaleString(localeData->ObjectiveText[i], locale, questObjectiveText[i]);
@@ -550,12 +513,17 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << uint32(quest->GetRewHonorAddition());
data << float(quest->GetRewHonorMultiplier());
data << uint32(quest->GetSrcItemId()); // source item id
- data << uint32(quest->GetFlags() & 0xFFFF); // quest flags
+ data << uint32(quest->GetFlags()); // quest flags
+ data << uint32(quest->GetMinimapTargetMark()); // minimap target mark (skull, etc. missing enum)
data << uint32(quest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
data << uint32(quest->GetPlayersSlain()); // players slain
data << uint32(quest->GetBonusTalents()); // bonus talents
- data << uint32(quest->GetRewArenaPoints()); // bonus arena points
- data << uint32(0); // review rep show mask
+ data << uint32(quest->GetRewArenaPoints()); // bonus arena points FIXME: arena points were removed, right?
+ data << uint32(quest->GetRewardSkillId()); // reward skill id
+ data << uint32(quest->GetRewardSkillPoints()); // reward skill points
+ data << uint32(quest->GetRewardReputationMask()); // rep mask (unsure on what it does)
+ data << uint32(quest->GetQuestGiverPortrait()); // quest giver entry ?
+ data << uint32(quest->GetQuestTurnInPortrait()); // quest turnin entry ?
if (quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
{
@@ -584,7 +552,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid+1 QuestFactionReward.dbc?
data << int32(quest->RewardFactionValueId[i]);
- for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // unk (0)
+ for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // unknown usage
data << int32(quest->RewardFactionValueIdOverride[i]);
data << uint32(quest->GetPointMapId());
@@ -599,7 +567,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << questObjectives;
data << questDetails;
data << questEndText;
- data << questCompletedText; // display in quest objectives window once all objectives are completed
+ data << questCompletedText;
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
{
@@ -610,7 +578,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << uint32(quest->RequiredNpcOrGoCount[i]);
data << uint32(quest->RequiredSourceItemId[i]);
- data << uint32(0); // req source count?
+ data << uint32(quest->RequiredSourceItemCount[i]);
}
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
@@ -619,9 +587,30 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << uint32(quest->RequiredItemCount[i]);
}
+ data << uint32(quest->GetRequiredSpell()); // Is it required to be cast, learned or what?
+
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
data << questObjectiveText[i];
+ for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ {
+ data << uint32(quest->RewardCurrencyId[i]);
+ data << uint32(quest->RewardCurrencyCount[i]);
+ }
+
+ for (uint32 i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ {
+ data << uint32(quest->RequiredCurrencyId[i]);
+ data << uint32(quest->RequiredCurrencyCount[i]);
+ }
+
+ data << questGiverTextWindow;
+ data << questGiverTargetName;
+ data << questTurnTextWindow;
+ data << questTurnTargetName;
+ data << uint32(quest->GetSoundAccept());
+ data << uint32(quest->GetSoundTurnIn());
+
_session->SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", quest->GetQuestId());
}
@@ -630,6 +619,10 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b
{
std::string questTitle = quest->GetTitle();
std::string questOfferRewardText = quest->GetOfferRewardText();
+ std::string questGiverTextWindow = quest->GetQuestGiverTextWindow();
+ std::string questGiverTargetName = quest->GetQuestGiverTargetName();
+ std::string questTurnTextWindow = quest->GetQuestTurnTextWindow();
+ std::string questTurnTargetName = quest->GetQuestTurnTargetName();
int32 locale = _session->GetSessionDbLocaleIndex();
if (locale >= 0)
@@ -638,6 +631,10 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b
{
ObjectMgr::GetLocaleString(localeData->Title, locale, questTitle);
ObjectMgr::GetLocaleString(localeData->OfferRewardText, locale, questOfferRewardText);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTextWindow, locale, questGiverTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestGiverTargetName, locale, questGiverTargetName);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTextWindow, locale, questTurnTextWindow);
+ ObjectMgr::GetLocaleString(localeData->QuestTurnTargetName, locale, questTurnTargetName);
}
}
@@ -650,6 +647,13 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b
data << questTitle;
data << questOfferRewardText;
+ data << questGiverTextWindow;
+ data << questGiverTargetName;
+ data << questTurnTextWindow;
+ data << questTurnTargetName;
+ data << uint32(quest->GetQuestGiverPortrait());
+ data << uint32(quest->GetQuestTurnInPortrait());
+
data << uint8(enableNext ? 1 : 0); // Auto Finish
data << uint32(quest->GetFlags()); // 3.3.3 questFlags
data << uint32(quest->GetSuggestedPlayers()); // SuggestedGroupNum
@@ -669,52 +673,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b
data << uint32(quest->OfferRewardEmote[i]);
}
- data << uint32(quest->GetRewChoiceItemsCount());
- for (uint32 i=0; i < quest->GetRewChoiceItemsCount(); ++i)
- {
- data << uint32(quest->RewardChoiceItemId[i]);
- data << uint32(quest->RewardChoiceItemCount[i]);
-
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[i]))
- data << uint32(itemTemplate->DisplayInfoID);
- else
- data << uint32(0);
- }
-
- data << uint32(quest->GetRewItemsCount());
- for (uint32 i = 0; i < quest->GetRewItemsCount(); ++i)
- {
- data << uint32(quest->RewardItemId[i]);
- data << uint32(quest->RewardItemIdCount[i]);
-
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardItemId[i]))
- data << uint32(itemTemplate->DisplayInfoID);
- else
- data << uint32(0);
- }
-
- data << uint32(quest->GetRewOrReqMoney());
- data << uint32(quest->XPValue(_session->GetPlayer()) * sWorld->getRate(RATE_XP_QUEST));
-
- // rewarded honor points. Multiply with 10 to satisfy client
- data << uint32(10 * quest->CalculateHonorGain(_session->GetPlayer()->GetQuestLevel(quest)));
- data << float(0.0f); // unk, honor multiplier?
- data << uint32(0x08); // unused by client?
- data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (cast if RewSpellCast == 0)
- data << int32(quest->GetRewSpellCast()); // cast spell
- data << uint32(0); // unknown
- data << uint32(quest->GetBonusTalents()); // bonus talents
- data << uint32(quest->GetRewArenaPoints()); // arena points
- data << uint32(0);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids
- data << uint32(quest->RewardFactionId[i]);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid in QuestFactionReward.dbc (zero based)?
- data << int32(quest->RewardFactionValueId[i]);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward reputation override?
- data << uint32(quest->RewardFactionValueIdOverride[i]);
+ quest->BuildExtraQuestInfo(data, _session->GetPlayer());
_session->SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), quest->GetQuestId());
@@ -784,14 +743,25 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, uint64 npcGUID,
data << uint32(0);
}
- if (!canComplete)
- data << uint32(0x00);
+ data << uint32(quest->GetReqCurrencyCount());
+ for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ {
+ if (!quest->RequiredCurrencyId[i])
+ continue;
+
+ data << uint32(quest->RequiredCurrencyId[i]);
+ data << uint32(quest->RequiredCurrencyCount[i]);
+ }
+
+ if (!canComplete) // Experimental; there are 6 similar flags, if any of them
+ data << uint32(0x00); // of them is 0 player can't complete quest (still unknown meaning)
else
- data << uint32(0x03);
+ data << uint32(0x02);
data << uint32(0x04);
data << uint32(0x08);
data << uint32(0x10);
+ data << uint32(0x40);
_session->SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), quest->GetQuestId());
diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h
index e8fac878409..6d42d7c33f7 100644
--- a/src/server/game/Entities/Creature/GossipDef.h
+++ b/src/server/game/Entities/Creature/GossipDef.h
@@ -274,7 +274,7 @@ class PlayerMenu
/*********************************************************/
/*** QUEST SYSTEM ***/
/*********************************************************/
- void SendQuestGiverStatus(uint8 questStatus, uint64 npcGUID) const;
+ void SendQuestGiverStatus(uint32 questStatus, uint64 npcGUID) const;
void SendQuestGiverQuestList(QEmote const& eEmote, const std::string& Title, uint64 npcGUID);
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index d31117c8381..b982de1289d 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.cpp
+++ b/src/server/game/Entities/Creature/TemporarySummon.cpp
@@ -196,7 +196,8 @@ void TempSummon::InitStats(uint32 duration)
if (owner)
{
- if (uint32 slot = m_Properties->Slot)
+ int32 slot = m_Properties->Slot;
+ if (slot > 0)
{
if (owner->m_SummonSlot[slot] && owner->m_SummonSlot[slot] != GetGUID())
{
@@ -268,10 +269,13 @@ void TempSummon::RemoveFromWorld()
return;
if (m_Properties)
- if (uint32 slot = m_Properties->Slot)
+ {
+ int32 slot = m_Properties->Slot;
+ if (slot > 0)
if (Unit* owner = GetSummoner())
if (owner->m_SummonSlot[slot] == GetGUID())
owner->m_SummonSlot[slot] = 0;
+ }
//if (GetOwnerGUID())
// TC_LOG_ERROR("entities.unit", "Unit %u has owner guid when removed from world", GetEntry());
@@ -285,6 +289,8 @@ Minion::Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorl
ASSERT(m_owner);
m_unitTypeMask |= UNIT_MASK_MINION;
m_followAngle = PET_FOLLOW_ANGLE;
+ /// @todo: Find correct way
+ InitCharmInfo();
}
void Minion::InitStats(uint32 duration)
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
index e008146bb85..00d555c5e9c 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
@@ -34,7 +34,7 @@ DynamicObject::DynamicObject(bool isWorldObject) : WorldObject(isWorldObject),
m_objectType |= TYPEMASK_DYNAMICOBJECT;
m_objectTypeId = TYPEID_DYNAMICOBJECT;
- m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_POSITION);
+ m_updateFlag = UPDATEFLAG_STATIONARY_POSITION;
m_valuesCount = DYNAMICOBJECT_END;
}
@@ -80,29 +80,23 @@ void DynamicObject::RemoveFromWorld()
}
}
-bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type)
+bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, SpellInfo const* spell, Position const& pos, float radius, DynamicObjectType type)
{
SetMap(caster->GetMap());
Relocate(pos);
if (!IsPositionValid())
{
- TC_LOG_ERROR("misc", "DynamicObject (spell %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", spellId, GetPositionX(), GetPositionY());
+ TC_LOG_ERROR("misc", "DynamicObject (spell %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", spell->Id, GetPositionX(), GetPositionY());
return false;
}
WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetPhaseMask());
- SetEntry(spellId);
+ SetEntry(spell->Id);
SetObjectScale(1);
SetUInt64Value(DYNAMICOBJECT_CASTER, caster->GetGUID());
-
- // The lower word of DYNAMICOBJECT_BYTES must be 0x0001. This value means that the visual radius will be overriden
- // by client for most of the "ground patch" visual effect spells and a few "skyfall" ones like Hurricane.
- // If any other value is used, the client will _always_ use the radius provided in DYNAMICOBJECT_RADIUS, but
- // precompensation is necessary (eg radius *= 2) for many spells. Anyway, blizz sends 0x0001 for all the spells
- // I saw sniffed...
- SetByteValue(DYNAMICOBJECT_BYTES, 0, type);
- SetUInt32Value(DYNAMICOBJECT_SPELLID, spellId);
+ SetUInt32Value(DYNAMICOBJECT_BYTES, spell->SpellVisual[0] | (type << 28));
+ SetUInt32Value(DYNAMICOBJECT_SPELLID, spell->Id);
SetFloatValue(DYNAMICOBJECT_RADIUS, radius);
SetUInt32Value(DYNAMICOBJECT_CASTTIME, getMSTime());
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h
index c9fd1d29f8b..ed9b5a3af68 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.h
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.h
@@ -41,7 +41,7 @@ class DynamicObject : public WorldObject, public GridObject<DynamicObject>, publ
void AddToWorld();
void RemoveFromWorld();
- bool CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type);
+ bool CreateDynamicObject(uint32 guidlow, Unit* caster, SpellInfo const* spell, Position const& pos, float radius, DynamicObjectType type);
void Update(uint32 p_time);
void Remove();
void SetDuration(int32 newDuration);
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 0f3e68bb1ae..90f46c4ad86 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -41,7 +41,7 @@ GameObject::GameObject() : WorldObject(false), MapObject(),
m_objectType |= TYPEMASK_GAMEOBJECT;
m_objectTypeId = TYPEID_GAMEOBJECT;
- m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_POSITION | UPDATEFLAG_ROTATION);
+ m_updateFlag = (UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION);
m_valuesCount = GAMEOBJECT_END;
m_respawnTime = 0;
@@ -167,7 +167,7 @@ void GameObject::RemoveFromWorld()
}
}
-bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, 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, GOState go_state, uint32 artKit)
{
ASSERT(map);
SetMap(map);
@@ -180,8 +180,6 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
return false;
}
- SetPhaseMask(phaseMask, false);
-
SetZoneScript();
if (m_zoneScript)
{
@@ -198,7 +196,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
}
if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT)
- m_updateFlag = (m_updateFlag | UPDATEFLAG_TRANSPORT) & ~UPDATEFLAG_POSITION;
+ m_updateFlag |= UPDATEFLAG_TRANSPORT;
Object::_Create(guidlow, goinfo->entry, HIGHGUID_GAMEOBJECT);
@@ -243,6 +241,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
m_goValue.Building.Health = goinfo->building.intactNumHits + goinfo->building.damagedNumHits;
m_goValue.Building.MaxHealth = m_goValue.Building.Health;
SetGoAnimProgress(255);
+ SetUInt32Value(GAMEOBJECT_PARENTROTATION, m_goInfo->building.destructibleData);
break;
case GAMEOBJECT_TYPE_TRANSPORT:
SetUInt32Value(GAMEOBJECT_LEVEL, goinfo->transport.pause);
@@ -354,7 +353,7 @@ void GameObject::Update(uint32 diff)
SetGoState(GO_STATE_ACTIVE);
SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN);
- UpdateData udata;
+ UpdateData udata(caster->GetMapId());
WorldPacket packet;
BuildValuesUpdateBlockForPlayer(&udata, caster->ToPlayer());
udata.BuildPacket(&packet);
@@ -831,6 +830,16 @@ bool GameObject::LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap)
if (!Create(guid, entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, artKit))
return false;
+ if (data->phaseid)
+ SetInPhase(data->phaseid, false, true);
+
+ if (data->phaseGroup)
+ {
+ // Set the gameobject in all the phases of the phasegroup
+ for (auto ph : GetPhasesForGroup(data->phaseGroup))
+ SetInPhase(ph, false, true);
+ }
+
if (data->spawntimesecs >= 0)
{
m_spawnedByDefault = true;
@@ -2081,9 +2090,9 @@ void GameObject::SetDisplayId(uint32 displayid)
UpdateModel();
}
-void GameObject::SetPhaseMask(uint32 newPhaseMask, bool update)
+void GameObject::SetInPhase(uint32 id, bool update, bool apply)
{
- WorldObject::SetPhaseMask(newPhaseMask, update);
+ WorldObject::SetInPhase(id, update, apply);
if (m_model && m_model->isEnabled())
EnableCollision(true);
}
@@ -2264,7 +2273,7 @@ void GameObject::GetRespawnPosition(float &x, float &y, float &z, float* ori /*
*ori = GetOrientation();
}
-float GameObject::GetInteractionDistance()
+float GameObject::GetInteractionDistance() const
{
switch (GetGoType())
{
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index f5074e202e9..09c84c71244 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -46,6 +46,7 @@ struct GameObjectTemplate
uint32 flags;
float size;
uint32 questItems[MAX_GAMEOBJECT_QUEST_ITEMS];
+ int32 unkInt32;
union // different GO types have different data field
{
//0 GAMEOBJECT_TYPE_DOOR
@@ -591,7 +592,7 @@ struct GameObjectData
{
explicit GameObjectData() : id(0), mapid(0), phaseMask(0), posX(0.0f), posY(0.0f), posZ(0.0f), orientation(0.0f),
rotation0(0.0f), rotation1(0.0f), rotation2(0.0f), rotation3(0.0f), spawntimesecs(0),
- animprogress(0), go_state(GO_STATE_ACTIVE), spawnMask(0), artKit(0), dbData(true) { }
+ animprogress(0), go_state(GO_STATE_ACTIVE), spawnMask(0), artKit(0), phaseid(0), phaseGroup(0), dbData(true) { }
uint32 id; // entry in gamobject_template
uint16 mapid;
uint32 phaseMask;
@@ -608,6 +609,8 @@ struct GameObjectData
GOState go_state;
uint8 spawnMask;
uint8 artKit;
+ uint32 phaseid;
+ uint32 phaseGroup;
bool dbData;
};
@@ -724,7 +727,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); }
static void SetGoArtKit(uint8 artkit, GameObject* go, uint32 lowguid = 0);
- void SetPhaseMask(uint32 newPhaseMask, bool update);
+ void SetInPhase(uint32 id, bool update, bool apply);
void EnableCollision(bool enable);
void Use(Unit* user);
@@ -833,7 +836,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
float GetStationaryZ() const { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetPositionZ(); return GetPositionZ(); }
float GetStationaryO() const { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetOrientation(); return GetOrientation(); }
- float GetInteractionDistance();
+ float GetInteractionDistance() const;
void UpdateModelPosition();
@@ -878,6 +881,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
//! Following check does check 3d distance
return IsInRange(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), dist2compare);
}
+
GameObjectAI* m_AI;
};
#endif
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 09911fc8f57..dcf534690db 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -27,6 +27,7 @@
#include "ScriptMgr.h"
#include "ConditionMgr.h"
#include "Player.h"
+#include "Opcodes.h"
#include "WorldSession.h"
void AddItemsSetItem(Player* player, Item* item)
@@ -213,6 +214,10 @@ bool ItemCanGoIntoBag(ItemTemplate const* pProto, ItemTemplate const* pBagProto)
if (!(pProto->BagFamily & BAG_FAMILY_MASK_INSCRIPTION_SUPP))
return false;
return true;
+ case ITEM_SUBCLASS_TACKLE_CONTAINER:
+ if (!(pProto->BagFamily & BAG_FAMILY_MASK_FISHING_SUPP))
+ return false;
+ return true;
default:
return false;
}
@@ -239,7 +244,7 @@ Item::Item()
m_objectType |= TYPEMASK_ITEM;
m_objectTypeId = TYPEID_ITEM;
- m_updateFlag = UPDATEFLAG_LOWGUID;
+ m_updateFlag = 0;
m_valuesCount = ITEM_END;
m_slot = 0;
@@ -553,46 +558,6 @@ uint32 Item::GetSkill()
}
}
-uint32 Item::GetSpell()
-{
- ItemTemplate const* proto = GetTemplate();
-
- switch (proto->Class)
- {
- case ITEM_CLASS_WEAPON:
- switch (proto->SubClass)
- {
- case ITEM_SUBCLASS_WEAPON_AXE: return 196;
- case ITEM_SUBCLASS_WEAPON_AXE2: return 197;
- case ITEM_SUBCLASS_WEAPON_BOW: return 264;
- case ITEM_SUBCLASS_WEAPON_GUN: return 266;
- case ITEM_SUBCLASS_WEAPON_MACE: return 198;
- case ITEM_SUBCLASS_WEAPON_MACE2: return 199;
- case ITEM_SUBCLASS_WEAPON_POLEARM: return 200;
- case ITEM_SUBCLASS_WEAPON_SWORD: return 201;
- case ITEM_SUBCLASS_WEAPON_SWORD2: return 202;
- case ITEM_SUBCLASS_WEAPON_STAFF: return 227;
- case ITEM_SUBCLASS_WEAPON_DAGGER: return 1180;
- case ITEM_SUBCLASS_WEAPON_THROWN: return 2567;
- case ITEM_SUBCLASS_WEAPON_SPEAR: return 3386;
- case ITEM_SUBCLASS_WEAPON_CROSSBOW:return 5011;
- case ITEM_SUBCLASS_WEAPON_WAND: return 5009;
- default: return 0;
- }
- case ITEM_CLASS_ARMOR:
- switch (proto->SubClass)
- {
- case ITEM_SUBCLASS_ARMOR_CLOTH: return 9078;
- case ITEM_SUBCLASS_ARMOR_LEATHER: return 9077;
- case ITEM_SUBCLASS_ARMOR_MAIL: return 8737;
- case ITEM_SUBCLASS_ARMOR_PLATE: return 750;
- case ITEM_SUBCLASS_ARMOR_SHIELD: return 9116;
- default: return 0;
- }
- }
- return 0;
-}
-
int32 Item::GenerateItemRandomPropertyId(uint32 item_id)
{
ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_id);
@@ -654,8 +619,8 @@ void Item::SetItemRandomProperties(int32 randomPropId)
SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, item_rand->ID);
SetState(ITEM_CHANGED, GetOwner());
}
- for (uint32 i = PROP_ENCHANTMENT_SLOT_2; i < PROP_ENCHANTMENT_SLOT_2 + 3; ++i)
- SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_2], 0, 0);
+ for (uint32 i = PROP_ENCHANTMENT_SLOT_1; i < PROP_ENCHANTMENT_SLOT_1 + 3; ++i)
+ SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_1], 0, 0);
}
}
else
@@ -671,7 +636,7 @@ void Item::SetItemRandomProperties(int32 randomPropId)
SetState(ITEM_CHANGED, GetOwner());
}
- for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i < PROP_ENCHANTMENT_SLOT_0 + 3; ++i)
+ for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i <= PROP_ENCHANTMENT_SLOT_4; ++i)
SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_0], 0, 0);
}
}
@@ -791,10 +756,15 @@ bool Item::HasEnchantRequiredSkill(const Player* player) const
{
// Check all enchants for required skill
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
+ {
+ if (enchant_slot > PRISMATIC_ENCHANTMENT_SLOT && enchant_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
if (enchantEntry->requiredSkill && player->GetSkillValue(enchantEntry->requiredSkill) < enchantEntry->requiredSkillValue)
return false;
+ }
return true;
}
@@ -805,10 +775,15 @@ uint32 Item::GetEnchantRequiredLevel() const
// Check all enchants for required level
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
+ {
+ if (enchant_slot > PRISMATIC_ENCHANTMENT_SLOT && enchant_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
if (enchantEntry->requiredLevel > level)
level = enchantEntry->requiredLevel;
+ }
return level;
}
@@ -817,10 +792,16 @@ bool Item::IsBoundByEnchant() const
{
// Check all enchants for soulbound
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
+ {
+ if (enchant_slot > PRISMATIC_ENCHANTMENT_SLOT && enchant_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
if (enchantEntry->slot & ENCHANTMENT_CAN_SOULBOUND)
return true;
+ }
+
return false;
}
@@ -828,15 +809,15 @@ InventoryResult Item::CanBeMergedPartlyWith(ItemTemplate const* proto) const
{
// not allow merge looting currently items
if (m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
// check item type
if (GetEntry() != proto->ItemId)
- return EQUIP_ERR_ITEM_CANT_STACK;
+ return EQUIP_ERR_CANT_STACK;
// check free space (full stacks can't be target of merge
if (GetCount() >= proto->GetMaxStackSize())
- return EQUIP_ERR_ITEM_CANT_STACK;
+ return EQUIP_ERR_CANT_STACK;
return EQUIP_ERR_OK;
}
@@ -848,8 +829,8 @@ bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const
if (spellInfo->EquippedItemClass != -1) // -1 == any item class
{
// Special case - accept vellum for armor/weapon requirements
- if ((spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && proto->IsArmorVellum())
- ||(spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && proto->IsWeaponVellum()))
+ if ((spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR ||
+ spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON) && proto->IsVellum())
if (spellInfo->IsAbilityOfSkillType(SKILL_ENCHANTING)) // only for enchanting spells
return true;
@@ -1227,6 +1208,305 @@ bool Item::CheckSoulboundTradeExpire()
return false;
}
+bool Item::CanBeTransmogrified() const
+{
+ ItemTemplate const* proto = GetTemplate();
+
+ if (!proto)
+ return false;
+
+ if (proto->Quality == ITEM_QUALITY_LEGENDARY)
+ return false;
+
+ if (proto->Class != ITEM_CLASS_ARMOR &&
+ proto->Class != ITEM_CLASS_WEAPON)
+ return false;
+
+ if (proto->Class == ITEM_CLASS_WEAPON && proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE)
+ return false;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG)
+ return false;
+
+ if (!HasStats())
+ return false;
+
+ return true;
+}
+
+bool Item::CanTransmogrify() const
+{
+ ItemTemplate const* proto = GetTemplate();
+
+ if (!proto)
+ return false;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG)
+ return false;
+
+ if (proto->Quality == ITEM_QUALITY_LEGENDARY)
+ return false;
+
+ if (proto->Class != ITEM_CLASS_ARMOR &&
+ proto->Class != ITEM_CLASS_WEAPON)
+ return false;
+
+ if (proto->Class == ITEM_CLASS_WEAPON && proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE)
+ return false;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_CAN_TRANSMOG)
+ return true;
+
+ if (!HasStats())
+ return false;
+
+ return true;
+}
+
+bool Item::CanTransmogrifyItemWithItem(Item const* transmogrified, Item const* transmogrifier)
+{
+ if (!transmogrifier || !transmogrified)
+ return false;
+
+ ItemTemplate const* proto1 = transmogrifier->GetTemplate(); // source
+ ItemTemplate const* proto2 = transmogrified->GetTemplate(); // dest
+
+ if (proto1->ItemId == proto2->ItemId)
+ return false;
+
+ if (!transmogrified->CanTransmogrify() || !transmogrifier->CanBeTransmogrified())
+ return false;
+
+ if (proto1->InventoryType == INVTYPE_BAG ||
+ proto1->InventoryType == INVTYPE_RELIC ||
+ proto1->InventoryType == INVTYPE_BODY ||
+ proto1->InventoryType == INVTYPE_FINGER ||
+ proto1->InventoryType == INVTYPE_TRINKET ||
+ proto1->InventoryType == INVTYPE_AMMO ||
+ proto1->InventoryType == INVTYPE_QUIVER)
+ return false;
+
+ if (proto1->SubClass != proto2->SubClass && (proto1->Class != ITEM_CLASS_WEAPON || !proto2->IsRangedWeapon() || !proto1->IsRangedWeapon()))
+ return false;
+
+ if (proto1->InventoryType != proto2->InventoryType &&
+ (proto1->Class != ITEM_CLASS_WEAPON || (proto2->InventoryType != INVTYPE_WEAPONMAINHAND && proto2->InventoryType != INVTYPE_WEAPONOFFHAND)) &&
+ (proto1->Class != ITEM_CLASS_ARMOR || (proto1->InventoryType != INVTYPE_CHEST && proto2->InventoryType != INVTYPE_ROBE && proto1->InventoryType != INVTYPE_ROBE && proto2->InventoryType != INVTYPE_CHEST)))
+ return false;
+
+ return true;
+}
+
+bool Item::HasStats() const
+{
+ if (GetItemRandomPropertyId() != 0)
+ return true;
+
+ ItemTemplate const* proto = GetTemplate();
+ for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ if (proto->ItemStat[i].ItemStatValue != 0)
+ return true;
+
+ return false;
+}
+
+// used by mail items, transmog cost, stationeryinfo and others
+uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice)
+{
+ normalSellPrice = true;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE)
+ {
+ return proto->BuyPrice;
+ }
+ else
+ {
+ ImportPriceQualityEntry const* qualityPrice = sImportPriceQualityStore.LookupEntry(proto->Quality + 1);
+ ItemPriceBaseEntry const* basePrice = sItemPriceBaseStore.LookupEntry(proto->ItemLevel);
+
+ if (!qualityPrice || !basePrice)
+ return 0;
+
+ float qualityFactor = qualityPrice->Factor;
+ float baseFactor = 0.0f;
+
+ uint32 inventoryType = proto->InventoryType;
+
+ if (inventoryType == INVTYPE_WEAPON ||
+ inventoryType == INVTYPE_2HWEAPON ||
+ inventoryType == INVTYPE_WEAPONMAINHAND ||
+ inventoryType == INVTYPE_WEAPONOFFHAND ||
+ inventoryType == INVTYPE_RANGED ||
+ inventoryType == INVTYPE_THROWN ||
+ inventoryType == INVTYPE_RANGEDRIGHT)
+ baseFactor = basePrice->WeaponFactor;
+ else
+ baseFactor = basePrice->ArmorFactor;
+
+ if (inventoryType == INVTYPE_ROBE)
+ inventoryType = INVTYPE_CHEST;
+
+ float typeFactor = 0.0f;
+ int8 weapType = -1;
+
+ switch (inventoryType)
+ {
+ case INVTYPE_HEAD:
+ case INVTYPE_SHOULDERS:
+ case INVTYPE_CHEST:
+ case INVTYPE_WAIST:
+ case INVTYPE_LEGS:
+ case INVTYPE_FEET:
+ case INVTYPE_WRISTS:
+ case INVTYPE_HANDS:
+ case INVTYPE_CLOAK:
+ {
+ ImportPriceArmorEntry const* armorPrice = sImportPriceArmorStore.LookupEntry(inventoryType);
+ if (!armorPrice)
+ return 0;
+
+ switch (proto->SubClass)
+ {
+ case ITEM_SUBCLASS_ARMOR_MISCELLANEOUS:
+ case ITEM_SUBCLASS_ARMOR_CLOTH:
+ typeFactor = armorPrice->ClothFactor;
+ break;
+ case ITEM_SUBCLASS_ARMOR_LEATHER:
+ typeFactor = armorPrice->LeatherFactor;
+ break;
+ case ITEM_SUBCLASS_ARMOR_MAIL:
+ typeFactor = armorPrice->MailFactor;
+ break;
+ case ITEM_SUBCLASS_ARMOR_PLATE:
+ typeFactor = armorPrice->PlateFactor;
+ break;
+ default:
+ return 0;
+ }
+
+ break;
+ }
+ case INVTYPE_SHIELD:
+ {
+ ImportPriceShieldEntry const* shieldPrice = sImportPriceShieldStore.LookupEntry(1); // it only has two rows, it's unclear which is the one used
+ if (!shieldPrice)
+ return 0;
+
+ typeFactor = shieldPrice->Factor;
+ break;
+ }
+ case INVTYPE_WEAPONMAINHAND:
+ weapType = 0;
+ break;
+ case INVTYPE_WEAPONOFFHAND:
+ weapType = 1;
+ break;
+ case INVTYPE_WEAPON:
+ weapType = 2;
+ break;
+ case INVTYPE_2HWEAPON:
+ weapType = 3;
+ break;
+ case INVTYPE_RANGED:
+ case INVTYPE_RANGEDRIGHT:
+ case INVTYPE_RELIC:
+ weapType = 4;
+ break;
+ default:
+ return proto->BuyPrice;
+ }
+
+ if (weapType != -1)
+ {
+ ImportPriceWeaponEntry const* weaponPrice = sImportPriceWeaponStore.LookupEntry(weapType + 1);
+ if (!weaponPrice)
+ return 0;
+
+ typeFactor = weaponPrice->Factor;
+ }
+
+ normalSellPrice = false;
+ return uint32(qualityFactor * proto->Unk430_2 * proto->Unk430_1 * typeFactor * baseFactor);
+ }
+}
+
+uint32 Item::GetSpecialPrice(ItemTemplate const* proto, uint32 minimumPrice /*= 10000*/)
+{
+ uint32 cost = 0;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE)
+ cost = proto->SellPrice;
+ else
+ {
+ bool normalPrice;
+ cost = Item::GetSellPrice(proto, normalPrice);
+
+ if (!normalPrice)
+ {
+ if (proto->BuyCount <= 1)
+ {
+ ItemClassEntry const* classEntry = sItemClassStore.LookupEntry(proto->Class);
+ if (classEntry)
+ cost *= classEntry->PriceFactor;
+ else
+ cost = 0;
+ }
+ else
+ cost /= 4 * proto->BuyCount;
+ }
+ else
+ cost = proto->SellPrice;
+ }
+
+ if (cost < minimumPrice)
+ cost = minimumPrice;
+
+ return cost;
+}
+
+int32 Item::GetReforgableStat(ItemModType statType) const
+{
+ ItemTemplate const* proto = GetTemplate();
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ if (ItemModType(proto->ItemStat[i].ItemStatType) == statType)
+ return proto->ItemStat[i].ItemStatValue;
+
+ int32 randomPropId = GetItemRandomPropertyId();
+ if (!randomPropId)
+ return 0;
+
+ if (randomPropId < 0)
+ {
+ ItemRandomSuffixEntry const* randomSuffix = sItemRandomSuffixStore.LookupEntry(-randomPropId);
+ if (!randomSuffix)
+ return 0;
+
+ for (uint32 e = PROP_ENCHANTMENT_SLOT_0; e <= PROP_ENCHANTMENT_SLOT_4; ++e)
+ if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(GetEnchantmentId(EnchantmentSlot(e))))
+ for (uint32 f = 0; f < MAX_ITEM_ENCHANTMENT_EFFECTS; ++f)
+ if (enchant->type[f] == ITEM_ENCHANTMENT_TYPE_STAT && ItemModType(enchant->spellid[f]) == statType)
+ for (int k = 0; k < 5; ++k)
+ if (randomSuffix->enchant_id[k] == enchant->ID)
+ return int32((randomSuffix->prefix[k] * GetItemSuffixFactor()) / 10000);
+ }
+ else
+ {
+ ItemRandomPropertiesEntry const* randomProp = sItemRandomPropertiesStore.LookupEntry(randomPropId);
+ if (!randomProp)
+ return 0;
+
+ for (uint32 e = PROP_ENCHANTMENT_SLOT_0; e <= PROP_ENCHANTMENT_SLOT_4; ++e)
+ if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(GetEnchantmentId(EnchantmentSlot(e))))
+ for (uint32 f = 0; f < MAX_ITEM_ENCHANTMENT_EFFECTS; ++f)
+ if (enchant->type[f] == ITEM_ENCHANTMENT_TYPE_STAT && ItemModType(enchant->spellid[f]) == statType)
+ for (int k = 0; k < MAX_ITEM_ENCHANTMENT_EFFECTS; ++k)
+ if (randomProp->enchant_id[k] == enchant->ID)
+ return int32(enchant->amount[k]);
+ }
+
+ return 0;
+}
+
void Item::ItemContainerSaveLootToDB()
{
// Saves the money and item loot associated with an openable item to the DB
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index a65579cc134..ebd66a64838 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -38,95 +38,99 @@ struct ItemSetEffect
enum InventoryResult
{
- EQUIP_ERR_OK = 0,
- EQUIP_ERR_CANT_EQUIP_LEVEL_I = 1,
- EQUIP_ERR_CANT_EQUIP_SKILL = 2,
- EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT = 3,
- EQUIP_ERR_BAG_FULL = 4,
- EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG = 5,
- EQUIP_ERR_CANT_TRADE_EQUIP_BAGS = 6,
- EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE = 7,
- EQUIP_ERR_NO_REQUIRED_PROFICIENCY = 8,
- EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE = 9,
- EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM = 10,
- EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM2 = 11,
- EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE2 = 12,
- EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED = 13,
- EQUIP_ERR_CANT_DUAL_WIELD = 14,
- EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG = 15,
- EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG2 = 16,
- EQUIP_ERR_CANT_CARRY_MORE_OF_THIS = 17,
- EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE3 = 18,
- EQUIP_ERR_ITEM_CANT_STACK = 19,
- EQUIP_ERR_ITEM_CANT_BE_EQUIPPED = 20,
- EQUIP_ERR_ITEMS_CANT_BE_SWAPPED = 21,
- EQUIP_ERR_SLOT_IS_EMPTY = 22,
- EQUIP_ERR_ITEM_NOT_FOUND = 23,
- EQUIP_ERR_CANT_DROP_SOULBOUND = 24,
- EQUIP_ERR_OUT_OF_RANGE = 25,
- EQUIP_ERR_TRIED_TO_SPLIT_MORE_THAN_COUNT = 26,
- EQUIP_ERR_COULDNT_SPLIT_ITEMS = 27,
- EQUIP_ERR_MISSING_REAGENT = 28,
- EQUIP_ERR_NOT_ENOUGH_MONEY = 29,
- EQUIP_ERR_NOT_A_BAG = 30,
- EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS = 31,
- EQUIP_ERR_DONT_OWN_THAT_ITEM = 32,
- EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER = 33,
- EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT = 34,
- EQUIP_ERR_TOO_FAR_AWAY_FROM_BANK = 35,
- EQUIP_ERR_ITEM_LOCKED = 36,
- EQUIP_ERR_YOU_ARE_STUNNED = 37,
- EQUIP_ERR_YOU_ARE_DEAD = 38,
- EQUIP_ERR_CANT_DO_RIGHT_NOW = 39,
- EQUIP_ERR_INT_BAG_ERROR = 40,
- EQUIP_ERR_CAN_EQUIP_ONLY1_BOLT = 41,
- EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH = 42,
- EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED = 43,
- EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED = 44,
- EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED = 45,
- EQUIP_ERR_BOUND_CANT_BE_WRAPPED = 46,
- EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED = 47,
- EQUIP_ERR_BAGS_CANT_BE_WRAPPED = 48,
- EQUIP_ERR_ALREADY_LOOTED = 49,
- EQUIP_ERR_INVENTORY_FULL = 50,
- EQUIP_ERR_BANK_FULL = 51,
- EQUIP_ERR_ITEM_IS_CURRENTLY_SOLD_OUT = 52,
- EQUIP_ERR_BAG_FULL3 = 53,
- EQUIP_ERR_ITEM_NOT_FOUND2 = 54,
- EQUIP_ERR_ITEM_CANT_STACK2 = 55,
- EQUIP_ERR_BAG_FULL4 = 56,
- EQUIP_ERR_ITEM_SOLD_OUT = 57,
- EQUIP_ERR_OBJECT_IS_BUSY = 58,
- EQUIP_ERR_NONE = 59,
- EQUIP_ERR_NOT_IN_COMBAT = 60,
- EQUIP_ERR_NOT_WHILE_DISARMED = 61,
- EQUIP_ERR_BAG_FULL6 = 62,
- EQUIP_ERR_CANT_EQUIP_RANK = 63,
- EQUIP_ERR_CANT_EQUIP_REPUTATION = 64,
- EQUIP_ERR_TOO_MANY_SPECIAL_BAGS = 65,
- EQUIP_ERR_LOOT_CANT_LOOT_THAT_NOW = 66,
- EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE = 67,
- EQUIP_ERR_VENDOR_MISSING_TURNINS = 68,
- EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS = 69,
- EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS = 70,
- EQUIP_ERR_ITEM_MAX_COUNT_SOCKETED = 71,
- EQUIP_ERR_MAIL_BOUND_ITEM = 72,
- EQUIP_ERR_NO_SPLIT_WHILE_PROSPECTING = 73,
- EQUIP_ERR_ITEM_MAX_COUNT_EQUIPPED_SOCKETED = 75,
- EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED = 76,
- EQUIP_ERR_TOO_MUCH_GOLD = 77,
- EQUIP_ERR_NOT_DURING_ARENA_MATCH = 78,
- EQUIP_ERR_CANNOT_TRADE_THAT = 79,
- EQUIP_ERR_PERSONAL_ARENA_RATING_TOO_LOW = 80,
- EQUIP_ERR_EVENT_AUTOEQUIP_BIND_CONFIRM = 81,
- EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS = 82,
- // no output = 83,
- EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED = 84,
- EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_SOCKETED_EXCEEDED = 85,
- EQUIP_ERR_SCALING_STAT_ITEM_LEVEL_EXCEEDED = 86,
- EQUIP_ERR_PURCHASE_LEVEL_TOO_LOW = 87,
- EQUIP_ERR_CANT_EQUIP_NEED_TALENT = 88,
- EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED = 89
+ EQUIP_ERR_OK = 0,
+ EQUIP_ERR_CANT_EQUIP_LEVEL_I = 1, // You must reach level %d to use that item.
+ EQUIP_ERR_CANT_EQUIP_SKILL = 2, // You aren't skilled enough to use that item.
+ EQUIP_ERR_WRONG_SLOT = 3, // That item does not go in that slot.
+ EQUIP_ERR_BAG_FULL = 4, // That bag is full.
+ EQUIP_ERR_BAG_IN_BAG = 5, // Can't put non-empty bags in other bags.
+ EQUIP_ERR_TRADE_EQUIPPED_BAG = 6, // You can't trade equipped bags.
+ EQUIP_ERR_AMMO_ONLY = 7, // Only ammo can go there.
+ EQUIP_ERR_PROFICIENCY_NEEDED = 8, // You do not have the required proficiency for that item.
+ EQUIP_ERR_NO_SLOT_AVAILABLE = 9, // No equipment slot is available for that item.
+ EQUIP_ERR_CANT_EQUIP_EVER = 10, // You can never use that item.
+ EQUIP_ERR_CANT_EQUIP_EVER_2 = 11, // You can never use that item.
+ EQUIP_ERR_NO_SLOT_AVAILABLE_2 = 12, // No equipment slot is available for that item.
+ EQUIP_ERR_2HANDED_EQUIPPED = 13, // Cannot equip that with a two-handed weapon.
+ EQUIP_ERR_2HSKILLNOTFOUND = 14, // You cannot dual-wield
+ EQUIP_ERR_WRONG_BAG_TYPE = 15, // That item doesn't go in that container.
+ EQUIP_ERR_WRONG_BAG_TYPE_2 = 16, // That item doesn't go in that container.
+ EQUIP_ERR_ITEM_MAX_COUNT = 17, // You can't carry any more of those items.
+ EQUIP_ERR_NO_SLOT_AVAILABLE_3 = 18, // No equipment slot is available for that item.
+ EQUIP_ERR_CANT_STACK = 19, // This item cannot stack.
+ EQUIP_ERR_NOT_EQUIPPABLE = 20, // This item cannot be equipped.
+ EQUIP_ERR_CANT_SWAP = 21, // These items can't be swapped.
+ EQUIP_ERR_SLOT_EMPTY = 22, // That slot is empty.
+ EQUIP_ERR_ITEM_NOT_FOUND = 23, // The item was not found.
+ EQUIP_ERR_DROP_BOUND_ITEM = 24, // You can't drop a soulbound item.
+ EQUIP_ERR_OUT_OF_RANGE = 25, // Out of range.
+ EQUIP_ERR_TOO_FEW_TO_SPLIT = 26, // Tried to split more than number in stack.
+ EQUIP_ERR_SPLIT_FAILED = 27, // Couldn't split those items.
+ EQUIP_ERR_SPELL_FAILED_REAGENTS_GENERIC = 28, // Missing reagent
+ EQUIP_ERR_NOT_ENOUGH_MONEY = 29, // You don't have enough money.
+ EQUIP_ERR_NOT_A_BAG = 30, // Not a bag.
+ EQUIP_ERR_DESTROY_NONEMPTY_BAG = 31, // You can only do that with empty bags.
+ EQUIP_ERR_NOT_OWNER = 32, // You don't own that item.
+ EQUIP_ERR_ONLY_ONE_QUIVER = 33, // You can only equip one quiver.
+ EQUIP_ERR_NO_BANK_SLOT = 34, // You must purchase that bag slot first
+ EQUIP_ERR_NO_BANK_HERE = 35, // You are too far away from a bank.
+ EQUIP_ERR_ITEM_LOCKED = 36, // Item is locked.
+ EQUIP_ERR_GENERIC_STUNNED = 37, // You are stunned
+ EQUIP_ERR_PLAYER_DEAD = 38, // You can't do that when you're dead.
+ EQUIP_ERR_CLIENT_LOCKED_OUT = 39, // You can't do that right now.
+ EQUIP_ERR_INTERNAL_BAG_ERROR = 40, // Internal Bag Error
+ EQUIP_ERR_ONLY_ONE_BOLT = 41, // You can only equip one quiver.
+ EQUIP_ERR_ONLY_ONE_AMMO = 42, // You can only equip one ammo pouch.
+ EQUIP_ERR_CANT_WRAP_STACKABLE = 43, // Stackable items can't be wrapped.
+ EQUIP_ERR_CANT_WRAP_EQUIPPED = 44, // Equipped items can't be wrapped.
+ EQUIP_ERR_CANT_WRAP_WRAPPED = 45, // Wrapped items can't be wrapped.
+ EQUIP_ERR_CANT_WRAP_BOUND = 46, // Bound items can't be wrapped.
+ EQUIP_ERR_CANT_WRAP_UNIQUE = 47, // Unique items can't be wrapped.
+ EQUIP_ERR_CANT_WRAP_BAGS = 48, // Bags can't be wrapped.
+ EQUIP_ERR_LOOT_GONE = 49, // Already looted
+ EQUIP_ERR_INV_FULL = 50, // Inventory is full.
+ EQUIP_ERR_BANK_FULL = 51, // Your bank is full
+ EQUIP_ERR_VENDOR_SOLD_OUT = 52, // That item is currently sold out.
+ EQUIP_ERR_BAG_FULL_2 = 53, // That bag is full.
+ EQUIP_ERR_ITEM_NOT_FOUND_2 = 54, // The item was not found.
+ EQUIP_ERR_CANT_STACK_2 = 55, // This item cannot stack.
+ EQUIP_ERR_BAG_FULL_3 = 56, // That bag is full.
+ EQUIP_ERR_VENDOR_SOLD_OUT_2 = 57, // That item is currently sold out.
+ EQUIP_ERR_OBJECT_IS_BUSY = 58, // That object is busy.
+ EQUIP_ERR_CANT_BE_DISENCHANTED = 59,
+ EQUIP_ERR_NOT_IN_COMBAT = 60, // You can't do that while in combat
+ EQUIP_ERR_NOT_WHILE_DISARMED = 61, // You can't do that while disarmed
+ EQUIP_ERR_BAG_FULL_4 = 62, // That bag is full.
+ EQUIP_ERR_CANT_EQUIP_RANK = 63, // You don't have the required rank for that item
+ EQUIP_ERR_CANT_EQUIP_REPUTATION = 64, // You don't have the required reputation for that item
+ EQUIP_ERR_TOO_MANY_SPECIAL_BAGS = 65, // You cannot equip another bag of that type
+ EQUIP_ERR_LOOT_CANT_LOOT_THAT_NOW = 66, // You can't loot that item now.
+ EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE = 67, // You cannot equip more than one of those.
+ EQUIP_ERR_VENDOR_MISSING_TURNINS = 68, // You do not have the required items for that purchase
+ EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS = 69, // You don't have enough honor points
+ EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS = 70, // You don't have enough arena points
+ EQUIP_ERR_ITEM_MAX_COUNT_SOCKETED = 71, // You have the maximum number of those gems in your inventory or socketed into items.
+ EQUIP_ERR_MAIL_BOUND_ITEM = 72, // You can't mail soulbound items.
+ EQUIP_ERR_INTERNAL_BAG_ERROR_2 = 73, // Internal Bag Error
+ EQUIP_ERR_BAG_FULL_5 = 74, // That bag is full.
+ EQUIP_ERR_ITEM_MAX_COUNT_EQUIPPED_SOCKETED = 75, // You have the maximum number of those gems socketed into equipped items.
+ EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED = 76, // You cannot socket more than one of those gems into a single item.
+ EQUIP_ERR_TOO_MUCH_GOLD = 77, // At gold limit
+ EQUIP_ERR_NOT_DURING_ARENA_MATCH = 78, // You can't do that while in an arena match
+ EQUIP_ERR_TRADE_BOUND_ITEM = 79, // You can't trade a soulbound item.
+ EQUIP_ERR_CANT_EQUIP_RATING = 80, // You don't have the personal, team, or battleground rating required to buy that item
+ EQUIP_ERR_NO_OUTPUT = 81,
+ EQUIP_ERR_NOT_SAME_ACCOUNT = 82, // Account-bound items can only be given to your own characters.
+ EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED_IS = 84, // You can only carry %d %s
+ EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_SOCKETED_EXCEEDED_IS = 85, // You can only equip %d |4item:items in the %s category
+ EQUIP_ERR_SCALING_STAT_ITEM_LEVEL_EXCEEDED = 86, // Your level is too high to use that item
+ EQUIP_ERR_PURCHASE_LEVEL_TOO_LOW = 87, // You must reach level %d to purchase that item.
+ EQUIP_ERR_CANT_EQUIP_NEED_TALENT = 88, // You do not have the required talent to equip that.
+ EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS = 89, // You can only equip %d |4item:items in the %s category
+ EQUIP_ERR_SHAPESHIFT_FORM_CANNOT_EQUIP = 90, // Cannot equip item in this form
+ EQUIP_ERR_ITEM_INVENTORY_FULL_SATCHEL = 91, // Your inventory is full. Your satchel has been delivered to your mailbox.
+ EQUIP_ERR_SCALING_STAT_ITEM_LEVEL_TOO_LOW = 92, // Your level is too low to use that item
+ EQUIP_ERR_CANT_BUY_QUANTITY = 93, // You can't buy the specified quantity of that item.
};
enum BuyResult
@@ -162,14 +166,17 @@ enum EnchantmentSlot
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
+ //TODO: 7,
+ REFORGE_ENCHANTMENT_SLOT = 8,
+ TRANSMOGRIFY_ENCHANTMENT_SLOT = 9,
+ MAX_INSPECTED_ENCHANTMENT_SLOT = 10,
+
+ PROP_ENCHANTMENT_SLOT_0 = 10, // used with RandomSuffix
+ PROP_ENCHANTMENT_SLOT_1 = 11, // used with RandomSuffix
+ PROP_ENCHANTMENT_SLOT_2 = 12, // used with RandomSuffix and RandomProperty
+ PROP_ENCHANTMENT_SLOT_3 = 13, // used with RandomProperty
+ PROP_ENCHANTMENT_SLOT_4 = 14, // used with RandomProperty
+ MAX_ENCHANTMENT_SLOT = 15
};
#define MAX_VISIBLE_ITEM_OFFSET 2 // 2 fields per visible item (entry+enchantment)
@@ -224,6 +231,7 @@ class Item : public Object
void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_SOULBOUND, val); }
bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_SOULBOUND); }
bool IsBoundAccountWide() const { return (GetTemplate()->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT) != 0; }
+ bool IsBattlenetAccountBound() const { return (GetTemplate()->Flags2 & ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND) != 0; }
bool IsBindedNotWith(Player const* player) const;
bool IsBoundByEnchant() const;
virtual void SaveToDB(SQLTransaction& trans);
@@ -281,7 +289,6 @@ class Item : public Object
bool IsEquipped() const;
uint32 GetSkill();
- uint32 GetSpell();
// RandomPropertyId (signed but stored as unsigned)
int32 GetItemRandomPropertyId() const { return GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID); }
@@ -326,10 +333,11 @@ class Item : public Object
bool hasQuest(uint32 quest_id) const { return GetTemplate()->StartQuest == quest_id; }
bool hasInvolvedQuest(uint32 /*quest_id*/) const { return false; }
+ bool HasStats() const;
bool IsPotion() const { return GetTemplate()->IsPotion(); }
- bool IsWeaponVellum() const { return GetTemplate()->IsWeaponVellum(); }
- bool IsArmorVellum() const { return GetTemplate()->IsArmorVellum(); }
+ bool IsVellum() const { return GetTemplate()->IsVellum(); }
bool IsConjuredConsumable() const { return GetTemplate()->IsConjuredConsumable(); }
+ bool IsRangedWeapon() const { return GetTemplate()->IsRangedWeapon(); }
// Item Refund system
void SetNotRefundable(Player* owner, bool changestate = true, SQLTransaction* trans = NULL);
@@ -353,6 +361,24 @@ class Item : public Object
void BuildUpdate(UpdateDataMapType&);
uint32 GetScriptId() const { return GetTemplate()->ScriptId; }
+
+ bool CanBeTransmogrified() const;
+ bool CanTransmogrify() const;
+ static bool CanTransmogrifyItemWithItem(Item const* transmogrified, Item const* transmogrifier);
+ static uint32 GetSpecialPrice(ItemTemplate const* proto, uint32 minimumPrice = 10000);
+ uint32 GetSpecialPrice(uint32 minimumPrice = 10000) const { return Item::GetSpecialPrice(GetTemplate(), minimumPrice); }
+
+ uint32 GetVisibleEntry() const
+ {
+ if (uint32 transmogrification = GetEnchantmentId(TRANSMOGRIFY_ENCHANTMENT_SLOT))
+ return transmogrification;
+ return GetEntry();
+ }
+
+ static uint32 GetSellPrice(ItemTemplate const* proto, bool& success);
+
+ int32 GetReforgableStat(ItemModType statType) const;
+
private:
std::string m_text;
uint8 m_slot;
diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h
index 7e17fd6ae4d..e470afac1ab 100644
--- a/src/server/game/Entities/Item/ItemPrototype.h
+++ b/src/server/game/Entities/Item/ItemPrototype.h
@@ -59,18 +59,23 @@ enum ItemModType
ITEM_MOD_EXPERTISE_RATING = 37,
ITEM_MOD_ATTACK_POWER = 38,
ITEM_MOD_RANGED_ATTACK_POWER = 39,
- //ITEM_MOD_FERAL_ATTACK_POWER = 40, not in 3.3
- ITEM_MOD_SPELL_HEALING_DONE = 41, // deprecated
- ITEM_MOD_SPELL_DAMAGE_DONE = 42, // deprecated
ITEM_MOD_MANA_REGENERATION = 43,
ITEM_MOD_ARMOR_PENETRATION_RATING = 44,
ITEM_MOD_SPELL_POWER = 45,
ITEM_MOD_HEALTH_REGEN = 46,
ITEM_MOD_SPELL_PENETRATION = 47,
- ITEM_MOD_BLOCK_VALUE = 48
+ ITEM_MOD_BLOCK_VALUE = 48,
+ ITEM_MOD_MASTERY_RATING = 49,
+ ITEM_MOD_EXTRA_ARMOR = 50,
+ ITEM_MOD_FIRE_RESISTANCE = 51,
+ ITEM_MOD_FROST_RESISTANCE = 52,
+ ITEM_MOD_HOLY_RESISTANCE = 53,
+ ITEM_MOD_SHADOW_RESISTANCE = 54,
+ ITEM_MOD_NATURE_RESISTANCE = 55,
+ ITEM_MOD_ARCANE_RESISTANCE = 56,
};
-#define MAX_ITEM_MOD 49
+#define MAX_ITEM_MOD 57
enum ItemSpelltriggerType
{
@@ -138,7 +143,7 @@ enum ItemProtoFlags
ITEM_PROTO_FLAG_TRIGGERED_CAST = 0x10000000, // Spell is cast with triggered flag
ITEM_PROTO_FLAG_MILLABLE = 0x20000000, // Item can be milled
ITEM_PROTO_FLAG_UNK11 = 0x40000000, // ?
- ITEM_PROTO_FLAG_UNK12 = 0x80000000 // ?
+ ITEM_PROTO_FLAG_BOP_TRADEABLE = 0x80000000 // bound item that can be traded
};
enum ItemFieldFlags
@@ -184,7 +189,13 @@ enum ItemFlagsExtra
ITEM_FLAGS_EXTRA_HORDE_ONLY = 0x00000001,
ITEM_FLAGS_EXTRA_ALLIANCE_ONLY = 0x00000002,
ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD = 0x00000004, // when item uses extended cost, gold is also required
- ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED = 0x00000100
+ ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED = 0x00000100,
+ ITEM_FLAGS_EXTRA_CASTER_WEAPON = 0x00000200,
+ ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE = 0x00004000,
+ ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND = 0x00020000,
+ ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG = 0x00200000,
+ ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG = 0x00400000,
+ ITEM_FLAGS_EXTRA_CAN_TRANSMOG = 0x00800000,
};
enum ItemFlagsCustom
@@ -194,6 +205,28 @@ enum ItemFlagsCustom
ITEM_FLAGS_CU_FOLLOW_LOOT_RULES = 0x0004 // Item will always follow group/master/need before greed looting rules
};
+enum CurrencyFlags
+{
+ CURRENCY_FLAG_TRADEABLE = 0x01,
+ // ...
+ CURRENCY_FLAG_HIGH_PRECISION = 0x08,
+ // ...
+ CURRENCY_FLAG_COUNT_SEASON_TOTAL = 0x80,
+};
+
+enum CurrencyCategory
+{
+ // ...
+ CURRENCY_CATEGORY_META_CONQUEST = 89,
+ // ...
+};
+
+enum ItemVendorType
+{
+ ITEM_VENDOR_TYPE_ITEM = 1,
+ ITEM_VENDOR_TYPE_CURRENCY = 2,
+};
+
enum BAG_FAMILY_MASK
{
BAG_FAMILY_MASK_NONE = 0x00000000,
@@ -211,7 +244,8 @@ enum BAG_FAMILY_MASK
BAG_FAMILY_MASK_SOULBOUND_EQUIPMENT = 0x00000800,
BAG_FAMILY_MASK_VANITY_PETS = 0x00001000,
BAG_FAMILY_MASK_CURRENCY_TOKENS = 0x00002000,
- BAG_FAMILY_MASK_QUEST_ITEMS = 0x00004000
+ BAG_FAMILY_MASK_QUEST_ITEMS = 0x00004000,
+ BAG_FAMILY_MASK_FISHING_SUPP = 0x00008000,
};
enum SocketColor
@@ -219,10 +253,12 @@ enum SocketColor
SOCKET_COLOR_META = 1,
SOCKET_COLOR_RED = 2,
SOCKET_COLOR_YELLOW = 4,
- SOCKET_COLOR_BLUE = 8
+ SOCKET_COLOR_BLUE = 8,
+ SOCKET_COLOR_HYDRAULIC = 16, // not used
+ SOCKET_COLOR_COGWHEEL = 32,
};
-#define SOCKET_COLOR_ALL (SOCKET_COLOR_META | SOCKET_COLOR_RED | SOCKET_COLOR_YELLOW | SOCKET_COLOR_BLUE)
+#define SOCKET_COLOR_ALL (SOCKET_COLOR_META | SOCKET_COLOR_RED | SOCKET_COLOR_YELLOW | SOCKET_COLOR_BLUE | SOCKET_COLOR_COGWHEEL)
enum InventoryType
{
@@ -269,14 +305,14 @@ enum ItemClass
ITEM_CLASS_REAGENT = 5,
ITEM_CLASS_PROJECTILE = 6,
ITEM_CLASS_TRADE_GOODS = 7,
- ITEM_CLASS_GENERIC = 8,
+ ITEM_CLASS_GENERIC = 8, // OBSOLETE
ITEM_CLASS_RECIPE = 9,
- ITEM_CLASS_MONEY = 10,
+ ITEM_CLASS_MONEY = 10, // OBSOLETE
ITEM_CLASS_QUIVER = 11,
ITEM_CLASS_QUEST = 12,
ITEM_CLASS_KEY = 13,
- ITEM_CLASS_PERMANENT = 14,
- ITEM_CLASS_MISC = 15,
+ ITEM_CLASS_PERMANENT = 14, // OBSOLETE
+ ITEM_CLASS_MISCELLANEOUS = 15,
ITEM_CLASS_GLYPH = 16
};
@@ -289,7 +325,7 @@ enum ItemSubclassConsumable
ITEM_SUBCLASS_ELIXIR = 2,
ITEM_SUBCLASS_FLASK = 3,
ITEM_SUBCLASS_SCROLL = 4,
- ITEM_SUBCLASS_FOOD = 5,
+ ITEM_SUBCLASS_FOOD_DRINK = 5,
ITEM_SUBCLASS_ITEM_ENHANCEMENT = 6,
ITEM_SUBCLASS_BANDAGE = 7,
ITEM_SUBCLASS_CONSUMABLE_OTHER = 8
@@ -307,28 +343,29 @@ enum ItemSubclassContainer
ITEM_SUBCLASS_GEM_CONTAINER = 5,
ITEM_SUBCLASS_MINING_CONTAINER = 6,
ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7,
- ITEM_SUBCLASS_INSCRIPTION_CONTAINER = 8
+ ITEM_SUBCLASS_INSCRIPTION_CONTAINER = 8,
+ ITEM_SUBCLASS_TACKLE_CONTAINER = 9
};
-#define MAX_ITEM_SUBCLASS_CONTAINER 9
+#define MAX_ITEM_SUBCLASS_CONTAINER 10
enum ItemSubclassWeapon
{
- ITEM_SUBCLASS_WEAPON_AXE = 0,
- ITEM_SUBCLASS_WEAPON_AXE2 = 1,
+ ITEM_SUBCLASS_WEAPON_AXE = 0, // One-Handed Axes
+ ITEM_SUBCLASS_WEAPON_AXE2 = 1, // Two-Handed Axes
ITEM_SUBCLASS_WEAPON_BOW = 2,
ITEM_SUBCLASS_WEAPON_GUN = 3,
- ITEM_SUBCLASS_WEAPON_MACE = 4,
- ITEM_SUBCLASS_WEAPON_MACE2 = 5,
+ ITEM_SUBCLASS_WEAPON_MACE = 4, // One-Handed Maces
+ ITEM_SUBCLASS_WEAPON_MACE2 = 5, // Two-Handed Maces
ITEM_SUBCLASS_WEAPON_POLEARM = 6,
- ITEM_SUBCLASS_WEAPON_SWORD = 7,
- ITEM_SUBCLASS_WEAPON_SWORD2 = 8,
- ITEM_SUBCLASS_WEAPON_obsolete = 9,
+ ITEM_SUBCLASS_WEAPON_SWORD = 7, // One-Handed Swords
+ ITEM_SUBCLASS_WEAPON_SWORD2 = 8, // Two-Handed Swords
+ ITEM_SUBCLASS_WEAPON_Obsolete = 9,
ITEM_SUBCLASS_WEAPON_STAFF = 10,
- ITEM_SUBCLASS_WEAPON_EXOTIC = 11,
- ITEM_SUBCLASS_WEAPON_EXOTIC2 = 12,
- ITEM_SUBCLASS_WEAPON_FIST = 13,
- ITEM_SUBCLASS_WEAPON_MISC = 14,
+ ITEM_SUBCLASS_WEAPON_EXOTIC = 11, // One-Handed Exotics
+ ITEM_SUBCLASS_WEAPON_EXOTIC2 = 12, // Two-Handed Exotics
+ ITEM_SUBCLASS_WEAPON_FIST_WEAPON = 13,
+ ITEM_SUBCLASS_WEAPON_MISCELLANEOUS = 14,
ITEM_SUBCLASS_WEAPON_DAGGER = 15,
ITEM_SUBCLASS_WEAPON_THROWN = 16,
ITEM_SUBCLASS_WEAPON_SPEAR = 17,
@@ -353,27 +390,30 @@ enum ItemSubclassGem
ITEM_SUBCLASS_GEM_ORANGE = 5,
ITEM_SUBCLASS_GEM_META = 6,
ITEM_SUBCLASS_GEM_SIMPLE = 7,
- ITEM_SUBCLASS_GEM_PRISMATIC = 8
+ ITEM_SUBCLASS_GEM_PRISMATIC = 8,
+ ITEM_SUBCLASS_GEM_HYDRAULIC = 9,
+ ITEM_SUBCLASS_GEM_COGWHEEL = 10
};
-#define MAX_ITEM_SUBCLASS_GEM 9
+#define MAX_ITEM_SUBCLASS_GEM 11
enum ItemSubclassArmor
{
- ITEM_SUBCLASS_ARMOR_MISC = 0,
+ ITEM_SUBCLASS_ARMOR_MISCELLANEOUS = 0,
ITEM_SUBCLASS_ARMOR_CLOTH = 1,
ITEM_SUBCLASS_ARMOR_LEATHER = 2,
ITEM_SUBCLASS_ARMOR_MAIL = 3,
ITEM_SUBCLASS_ARMOR_PLATE = 4,
- ITEM_SUBCLASS_ARMOR_BUCKLER = 5,
+ ITEM_SUBCLASS_ARMOR_BUCKLER = 5, // OBSOLETE
ITEM_SUBCLASS_ARMOR_SHIELD = 6,
ITEM_SUBCLASS_ARMOR_LIBRAM = 7,
ITEM_SUBCLASS_ARMOR_IDOL = 8,
ITEM_SUBCLASS_ARMOR_TOTEM = 9,
- ITEM_SUBCLASS_ARMOR_SIGIL = 10
+ ITEM_SUBCLASS_ARMOR_SIGIL = 10,
+ ITEM_SUBCLASS_ARMOR_RELIC = 11,
};
-#define MAX_ITEM_SUBCLASS_ARMOR 11
+#define MAX_ITEM_SUBCLASS_ARMOR 12
enum ItemSubclassReagent
{
@@ -384,11 +424,11 @@ enum ItemSubclassReagent
enum ItemSubclassProjectile
{
- ITEM_SUBCLASS_WAND = 0, // ABS
- ITEM_SUBCLASS_BOLT = 1, // ABS
+ ITEM_SUBCLASS_WAND = 0, // OBSOLETE
+ ITEM_SUBCLASS_BOLT = 1, // OBSOLETE
ITEM_SUBCLASS_ARROW = 2,
ITEM_SUBCLASS_BULLET = 3,
- ITEM_SUBCLASS_THROWN = 4 // ABS
+ ITEM_SUBCLASS_THROWN = 4 // OBSOLETE
};
#define MAX_ITEM_SUBCLASS_PROJECTILE 5
@@ -409,15 +449,14 @@ enum ItemSubclassTradeGoods
ITEM_SUBCLASS_TRADE_GOODS_OTHER = 11,
ITEM_SUBCLASS_ENCHANTING = 12,
ITEM_SUBCLASS_MATERIAL = 13,
- ITEM_SUBCLASS_ARMOR_ENCHANTMENT = 14,
- ITEM_SUBCLASS_WEAPON_ENCHANTMENT = 15
+ ITEM_SUBCLASS_ENCHANTMENT = 14,
};
-#define MAX_ITEM_SUBCLASS_TRADE_GOODS 16
+#define MAX_ITEM_SUBCLASS_TRADE_GOODS 15
enum ItemSubclassGeneric
{
- ITEM_SUBCLASS_GENERIC = 0
+ ITEM_SUBCLASS_GENERIC = 0 // OBSOLETE
};
#define MAX_ITEM_SUBCLASS_GENERIC 1
@@ -434,22 +473,24 @@ enum ItemSubclassRecipe
ITEM_SUBCLASS_FIRST_AID_MANUAL = 7,
ITEM_SUBCLASS_ENCHANTING_FORMULA = 8,
ITEM_SUBCLASS_FISHING_MANUAL = 9,
- ITEM_SUBCLASS_JEWELCRAFTING_RECIPE = 10
+ ITEM_SUBCLASS_JEWELCRAFTING_RECIPE = 10,
+ ITEM_SUBCLASS_INSCRIPTION_TECHNIQUE = 11
};
-#define MAX_ITEM_SUBCLASS_RECIPE 11
+#define MAX_ITEM_SUBCLASS_RECIPE 12
enum ItemSubclassMoney
{
- ITEM_SUBCLASS_MONEY = 0
+ ITEM_SUBCLASS_MONEY = 0, // OBSOLETE
+ ITEM_SUBCLASS_MONEY_UNK_7 = 7, // OBSOLETE, 1 item (41749)
};
-#define MAX_ITEM_SUBCLASS_MONEY 1
+#define MAX_ITEM_SUBCLASS_MONEY 8
enum ItemSubclassQuiver
{
- ITEM_SUBCLASS_QUIVER0 = 0, // ABS
- ITEM_SUBCLASS_QUIVER1 = 1, // ABS
+ ITEM_SUBCLASS_QUIVER0 = 0, // OBSOLETE
+ ITEM_SUBCLASS_QUIVER1 = 1, // OBSOLETE
ITEM_SUBCLASS_QUIVER = 2,
ITEM_SUBCLASS_AMMO_POUCH = 3
};
@@ -458,10 +499,12 @@ enum ItemSubclassQuiver
enum ItemSubclassQuest
{
- ITEM_SUBCLASS_QUEST = 0
+ ITEM_SUBCLASS_QUEST = 0,
+ ITEM_SUBCLASS_QUEST_UNK3 = 3, // 1 item (33604)
+ ITEM_SUBCLASS_QUEST_UNK8 = 8, // 2 items (37445, 49700)
};
-#define MAX_ITEM_SUBCLASS_QUEST 1
+#define MAX_ITEM_SUBCLASS_QUEST 9
enum ItemSubclassKey
{
@@ -485,10 +528,11 @@ enum ItemSubclassJunk
ITEM_SUBCLASS_JUNK_PET = 2,
ITEM_SUBCLASS_JUNK_HOLIDAY = 3,
ITEM_SUBCLASS_JUNK_OTHER = 4,
- ITEM_SUBCLASS_JUNK_MOUNT = 5
+ ITEM_SUBCLASS_JUNK_MOUNT = 5,
+ ITEM_SUBCLASS_JUNK_UNK12 = 12, // 1 item (37677)
};
-#define MAX_ITEM_SUBCLASS_JUNK 6
+#define MAX_ITEM_SUBCLASS_JUNK 13
enum ItemSubclassGlyph
{
@@ -544,24 +588,19 @@ inline uint8 ItemSubClassToDurabilityMultiplierId(uint32 ItemClass, uint32 ItemS
#pragma pack(push, 1)
#endif
-struct _Damage
-{
- float DamageMin;
- float DamageMax;
- uint32 DamageType; // id from Resistances.dbc
-};
-
struct _ItemStat
{
uint32 ItemStatType;
int32 ItemStatValue;
+ int32 ItemStatUnk1;
+ int32 ItemStatUnk2;
};
+
struct _Spell
{
int32 SpellId; // id from Spell.dbc
uint32 SpellTrigger;
int32 SpellCharges;
- float SpellPPMRate;
int32 SpellCooldown;
uint32 SpellCategory; // id from SpellCategory.dbc
int32 SpellCategoryCooldown;
@@ -596,6 +635,8 @@ struct ItemTemplate
uint32 Quality;
uint32 Flags;
uint32 Flags2;
+ float Unk430_1;
+ float Unk430_2;
uint32 BuyCount;
int32 BuyPrice;
uint32 SellPrice;
@@ -614,24 +655,14 @@ struct ItemTemplate
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[MAX_ITEM_PROTO_STATS];
uint32 ScalingStatDistribution; // id from ScalingStatDistribution.dbc
- uint32 ScalingStatValue; // mask for selecting column in ScalingStatValues.dbc
- _Damage Damage[MAX_ITEM_PROTO_DAMAGES];
- uint32 Armor;
- uint32 HolyRes;
- uint32 FireRes;
- uint32 NatureRes;
- uint32 FrostRes;
- uint32 ShadowRes;
- uint32 ArcaneRes;
+ uint32 DamageType; // id from Resistances.dbc
uint32 Delay;
- uint32 AmmoType;
float RangedModRange;
_Spell Spells[MAX_ITEM_PROTO_SPELLS];
uint32 Bonding;
- std::string Description;
+ std::string Description;
uint32 PageText;
uint32 LanguageID;
uint32 PageMaterial;
@@ -641,7 +672,6 @@ struct ItemTemplate
uint32 Sheath;
int32 RandomProperty; // id from ItemRandomProperties.dbc
int32 RandomSuffix; // id from ItemRandomSuffix.dbc
- uint32 Block;
uint32 ItemSet; // id from ItemSet.dbc
uint32 MaxDurability;
uint32 Area; // id from AreaTable.dbc
@@ -651,13 +681,23 @@ struct ItemTemplate
_Socket Socket[MAX_ITEM_PROTO_SOCKETS];
uint32 socketBonus; // id from SpellItemEnchantment.dbc
uint32 GemProperties; // id from GemProperties.dbc
- uint32 RequiredDisenchantSkill;
float ArmorDamageModifier;
uint32 Duration;
uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc
uint32 HolidayId; // id from Holidays.dbc
+ float StatScalingFactor;
+ uint32 CurrencySubstitutionId; // May be used instead of a currency
+ uint32 CurrencySubstitutionCount;
+
+ // extra fields, not part of db2 files
+ float DamageMin;
+ float DamageMax;
+ float DPS;
+ uint32 Armor;
+ float SpellPPMRate;
uint32 ScriptId;
uint32 DisenchantID;
+ uint32 RequiredDisenchantSkill;
uint32 FoodType;
uint32 MinMoneyLoot;
uint32 MaxMoneyLoot;
@@ -691,29 +731,6 @@ struct ItemTemplate
return (Stackable == 2147483647 || Stackable <= 0) ? uint32(0x7FFFFFFF-1) : uint32(Stackable);
}
- float getDPS() const
- {
- if (Delay == 0)
- return 0;
- float temp = 0;
- for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
- temp+=Damage[i].DamageMin + Damage[i].DamageMax;
- return temp*500/Delay;
- }
-
- int32 getFeralBonus(int32 extraDPS = 0) const
- {
- // 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc
- if (Class == ITEM_CLASS_WEAPON && (1<<SubClass)&0x02A5F3)
- {
- int32 bonus = int32((extraDPS + getDPS())*14.0f) - 767;
- if (bonus < 0)
- return 0;
- return bonus;
- }
- return 0;
- }
-
float GetItemLevelIncludingQuality() const
{
float itemLevel = (float)ItemLevel;
@@ -738,9 +755,16 @@ struct ItemTemplate
}
bool IsPotion() const { return Class == ITEM_CLASS_CONSUMABLE && SubClass == ITEM_SUBCLASS_POTION; }
- bool IsWeaponVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_WEAPON_ENCHANTMENT; }
- bool IsArmorVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_ARMOR_ENCHANTMENT; }
+ bool IsVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_ENCHANTMENT; }
bool IsConjuredConsumable() const { return Class == ITEM_CLASS_CONSUMABLE && (Flags & ITEM_PROTO_FLAG_CONJURED); }
+
+ bool IsRangedWeapon() const
+ {
+ return Class == ITEM_CLASS_WEAPON ||
+ SubClass == ITEM_SUBCLASS_WEAPON_BOW ||
+ SubClass == ITEM_SUBCLASS_WEAPON_GUN ||
+ SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW;
+ }
};
// Benchmarked: Faster than std::map (insert/find)
@@ -752,15 +776,4 @@ struct ItemLocale
StringVector Description;
};
-struct ItemSetNameEntry
-{
- std::string name;
- uint32 InventoryType;
-};
-
-struct ItemSetNameLocale
-{
- StringVector Name;
-};
-
#endif
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index dfc0c438662..51087e0f966 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -47,6 +47,7 @@
#include "OutdoorPvPMgr.h"
#include "MovementPacketBuilder.h"
#include "DynamicTree.h"
+#include "Unit.h"
#include "Group.h"
#include "BattlefieldMgr.h"
#include "Battleground.h"
@@ -64,6 +65,7 @@ uint32 GuidHigh2TypeId(uint32 guid_hi)
case HIGHGUID_GAMEOBJECT: return TYPEID_GAMEOBJECT;
case HIGHGUID_DYNAMICOBJECT:return TYPEID_DYNAMICOBJECT;
case HIGHGUID_CORPSE: return TYPEID_CORPSE;
+ case HIGHGUID_AREATRIGGER: return TYPEID_AREATRIGGER;
case HIGHGUID_MO_TRANSPORT: return TYPEID_GAMEOBJECT;
case HIGHGUID_VEHICLE: return TYPEID_UNIT;
}
@@ -138,8 +140,8 @@ void Object::_Create(uint32 guidlow, uint32 entry, HighGuid guidhigh)
uint64 guid = MAKE_NEW_GUID(guidlow, entry, guidhigh);
SetUInt64Value(OBJECT_FIELD_GUID, guid);
- SetUInt32Value(OBJECT_FIELD_TYPE, m_objectType);
- m_PackGUID.wpos(0);
+ SetUInt16Value(OBJECT_FIELD_TYPE, 0, m_objectType);
+ m_PackGUID.clear();
m_PackGUID.appendPackGUID(GetGUID());
}
@@ -175,18 +177,6 @@ void Object::RemoveFromWorld()
ClearUpdateMask(true);
}
-void Object::BuildMovementUpdateBlock(UpdateData* data, uint32 flags) const
-{
- ByteBuffer buf(500);
-
- buf << uint8(UPDATETYPE_MOVEMENT);
- buf.append(GetPackGUID());
-
- BuildMovementUpdate(&buf, flags);
-
- data->AddUpdateBlock(buf);
-}
-
void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const
{
if (!target)
@@ -199,16 +189,36 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
if (target == this) // building packet for yourself
flags |= UPDATEFLAG_SELF;
- if (flags & UPDATEFLAG_STATIONARY_POSITION)
+ switch (GetGUIDHigh())
{
- // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
- if (isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER))
+ case HIGHGUID_PLAYER:
+ case HIGHGUID_PET:
+ case HIGHGUID_CORPSE:
+ case HIGHGUID_DYNAMICOBJECT:
+ case HIGHGUID_AREATRIGGER:
updateType = UPDATETYPE_CREATE_OBJECT2;
+ break;
+ case HIGHGUID_UNIT:
+ case HIGHGUID_VEHICLE:
+ {
+ if (TempSummon const* summon = ToUnit()->ToTempSummon())
+ if (IS_PLAYER_GUID(summon->GetSummonerGUID()))
+ updateType = UPDATETYPE_CREATE_OBJECT2;
- // UPDATETYPE_CREATE_OBJECT2 for pets...
- if (target->GetPetGUID() == GetGUID())
- updateType = UPDATETYPE_CREATE_OBJECT2;
+ break;
+ }
+ case HIGHGUID_GAMEOBJECT:
+ {
+ if (IS_PLAYER_GUID(ToGameObject()->GetOwnerGUID()))
+ updateType = UPDATETYPE_CREATE_OBJECT2;
+ break;
+ }
+ default:
+ break;
+ }
+ if (flags & UPDATEFLAG_STATIONARY_POSITION)
+ {
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
if (isType(TYPEMASK_GAMEOBJECT))
{
@@ -224,15 +234,11 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
break;
}
}
-
- if (isType(TYPEMASK_UNIT))
- {
- if (ToUnit()->GetVictim())
- flags |= UPDATEFLAG_HAS_TARGET;
- }
}
- //TC_LOG_DEBUG("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updateType, m_objectTypeId, flags, flags2);
+ if (Unit const* unit = ToUnit())
+ if (unit->GetVictim())
+ flags |= UPDATEFLAG_HAS_TARGET;
ByteBuffer buf(500);
buf << uint8(updateType);
@@ -247,7 +253,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
void Object::SendUpdateToPlayer(Player* player)
{
// send create update to player
- UpdateData upd;
+ UpdateData upd(player->GetMapId());
WorldPacket packet;
BuildCreateUpdateBlockForPlayer(&upd, player);
@@ -337,139 +343,315 @@ uint16 Object::GetUInt16Value(uint16 index, uint8 offset) const
void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
{
- Unit const* unit = NULL;
- WorldObject const* object = NULL;
+ Unit const* self = NULL;
+ ObjectGuid guid = GetGUID();
+ uint32 movementFlags = 0;
+ uint16 movementFlagsExtra = 0;
+
+ bool hasTransportTime2 = false;
+ bool hasTransportTime3 = false;
+ bool hasFallDirection = false;
+ bool hasFallData = false;
+ bool hasPitch = false;
+ bool hasSpline = false;
+ bool hasSplineElevation = false;
+
+ uint32 unkLoopCounter = 0;
+ // Bit content
+ data->WriteBit(0);
+ data->WriteBit(0);
+ data->WriteBit(flags & UPDATEFLAG_ROTATION);
+ data->WriteBit(flags & UPDATEFLAG_ANIMKITS);
+ data->WriteBit(flags & UPDATEFLAG_HAS_TARGET);
+ data->WriteBit(flags & UPDATEFLAG_SELF);
+ data->WriteBit(flags & UPDATEFLAG_VEHICLE);
+ data->WriteBit(flags & UPDATEFLAG_LIVING);
+ data->WriteBits(unkLoopCounter, 24);
+ data->WriteBit(0);
+ data->WriteBit(flags & UPDATEFLAG_GO_TRANSPORT_POSITION);
+ data->WriteBit(flags & UPDATEFLAG_STATIONARY_POSITION);
+ data->WriteBit(flags & UPDATEFLAG_UNK5);
+ data->WriteBit(0);
+ data->WriteBit(flags & UPDATEFLAG_TRANSPORT);
- if (isType(TYPEMASK_UNIT))
- unit = ToUnit();
- else
- object = (WorldObject const*)this;
-
- *data << uint16(flags); // update flags
-
- // 0x20
if (flags & UPDATEFLAG_LIVING)
{
- ASSERT(unit);
- unit->BuildMovementPacket(data);
+ self = ToUnit();
+ movementFlags = self->m_movementInfo.GetMovementFlags();
+ movementFlagsExtra = self->m_movementInfo.GetExtraMovementFlags();
+ hasSpline = self->IsSplineEnabled();
+
+ hasTransportTime2 = self->m_movementInfo.transport.guid != 0 && self->m_movementInfo.transport.time2 != 0;
+ hasTransportTime3 = false;
+ hasPitch = self->HasUnitMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || self->HasExtraUnitMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING);
+ hasFallDirection = self->HasUnitMovementFlag(MOVEMENTFLAG_FALLING);
+ hasFallData = hasFallDirection || self->m_movementInfo.jump.fallTime != 0;
+ hasSplineElevation = self->HasUnitMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION);
- *data << unit->GetSpeed(MOVE_WALK)
- << unit->GetSpeed(MOVE_RUN)
- << unit->GetSpeed(MOVE_RUN_BACK)
- << unit->GetSpeed(MOVE_SWIM)
- << unit->GetSpeed(MOVE_SWIM_BACK)
- << unit->GetSpeed(MOVE_FLIGHT)
- << unit->GetSpeed(MOVE_FLIGHT_BACK)
- << unit->GetSpeed(MOVE_TURN_RATE)
- << unit->GetSpeed(MOVE_PITCH_RATE);
+ if (GetTypeId() == TYPEID_UNIT)
+ movementFlags &= MOVEMENTFLAG_MASK_CREATURE_ALLOWED;
+
+ data->WriteBit(!movementFlags);
+ data->WriteBit(G3D::fuzzyEq(self->GetOrientation(), 0.0f)); // Has Orientation
+ data->WriteBit(guid[7]);
+ data->WriteBit(guid[3]);
+ data->WriteBit(guid[2]);
+ if (movementFlags)
+ data->WriteBits(movementFlags, 30);
+
+ data->WriteBit(hasSpline && GetTypeId() == TYPEID_PLAYER); // Has spline (from MovementInfo)
+ data->WriteBit(!hasPitch); // Has pitch
+ data->WriteBit(hasSpline); // Has spline data (independent)
+ data->WriteBit(hasFallData); // Has fall data
+ data->WriteBit(!hasSplineElevation); // Has spline elevation
+ data->WriteBit(guid[5]);
+ data->WriteBit(self->m_movementInfo.transport.guid); // Has transport data
+ data->WriteBit(0); // Is missing time
+
+ if (self->m_movementInfo.transport.guid)
+ {
+ ObjectGuid transGuid = self->m_movementInfo.transport.guid;
+
+ data->WriteBit(transGuid[1]);
+ data->WriteBit(hasTransportTime2); // Has transport time 2
+ data->WriteBit(transGuid[4]);
+ data->WriteBit(transGuid[0]);
+ data->WriteBit(transGuid[6]);
+ data->WriteBit(hasTransportTime3); // Has transport time 3
+ data->WriteBit(transGuid[7]);
+ data->WriteBit(transGuid[5]);
+ data->WriteBit(transGuid[3]);
+ data->WriteBit(transGuid[2]);
+ }
+
+ data->WriteBit(guid[4]);
- // 0x08000000
- if (unit->m_movementInfo.GetMovementFlags() & MOVEMENTFLAG_SPLINE_ENABLED)
- Movement::PacketBuilder::WriteCreate(*unit->movespline, *data);
+ if (hasSpline)
+ Movement::PacketBuilder::WriteCreateBits(*self->movespline, *data);
+
+ data->WriteBit(guid[6]);
+ if (hasFallData)
+ data->WriteBit(hasFallDirection);
+
+ data->WriteBit(guid[0]);
+ data->WriteBit(guid[1]);
+ data->WriteBit(0);
+ data->WriteBit(!movementFlagsExtra);
+ if (movementFlagsExtra)
+ data->WriteBits(movementFlagsExtra, 12);
}
- else
+
+ if (flags & UPDATEFLAG_GO_TRANSPORT_POSITION)
{
- if (flags & UPDATEFLAG_POSITION)
- {
- ASSERT(object);
- Transport* transport = object->GetTransport();
+ WorldObject const* self = static_cast<WorldObject const*>(this);
+ ObjectGuid transGuid = self->m_movementInfo.transport.guid;
+ data->WriteBit(transGuid[5]);
+ data->WriteBit(0); // Has GO transport time 3
+ data->WriteBit(transGuid[0]);
+ data->WriteBit(transGuid[3]);
+ data->WriteBit(transGuid[6]);
+ data->WriteBit(transGuid[1]);
+ data->WriteBit(transGuid[4]);
+ data->WriteBit(transGuid[2]);
+ data->WriteBit(0); // Has GO transport time 2
+ data->WriteBit(transGuid[7]);
+ }
- if (transport)
- data->append(transport->GetPackGUID());
- else
- *data << uint8(0);
+ if (flags & UPDATEFLAG_HAS_TARGET)
+ {
+ ObjectGuid victimGuid = self->GetVictim()->GetGUID(); // checked in BuildCreateUpdateBlockForPlayer
+ data->WriteBit(victimGuid[2]);
+ data->WriteBit(victimGuid[7]);
+ data->WriteBit(victimGuid[0]);
+ data->WriteBit(victimGuid[4]);
+ data->WriteBit(victimGuid[5]);
+ data->WriteBit(victimGuid[6]);
+ data->WriteBit(victimGuid[1]);
+ data->WriteBit(victimGuid[3]);
+ }
- *data << object->GetPositionX();
- *data << object->GetPositionY();
- if (isType(TYPEMASK_UNIT))
- *data << unit->GetPositionZMinusOffset();
- else
- *data << object->GetPositionZ();
+ if (flags & UPDATEFLAG_ANIMKITS)
+ {
+ data->WriteBit(1); // Missing AnimKit1
+ data->WriteBit(1); // Missing AnimKit2
+ data->WriteBit(1); // Missing AnimKit3
+ }
- if (transport)
- {
- *data << object->GetTransOffsetX();
- *data << object->GetTransOffsetY();
- *data << object->GetTransOffsetZ();
- }
- else
- {
- *data << object->GetPositionX();
- *data << object->GetPositionY();
- if (isType(TYPEMASK_UNIT))
- *data << unit->GetPositionZMinusOffset();
- else
- *data << object->GetPositionZ();
- }
+ data->FlushBits();
- *data << object->GetOrientation();
+ // Data
+ for (uint32 i = 0; i < unkLoopCounter; ++i)
+ *data << uint32(0);
- if (GetTypeId() == TYPEID_CORPSE)
- *data << float(object->GetOrientation());
- else
- *data << float(0);
- }
- else
+ if (flags & UPDATEFLAG_LIVING)
+ {
+ data->WriteByteSeq(guid[4]);
+ *data << self->GetSpeed(MOVE_RUN_BACK);
+
+ if (hasFallData)
{
- // 0x40
- if (flags & UPDATEFLAG_STATIONARY_POSITION)
+ if (hasFallDirection)
{
- ASSERT(object);
- *data << object->GetStationaryX();
- *data << object->GetStationaryY();
- *data << object->GetStationaryZ();
- *data << object->GetStationaryO();
+ *data << float(self->m_movementInfo.jump.xyspeed);
+ *data << float(self->m_movementInfo.jump.sinAngle);
+ *data << float(self->m_movementInfo.jump.cosAngle);
}
+
+ *data << uint32(self->m_movementInfo.jump.fallTime);
+ *data << float(self->m_movementInfo.jump.zspeed);
+ }
+
+ *data << self->GetSpeed(MOVE_SWIM_BACK);
+ if (hasSplineElevation)
+ *data << float(self->m_movementInfo.splineElevation);
+
+ if (hasSpline)
+ Movement::PacketBuilder::WriteCreateData(*self->movespline, *data);
+
+ *data << float(self->GetPositionZMinusOffset());
+ data->WriteByteSeq(guid[5]);
+
+ if (self->m_movementInfo.transport.guid)
+ {
+ ObjectGuid transGuid = self->m_movementInfo.transport.guid;
+
+ data->WriteByteSeq(transGuid[5]);
+ data->WriteByteSeq(transGuid[7]);
+ *data << uint32(self->GetTransTime());
+ *data << float(self->GetTransOffsetO());
+ if (hasTransportTime2)
+ *data << uint32(self->m_movementInfo.transport.time2);
+
+ *data << float(self->GetTransOffsetY());
+ *data << float(self->GetTransOffsetX());
+ data->WriteByteSeq(transGuid[3]);
+ *data << float(self->GetTransOffsetZ());
+ data->WriteByteSeq(transGuid[0]);
+ if (hasTransportTime3)
+ *data << uint32(self->m_movementInfo.transport.time3);
+
+ *data << int8(self->GetTransSeat());
+ data->WriteByteSeq(transGuid[1]);
+ data->WriteByteSeq(transGuid[6]);
+ data->WriteByteSeq(transGuid[2]);
+ data->WriteByteSeq(transGuid[4]);
}
+
+ *data << float(self->GetPositionX());
+ *data << self->GetSpeed(MOVE_PITCH_RATE);
+ data->WriteByteSeq(guid[3]);
+ data->WriteByteSeq(guid[0]);
+ *data << self->GetSpeed(MOVE_SWIM);
+ *data << float(self->GetPositionY());
+ data->WriteByteSeq(guid[7]);
+ data->WriteByteSeq(guid[1]);
+ data->WriteByteSeq(guid[2]);
+ *data << self->GetSpeed(MOVE_WALK);
+
+ //if (true) // Has time, controlled by bit just after HasTransport
+ *data << uint32(getMSTime());
+
+ *data << self->GetSpeed(MOVE_TURN_RATE);
+ data->WriteByteSeq(guid[6]);
+ *data << self->GetSpeed(MOVE_FLIGHT);
+ if (!G3D::fuzzyEq(self->GetOrientation(), 0.0f))
+ *data << float(self->GetOrientation());
+
+ *data << self->GetSpeed(MOVE_RUN);
+ if (hasPitch)
+ *data << float(self->m_movementInfo.pitch);
+
+ *data << self->GetSpeed(MOVE_FLIGHT_BACK);
}
- // 0x8
- if (flags & UPDATEFLAG_UNKNOWN)
+ if (flags & UPDATEFLAG_VEHICLE)
{
- *data << uint32(0);
+ *data << float(self->GetOrientation());
+ *data << uint32(self->GetVehicleKit()->GetVehicleInfo()->m_ID);
}
- // 0x10
- if (flags & UPDATEFLAG_LOWGUID)
+ if (flags & UPDATEFLAG_GO_TRANSPORT_POSITION)
{
- switch (GetTypeId())
- {
- case TYPEID_OBJECT:
- case TYPEID_ITEM:
- case TYPEID_CONTAINER:
- case TYPEID_GAMEOBJECT:
- case TYPEID_DYNAMICOBJECT:
- case TYPEID_CORPSE:
- *data << uint32(GetGUIDLow()); // GetGUIDLow()
- break;
- //! Unit, Player and default here are sending wrong values.
- /// @todo Research the proper formula
- case TYPEID_UNIT:
- *data << uint32(0x0000000B); // unk
- break;
- case TYPEID_PLAYER:
- if (flags & UPDATEFLAG_SELF)
- *data << uint32(0x0000002F); // unk
- else
- *data << uint32(0x00000008); // unk
- break;
- default:
- *data << uint32(0x00000000); // unk
- break;
- }
+ WorldObject const* self = static_cast<WorldObject const*>(this);
+ ObjectGuid transGuid = self->m_movementInfo.transport.guid;
+
+ data->WriteBit(transGuid[0]);
+ data->WriteBit(transGuid[5]);
+ if (hasTransportTime3)
+ *data << uint32(self->m_movementInfo.transport.time3);
+
+ data->WriteBit(transGuid[3]);
+ *data << float(self->GetTransOffsetX());
+ data->WriteBit(transGuid[4]);
+ data->WriteBit(transGuid[6]);
+ data->WriteBit(transGuid[1]);
+ *data << uint32(self->GetTransTime());
+ *data << float(self->GetTransOffsetY());
+ data->WriteBit(transGuid[2]);
+ data->WriteBit(transGuid[7]);
+ *data << float(self->GetTransOffsetZ());
+ *data << int8(self->GetTransSeat());
+ *data << float(self->GetTransOffsetO());
+ if (hasTransportTime2)
+ *data << uint32(self->m_movementInfo.transport.time2);
}
- // 0x4
- if (flags & UPDATEFLAG_HAS_TARGET)
+ if (flags & UPDATEFLAG_ROTATION)
+ *data << uint64(ToGameObject()->GetRotation());
+
+ if (flags & UPDATEFLAG_UNK5)
+ {
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << uint8(0);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ *data << float(0.0f);
+ }
+
+ if (flags & UPDATEFLAG_STATIONARY_POSITION)
{
- ASSERT(unit);
- if (Unit* victim = unit->GetVictim())
- data->append(victim->GetPackGUID());
- else
- *data << uint8(0);
+ WorldObject const* self = static_cast<WorldObject const*>(this);
+ *data << float(self->GetStationaryO());
+ *data << float(self->GetStationaryX());
+ *data << float(self->GetStationaryY());
+ *data << float(self->GetStationaryZ());
}
- // 0x2
+ if (flags & UPDATEFLAG_HAS_TARGET)
+ {
+ ObjectGuid victimGuid = self->GetVictim()->GetGUID(); // checked in BuildCreateUpdateBlockForPlayer
+ data->WriteByteSeq(victimGuid[4]);
+ data->WriteByteSeq(victimGuid[0]);
+ data->WriteByteSeq(victimGuid[3]);
+ data->WriteByteSeq(victimGuid[5]);
+ data->WriteByteSeq(victimGuid[7]);
+ data->WriteByteSeq(victimGuid[6]);
+ data->WriteByteSeq(victimGuid[2]);
+ data->WriteByteSeq(victimGuid[1]);
+ }
+
+ //if (flags & UPDATEFLAG_ANIMKITS)
+ //{
+ // if (hasAnimKit1)
+ // *data << uint16(animKit1);
+ // if (hasAnimKit2)
+ // *data << uint16(animKit2);
+ // if (hasAnimKit3)
+ // *data << uint16(animKit3);
+ //}
+
if (flags & UPDATEFLAG_TRANSPORT)
{
GameObject const* go = ToGameObject();
@@ -483,24 +665,6 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
else
*data << uint32(getMSTime());
}
-
- // 0x80
- if (flags & UPDATEFLAG_VEHICLE)
- {
- /// @todo Allow players to aquire this updateflag.
- ASSERT(unit);
- ASSERT(unit->GetVehicleKit());
- ASSERT(unit->GetVehicleKit()->GetVehicleInfo());
- *data << uint32(unit->GetVehicleKit()->GetVehicleInfo()->m_ID);
- if (unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
- *data << float(unit->GetTransOffsetO());
- else
- *data << float(unit->GetOrientation());
- }
-
- // 0x200
- if (flags & UPDATEFLAG_ROTATION)
- *data << int64(ToGameObject()->GetRotation());
}
void Object::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
@@ -548,7 +712,7 @@ void Object::BuildFieldsUpdate(Player* player, UpdateDataMapType& data_map) cons
if (iter == data_map.end())
{
- std::pair<UpdateDataMapType::iterator, bool> p = data_map.emplace(player, UpdateData());
+ std::pair<UpdateDataMapType::iterator, bool> p = data_map.emplace(player, UpdateData(player->GetMapId()));
ASSERT(p.second);
iter = p.first;
}
@@ -602,6 +766,9 @@ uint32 Object::GetUpdateFieldData(Player const* target, uint32*& flags) const
if (ToCorpse()->GetOwnerGUID() == target->GetGUID())
visibleFlag |= UF_FLAG_OWNER;
break;
+ case TYPEID_AREATRIGGER:
+ flags = AreaTriggerUpdateFieldFlags;
+ break;
case TYPEID_OBJECT:
break;
}
@@ -1072,11 +1239,11 @@ void MovementInfo::OutDebug()
{
TC_LOG_INFO("misc", "MOVEMENT INFO");
TC_LOG_INFO("misc", "guid " UI64FMTD, guid);
- TC_LOG_INFO("misc", "flags %u", flags);
- TC_LOG_INFO("misc", "flags2 %u", flags2);
- TC_LOG_INFO("misc", "time %u current time " UI64FMTD "", flags2, uint64(::time(NULL)));
+ TC_LOG_INFO("misc", "flags %s (%u)", Movement::MovementFlags_ToString(flags).c_str(), flags);
+ TC_LOG_INFO("misc", "flags2 %s (%u)", Movement::MovementFlagsExtra_ToString(flags2).c_str(), flags2);
+ TC_LOG_INFO("misc", "time %u current time %u", time, getMSTime());
TC_LOG_INFO("misc", "position: `%s`", pos.ToString().c_str());
- if (flags & MOVEMENTFLAG_ONTRANSPORT)
+ if (transport.guid)
{
TC_LOG_INFO("misc", "TRANSPORT:");
TC_LOG_INFO("misc", "guid: " UI64FMTD, transport.guid);
@@ -1085,14 +1252,19 @@ void MovementInfo::OutDebug()
TC_LOG_INFO("misc", "time: %u", transport.time);
if (flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT)
TC_LOG_INFO("misc", "time2: %u", transport.time2);
+ if (transport.time3)
+ TC_LOG_INFO("misc", "time3: %u", transport.time3);
}
if ((flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING))
TC_LOG_INFO("misc", "pitch: %f", pitch);
- TC_LOG_INFO("misc", "fallTime: %u", fallTime);
- if (flags & MOVEMENTFLAG_FALLING)
- TC_LOG_INFO("misc", "j_zspeed: %f j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", jump.zspeed, jump.sinAngle, jump.cosAngle, jump.xyspeed);
+ if (flags & MOVEMENTFLAG_FALLING || jump.fallTime)
+ {
+ TC_LOG_INFO("misc", "fallTime: %u j_zspeed: %f", jump.fallTime, jump.zspeed);
+ if (flags & MOVEMENTFLAG_FALLING)
+ TC_LOG_INFO("misc", "j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", jump.sinAngle, jump.cosAngle, jump.xyspeed);
+ }
if (flags & MOVEMENTFLAG_SPLINE_ELEVATION)
TC_LOG_INFO("misc", "splineElevation: %f", splineElevation);
@@ -1324,7 +1496,7 @@ bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool
bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D /*= true*/) const
{
- return obj && IsInMap(obj) && InSamePhase(obj) && _IsWithinDist(obj, dist2compare, is3D);
+ return obj && IsInMap(obj) && IsInPhase(obj) && _IsWithinDist(obj, dist2compare, is3D);
}
bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const
@@ -1763,7 +1935,7 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
bool WorldObject::CanNeverSee(WorldObject const* obj) const
{
- return GetMap() != obj->GetMap() || !InSamePhase(obj);
+ return GetMap() != obj->GetMap() || !IsInPhase(obj);
}
bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth) const
@@ -1795,13 +1967,6 @@ bool WorldObject::CanDetectInvisibilityOf(WorldObject const* obj) const
if (mask != obj->m_invisibility.GetFlags())
return false;
- // It isn't possible in invisibility to detect something that can't detect the invisible object
- // (it's at least true for spell: 66)
- // It seems like that only Units are affected by this check (couldn't see arena doors with preparation invisibility)
- if (obj->ToUnit())
- if ((m_invisibility.GetFlags() & obj->m_invisibilityDetect.GetFlags()) != m_invisibility.GetFlags())
- return false;
-
for (uint32 i = 0; i < TOTAL_INVISIBILITY_TYPES; ++i)
{
if (!(mask & (1 << i)))
@@ -1881,7 +2046,8 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const
void WorldObject::SendPlaySound(uint32 Sound, bool OnlySelf)
{
WorldPacket data(SMSG_PLAY_SOUND, 4);
- data << Sound;
+ data << uint32(Sound);
+ data << uint64(GetGUID());
if (OnlySelf && GetTypeId() == TYPEID_PLAYER)
this->ToPlayer()->GetSession()->SendPacket(&data);
else
@@ -2041,13 +2207,6 @@ void WorldObject::MonsterWhisper(int32 textId, Player const* target, bool IsBoss
target->GetSession()->SendPacket(&data);
}
-void Unit::BuildHeartBeatMsg(WorldPacket* data) const
-{
- data->Initialize(MSG_MOVE_HEARTBEAT, 32);
- data->append(GetPackGUID());
- BuildMovementPacket(data);
-}
-
void WorldObject::SendMessageToSet(WorldPacket* data, bool self)
{
if (IsInWorld())
@@ -2173,9 +2332,9 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
}
}
- uint32 phase = PHASEMASK_NORMAL;
+ std::set<uint32> phases;
if (summoner)
- phase = summoner->GetPhaseMask();
+ phases = summoner->GetPhases();
TempSummon* summon = NULL;
switch (mask)
@@ -2197,12 +2356,16 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
break;
}
- if (!summon->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), this, phase, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), nullptr, vehId))
+ if (!summon->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), this, 0, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), nullptr, vehId))
{
delete summon;
return NULL;
}
+ // Set the summon to the summoner's phase
+ for (auto phaseId : phases)
+ summon->SetInPhase(phaseId, false, true);
+
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId);
summon->SetHomePosition(pos);
@@ -2297,6 +2460,9 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float
return NULL;
}
+ for (auto phase : GetPhases())
+ go->SetInPhase(phase, false, true);
+
go->SetRespawnTime(respawnTime);
if (GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT) //not sure how to handle this
ToUnit()->AddGameObject(go);
@@ -2699,9 +2865,36 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
UpdateObjectVisibility();
}
+void WorldObject::SetInPhase(uint32 id, bool update, bool apply)
+{
+ if (apply)
+ _phases.insert(id);
+ else
+ _phases.erase(id);
+
+ if (update && IsInWorld())
+ UpdateObjectVisibility();
+}
+
+bool WorldObject::IsInPhase(WorldObject const* obj) const
+{
+ // PhaseId 169 is the default fallback phase
+ if (_phases.empty() && obj->GetPhases().empty())
+ return true;
+
+ if (_phases.empty() && obj->IsInPhase(169))
+ return true;
+
+ if (obj->GetPhases().empty() && IsInPhase(169))
+ return true;
+
+ return Trinity::Containers::Intersects(_phases.begin(), _phases.end(), obj->GetPhases().begin(), obj->GetPhases().end());
+}
+
bool WorldObject::InSamePhase(WorldObject const* obj) const
{
- return InSamePhase(obj->GetPhaseMask());
+ return IsInPhase(obj);
+ // return InSamePhase(obj->GetPhaseMask());
}
void WorldObject::PlayDistanceSound(uint32 sound_id, Player* target /*= NULL*/)
@@ -2719,6 +2912,7 @@ void WorldObject::PlayDirectSound(uint32 sound_id, Player* target /*= NULL*/)
{
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << uint32(sound_id);
+ data << uint64(GetGUID());
if (target)
target->SendDirectMessage(&data);
else
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index b82ca1cb0b2..87f94008455 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -56,6 +56,7 @@ enum TypeMask
TYPEMASK_GAMEOBJECT = 0x0020,
TYPEMASK_DYNAMICOBJECT = 0x0040,
TYPEMASK_CORPSE = 0x0080,
+ TYPEMASK_AREATRIGGER = 0x0100,
TYPEMASK_SEER = TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT
};
@@ -68,10 +69,11 @@ enum TypeID
TYPEID_PLAYER = 4,
TYPEID_GAMEOBJECT = 5,
TYPEID_DYNAMICOBJECT = 6,
- TYPEID_CORPSE = 7
+ TYPEID_CORPSE = 7,
+ TYPEID_AREATRIGGER = 8
};
-#define NUM_CLIENT_OBJECT_TYPES 8
+#define NUM_CLIENT_OBJECT_TYPES 9
uint32 GuidHigh2TypeId(uint32 guid_hi);
@@ -118,6 +120,62 @@ class ZoneScript;
typedef std::unordered_map<Player*, UpdateData> UpdateDataMapType;
+//! Structure to ease conversions from single 64 bit integer guid into individual bytes, for packet sending purposes
+//! Nuke this out when porting ObjectGuid from MaNGOS, but preserve the per-byte storage
+struct ObjectGuid
+{
+ public:
+ ObjectGuid() { _data.u64 = UI64LIT(0); }
+ ObjectGuid(uint64 guid) { _data.u64 = guid; }
+ ObjectGuid(ObjectGuid const& other) { _data.u64 = other._data.u64; }
+
+ uint8& operator[](uint32 index)
+ {
+ ASSERT(index < sizeof(uint64));
+
+#if TRINITY_ENDIAN == TRINITY_LITTLEENDIAN
+ return _data.byte[index];
+#else
+ return _data.byte[7 - index];
+#endif
+ }
+
+ uint8 const& operator[](uint32 index) const
+ {
+ ASSERT(index < sizeof(uint64));
+
+#if TRINITY_ENDIAN == TRINITY_LITTLEENDIAN
+ return _data.byte[index];
+#else
+ return _data.byte[7 - index];
+#endif
+ }
+
+ operator uint64()
+ {
+ return _data.u64;
+ }
+
+ ObjectGuid& operator=(uint64 guid)
+ {
+ _data.u64 = guid;
+ return *this;
+ }
+
+ ObjectGuid& operator=(ObjectGuid const& other)
+ {
+ _data.u64 = other._data.u64;
+ return *this;
+ }
+
+ private:
+ union
+ {
+ uint64 u64;
+ uint8 byte[8];
+ } _data;
+};
+
class Object
{
public:
@@ -147,7 +205,6 @@ class Object
void BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) const;
void BuildOutOfRangeUpdateBlock(UpdateData* data) const;
- void BuildMovementUpdateBlock(UpdateData* data, uint32 flags = 0) const;
virtual void DestroyForPlayer(Player* target, bool onDeath = false) const;
@@ -229,6 +286,9 @@ class Object
DynamicObject* ToDynObject() { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast<DynamicObject*>(this); else return NULL; }
DynamicObject const* ToDynObject() const { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast<DynamicObject const*>(this); else return NULL; }
+ AreaTrigger* ToAreaTrigger() { if (GetTypeId() == TYPEID_AREATRIGGER) return reinterpret_cast<AreaTrigger*>(this); else return NULL; }
+ AreaTrigger const* ToAreaTrigger() const { if (GetTypeId() == TYPEID_AREATRIGGER) return reinterpret_cast<AreaTrigger const*>(this); else return NULL; }
+
protected:
Object();
@@ -426,6 +486,7 @@ struct MovementInfo
seat = -1;
time = 0;
time2 = 0;
+ time3 = 0;
}
uint64 guid;
@@ -433,22 +494,23 @@ struct MovementInfo
int8 seat;
uint32 time;
uint32 time2;
+ uint32 time3;
} transport;
// swimming/flying
float pitch;
- // falling
- uint32 fallTime;
-
- // jumping
+ // jumping
struct JumpInfo
{
void Reset()
{
+ fallTime = 0;
zspeed = sinAngle = cosAngle = xyspeed = 0.0f;
}
+ uint32 fallTime;
+
float zspeed, sinAngle, cosAngle, xyspeed;
} jump;
@@ -457,7 +519,7 @@ struct MovementInfo
float splineElevation;
MovementInfo() :
- guid(0), flags(0), flags2(0), time(0), pitch(0.0f), fallTime(0), splineElevation(0.0f)
+ guid(0), flags(0), flags2(0), time(0), pitch(0.0f), splineElevation(0.0f)
{
pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
transport.Reset();
@@ -471,10 +533,23 @@ struct MovementInfo
bool HasMovementFlag(uint32 flag) const { return (flags & flag) != 0; }
uint16 GetExtraMovementFlags() const { return flags2; }
+ void SetExtraMovementFlags(uint16 flag) { flags2 = flag; }
void AddExtraMovementFlag(uint16 flag) { flags2 |= flag; }
+ void RemoveExtraMovementFlag(uint16 flag) { flags2 &= ~flag; }
bool HasExtraMovementFlag(uint16 flag) const { return (flags2 & flag) != 0; }
- void SetFallTime(uint32 time) { fallTime = time; }
+ uint32 GetFallTime() const { return jump.fallTime; }
+ void SetFallTime(uint32 time) { jump.fallTime = time; }
+
+ void ResetTransport()
+ {
+ transport.Reset();
+ }
+
+ void ResetJump()
+ {
+ jump.Reset();
+ }
void OutDebug();
};
@@ -602,9 +677,13 @@ class WorldObject : public Object, public WorldLocation
uint32 GetInstanceId() const { return m_InstanceId; }
virtual void SetPhaseMask(uint32 newPhaseMask, bool update);
+ virtual void SetInPhase(uint32 id, bool update, bool apply);
uint32 GetPhaseMask() const { return m_phaseMask; }
bool InSamePhase(WorldObject const* obj) const;
bool InSamePhase(uint32 phasemask) const { return (GetPhaseMask() & phasemask) != 0; }
+ bool IsInPhase(uint32 phase) const { return _phases.find(phase) != _phases.end(); }
+ bool IsInPhase(WorldObject const* obj) const;
+ std::set<uint32> const& GetPhases() const { return _phases; }
uint32 GetZoneId() const;
uint32 GetAreaId() const;
@@ -787,6 +866,7 @@ class WorldObject : public Object, public WorldLocation
//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
+ std::set<uint32> _phases;
uint16 m_notifyflags;
uint16 m_executed_notifies;
diff --git a/src/server/game/Entities/Object/ObjectDefines.h b/src/server/game/Entities/Object/ObjectDefines.h
index 236f77caf5a..03a4f80bf60 100644
--- a/src/server/game/Entities/Object/ObjectDefines.h
+++ b/src/server/game/Entities/Object/ObjectDefines.h
@@ -23,18 +23,21 @@
enum HighGuid
{
- HIGHGUID_ITEM = 0x4000, // blizz 4000
- HIGHGUID_CONTAINER = 0x4000, // blizz 4000
- HIGHGUID_PLAYER = 0x0000, // blizz 0000
- HIGHGUID_GAMEOBJECT = 0xF110, // blizz F110
- 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_ITEM = 0x400, // blizz 4000
+ HIGHGUID_CONTAINER = 0x400, // blizz 4000
+ HIGHGUID_PLAYER = 0x000, // blizz 0000
+ HIGHGUID_GAMEOBJECT = 0xF11, // blizz F110
+ HIGHGUID_TRANSPORT = 0xF12, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT)
+ HIGHGUID_UNIT = 0xF13, // blizz F130
+ HIGHGUID_PET = 0xF14, // blizz F140
+ HIGHGUID_VEHICLE = 0xF15, // blizz F550
+ HIGHGUID_DYNAMICOBJECT = 0xF10, // blizz F100
HIGHGUID_CORPSE = 0xF101, // blizz F100
- HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
- HIGHGUID_GROUP = 0x1F50
+ HIGHGUID_AREATRIGGER = 0xF102, // blizz F100
+ HIGHGUID_BATTLEGROUND = 0x1F1, // new 4.x
+ HIGHGUID_MO_TRANSPORT = 0x1FC, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
+ HIGHGUID_GROUP = 0x1F5,
+ HIGHGUID_GUILD = 0x1FF // new 4.x
};
// used for creating values for respawn for example
@@ -53,6 +56,7 @@ inline bool IS_VEHICLE_GUID(uint64 guid);
inline bool IS_CRE_OR_VEH_GUID(uint64 guid);
inline bool IS_CRE_OR_VEH_OR_PET_GUID(uint64 guid);
inline bool IS_PLAYER_GUID(uint64 guid);
+inline bool IS_GUILD_GUID(uint64 guid);
inline bool IS_UNIT_GUID(uint64 guid);
inline bool IS_ITEM_GUID(uint64 guid);
inline bool IS_GAMEOBJECT_GUID(uint64 guid);
@@ -61,6 +65,7 @@ inline bool IS_CORPSE_GUID(uint64 guid);
inline bool IS_TRANSPORT_GUID(uint64 guid);
inline bool IS_MO_TRANSPORT_GUID(uint64 guid);
inline bool IS_GROUP_GUID(uint64 guid);
+inline bool IS_AREATRIGGER_GUID(uint64 guid);
// l - OBJECT_FIELD_GUID
// e - OBJECT_FIELD_ENTRY for GO (except GAMEOBJECT_TYPE_MO_TRANSPORT) and creatures or UNIT_FIELD_PETNUMBER for pets
@@ -145,6 +150,11 @@ bool IS_PLAYER_GUID(uint64 guid)
return guid != 0 && GUID_HIPART(guid) == HIGHGUID_PLAYER;
}
+bool IS_GUILD_GUID(uint64 guid)
+{
+ return GUID_HIPART(guid) == HIGHGUID_GUILD;
+}
+
bool IS_UNIT_GUID(uint64 guid)
{
return IS_CRE_OR_VEH_OR_PET_GUID(guid) || IS_PLAYER_GUID(guid);
@@ -185,28 +195,33 @@ bool IS_GROUP_GUID(uint64 guid)
return GUID_HIPART(guid) == HIGHGUID_GROUP;
}
+bool IS_AREATRIGGER_GUID(uint64 guid)
+{
+ return GUID_HIPART(guid) == HIGHGUID_AREATRIGGER;
+}
+
uint64 MAKE_NEW_GUID(uint32 l, uint32 e, uint32 h)
{
- return uint64(uint64(l) | (uint64(e) << 24) | (uint64(h) << 48));
+ return uint64(uint64(l) | (uint64(e) << 32) | (uint64(h) << ((h == HIGHGUID_CORPSE || h == HIGHGUID_AREATRIGGER) ? 48 : 52)));
}
uint32 GUID_HIPART(uint64 guid)
{
- return (uint32)((uint64(guid) >> 48) & 0x0000FFFF);
+ uint32 t = ((uint64(guid) >> 48) & 0x0000FFFF);
+ return (t == HIGHGUID_CORPSE || t == HIGHGUID_AREATRIGGER) ? t : ((t >> 4) & 0x00000FFF);
}
uint32 GUID_ENPART(uint64 x)
{
return IsGuidHaveEnPart(x)
- ? (uint32)((x >> 24) & UI64LIT(0x0000000000FFFFFF))
+ ? ((uint32)((x >> 32) & UI64LIT(0x00000000000FFFFF)))
: 0;
}
uint32 GUID_LOPART(uint64 x)
{
- return IsGuidHaveEnPart(x)
- ? (uint32)(x & UI64LIT(0x0000000000FFFFFF))
- : (uint32)(x & UI64LIT(0x00000000FFFFFFFF));
+ // _GUID_LOPART_3 and _GUID_LOPART_2 were both equal to PAIR64_LOPART
+ return PAIR64_LOPART(x);
}
bool IsGuidHaveEnPart(uint64 guid)
@@ -218,6 +233,7 @@ bool IsGuidHaveEnPart(uint64 guid)
case HIGHGUID_DYNAMICOBJECT:
case HIGHGUID_CORPSE:
case HIGHGUID_GROUP:
+ case HIGHGUID_GUILD:
return false;
case HIGHGUID_GAMEOBJECT:
case HIGHGUID_TRANSPORT:
@@ -225,6 +241,7 @@ bool IsGuidHaveEnPart(uint64 guid)
case HIGHGUID_PET:
case HIGHGUID_VEHICLE:
case HIGHGUID_MO_TRANSPORT:
+ case HIGHGUID_AREATRIGGER:
default:
return true;
}
@@ -245,6 +262,8 @@ char const* GetLogNameForGuid(uint64 guid)
case HIGHGUID_CORPSE: return "corpse";
case HIGHGUID_MO_TRANSPORT: return "mo_transport";
case HIGHGUID_GROUP: return "group";
+ case HIGHGUID_GUILD: return "guild";
+ case HIGHGUID_AREATRIGGER: return "areatrigger";
default:
return "<unknown>";
}
diff --git a/src/server/game/Entities/Object/Updates/UpdateData.cpp b/src/server/game/Entities/Object/Updates/UpdateData.cpp
index e996db52c38..ee84b01e175 100644
--- a/src/server/game/Entities/Object/Updates/UpdateData.cpp
+++ b/src/server/game/Entities/Object/Updates/UpdateData.cpp
@@ -25,7 +25,7 @@
#include "World.h"
#include "zlib.h"
-UpdateData::UpdateData() : m_blockCount(0) { }
+UpdateData::UpdateData(uint16 map) : m_map(map), m_blockCount(0) { }
void UpdateData::AddOutOfRangeGUID(std::set<uint64>& guids)
{
@@ -43,104 +43,24 @@ void UpdateData::AddUpdateBlock(const ByteBuffer &block)
++m_blockCount;
}
-void UpdateData::Compress(void* dst, uint32 *dst_size, void* src, int src_size)
-{
- z_stream c_stream;
-
- c_stream.zalloc = (alloc_func)0;
- c_stream.zfree = (free_func)0;
- c_stream.opaque = (voidpf)0;
-
- // default Z_BEST_SPEED (1)
- int z_res = deflateInit(&c_stream, sWorld->getIntConfig(CONFIG_COMPRESSION));
- if (z_res != Z_OK)
- {
- TC_LOG_ERROR("misc", "Can't compress update packet (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res));
- *dst_size = 0;
- return;
- }
-
- c_stream.next_out = (Bytef*)dst;
- c_stream.avail_out = *dst_size;
- c_stream.next_in = (Bytef*)src;
- c_stream.avail_in = (uInt)src_size;
-
- z_res = deflate(&c_stream, Z_NO_FLUSH);
- if (z_res != Z_OK)
- {
- TC_LOG_ERROR("misc", "Can't compress update packet (zlib: deflate) Error code: %i (%s)", z_res, zError(z_res));
- *dst_size = 0;
- return;
- }
-
- if (c_stream.avail_in != 0)
- {
- TC_LOG_ERROR("misc", "Can't compress update packet (zlib: deflate not greedy)");
- *dst_size = 0;
- return;
- }
-
- z_res = deflate(&c_stream, Z_FINISH);
- if (z_res != Z_STREAM_END)
- {
- TC_LOG_ERROR("misc", "Can't compress update packet (zlib: deflate should report Z_STREAM_END instead %i (%s)", z_res, zError(z_res));
- *dst_size = 0;
- return;
- }
-
- z_res = deflateEnd(&c_stream);
- if (z_res != Z_OK)
- {
- TC_LOG_ERROR("misc", "Can't compress update packet (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res));
- *dst_size = 0;
- return;
- }
-
- *dst_size = c_stream.total_out;
-}
-
bool UpdateData::BuildPacket(WorldPacket* packet)
{
ASSERT(packet->empty()); // shouldn't happen
+ packet->Initialize(SMSG_UPDATE_OBJECT, 2 + 4 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.wpos());
- ByteBuffer buf(4 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.wpos());
-
- buf << (uint32) (!m_outOfRangeGUIDs.empty() ? m_blockCount + 1 : m_blockCount);
+ *packet << uint16(m_map);
+ *packet << uint32(m_blockCount + (m_outOfRangeGUIDs.empty() ? 0 : 1));
if (!m_outOfRangeGUIDs.empty())
{
- buf << (uint8) UPDATETYPE_OUT_OF_RANGE_OBJECTS;
- buf << (uint32) m_outOfRangeGUIDs.size();
+ *packet << uint8(UPDATETYPE_OUT_OF_RANGE_OBJECTS);
+ *packet << uint32(m_outOfRangeGUIDs.size());
for (std::set<uint64>::const_iterator i = m_outOfRangeGUIDs.begin(); i != m_outOfRangeGUIDs.end(); ++i)
- {
- buf.appendPackGUID(*i);
- }
- }
-
- buf.append(m_data);
-
- size_t pSize = buf.wpos(); // use real used data size
-
- if (pSize > 100) // compress large packets
- {
- uint32 destsize = compressBound(pSize);
- packet->resize(destsize + sizeof(uint32));
-
- packet->put<uint32>(0, pSize);
- Compress(const_cast<uint8*>(packet->contents()) + sizeof(uint32), &destsize, (void*)buf.contents(), pSize);
- if (destsize == 0)
- return false;
-
- packet->resize(destsize + sizeof(uint32));
- packet->SetOpcode(SMSG_COMPRESSED_UPDATE_OBJECT);
- }
- else // send small packets without compression
- {
- packet->append(buf);
- packet->SetOpcode(SMSG_UPDATE_OBJECT);
+ packet->appendPackGUID(*i);
}
+ packet->append(m_data);
return true;
}
@@ -149,5 +69,6 @@ void UpdateData::Clear()
m_data.clear();
m_outOfRangeGUIDs.clear();
m_blockCount = 0;
+ m_map = 0;
}
diff --git a/src/server/game/Entities/Object/Updates/UpdateData.h b/src/server/game/Entities/Object/Updates/UpdateData.h
index 1ec86192fab..e0666a1a717 100644
--- a/src/server/game/Entities/Object/Updates/UpdateData.h
+++ b/src/server/game/Entities/Object/Updates/UpdateData.h
@@ -27,33 +27,35 @@ class WorldPacket;
enum OBJECT_UPDATE_TYPE
{
UPDATETYPE_VALUES = 0,
- UPDATETYPE_MOVEMENT = 1,
- UPDATETYPE_CREATE_OBJECT = 2,
- UPDATETYPE_CREATE_OBJECT2 = 3,
- UPDATETYPE_OUT_OF_RANGE_OBJECTS = 4,
- UPDATETYPE_NEAR_OBJECTS = 5
+ UPDATETYPE_CREATE_OBJECT = 1,
+ UPDATETYPE_CREATE_OBJECT2 = 2,
+ UPDATETYPE_OUT_OF_RANGE_OBJECTS = 3,
};
enum OBJECT_UPDATE_FLAGS
{
- UPDATEFLAG_NONE = 0x0000,
- UPDATEFLAG_SELF = 0x0001,
- UPDATEFLAG_TRANSPORT = 0x0002,
- UPDATEFLAG_HAS_TARGET = 0x0004,
- UPDATEFLAG_UNKNOWN = 0x0008,
- UPDATEFLAG_LOWGUID = 0x0010,
- UPDATEFLAG_LIVING = 0x0020,
- UPDATEFLAG_STATIONARY_POSITION = 0x0040,
- UPDATEFLAG_VEHICLE = 0x0080,
- UPDATEFLAG_POSITION = 0x0100,
- UPDATEFLAG_ROTATION = 0x0200
+ UPDATEFLAG_NONE = 0x0000,
+ UPDATEFLAG_SELF = 0x0001,
+ UPDATEFLAG_TRANSPORT = 0x0002,
+ UPDATEFLAG_HAS_TARGET = 0x0004,
+ UPDATEFLAG_UNKNOWN = 0x0008,
+ UPDATEFLAG_LOWGUID = 0x0010,
+ UPDATEFLAG_LIVING = 0x0020,
+ UPDATEFLAG_STATIONARY_POSITION = 0x0040,
+ UPDATEFLAG_VEHICLE = 0x0080,
+ UPDATEFLAG_GO_TRANSPORT_POSITION = 0x0100,
+ UPDATEFLAG_ROTATION = 0x0200,
+ UPDATEFLAG_UNK3 = 0x0400,
+ UPDATEFLAG_ANIMKITS = 0x0800,
+ UPDATEFLAG_UNK5 = 0x1000,
+ UPDATEFLAG_UNK6 = 0x2000,
};
class UpdateData
{
public:
- UpdateData();
- UpdateData(UpdateData&& right) : m_blockCount(right.m_blockCount),
+ UpdateData(uint16 map);
+ UpdateData(UpdateData&& right) : m_map(right.m_map), m_blockCount(right.m_blockCount),
m_outOfRangeGUIDs(std::move(right.m_outOfRangeGUIDs)),
m_data(std::move(right.m_data))
{
@@ -69,12 +71,11 @@ class UpdateData
std::set<uint64> const& GetOutOfRangeGUIDs() const { return m_outOfRangeGUIDs; }
protected:
+ uint16 m_map;
uint32 m_blockCount;
std::set<uint64> m_outOfRangeGUIDs;
ByteBuffer m_data;
- void Compress(void* dst, uint32 *dst_size, void* src, int src_size);
-
UpdateData(UpdateData const& right) = delete;
UpdateData& operator=(UpdateData const& right) = delete;
};
diff --git a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp
index 5629fef7d0c..0db2a312c9a 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp
+++ b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp
@@ -21,6 +21,8 @@ uint32 ItemUpdateFieldFlags[CONTAINER_END] =
{
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
@@ -77,12 +79,20 @@ uint32 ItemUpdateFieldFlags[CONTAINER_END] =
UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_12_1
UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_12_1+1
UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_12_3
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_13_1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_13_1+1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_13_3
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_14_1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_14_1+1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_14_3
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_15_1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_15_1+1
+ UF_FLAG_PUBLIC, // ITEM_FIELD_ENCHANTMENT_15_3
UF_FLAG_PUBLIC, // ITEM_FIELD_PROPERTY_SEED
UF_FLAG_PUBLIC, // ITEM_FIELD_RANDOM_PROPERTIES_ID
UF_FLAG_OWNER | UF_FLAG_ITEM_OWNER, // ITEM_FIELD_DURABILITY
UF_FLAG_OWNER | UF_FLAG_ITEM_OWNER, // ITEM_FIELD_MAXDURABILITY
UF_FLAG_PUBLIC, // ITEM_FIELD_CREATE_PLAYED_TIME
- UF_FLAG_NONE, // ITEM_FIELD_PAD
UF_FLAG_PUBLIC, // CONTAINER_FIELD_NUM_SLOTS
UF_FLAG_NONE, // CONTAINER_ALIGN_PAD
UF_FLAG_PUBLIC, // CONTAINER_FIELD_SLOT_1
@@ -163,6 +173,8 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
{
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
@@ -191,30 +203,22 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PUBLIC, // UNIT_FIELD_POWER3
UF_FLAG_PUBLIC, // UNIT_FIELD_POWER4
UF_FLAG_PUBLIC, // UNIT_FIELD_POWER5
- UF_FLAG_PUBLIC, // UNIT_FIELD_POWER6
- UF_FLAG_PUBLIC, // UNIT_FIELD_POWER7
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXHEALTH
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER1
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER2
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER3
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER4
UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER5
- UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER6
- UF_FLAG_PUBLIC, // UNIT_FIELD_MAXPOWER7
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+1
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+2
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+3
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+4
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+5
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+6
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+1
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+2
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+3
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+4
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+5
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+6
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+1
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+2
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+3
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER+4
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+1
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+2
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+3
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_UNUSED2, // UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER+4
UF_FLAG_PUBLIC, // UNIT_FIELD_LEVEL
UF_FLAG_PUBLIC, // UNIT_FIELD_FACTIONTEMPLATE
UF_FLAG_PUBLIC, // UNIT_VIRTUAL_ITEM_SLOT_ID
@@ -228,7 +232,7 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // UNIT_FIELD_RANGEDATTACKTIME
UF_FLAG_PUBLIC, // UNIT_FIELD_BOUNDINGRADIUS
UF_FLAG_PUBLIC, // UNIT_FIELD_COMBATREACH
- UF_FLAG_PUBLIC, // UNIT_FIELD_DISPLAYID
+ UF_FLAG_DYNAMIC, // UNIT_FIELD_DISPLAYID
UF_FLAG_PUBLIC, // UNIT_FIELD_NATIVEDISPLAYID
UF_FLAG_PUBLIC, // UNIT_FIELD_MOUNTDISPLAYID
UF_FLAG_PRIVATE | UF_FLAG_OWNER | UF_FLAG_SPECIAL_INFO, // UNIT_FIELD_MINDAMAGE
@@ -242,6 +246,7 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_OWNER, // UNIT_FIELD_PETNEXTLEVELEXP
UF_FLAG_DYNAMIC, // UNIT_DYNAMIC_FLAGS
UF_FLAG_PUBLIC, // UNIT_MOD_CAST_SPEED
+ UF_FLAG_PUBLIC, // UNIT_MOD_CAST_HASTE
UF_FLAG_PUBLIC, // UNIT_CREATED_BY_SPELL
UF_FLAG_DYNAMIC, // UNIT_NPC_FLAGS
UF_FLAG_PUBLIC, // UNIT_NPC_EMOTESTATE
@@ -285,10 +290,12 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_BASE_HEALTH
UF_FLAG_PUBLIC, // UNIT_FIELD_BYTES_2
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_ATTACK_POWER
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_ATTACK_POWER_MODS
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_ATTACK_POWER_MOD_POS
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_ATTACK_POWER_MOD_NEG
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_ATTACK_POWER_MULTIPLIER
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_RANGED_ATTACK_POWER
- UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_RANGED_ATTACK_POWER_MODS
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS
+ UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_MINRANGEDDAMAGE
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_MAXRANGEDDAMAGE
@@ -308,142 +315,269 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_POWER_COST_MULTIPLIER+6
UF_FLAG_PRIVATE | UF_FLAG_OWNER, // UNIT_FIELD_MAXHEALTHMODIFIER
UF_FLAG_PUBLIC, // UNIT_FIELD_HOVERHEIGHT
+ UF_FLAG_PUBLIC, // UNIT_FIELD_MAXITEMLEVEL
UF_FLAG_NONE, // UNIT_FIELD_PADDING
UF_FLAG_PUBLIC, // PLAYER_DUEL_ARBITER
UF_FLAG_PUBLIC, // PLAYER_DUEL_ARBITER+1
UF_FLAG_PUBLIC, // PLAYER_FLAGS
- UF_FLAG_PUBLIC, // PLAYER_GUILDID
UF_FLAG_PUBLIC, // PLAYER_GUILDRANK
+ UF_FLAG_PUBLIC, // PLAYER_GUILDDELETE_DATE
+ UF_FLAG_PUBLIC, // PLAYER_GUILDLEVEL
UF_FLAG_PUBLIC, // PLAYER_BYTES
UF_FLAG_PUBLIC, // PLAYER_BYTES_2
UF_FLAG_PUBLIC, // PLAYER_BYTES_3
UF_FLAG_PUBLIC, // PLAYER_DUEL_TEAM
UF_FLAG_PUBLIC, // PLAYER_GUILD_TIMESTAMP
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_1_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_1_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_1_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_1_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_1_4
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_1_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_1_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_1_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_1_4
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_2_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_2_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_2_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_2_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_2_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_2_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_2_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_2_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_2_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_3_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_3_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_3_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_3_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_3_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_3_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_3_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_3_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_3_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_4_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_4_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_4_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_4_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_4_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_4_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_4_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_4_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_4_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_5_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_5_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_5_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_5_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_5_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_5_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_5_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_5_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_5_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_6_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_6_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_6_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_6_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_6_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_6_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_6_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_6_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_6_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_7_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_7_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_7_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_7_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_7_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_7_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_7_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_7_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_7_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_8_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_8_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_8_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_8_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_8_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_8_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_8_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_8_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_8_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_9_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_9_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_9_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_9_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_9_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_9_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_9_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_9_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_9_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_10_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_10_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_10_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_10_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_10_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_10_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_10_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_10_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_10_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_11_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_11_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_11_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_11_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_11_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_11_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_11_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_11_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_11_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_12_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_12_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_12_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_12_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_12_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_12_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_12_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_12_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_12_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_13_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_13_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_13_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_13_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_13_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_13_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_13_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_13_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_13_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_14_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_14_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_14_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_14_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_14_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_14_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_14_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_14_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_14_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_15_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_15_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_15_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_15_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_15_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_15_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_15_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_15_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_15_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_16_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_16_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_16_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_16_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_16_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_16_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_16_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_16_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_16_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_17_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_17_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_17_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_17_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_17_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_17_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_17_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_17_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_17_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_18_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_18_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_18_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_18_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_18_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_18_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_18_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_18_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_18_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_19_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_19_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_19_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_19_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_19_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_19_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_19_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_19_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_19_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_20_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_20_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_20_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_20_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_20_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_20_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_20_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_20_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_20_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_21_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_21_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_21_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_21_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_21_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_21_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_21_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_21_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_21_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_22_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_22_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_22_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_22_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_22_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_22_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_22_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_22_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_22_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_23_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_23_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_23_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_23_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_23_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_23_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_23_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_23_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_23_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_24_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_24_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_24_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_24_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_24_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_24_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_24_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_24_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_24_5
UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_25_1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_25_2
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_25_3
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_25_3+1
- UF_FLAG_PRIVATE, // PLAYER_QUEST_LOG_25_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_25_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_25_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_25_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_25_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_26_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_26_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_26_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_26_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_26_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_27_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_27_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_27_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_27_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_27_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_28_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_28_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_28_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_28_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_28_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_29_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_29_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_29_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_29_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_29_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_30_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_30_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_30_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_30_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_30_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_31_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_31_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_31_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_31_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_31_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_32_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_32_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_32_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_32_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_32_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_33_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_33_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_33_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_33_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_33_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_34_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_34_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_34_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_34_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_34_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_35_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_35_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_35_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_35_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_35_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_36_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_36_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_36_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_36_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_36_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_37_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_37_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_37_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_37_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_37_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_38_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_38_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_38_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_38_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_38_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_39_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_39_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_39_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_39_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_39_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_40_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_40_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_40_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_40_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_40_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_41_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_41_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_41_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_41_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_41_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_42_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_42_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_42_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_42_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_42_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_43_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_43_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_43_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_43_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_43_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_44_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_44_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_44_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_44_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_44_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_45_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_45_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_45_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_45_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_45_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_46_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_46_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_46_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_46_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_46_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_47_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_47_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_47_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_47_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_47_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_48_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_48_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_48_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_48_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_48_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_49_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_49_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_49_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_49_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_49_5
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_50_1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_50_2
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_50_3
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_50_3+1
+ UF_FLAG_PARTY_MEMBER, // PLAYER_QUEST_LOG_50_5
UF_FLAG_PUBLIC, // PLAYER_VISIBLE_ITEM_1_ENTRYID
UF_FLAG_PUBLIC, // PLAYER_VISIBLE_ITEM_1_ENCHANTMENT
UF_FLAG_PUBLIC, // PLAYER_VISIBLE_ITEM_2_ENTRYID
@@ -657,134 +791,6 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_VENDORBUYBACK_SLOT_1+21
UF_FLAG_PRIVATE, // PLAYER_FIELD_VENDORBUYBACK_SLOT_1+22
UF_FLAG_PRIVATE, // PLAYER_FIELD_VENDORBUYBACK_SLOT_1+23
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+1
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+2
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+3
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+4
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+5
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+6
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+7
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+8
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+9
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+10
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+11
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+12
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+13
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+14
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+15
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+16
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+17
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+18
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+19
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+20
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+21
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+22
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+23
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+24
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+25
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+26
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+27
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+28
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+29
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+30
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+31
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+32
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+33
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+34
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+35
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+36
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+37
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+38
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+39
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+40
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+41
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+42
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+43
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+44
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+45
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+46
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+47
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+48
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+49
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+50
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+51
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+52
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+53
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+54
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+55
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+56
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+57
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+58
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+59
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+60
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+61
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+62
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KEYRING_SLOT_1+63
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+1
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+2
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+3
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+4
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+5
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+6
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+7
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+8
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+9
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+10
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+11
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+12
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+13
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+14
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+15
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+16
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+17
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+18
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+19
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+20
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+21
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+22
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+23
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+24
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+25
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+26
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+27
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+28
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+29
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+30
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+31
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+32
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+33
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+34
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+35
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+36
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+37
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+38
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+39
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+40
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+41
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+42
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+43
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+44
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+45
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+46
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+47
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+48
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+49
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+50
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+51
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+52
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+53
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+54
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+55
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+56
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+57
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+58
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+59
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+60
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+61
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+62
- UF_FLAG_PRIVATE, // PLAYER_FIELD_CURRENCYTOKEN_SLOT_1+63
UF_FLAG_PRIVATE, // PLAYER_FARSIGHT
UF_FLAG_PRIVATE, // PLAYER_FARSIGHT+1
UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES
@@ -793,403 +799,402 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES1+1
UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES2
UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES2+1
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KNOWN_CURRENCIES
- UF_FLAG_PRIVATE, // PLAYER_FIELD_KNOWN_CURRENCIES+1
+ UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES3
+ UF_FLAG_PRIVATE, // PLAYER__FIELD_KNOWN_TITLES3+1
UF_FLAG_PRIVATE, // PLAYER_XP
UF_FLAG_PRIVATE, // PLAYER_NEXT_LEVEL_XP
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+1
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+2
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+3
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+4
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+5
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+6
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+7
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+8
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+9
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+10
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+11
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+12
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+13
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+14
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+15
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+16
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+17
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+18
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+19
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+20
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+21
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+22
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+23
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+24
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+25
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+26
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+27
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+28
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+29
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+30
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+31
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+32
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+33
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+34
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+35
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+36
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+37
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+38
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+39
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+40
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+41
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+42
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+43
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+44
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+45
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+46
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+47
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+48
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+49
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+50
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+51
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+52
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+53
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+54
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+55
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+56
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+57
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+58
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+59
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+60
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+61
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+62
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+63
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+64
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+65
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+66
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+67
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+68
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+69
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+70
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+71
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+72
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+73
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+74
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+75
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+76
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+77
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+78
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+79
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+80
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+81
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+82
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+83
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+84
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+85
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+86
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+87
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+88
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+89
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+90
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+91
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+92
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+93
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+94
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+95
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+96
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+97
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+98
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+99
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+100
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+101
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+102
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+103
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+104
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+105
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+106
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+107
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+108
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+109
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+110
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+111
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+112
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+113
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+114
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+115
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+116
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+117
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+118
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+119
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+120
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+121
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+122
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+123
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+124
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+125
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+126
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+127
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+128
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+129
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+130
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+131
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+132
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+133
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+134
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+135
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+136
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+137
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+138
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+139
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+140
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+141
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+142
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+143
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+144
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+145
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+146
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+147
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+148
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+149
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+150
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+151
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+152
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+153
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+154
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+155
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+156
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+157
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+158
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+159
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+160
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+161
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+162
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+163
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+164
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+165
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+166
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+167
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+168
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+169
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+170
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+171
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+172
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+173
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+174
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+175
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+176
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+177
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+178
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+179
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+180
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+181
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+182
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+183
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+184
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+185
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+186
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+187
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+188
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+189
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+190
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+191
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+192
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+193
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+194
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+195
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+196
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+197
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+198
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+199
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+200
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+201
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+202
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+203
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+204
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+205
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+206
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+207
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+208
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+209
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+210
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+211
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+212
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+213
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+214
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+215
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+216
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+217
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+218
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+219
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+220
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+221
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+222
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+223
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+224
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+225
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+226
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+227
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+228
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+229
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+230
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+231
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+232
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+233
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+234
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+235
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+236
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+237
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+238
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+239
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+240
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+241
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+242
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+243
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+244
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+245
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+246
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+247
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+248
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+249
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+250
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+251
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+252
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+253
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+254
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+255
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+256
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+257
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+258
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+259
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+260
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+261
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+262
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+263
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+264
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+265
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+266
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+267
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+268
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+269
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+270
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+271
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+272
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+273
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+274
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+275
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+276
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+277
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+278
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+279
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+280
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+281
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+282
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+283
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+284
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+285
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+286
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+287
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+288
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+289
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+290
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+291
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+292
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+293
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+294
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+295
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+296
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+297
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+298
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+299
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+300
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+301
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+302
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+303
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+304
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+305
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+306
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+307
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+308
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+309
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+310
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+311
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+312
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+313
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+314
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+315
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+316
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+317
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+318
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+319
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+320
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+321
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+322
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+323
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+324
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+325
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+326
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+327
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+328
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+329
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+330
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+331
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+332
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+333
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+334
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+335
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+336
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+337
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+338
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+339
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+340
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+341
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+342
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+343
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+344
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+345
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+346
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+347
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+348
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+349
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+350
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+351
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+352
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+353
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+354
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+355
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+356
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+357
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+358
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+359
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+360
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+361
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+362
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+363
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+364
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+365
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+366
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+367
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+368
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+369
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+370
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+371
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+372
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+373
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+374
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+375
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+376
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+377
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+378
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+379
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+380
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+381
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+382
- UF_FLAG_PRIVATE, // PLAYER_SKILL_INFO_1_1+383
- UF_FLAG_PRIVATE, // PLAYER_CHARACTER_POINTS1
- UF_FLAG_PRIVATE, // PLAYER_CHARACTER_POINTS2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_LINEID_0+63
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_STEP_0+63
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_RANK_0+63
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MAX_RANK_0+63
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_MODIFIER_0+63
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+1
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+2
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+3
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+4
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+5
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+6
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+7
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+8
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+9
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+10
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+11
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+12
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+13
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+14
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+15
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+16
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+17
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+18
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+19
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+20
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+21
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+22
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+23
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+24
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+25
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+26
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+27
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+28
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+29
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+30
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+31
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+32
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+33
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+34
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+35
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+36
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+37
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+38
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+39
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+40
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+41
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+42
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+43
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+44
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+45
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+46
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+47
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+48
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+49
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+50
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+51
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+52
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+53
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+54
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+55
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+56
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+57
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+58
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+59
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+60
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+61
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+62
+ UF_FLAG_PRIVATE, // PLAYER_SKILL_TALENT_0+63
+ UF_FLAG_PRIVATE, // PLAYER_CHARACTER_POINTS
UF_FLAG_PRIVATE, // PLAYER_TRACK_CREATURES
UF_FLAG_PRIVATE, // PLAYER_TRACK_RESOURCES
+ UF_FLAG_PRIVATE, // PLAYER_EXPERTISE
+ UF_FLAG_PRIVATE, // PLAYER_OFFHAND_EXPERTISE
UF_FLAG_PRIVATE, // PLAYER_BLOCK_PERCENTAGE
UF_FLAG_PRIVATE, // PLAYER_DODGE_PERCENTAGE
UF_FLAG_PRIVATE, // PLAYER_PARRY_PERCENTAGE
- UF_FLAG_PRIVATE, // PLAYER_EXPERTISE
- UF_FLAG_PRIVATE, // PLAYER_OFFHAND_EXPERTISE
UF_FLAG_PRIVATE, // PLAYER_CRIT_PERCENTAGE
UF_FLAG_PRIVATE, // PLAYER_RANGED_CRIT_PERCENTAGE
UF_FLAG_PRIVATE, // PLAYER_OFFHAND_CRIT_PERCENTAGE
@@ -1202,6 +1207,7 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_SPELL_CRIT_PERCENTAGE1+6
UF_FLAG_PRIVATE, // PLAYER_SHIELD_BLOCK
UF_FLAG_PRIVATE, // PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE
+ UF_FLAG_PRIVATE, // PLAYER_MASTERY
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+1
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+2
@@ -1330,8 +1336,37 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+125
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+126
UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+127
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+128
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+129
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+130
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+131
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+132
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+133
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+134
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+135
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+136
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+137
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+138
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+139
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+140
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+141
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+142
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+143
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+144
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+145
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+146
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+147
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+148
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+149
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+150
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+151
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+152
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+153
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+154
+ UF_FLAG_PRIVATE, // PLAYER_EXPLORED_ZONES_1+155
UF_FLAG_PRIVATE, // PLAYER_REST_STATE_EXPERIENCE
UF_FLAG_PRIVATE, // PLAYER_FIELD_COINAGE
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_COINAGE+1
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_DAMAGE_DONE_POS
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_DAMAGE_DONE_POS+1
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_DAMAGE_DONE_POS+2
@@ -1356,10 +1391,14 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_HEALING_DONE_POS
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_HEALING_PCT
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_HEALING_DONE_PCT
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_WEAPON_DMG_MULTIPLIERS
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_WEAPON_DMG_MULTIPLIERS+1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_WEAPON_DMG_MULTIPLIERS+2
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_SPELL_POWER_PCT
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_OVERRIDE_SPELL_POWER_BY_AP_PCT
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_TARGET_RESISTANCE
UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE
UF_FLAG_PRIVATE, // PLAYER_FIELD_BYTES
- UF_FLAG_PRIVATE, // PLAYER_AMMO_ID
UF_FLAG_PRIVATE, // PLAYER_SELF_RES_SPELL
UF_FLAG_PRIVATE, // PLAYER_FIELD_PVP_MEDALS
UF_FLAG_PRIVATE, // PLAYER_FIELD_BUYBACK_PRICE_1
@@ -1387,8 +1426,6 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_BUYBACK_TIMESTAMP_1+10
UF_FLAG_PRIVATE, // PLAYER_FIELD_BUYBACK_TIMESTAMP_1+11
UF_FLAG_PRIVATE, // PLAYER_FIELD_KILLS
- UF_FLAG_PRIVATE, // PLAYER_FIELD_TODAY_CONTRIBUTION
- UF_FLAG_PRIVATE, // PLAYER_FIELD_YESTERDAY_CONTRIBUTION
UF_FLAG_PRIVATE, // PLAYER_FIELD_LIFETIME_HONORBALE_KILLS
UF_FLAG_PRIVATE, // PLAYER_FIELD_BYTES2
UF_FLAG_PRIVATE, // PLAYER_FIELD_WATCHED_FACTION_INDEX
@@ -1417,6 +1454,7 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_COMBAT_RATING_1+22
UF_FLAG_PRIVATE, // PLAYER_FIELD_COMBAT_RATING_1+23
UF_FLAG_PRIVATE, // PLAYER_FIELD_COMBAT_RATING_1+24
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_COMBAT_RATING_1+25
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1+1
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1+2
@@ -1438,8 +1476,7 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1+18
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1+19
UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_TEAM_INFO_1_1+20
- UF_FLAG_PRIVATE, // PLAYER_FIELD_HONOR_CURRENCY
- UF_FLAG_PRIVATE, // PLAYER_FIELD_ARENA_CURRENCY
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_BATTLEGROUND_RATING
UF_FLAG_PRIVATE, // PLAYER_FIELD_MAX_LEVEL
UF_FLAG_PRIVATE, // PLAYER_FIELD_DAILY_QUESTS_1
UF_FLAG_PRIVATE, // PLAYER_FIELD_DAILY_QUESTS_1+1
@@ -1479,20 +1516,53 @@ uint32 UnitUpdateFieldFlags[PLAYER_END] =
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+3
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+4
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+5
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+6
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+7
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPH_SLOTS_1+8
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+1
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+2
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+3
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+4
UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+5
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+6
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+7
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_GLYPHS_1+8
UF_FLAG_PRIVATE, // PLAYER_GLYPHS_ENABLED
UF_FLAG_PRIVATE, // PLAYER_PET_SPELL_POWER
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+2
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+3
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+4
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+5
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+6
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESEARCHING_1+7
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+2
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+3
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+4
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+5
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+6
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_RESERACH_SITE_1+7
+ UF_FLAG_PRIVATE, // PLAYER_PROFESSION_SKILL_LINE_1
+ UF_FLAG_PRIVATE, // PLAYER_PROFESSION_SKILL_LINE_1+1
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_UI_HIT_MODIFIER
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_UI_SPELL_HIT_MODIFIER
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_HOME_REALM_TIME_OFFSET
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_HASTE
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_RANGED_HASTE
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_PET_HASTE
+ UF_FLAG_PRIVATE, // PLAYER_FIELD_MOD_HASTE_REGEN
};
uint32 GameObjectUpdateFieldFlags[GAMEOBJECT_END] =
{
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
@@ -1515,13 +1585,15 @@ uint32 DynamicObjectUpdateFieldFlags[DYNAMICOBJECT_END] =
{
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
UF_FLAG_NONE, // OBJECT_FIELD_PADDING
UF_FLAG_PUBLIC, // DYNAMICOBJECT_CASTER
UF_FLAG_PUBLIC, // DYNAMICOBJECT_CASTER+1
- UF_FLAG_PUBLIC, // DYNAMICOBJECT_BYTES
+ UF_FLAG_DYNAMIC, // DYNAMICOBJECT_BYTES
UF_FLAG_PUBLIC, // DYNAMICOBJECT_SPELLID
UF_FLAG_PUBLIC, // DYNAMICOBJECT_RADIUS
UF_FLAG_PUBLIC, // DYNAMICOBJECT_CASTTIME
@@ -1531,6 +1603,8 @@ uint32 CorpseUpdateFieldFlags[CORPSE_END] =
{
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
@@ -1561,8 +1635,24 @@ uint32 CorpseUpdateFieldFlags[CORPSE_END] =
UF_FLAG_PUBLIC, // CORPSE_FIELD_ITEM+18
UF_FLAG_PUBLIC, // CORPSE_FIELD_BYTES_1
UF_FLAG_PUBLIC, // CORPSE_FIELD_BYTES_2
- UF_FLAG_PUBLIC, // CORPSE_FIELD_GUILD
UF_FLAG_PUBLIC, // CORPSE_FIELD_FLAGS
UF_FLAG_DYNAMIC, // CORPSE_FIELD_DYNAMIC_FLAGS
- UF_FLAG_NONE, // CORPSE_FIELD_PAD
+};
+
+uint32 AreaTriggerUpdateFieldFlags[AREATRIGGER_END] =
+{
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_GUID+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_DATA+1
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_TYPE
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_ENTRY
+ UF_FLAG_PUBLIC, // OBJECT_FIELD_SCALE_X
+ UF_FLAG_NONE, // OBJECT_FIELD_PADDING
+ UF_FLAG_PUBLIC, // AREATRIGGER_SPELLID
+ UF_FLAG_PUBLIC, // AREATRIGGER_SPELLVISUALID
+ UF_FLAG_PUBLIC, // AREATRIGGER_DURATION
+ UF_FLAG_PUBLIC, // AREATRIGGER_FINAL_POS
+ UF_FLAG_PUBLIC, // AREATRIGGER_FINAL_POS+1
+ UF_FLAG_PUBLIC, // AREATRIGGER_FINAL_POS+2
};
diff --git a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h
index 6d168cd56c4..b0e6bb6afa2 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h
+++ b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h
@@ -40,5 +40,6 @@ extern uint32 UnitUpdateFieldFlags[PLAYER_END];
extern uint32 GameObjectUpdateFieldFlags[GAMEOBJECT_END];
extern uint32 DynamicObjectUpdateFieldFlags[DYNAMICOBJECT_END];
extern uint32 CorpseUpdateFieldFlags[CORPSE_END];
+extern uint32 AreaTriggerUpdateFieldFlags[AREATRIGGER_END];
#endif // _UPDATEFIELDFLAGS_H
diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.h b/src/server/game/Entities/Object/Updates/UpdateFields.h
index 2838ee31d81..880eb68bb89 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFields.h
+++ b/src/server/game/Entities/Object/Updates/UpdateFields.h
@@ -16,418 +16,550 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _UPDATEFIELDS_AUTO_H
-#define _UPDATEFIELDS_AUTO_H
+#ifndef _UPDATEFIELDS_H
+#define _UPDATEFIELDS_H
-// Auto generated for version 3, 3, 5, 12340
+// Auto generated for version 4, 3, 4, 15595
enum EObjectFields
{
- OBJECT_FIELD_GUID = 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- OBJECT_FIELD_TYPE = 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
- OBJECT_FIELD_ENTRY = 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
- OBJECT_FIELD_SCALE_X = 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC
- OBJECT_FIELD_PADDING = 0x0005, // Size: 1, Type: INT, Flags: NONE
- OBJECT_END = 0x0006
+ OBJECT_FIELD_GUID = 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ OBJECT_FIELD_DATA = 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
+ OBJECT_FIELD_TYPE = 0x0004, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ OBJECT_FIELD_ENTRY = 0x0005, // Size: 1, Type: INT, Flags: PUBLIC
+ OBJECT_FIELD_SCALE_X = 0x0006, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ OBJECT_FIELD_PADDING = 0x0007, // Size: 1, Type: INT, Flags: NONE
+ OBJECT_END = 0x0008
};
enum EItemFields
{
- ITEM_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- ITEM_FIELD_CONTAINED = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
- ITEM_FIELD_CREATOR = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC
- ITEM_FIELD_GIFTCREATOR = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
- ITEM_FIELD_STACK_COUNT = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC
- 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_DURABILITY = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_CREATE_PLAYED_TIME = OBJECT_END + 0x0038, // Size: 1, Type: INT, Flags: PUBLIC
- ITEM_FIELD_PAD = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: NONE
- ITEM_END = OBJECT_END + 0x003A
+ ITEM_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ ITEM_FIELD_CONTAINED = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
+ ITEM_FIELD_CREATOR = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC
+ ITEM_FIELD_GIFTCREATOR = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
+ ITEM_FIELD_STACK_COUNT = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
+ ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
+ ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER, ITEM_OWNER
+ ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC
+ 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_ENCHANTMENT_13_1 = OBJECT_END + 0x0034, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_13_3 = OBJECT_END + 0x0036, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_14_1 = OBJECT_END + 0x0037, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_14_3 = OBJECT_END + 0x0039, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_15_1 = OBJECT_END + 0x003A, // Size: 2, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_ENCHANTMENT_15_3 = OBJECT_END + 0x003C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC
+ ITEM_FIELD_DURABILITY = OBJECT_END + 0x003F, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
+ ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0040, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
+ ITEM_FIELD_CREATE_PLAYED_TIME = OBJECT_END + 0x0041, // Size: 1, Type: INT, Flags: PUBLIC
+ ITEM_END = OBJECT_END + 0x0042,
};
enum EContainerFields
{
- CONTAINER_FIELD_NUM_SLOTS = ITEM_END + 0x0000, // Size: 1, Type: INT, Flags: PUBLIC
- CONTAINER_ALIGN_PAD = ITEM_END + 0x0001, // Size: 1, Type: BYTES, Flags: NONE
- CONTAINER_FIELD_SLOT_1 = ITEM_END + 0x0002, // Size: 72, Type: LONG, Flags: PUBLIC
- CONTAINER_END = ITEM_END + 0x004A
+ CONTAINER_FIELD_NUM_SLOTS = ITEM_END + 0x0000, // Size: 1, Type: INT, Flags: PUBLIC
+ CONTAINER_ALIGN_PAD = ITEM_END + 0x0001, // Size: 1, Type: BYTES, Flags: NONE
+ CONTAINER_FIELD_SLOT_1 = ITEM_END + 0x0002, // Size: 72, Type: LONG, Flags: PUBLIC
+ CONTAINER_END = ITEM_END + 0x004A
};
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_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_CHANNEL_SPELL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0011, // Size: 1, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_HEALTH = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER1 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER2 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER3 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER4 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER5 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER6 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER7 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001E, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001F, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER6 = OBJECT_END + 0x0020, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MAXPOWER7 = OBJECT_END + 0x0021, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x0022, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0029, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_LEVEL = OBJECT_END + 0x0030, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0031, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x0032, // Size: 3, Type: INT, Flags: PUBLIC
- UNIT_FIELD_FLAGS = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_AURASTATE = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0038, // Size: 2, Type: INT, Flags: PUBLIC
- UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x003A, // Size: 1, Type: INT, Flags: PRIVATE
- UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PUBLIC
- UNIT_FIELD_COMBATREACH = OBJECT_END + 0x003C, // Size: 1, Type: FLOAT, Flags: PUBLIC
- UNIT_FIELD_DISPLAYID = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x003F, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0040, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER
- UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0041, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER
- UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER
- UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0043, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER
- UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0044, // Size: 1, Type: BYTES, Flags: PUBLIC
- UNIT_FIELD_PETNUMBER = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: PUBLIC
- UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: OWNER
- UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: OWNER
- UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: DYNAMIC
- 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
- UNIT_FIELD_STAT1 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_STAT2 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_STAT3 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_STAT4 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0057, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0058, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x005A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x005C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_RESISTANCES = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER, PARTY_LEADER
- UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x006B, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
- 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
- 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
- UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x0076, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER
- UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0078, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x0079, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER
- UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x007A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x007B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x007C, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x007D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
- UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x0084, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER
- UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x008B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
- 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,
+ 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_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_CHANNEL_SPELL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0011, // Size: 1, Type: BYTES, Flags: PUBLIC
+ UNIT_FIELD_HEALTH = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER1 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER2 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER3 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER4 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER5 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x001E, // Size: 5, Type: FLOAT, Flags: PRIVATE, OWNER, UNUSED2
+ UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0023, // Size: 5, Type: FLOAT, Flags: PRIVATE, OWNER, UNUSED2
+ UNIT_FIELD_LEVEL = OBJECT_END + 0x0028, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0029, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x002A, // Size: 3, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_FLAGS = OBJECT_END + 0x002D, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x002E, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_AURASTATE = OBJECT_END + 0x002F, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0030, // Size: 2, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x0032, // Size: 1, Type: INT, Flags: PRIVATE
+ UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x0033, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_FIELD_COMBATREACH = OBJECT_END + 0x0034, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_FIELD_DISPLAYID = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: DYNAMIC
+ UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0038, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, SPECIAL_INFO
+ UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0039, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, SPECIAL_INFO
+ UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x003A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, SPECIAL_INFO
+ UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, SPECIAL_INFO
+ UNIT_FIELD_BYTES_1 = OBJECT_END + 0x003C, // Size: 1, Type: BYTES, Flags: PUBLIC
+ UNIT_FIELD_PETNUMBER = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x003F, // Size: 1, Type: INT, Flags: OWNER
+ UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0040, // Size: 1, Type: INT, Flags: OWNER
+ UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0041, // Size: 1, Type: INT, Flags: DYNAMIC
+ UNIT_MOD_CAST_SPEED = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_MOD_CAST_HASTE = OBJECT_END + 0x0043, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_CREATED_BY_SPELL = OBJECT_END + 0x0044, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_NPC_FLAGS = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: DYNAMIC
+ UNIT_NPC_EMOTESTATE = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_STAT0 = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_STAT1 = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_STAT2 = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_STAT3 = OBJECT_END + 0x004A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_STAT4 = OBJECT_END + 0x004B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x004C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x004D, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x004E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RESISTANCES = OBJECT_END + 0x0056, // Size: 7, Type: INT, Flags: PRIVATE, OWNER, SPECIAL_INFO
+ UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_BASE_MANA = OBJECT_END + 0x006B, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x006C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_BYTES_2 = OBJECT_END + 0x006D, // Size: 1, Type: BYTES, Flags: PUBLIC
+ UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x006E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_ATTACK_POWER_MOD_POS = OBJECT_END + 0x006F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_ATTACK_POWER_MOD_NEG = OBJECT_END + 0x0070, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0071, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0072, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS = OBJECT_END + 0x0073, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG = OBJECT_END + 0x0074, // Size: 1, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0075, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x0076, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x0078, // Size: 7, Type: INT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x007F, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x0086, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER
+ UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x0087, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ UNIT_FIELD_MAXITEMLEVEL = OBJECT_END + 0x0088, // Size: 1, Type: INT, Flags: PUBLIC
+ UNIT_FIELD_PADDING = OBJECT_END + 0x0089, // Size: 1, Type: INT, Flags: NONE
+ UNIT_END = OBJECT_END + 0x008A
+};
+
+enum EPlayerFields
+{
+ PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_GUILDRANK = UNIT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_GUILDDELETE_DATE = UNIT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_GUILDLEVEL = UNIT_END + 0x0005, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_BYTES = UNIT_END + 0x0006, // Size: 1, Type: BYTES, Flags: PUBLIC
+ PLAYER_BYTES_2 = UNIT_END + 0x0007, // Size: 1, Type: BYTES, Flags: PUBLIC
+ PLAYER_BYTES_3 = UNIT_END + 0x0008, // Size: 1, Type: BYTES, Flags: PUBLIC
+ PLAYER_DUEL_TEAM = UNIT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_GUILD_TIMESTAMP = UNIT_END + 0x000A, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_QUEST_LOG_1_1 = UNIT_END + 0x000B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_1_2 = UNIT_END + 0x000C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_1_3 = UNIT_END + 0x000D, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_1_4 = UNIT_END + 0x000F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_2_1 = UNIT_END + 0x0010, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_2_2 = UNIT_END + 0x0011, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_2_3 = UNIT_END + 0x0012, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_2_5 = UNIT_END + 0x0014, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_3_1 = UNIT_END + 0x0015, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_3_2 = UNIT_END + 0x0016, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_3_3 = UNIT_END + 0x0017, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_3_5 = UNIT_END + 0x0019, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_4_1 = UNIT_END + 0x001A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_4_2 = UNIT_END + 0x001B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_4_3 = UNIT_END + 0x001C, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_4_5 = UNIT_END + 0x001E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_5_1 = UNIT_END + 0x001F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_5_2 = UNIT_END + 0x0020, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_5_3 = UNIT_END + 0x0021, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_5_5 = UNIT_END + 0x0023, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_6_1 = UNIT_END + 0x0024, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_6_2 = UNIT_END + 0x0025, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_6_3 = UNIT_END + 0x0026, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_6_5 = UNIT_END + 0x0028, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_7_1 = UNIT_END + 0x0029, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_7_2 = UNIT_END + 0x002A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_7_3 = UNIT_END + 0x002B, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_7_5 = UNIT_END + 0x002D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_8_1 = UNIT_END + 0x002E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_8_2 = UNIT_END + 0x002F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_8_3 = UNIT_END + 0x0030, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_8_5 = UNIT_END + 0x0032, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_9_1 = UNIT_END + 0x0033, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_9_2 = UNIT_END + 0x0034, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_9_3 = UNIT_END + 0x0035, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_9_5 = UNIT_END + 0x0037, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_10_1 = UNIT_END + 0x0038, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_10_2 = UNIT_END + 0x0039, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_10_3 = UNIT_END + 0x003A, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_10_5 = UNIT_END + 0x003C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_11_1 = UNIT_END + 0x003D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_11_2 = UNIT_END + 0x003E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_11_3 = UNIT_END + 0x003F, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_11_5 = UNIT_END + 0x0041, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_12_1 = UNIT_END + 0x0042, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_12_2 = UNIT_END + 0x0043, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_12_3 = UNIT_END + 0x0044, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_12_5 = UNIT_END + 0x0046, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_13_1 = UNIT_END + 0x0047, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_13_2 = UNIT_END + 0x0048, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_13_3 = UNIT_END + 0x0049, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_13_5 = UNIT_END + 0x004B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_14_1 = UNIT_END + 0x004C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_14_2 = UNIT_END + 0x004D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_14_3 = UNIT_END + 0x004E, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_14_5 = UNIT_END + 0x0050, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_15_1 = UNIT_END + 0x0051, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_15_2 = UNIT_END + 0x0052, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_15_3 = UNIT_END + 0x0053, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_15_5 = UNIT_END + 0x0055, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_16_1 = UNIT_END + 0x0056, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_16_2 = UNIT_END + 0x0057, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_16_3 = UNIT_END + 0x0058, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_16_5 = UNIT_END + 0x005A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_17_1 = UNIT_END + 0x005B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_17_2 = UNIT_END + 0x005C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_17_3 = UNIT_END + 0x005D, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_17_5 = UNIT_END + 0x005F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_18_1 = UNIT_END + 0x0060, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_18_2 = UNIT_END + 0x0061, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_18_3 = UNIT_END + 0x0062, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_18_5 = UNIT_END + 0x0064, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_19_1 = UNIT_END + 0x0065, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_19_2 = UNIT_END + 0x0066, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_19_3 = UNIT_END + 0x0067, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_19_5 = UNIT_END + 0x0069, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_20_1 = UNIT_END + 0x006A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_20_2 = UNIT_END + 0x006B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_20_3 = UNIT_END + 0x006C, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_20_5 = UNIT_END + 0x006E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_21_1 = UNIT_END + 0x006F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_21_2 = UNIT_END + 0x0070, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_21_3 = UNIT_END + 0x0071, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_21_5 = UNIT_END + 0x0073, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_22_1 = UNIT_END + 0x0074, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_22_2 = UNIT_END + 0x0075, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_22_3 = UNIT_END + 0x0076, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_22_5 = UNIT_END + 0x0078, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_23_1 = UNIT_END + 0x0079, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_23_2 = UNIT_END + 0x007A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_23_3 = UNIT_END + 0x007B, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_23_5 = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_24_1 = UNIT_END + 0x007E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_24_2 = UNIT_END + 0x007F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_24_3 = UNIT_END + 0x0080, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_24_5 = UNIT_END + 0x0082, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_25_1 = UNIT_END + 0x0083, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_25_2 = UNIT_END + 0x0084, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x0085, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_25_5 = UNIT_END + 0x0087, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_26_1 = UNIT_END + 0x0088, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_26_2 = UNIT_END + 0x0089, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_26_3 = UNIT_END + 0x008A, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_26_5 = UNIT_END + 0x008C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_27_1 = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_27_2 = UNIT_END + 0x008E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_27_3 = UNIT_END + 0x008F, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_27_5 = UNIT_END + 0x0091, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_28_1 = UNIT_END + 0x0092, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_28_2 = UNIT_END + 0x0093, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_28_3 = UNIT_END + 0x0094, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_28_5 = UNIT_END + 0x0096, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_29_1 = UNIT_END + 0x0097, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_29_2 = UNIT_END + 0x0098, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_29_3 = UNIT_END + 0x0099, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_29_5 = UNIT_END + 0x009B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_30_1 = UNIT_END + 0x009C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_30_2 = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_30_3 = UNIT_END + 0x009E, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_30_5 = UNIT_END + 0x00A0, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_31_1 = UNIT_END + 0x00A1, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_31_2 = UNIT_END + 0x00A2, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_31_3 = UNIT_END + 0x00A3, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_31_5 = UNIT_END + 0x00A5, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_32_1 = UNIT_END + 0x00A6, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_32_2 = UNIT_END + 0x00A7, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_32_3 = UNIT_END + 0x00A8, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_32_5 = UNIT_END + 0x00AA, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_33_1 = UNIT_END + 0x00AB, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_33_2 = UNIT_END + 0x00AC, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_33_3 = UNIT_END + 0x00AD, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_33_5 = UNIT_END + 0x00AF, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_34_1 = UNIT_END + 0x00B0, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_34_2 = UNIT_END + 0x00B1, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_34_3 = UNIT_END + 0x00B2, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_34_5 = UNIT_END + 0x00B4, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_35_1 = UNIT_END + 0x00B5, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_35_2 = UNIT_END + 0x00B6, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_35_3 = UNIT_END + 0x00B7, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_35_5 = UNIT_END + 0x00B9, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_36_1 = UNIT_END + 0x00BA, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_36_2 = UNIT_END + 0x00BB, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_36_3 = UNIT_END + 0x00BC, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_36_5 = UNIT_END + 0x00BE, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_37_1 = UNIT_END + 0x00BF, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_37_2 = UNIT_END + 0x00C0, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_37_3 = UNIT_END + 0x00C1, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_37_5 = UNIT_END + 0x00C3, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_38_1 = UNIT_END + 0x00C4, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_38_2 = UNIT_END + 0x00C5, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_38_3 = UNIT_END + 0x00C6, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_38_5 = UNIT_END + 0x00C8, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_39_1 = UNIT_END + 0x00C9, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_39_2 = UNIT_END + 0x00CA, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_39_3 = UNIT_END + 0x00CB, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_39_5 = UNIT_END + 0x00CD, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_40_1 = UNIT_END + 0x00CE, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_40_2 = UNIT_END + 0x00CF, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_40_3 = UNIT_END + 0x00D0, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_40_5 = UNIT_END + 0x00D2, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_41_1 = UNIT_END + 0x00D3, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_41_2 = UNIT_END + 0x00D4, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_41_3 = UNIT_END + 0x00D5, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_41_5 = UNIT_END + 0x00D7, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_42_1 = UNIT_END + 0x00D8, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_42_2 = UNIT_END + 0x00D9, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_42_3 = UNIT_END + 0x00DA, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_42_5 = UNIT_END + 0x00DC, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_43_1 = UNIT_END + 0x00DD, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_43_2 = UNIT_END + 0x00DE, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_43_3 = UNIT_END + 0x00DF, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_43_5 = UNIT_END + 0x00E1, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_44_1 = UNIT_END + 0x00E2, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_44_2 = UNIT_END + 0x00E3, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_44_3 = UNIT_END + 0x00E4, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_44_5 = UNIT_END + 0x00E6, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_45_1 = UNIT_END + 0x00E7, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_45_2 = UNIT_END + 0x00E8, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_45_3 = UNIT_END + 0x00E9, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_45_5 = UNIT_END + 0x00EB, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_46_1 = UNIT_END + 0x00EC, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_46_2 = UNIT_END + 0x00ED, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_46_3 = UNIT_END + 0x00EE, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_46_5 = UNIT_END + 0x00F0, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_47_1 = UNIT_END + 0x00F1, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_47_2 = UNIT_END + 0x00F2, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_47_3 = UNIT_END + 0x00F3, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_47_5 = UNIT_END + 0x00F5, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_48_1 = UNIT_END + 0x00F6, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_48_2 = UNIT_END + 0x00F7, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_48_3 = UNIT_END + 0x00F8, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_48_5 = UNIT_END + 0x00FA, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_49_1 = UNIT_END + 0x00FB, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_49_2 = UNIT_END + 0x00FC, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_49_3 = UNIT_END + 0x00FD, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_49_5 = UNIT_END + 0x00FF, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_50_1 = UNIT_END + 0x0100, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_50_2 = UNIT_END + 0x0101, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_50_3 = UNIT_END + 0x0102, // Size: 2, Type: TWO_SHORT, Flags: PARTY_MEMBER
+ PLAYER_QUEST_LOG_50_5 = UNIT_END + 0x0104, // Size: 1, Type: INT, Flags: PARTY_MEMBER
+ PLAYER_VISIBLE_ITEM_1_ENTRYID = UNIT_END + 0x0105, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_1_ENCHANTMENT = UNIT_END + 0x0106, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_2_ENTRYID = UNIT_END + 0x0107, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_2_ENCHANTMENT = UNIT_END + 0x0108, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_3_ENTRYID = UNIT_END + 0x0109, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_3_ENCHANTMENT = UNIT_END + 0x010A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_4_ENTRYID = UNIT_END + 0x010B, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_4_ENCHANTMENT = UNIT_END + 0x010C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_5_ENTRYID = UNIT_END + 0x010D, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_5_ENCHANTMENT = UNIT_END + 0x010E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_6_ENTRYID = UNIT_END + 0x010F, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_6_ENCHANTMENT = UNIT_END + 0x0110, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_7_ENTRYID = UNIT_END + 0x0111, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_7_ENCHANTMENT = UNIT_END + 0x0112, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_8_ENTRYID = UNIT_END + 0x0113, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_8_ENCHANTMENT = UNIT_END + 0x0114, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_9_ENTRYID = UNIT_END + 0x0115, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_9_ENCHANTMENT = UNIT_END + 0x0116, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_10_ENTRYID = UNIT_END + 0x0117, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_10_ENCHANTMENT = UNIT_END + 0x0118, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_11_ENTRYID = UNIT_END + 0x0119, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_11_ENCHANTMENT = UNIT_END + 0x011A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_12_ENTRYID = UNIT_END + 0x011B, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_12_ENCHANTMENT = UNIT_END + 0x011C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_13_ENTRYID = UNIT_END + 0x011D, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_13_ENCHANTMENT = UNIT_END + 0x011E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_14_ENTRYID = UNIT_END + 0x011F, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_14_ENCHANTMENT = UNIT_END + 0x0120, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_15_ENTRYID = UNIT_END + 0x0121, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_15_ENCHANTMENT = UNIT_END + 0x0122, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_16_ENTRYID = UNIT_END + 0x0123, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_16_ENCHANTMENT = UNIT_END + 0x0124, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_17_ENTRYID = UNIT_END + 0x0125, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_17_ENCHANTMENT = UNIT_END + 0x0126, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_18_ENTRYID = UNIT_END + 0x0127, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_18_ENCHANTMENT = UNIT_END + 0x0128, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_19_ENTRYID = UNIT_END + 0x0129, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_VISIBLE_ITEM_19_ENCHANTMENT = UNIT_END + 0x012A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
+ PLAYER_CHOSEN_TITLE = UNIT_END + 0x012B, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_FAKE_INEBRIATION = UNIT_END + 0x012C, // Size: 1, Type: INT, Flags: PUBLIC
+ PLAYER_FIELD_PAD_0 = UNIT_END + 0x012D, // Size: 1, Type: INT, Flags: NONE
+ PLAYER_END_NOT_SELF = UNIT_END + 0x012E,
- PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_GUILDID = UNIT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_GUILDRANK = UNIT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_BYTES = UNIT_END + 0x0005, // Size: 1, Type: BYTES, Flags: PUBLIC
- PLAYER_BYTES_2 = UNIT_END + 0x0006, // Size: 1, Type: BYTES, Flags: PUBLIC
- PLAYER_BYTES_3 = UNIT_END + 0x0007, // Size: 1, Type: BYTES, Flags: PUBLIC
- PLAYER_DUEL_TEAM = UNIT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_GUILD_TIMESTAMP = UNIT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_QUEST_LOG_1_1 = UNIT_END + 0x000A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_1_2 = UNIT_END + 0x000B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_1_3 = UNIT_END + 0x000C, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_1_4 = UNIT_END + 0x000E, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_2_1 = UNIT_END + 0x000F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_2_2 = UNIT_END + 0x0010, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_2_3 = UNIT_END + 0x0011, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_2_5 = UNIT_END + 0x0013, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_3_1 = UNIT_END + 0x0014, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_3_2 = UNIT_END + 0x0015, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_3_3 = UNIT_END + 0x0016, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_3_5 = UNIT_END + 0x0018, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_4_1 = UNIT_END + 0x0019, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_4_2 = UNIT_END + 0x001A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_4_3 = UNIT_END + 0x001B, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_4_5 = UNIT_END + 0x001D, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_5_1 = UNIT_END + 0x001E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_5_2 = UNIT_END + 0x001F, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_5_3 = UNIT_END + 0x0020, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_5_5 = UNIT_END + 0x0022, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_6_1 = UNIT_END + 0x0023, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_6_2 = UNIT_END + 0x0024, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_6_3 = UNIT_END + 0x0025, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_6_5 = UNIT_END + 0x0027, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_7_1 = UNIT_END + 0x0028, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_7_2 = UNIT_END + 0x0029, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_7_3 = UNIT_END + 0x002A, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_7_5 = UNIT_END + 0x002C, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_8_1 = UNIT_END + 0x002D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_8_2 = UNIT_END + 0x002E, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_8_3 = UNIT_END + 0x002F, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_8_5 = UNIT_END + 0x0031, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_9_1 = UNIT_END + 0x0032, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_9_2 = UNIT_END + 0x0033, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_9_3 = UNIT_END + 0x0034, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_9_5 = UNIT_END + 0x0036, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_10_1 = UNIT_END + 0x0037, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_10_2 = UNIT_END + 0x0038, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_10_3 = UNIT_END + 0x0039, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_10_5 = UNIT_END + 0x003B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_11_1 = UNIT_END + 0x003C, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_11_2 = UNIT_END + 0x003D, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_11_3 = UNIT_END + 0x003E, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_11_5 = UNIT_END + 0x0040, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_12_1 = UNIT_END + 0x0041, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_12_2 = UNIT_END + 0x0042, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_12_3 = UNIT_END + 0x0043, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_12_5 = UNIT_END + 0x0045, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_13_1 = UNIT_END + 0x0046, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_13_2 = UNIT_END + 0x0047, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_13_3 = UNIT_END + 0x0048, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_13_5 = UNIT_END + 0x004A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_14_1 = UNIT_END + 0x004B, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_14_2 = UNIT_END + 0x004C, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_14_3 = UNIT_END + 0x004D, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_14_5 = UNIT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_15_1 = UNIT_END + 0x0050, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_15_2 = UNIT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_15_3 = UNIT_END + 0x0052, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_15_5 = UNIT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_16_1 = UNIT_END + 0x0055, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_16_2 = UNIT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_16_3 = UNIT_END + 0x0057, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_16_5 = UNIT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_17_1 = UNIT_END + 0x005A, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_17_2 = UNIT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_17_3 = UNIT_END + 0x005C, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_17_5 = UNIT_END + 0x005E, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_18_1 = UNIT_END + 0x005F, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_18_2 = UNIT_END + 0x0060, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_18_3 = UNIT_END + 0x0061, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_18_5 = UNIT_END + 0x0063, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_19_1 = UNIT_END + 0x0064, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_19_2 = UNIT_END + 0x0065, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_19_3 = UNIT_END + 0x0066, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_19_5 = UNIT_END + 0x0068, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_20_1 = UNIT_END + 0x0069, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_20_2 = UNIT_END + 0x006A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_20_3 = UNIT_END + 0x006B, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_20_5 = UNIT_END + 0x006D, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_21_1 = UNIT_END + 0x006E, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_21_2 = UNIT_END + 0x006F, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_21_3 = UNIT_END + 0x0070, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_21_5 = UNIT_END + 0x0072, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_22_1 = UNIT_END + 0x0073, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_22_2 = UNIT_END + 0x0074, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_22_3 = UNIT_END + 0x0075, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_22_5 = UNIT_END + 0x0077, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_23_1 = UNIT_END + 0x0078, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_23_2 = UNIT_END + 0x0079, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_23_3 = UNIT_END + 0x007A, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_23_5 = UNIT_END + 0x007C, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_24_1 = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_24_2 = UNIT_END + 0x007E, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_24_3 = UNIT_END + 0x007F, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_24_5 = UNIT_END + 0x0081, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_25_1 = UNIT_END + 0x0082, // Size: 1, Type: INT, Flags: PARTY_MEMBER
- PLAYER_QUEST_LOG_25_2 = UNIT_END + 0x0083, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x0084, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_QUEST_LOG_25_5 = UNIT_END + 0x0086, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_VISIBLE_ITEM_1_ENTRYID = UNIT_END + 0x0087, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_1_ENCHANTMENT = UNIT_END + 0x0088, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_2_ENTRYID = UNIT_END + 0x0089, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_2_ENCHANTMENT = UNIT_END + 0x008A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_3_ENTRYID = UNIT_END + 0x008B, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_3_ENCHANTMENT = UNIT_END + 0x008C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_4_ENTRYID = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_4_ENCHANTMENT = UNIT_END + 0x008E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_5_ENTRYID = UNIT_END + 0x008F, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_5_ENCHANTMENT = UNIT_END + 0x0090, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_6_ENTRYID = UNIT_END + 0x0091, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_6_ENCHANTMENT = UNIT_END + 0x0092, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_7_ENTRYID = UNIT_END + 0x0093, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_7_ENCHANTMENT = UNIT_END + 0x0094, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_8_ENTRYID = UNIT_END + 0x0095, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_8_ENCHANTMENT = UNIT_END + 0x0096, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_9_ENTRYID = UNIT_END + 0x0097, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_9_ENCHANTMENT = UNIT_END + 0x0098, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_10_ENTRYID = UNIT_END + 0x0099, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_10_ENCHANTMENT = UNIT_END + 0x009A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_11_ENTRYID = UNIT_END + 0x009B, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_11_ENCHANTMENT = UNIT_END + 0x009C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_12_ENTRYID = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_12_ENCHANTMENT = UNIT_END + 0x009E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_13_ENTRYID = UNIT_END + 0x009F, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_13_ENCHANTMENT = UNIT_END + 0x00A0, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_14_ENTRYID = UNIT_END + 0x00A1, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_14_ENCHANTMENT = UNIT_END + 0x00A2, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_15_ENTRYID = UNIT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_15_ENCHANTMENT = UNIT_END + 0x00A4, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_16_ENTRYID = UNIT_END + 0x00A5, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_16_ENCHANTMENT = UNIT_END + 0x00A6, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_17_ENTRYID = UNIT_END + 0x00A7, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_17_ENCHANTMENT = UNIT_END + 0x00A8, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_18_ENTRYID = UNIT_END + 0x00A9, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_18_ENCHANTMENT = UNIT_END + 0x00AA, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_19_ENTRYID = UNIT_END + 0x00AB, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_VISIBLE_ITEM_19_ENCHANTMENT = UNIT_END + 0x00AC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
- PLAYER_CHOSEN_TITLE = UNIT_END + 0x00AD, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_FAKE_INEBRIATION = UNIT_END + 0x00AE, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_FIELD_PAD_0 = UNIT_END + 0x00AF, // Size: 1, Type: INT, Flags: NONE
- PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x00B0, // Size: 46, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x00DE, // Size: 32, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x00FE, // Size: 56, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x0136, // Size: 14, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x0144, // Size: 24, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x015C, // Size: 64, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_CURRENCYTOKEN_SLOT_1 = UNIT_END + 0x019C, // Size: 64, Type: LONG, Flags: PRIVATE
- PLAYER_FARSIGHT = UNIT_END + 0x01DC, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x01DE, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER__FIELD_KNOWN_TITLES1 = UNIT_END + 0x01E0, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER__FIELD_KNOWN_TITLES2 = UNIT_END + 0x01E2, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER_FIELD_KNOWN_CURRENCIES = UNIT_END + 0x01E4, // Size: 2, Type: LONG, Flags: PRIVATE
- PLAYER_XP = UNIT_END + 0x01E6, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x01E7, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x01E8, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x0368, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x0369, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_TRACK_CREATURES = UNIT_END + 0x036A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_TRACK_RESOURCES = UNIT_END + 0x036B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x036C, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x036D, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x036E, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_EXPERTISE = UNIT_END + 0x036F, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x0370, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x0371, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x0372, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0373, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0374, // Size: 7, Type: FLOAT, Flags: PRIVATE
- PLAYER_SHIELD_BLOCK = UNIT_END + 0x037B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE = UNIT_END + 0x037C, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x037D, // Size: 128, Type: BYTES, Flags: PRIVATE
- PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x03FD, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_COINAGE = UNIT_END + 0x03FE, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x03FF, // Size: 7, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x0406, // Size: 7, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x040D, // Size: 7, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x0414, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_HEALING_PCT = UNIT_END + 0x0415, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_FIELD_MOD_HEALING_DONE_PCT = UNIT_END + 0x0416, // Size: 1, Type: FLOAT, Flags: PRIVATE
- PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x0417, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x0418, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BYTES = UNIT_END + 0x0419, // Size: 1, Type: BYTES, Flags: PRIVATE
- PLAYER_AMMO_ID = UNIT_END + 0x041A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_SELF_RES_SPELL = UNIT_END + 0x041B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x041C, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x041D, // Size: 12, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x0429, // Size: 12, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_KILLS = UNIT_END + 0x0435, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x0436, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_LIFETIME_HONORABLE_KILLS = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BYTES2 = UNIT_END + 0x0439, // Size: 1, Type: 6, Flags: PRIVATE
- PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x043A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x043B, // Size: 25, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x0454, // Size: 21, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x0469, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x046A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x046B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x046C, // Size: 25, Type: INT, Flags: PRIVATE
- PLAYER_RUNE_REGEN_1 = UNIT_END + 0x0485, // Size: 4, Type: FLOAT, Flags: PRIVATE
- PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x0489, // Size: 3, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x048C, // Size: 6, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x0492, // Size: 6, Type: INT, Flags: PRIVATE
- PLAYER_GLYPHS_ENABLED = UNIT_END + 0x0498, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_PET_SPELL_POWER = UNIT_END + 0x0499, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_END = UNIT_END + 0x049A
+ PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x012E, // Size: 46, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x015C, // Size: 32, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x017C, // Size: 56, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x01B4, // Size: 14, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x01C2, // Size: 24, Type: LONG, Flags: PRIVATE
+ PLAYER_FARSIGHT = UNIT_END + 0x01DA, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x01DC, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER__FIELD_KNOWN_TITLES1 = UNIT_END + 0x01DE, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER__FIELD_KNOWN_TITLES2 = UNIT_END + 0x01E0, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER__FIELD_KNOWN_TITLES3 = UNIT_END + 0x01E2, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER_XP = UNIT_END + 0x01E4, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x01E5, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_SKILL_LINEID_0 = UNIT_END + 0x01E6, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_SKILL_STEP_0 = UNIT_END + 0x0226, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_SKILL_RANK_0 = UNIT_END + 0x0266, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_SKILL_MAX_RANK_0 = UNIT_END + 0x02A6, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_SKILL_MODIFIER_0 = UNIT_END + 0x02E6, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_SKILL_TALENT_0 = UNIT_END + 0x0326, // Size: 64, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_CHARACTER_POINTS = UNIT_END + 0x0366, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_TRACK_CREATURES = UNIT_END + 0x0367, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_TRACK_RESOURCES = UNIT_END + 0x0368, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_EXPERTISE = UNIT_END + 0x0369, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x036A, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x036B, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x036C, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x036D, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x036E, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x036F, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0370, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0371, // Size: 7, Type: FLOAT, Flags: PRIVATE
+ PLAYER_SHIELD_BLOCK = UNIT_END + 0x0378, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE = UNIT_END + 0x0379, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_MASTERY = UNIT_END + 0x037A, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x037B, // Size: 156, Type: BYTES, Flags: PRIVATE
+ PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x0417, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_COINAGE = UNIT_END + 0x0418, // Size: 2, Type: LONG, Flags: PRIVATE
+ PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x041A, // Size: 7, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x0421, // Size: 7, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x0428, // Size: 7, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x042F, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HEALING_PCT = UNIT_END + 0x0430, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HEALING_DONE_PCT = UNIT_END + 0x0431, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_WEAPON_DMG_MULTIPLIERS = UNIT_END + 0x0432, // Size: 3, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_SPELL_POWER_PCT = UNIT_END + 0x0435, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_OVERRIDE_SPELL_POWER_BY_AP_PCT = UNIT_END + 0x0436, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BYTES = UNIT_END + 0x0439, // Size: 1, Type: BYTES, Flags: PRIVATE
+ PLAYER_SELF_RES_SPELL = UNIT_END + 0x043A, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x043B, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x043C, // Size: 12, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x0448, // Size: 12, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_KILLS = UNIT_END + 0x0454, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_FIELD_LIFETIME_HONORABLE_KILLS = UNIT_END + 0x0455, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BYTES2 = UNIT_END + 0x0456, // Size: 1, Type: 6, Flags: PRIVATE
+ PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x0457, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x0458, // Size: 26, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x0472, // Size: 21, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BATTLEGROUND_RATING = UNIT_END + 0x0487, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x0488, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x0489, // Size: 25, Type: INT, Flags: PRIVATE
+ PLAYER_RUNE_REGEN_1 = UNIT_END + 0x04A2, // Size: 4, Type: FLOAT, Flags: PRIVATE
+ PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x04A6, // Size: 3, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x04A9, // Size: 9, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x04B2, // Size: 9, Type: INT, Flags: PRIVATE
+ PLAYER_GLYPHS_ENABLED = UNIT_END + 0x04BB, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_PET_SPELL_POWER = UNIT_END + 0x04BC, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_RESEARCHING_1 = UNIT_END + 0x04BD, // Size: 8, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_FIELD_RESERACH_SITE_1 = UNIT_END + 0x04C5, // Size: 8, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_PROFESSION_SKILL_LINE_1 = UNIT_END + 0x04CD, // Size: 2, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_UI_HIT_MODIFIER = UNIT_END + 0x04CF, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_UI_SPELL_HIT_MODIFIER = UNIT_END + 0x04D0, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_HOME_REALM_TIME_OFFSET = UNIT_END + 0x04D1, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HASTE = UNIT_END + 0x04D2, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_RANGED_HASTE = UNIT_END + 0x04D3, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_PET_HASTE = UNIT_END + 0x04D4, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HASTE_REGEN = UNIT_END + 0x04D5, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_END = UNIT_END + 0x04D6
};
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_PARENTROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC
- GAMEOBJECT_DYNAMIC = OBJECT_END + 0x0008, // Size: 1, Type: TWO_SHORT, Flags: DYNAMIC
- GAMEOBJECT_FACTION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_LEVEL = OBJECT_END + 0x000A, // Size: 1, Type: INT, Flags: PUBLIC
- GAMEOBJECT_BYTES_1 = OBJECT_END + 0x000B, // Size: 1, Type: BYTES, Flags: PUBLIC
- GAMEOBJECT_END = OBJECT_END + 0x000C
+ 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_PARENTROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC
+ GAMEOBJECT_DYNAMIC = OBJECT_END + 0x0008, // Size: 1, Type: TWO_SHORT, Flags: DYNAMIC
+ GAMEOBJECT_FACTION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC
+ GAMEOBJECT_LEVEL = OBJECT_END + 0x000A, // Size: 1, Type: INT, Flags: PUBLIC
+ GAMEOBJECT_BYTES_1 = OBJECT_END + 0x000B, // Size: 1, Type: BYTES, Flags: PUBLIC
+ GAMEOBJECT_END = OBJECT_END + 0x000C
};
enum EDynamicObjectFields
{
- DYNAMICOBJECT_CASTER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- DYNAMICOBJECT_BYTES = OBJECT_END + 0x0002, // Size: 1, Type: BYTES, Flags: PUBLIC
- DYNAMICOBJECT_SPELLID = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
- DYNAMICOBJECT_RADIUS = OBJECT_END + 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC
- DYNAMICOBJECT_CASTTIME = OBJECT_END + 0x0005, // Size: 1, Type: INT, Flags: PUBLIC
- DYNAMICOBJECT_END = OBJECT_END + 0x0006
+ DYNAMICOBJECT_CASTER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ DYNAMICOBJECT_BYTES = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: DYNAMIC
+ DYNAMICOBJECT_SPELLID = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
+ DYNAMICOBJECT_RADIUS = OBJECT_END + 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC
+ DYNAMICOBJECT_CASTTIME = OBJECT_END + 0x0005, // Size: 1, Type: INT, Flags: PUBLIC
+ DYNAMICOBJECT_END = OBJECT_END + 0x0006
};
enum ECorpseFields
{
- CORPSE_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
- CORPSE_FIELD_PARTY = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
- CORPSE_FIELD_DISPLAY_ID = OBJECT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC
- CORPSE_FIELD_ITEM = OBJECT_END + 0x0005, // Size: 19, Type: INT, Flags: PUBLIC
- CORPSE_FIELD_BYTES_1 = OBJECT_END + 0x0018, // Size: 1, Type: BYTES, Flags: PUBLIC
- CORPSE_FIELD_BYTES_2 = OBJECT_END + 0x0019, // Size: 1, Type: BYTES, Flags: PUBLIC
- CORPSE_FIELD_GUILD = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
- CORPSE_FIELD_FLAGS = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
- CORPSE_FIELD_DYNAMIC_FLAGS = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: DYNAMIC
- CORPSE_FIELD_PAD = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: NONE
- CORPSE_END = OBJECT_END + 0x001E
+ CORPSE_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
+ CORPSE_FIELD_PARTY = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
+ CORPSE_FIELD_DISPLAY_ID = OBJECT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC
+ CORPSE_FIELD_ITEM = OBJECT_END + 0x0005, // Size: 19, Type: INT, Flags: PUBLIC
+ CORPSE_FIELD_BYTES_1 = OBJECT_END + 0x0018, // Size: 1, Type: BYTES, Flags: PUBLIC
+ CORPSE_FIELD_BYTES_2 = OBJECT_END + 0x0019, // Size: 1, Type: BYTES, Flags: PUBLIC
+ CORPSE_FIELD_FLAGS = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
+ CORPSE_FIELD_DYNAMIC_FLAGS = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: DYNAMIC
+ CORPSE_END = OBJECT_END + 0x001C
};
-#endif
+
+enum EAreaTriggerFields
+{
+ AREATRIGGER_SPELLID = OBJECT_END + 0x0000, // Size: 1, Type: INT, Flags: PUBLIC
+ AREATRIGGER_SPELLVISUALID = OBJECT_END + 0x0001, // Size: 1, Type: INT, Flags: PUBLIC
+ AREATRIGGER_DURATION = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
+ AREATRIGGER_FINAL_POS = OBJECT_END + 0x0003, // Size: 3, Type: FLOAT, Flags: PUBLIC
+ AREATRIGGER_END = OBJECT_END + 0x0006
+};
+
+#endif // _UPDATEFIELDS_H
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 876f35a58ce..5c731c6f8f7 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -30,13 +30,14 @@
#include "Unit.h"
#include "Util.h"
#include "Group.h"
+#include "Opcodes.h"
#include "WorldSession.h"
#define PET_XP_FACTOR 0.05f
Pet::Pet(Player* owner, PetType type) :
Guardian(NULL, owner, true), m_usedTalentCount(0), m_removed(false),
- m_happinessTimer(7500), m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false),
+ m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false),
m_declinedname(NULL)
{
ASSERT(GetOwner());
@@ -150,14 +151,14 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
if (!petEntry)
return false;
- uint32 summonSpellId = fields[15].GetUInt32();
+ uint32 summonSpellId = fields[14].GetUInt32();
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summonSpellId);
bool isTemporarySummon = spellInfo && spellInfo->GetDuration() > 0;
if (current && isTemporarySummon)
return false;
- PetType petType = PetType(fields[16].GetUInt8());
+ PetType petType = PetType(fields[15].GetUInt8());
if (petType == HUNTER_PET)
{
CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petEntry);
@@ -178,6 +179,9 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
if (!Create(guid, map, owner->GetPhaseMask(), petEntry, petId))
return false;
+ for (auto itr : owner->GetPhases())
+ SetInPhase(itr, false, true);
+
setPetType(petType);
setFaction(owner->getFaction());
SetUInt32Value(UNIT_CREATED_BY_SPELL, summonSpellId);
@@ -224,8 +228,6 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
// this enables popup window (pet abandon, cancel)
- SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
- SetPower(POWER_HAPPINESS, fields[12].GetUInt32());
setPowerType(POWER_FOCUS);
break;
default:
@@ -267,7 +269,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
else
{
SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth);
- SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana);
+ SetPower(POWER_MANA, savedmana > uint32(GetMaxPower(POWER_MANA)) ? GetMaxPower(POWER_MANA) : savedmana);
}
}
@@ -315,13 +317,13 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
InitTalentForLevel(); // set original talents points before spell loading
- uint32 timediff = uint32(time(NULL) - fields[14].GetUInt32());
+ uint32 timediff = uint32(time(NULL) - fields[13].GetUInt32());
_LoadAuras(timediff);
// load action bar, if data broken will fill later by default spells.
if (!isTemporarySummon)
{
- m_charmInfo->LoadPetActionBar(fields[13].GetString());
+ m_charmInfo->LoadPetActionBar(fields[12].GetString());
_LoadSpells();
InitTalentForLevel(); // re-init to check talent count
@@ -447,7 +449,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
// save pet
std::ostringstream ss;
- ss << "INSERT INTO character_pet (id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType) "
+ ss << "INSERT INTO character_pet (id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType) "
<< "VALUES ("
<< m_charmInfo->GetPetNumber() << ','
<< GetEntry() << ','
@@ -460,8 +462,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
<< name.c_str() << "', "
<< uint32(HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) ? 0 : 1) << ','
<< curhealth << ','
- << curmana << ','
- << GetPower(POWER_HAPPINESS) << ", '";
+ << curmana << ", '";
for (uint32 i = ACTION_BAR_INDEX_START; i < ACTION_BAR_INDEX_END; ++i)
{
@@ -523,10 +524,6 @@ void Pet::setDeathState(DeathState s) // overwrite virtual
SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE);
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
- // lose happiness when died and not in BG/Arena
- if (!GetMap()->IsBattlegroundOrArena())
- ModifyPower(POWER_HAPPINESS, -HAPPINESS_LEVEL_SIZE);
-
//SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
}
}
@@ -620,18 +617,6 @@ void Pet::Update(uint32 diff)
}
}
}
-
- if (getPetType() != HUNTER_PET)
- break;
-
- if (m_happinessTimer <= diff)
- {
- LoseHappiness();
- m_happinessTimer = 7500;
- }
- else
- m_happinessTimer -= diff;
-
break;
}
default:
@@ -679,27 +664,6 @@ void Creature::Regenerate(Powers power)
ModifyPower(power, int32(addvalue));
}
-void Pet::LoseHappiness()
-{
- uint32 curValue = GetPower(POWER_HAPPINESS);
- if (curValue <= 0)
- return;
- 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.5f);
- ModifyPower(POWER_HAPPINESS, -addvalue);
-}
-
-HappinessState Pet::GetHappinessState()
-{
- if (GetPower(POWER_HAPPINESS) < HAPPINESS_LEVEL_SIZE)
- return UNHAPPY;
- else if (GetPower(POWER_HAPPINESS) >= HAPPINESS_LEVEL_SIZE * 2)
- return HAPPY;
- else
- return CONTENT;
-}
-
void Pet::Remove(PetSaveMode mode, bool returnreagent)
{
GetOwner()->RemovePet(this, mode, returnreagent);
@@ -784,7 +748,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
SetDisplayId(creature->GetDisplayId());
if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))
- SetName(cFamily->Name[sWorld->GetDefaultDbcLocale()]);
+ SetName(cFamily->Name);
else
SetName(creature->GetNameForLocaleIdx(sObjectMgr->GetDBCLocaleIndex()));
@@ -797,7 +761,7 @@ bool Pet::CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner)
return false;
if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))
- SetName(cFamily->Name[sWorld->GetDefaultDbcLocale()]);
+ SetName(cFamily->Name);
Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation());
@@ -812,8 +776,6 @@ bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phas
if (!Create(guid, map, phaseMask, cinfo->Entry, petId))
return false;
- SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
- SetPower(POWER_HAPPINESS, 166500);
setPowerType(POWER_FOCUS);
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
@@ -871,6 +833,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME);
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
+ SetFloatValue(UNIT_MOD_CAST_HASTE, 1.0f);
//scale
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family);
@@ -1891,6 +1854,8 @@ bool Pet::IsPermanentPetFor(Player* owner) const
return GetCreatureTemplate()->type == CREATURE_TYPE_DEMON;
case CLASS_DEATH_KNIGHT:
return GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD;
+ case CLASS_MAGE:
+ return GetCreatureTemplate()->type == CREATURE_TYPE_ELEMENTAL;
default:
return false;
}
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index 68465f6b8e7..97323f3f9ab 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -77,8 +77,6 @@ class Pet : public Guardian
return m_autospells[pos];
}
- void LoseHappiness();
- HappinessState GetHappinessState();
void GivePetXP(uint32 xp);
void GivePetLevel(uint8 level);
void SynchronizeLevelWithOwner();
@@ -149,7 +147,6 @@ class Pet : public Guardian
Player* GetOwner() const;
protected:
- uint32 m_happinessTimer;
PetType m_petType;
int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets)
uint64 m_auraRaidUpdateMask;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index ee93fc09f5e..73d87ef4774 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -36,6 +36,7 @@
#include "ConditionMgr.h"
#include "CreatureAI.h"
#include "DatabaseEnv.h"
+#include "DB2Stores.h"
#include "DisableMgr.h"
#include "Formulas.h"
#include "GameEventMgr.h"
@@ -78,22 +79,11 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
+#include "MovementStructures.h"
#include "GameObjectAI.h"
#define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS)
-#define PLAYER_SKILL_INDEX(x) (PLAYER_SKILL_INFO_1_1 + ((x)*3))
-#define PLAYER_SKILL_VALUE_INDEX(x) (PLAYER_SKILL_INDEX(x)+1)
-#define PLAYER_SKILL_BONUS_INDEX(x) (PLAYER_SKILL_INDEX(x)+2)
-
-#define SKILL_VALUE(x) PAIR32_LOPART(x)
-#define SKILL_MAX(x) PAIR32_HIPART(x)
-#define MAKE_SKILL_VALUE(v, m) MAKE_PAIR32(v, m)
-
-#define SKILL_TEMP_BONUS(x) int16(PAIR32_LOPART(x))
-#define SKILL_PERM_BONUS(x) int16(PAIR32_HIPART(x))
-#define MAKE_SKILL_BONUS(t, p) MAKE_PAIR32(t, p)
-
enum CharacterFlags
{
CHARACTER_FLAG_NONE = 0x00000000,
@@ -145,7 +135,23 @@ enum CharacterCustomizeFlags
static uint32 copseReclaimDelay[MAX_DEATH_COUNT] = { 30, 60, 120 };
-uint32 const MAX_MONEY_AMOUNT = static_cast<uint32>(std::numeric_limits<int32>::max());
+uint32 const MasterySpells[MAX_CLASSES] =
+{
+ 0,
+ 87500, // Warrior
+ 87494, // Paladin
+ 87493, // Hunter
+ 87496, // Rogue
+ 87495, // Priest
+ 87492, // Death Knight
+ 87497, // Shaman
+ 86467, // Mage
+ 87498, // Warlock
+ 0,
+ 87491, // Druid
+};
+
+uint64 const MAX_MONEY_AMOUNT = static_cast<uint64>(std::numeric_limits<int64>::max());
// == PlayerTaxi ================================================
@@ -208,15 +214,16 @@ void PlayerTaxi::LoadTaxiMask(std::string const &data)
void PlayerTaxi::AppendTaximaskTo(ByteBuffer& data, bool all)
{
+ data << uint32(TaxiMaskSize);
if (all)
{
for (uint8 i = 0; i < TaxiMaskSize; ++i)
- data << uint32(sTaxiNodesMask[i]); // all existed nodes
+ data << uint8(sTaxiNodesMask[i]); // all existed nodes
}
else
{
for (uint8 i = 0; i < TaxiMaskSize; ++i)
- data << uint32(m_taximask[i]); // known nodes
+ data << uint8(m_taximask[i]); // known nodes
}
}
@@ -284,7 +291,7 @@ uint32 PlayerTaxi::GetCurrentTaxiPath() const
std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
{
for (uint8 i = 0; i < TaxiMaskSize; ++i)
- ss << taxi.m_taximask[i] << ' ';
+ ss << uint32(taxi.m_taximask[i]) << ' ';
return ss;
}
@@ -362,7 +369,7 @@ void TradeData::SetSpell(uint32 spell_id, Item* castItem /*= NULL*/)
Update(false); // send spell info to caster self
}
-void TradeData::SetMoney(uint32 money)
+void TradeData::SetMoney(uint64 money)
{
if (m_money == money)
return;
@@ -442,6 +449,7 @@ void TradeData::SetAccepted(bool state, bool crosssend /*= false*/)
// 4.3. Give reputation (player must not be on BG).
// 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
// 5. Credit instance encounter.
+// 6. Update guild achievements.
KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) :
// 1. Initialize internal variables to default values.
_killer(killer), _victim(victim), _group(killer->GetGroup()),
@@ -530,10 +538,14 @@ inline void KillRewarder::_RewardXP(Player* player, float rate)
for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
AddPct(xp, (*i)->GetAmount());
- // 4.2.3. Give XP to player.
+ // 4.2.3. Calculate expansion penalty
+ if (_victim->GetTypeId() == TYPEID_UNIT && player->getLevel() >= GetMaxLevelForExpansion(_victim->ToCreature()->GetCreatureTemplate()->expansion))
+ xp = CalculatePct(xp, 10); // Players get only 10% xp for killing creatures of lower expansion levels than himself
+
+ // 4.2.4. Give XP to player.
player->GiveXP(xp, _victim, _groupRate);
if (Pet* pet = player->GetPet())
- // 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
+ // 4.2.5. If player has pet, reward pet with XP (100% for single player, 50% for group case).
pet->GivePetXP(_group ? xp / 2 : xp);
}
}
@@ -552,7 +564,7 @@ inline void KillRewarder::_RewardKillCredit(Player* player)
if (Creature* target = _victim->ToCreature())
{
player->KilledMonster(target->GetCreatureTemplate(), target->GetGUID());
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, target->GetCreatureType(), 1, target);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, target->GetCreatureType(), 1, 0, target);
}
}
@@ -615,7 +627,7 @@ void KillRewarder::_RewardGroup()
if (member->IsAtGroupRewardDistance(_victim))
{
_RewardPlayer(member, isDungeon);
- member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, _victim);
+ member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, 0, _victim);
}
}
}
@@ -643,10 +655,18 @@ void KillRewarder::Reward()
}
// 5. Credit instance encounter.
+ // 6. Update guild achievements.
if (Creature* victim = _victim->ToCreature())
+ {
if (victim->IsDungeonBoss())
if (InstanceScript* instance = _victim->GetInstanceScript())
instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, _victim->GetEntry(), _victim);
+
+ if (uint32 guildId = victim->GetMap()->GetOwnerGuildId())
+ if (Guild* guild = sGuildMgr->GetGuildById(guildId))
+ guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, victim->GetEntry(), 1, 0, victim, _killer);
+ }
+
}
Player::Player(WorldSession* session): Unit(true)
@@ -678,11 +698,10 @@ Player::Player(WorldSession* session): Unit(true)
m_comboTarget = 0;
m_comboPoints = 0;
- m_usedTalentCount = 0;
- m_questRewardTalentCount = 0;
-
m_regenTimer = 0;
m_regenTimerCount = 0;
+ m_holyPowerRegenTimerCount = 0;
+ m_focusRegenTimerCount = 0;
m_weaponChangeTimer = 0;
m_zoneUpdateId = uint32(-1);
@@ -695,7 +714,7 @@ Player::Player(WorldSession* session): Unit(true)
m_nextSave = sWorld->getIntConfig(CONFIG_INTERVAL_SAVE);
- clearResurrectRequestData();
+ _resurrectionData = NULL;
memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT);
@@ -760,7 +779,6 @@ Player::Player(WorldSession* session): Unit(true)
m_canParry = false;
m_canBlock = false;
m_canTitanGrip = false;
- m_ammoDPS = 0.0f;
m_temporaryUnsummonedPetNumber = 0;
//cache for UNIT_CREATED_BY_SPELL to allow
@@ -784,8 +802,6 @@ Player::Player(WorldSession* session): Unit(true)
unReadMails = 0;
m_nextMailDelivereTime = 0;
- m_resetTalentsCost = 0;
- m_resetTalentsTime = 0;
m_itemUpdateQueueBlocked = false;
for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
@@ -802,17 +818,7 @@ Player::Player(WorldSession* session): Unit(true)
m_raidMapDifficulty = RAID_DIFFICULTY_10MAN_NORMAL;
m_lastPotionId = 0;
-
- m_activeSpec = 0;
- m_specsCount = 1;
-
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
- {
- for (uint8 g = 0; g < MAX_GLYPH_SLOT_INDEX; ++g)
- m_Glyphs[i][g] = 0;
-
- m_talents[i] = new PlayerTalentMap();
- }
+ _talentMgr = new PlayerTalentInfo();
for (uint8 i = 0; i < BASEMOD_END; ++i)
{
@@ -824,7 +830,6 @@ Player::Player(WorldSession* session): Unit(true)
m_baseRatingValue[i] = 0;
m_baseSpellPower = 0;
- m_baseFeralAP = 0;
m_baseManaRegen = 0;
m_baseHealthRegen = 0;
m_spellPenetrationItemMod = 0;
@@ -876,12 +881,11 @@ Player::Player(WorldSession* session): Unit(true)
m_ChampioningFaction = 0;
- m_timeSyncCounter = 0;
m_timeSyncTimer = 0;
m_timeSyncClient = 0;
m_timeSyncServer = 0;
- for (uint8 i = 0; i < MAX_POWERS; ++i)
+ for (uint8 i = 0; i < MAX_POWERS_PER_CLASS; ++i)
m_powerFraction[i] = 0;
isDebugAreaTriggers = false;
@@ -895,7 +899,12 @@ Player::Player(WorldSession* session): Unit(true)
SetPendingBind(0, 0);
_activeCheats = CHEAT_NONE;
- m_achievementMgr = new AchievementMgr(this);
+ _maxPersonalArenaRate = 0;
+
+ memset(_voidStorageItems, 0, VOID_STORAGE_MAX_SLOT * sizeof(VoidStorageItem*));
+ memset(_CUFProfiles, 0, MAX_CUF_PROFILES * sizeof(CUFProfile*));
+
+ m_achievementMgr = new AchievementMgr<Player>(this);
m_reputationMgr = new ReputationMgr(this);
}
@@ -911,12 +920,7 @@ Player::~Player()
for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
delete itr->second;
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
- {
- for (PlayerTalentMap::const_iterator itr = m_talents[i]->begin(); itr != m_talents[i]->end(); ++itr)
- delete itr->second;
- delete m_talents[i];
- }
+ delete _talentMgr;
//all mailed items should be deleted, also all mail should be deallocated
for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr)
@@ -935,6 +939,14 @@ Player::~Player()
delete m_achievementMgr;
delete m_reputationMgr;
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ delete _voidStorageItems[i];
+
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ delete _CUFProfiles[i];
+
+ ClearResurrectRequestData();
+
sWorld->DecreasePlayerCount();
}
@@ -1007,8 +1019,8 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
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
SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); // -1 is default value
@@ -1021,8 +1033,9 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
SetByteValue(PLAYER_BYTES_3, 0, createInfo->Gender);
SetByteValue(PLAYER_BYTES_3, 3, 0); // BattlefieldArenaFaction (0 or 1)
- SetUInt32Value(PLAYER_GUILDID, 0);
+ SetUInt64Value(OBJECT_FIELD_DATA, 0);
SetUInt32Value(PLAYER_GUILDRANK, 0);
+ SetGuildLevel(0);
SetUInt32Value(PLAYER_GUILD_TIMESTAMP, 0);
for (int i = 0; i < KNOWN_TITLES_SIZE; ++i)
@@ -1031,8 +1044,6 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
SetUInt32Value(PLAYER_FIELD_KILLS, 0);
SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0);
- SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0);
- SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0);
// set starting level
uint32 start_level = getClass() != CLASS_DEATH_KNIGHT
@@ -1051,8 +1062,9 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
InitRunes();
SetUInt32Value(PLAYER_FIELD_COINAGE, sWorld->getIntConfig(CONFIG_START_PLAYER_MONEY));
- SetHonorPoints(sWorld->getIntConfig(CONFIG_START_HONOR_POINTS));
- SetArenaPoints(sWorld->getIntConfig(CONFIG_START_ARENA_POINTS));
+ SetCurrency(CURRENCY_TYPE_HONOR_POINTS, sWorld->getIntConfig(CONFIG_CURRENCY_START_HONOR_POINTS));
+ SetCurrency(CURRENCY_TYPE_JUSTICE_POINTS, sWorld->getIntConfig(CONFIG_CURRENCY_START_JUSTICE_POINTS));
+ SetCurrency(CURRENCY_TYPE_CONQUEST_POINTS, sWorld->getIntConfig(CONFIG_CURRENCY_START_CONQUEST_POINTS));
// start with every map explored
if (sWorld->getBoolConfig(CONFIG_START_ALL_EXPLORED))
@@ -1127,8 +1139,8 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
if (getPowerType() == POWER_RUNIC_POWER)
{
- SetPower(POWER_RUNE, 8);
- SetMaxPower(POWER_RUNE, 8);
+ SetPower(POWER_RUNES, 8);
+ SetMaxPower(POWER_RUNES, 8);
SetPower(POWER_RUNIC_POWER, 0);
SetMaxPower(POWER_RUNIC_POWER, 1000);
}
@@ -1160,7 +1172,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
uint32 count = iProto->BuyCount;
// special amount for food/drink
- if (iProto->Class == ITEM_CLASS_CONSUMABLE && iProto->SubClass == ITEM_SUBCLASS_FOOD)
+ if (iProto->Class == ITEM_CLASS_CONSUMABLE && iProto->SubClass == ITEM_SUBCLASS_FOOD_DRINK)
{
switch (iProto->Spells[0].SpellCategory)
{
@@ -1196,7 +1208,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
RemoveItem(INVENTORY_SLOT_BAG_0, i, true);
EquipItem(eDest, pItem, true);
}
- // move other items to more appropriate slots (ammo not equipped in special bag)
+ // move other items to more appropriate slots
else
{
ItemPosCountVec sDest;
@@ -1206,11 +1218,6 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
RemoveItem(INVENTORY_SLOT_BAG_0, i, true);
pItem = StoreItem(sDest, pItem, true);
}
-
- // if this is ammo then use it
- msg = CanUseAmmo(pItem->GetEntry());
- if (msg == EQUIP_ERR_OK)
- SetAmmo(pItem->GetEntry());
}
}
}
@@ -1320,8 +1327,7 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
TC_LOG_DEBUG("entities.player", "We are fall to death, loosing 10 percents durability");
DurabilityLossAll(0.10f, false);
// durability lost message
- WorldPacket data2(SMSG_DURABILITY_DAMAGE_DEATH, 0);
- GetSession()->SendPacket(&data2);
+ SendDurabilityLoss(this, 10);
}
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM, 1, type);
@@ -1876,7 +1882,7 @@ void Player::setDeathState(DeathState s)
// lost combo points at any target (targeted combo points clear in Unit::setDeathState)
ClearComboPoints();
- clearResurrectRequestData();
+ ClearResurrectRequestData();
//FIXME: is pet dismissed at dying or releasing spirit? if second, add setDeathState(DEAD) to HandleRepopRequestOpcode and define pet unsummon here with (s == DEAD)
RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
@@ -1915,100 +1921,70 @@ void Player::InnEnter(time_t time, uint32 mapid, float x, float y, float z)
time_inn_enter = time;
}
-bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
+bool Player::BuildEnumData(PreparedQueryResult result, ByteBuffer* dataBuffer, ByteBuffer* bitBuffer)
{
// 0 1 2 3 4 5 6 7
// "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, "
// 8 9 10 11 12 13 14
// "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, "
- // 15 16 17 18 19 20 21
- // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_banned.guid, character_declinedname.genitive "
+ // 15 16 17 18 19 20 21 22
+ // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_banned.guid, characters.slot, character_declinedname.genitive"
Field* fields = result->Fetch();
- uint32 guid = fields[0].GetUInt32();
+ ObjectGuid guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
+ std::string name = fields[1].GetString();
uint8 plrRace = fields[2].GetUInt8();
uint8 plrClass = fields[3].GetUInt8();
uint8 gender = fields[4].GetUInt8();
-
- PlayerInfo const* info = sObjectMgr->GetPlayerInfo(plrRace, plrClass);
- if (!info)
- {
- TC_LOG_ERROR("entities.player.loading", "Player %u has incorrect race/class pair. Don't build enum.", guid);
- return false;
- }
- else if (!IsValidGender(gender))
- {
- TC_LOG_ERROR("entities.player.loading", "Player (%u) has incorrect gender (%u), don't build enum.", guid, gender);
- return false;
- }
-
- *data << uint64(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));
- *data << fields[1].GetString(); // name
- *data << uint8(plrRace); // race
- *data << uint8(plrClass); // class
- *data << uint8(gender); // gender
-
- uint32 playerBytes = fields[5].GetUInt32();
- *data << uint8(playerBytes); // skin
- *data << uint8(playerBytes >> 8); // face
- *data << uint8(playerBytes >> 16); // hair style
- *data << uint8(playerBytes >> 24); // hair color
-
- uint32 playerBytes2 = fields[6].GetUInt32();
- *data << uint8(playerBytes2 & 0xFF); // facial hair
-
- *data << uint8(fields[7].GetUInt8()); // level
- *data << uint32(fields[8].GetUInt16()); // zone
- *data << uint32(fields[9].GetUInt16()); // map
-
- *data << fields[10].GetFloat(); // x
- *data << fields[11].GetFloat(); // y
- *data << fields[12].GetFloat(); // z
-
- *data << uint32(fields[13].GetUInt32()); // guild id
+ uint8 skin = uint8(fields[5].GetUInt32() & 0xFF);
+ uint8 face = uint8((fields[5].GetUInt32() >> 8) & 0xFF);
+ uint8 hairStyle = uint8((fields[5].GetUInt32() >> 16) & 0xFF);
+ uint8 hairColor = uint8((fields[5].GetUInt32() >> 24) & 0xFF);
+ uint8 facialHair = uint8(fields[6].GetUInt32() & 0xFF);
+ uint8 level = fields[7].GetUInt8();
+ uint32 zone = fields[8].GetUInt16();
+ uint32 mapId = uint32(fields[9].GetUInt16());
+ float x = fields[10].GetFloat();
+ float y = fields[11].GetFloat();
+ float z = fields[12].GetFloat();
+ uint32 guildId = fields[13].GetUInt32();
+ ObjectGuid guildGuid = MAKE_NEW_GUID(guildId, 0, guildId ? uint32(HIGHGUID_GUILD) : 0);
+ uint32 playerFlags = fields[14].GetUInt32();
+ uint32 atLoginFlags = fields[15].GetUInt16();
+ Tokenizer equipment(fields[19].GetString(), ' ');
+ uint8 slot = fields[21].GetUInt8();
uint32 charFlags = 0;
- uint32 playerFlags = fields[14].GetUInt32();
- uint16 atLoginFlags = fields[15].GetUInt16();
if (playerFlags & PLAYER_FLAGS_HIDE_HELM)
charFlags |= CHARACTER_FLAG_HIDE_HELM;
+
if (playerFlags & PLAYER_FLAGS_HIDE_CLOAK)
charFlags |= CHARACTER_FLAG_HIDE_CLOAK;
+
if (playerFlags & PLAYER_FLAGS_GHOST)
charFlags |= CHARACTER_FLAG_GHOST;
+
if (atLoginFlags & AT_LOGIN_RENAME)
charFlags |= CHARACTER_FLAG_RENAME;
+
if (fields[20].GetUInt32())
charFlags |= CHARACTER_FLAG_LOCKED_BY_BILLING;
- if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED))
- {
- if (!fields[21].GetString().empty())
- charFlags |= CHARACTER_FLAG_DECLINED;
- }
- else
- charFlags |= CHARACTER_FLAG_DECLINED;
- *data << uint32(charFlags); // character flags
+ if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[22].GetString().empty())
+ charFlags |= CHARACTER_FLAG_DECLINED;
- // character customize flags
+ uint32 customizationFlag = 0;
if (atLoginFlags & AT_LOGIN_CUSTOMIZE)
- *data << uint32(CHAR_CUSTOMIZE_FLAG_CUSTOMIZE);
+ customizationFlag = CHAR_CUSTOMIZE_FLAG_CUSTOMIZE;
else if (atLoginFlags & AT_LOGIN_CHANGE_FACTION)
- *data << uint32(CHAR_CUSTOMIZE_FLAG_FACTION);
+ customizationFlag = CHAR_CUSTOMIZE_FLAG_FACTION;
else if (atLoginFlags & AT_LOGIN_CHANGE_RACE)
- *data << uint32(CHAR_CUSTOMIZE_FLAG_RACE);
- else
- *data << uint32(CHAR_CUSTOMIZE_FLAG_NONE);
-
- // First login
- *data << uint8(atLoginFlags & AT_LOGIN_FIRST ? 1 : 0);
+ customizationFlag = CHAR_CUSTOMIZE_FLAG_RACE;
- // Pets info
uint32 petDisplayId = 0;
- uint32 petLevel = 0;
- uint32 petFamily = 0;
-
+ uint32 petLevel = 0;
+ uint32 petFamily = 0;
// show pet at selection character in character list only for non-ghost character
if (result && !(playerFlags & PLAYER_FLAGS_GHOST) && (plrClass == CLASS_WARLOCK || plrClass == CLASS_HUNTER || plrClass == CLASS_DEATH_KNIGHT))
{
@@ -2017,32 +1993,48 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
if (creatureInfo)
{
petDisplayId = fields[17].GetUInt32();
- petLevel = fields[18].GetUInt16();
- petFamily = creatureInfo->family;
- }
- }
-
- *data << uint32(petDisplayId);
- *data << uint32(petLevel);
- *data << uint32(petFamily);
-
- Tokenizer equipment(fields[19].GetString(), ' ');
+ petLevel = fields[18].GetUInt16();
+ petFamily = creatureInfo->family;
+ }
+ }
+
+ // Packet content flags
+ bitBuffer->WriteBit(guid[3]);
+ bitBuffer->WriteBit(guildGuid[1]);
+ bitBuffer->WriteBit(guildGuid[7]);
+ bitBuffer->WriteBit(guildGuid[2]);
+ bitBuffer->WriteBits(uint32(name.length()), 7);
+ bitBuffer->WriteBit(guid[4]);
+ bitBuffer->WriteBit(guid[7]);
+ bitBuffer->WriteBit(guildGuid[3]);
+ bitBuffer->WriteBit(guid[5]);
+ bitBuffer->WriteBit(guildGuid[6]);
+ bitBuffer->WriteBit(guid[1]);
+ bitBuffer->WriteBit(guildGuid[5]);
+ bitBuffer->WriteBit(guildGuid[4]);
+ bitBuffer->WriteBit(atLoginFlags & AT_LOGIN_FIRST);
+ bitBuffer->WriteBit(guid[0]);
+ bitBuffer->WriteBit(guid[2]);
+ bitBuffer->WriteBit(guid[6]);
+ bitBuffer->WriteBit(guildGuid[0]);
+
+ // Character data
+ *dataBuffer << uint8(plrClass); // Class
for (uint8 slot = 0; slot < INVENTORY_SLOT_BAG_END; ++slot)
{
- uint32 visualBase = slot * 2;
- uint32 itemId = GetUInt32ValueFromArray(equipment, visualBase);
+ uint32 visualbase = slot * 2;
+ uint32 itemId = GetUInt32ValueFromArray(equipment, visualbase);
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (!proto)
{
- *data << uint32(0);
- *data << uint8(0);
- *data << uint32(0);
+ *dataBuffer << uint8(0);
+ *dataBuffer << uint32(0);
+ *dataBuffer << uint32(0);
continue;
}
SpellItemEnchantmentEntry const* enchant = NULL;
-
- uint32 enchants = GetUInt32ValueFromArray(equipment, visualBase + 1);
+ uint32 enchants = GetUInt32ValueFromArray(equipment, visualbase + 1);
for (uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot)
{
// values stored in 2 uint16
@@ -2055,11 +2047,47 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
break;
}
- *data << uint32(proto->DisplayInfoID);
- *data << uint8(proto->InventoryType);
- *data << uint32(enchant ? enchant->aura_id : 0);
- }
-
+ *dataBuffer << uint8(proto->InventoryType);
+ *dataBuffer << uint32(proto->DisplayInfoID);
+ *dataBuffer << uint32(enchant ? enchant->aura_id : 0);
+ }
+
+ *dataBuffer << uint32(petFamily); // Pet family
+ dataBuffer->WriteByteSeq(guildGuid[2]);
+ *dataBuffer << uint8(slot); // List order
+ *dataBuffer << uint8(hairStyle); // Hair style
+ dataBuffer->WriteByteSeq(guildGuid[3]);
+ *dataBuffer << uint32(petDisplayId); // Pet DisplayID
+ *dataBuffer << uint32(charFlags); // Character flags
+ *dataBuffer << uint8(hairColor); // Hair color
+ dataBuffer->WriteByteSeq(guid[4]);
+ *dataBuffer << uint32(mapId); // Map Id
+ dataBuffer->WriteByteSeq(guildGuid[5]);
+ *dataBuffer << float(z); // Z
+ dataBuffer->WriteByteSeq(guildGuid[6]);
+ *dataBuffer << uint32(petLevel); // Pet level
+ dataBuffer->WriteByteSeq(guid[3]);
+ *dataBuffer << float(y); // Y
+ *dataBuffer << uint32(customizationFlag); // Character customization flags
+ *dataBuffer << uint8(facialHair); // Facial hair
+ dataBuffer->WriteByteSeq(guid[7]);
+ *dataBuffer << uint8(gender); // Gender
+ dataBuffer->append(name.c_str(), name.length()); // Name
+ *dataBuffer << uint8(face); // Face
+ dataBuffer->WriteByteSeq(guid[0]);
+ dataBuffer->WriteByteSeq(guid[2]);
+ dataBuffer->WriteByteSeq(guildGuid[1]);
+ dataBuffer->WriteByteSeq(guildGuid[7]);
+ *dataBuffer << float(x); // X
+ *dataBuffer << uint8(skin); // Skin
+ *dataBuffer << uint8(plrRace); // Race
+ *dataBuffer << uint8(level); // Level
+ dataBuffer->WriteByteSeq(guid[6]);
+ dataBuffer->WriteByteSeq(guildGuid[4]);
+ dataBuffer->WriteByteSeq(guildGuid[0]);
+ dataBuffer->WriteByteSeq(guid[5]);
+ dataBuffer->WriteByteSeq(guid[1]);
+ *dataBuffer << uint32(zone); // Zone id
return true;
}
@@ -2093,15 +2121,6 @@ uint8 Player::GetChatTag() const
return tag;
}
-void Player::SendTeleportAckPacket()
-{
- WorldPacket data(MSG_MOVE_TELEPORT_ACK, 41);
- data.append(GetPackGUID());
- data << uint32(0); // this value increments every time
- BuildMovementPacket(&data);
- GetSession()->SendPacket(&data);
-}
-
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options)
{
if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation))
@@ -2151,13 +2170,12 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// reset movement flags at teleport, because player will continue move with these flags after teleport
SetUnitMovementFlags(GetUnitMovementFlags() & MOVEMENTFLAG_MASK_HAS_PLAYER_STATUS_OPCODE);
+ m_movementInfo.ResetJump();
DisableSpline();
if (Transport* transport = GetTransport())
{
- if (options & TELE_TO_NOT_LEAVE_TRANSPORT)
- AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
- else
+ if (!(options & TELE_TO_NOT_LEAVE_TRANSPORT))
transport->RemovePassenger(this);
}
@@ -2199,16 +2217,15 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
SetFallInformation(0, z);
// code for finish transfer called in WorldSession::HandleMovementOpcodes()
- // at client packet MSG_MOVE_TELEPORT_ACK
+ // at client packet CMSG_MOVE_TELEPORT_ACK
SetSemaphoreTeleportNear(true);
- // near teleport, triggering send MSG_MOVE_TELEPORT_ACK from client at landing
+ // near teleport, triggering send CMSG_MOVE_TELEPORT_ACK from client at landing
if (!GetSession()->PlayerLogout())
{
Position oldPos = GetPosition();
if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
z += GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
Relocate(x, y, z, orientation);
- SendTeleportAckPacket();
SendTeleportPacket(oldPos); // this automatically relocates to oldPos in order to broadcast the packet in the right place
}
}
@@ -2292,10 +2309,16 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
{
// send transfer packets
WorldPacket data(SMSG_TRANSFER_PENDING, 4 + 4 + 4);
- data << uint32(mapid);
+ data.WriteBit(0); // unknown
if (Transport* transport = GetTransport())
- data << transport->GetEntry() << GetMapId();
+ {
+ data.WriteBit(1); // has transport
+ data << GetMapId() << transport->GetEntry();
+ }
+ else
+ data.WriteBit(0); // has transport
+ data << uint32(mapid);
GetSession()->SendPacket(&data);
}
@@ -2311,11 +2334,11 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (!GetSession()->PlayerLogout())
{
WorldPacket data(SMSG_NEW_WORLD, 4 + 4 + 4 + 4 + 4);
+ data << float(m_teleport_dest.GetPositionX());
+ data << float(m_teleport_dest.GetOrientation());
+ data << float(m_teleport_dest.GetPositionZ());
data << uint32(mapid);
- if (GetTransport())
- data << m_movementInfo.transport.pos.PositionXYZOStream();
- else
- data << m_teleport_dest.PositionXYZOStream();
+ data << float(m_teleport_dest.GetPositionY());
GetSession()->SendPacket(&data);
SendSavedInstances();
@@ -2356,18 +2379,22 @@ void Player::ProcessDelayedOperations()
{
ResurrectPlayer(0.0f, false);
- if (GetMaxHealth() > m_resurrectHealth)
- SetHealth(m_resurrectHealth);
+ if (GetMaxHealth() > _resurrectionData->Health)
+ SetHealth(_resurrectionData->Health);
else
SetFullHealth();
- if (GetMaxPower(POWER_MANA) > m_resurrectMana)
- SetPower(POWER_MANA, m_resurrectMana);
+ if (uint32(GetMaxPower(POWER_MANA)) > _resurrectionData->Mana)
+ SetPower(POWER_MANA, _resurrectionData->Mana);
else
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
SetPower(POWER_RAGE, 0);
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
+ SetPower(POWER_ECLIPSE, 0);
+
+ if (uint32 aura = _resurrectionData->Aura)
+ CastSpell(this, aura, true, NULL, NULL, _resurrectionData->GUID);
SpawnCorpseBones();
}
@@ -2466,15 +2493,40 @@ void Player::RegenerateAll()
m_regenTimerCount += m_regenTimer;
- Regenerate(POWER_ENERGY);
+ if (getClass() == CLASS_PALADIN)
+ m_holyPowerRegenTimerCount += m_regenTimer;
+
+ if (getClass() == CLASS_HUNTER)
+ m_focusRegenTimerCount += m_regenTimer;
+ Regenerate(POWER_ENERGY);
Regenerate(POWER_MANA);
// Runes act as cooldowns, and they don't need to send any data
if (getClass() == CLASS_DEATH_KNIGHT)
- for (uint8 i = 0; i < MAX_RUNES; ++i)
- if (uint32 cd = GetRuneCooldown(i))
- SetRuneCooldown(i, (cd > m_regenTimer) ? cd - m_regenTimer : 0);
+ {
+ for (uint8 i = 0; i < MAX_RUNES; i += 2)
+ {
+ uint8 runeToRegen = i;
+ uint32 cd = GetRuneCooldown(i);
+ uint32 secondRuneCd = GetRuneCooldown(i + 1);
+ // Regenerate second rune of the same type only after first rune is off the cooldown
+ if (secondRuneCd && (cd > secondRuneCd || !cd))
+ {
+ runeToRegen = i + 1;
+ cd = secondRuneCd;
+ }
+
+ if (cd)
+ SetRuneCooldown(runeToRegen, (cd > m_regenTimer) ? cd - m_regenTimer : 0);
+ }
+ }
+
+ if (m_focusRegenTimerCount >= 1000 && getClass() == CLASS_HUNTER)
+ {
+ Regenerate(POWER_FOCUS);
+ m_focusRegenTimerCount -= 1000;
+ }
if (m_regenTimerCount >= 2000)
{
@@ -2493,6 +2545,12 @@ void Player::RegenerateAll()
m_regenTimerCount -= 2000;
}
+ if (m_holyPowerRegenTimerCount >= 10000 && getClass() == CLASS_PALADIN)
+ {
+ Regenerate(POWER_HOLY_POWER);
+ m_holyPowerRegenTimerCount -= 10000;
+ }
+
m_regenTimer = 0;
}
@@ -2508,33 +2566,44 @@ void Player::Regenerate(Powers power)
if (HasAuraTypeWithValue(SPELL_AURA_PREVENT_REGENERATE_POWER, power))
return;
+ // Skip regeneration for power type we cannot have
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS)
+ return;
+
float addvalue = 0.0f;
+ // Powers now benefit from haste.
+ float rangedHaste = GetFloatValue(PLAYER_FIELD_MOD_RANGED_HASTE);
+ float meleeHaste = GetFloatValue(PLAYER_FIELD_MOD_HASTE);
+ float spellHaste = GetFloatValue(UNIT_MOD_CAST_SPEED);
+
switch (power)
{
case POWER_MANA:
{
- bool recentCast = IsUnderLastManaUseEffect();
float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA);
- if (getLevel() < 15)
- ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA) * (2.066f - (getLevel() * 0.066f));
-
- if (recentCast) // Trinity Updates Mana in intervals of 2s, which is correct
- addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * 0.001f * m_regenTimer;
+ if (IsInCombat()) // Trinity Updates Mana in intervals of 2s, which is correct
+ addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * ((0.001f * m_regenTimer) + CalculatePct(0.001f, spellHaste));
else
- addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) * ManaIncreaseRate * 0.001f * m_regenTimer;
- } break;
- case POWER_RAGE: // Regenerate rage
+ addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) * ManaIncreaseRate * ((0.001f * m_regenTimer) + CalculatePct(0.001f, spellHaste));
+ }
+ break;
+ case POWER_RAGE: // Regenerate rage
{
if (!IsInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN))
{
float RageDecreaseRate = sWorld->getRate(RATE_POWER_RAGE_LOSS);
- addvalue += -20 * RageDecreaseRate; // 2 rage by tick (= 2 seconds => 1 rage/sec)
+ addvalue += -25 * RageDecreaseRate / meleeHaste; // 2.5 rage by tick (= 2 seconds => 1.25 rage/sec)
}
- } break;
- case POWER_ENERGY: // Regenerate energy (rogue)
- addvalue += 0.01f * m_regenTimer * sWorld->getRate(RATE_POWER_ENERGY);
+ }
+ break;
+ case POWER_FOCUS:
+ addvalue += (6.0f + CalculatePct(6.0f, rangedHaste)) * sWorld->getRate(RATE_POWER_FOCUS);
+ break;
+ case POWER_ENERGY: // Regenerate energy (rogue)
+ addvalue += ((0.01f * m_regenTimer) + CalculatePct(0.01f, meleeHaste)) * sWorld->getRate(RATE_POWER_ENERGY);
break;
case POWER_RUNIC_POWER:
{
@@ -2543,10 +2612,15 @@ void Player::Regenerate(Powers power)
float RunicPowerDecreaseRate = sWorld->getRate(RATE_POWER_RUNICPOWER_LOSS);
addvalue += -30 * RunicPowerDecreaseRate; // 3 RunicPower by tick
}
- } break;
- case POWER_RUNE:
- case POWER_FOCUS:
- case POWER_HAPPINESS:
+ }
+ break;
+ case POWER_HOLY_POWER: // Regenerate holy power
+ {
+ if (!IsInCombat())
+ addvalue += -1.0f; // remove 1 each 10 sec
+ }
+ break;
+ case POWER_RUNES:
break;
case POWER_HEALTH:
return;
@@ -2580,7 +2654,7 @@ void Player::Regenerate(Powers power)
else
return;
- addvalue += m_powerFraction[power];
+ addvalue += m_powerFraction[powerIndex];
uint32 integerValue = uint32(fabs(addvalue));
if (addvalue < 0.0f)
@@ -2588,12 +2662,12 @@ void Player::Regenerate(Powers power)
if (curValue > integerValue)
{
curValue -= integerValue;
- m_powerFraction[power] = addvalue + integerValue;
+ m_powerFraction[powerIndex] = addvalue + integerValue;
}
else
{
curValue = 0;
- m_powerFraction[power] = 0;
+ m_powerFraction[powerIndex] = 0;
}
}
else
@@ -2603,15 +2677,16 @@ void Player::Regenerate(Powers power)
if (curValue > maxValue)
{
curValue = maxValue;
- m_powerFraction[power] = 0;
+ m_powerFraction[powerIndex] = 0;
}
else
- m_powerFraction[power] = addvalue - integerValue;
+ m_powerFraction[powerIndex] = addvalue - integerValue;
}
+
if (m_regenTimerCount >= 2000)
SetPower(power, curValue);
else
- UpdateUInt32Value(UNIT_FIELD_POWER1 + power, curValue);
+ UpdateUInt32Value(UNIT_FIELD_POWER1 + powerIndex, curValue);
}
void Player::RegenerateHealth()
@@ -2623,10 +2698,6 @@ void Player::RegenerateHealth()
return;
float HealthIncreaseRate = sWorld->getRate(RATE_HEALTH);
-
- if (getLevel() < 15)
- HealthIncreaseRate = sWorld->getRate(RATE_HEALTH) * (2.066f - (getLevel() * 0.066f));
-
float addValue = 0.0f;
// polymorphed case
@@ -2635,9 +2706,15 @@ void Player::RegenerateHealth()
// normal regen case (maybe partly in combat case)
else if (!IsInCombat() || HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT))
{
- addValue = OCTRegenHPPerSpirit() * HealthIncreaseRate;
+ addValue = HealthIncreaseRate;
+
if (!IsInCombat())
{
+ if (getLevel() < 15)
+ addValue = (0.20f * ((float)GetMaxHealth()) / getLevel() * HealthIncreaseRate);
+ else
+ addValue = 0.015f * ((float)GetMaxHealth()) * HealthIncreaseRate;
+
AuraEffectList const& mModHealthRegenPct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT);
for (AuraEffectList::const_iterator i = mModHealthRegenPct.begin(); i != mModHealthRegenPct.end(); ++i)
AddPct(addValue, (*i)->GetAmount());
@@ -2678,6 +2755,9 @@ void Player::ResetAllPowers()
case POWER_RUNIC_POWER:
SetPower(POWER_RUNIC_POWER, 0);
break;
+ case POWER_ECLIPSE:
+ SetPower(POWER_ECLIPSE, 0);
+ break;
default:
break;
}
@@ -2814,23 +2894,10 @@ void Player::SetGameMaster(bool on)
getHostileRefManager().setOnlineOfflineState(false);
CombatStopWithPets();
- SetPhaseMask(uint32(PHASEMASK_ANYWHERE), false); // see and visible in all phases
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GM, GetSession()->GetSecurity());
}
else
{
- // restore phase
- uint32 newPhase = 0;
- AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE);
- if (!phases.empty())
- for (AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
- newPhase |= (*itr)->GetMiscValue();
-
- if (!newPhase)
- newPhase = PHASEMASK_NORMAL;
-
- SetPhaseMask(newPhase, false);
-
m_ExtraFlags &= ~ PLAYER_EXTRA_GM_ON;
setFactionForRace(getRace());
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM);
@@ -3020,23 +3087,21 @@ void Player::GiveLevel(uint8 level)
PlayerLevelInfo info;
sObjectMgr->GetPlayerLevelInfo(getRace(), getClass(), level, &info);
- PlayerClassLevelInfo classInfo;
- sObjectMgr->GetPlayerClassLevelInfo(getClass(), level, &classInfo);
+ uint32 basehp = 0, basemana = 0;
+ sObjectMgr->GetPlayerClassLevelInfo(getClass(), level, basehp, basemana);
// send levelup info to client
- WorldPacket data(SMSG_LEVELUP_INFO, (4+4+MAX_POWERS*4+MAX_STATS*4));
+ WorldPacket data(SMSG_LEVELUP_INFO, (4+4+MAX_POWERS_PER_CLASS*4+MAX_STATS*4));
data << uint32(level);
- data << uint32(int32(classInfo.basehealth) - int32(GetCreateHealth()));
- // for (int i = 0; i < MAX_POWERS; ++i) // Powers loop (0-6)
- data << uint32(int32(classInfo.basemana) - int32(GetCreateMana()));
- data << uint32(0);
- data << uint32(0);
+ data << uint32(int32(basehp) - int32(GetCreateHealth()));
+ // for (int i = 0; i < MAX_STORED_POWERS; ++i) // Powers loop (0-10)
+ data << uint32(int32(basemana) - int32(GetCreateMana()));
data << uint32(0);
data << uint32(0);
data << uint32(0);
data << uint32(0);
// end for
- for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) // Stats loop (0-4)
+ for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) // Stats loop (0-4)
data << uint32(int32(info.stats[i]) - GetCreateStat(Stats(i)));
GetSession()->SendPacket(&data);
@@ -3056,8 +3121,8 @@ void Player::GiveLevel(uint8 level)
for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
SetCreateStat(Stats(i), info.stats[i]);
- SetCreateHealth(classInfo.basehealth);
- SetCreateMana(classInfo.basemana);
+ SetCreateHealth(basehp);
+ SetCreateMana(basemana);
InitTalentForLevel();
InitTaxiNodesForLevel();
@@ -3068,6 +3133,8 @@ void Player::GiveLevel(uint8 level)
if (sWorld->getBoolConfig(CONFIG_ALWAYS_MAXSKILL)) // Max weapon skill when leveling up
UpdateSkillsToMaxSkillsForLevel();
+ _ApplyAllLevelScaleItemMods(true); // Moved to above SetFullHealth so player will have full health from Heirlooms
+
// set current level health and mana/energy to maximum after applying all mods.
SetFullHealth();
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
@@ -3075,9 +3142,6 @@ void Player::GiveLevel(uint8 level)
if (GetPower(POWER_RAGE) > GetMaxPower(POWER_RAGE))
SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE));
SetPower(POWER_FOCUS, 0);
- SetPower(POWER_HAPPINESS, 0);
-
- _ApplyAllLevelScaleItemMods(true);
// update level to hunter/summon pet
if (Pet* pet = GetPet())
@@ -3114,24 +3178,24 @@ void Player::InitTalentForLevel()
if (level < 10)
{
// Remove all talent points
- if (m_usedTalentCount > 0) // Free any used talents
+ if (GetUsedTalentCount() > 0) // Free any used talents
{
- ResetTalents(true); /// @todo: Has to (collectively) be renamed to ResetTalents
+ ResetTalents(true);
SetFreeTalentPoints(0);
}
}
else
{
- if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || m_specsCount == 0)
+ if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || GetSpecsCount() == 0)
{
- m_specsCount = 1;
- m_activeSpec = 0;
+ SetSpecsCount(1);
+ SetActiveSpec(0);
}
uint32 talentPointsForLevel = CalculateTalentsPoints();
// if used more that have then reset
- if (m_usedTalentCount > talentPointsForLevel)
+ if (GetUsedTalentCount() > talentPointsForLevel)
{
if (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED))
ResetTalents(true);
@@ -3140,7 +3204,7 @@ void Player::InitTalentForLevel()
}
// else update amount of free points
else
- SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount);
+ SetFreeTalentPoints(talentPointsForLevel - GetUsedTalentCount());
}
if (!GetSession()->PlayerLoading())
@@ -3152,8 +3216,8 @@ void Player::InitStatsForLevel(bool reapplyMods)
if (reapplyMods) //reapply stats values only on .reset stats (level) command
_RemoveAllStatBonuses();
- PlayerClassLevelInfo classInfo;
- sObjectMgr->GetPlayerClassLevelInfo(getClass(), getLevel(), &classInfo);
+ uint32 basehp = 0, basemana = 0;
+ sObjectMgr->GetPlayerClassLevelInfo(getClass(), getLevel(), basehp, basemana);
PlayerLevelInfo info;
sObjectMgr->GetPlayerLevelInfo(getRace(), getClass(), getLevel(), &info);
@@ -3168,6 +3232,9 @@ void Player::InitStatsForLevel(bool reapplyMods)
// set default cast time multiplier
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
+ SetFloatValue(UNIT_MOD_CAST_HASTE, 1.0f);
+ SetFloatValue(PLAYER_FIELD_MOD_HASTE, 1.0f);
+ SetFloatValue(PLAYER_FIELD_MOD_RANGED_HASTE, 1.0f);
// reset size before reapply auras
SetObjectScale(1.0f);
@@ -3179,10 +3246,10 @@ void Player::InitStatsForLevel(bool reapplyMods)
for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
SetStat(Stats(i), info.stats[i]);
- SetCreateHealth(classInfo.basehealth);
+ SetCreateHealth(basehp);
//set create powers
- SetCreateMana(classInfo.basemana);
+ SetCreateMana(basemana);
SetArmor(int32(m_createStats[STAT_AGILITY]*2));
@@ -3193,13 +3260,17 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetUInt32Value(index, 0);
SetUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, 0);
+ SetFloatValue(PLAYER_FIELD_MOD_HEALING_PCT, 1.0f);
+ SetFloatValue(PLAYER_FIELD_MOD_HEALING_DONE_PCT, 1.0f);
for (uint8 i = 0; i < 7; ++i)
{
SetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i, 0);
SetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, 0);
- SetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i, 1.00f);
+ SetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i, 1.0f);
}
+ SetFloatValue(PLAYER_FIELD_MOD_SPELL_POWER_PCT, 1.0f);
+
//reset attack power, damage and attack speed fields
SetFloatValue(UNIT_FIELD_BASEATTACKTIME, 2000.0f);
SetFloatValue(UNIT_FIELD_BASEATTACKTIME + 1, 2000.0f); // offhand attack time
@@ -3211,12 +3282,11 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, 0.0f);
SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, 0.0f);
SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, 0.0f);
+ SetFloatValue(PLAYER_FIELD_WEAPON_DMG_MULTIPLIERS, 1.0f);
SetInt32Value(UNIT_FIELD_ATTACK_POWER, 0);
- SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, 0);
SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, 0.0f);
SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER, 0);
- SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS, 0);
SetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER, 0.0f);
// Base crit values (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset
@@ -3230,7 +3300,9 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetFloatValue(PLAYER_PARRY_PERCENTAGE, 0.0f);
SetFloatValue(PLAYER_BLOCK_PERCENTAGE, 0.0f);
- SetUInt32Value(PLAYER_SHIELD_BLOCK, 0);
+
+ // Static 30% damage blocked
+ SetUInt32Value(PLAYER_SHIELD_BLOCK, 30);
// Dodge percentage
SetFloatValue(PLAYER_DODGE_PERCENTAGE, 0.0f);
@@ -3262,9 +3334,9 @@ void Player::InitStatsForLevel(bool reapplyMods)
// save new stats
for (uint8 i = POWER_MANA; i < MAX_POWERS; ++i)
- SetMaxPower(Powers(i), uint32(GetCreatePowers(Powers(i))));
+ SetMaxPower(Powers(i), GetCreatePowers(Powers(i)));
- SetMaxHealth(classInfo.basehealth); // stamina bonus will applied later
+ SetMaxHealth(basehp); // stamina bonus will applied later
// cleanup mounted state (it will set correctly at aura loading if player saved at mount.
SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
@@ -3299,8 +3371,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
if (GetPower(POWER_RAGE) > GetMaxPower(POWER_RAGE))
SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE));
- SetPower(POWER_FOCUS, 0);
- SetPower(POWER_HAPPINESS, 0);
+ SetPower(POWER_FOCUS, GetMaxPower(POWER_FOCUS));
SetPower(POWER_RUNIC_POWER, 0);
// update level to hunter/summon pet
@@ -3332,7 +3403,7 @@ void Player::SendInitialSpells()
data << uint32(itr->first);
data << uint16(0); // it's not slot id
- spellCount +=1;
+ ++spellCount;
}
data.put<uint16>(countPos, spellCount); // write real count value
@@ -3347,7 +3418,7 @@ void Player::SendInitialSpells()
data << uint32(itr->first);
- data << uint16(itr->second.itemid); // cast item id
+ data << uint32(itr->second.itemid); // cast item id
data << uint16(sEntry->GetCategory()); // spell category
// send infinity cooldown in special format
@@ -3393,15 +3464,15 @@ void Player::RemoveMail(uint32 id)
void Player::SendMailResult(uint32 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError, uint32 item_guid, uint32 item_count)
{
WorldPacket data(SMSG_SEND_MAIL_RESULT, (4+4+4+(mailError == MAIL_ERR_EQUIP_ERROR?4:(mailAction == MAIL_ITEM_TAKEN?4+4:0))));
- data << (uint32) mailId;
- data << (uint32) mailAction;
- data << (uint32) mailError;
+ data << uint32(mailId);
+ data << uint32(mailAction);
+ data << uint32(mailError);
if (mailError == MAIL_ERR_EQUIP_ERROR)
- data << (uint32) equipError;
+ data << uint32(equipError);
else if (mailAction == MAIL_ITEM_TAKEN)
{
- data << (uint32) item_guid; // item guid low?
- data << (uint32) item_count; // item count?
+ data << uint32(item_guid); // item guid low?
+ data << uint32(item_count); // item count?
}
GetSession()->SendPacket(&data);
}
@@ -3493,8 +3564,8 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
return false;
}
- PlayerTalentMap::iterator itr = m_talents[spec]->find(spellId);
- if (itr != m_talents[spec]->end())
+ PlayerTalentMap::iterator itr = GetTalentMap(spec)->find(spellId);
+ if (itr != GetTalentMap(spec)->end())
itr->second->state = PLAYERSPELL_UNCHANGED;
else if (TalentSpellPos const* talentPos = GetTalentSpellPos(spellId))
{
@@ -3507,8 +3578,8 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
if (!rankSpellId || rankSpellId == spellId)
continue;
- itr = m_talents[spec]->find(rankSpellId);
- if (itr != m_talents[spec]->end())
+ itr = GetTalentMap(spec)->find(rankSpellId);
+ if (itr != GetTalentMap(spec)->end())
itr->second->state = PLAYERSPELL_REMOVED;
}
}
@@ -3519,7 +3590,7 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
newtalent->state = state;
newtalent->spec = spec;
- (*m_talents[spec])[spellId] = newtalent;
+ (*GetTalentMap(spec))[spellId] = newtalent;
return true;
}
return false;
@@ -3772,7 +3843,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
}
// update used talent points count
- m_usedTalentCount += talentCost;
+ SetUsedTalentCount(GetUsedTalentCount() + talentCost);
// update free primary prof.points (if any, can be none in case GM .learn prof. learning)
if (uint32 freeProfs = GetFreePrimaryProfessionPoints())
@@ -3812,12 +3883,6 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
if (_spell_idx->second->AutolearnType == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->id))
LearnDefaultSkill(pSkill->id, 0);
-
- if (pSkill->id == SKILL_MOUNTS && !Has310Flyer(false))
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
- spellInfo->Effects[i].CalcValue() == 310)
- SetHas310Flyer(true);
}
}
}
@@ -3887,10 +3952,21 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const
bool need_cast = (!spellInfo->Stances || (form && (spellInfo->Stances & (1 << (form - 1)))) ||
(!form && (spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_NEED_SHAPESHIFT)));
+ if (spellInfo->AttributesEx8 & SPELL_ATTR8_MASTERY_SPECIALIZATION)
+ need_cast &= IsCurrentSpecMasterySpell(spellInfo);
+
//Check CasterAuraStates
return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraStateType(spellInfo->CasterAuraState)));
}
+bool Player::IsCurrentSpecMasterySpell(SpellInfo const* spellInfo) const
+{
+ if (TalentTabEntry const* talentTab = sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec())))
+ return spellInfo->Id == talentTab->MasterySpellId[0] || spellInfo->Id == talentTab->MasterySpellId[1];
+
+ return false;
+}
+
void Player::LearnSpell(uint32 spell_id, bool dependent, bool fromSkill /*= false*/)
{
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
@@ -3903,9 +3979,9 @@ void Player::LearnSpell(uint32 spell_id, bool dependent, bool fromSkill /*= fals
// prevent duplicated entires in spell book, also not send if not in world (loading)
if (learning && IsInWorld())
{
- WorldPacket data(SMSG_LEARNED_SPELL, 6);
+ WorldPacket data(SMSG_LEARNED_SPELL, 8);
data << uint32(spell_id);
- data << uint16(0);
+ data << uint32(0);
GetSession()->SendPacket(&data);
}
@@ -3987,10 +4063,10 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
uint32 talentCosts = GetTalentSpellCost(spell_id);
if (talentCosts > 0 && giveTalentPoints)
{
- if (talentCosts < m_usedTalentCount)
- m_usedTalentCount -= talentCosts;
+ if (talentCosts < GetUsedTalentCount())
+ SetUsedTalentCount(GetUsedTalentCount() - talentCosts);
else
- m_usedTalentCount = 0;
+ SetUsedTalentCount(0);
}
// update free primary prof.points (if not overflow setting, can be in case GM use before .learn prof. learning)
@@ -4038,35 +4114,6 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
}
}
}
- else
- {
- // not ranked skills
- SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spell_id);
-
- // most likely will never be used, haven't heard of cases where players unlearn a mount
- if (Has310Flyer(false) && spellInfo)
- {
- for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
- {
- SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId);
- if (!pSkill)
- continue;
-
- if (_spell_idx->second->skillId == SKILL_MOUNTS)
- {
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
- spellInfo->Effects[i].CalcValue() == 310)
- {
- Has310Flyer(true, spell_id); // with true as first argument its also used to set/remove the flag
- break;
- }
- }
- }
- }
- }
- }
// remove dependent spells
SpellLearnSpellMapBounds spell_bounds = sSpellMgr->GetSpellLearnSpellMapBounds(spell_id);
@@ -4117,8 +4164,19 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
if (spell_id == 46917 && m_canTitanGrip)
SetCanTitanGrip(false);
- if (spell_id == 674 && m_canDualWield)
- SetCanDualWield(false);
+ if (m_canDualWield)
+ {
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
+ if (spellInfo->IsPassive())
+ {
+ for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
+ if (spellInfo->Effects[i].Effect == SPELL_EFFECT_DUAL_WIELD)
+ {
+ SetCanDualWield(false);
+ break;
+ }
+ }
+ }
if (sWorld->getBoolConfig(CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN))
AutoUnequipOffhandIfNeed();
@@ -4132,40 +4190,6 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
}
}
-bool Player::Has310Flyer(bool checkAllSpells, uint32 excludeSpellId)
-{
- if (!checkAllSpells)
- return (m_ExtraFlags & PLAYER_EXTRA_HAS_310_FLYER) != 0;
- else
- {
- SetHas310Flyer(false);
- SpellInfo const* spellInfo;
- for (PlayerSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
- {
- if (itr->first == excludeSpellId)
- continue;
-
- SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(itr->first);
- for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
- {
- if (_spell_idx->second->skillId != SKILL_MOUNTS)
- break; // We can break because mount spells belong only to one skillline (at least 310 flyers do)
-
- spellInfo = sSpellMgr->EnsureSpellInfo(itr->first);
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
- spellInfo->Effects[i].CalcValue() == 310)
- {
- SetHas310Flyer(true);
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
void Player::RemoveSpellCooldown(uint32 spell_id, bool update /* = false */)
{
m_spellCooldowns.erase(spell_id);
@@ -4236,9 +4260,7 @@ void Player::RemoveAllSpellCooldown()
{
if (!m_spellCooldowns.empty())
{
- for (SpellCooldowns::const_iterator itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr)
- SendClearCooldown(itr->first, this);
-
+ SendClearAllCooldowns(this);
m_spellCooldowns.clear();
}
}
@@ -4316,31 +4338,31 @@ void Player::_SaveSpellCooldowns(SQLTransaction& trans)
trans->Append(ss.str().c_str());
}
-uint32 Player::ResetTalentsCost() const
+uint32 Player::GetNextResetTalentsCost() const
{
// The first time reset costs 1 gold
- if (m_resetTalentsCost < 1*GOLD)
+ if (GetTalentResetCost() < 1*GOLD)
return 1*GOLD;
// then 5 gold
- else if (m_resetTalentsCost < 5*GOLD)
+ else if (GetTalentResetCost() < 5*GOLD)
return 5*GOLD;
// After that it increases in increments of 5 gold
- else if (m_resetTalentsCost < 10*GOLD)
+ else if (GetTalentResetCost() < 10*GOLD)
return 10*GOLD;
else
{
- uint64 months = (sWorld->GetGameTime() - m_resetTalentsTime)/MONTH;
+ uint64 months = (sWorld->GetGameTime() - GetTalentResetTime())/MONTH;
if (months > 0)
{
// This cost will be reduced by a rate of 5 gold per month
- int32 new_cost = int32(m_resetTalentsCost - 5*GOLD*months);
+ int32 new_cost = int32(GetTalentResetCost() - 5*GOLD*months);
// to a minimum of 10 gold.
return (new_cost < 10*GOLD ? 10*GOLD : new_cost);
}
else
{
// After that it increases in increments of 5 gold
- int32 new_cost = m_resetTalentsCost + 5*GOLD;
+ int32 new_cost = GetTalentResetCost() + 5*GOLD;
// until it hits a cap of 50 gold.
if (new_cost > 50*GOLD)
new_cost = 50*GOLD;
@@ -4359,7 +4381,7 @@ bool Player::ResetTalents(bool no_cost)
uint32 talentPointsForLevel = CalculateTalentsPoints();
- if (m_usedTalentCount == 0)
+ if (!GetUsedTalentCount())
{
SetFreeTalentPoints(talentPointsForLevel);
return false;
@@ -4369,9 +4391,9 @@ bool Player::ResetTalents(bool no_cost)
if (!no_cost && !sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST))
{
- cost = ResetTalentsCost();
+ cost = GetNextResetTalentsCost();
- if (!HasEnoughMoney(cost))
+ if (!HasEnoughMoney(uint64(cost)))
{
SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
return false;
@@ -4412,27 +4434,43 @@ bool Player::ResetTalents(bool no_cost)
if (_spellEntry->Effects[i].TriggerSpell > 0 && _spellEntry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL)
RemoveSpell(_spellEntry->Effects[i].TriggerSpell, true);
// if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted
- PlayerTalentMap::iterator plrTalent = m_talents[m_activeSpec]->find(talentInfo->RankID[rank]);
- if (plrTalent != m_talents[m_activeSpec]->end())
+ PlayerTalentMap::iterator plrTalent = GetTalentMap(GetActiveSpec())->find(talentInfo->RankID[rank]);
+ if (plrTalent != GetTalentMap(GetActiveSpec())->end())
plrTalent->second->state = PLAYERSPELL_REMOVED;
}
}
+ // Remove spec specific spells
+ uint32 const* talentTabs = GetTalentTabPages(getClass());
+ for (uint32 i = 0; i < MAX_TALENT_TABS; ++i)
+ {
+ if (std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(talentTabs[i]))
+ for (size_t j = 0; j < specSpells->size(); ++j)
+ RemoveSpell(specSpells->at(j), true);
+
+ TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentTabs[i]);
+ for (uint32 j = 0; j < MAX_MASTERY_SPELLS; ++j)
+ if (uint32 mastery = talentTabInfo->MasterySpellId[j])
+ RemoveAurasDueToSpell(mastery);
+ }
+
+
+ SetPrimaryTalentTree(GetActiveSpec(), 0);
+ SetFreeTalentPoints(talentPointsForLevel);
+
SQLTransaction trans = CharacterDatabase.BeginTransaction();
_SaveTalents(trans);
_SaveSpells(trans);
CharacterDatabase.CommitTransaction(trans);
- SetFreeTalentPoints(talentPointsForLevel);
-
if (!no_cost)
{
- ModifyMoney(-(int32)cost);
+ ModifyMoney(-(int64)cost);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS, cost);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS, 1);
- m_resetTalentsCost = cost;
- m_resetTalentsTime = time(NULL);
+ SetTalentResetCost(cost);
+ SetTalentResetTime(time(NULL));
}
/* when prev line will dropped use next line
@@ -4446,12 +4484,6 @@ bool Player::ResetTalents(bool no_cost)
return true;
}
-void Player::SetFreeTalentPoints(uint32 points)
-{
- sScriptMgr->OnPlayerFreeTalentPointsChanged(this, points);
- SetUInt32Value(PLAYER_CHARACTER_POINTS1, points);
-}
-
Mail* Player::GetMail(uint32 id)
{
for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr)
@@ -4480,13 +4512,6 @@ void Player::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
m_items[i]->BuildCreateUpdateBlockForPlayer(data, target);
}
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- {
- if (m_items[i] == NULL)
- continue;
-
- m_items[i]->BuildCreateUpdateBlockForPlayer(data, target);
- }
}
Unit::BuildCreateUpdateBlockForPlayer(data, target);
@@ -4513,13 +4538,6 @@ void Player::DestroyForPlayer(Player* target, bool onDeath) const
m_items[i]->DestroyForPlayer(target);
}
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- {
- if (m_items[i] == NULL)
- continue;
-
- m_items[i]->DestroyForPlayer(target);
- }
}
}
@@ -4532,8 +4550,8 @@ bool Player::HasSpell(uint32 spell) const
bool Player::HasTalent(uint32 spell, uint8 spec) const
{
- PlayerTalentMap::const_iterator itr = m_talents[spec]->find(spell);
- return (itr != m_talents[spec]->end() && itr->second->state != PLAYERSPELL_REMOVED);
+ PlayerTalentMap::const_iterator itr = GetTalentMap(spec)->find(spell);
+ return (itr != GetTalentMap(spec)->end() && itr->second->state != PLAYERSPELL_REMOVED);
}
bool Player::HasActiveSpell(uint32 spell) const
@@ -4692,7 +4710,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
uint32 sender = mailFields[3].GetUInt32();
std::string subject = mailFields[4].GetString();
std::string body = mailFields[5].GetString();
- uint32 money = mailFields[6].GetUInt32();
+ uint64 money = mailFields[6].GetUInt64();
bool has_items = mailFields[7].GetBool();
// We can return mail now
@@ -5006,24 +5024,6 @@ void Player::DeleteOldCharacters(uint32 keepDays)
}
}
-void Player::SetMovement(PlayerMovementType pType)
-{
- WorldPacket data;
- switch (pType)
- {
- case MOVE_ROOT: data.Initialize(SMSG_FORCE_MOVE_ROOT, GetPackGUID().size()+4); break;
- case MOVE_UNROOT: data.Initialize(SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size()+4); break;
- case MOVE_WATER_WALK: data.Initialize(SMSG_MOVE_WATER_WALK, GetPackGUID().size()+4); break;
- case MOVE_LAND_WALK: data.Initialize(SMSG_MOVE_LAND_WALK, GetPackGUID().size()+4); break;
- default:
- TC_LOG_ERROR("entities.player", "Player::SetMovement: Unsupported move type (%d), data not sent to client.", pType);
- return;
- }
- data.append(GetPackGUID());
- data << uint32(0);
- GetSession()->SendPacket(&data);
-}
-
/* Preconditions:
- a resurrectable corpse must not be loaded for the player (only bones)
- the player must be in world
@@ -5062,9 +5062,9 @@ void Player::BuildPlayerRepop()
// convert player body to ghost
SetHealth(1);
- SetMovement(MOVE_WATER_WALK);
- if (!GetSession()->isLogingOut())
- SetMovement(MOVE_UNROOT);
+ SetWaterWalking(true);
+ if (!GetSession()->isLogingOut() && !HasUnitState(UNIT_STATE_STUNNED))
+ SetRooted(false);
// BG - remove insignia related
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
@@ -5106,8 +5106,9 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
setDeathState(ALIVE);
- SetMovement(MOVE_LAND_WALK);
- SetMovement(MOVE_UNROOT);
+ SetWaterWalking(false);
+ if (!HasUnitState(UNIT_STATE_STUNNED))
+ SetRooted(false);
m_deathTimer = 0;
@@ -5118,6 +5119,8 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
SetPower(POWER_MANA, uint32(GetMaxPower(POWER_MANA)*restore_percent));
SetPower(POWER_RAGE, 0);
SetPower(POWER_ENERGY, uint32(GetMaxPower(POWER_ENERGY)*restore_percent));
+ SetPower(POWER_FOCUS, uint32(GetMaxPower(POWER_FOCUS)*restore_percent));
+ SetPower(POWER_ECLIPSE, 0);
}
// trigger update zone for alive state zone updates
@@ -5167,7 +5170,7 @@ void Player::KillPlayer()
if (IsFlying() && !GetTransport())
GetMotionMaster()->MoveFall();
- SetMovement(MOVE_ROOT);
+ SetRooted(true);
StopMirrorTimers(); //disable timers(bars)
@@ -5233,12 +5236,10 @@ void Player::CreateCorpse()
flags |= CORPSE_FLAG_HIDE_CLOAK;
if (InBattleground() && !InArena())
flags |= CORPSE_FLAG_LOOTABLE; // to be able to remove insignia
- corpse->SetUInt32Value(CORPSE_FIELD_FLAGS, flags);
+ corpse->SetUInt32Value(CORPSE_FIELD_FLAGS, flags);
corpse->SetUInt32Value(CORPSE_FIELD_DISPLAY_ID, GetNativeDisplayId());
- corpse->SetUInt32Value(CORPSE_FIELD_GUILD, GetGuildId());
-
uint32 iDisplayID;
uint32 iIventoryType;
uint32 _cfi;
@@ -5289,9 +5290,6 @@ void Player::DurabilityLossAll(double percent, bool inventory)
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
DurabilityLoss(pItem, percent);
- // keys not have durability
- //for (int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
-
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
if (Bag* pBag = GetBagByPos(i))
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
@@ -5310,6 +5308,8 @@ void Player::DurabilityLoss(Item* item, double percent)
if (!pMaxDurability)
return;
+ percent /= GetTotalAuraMultiplier(SPELL_AURA_MOD_DURABILITY_LOSS);
+
uint32 pDurabilityLoss = uint32(pMaxDurability*percent);
if (pDurabilityLoss < 1)
@@ -5333,9 +5333,6 @@ void Player::DurabilityPointsLossAll(int32 points, bool inventory)
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
DurabilityPointsLoss(pItem, points);
- // keys not have durability
- //for (int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
-
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
if (Bag* pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0, i))
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
@@ -5454,13 +5451,13 @@ uint32 Player::DurabilityRepair(uint16 pos, bool cost, float discountMod, bool g
TotalCost = costs;
}
- else if (!HasEnoughMoney(costs))
+ else if (!HasEnoughMoney(uint64(costs)))
{
TC_LOG_DEBUG("entities.player.items", "You do not have enough money");
return TotalCost;
}
else
- ModifyMoney(-int32(costs));
+ ModifyMoney(-int64(costs));
}
}
@@ -5481,7 +5478,7 @@ void Player::RepopAtGraveyard()
AreaTableEntry const* zone = GetAreaEntryByAreaID(GetAreaId());
// Such zones are considered unreachable as a ghost and the player must be automatically revived
- if ((!IsAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) || GetTransport() || GetPositionZ() < -500.0f)
+ if ((!IsAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) || GetTransport() || GetPositionZ() < (zone ? zone->MaxDepth : -500.0f))
{
ResurrectPlayer(0.5f);
SpawnCorpseBones();
@@ -5507,7 +5504,8 @@ void Player::RepopAtGraveyard()
// and don't show spirit healer location
if (ClosestGrave)
{
- TeleportTo(ClosestGrave->map_id, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, GetOrientation());
+ float const* orientation = sObjectMgr->GetGraveyardOrientation(ClosestGrave->ID);
+ TeleportTo(ClosestGrave->map_id, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, orientation ? *orientation : GetOrientation());
if (isDead()) // not send if alive, because it used in TeleportTo()
{
WorldPacket data(SMSG_DEATH_RELEASE_LOC, 4*4); // show spirit healer position on minimap
@@ -5518,7 +5516,7 @@ void Player::RepopAtGraveyard()
GetSession()->SendPacket(&data);
}
}
- else if (GetPositionZ() < -500.0f)
+ else if (GetPositionZ() < zone->MaxDepth)
TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation());
}
@@ -5572,7 +5570,7 @@ void Player::UpdateLocalChannels(uint32 newZone)
if (!cMgr)
return;
- std::string current_zone_name = current_zone->area_name[GetSession()->GetSessionDbcLocale()];
+ std::string current_zone_name = current_zone->area_name;
for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
{
@@ -5608,7 +5606,7 @@ void Player::UpdateLocalChannels(uint32 newZone)
else
currentNameExt = current_zone_name.c_str();
- snprintf(new_channel_name_buf, 100, channel->pattern[m_session->GetSessionDbcLocale()], currentNameExt);
+ snprintf(new_channel_name_buf, 100, channel->pattern, currentNameExt);
joinChannel = cMgr->GetJoinChannel(new_channel_name_buf, channel->ChannelID);
if (usedChannel)
@@ -5623,7 +5621,7 @@ void Player::UpdateLocalChannels(uint32 newZone)
}
}
else
- joinChannel = cMgr->GetJoinChannel(channel->pattern[m_session->GetSessionDbcLocale()], channel->ChannelID);
+ joinChannel = cMgr->GetJoinChannel(channel->pattern, channel->ChannelID);
}
else
removeChannel = usedChannel;
@@ -5654,12 +5652,6 @@ void Player::LeaveLFGChannel()
}
}
-void Player::UpdateDefense()
-{
- if (UpdateSkill(SKILL_DEFENSE, sWorld->getIntConfig(CONFIG_SKILL_GAIN_DEFENSE)))
- UpdateDefenseBonusesMod(); // update dependent from defense skill part
-}
-
void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply)
{
if (modGroup >= BASEMOD_END || modType >= MOD_END)
@@ -5681,7 +5673,6 @@ void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, floa
case CRIT_PERCENTAGE: UpdateCritPercentage(BASE_ATTACK); break;
case RANGED_CRIT_PERCENTAGE: UpdateCritPercentage(RANGED_ATTACK); break;
case OFFHAND_CRIT_PERCENTAGE: UpdateCritPercentage(OFF_ATTACK); break;
- case SHIELD_BLOCK_VALUE: UpdateShieldBlockValue(); break;
default: break;
}
}
@@ -5714,15 +5705,6 @@ float Player::GetTotalBaseModValue(BaseModGroup modGroup) const
return m_auraBaseMod[modGroup][FLAT_MOD] * m_auraBaseMod[modGroup][PCT_MOD];
}
-uint32 Player::GetShieldBlockValue() const
-{
- float value = (m_auraBaseMod[SHIELD_BLOCK_VALUE][FLAT_MOD] + GetStat(STAT_STRENGTH) * 0.5f - 10)*m_auraBaseMod[SHIELD_BLOCK_VALUE][PCT_MOD];
-
- value = (value < 0) ? 0 : value;
-
- return uint32(value);
-}
-
float Player::GetMeleeCritFromAgility()
{
uint8 level = getLevel();
@@ -5745,17 +5727,17 @@ void Player::GetDodgeFromAgility(float &diminishing, float &nondiminishing)
// Table for base dodge values
const float dodge_base[MAX_CLASSES] =
{
- 0.036640f, // Warrior
- 0.034943f, // Paladin
- -0.040873f, // Hunter
- 0.020957f, // Rogue
- 0.034178f, // Priest
+ 0.037580f, // Warrior
+ 0.036520f, // Paladin
+ -0.054500f, // Hunter
+ -0.005900f, // Rogue
+ 0.031830f, // Priest
0.036640f, // DK
- 0.021080f, // Shaman
- 0.036587f, // Mage
- 0.024211f, // Warlock
+ 0.016750f, // Shaman
+ 0.034575f, // Mage
+ 0.020350f, // Warlock
0.0f, // ??
- 0.056097f // Druid
+ 0.049510f // Druid
};
// Crit/agility to dodge/agility coefficient multipliers; 3.2.0 increased required agility by 15%
const float crit_to_dodge[MAX_CLASSES] =
@@ -5801,13 +5783,13 @@ float Player::GetSpellCritFromIntellect()
if (level > GT_MAX_LEVEL)
level = GT_MAX_LEVEL;
- GtChanceToSpellCritBaseEntry const* critBase = sGtChanceToSpellCritBaseStore.LookupEntry(pclass-1);
- GtChanceToSpellCritEntry const* critRatio = sGtChanceToSpellCritStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1);
+ GtChanceToSpellCritBaseEntry const* critBase = sGtChanceToSpellCritBaseStore.LookupEntry(pclass - 1);
+ GtChanceToSpellCritEntry const* critRatio = sGtChanceToSpellCritStore.LookupEntry((pclass - 1) * GT_MAX_LEVEL + level - 1);
if (critBase == NULL || critRatio == NULL)
return 0.0f;
- float crit=critBase->base + GetStat(STAT_INTELLECT)*critRatio->ratio;
- return crit*100.0f;
+ float crit = critBase->base + GetStat(STAT_INTELLECT) * critRatio->ratio;
+ return crit * 100.0f;
}
float Player::GetRatingMultiplier(CombatRating cr) const
@@ -5828,7 +5810,10 @@ float Player::GetRatingMultiplier(CombatRating cr) const
float Player::GetRatingBonusValue(CombatRating cr) const
{
- return float(GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr)) * GetRatingMultiplier(cr);
+ float baseResult = float(GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr)) * GetRatingMultiplier(cr);
+ if (cr != CR_RESILIENCE_PLAYER_DAMAGE_TAKEN)
+ return baseResult;
+ return float(1.0f - pow(0.99f, baseResult)) * 100.0f;
}
float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const
@@ -5845,29 +5830,6 @@ float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const
return 0.0f;
}
-float Player::OCTRegenHPPerSpirit()
-{
- uint8 level = getLevel();
- uint32 pclass = getClass();
-
- if (level > GT_MAX_LEVEL)
- level = GT_MAX_LEVEL;
-
- GtOCTRegenHPEntry const* baseRatio = sGtOCTRegenHPStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1);
- GtRegenHPPerSptEntry const* moreRatio = sGtRegenHPPerSptStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1);
- if (baseRatio == NULL || moreRatio == NULL)
- return 0.0f;
-
- // Formula from PaperDollFrame script
- float spirit = GetStat(STAT_SPIRIT);
- float baseSpirit = spirit;
- if (baseSpirit > 50)
- baseSpirit = 50;
- float moreSpirit = spirit - baseSpirit;
- float regen = baseSpirit * baseRatio->ratio + moreSpirit * moreRatio->ratio;
- return regen;
-}
-
float Player::OCTRegenMPPerSpirit()
{
uint8 level = getLevel();
@@ -5889,33 +5851,31 @@ float Player::OCTRegenMPPerSpirit()
void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply)
{
- float oldRating = m_baseRatingValue[cr];
- m_baseRatingValue[cr]+=(apply ? value : -value);
+ m_baseRatingValue[cr] += (apply ? value : -value);
+
// explicit affected values
- if (cr == CR_HASTE_MELEE || cr == CR_HASTE_RANGED || cr == CR_HASTE_SPELL)
- {
- float const mult = GetRatingMultiplier(cr);
- float const oldVal = oldRating * mult;
- float const newVal = m_baseRatingValue[cr] * mult;
- switch (cr)
- {
- case CR_HASTE_MELEE:
- ApplyAttackTimePercentMod(BASE_ATTACK, oldVal, false);
- ApplyAttackTimePercentMod(OFF_ATTACK, oldVal, false);
- ApplyAttackTimePercentMod(BASE_ATTACK, newVal, true);
- ApplyAttackTimePercentMod(OFF_ATTACK, newVal, true);
- break;
- case CR_HASTE_RANGED:
- ApplyAttackTimePercentMod(RANGED_ATTACK, oldVal, false);
- ApplyAttackTimePercentMod(RANGED_ATTACK, newVal, true);
- break;
- case CR_HASTE_SPELL:
- ApplyCastTimePercentMod(oldVal, false);
- ApplyCastTimePercentMod(newVal, true);
- break;
- default: // shut up compiler warnings
- break;
- }
+ float const mult = GetRatingMultiplier(cr);
+ float const oldVal = m_baseRatingValue[cr] * mult;
+ float const newVal = m_baseRatingValue[cr] * mult;
+
+ switch (cr)
+ {
+ case CR_HASTE_MELEE:
+ ApplyAttackTimePercentMod(BASE_ATTACK, oldVal, false);
+ ApplyAttackTimePercentMod(OFF_ATTACK, oldVal, false);
+ ApplyAttackTimePercentMod(BASE_ATTACK, newVal, true);
+ ApplyAttackTimePercentMod(OFF_ATTACK, newVal, true);
+ break;
+ case CR_HASTE_RANGED:
+ ApplyAttackTimePercentMod(RANGED_ATTACK, oldVal, false);
+ ApplyAttackTimePercentMod(RANGED_ATTACK, newVal, true);
+ break;
+ case CR_HASTE_SPELL:
+ ApplyCastTimePercentMod(oldVal, false);
+ ApplyCastTimePercentMod(newVal, true);
+ break;
+ default: // shut up compiler warnings
+ break;
}
UpdateRating(cr);
@@ -5938,9 +5898,8 @@ void Player::UpdateRating(CombatRating cr)
switch (cr)
{
- case CR_WEAPON_SKILL: // Implemented in Unit::RollMeleeOutcomeAgainst
+ case CR_WEAPON_SKILL:
case CR_DEFENSE_SKILL:
- UpdateDefenseBonusesMod();
break;
case CR_DODGE:
UpdateDodgePercentage();
@@ -5975,15 +5934,12 @@ void Player::UpdateRating(CombatRating cr)
if (affectStats)
UpdateAllSpellCritChances();
break;
- case CR_HIT_TAKEN_MELEE: // Implemented in Unit::MeleeMissChanceCalc
- case CR_HIT_TAKEN_RANGED:
- break;
- case CR_HIT_TAKEN_SPELL: // Implemented in Unit::MagicSpellHitResult
- break;
- case CR_CRIT_TAKEN_MELEE: // Implemented in Unit::RollMeleeOutcomeAgainst (only for chance to crit)
- case CR_CRIT_TAKEN_RANGED:
- break;
- case CR_CRIT_TAKEN_SPELL: // Implemented in Unit::SpellCriticalBonus (only for chance to crit)
+ case CR_HIT_TAKEN_MELEE: // Deprecated since Cataclysm
+ case CR_HIT_TAKEN_RANGED: // Deprecated since Cataclysm
+ case CR_HIT_TAKEN_SPELL: // Deprecated since Cataclysm
+ case CR_RESILIENCE_PLAYER_DAMAGE_TAKEN:
+ case CR_RESILIENCE_CRIT_TAKEN:
+ case CR_CRIT_TAKEN_SPELL: // Deprecated since Cataclysm
break;
case CR_HASTE_MELEE: // Implemented in Player::ApplyRatingMod
case CR_HASTE_RANGED:
@@ -6004,6 +5960,9 @@ void Player::UpdateRating(CombatRating cr)
if (affectStats)
UpdateArmorPenetration(amount);
break;
+ case CR_MASTERY:
+ UpdateMastery();
+ break;
}
}
@@ -6039,12 +5998,13 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return false;
- uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
- uint32 data = GetUInt32Value(valueIndex);
- uint32 value = SKILL_VALUE(data);
- uint32 max = SKILL_MAX(data);
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
+
+ uint16 value = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
+ uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
- if ((!max) || (!value) || (value >= max))
+ if (!max || !value || value >= max)
return false;
if (value < max)
@@ -6053,7 +6013,7 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
if (new_value > max)
new_value = max;
- SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, max));
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value);
if (itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
@@ -6149,145 +6109,65 @@ 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};
-static const size_t bonusSkillLevelsSize = sizeof(bonusSkillLevels) / sizeof(uint32);
-
-bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
+bool Player::UpdateSkillPro(uint16 skillId, int32 chance, uint32 step)
{
- TC_LOG_DEBUG("entities.player.skills", "UpdateSkillPro(SkillId %d, Chance %3.1f%%)", SkillId, Chance / 10.0f);
- if (!SkillId)
+ // 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, 525 };
+ static const size_t bonusSkillLevelsSize = sizeof(bonusSkillLevels) / sizeof(uint32);
+
+ TC_LOG_DEBUG("entities.player.skills", "UpdateSkillPro(SkillId %d, Chance %3.1f%%)", skillId, chance / 10.0f);
+ if (!skillId)
return false;
- if (Chance <= 0) // speedup in 0 chance case
+ if (chance <= 0) // speedup in 0 chance case
{
- TC_LOG_DEBUG("entities.player.skills", "Player::UpdateSkillPro Chance=%3.1f%% missed", Chance / 10.0f);
+ TC_LOG_DEBUG("entities.player.skills", "Player::UpdateSkillPro Chance=%3.1f%% missed", chance / 10.0f);
return false;
}
- SkillStatusMap::iterator itr = mSkillStatus.find(SkillId);
+ SkillStatusMap::iterator itr = mSkillStatus.find(skillId);
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return false;
- uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
- uint32 data = GetUInt32Value(valueIndex);
- uint16 SkillValue = SKILL_VALUE(data);
- uint16 MaxValue = SKILL_MAX(data);
+ uint16 value = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
+ uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
- if (!MaxValue || !SkillValue || SkillValue >= MaxValue)
+ if (!max || !value || value >= max)
return false;
- int32 Roll = irand(1, 1000);
-
- if (Roll <= Chance)
+ if (irand(1, 1000) > chance)
{
- uint32 new_value = SkillValue+step;
- if (new_value > MaxValue)
- new_value = MaxValue;
-
- SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, MaxValue));
- if (itr->second.uState != SKILL_NEW)
- itr->second.uState = SKILL_CHANGED;
- for (size_t i = 0; i < bonusSkillLevelsSize; ++i)
- {
- uint32 bsl = bonusSkillLevels[i];
- if (SkillValue < bsl && new_value >= bsl)
- {
- LearnSkillRewardedSpells(SkillId, new_value);
- break;
- }
- }
- UpdateSkillEnchantments(SkillId, SkillValue, new_value);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, SkillId);
- TC_LOG_DEBUG("entities.player.skills", "Player::UpdateSkillPro Chance=%3.1f%% taken", Chance / 10.0f);
- return true;
+ TC_LOG_DEBUG("entities.player.skills", "Player::UpdateSkillPro Chance=%3.1f%% missed", chance / 10.0f);
+ return false;
}
- TC_LOG_DEBUG("entities.player.skills", "Player::UpdateSkillPro Chance=%3.1f%% missed", Chance / 10.0f);
- return false;
-}
+ uint16 new_value = value + step;
+ if (new_value > max)
+ new_value = max;
-void Player::UpdateWeaponSkill(WeaponAttackType attType)
-{
- // no skill gain in pvp
- Unit* victim = GetVictim();
- if (victim && victim->GetTypeId() == TYPEID_PLAYER)
- return;
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value);
+ if (itr->second.uState != SKILL_NEW)
+ itr->second.uState = SKILL_CHANGED;
- if (IsInFeralForm())
- return; // always maximized SKILL_FERAL_COMBAT in fact
-
- if (GetShapeshiftForm() == FORM_TREE)
- return; // use weapon but not skill up
-
- if (victim && victim->GetTypeId() == TYPEID_UNIT && (victim->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_SKILLGAIN))
- return;
-
- uint32 weapon_skill_gain = sWorld->getIntConfig(CONFIG_SKILL_GAIN_WEAPON);
-
- Item* tmpitem = GetWeaponForAttack(attType, true);
- if (!tmpitem && attType == BASE_ATTACK)
- {
- // Keep unarmed & fist weapon skills in sync
- UpdateSkill(SKILL_UNARMED, weapon_skill_gain);
- UpdateSkill(SKILL_FIST_WEAPONS, weapon_skill_gain);
- }
- else if (tmpitem && tmpitem->GetTemplate()->SubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE)
+ for (size_t i = 0; i < bonusSkillLevelsSize; ++i)
{
- switch (tmpitem->GetTemplate()->SubClass)
+ uint32 bsl = bonusSkillLevels[i];
+ if (value < bsl && new_value >= bsl)
{
- case ITEM_SUBCLASS_WEAPON_FISHING_POLE:
- break;
- case ITEM_SUBCLASS_WEAPON_FIST:
- UpdateSkill(SKILL_UNARMED, weapon_skill_gain);
- // no break intended
- default:
- UpdateSkill(tmpitem->GetSkill(), weapon_skill_gain);
- break;
+ LearnSkillRewardedSpells(skillId, new_value);
+ break;
}
}
- UpdateAllCritPercentages();
-}
-
-void Player::UpdateCombatSkills(Unit* victim, WeaponAttackType attType, bool defence)
-{
- uint8 plevel = getLevel(); // if defense than victim == attacker
- uint8 greylevel = Trinity::XP::GetGrayLevel(plevel);
- uint8 moblevel = victim->getLevelForTarget(this);
- if (moblevel < greylevel)
- return;
-
- if (moblevel > plevel + 5)
- moblevel = plevel + 5;
-
- uint8 lvldif = moblevel - greylevel;
- if (lvldif < 3)
- lvldif = 3;
-
- uint32 skilldif = 5 * plevel - (defence ? GetBaseDefenseSkillValue() : GetBaseWeaponSkillValue(attType));
- if (skilldif <= 0)
- return;
-
- float chance = float(3 * lvldif * skilldif) / plevel;
- if (!defence)
- if (getClass() == CLASS_WARRIOR || getClass() == CLASS_ROGUE)
- chance += chance * 0.02f * GetStat(STAT_INTELLECT);
-
- chance = chance < 1.0f ? 1.0f : chance; //minimum chance to increase skill is 1%
-
- if (roll_chance_f(chance))
- {
- if (defence)
- UpdateDefense();
- else
- UpdateWeaponSkill(attType);
- }
- else
- return;
+ UpdateSkillEnchantments(skillId, value, new_value);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skillId);
+ TC_LOG_DEBUG("entities.player.skills", "Player::UpdateSkillPro Chance=%3.1f%% taken", chance / 10.0f);
+ return true;
}
void Player::ModifySkillBonus(uint32 skillid, int32 val, bool talent)
@@ -6296,25 +6176,18 @@ void Player::ModifySkillBonus(uint32 skillid, int32 val, bool talent)
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return;
- uint32 bonusIndex = PLAYER_SKILL_BONUS_INDEX(itr->second.pos);
+ uint16 field = itr->second.pos / 2 + (talent ? PLAYER_SKILL_TALENT_0 : PLAYER_SKILL_MODIFIER_0);
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
- uint32 bonus_val = GetUInt32Value(bonusIndex);
- int16 temp_bonus = SKILL_TEMP_BONUS(bonus_val);
- int16 perm_bonus = SKILL_PERM_BONUS(bonus_val);
+ uint16 bonus = GetUInt16Value(field, offset);
- if (talent) // permanent bonus stored in high part
- SetUInt32Value(bonusIndex, MAKE_SKILL_BONUS(temp_bonus, perm_bonus+val));
- else // temporary/item bonus stored in low part
- SetUInt32Value(bonusIndex, MAKE_SKILL_BONUS(temp_bonus+val, perm_bonus));
+ SetUInt16Value(field, offset, bonus + val);
}
void Player::UpdateSkillsForLevel()
{
- uint16 maxconfskill = sWorld->GetConfigMaxSkillValue();
uint32 maxSkill = GetMaxSkillValueForLevel();
- bool alwaysMaxSkill = sWorld->getBoolConfig(CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL);
-
for (SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); ++itr)
{
if (itr->second.uState == SKILL_DELETED)
@@ -6328,27 +6201,22 @@ void Player::UpdateSkillsForLevel()
if (GetSkillRangeType(rcEntry) != SKILL_RANGE_LEVEL)
continue;
- uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
- uint32 data = GetUInt32Value(valueIndex);
- uint32 max = SKILL_MAX(data);
- uint32 val = SKILL_VALUE(data);
+ if (IsWeaponSkill(rcEntry->SkillId))
+ continue;
+
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
+
+ //uint16 val = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
+ uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
/// update only level dependent max skill values
if (max != 1)
{
- /// maximize skill always
- if (alwaysMaxSkill)
- {
- SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(maxSkill, maxSkill));
- if (itr->second.uState != SKILL_NEW)
- itr->second.uState = SKILL_CHANGED;
- }
- else if (max != maxconfskill) /// update max skill value if current max skill not maximized
- {
- SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(val, maxSkill));
- if (itr->second.uState != SKILL_NEW)
- itr->second.uState = SKILL_CHANGED;
- }
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, maxSkill);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxSkill);
+ if (itr->second.uState != SKILL_NEW)
+ itr->second.uState = SKILL_CHANGED;
}
}
}
@@ -6361,20 +6229,28 @@ void Player::UpdateSkillsToMaxSkillsForLevel()
continue;
uint32 pskill = itr->first;
- if (IsProfessionOrRidingSkill(pskill))
+ SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(pskill, getRace(), getClass());
+ if (!rcEntry)
continue;
- uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
- uint32 data = GetUInt32Value(valueIndex);
- uint32 max = SKILL_MAX(data);
+
+ if (IsProfessionOrRidingSkill(rcEntry->SkillId))
+ continue;
+
+ if (IsWeaponSkill(rcEntry->SkillId))
+ continue;
+
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
+
+ uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
if (max > 1)
{
- SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(max, max));
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, max);
+
if (itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
}
- if (pskill == SKILL_DEFENSE)
- UpdateDefenseBonusesMod();
}
}
@@ -6391,22 +6267,29 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
//has skill
if (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED)
{
- currVal = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
+ currVal = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
if (newVal)
{
// if skill value is going down, update enchantments before setting the new value
if (newVal < currVal)
UpdateSkillEnchantments(id, currVal, newVal);
+
// update step
- SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos), MAKE_PAIR32(id, step));
+ SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step);
// update value
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos), MAKE_SKILL_VALUE(newVal, maxVal));
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, newVal);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxVal);
+
if (itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
+
LearnSkillRewardedSpells(id, newVal);
// if skill value is going up, update enchantments after setting the new value
if (newVal > currVal)
UpdateSkillEnchantments(id, currVal, newVal);
+
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id);
}
@@ -6415,9 +6298,12 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
//remove enchantments needing this skill
UpdateSkillEnchantments(id, currVal, 0);
// clear skill fields
- SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos), 0);
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos), 0);
- SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos), 0);
+ SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0);
// mark as deleted or simply remove from map if not saved yet
if (itr->second.uState != SKILL_NEW)
@@ -6430,24 +6316,44 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
if (SkillLineAbilityEntry const* pAbility = sSkillLineAbilityStore.LookupEntry(j))
if (pAbility->skillId == id)
RemoveSpell(sSpellMgr->GetFirstSpellInChain(pAbility->spellId));
+
+ // Clear profession lines
+ if (GetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1) == id)
+ SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1, 0);
+ else if (GetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + 1) == id)
+ SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + 1, 0);
}
}
else if (newVal) //add
{
currVal = 0;
- for (int i=0; i < PLAYER_MAX_SKILLS; ++i)
+ for (uint32 i = 0; i < PLAYER_MAX_SKILLS; ++i)
{
- if (!GetUInt32Value(PLAYER_SKILL_INDEX(i)))
+ uint16 field = i / 2;
+ uint8 offset = i & 1; // i % 2
+
+ if (!GetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset))
{
- SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(id);
- if (!pSkill)
+ SkillLineEntry const* skillEntry = sSkillLineStore.LookupEntry(id);
+ if (!skillEntry)
{
- TC_LOG_ERROR("entities.player.skills", "Skill not found in SkillLineStore: skill #%u", id);
+ TC_LOG_ERROR("misc", "Skill not found in SkillLineStore: skill #%u", id);
return;
}
- SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id, step));
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i), MAKE_SKILL_VALUE(newVal, maxVal));
+ SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, id);
+ if (skillEntry->categoryId == SKILL_CATEGORY_PROFESSION)
+ {
+ if (!GetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1))
+ SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1, id);
+ else if (!GetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + 1))
+ SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + 1, id);
+ }
+
+ SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step);
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, newVal);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxVal);
+
UpdateSkillEnchantments(id, currVal, newVal);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id);
@@ -6462,8 +6368,8 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
mSkillStatus.insert(SkillStatusMap::value_type(id, SkillStatusData(i, SKILL_NEW)));
// apply skill bonuses
- SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i), 0);
-
+ SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0);
// temporary bonuses
AuraEffectList const& mModSkill = GetAuraEffectsByType(SPELL_AURA_MOD_SKILL);
for (AuraEffectList::const_iterator j = mModSkill.begin(); j != mModSkill.end(); ++j)
@@ -6502,7 +6408,7 @@ uint16 Player::GetSkillStep(uint16 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return PAIR32_HIPART(GetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos)));
+ return GetUInt16Value(PLAYER_SKILL_STEP_0 + itr->second.pos / 2, itr->second.pos & 1);
}
uint16 Player::GetSkillValue(uint32 skill) const
@@ -6514,11 +6420,12 @@ uint16 Player::GetSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
- int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
- result += SKILL_TEMP_BONUS(bonus);
- result += SKILL_PERM_BONUS(bonus);
+ int32 result = int32(GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset));
+ result += int32(GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset));
+ result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset));
return result < 0 ? 0 : result;
}
@@ -6531,11 +6438,12 @@ uint16 Player::GetMaxSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
- int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
- result += SKILL_TEMP_BONUS(bonus);
- result += SKILL_PERM_BONUS(bonus);
+ int32 result = int32(GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset));
+ result += int32(GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset));
+ result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset));
return result < 0 ? 0 : result;
}
@@ -6548,7 +6456,10 @@ uint16 Player::GetPureMaxSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ return GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
}
uint16 Player::GetBaseSkillValue(uint32 skill) const
@@ -6560,8 +6471,11 @@ uint16 Player::GetBaseSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
- result += SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ int32 result = int32(GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset));
+ result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset));
return result < 0 ? 0 : result;
}
@@ -6574,7 +6488,10 @@ uint16 Player::GetPureSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ return GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
}
int16 Player::GetSkillPermBonusValue(uint32 skill) const
@@ -6586,7 +6503,10 @@ int16 Player::GetSkillPermBonusValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ return GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset);
}
int16 Player::GetSkillTempBonusValue(uint32 skill) const
@@ -6598,17 +6518,19 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ return GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset);
}
void Player::SendActionButtons(uint32 state) const
{
WorldPacket data(SMSG_ACTION_BUTTONS, 1+(MAX_ACTION_BUTTONS*4));
- data << uint8(state);
/*
state can be 0, 1, 2
- 0 - Looks to be sent when initial action buttons get sent, however on Trinity we use 1 since 0 had some difficulties
- 1 - Used in any SMSG_ACTION_BUTTONS packet with button data on Trinity. Only used after spec swaps on retail.
+ 0 - Sends initial action buttons, client does not validate if we have the spell or not
+ 1 - Used used after spec swaps, client validates if a spell is known.
2 - Clears the action bars client sided. This is sent during spec swap before unlearning and before sending the new buttons
*/
if (state != 2)
@@ -6622,9 +6544,12 @@ void Player::SendActionButtons(uint32 state) const
data << uint32(0);
}
}
+ else
+ data.resize(MAX_ACTION_BUTTONS * 4); // insert crap, client doesnt even parse this for state == 2
+ data << uint8(state);
GetSession()->SendPacket(&data);
- TC_LOG_INFO("network", "SMSG_ACTION_BUTTONS sent '%u' spec '%u' Sent", GetGUIDLow(), m_activeSpec);
+ TC_LOG_INFO("network", "Action Buttons for '%u' spec '%u' Sent", GetGUIDLow(), GetActiveSpec());
}
bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
@@ -6667,6 +6592,7 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
case ACTION_BUTTON_CMACRO:
case ACTION_BUTTON_MACRO:
case ACTION_BUTTON_EQSET:
+ case ACTION_BUTTON_DROPDOWN:
break;
default:
TC_LOG_ERROR("entities.player", "Unknown action type %u", type);
@@ -7097,16 +7023,12 @@ void Player::UpdateHonorFields()
// update yesterday's contribution
if (m_lastHonorUpdateTime >= yesterday)
{
- SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION));
-
// this is the first update today, reset today's contribution
- SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0);
SetUInt32Value(PLAYER_FIELD_KILLS, MAKE_PAIR32(0, kills_today));
}
else
{
// no honor/kills yesterday or today, reset
- SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0);
SetUInt32Value(PLAYER_FIELD_KILLS, 0);
}
}
@@ -7198,7 +7120,7 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS, victim->getClass());
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_RACE, victim->getRace());
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA, GetAreaId());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, 1, 0, victim);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, 1, 0, 0, victim);
}
else
{
@@ -7235,9 +7157,7 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto
GetSession()->SendPacket(&data);
// add honor points
- ModifyHonorPoints(honor);
-
- ApplyModUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, honor, true);
+ ModifyCurrency(CURRENCY_TYPE_HONOR_POINTS, int32(honor));
if (InBattleground() && honor > 0)
{
@@ -7272,82 +7192,441 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto
return true;
}
-void Player::SetHonorPoints(uint32 value)
+
+void Player::_LoadCurrency(PreparedQueryResult result)
{
- if (value > sWorld->getIntConfig(CONFIG_MAX_HONOR_POINTS))
- value = sWorld->getIntConfig(CONFIG_MAX_HONOR_POINTS);
- SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, value);
- if (value)
- AddKnownCurrency(ITEM_HONOR_POINTS_ID);
+ if (!result)
+ return;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint16 currencyID = fields[0].GetUInt16();
+
+ CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(currencyID);
+ if (!currency)
+ continue;
+
+ PlayerCurrency cur;
+ cur.state = PLAYERCURRENCY_UNCHANGED;
+ cur.weekCount = fields[1].GetUInt32();
+ cur.totalCount = fields[2].GetUInt32();
+
+ _currencyStorage.insert(PlayerCurrenciesMap::value_type(currencyID, cur));
+
+ } while (result->NextRow());
}
-void Player::SetArenaPoints(uint32 value)
+void Player::_SaveCurrency(SQLTransaction& trans)
{
- if (value > sWorld->getIntConfig(CONFIG_MAX_ARENA_POINTS))
- value = sWorld->getIntConfig(CONFIG_MAX_ARENA_POINTS);
- SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, value);
- if (value)
- AddKnownCurrency(ITEM_ARENA_POINTS_ID);
+ PreparedStatement* stmt = NULL;
+ for (PlayerCurrenciesMap::iterator itr = _currencyStorage.begin(); itr != _currencyStorage.end(); ++itr)
+ {
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(itr->first);
+ if (!entry) // should never happen
+ continue;
+
+ switch (itr->second.state)
+ {
+ case PLAYERCURRENCY_NEW:
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_PLAYER_CURRENCY);
+ stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt16(1, itr->first);
+ stmt->setUInt32(2, itr->second.weekCount);
+ stmt->setUInt32(3, itr->second.totalCount);
+ trans->Append(stmt);
+ break;
+ case PLAYERCURRENCY_CHANGED:
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PLAYER_CURRENCY);
+ stmt->setUInt32(0, itr->second.weekCount);
+ stmt->setUInt32(1, itr->second.totalCount);
+ stmt->setUInt32(2, GetGUIDLow());
+ stmt->setUInt16(3, itr->first);
+ trans->Append(stmt);
+ break;
+ default:
+ break;
+ }
+
+ itr->second.state = PLAYERCURRENCY_UNCHANGED;
+ }
}
-void Player::ModifyHonorPoints(int32 value, SQLTransaction trans)
+void Player::SendNewCurrency(uint32 id) const
{
- int32 newValue = int32(GetHonorPoints()) + value;
- if (newValue < 0)
- newValue = 0;
- SetHonorPoints(uint32(newValue));
+ PlayerCurrenciesMap::const_iterator itr = _currencyStorage.find(id);
+ if (itr == _currencyStorage.end())
+ return;
+
+ ByteBuffer currencyData;
+ WorldPacket packet(SMSG_INIT_CURRENCY, 4 + (5*4 + 1));
+ packet.WriteBits(1, 23);
+
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(id);
+ if (!entry) // should never happen
+ return;
+
+ uint32 precision = (entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+ uint32 weekCount = itr->second.weekCount / precision;
+ uint32 weekCap = GetCurrencyWeekCap(entry) / precision;
+
+ packet.WriteBit(weekCount);
+ packet.WriteBits(0, 4); // some flags
+ packet.WriteBit(weekCap);
+ packet.WriteBit(0); // season total earned
+
+ currencyData << uint32(itr->second.totalCount / precision);
+ if (weekCap)
+ currencyData << uint32(weekCap);
+
+ //if (seasonTotal)
+ // currencyData << uint32(seasonTotal / precision);
- if (trans)
+ currencyData << uint32(entry->ID);
+ if (weekCount)
+ currencyData << uint32(weekCount);
+
+ packet.FlushBits();
+ packet.append(currencyData);
+ GetSession()->SendPacket(&packet);
+}
+
+void Player::SendCurrencies() const
+{
+ ByteBuffer currencyData;
+ WorldPacket packet(SMSG_INIT_CURRENCY, 4 + _currencyStorage.size()*(5*4 + 1));
+ size_t count_pos = packet.bitwpos();
+ packet.WriteBits(_currencyStorage.size(), 23);
+
+ size_t count = 0;
+ for (PlayerCurrenciesMap::const_iterator itr = _currencyStorage.begin(); itr != _currencyStorage.end(); ++itr)
{
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_HONOR_POINTS);
- stmt->setUInt32(0, newValue);
- stmt->setUInt32(1, GetGUIDLow());
- trans->Append(stmt);
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(itr->first);
+
+ // not send init meta currencies.
+ if (!entry || entry->Category == CURRENCY_CATEGORY_META_CONQUEST)
+ continue;
+
+ uint32 precision = (entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+ uint32 weekCount = itr->second.weekCount / precision;
+ uint32 weekCap = GetCurrencyWeekCap(entry) / precision;
+
+ packet.WriteBit(weekCount);
+ packet.WriteBits(0, 4); // some flags
+ packet.WriteBit(weekCap);
+ packet.WriteBit(0); // season total earned
+
+ currencyData << uint32(itr->second.totalCount / precision);
+ if (weekCap)
+ currencyData << uint32(weekCap);
+
+ //if (seasonTotal)
+ // currencyData << uint32(seasonTotal / precision);
+
+ currencyData << uint32(entry->ID);
+ if (weekCount)
+ currencyData << uint32(weekCount);
+
+ ++count;
}
+
+ packet.FlushBits();
+ packet.append(currencyData);
+ packet.PutBits(count_pos, count, 23);
+ GetSession()->SendPacket(&packet);
+}
+
+void Player::SendPvpRewards() const
+{
+ WorldPacket packet(SMSG_REQUEST_PVP_REWARDS_RESPONSE, 24);
+ packet << GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_POINTS, true);
+ packet << GetCurrencyOnWeek(CURRENCY_TYPE_CONQUEST_POINTS, true);
+ packet << GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_META_ARENA, true);
+ packet << GetCurrencyOnWeek(CURRENCY_TYPE_CONQUEST_META_RBG, true);
+ packet << GetCurrencyOnWeek(CURRENCY_TYPE_CONQUEST_META_ARENA, true);
+ packet << GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_POINTS, true);
+ packet << GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_META_RBG, true);
+ GetSession()->SendPacket(&packet);
}
-void Player::ModifyArenaPoints(int32 value, SQLTransaction trans)
+uint32 Player::GetCurrency(uint32 id, bool usePrecision) const
{
- int32 newValue = int32(GetArenaPoints()) + value;
- if (newValue < 0)
- newValue = 0;
- SetArenaPoints(uint32(newValue));
+ PlayerCurrenciesMap::const_iterator itr = _currencyStorage.find(id);
+ if (itr == _currencyStorage.end())
+ return 0;
+
+ CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(id);
+ uint32 precision = (usePrecision && currency->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+
+ return itr->second.totalCount / precision;
+}
+
+uint32 Player::GetCurrencyOnWeek(uint32 id, bool usePrecision) const
+{
+ PlayerCurrenciesMap::const_iterator itr = _currencyStorage.find(id);
+ if (itr == _currencyStorage.end())
+ return 0;
+
+ CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(id);
+ uint32 precision = (usePrecision && currency->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+
+ return itr->second.weekCount / precision;
+}
+
+bool Player::HasCurrency(uint32 id, uint32 count) const
+{
+ PlayerCurrenciesMap::const_iterator itr = _currencyStorage.find(id);
+ return itr != _currencyStorage.end() && itr->second.totalCount >= count;
+}
+
+void Player::ModifyCurrency(uint32 id, int32 count, bool printLog/* = true*/, bool ignoreMultipliers/* = false*/)
+{
+ if (!count)
+ return;
- if (trans)
+ CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(id);
+ ASSERT(currency);
+
+ if (!ignoreMultipliers)
+ count *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_CURRENCY_GAIN, id);
+
+ int32 precision = currency->Flags & CURRENCY_FLAG_HIGH_PRECISION ? CURRENCY_PRECISION : 1;
+ uint32 oldTotalCount = 0;
+ uint32 oldWeekCount = 0;
+ PlayerCurrenciesMap::iterator itr = _currencyStorage.find(id);
+ if (itr == _currencyStorage.end())
{
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ARENA_POINTS);
- stmt->setUInt32(0, newValue);
- stmt->setUInt32(1, GetGUIDLow());
- trans->Append(stmt);
+ PlayerCurrency cur;
+ cur.state = PLAYERCURRENCY_NEW;
+ cur.totalCount = 0;
+ cur.weekCount = 0;
+ _currencyStorage[id] = cur;
+ itr = _currencyStorage.find(id);
+ }
+ else
+ {
+ oldTotalCount = itr->second.totalCount;
+ oldWeekCount = itr->second.weekCount;
+ }
+
+ // count can't be more then weekCap if used (weekCap > 0)
+ uint32 weekCap = GetCurrencyWeekCap(currency);
+ if (weekCap && count > int32(weekCap))
+ count = weekCap;
+
+ // count can't be more then totalCap if used (totalCap > 0)
+ uint32 totalCap = GetCurrencyTotalCap(currency);
+ if (totalCap && count > int32(totalCap))
+ count = totalCap;
+
+ int32 newTotalCount = int32(oldTotalCount) + count;
+ if (newTotalCount < 0)
+ newTotalCount = 0;
+
+ int32 newWeekCount = int32(oldWeekCount) + (count > 0 ? count : 0);
+ if (newWeekCount < 0)
+ newWeekCount = 0;
+
+ // if we get more then weekCap just set to limit
+ if (weekCap && int32(weekCap) < newWeekCount)
+ {
+ newWeekCount = int32(weekCap);
+ // weekCap - oldWeekCount always >= 0 as we set limit before!
+ newTotalCount = oldTotalCount + (weekCap - oldWeekCount);
+ }
+
+ // if we get more then totalCap set to maximum;
+ if (totalCap && int32(totalCap) < newTotalCount)
+ {
+ newTotalCount = int32(totalCap);
+ newWeekCount = weekCap;
+ }
+
+ if (uint32(newTotalCount) != oldTotalCount)
+ {
+ if (itr->second.state != PLAYERCURRENCY_NEW)
+ itr->second.state = PLAYERCURRENCY_CHANGED;
+
+ itr->second.totalCount = newTotalCount;
+ itr->second.weekCount = newWeekCount;
+
+ if (count > 0)
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CURRENCY, id, count);
+
+ if (currency->Category == CURRENCY_CATEGORY_META_CONQUEST)
+ {
+ // count was changed to week limit, now we can modify original points.
+ ModifyCurrency(CURRENCY_TYPE_CONQUEST_POINTS, count, printLog);
+ return;
+ }
+
+ WorldPacket packet(SMSG_UPDATE_CURRENCY, 12);
+
+ packet.WriteBit(weekCap != 0);
+ packet.WriteBit(0); // hasSeasonCount
+ packet.WriteBit(!printLog); // print in log
+
+ // if hasSeasonCount packet << uint32(seasontotalearned); TODO: save this in character DB and use it
+
+ packet << uint32(newTotalCount / precision);
+ packet << uint32(id);
+ if (weekCap)
+ packet << uint32(newWeekCount / precision);
+
+ GetSession()->SendPacket(&packet);
+ }
+}
+
+void Player::SetCurrency(uint32 id, uint32 count, bool /*printLog*/ /*= true*/)
+{
+ PlayerCurrenciesMap::iterator itr = _currencyStorage.find(id);
+ if (itr == _currencyStorage.end())
+ {
+ PlayerCurrency cur;
+ cur.state = PLAYERCURRENCY_NEW;
+ cur.totalCount = count;
+ cur.weekCount = 0;
+ _currencyStorage[id] = cur;
}
}
+uint32 Player::GetCurrencyWeekCap(uint32 id, bool usePrecision) const
+{
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(id);
+ if (!entry)
+ return 0;
+
+ uint32 precision = (usePrecision && entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+
+ return GetCurrencyWeekCap(entry) / precision;
+}
+
+void Player::ResetCurrencyWeekCap()
+{
+ for (uint32 arenaSlot = 0; arenaSlot < MAX_ARENA_SLOT; arenaSlot++)
+ {
+ if (uint32 arenaTeamId = GetArenaTeamId(arenaSlot))
+ {
+ ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId);
+ arenaTeam->FinishWeek(); // set played this week etc values to 0 in memory, too
+ arenaTeam->SaveToDB(); // save changes
+ arenaTeam->NotifyStatsChanged(); // notify the players of the changes
+ }
+ }
+
+ for (PlayerCurrenciesMap::iterator itr = _currencyStorage.begin(); itr != _currencyStorage.end(); ++itr)
+ {
+ itr->second.weekCount = 0;
+ itr->second.state = PLAYERCURRENCY_CHANGED;
+ }
+
+ WorldPacket data(SMSG_WEEKLY_RESET_CURRENCY, 0);
+ SendDirectMessage(&data);
+}
+
+uint32 Player::GetCurrencyWeekCap(CurrencyTypesEntry const* currency) const
+{
+ switch (currency->ID)
+ {
+ //original conquest not have week cap
+ case CURRENCY_TYPE_CONQUEST_POINTS:
+ return std::max(GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_META_ARENA, false), GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_META_RBG, false));
+ case CURRENCY_TYPE_CONQUEST_META_ARENA:
+ // should add precision mod = 100
+ return Trinity::Currency::ConquestRatingCalculator(_maxPersonalArenaRate) * CURRENCY_PRECISION;
+ case CURRENCY_TYPE_CONQUEST_META_RBG:
+ // should add precision mod = 100
+ return Trinity::Currency::BgConquestRatingCalculator(GetRBGPersonalRating()) * CURRENCY_PRECISION;
+ }
+
+ return currency->WeekCap;
+}
+
+uint32 Player::GetCurrencyTotalCap(CurrencyTypesEntry const* currency) const
+{
+ uint32 cap = currency->TotalCap;
+
+ switch (currency->ID)
+ {
+ case CURRENCY_TYPE_HONOR_POINTS:
+ {
+ uint32 honorcap = sWorld->getIntConfig(CONFIG_CURRENCY_MAX_HONOR_POINTS);
+ if (honorcap > 0)
+ cap = honorcap;
+ break;
+ }
+ case CURRENCY_TYPE_JUSTICE_POINTS:
+ {
+ uint32 justicecap = sWorld->getIntConfig(CONFIG_CURRENCY_MAX_JUSTICE_POINTS);
+ if (justicecap > 0)
+ cap = justicecap;
+ break;
+ }
+ }
+
+ return cap;
+}
+
+void Player::UpdateConquestCurrencyCap(uint32 currency)
+{
+ uint32 currenciesToUpdate[2] = { currency, CURRENCY_TYPE_CONQUEST_POINTS };
+
+ for (uint32 i = 0; i < 2; ++i)
+ {
+ CurrencyTypesEntry const* currencyEntry = sCurrencyTypesStore.LookupEntry(currenciesToUpdate[i]);
+ if (!currencyEntry)
+ continue;
+
+ uint32 precision = (currencyEntry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? 100 : 1;
+ uint32 cap = GetCurrencyWeekCap(currencyEntry);
+
+ WorldPacket packet(SMSG_UPDATE_CURRENCY_WEEK_LIMIT, 8);
+ packet << uint32(cap / precision);
+ packet << uint32(currenciesToUpdate[i]);
+ GetSession()->SendPacket(&packet);
+ }
+}
+
+void Player::SetInGuild(uint32 guildId)
+{
+ if (guildId)
+ SetUInt64Value(OBJECT_FIELD_DATA, MAKE_NEW_GUID(guildId, 0, HIGHGUID_GUILD));
+ else
+ SetUInt64Value(OBJECT_FIELD_DATA, 0);
+
+ ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_GUILD_LEVEL_ENABLED, guildId != 0 && sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED));
+ SetUInt16Value(OBJECT_FIELD_TYPE, 1, guildId != 0);
+}
+
uint32 Player::GetGuildIdFromDB(uint64 guid)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER);
stmt->setUInt32(0, GUID_LOPART(guid));
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
-
- if (!result)
- return 0;
+ if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
+ return result->Fetch()[0].GetUInt32();
- uint32 id = result->Fetch()[0].GetUInt32();
- return id;
+ return 0;
}
uint8 Player::GetRankFromDB(uint64 guid)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER);
stmt->setUInt32(0, GUID_LOPART(guid));
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
+ if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
+ return result->Fetch()[1].GetUInt8();
- if (result)
+ return 0;
+}
+
+void Player::SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value)
+{
+ SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + type, value);
+ if (type == ARENA_TEAM_PERSONAL_RATING && value > _maxPersonalArenaRate)
{
- uint32 v = result->Fetch()[1].GetUInt8();
- return v;
+ _maxPersonalArenaRate = value;
+ UpdateConquestCurrencyCap(CURRENCY_TYPE_CONQUEST_META_ARENA);
}
- else
- return 0;
}
void Player::SetInArenaTeam(uint32 ArenaTeamId, uint8 slot, uint8 type)
@@ -7355,10 +7634,6 @@ void Player::SetInArenaTeam(uint32 ArenaTeamId, uint8 slot, uint8 type)
SetArenaTeamInfoField(slot, ARENA_TEAM_ID, ArenaTeamId);
SetArenaTeamInfoField(slot, ARENA_TEAM_TYPE, type);
}
-void Player::SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value)
-{
- SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + type, value);
-}
uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type)
{
@@ -7500,7 +7775,7 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
if (!zone)
return;
- if (sWorld->getBoolConfig(CONFIG_WEATHER))
+ if (sWorld->getBoolConfig(CONFIG_WEATHER) && !HasAuraType(SPELL_AURA_FORCE_WEATHER))
{
if (Weather* weather = WeatherMgr::FindWeather(zone->ID))
weather->SendWeatherUpdateToPlayer(this);
@@ -7762,10 +8037,6 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply)
_ApplyWeaponDependentAuraMods(item, WeaponAttackType(attacktype), apply);
_ApplyItemBonuses(proto, slot, apply);
-
- if (slot == EQUIPMENT_SLOT_RANGED)
- _ApplyAmmoBonuses();
-
ApplyItemEquipSpell(item, apply);
ApplyEnchantment(item, apply);
@@ -7786,7 +8057,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (ssd && ssd_level > ssd->MaxLevel)
ssd_level = ssd->MaxLevel;
- ScalingStatValuesEntry const* ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : NULL;
+ ScalingStatValuesEntry const* ssv = ssd ? sScalingStatValuesStore.LookupEntry(ssd_level) : NULL;
if (only_level_scale && !ssv)
return;
@@ -7800,12 +8071,10 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (ssd->StatMod[i] < 0)
continue;
statType = ssd->StatMod[i];
- val = (ssv->getssdMultiplier(proto->ScalingStatValue) * ssd->Modifier[i]) / 10000;
+ val = (ssv->GetStatMultiplier(proto->InventoryType) * ssd->Modifier[i]) / 10000;
}
else
{
- if (i >= proto->StatsCount)
- continue;
statType = proto->ItemStat[i].ItemStatType;
val = proto->ItemStat[i].ItemStatValue;
}
@@ -7871,24 +8140,24 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
case ITEM_MOD_CRIT_SPELL_RATING:
ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply);
break;
- case ITEM_MOD_HIT_TAKEN_MELEE_RATING:
- ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply);
- break;
- case ITEM_MOD_HIT_TAKEN_RANGED_RATING:
- ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply);
- break;
- case ITEM_MOD_HIT_TAKEN_SPELL_RATING:
- ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply);
- break;
- case ITEM_MOD_CRIT_TAKEN_MELEE_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply);
- break;
+ // case ITEM_MOD_HIT_TAKEN_MELEE_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply);
+ // break;
+ // case ITEM_MOD_HIT_TAKEN_RANGED_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply);
+ // break;
+ // case ITEM_MOD_HIT_TAKEN_SPELL_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_MELEE_RATING:
+ // ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply);
+ // break;
case ITEM_MOD_CRIT_TAKEN_RANGED_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply);
- break;
- case ITEM_MOD_CRIT_TAKEN_SPELL_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
+ ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, int32(val), apply);
break;
+ // case ITEM_MOD_CRIT_TAKEN_SPELL_RATING:
+ // ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
+ // break;
case ITEM_MOD_HASTE_MELEE_RATING:
ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply);
break;
@@ -7908,20 +8177,18 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
ApplyRatingMod(CR_CRIT_RANGED, int32(val), apply);
ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply);
break;
- case ITEM_MOD_HIT_TAKEN_RATING:
- ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply);
- ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply);
- ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply);
- break;
- case ITEM_MOD_CRIT_TAKEN_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply);
- ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply);
- ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
- break;
+ // case ITEM_MOD_HIT_TAKEN_RATING: // Unused since 3.3.5
+ // ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply);
+ // ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply);
+ // ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_RATING: // Unused since 3.3.5
+ // ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply);
+ // ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply);
+ // ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
+ // break;
case ITEM_MOD_RESILIENCE_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply);
- ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply);
- ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
+ ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, int32(val), apply);
break;
case ITEM_MOD_HASTE_RATING:
ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply);
@@ -7938,9 +8205,6 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
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_MANA_REGENERATION:
ApplyManaRegenBonus(int32(val), apply);
break;
@@ -7956,28 +8220,39 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
case ITEM_MOD_SPELL_PENETRATION:
ApplySpellPenetrationBonus(val, apply);
break;
- case ITEM_MOD_BLOCK_VALUE:
- HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(val), apply);
+ case ITEM_MOD_MASTERY_RATING:
+ ApplyRatingMod(CR_MASTERY, int32(val), apply);
+ break;
+ case ITEM_MOD_FIRE_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_FROST_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_HOLY_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_SHADOW_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(val), apply);
break;
- // deprecated item mods
- case ITEM_MOD_SPELL_HEALING_DONE:
- case ITEM_MOD_SPELL_DAMAGE_DONE:
+ case ITEM_MOD_NATURE_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_ARCANE_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply);
break;
}
}
// Apply Spell Power from ScalingStatValue if set
- if (ssv)
- if (int32 spellbonus = ssv->getSpellBonus(proto->ScalingStatValue))
+ if (ssv && proto->Flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON)
+ if (int32 spellbonus = int32(ssv->Spellpower))
ApplySpellPowerBonus(spellbonus, apply);
// If set ScalingStatValue armor get it or use item armor
uint32 armor = proto->Armor;
- if (ssv)
- {
- if (uint32 ssvarmor = ssv->getArmorMod(proto->ScalingStatValue))
- armor = ssvarmor;
- }
+ if (ssv && proto->Class == ITEM_CLASS_ARMOR)
+ armor = ssv->GetArmor(proto->InventoryType, proto->SubClass - 1);
else if (armor && proto->ArmorDamageModifier)
armor -= uint32(proto->ArmorDamageModifier);
@@ -8004,27 +8279,6 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (proto->ArmorDamageModifier > 0)
HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply);
- if (proto->Block)
- HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply);
-
- if (proto->HolyRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply);
-
- if (proto->FireRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply);
-
- if (proto->NatureRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply);
-
- if (proto->FrostRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply);
-
- if (proto->ShadowRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply);
-
- if (proto->ArcaneRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply);
-
WeaponAttackType attType = BASE_ATTACK;
if (slot == EQUIPMENT_SLOT_RANGED && (
@@ -8040,23 +8294,6 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (CanUseAttackType(attType))
_ApplyWeaponDamage(slot, proto, ssv, apply);
-
-
- // Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue)
- if (getClass() == CLASS_DRUID)
- {
- int32 dpsMod = 0;
- int32 feral_bonus = 0;
- if (ssv)
- {
- dpsMod = ssv->getDPSMod(proto->ScalingStatValue);
- feral_bonus += ssv->getFeralBonus(proto->ScalingStatValue);
- }
-
- feral_bonus += proto->getFeralBonus(dpsMod);
- if (feral_bonus)
- ApplyFeralAPBonus(feral_bonus, apply);
- }
}
void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv, bool apply)
@@ -8075,18 +8312,20 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
attType = OFF_ATTACK;
}
- float minDamage = proto->Damage[0].DamageMin;
- float maxDamage = proto->Damage[0].DamageMax;
+ float minDamage = proto->DamageMin;
+ float maxDamage = proto->DamageMax;
// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
+ int32 extraDPS = 0;
if (ssv)
{
- int32 extraDPS = ssv->getDPSMod(proto->ScalingStatValue);
+ float damageMultiplier = 0.0f;
+ extraDPS = ssv->GetDPSAndDamageMultiplier(proto->SubClass, (proto->Flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON) != 0, &damageMultiplier);
if (extraDPS)
{
float average = extraDPS * proto->Delay / 1000.0f;
- minDamage = 0.7f * average;
- maxDamage = 1.3f * average;
+ minDamage = (1.0f - damageMultiplier) * average;
+ maxDamage = (1.0f + damageMultiplier) * average;
}
}
@@ -8112,10 +8351,6 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
SetAttackTime(OFF_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME);
}
- // No need to modify any physical damage for ferals as it is calculated from stats only
- if (IsInFeralForm())
- return;
-
if (CanModifyStats() && (damage || proto->Delay))
UpdateDamagePhysical(attType);
}
@@ -8364,10 +8599,10 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
float chance = (float)spellInfo->ProcChance;
- if (spellData.SpellPPMRate)
+ if (proto->SpellPPMRate)
{
uint32 WeaponSpeed = GetAttackTime(attType);
- chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate, spellInfo);
+ chance = GetPPMProcChance(WeaponSpeed, proto->SpellPPMRate, spellInfo);
}
else if (chance > 100.0f)
chance = GetWeaponProcChance();
@@ -8380,6 +8615,9 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
// item combat enchantments
for (uint8 e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot)
{
+ if (e_slot > PRISMATIC_ENCHANTMENT_SLOT && e_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
uint32 enchant_id = item->GetEnchantmentId(EnchantmentSlot(e_slot));
SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
if (!pEnchant)
@@ -8455,7 +8693,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
if (!spellInfo)
{
TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring ", proto->ItemId, learn_spell_id);
- SendEquipError(EQUIP_ERR_NONE, item, NULL);
+ SendEquipError(EQUIP_ERR_INTERNAL_BAG_ERROR, item, NULL);
return;
}
@@ -8502,6 +8740,9 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
// Item enchantments spells cast at use
for (uint8 e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot)
{
+ if (e_slot > PRISMATIC_ENCHANTMENT_SLOT && e_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
uint32 enchant_id = item->GetEnchantmentId(EnchantmentSlot(e_slot));
SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
if (!pEnchant)
@@ -8568,9 +8809,6 @@ void Player::_RemoveAllItemMods()
_ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), false);
_ApplyItemBonuses(proto, i, false);
-
- if (i == EQUIPMENT_SLOT_RANGED)
- _ApplyAmmoBonuses();
}
}
@@ -8597,9 +8835,6 @@ void Player::_ApplyAllItemMods()
_ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), true);
_ApplyItemBonuses(proto, i, true);
-
- if (i == EQUIPMENT_SLOT_RANGED)
- _ApplyAmmoBonuses();
}
}
@@ -8644,63 +8879,6 @@ void Player::_ApplyAllLevelScaleItemMods(bool apply)
}
}
-void Player::_ApplyAmmoBonuses()
-{
- // check ammo
- uint32 ammo_id = GetUInt32Value(PLAYER_AMMO_ID);
- if (!ammo_id)
- return;
-
- float currentAmmoDPS;
-
- ItemTemplate const* ammo_proto = sObjectMgr->GetItemTemplate(ammo_id);
- if (!ammo_proto || ammo_proto->Class != ITEM_CLASS_PROJECTILE || !CheckAmmoCompatibility(ammo_proto))
- currentAmmoDPS = 0.0f;
- else
- currentAmmoDPS = (ammo_proto->Damage[0].DamageMin + ammo_proto->Damage[0].DamageMax) / 2;
-
- if (currentAmmoDPS == GetAmmoDPS())
- return;
-
- m_ammoDPS = currentAmmoDPS;
-
- if (CanModifyStats())
- UpdateDamagePhysical(RANGED_ATTACK);
-}
-
-bool Player::CheckAmmoCompatibility(const ItemTemplate* ammo_proto) const
-{
- if (!ammo_proto)
- return false;
-
- // check ranged weapon
- Item* weapon = GetWeaponForAttack(RANGED_ATTACK);
- if (!weapon || weapon->IsBroken())
- return false;
-
- ItemTemplate const* weapon_proto = weapon->GetTemplate();
- if (!weapon_proto || weapon_proto->Class != ITEM_CLASS_WEAPON)
- return false;
-
- // check ammo ws. weapon compatibility
- switch (weapon_proto->SubClass)
- {
- case ITEM_SUBCLASS_WEAPON_BOW:
- case ITEM_SUBCLASS_WEAPON_CROSSBOW:
- if (ammo_proto->SubClass != ITEM_SUBCLASS_ARROW)
- return false;
- break;
- case ITEM_SUBCLASS_WEAPON_GUN:
- if (ammo_proto->SubClass != ITEM_SUBCLASS_BULLET)
- return false;
- break;
- default:
- return false;
- }
-
- return true;
-}
-
/* If in a battleground a player dies, and an enemy removes the insignia, the player's bones is lootable
Called by remove insignia spell effect */
void Player::RemovedInsignia(Player* looterPlr)
@@ -9047,7 +9225,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
// need know merged fishing/corpse loot type for achievements
loot->loot_type = loot_type;
- WorldPacket data(SMSG_LOOT_RESPONSE, (9+50)); // we guess size
+ WorldPacket data(SMSG_LOOT_RESPONSE, 8 + 1 + 50 + 1 + 1); // we guess size
data << uint64(guid);
data << uint8(loot_type);
data << LootView(*loot, this, permission);
@@ -9077,9 +9255,10 @@ void Player::SendNotifyLootItemRemoved(uint8 lootSlot)
void Player::SendUpdateWorldState(uint32 Field, uint32 Value)
{
- WorldPacket data(SMSG_UPDATE_WORLD_STATE, 8);
+ WorldPacket data(SMSG_UPDATE_WORLD_STATE, 4+4+1);
data << Field;
data << Value;
+ data << uint8(0);
GetSession()->SendPacket(&data);
}
@@ -9132,46 +9311,6 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
case 2257: // Deeprun Tram
case 3703: // Shattrath City
break;
- case 139: // Eastern Plaguelands
- if (pvp && pvp->GetTypeId() == OUTDOOR_PVP_EP)
- pvp->FillInitialWorldStates(data);
- else
- {
- data << uint32(0x97a) << uint32(0x0); // 10 2426
- data << uint32(0x917) << uint32(0x0); // 11 2327
- data << uint32(0x918) << uint32(0x0); // 12 2328
- data << uint32(0x97b) << uint32(0x32); // 13 2427
- data << uint32(0x97c) << uint32(0x32); // 14 2428
- data << uint32(0x933) << uint32(0x1); // 15 2355
- data << uint32(0x946) << uint32(0x0); // 16 2374
- data << uint32(0x947) << uint32(0x0); // 17 2375
- data << uint32(0x948) << uint32(0x0); // 18 2376
- data << uint32(0x949) << uint32(0x0); // 19 2377
- data << uint32(0x94a) << uint32(0x0); // 20 2378
- data << uint32(0x94b) << uint32(0x0); // 21 2379
- data << uint32(0x932) << uint32(0x0); // 22 2354
- data << uint32(0x934) << uint32(0x0); // 23 2356
- data << uint32(0x935) << uint32(0x0); // 24 2357
- data << uint32(0x936) << uint32(0x0); // 25 2358
- data << uint32(0x937) << uint32(0x0); // 26 2359
- data << uint32(0x938) << uint32(0x0); // 27 2360
- data << uint32(0x939) << uint32(0x1); // 28 2361
- data << uint32(0x930) << uint32(0x1); // 29 2352
- data << uint32(0x93a) << uint32(0x0); // 30 2362
- data << uint32(0x93b) << uint32(0x0); // 31 2363
- data << uint32(0x93c) << uint32(0x0); // 32 2364
- data << uint32(0x93d) << uint32(0x0); // 33 2365
- data << uint32(0x944) << uint32(0x0); // 34 2372
- data << uint32(0x945) << uint32(0x0); // 35 2373
- data << uint32(0x931) << uint32(0x1); // 36 2353
- data << uint32(0x93e) << uint32(0x0); // 37 2366
- data << uint32(0x931) << uint32(0x1); // 38 2367 ?? grey horde not in dbc! send for consistency's sake, and to match field count
- data << uint32(0x940) << uint32(0x0); // 39 2368
- data << uint32(0x941) << uint32(0x0); // 7 2369
- data << uint32(0x942) << uint32(0x0); // 8 2370
- data << uint32(0x943) << uint32(0x0); // 9 2371
- }
- break;
case 1377: // Silithus
if (pvp && pvp->GetTypeId() == OUTDOOR_PVP_SI)
pvp->FillInitialWorldStates(data);
@@ -9665,16 +9804,37 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(4131) << uint32(0); // 10 WORLDSTATE_ALGALON_DESPAWN_TIMER
}
break;
- // Halls of Refection
- case 4820:
- if (instance && mapid == 668)
+ // Zul Aman
+ case 3805:
+ if (instance && mapid == 568)
instance->FillInitialWorldStates(data);
else
{
- data << uint32(4884) << uint32(0); // 9 WORLD_STATE_HOR_WAVES_ENABLED
- data << uint32(4882) << uint32(0); // 10 WORLD_STATE_HOR_WAVE_COUNT
+ data << uint32(3104) << uint32(0); // 9 WORLD_STATE_ZULAMAN_TIMER_ENABLED
+ data << uint32(3106) << uint32(0); // 10 WORLD_STATE_ZULAMAN_TIMER
+ }
+ break;
+ // Twin Peaks
+ case 5031:
+ if (bg && bg->GetTypeID(true) == BATTLEGROUND_TP)
+ bg->FillInitialWorldStates(data);
+ else
+ {
+ data << uint32(0x62d) << uint32(0x0); // 7 1581 alliance flag captures
+ data << uint32(0x62e) << uint32(0x0); // 8 1582 horde flag captures
+ data << uint32(0x609) << uint32(0x0); // 9 1545 unk
+ data << uint32(0x60a) << uint32(0x0); // 10 1546 unk
+ data << uint32(0x60b) << uint32(0x2); // 11 1547 unk
+ data << uint32(0x641) << uint32(0x3); // 12 1601 unk
+ data << uint32(0x922) << uint32(0x1); // 13 2338 horde (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing)
+ data << uint32(0x923) << uint32(0x1); // 14 2339 alliance (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing)
}
break;
+ // Battle for Gilneas
+ case 5449:
+ if (bg && bg->GetTypeID(true) == BATTLEGROUND_BFG)
+ bg->FillInitialWorldStates(data);
+ break;
// Wintergrasp
case 4197:
if (bf && bf->GetTypeId() == BATTLEFIELD_WG)
@@ -9682,6 +9842,16 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
bf->FillInitialWorldStates(data);
break;
}
+ // Halls of Refection
+ case 4820:
+ if (instance && mapid == 668)
+ instance->FillInitialWorldStates(data);
+ else
+ {
+ data << uint32(4884) << uint32(0); // 9 WORLD_STATE_HOR_WAVES_ENABLED
+ data << uint32(4882) << uint32(0); // 10 WORLD_STATE_HOR_WAVE_COUNT
+ }
+ break;
// No break here, intended.
default:
data << uint32(0x914) << uint32(0x0); // 7
@@ -9719,7 +9889,7 @@ void Player::SendBattlefieldWorldStates()
/// Send misc stuff that needs to be sent on every login, like the battle timers.
if (sWorld->getBoolConfig(CONFIG_WINTERGRASP_ENABLE))
{
- if (BattlefieldWG* wg = (BattlefieldWG*)sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG))
+ if (Battlefield* wg = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG))
{
if (wg->IsWarTime())
SendUpdateWorldState(ClockWorldState[1], uint32(time(NULL)));
@@ -9754,9 +9924,9 @@ void Player::SetBindPoint(uint64 guid)
void Player::SendTalentWipeConfirm(uint64 guid)
{
- WorldPacket data(MSG_TALENT_WIPE_CONFIRM, (8+4));
+ WorldPacket data(MSG_TALENT_WIPE_CONFIRM, 8 + 4);
data << uint64(guid);
- uint32 cost = sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST) ? 0 : ResetTalentsCost();
+ uint32 cost = sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST) ? 0 : GetNextResetTalentsCost();
data << cost;
GetSession()->SendPacket(&data);
}
@@ -9954,30 +10124,10 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c
break;
case INVTYPE_RELIC:
{
- switch (proto->SubClass)
- {
- case ITEM_SUBCLASS_ARMOR_LIBRAM:
- if (playerClass == CLASS_PALADIN)
- slots[0] = EQUIPMENT_SLOT_RANGED;
- break;
- case ITEM_SUBCLASS_ARMOR_IDOL:
- if (playerClass == CLASS_DRUID)
- slots[0] = EQUIPMENT_SLOT_RANGED;
- break;
- case ITEM_SUBCLASS_ARMOR_TOTEM:
- if (playerClass == CLASS_SHAMAN)
- slots[0] = EQUIPMENT_SLOT_RANGED;
- break;
- case ITEM_SUBCLASS_ARMOR_MISC:
- if (playerClass == CLASS_WARLOCK)
- slots[0] = EQUIPMENT_SLOT_RANGED;
- break;
- case ITEM_SUBCLASS_ARMOR_SIGIL:
- if (playerClass == CLASS_DEATH_KNIGHT)
- slots[0] = EQUIPMENT_SLOT_RANGED;
- break;
- }
- break;
+ if (playerClass == CLASS_PALADIN || playerClass == CLASS_DRUID ||
+ playerClass == CLASS_SHAMAN || playerClass == CLASS_DEATH_KNIGHT)
+ slots[0] = EQUIPMENT_SLOT_RANGED;
+ break;
}
default:
return NULL_SLOT;
@@ -10039,14 +10189,6 @@ InventoryResult Player::CanUnequipItems(uint32 item, uint32 count) const
return EQUIP_ERR_OK;
}
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem->GetEntry() == item)
- {
- tempcount += pItem->GetCount();
- if (tempcount >= count)
- return EQUIP_ERR_OK;
- }
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
if (Bag* pBag = GetBagByPos(i))
@@ -10071,11 +10213,6 @@ uint32 Player::GetItemCount(uint32 item, bool inBankAlso, Item* skipItem) const
if (pItem != skipItem && pItem->GetEntry() == item)
count += pItem->GetCount();
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem != skipItem && pItem->GetEntry() == item)
- count += pItem->GetCount();
-
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
if (Bag* pBag = GetBagByPos(i))
count += pBag->GetItemCount(item, skipItem);
@@ -10118,13 +10255,6 @@ uint32 Player::GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipIte
if (pProto->ItemLimitCategory == limitCategory)
count += pItem->GetCount();
- for (int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem != skipItem)
- if (ItemTemplate const* pProto = pItem->GetTemplate())
- if (pProto->ItemLimitCategory == limitCategory)
- count += pItem->GetCount();
-
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
if (Bag* pBag = GetBagByPos(i))
count += pBag->GetItemCountWithLimitCategory(limitCategory, skipItem);
@@ -10150,11 +10280,6 @@ Item* Player::GetItemByGuid(uint64 guid) const
if (pItem->GetGUID() == guid)
return pItem;
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem->GetGUID() == guid)
- return pItem;
-
for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
if (pItem->GetGUID() == guid)
@@ -10186,7 +10311,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 < CURRENCYTOKEN_SLOT_END)))
+ if (bag == INVENTORY_SLOT_BAG_0 && slot < BANK_SLOT_BAG_END)
return m_items[slot];
else if (Bag* pBag = GetBagByPos(bag))
return pBag->GetItemByPos(slot);
@@ -10276,8 +10401,6 @@ 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 < CURRENCYTOKEN_SLOT_END))
- return true;
return false;
}
@@ -10336,10 +10459,6 @@ bool Player::IsValidPos(uint8 bag, uint8 slot, bool explicit_pos)
if (slot >= INVENTORY_SLOT_ITEM_START && slot < INVENTORY_SLOT_ITEM_END)
return true;
- // keyring slots
- if (slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END)
- return true;
-
// bank main slots
if (slot >= BANK_SLOT_ITEM_START && slot < BANK_SLOT_ITEM_END)
return true;
@@ -10379,16 +10498,7 @@ bool Player::HasItemCount(uint32 item, uint32 count, bool inBankAlso) const
return true;
}
}
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- {
- Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
- {
- tempcount += pItem->GetCount();
- if (tempcount >= count)
- return true;
- }
- }
+
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
if (Bag* pBag = GetBagByPos(i))
@@ -10518,11 +10628,11 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item
{
if (no_space_count)
*no_space_count = count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
if (pItem && pItem->m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
// no maximum
if ((pProto->MaxCount <= 0 && pProto->ItemLimitCategory == 0) || pProto->MaxCount == 2147483647)
@@ -10535,7 +10645,7 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item
{
if (no_space_count)
*no_space_count = count + curcount - pProto->MaxCount;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
@@ -10547,7 +10657,7 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item
{
if (no_space_count)
*no_space_count = count;
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
}
if (limitEntry->mode == ITEM_LIMIT_CATEGORY_MODE_HAVE)
@@ -10557,7 +10667,7 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item
{
if (no_space_count)
*no_space_count = count + curcount - limitEntry->maxCount;
- return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED;
+ return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED_IS;
}
}
}
@@ -10578,36 +10688,6 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec& des
return CanStoreItem(bag, slot, dest, pItem->GetEntry(), count, pItem, swap, NULL);
}
-bool Player::HasItemTotemCategory(uint32 TotemCategory) const
-{
- Item* pItem;
- for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
- {
- pItem = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem && IsTotemCategoryCompatiableWith(pItem->GetTemplate()->TotemCategory, TotemCategory))
- return true;
- }
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- {
- pItem = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem && IsTotemCategoryCompatiableWith(pItem->GetTemplate()->TotemCategory, TotemCategory))
- return true;
- }
- for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
- {
- if (Bag* pBag = GetBagByPos(i))
- {
- for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
- {
- pItem = GetUseableItemByPos(i, j);
- if (pItem && IsTotemCategoryCompatiableWith(pItem->GetTemplate()->TotemCategory, TotemCategory))
- return true;
- }
- }
- }
- return false;
-}
-
InventoryResult Player::CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemPosCountVec &dest, ItemTemplate const* pProto, uint32& count, bool swap, Item* pSrcItem) const
{
Item* pItem2 = GetItemByPos(bag, slot);
@@ -10619,40 +10699,32 @@ InventoryResult Player::CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemP
uint32 need_space;
if (pSrcItem && pSrcItem->IsNotEmptyBag() && !IsBagPos(uint16(bag) << 8 | slot))
- return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS;
+ return EQUIP_ERR_DESTROY_NONEMPTY_BAG;
// empty specific slot - check item fit to slot
if (!pItem2 || swap)
{
if (bag == INVENTORY_SLOT_BAG_0)
{
- // keyring case
- if (slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_START+GetMaxKeyringSize() && !(pProto->BagFamily & BAG_FAMILY_MASK_KEYS))
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
-
- // currencytoken case
- if (slot >= CURRENCYTOKEN_SLOT_START && slot < CURRENCYTOKEN_SLOT_END && !(pProto->IsCurrencyToken()))
- 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;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
}
else
{
Bag* pBag = GetBagByPos(bag);
if (!pBag)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
ItemTemplate const* pBagProto = pBag->GetTemplate();
if (!pBagProto)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
if (slot >= pBagProto->ContainerSlots)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
if (!ItemCanGoIntoBag(pProto, pBagProto))
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
}
// non empty stack with space
@@ -10686,26 +10758,26 @@ InventoryResult Player::CanStoreItem_InBag(uint8 bag, ItemPosCountVec &dest, Ite
{
// skip specific bag already processed in first called CanStoreItem_InBag
if (bag == skip_bag)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
// skip not existed bag or self targeted bag
Bag* pBag = GetBagByPos(bag);
if (!pBag || pBag == pSrcItem)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
if (pSrcItem && pSrcItem->IsNotEmptyBag())
- return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS;
+ return EQUIP_ERR_DESTROY_NONEMPTY_BAG;
ItemTemplate const* pBagProto = pBag->GetTemplate();
if (!pBagProto)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
// specialized bag mode or non-specilized
if (non_specialized != (pBagProto->Class == ITEM_CLASS_CONTAINER && pBagProto->SubClass == ITEM_SUBCLASS_CONTAINER))
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
if (!ItemCanGoIntoBag(pProto, pBagProto))
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
{
@@ -10756,7 +10828,7 @@ InventoryResult Player::CanStoreItem_InInventorySlots(uint8 slot_begin, uint8 sl
{
//this is never called for non-bag slots so we can do this
if (pSrcItem && pSrcItem->IsNotEmptyBag())
- return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS;
+ return EQUIP_ERR_DESTROY_NONEMPTY_BAG;
for (uint32 j = slot_begin; j < slot_end; j++)
{
@@ -10812,7 +10884,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
{
if (no_space_count)
*no_space_count = count;
- return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND;
+ return swap ? EQUIP_ERR_CANT_SWAP : EQUIP_ERR_ITEM_NOT_FOUND;
}
if (pItem)
@@ -10822,14 +10894,14 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
{
if (no_space_count)
*no_space_count = count;
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
}
if (pItem->IsBindedNotWith(this))
{
if (no_space_count)
*no_space_count = count;
- return EQUIP_ERR_DONT_OWN_THAT_ITEM;
+ return EQUIP_ERR_NOT_OWNER;
}
}
@@ -10865,7 +10937,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
@@ -10879,24 +10951,6 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
{
if (bag == INVENTORY_SLOT_BAG_0) // inventory
{
- res = CanStoreItem_InInventorySlots(KEYRING_SLOT_START, CURRENCYTOKEN_SLOT_END, dest, pProto, count, true, 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, true, pItem, bag, slot);
if (res != EQUIP_ERR_OK)
{
@@ -10912,7 +10966,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
else // equipped bag
@@ -10936,7 +10990,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
}
@@ -10944,67 +10998,6 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
// search free slot in bag for place to
if (bag == INVENTORY_SLOT_BAG_0) // inventory
{
- // search free slot - keyring case
- if (pProto->BagFamily & BAG_FAMILY_MASK_KEYS)
- {
- uint32 keyringSize = GetMaxKeyringSize();
- res = CanStoreItem_InInventorySlots(KEYRING_SLOT_START, KEYRING_SLOT_START+keyringSize, 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(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;
- }
- }
- else if (pProto->IsCurrencyToken())
- {
- 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;
- }
- }
-
res = CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START, INVENTORY_SLOT_ITEM_END, dest, pProto, count, false, pItem, bag, slot);
if (res != EQUIP_ERR_OK)
{
@@ -11020,7 +11013,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
else // equipped bag
@@ -11043,7 +11036,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
}
@@ -11053,24 +11046,6 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
// search stack for merge to
if (pProto->Stackable != 1)
{
- res = CanStoreItem_InInventorySlots(KEYRING_SLOT_START, CURRENCYTOKEN_SLOT_END, dest, pProto, count, true, 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, true, pItem, bag, slot);
if (res != EQUIP_ERR_OK)
{
@@ -11086,7 +11061,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
if (pProto->BagFamily)
@@ -11104,7 +11079,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
}
@@ -11122,7 +11097,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
}
@@ -11130,48 +11105,6 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
// search free slot - special bag case
if (pProto->BagFamily)
{
- if (pProto->BagFamily & BAG_FAMILY_MASK_KEYS)
- {
- uint32 keyringSize = GetMaxKeyringSize();
- res = CanStoreItem_InInventorySlots(KEYRING_SLOT_START, KEYRING_SLOT_START+keyringSize, 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;
- }
- }
- else if (pProto->IsCurrencyToken())
- {
- 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;
- }
- }
-
for (uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
res = CanStoreItem_InBag(i, dest, pProto, count, false, false, pItem, bag, slot);
@@ -11185,13 +11118,13 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
}
if (pItem && pItem->IsNotEmptyBag())
- return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG;
+ return EQUIP_ERR_BAG_IN_BAG;
// search free slot
res = CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START, INVENTORY_SLOT_ITEM_END, dest, pProto, count, false, pItem, bag, slot);
@@ -11209,7 +11142,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
@@ -11225,14 +11158,14 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
+ return EQUIP_ERR_ITEM_MAX_COUNT;
}
}
if (no_space_count)
*no_space_count = count + no_similar_count;
- return EQUIP_ERR_INVENTORY_FULL;
+ return EQUIP_ERR_INV_FULL;
}
//////////////////////////////////////////////////////////////////////////
@@ -11243,13 +11176,9 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
// fill space table
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];
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));
for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
@@ -11258,20 +11187,6 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
inv_slot_items[i - INVENTORY_SLOT_ITEM_START] = pItem2->GetCount();
}
- for (uint8 i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
- {
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem2 && !pItem2->IsInTrade())
- inv_keys[i - KEYRING_SLOT_START] = pItem2->GetCount();
- }
-
- for (uint8 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 (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
if (Bag* pBag = GetBagByPos(i))
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
@@ -11299,11 +11214,11 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
// item used
if (pItem->m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
// item it 'bind'
if (pItem->IsBindedNotWith(this))
- return EQUIP_ERR_DONT_OWN_THAT_ITEM;
+ return EQUIP_ERR_NOT_OWNER;
ItemTemplate const* pBagProto;
@@ -11317,32 +11232,6 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
{
bool b_found = false;
- for (uint8 t = KEYRING_SLOT_START; t < KEYRING_SLOT_END; ++t)
- {
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
- if (pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_keys[t-KEYRING_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize())
- {
- inv_keys[t-KEYRING_SLOT_START] += pItem->GetCount();
- b_found = true;
- break;
- }
- }
- if (b_found)
- continue;
-
- for (int t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t)
- {
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
- if (pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && 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 = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; ++t)
{
pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
@@ -11383,38 +11272,6 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
if (pProto->BagFamily)
{
bool b_found = false;
- if (pProto->BagFamily & BAG_FAMILY_MASK_KEYS)
- {
- uint32 keyringSize = GetMaxKeyringSize();
- for (uint32 t = KEYRING_SLOT_START; t < KEYRING_SLOT_START+keyringSize; ++t)
- {
- if (inv_keys[t-KEYRING_SLOT_START] == 0)
- {
- inv_keys[t-KEYRING_SLOT_START] = 1;
- b_found = true;
- break;
- }
- }
- }
-
- if (b_found)
- continue;
-
- if (pProto->IsCurrencyToken())
- {
- 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;
for (int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; ++t)
{
@@ -11481,7 +11338,7 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
// no free slot found?
if (!b_found)
- return EQUIP_ERR_INVENTORY_FULL;
+ return EQUIP_ERR_INV_FULL;
}
return EQUIP_ERR_OK;
@@ -11513,10 +11370,10 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
{
// item used
if (pItem->m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
if (pItem->IsBindedNotWith(this))
- return EQUIP_ERR_DONT_OWN_THAT_ITEM;
+ return EQUIP_ERR_NOT_OWNER;
// check count of items (skip for auto move for same player from bank)
InventoryResult res = CanTakeMoreSimilarItems(pItem);
@@ -11529,7 +11386,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
// May be here should be more stronger checks; STUNNED checked
// ROOT, CONFUSED, DISTRACTED, FLEEING this needs to be checked.
if (HasUnitState(UNIT_STATE_STUNNED))
- return EQUIP_ERR_YOU_ARE_STUNNED;
+ return EQUIP_ERR_GENERIC_STUNNED;
// do not allow equipping gear except weapons, offhands, projectiles, relics in
// - combat
@@ -11545,27 +11402,27 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
}
if (IsInCombat()&& (pProto->Class == ITEM_CLASS_WEAPON || pProto->InventoryType == INVTYPE_RELIC) && m_weaponChangeTimer != 0)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW; // maybe exist better err
+ return EQUIP_ERR_CLIENT_LOCKED_OUT; // maybe exist better err
if (IsNonMeleeSpellCast(false))
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
ScalingStatDistributionEntry const* ssd = pProto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(pProto->ScalingStatDistribution) : 0;
// check allowed level (extend range to upper values if MaxLevel more or equal max player level, this let GM set high level with 1...max range items)
if (ssd && ssd->MaxLevel < DEFAULT_MAX_LEVEL && ssd->MaxLevel < getLevel())
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
uint8 eslot = FindEquipSlot(pProto, slot, swap);
if (eslot == NULL_SLOT)
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
res = CanUseItem(pItem, not_loading);
if (res != EQUIP_ERR_OK)
return res;
if (!swap && GetItemByPos(INVENTORY_SLOT_BAG_0, eslot))
- return EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE;
+ return EQUIP_ERR_NO_SLOT_AVAILABLE;
// if we are swapping 2 equiped items, CanEquipUniqueItem check
// should ignore the item we are trying to swap, and not the
@@ -11609,8 +11466,8 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
if (ItemTemplate const* pBagProto = pBag->GetTemplate())
if (pBagProto->Class == pProto->Class && (!swap || pBag->GetSlot() != eslot))
return (pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH)
- ? EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH
- : EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER;
+ ? EQUIP_ERR_ONLY_ONE_AMMO
+ : EQUIP_ERR_ONLY_ONE_QUIVER;
uint32 type = pProto->InventoryType;
@@ -11618,21 +11475,20 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
{
// Do not allow polearm to be equipped in the offhand (rare case for the only 1h polearm 41750)
if (type == INVTYPE_WEAPON && pProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM)
- return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT;
-
+ return EQUIP_ERR_2HSKILLNOTFOUND;
else if (type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND)
{
if (!CanDualWield())
- return EQUIP_ERR_CANT_DUAL_WIELD;
+ return EQUIP_ERR_2HSKILLNOTFOUND;
}
else if (type == INVTYPE_2HWEAPON)
{
if (!CanDualWield() || !CanTitanGrip())
- return EQUIP_ERR_CANT_DUAL_WIELD;
+ return EQUIP_ERR_2HSKILLNOTFOUND;
}
if (IsTwoHandUsed())
- return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED;
+ return EQUIP_ERR_2HANDED_EQUIPPED;
}
// equip two-hand weapon case (with possible unequip 2 items)
@@ -11641,10 +11497,10 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
if (eslot == EQUIPMENT_SLOT_OFFHAND)
{
if (!CanTitanGrip())
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
}
else if (eslot != EQUIPMENT_SLOT_MAINHAND)
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
if (!CanTitanGrip())
{
@@ -11654,7 +11510,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
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;
+ return swap ? EQUIP_ERR_CANT_SWAP : EQUIP_ERR_INV_FULL;
}
}
dest = ((INVENTORY_SLOT_BAG_0 << 8) | eslot);
@@ -11662,7 +11518,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool
}
}
- return !swap ? EQUIP_ERR_ITEM_NOT_FOUND : EQUIP_ERR_ITEMS_CANT_BE_SWAPPED;
+ return !swap ? EQUIP_ERR_ITEM_NOT_FOUND : EQUIP_ERR_CANT_SWAP;
}
InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
@@ -11685,7 +11541,7 @@ InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
// item used
if (pItem->m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
// do not allow unequipping gear except weapons, offhands, projectiles, relics in
// - combat
@@ -11701,7 +11557,7 @@ InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
}
if (!swap && pItem->IsNotEmptyBag())
- return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS;
+ return EQUIP_ERR_DESTROY_NONEMPTY_BAG;
return EQUIP_ERR_OK;
}
@@ -11709,29 +11565,28 @@ InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, Item* pItem, bool swap, bool not_loading) const
{
if (!pItem)
- return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND;
+ return swap ? EQUIP_ERR_CANT_SWAP : EQUIP_ERR_ITEM_NOT_FOUND;
uint32 count = pItem->GetCount();
TC_LOG_DEBUG("entities.player.items", "STORAGE: CanBankItem bag = %u, slot = %u, item = %u, count = %u", bag, slot, pItem->GetEntry(), pItem->GetCount());
ItemTemplate const* pProto = pItem->GetTemplate();
if (!pProto)
- return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND;
+ return swap ? EQUIP_ERR_CANT_SWAP : EQUIP_ERR_ITEM_NOT_FOUND;
// item used
if (pItem->m_lootGenerated)
- return EQUIP_ERR_ALREADY_LOOTED;
+ return EQUIP_ERR_LOOT_GONE;
if (pItem->IsBindedNotWith(this))
- return EQUIP_ERR_DONT_OWN_THAT_ITEM;
+ return EQUIP_ERR_NOT_OWNER;
- // Currency tokens are not supposed to be swapped out of their hidden bag
- uint8 pItemslot = pItem->GetSlot();
- if (pItemslot >= CURRENCYTOKEN_SLOT_START && pItemslot < CURRENCYTOKEN_SLOT_END)
+ // Currency Tokenizer are not supposed to be swapped out of their hidden bag
+ if (pItem->IsCurrencyToken())
{
TC_LOG_ERROR("entities.player", "Possible hacking attempt: Player %s [guid: %u] tried to move token [guid: %u, entry: %u] out of the currency bag!",
GetName().c_str(), GetGUIDLow(), pItem->GetGUIDLow(), pProto->ItemId);
- return EQUIP_ERR_ITEMS_CANT_BE_SWAPPED;
+ return EQUIP_ERR_CANT_SWAP;
}
// check count of items (skip for auto move for same player from bank)
@@ -11745,10 +11600,10 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest
if (slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END)
{
if (!pItem->IsBag())
- return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT;
+ return EQUIP_ERR_WRONG_SLOT;
if (slot - BANK_SLOT_BAG_START >= GetBankBagSlotCount())
- return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT;
+ return EQUIP_ERR_NO_BANK_SLOT;
res = CanUseItem(pItem, not_loading);
if (res != EQUIP_ERR_OK)
@@ -11769,7 +11624,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest
if (bag != NULL_BAG)
{
if (pItem->IsNotEmptyBag())
- return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG;
+ return EQUIP_ERR_BAG_IN_BAG;
// search stack in bag for merge to
if (pProto->Stackable != 1)
@@ -11900,16 +11755,16 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const
TC_LOG_DEBUG("entities.player.items", "STORAGE: CanUseItem item = %u", pItem->GetEntry());
if (!IsAlive() && not_loading)
- return EQUIP_ERR_YOU_ARE_DEAD;
+ return EQUIP_ERR_PLAYER_DEAD;
//if (isStunned())
- // return EQUIP_ERR_YOU_ARE_STUNNED;
+ // return EQUIP_ERR_GENERIC_STUNNED;
ItemTemplate const* pProto = pItem->GetTemplate();
if (pProto)
{
if (pItem->IsBindedNotWith(this))
- return EQUIP_ERR_DONT_OWN_THAT_ITEM;
+ return EQUIP_ERR_NOT_OWNER;
InventoryResult res = CanUseItem(pProto);
if (res != EQUIP_ERR_OK)
@@ -11922,8 +11777,7 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const
// Armor that is binded to account can "morph" from plate to mail, etc. if skill is not learned yet.
if (pProto->Quality == ITEM_QUALITY_HEIRLOOM && pProto->Class == ITEM_CLASS_ARMOR && !HasSkill(itemSkill))
{
- /// @todo when you right-click already equipped item it throws EQUIP_ERR_NO_REQUIRED_PROFICIENCY.
-
+ /// @todo when you right-click already equipped item it throws EQUIP_ERR_PROFICIENCY_NEEDED.
// In fact it's a visual bug, everything works properly... I need sniffs of operations with
// binded to account items from off server.
@@ -11940,7 +11794,7 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const
}
}
if (!allowEquip && GetSkillValue(itemSkill) == 0)
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
}
if (pProto->RequiredReputationFaction && uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank)
@@ -11959,31 +11813,31 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const
if (proto)
{
if ((proto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY) && GetTeam() != HORDE)
- return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+ return EQUIP_ERR_CANT_EQUIP_EVER;
if ((proto->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && GetTeam() != ALLIANCE)
- return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+ return EQUIP_ERR_CANT_EQUIP_EVER;
if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0)
- return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+ return EQUIP_ERR_CANT_EQUIP_EVER;
if (proto->RequiredSkill != 0)
{
if (GetSkillValue(proto->RequiredSkill) == 0)
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
else if (GetSkillValue(proto->RequiredSkill) < proto->RequiredSkillRank)
return EQUIP_ERR_CANT_EQUIP_SKILL;
}
if (proto->RequiredSpell != 0 && !HasSpell(proto->RequiredSpell))
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
if (getLevel() < proto->RequiredLevel)
return EQUIP_ERR_CANT_EQUIP_LEVEL_I;
// If World Event is not active, prevent using event dependant items
if (proto->HolidayId && !IsHolidayActive((HolidayIds)proto->HolidayId))
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
return EQUIP_ERR_OK;
}
@@ -12015,15 +11869,15 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
}; //Copy from function Item::GetSkill()
if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0)
- return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+ return EQUIP_ERR_CANT_EQUIP_EVER;
if (proto->RequiredSpell != 0 && !HasSpell(proto->RequiredSpell))
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
if (proto->RequiredSkill != 0)
{
if (!GetSkillValue(proto->RequiredSkill))
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
else if (GetSkillValue(proto->RequiredSkill) < proto->RequiredSkillRank)
return EQUIP_ERR_CANT_EQUIP_SKILL;
}
@@ -12031,108 +11885,43 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
uint8 _class = getClass();
if (proto->Class == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->SubClass]) == 0)
- return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ return EQUIP_ERR_PROFICIENCY_NEEDED;
- if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass > ITEM_SUBCLASS_ARMOR_MISC && proto->SubClass < ITEM_SUBCLASS_ARMOR_BUCKLER && proto->InventoryType != INVTYPE_CLOAK)
+ if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass > ITEM_SUBCLASS_ARMOR_MISCELLANEOUS && proto->SubClass < ITEM_SUBCLASS_ARMOR_BUCKLER && proto->InventoryType != INVTYPE_CLOAK)
{
if (_class == CLASS_WARRIOR || _class == CLASS_PALADIN || _class == CLASS_DEATH_KNIGHT)
{
if (getLevel() < 40)
{
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_PLATE)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
else if (_class == CLASS_HUNTER || _class == CLASS_SHAMAN)
{
if (getLevel() < 40)
{
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
if (_class == CLASS_ROGUE || _class == CLASS_DRUID)
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
if (_class == CLASS_MAGE || _class == CLASS_PRIEST || _class == CLASS_WARLOCK)
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_CLOTH)
- return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
return EQUIP_ERR_OK;
}
-InventoryResult Player::CanUseAmmo(uint32 item) const
-{
- TC_LOG_DEBUG("entities.player.items", "STORAGE: CanUseAmmo item = %u", item);
- if (!IsAlive())
- return EQUIP_ERR_YOU_ARE_DEAD;
- //if (isStunned())
- // return EQUIP_ERR_YOU_ARE_STUNNED;
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item);
- if (pProto)
- {
- if (pProto->InventoryType!= INVTYPE_AMMO)
- return EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE;
-
- InventoryResult res = CanUseItem(pProto);
- if (res != EQUIP_ERR_OK)
- return res;
-
- /*if (GetReputationMgr().GetReputation() < pProto->RequiredReputation)
- return EQUIP_ERR_CANT_EQUIP_REPUTATION;
- */
-
- // Requires No Ammo
- if (HasAura(46699))
- return EQUIP_ERR_BAG_FULL6;
-
- return EQUIP_ERR_OK;
- }
- return EQUIP_ERR_ITEM_NOT_FOUND;
-}
-
-void Player::SetAmmo(uint32 item)
-{
- if (!item)
- return;
-
- // already set
- if (GetUInt32Value(PLAYER_AMMO_ID) == item)
- return;
-
- // check ammo
- if (item)
- {
- InventoryResult msg = CanUseAmmo(item);
- if (msg != EQUIP_ERR_OK)
- {
- SendEquipError(msg, NULL, NULL, item);
- return;
- }
- }
-
- SetUInt32Value(PLAYER_AMMO_ID, item);
-
- _ApplyAmmoBonuses();
-}
-
-void Player::RemoveAmmo()
-{
- SetUInt32Value(PLAYER_AMMO_ID, 0);
-
- m_ammoDPS = 0.0f;
-
- if (CanModifyStats())
- UpdateDamagePhysical(RANGED_ATTACK);
-}
-
// Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case.
Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update, int32 randomPropertyId, AllowedLooterSet const& allowedLooters)
{
@@ -12234,10 +12023,6 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool
pItem->SetSlot(slot);
pItem->SetContainer(NULL);
-
- // need update known currency
- if (slot >= CURRENCYTOKEN_SLOT_START && slot < CURRENCYTOKEN_SLOT_END)
- AddKnownCurrency(pItem->GetEntry());
}
else
pBag->StoreItem(slot, pItem, update);
@@ -12452,7 +12237,7 @@ void Player::SetVisibleItemSlot(uint8 slot, Item* pItem)
{
if (pItem)
{
- SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2), pItem->GetEntry());
+ SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2), pItem->GetVisibleEntry());
SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 0, pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 1, pItem->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT));
}
@@ -12751,34 +12536,6 @@ void Player::DestroyItemCount(uint32 itemEntry, uint32 count, bool update, bool
}
}
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- {
- if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- {
- if (item->GetEntry() == itemEntry && !item->IsInTrade())
- {
- if (item->GetCount() + remcount <= count)
- {
- // all keys can be unequipped
- remcount += item->GetCount();
- DestroyItem(INVENTORY_SLOT_BAG_0, i, update);
-
- if (remcount >= count)
- return;
- }
- else
- {
- ItemRemovedQuestCheck(item->GetEntry(), count - remcount);
- item->SetCount(item->GetCount() - count + remcount);
- if (IsInWorld() && update)
- item->SendUpdateToPlayer(this);
- item->SetState(ITEM_CHANGED, this);
- return;
- }
- }
- }
- }
-
// in inventory bags
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
@@ -12918,11 +12675,6 @@ void Player::DestroyZoneLimitedItem(bool update, uint32 new_zone)
if (pItem->IsLimitedToAnotherMapOrZone(GetMapId(), new_zone))
DestroyItem(INVENTORY_SLOT_BAG_0, i, update);
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem->IsLimitedToAnotherMapOrZone(GetMapId(), new_zone))
- DestroyItem(INVENTORY_SLOT_BAG_0, i, update);
-
// in inventory bags
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
if (Bag* pBag = GetBagByPos(i))
@@ -12973,11 +12725,6 @@ Item* Player::GetItemByEntry(uint32 entry) const
if (pItem->GetEntry() == entry)
return pItem;
- for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (pItem->GetEntry() == entry)
- return pItem;
-
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
if (Bag* pBag = GetBagByPos(i))
for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
@@ -13035,21 +12782,21 @@ void Player::SplitItem(uint16 src, uint16 dst, uint32 count)
if (pSrcItem->m_lootGenerated) // prevent split looting item (item
{
//best error message found for attempting to split while looting
- SendEquipError(EQUIP_ERR_COULDNT_SPLIT_ITEMS, pSrcItem, NULL);
+ SendEquipError(EQUIP_ERR_SPLIT_FAILED, pSrcItem, NULL);
return;
}
// not let split all items (can be only at cheating)
if (pSrcItem->GetCount() == count)
{
- SendEquipError(EQUIP_ERR_COULDNT_SPLIT_ITEMS, pSrcItem, NULL);
+ SendEquipError(EQUIP_ERR_SPLIT_FAILED, pSrcItem, NULL);
return;
}
// not let split more existed items (can be only at cheating)
if (pSrcItem->GetCount() < count)
{
- SendEquipError(EQUIP_ERR_TRIED_TO_SPLIT_MORE_THAN_COUNT, pSrcItem, NULL);
+ SendEquipError(EQUIP_ERR_TOO_FEW_TO_SPLIT, pSrcItem, NULL);
return;
}
@@ -13150,7 +12897,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
if (!IsAlive())
{
- SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, pSrcItem, pDstItem);
+ SendEquipError(EQUIP_ERR_PLAYER_DEAD, pSrcItem, pDstItem);
return;
}
@@ -13159,7 +12906,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
if (pSrcItem->m_lootGenerated) // prevent swap looting item
{
//best error message found for attempting to swap while looting
- SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, pSrcItem, NULL);
+ SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, pSrcItem, NULL);
return;
}
@@ -13178,14 +12925,14 @@ void Player::SwapItem(uint16 src, uint16 dst)
// prevent put equipped/bank bag in self
if (IsBagPos(src) && srcslot == dstbag)
{
- SendEquipError(EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG, pSrcItem, pDstItem);
+ SendEquipError(EQUIP_ERR_BAG_IN_BAG, pSrcItem, pDstItem);
return;
}
// prevent equipping bag in the same slot from its inside
if (IsBagPos(dst) && srcbag == dstslot)
{
- SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pSrcItem, pDstItem);
+ SendEquipError(EQUIP_ERR_CANT_SWAP, pSrcItem, pDstItem);
return;
}
@@ -13196,7 +12943,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
if (pDstItem->m_lootGenerated) // prevent swap looting item
{
//best error message found for attempting to swap while looting
- SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, pDstItem, NULL);
+ SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, pDstItem, NULL);
return;
}
@@ -13393,7 +13140,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
if (!bagItemProto || !ItemCanGoIntoBag(bagItemProto, emptyProto))
{
// one from items not go to empty target bag
- SendEquipError(EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG, pSrcItem, pDstItem);
+ SendEquipError(EQUIP_ERR_BAG_IN_BAG, pSrcItem, pDstItem);
return;
}
@@ -13403,7 +13150,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
if (count > emptyBag->GetBagSize())
{
// too small targeted bag
- SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pSrcItem, pDstItem);
+ SendEquipError(EQUIP_ERR_CANT_SWAP, pSrcItem, pDstItem);
return;
}
@@ -13597,16 +13344,16 @@ void Player::SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2, uint
data << uint32(proto ? proto->RequiredLevel : 0);
break;
}
- case EQUIP_ERR_EVENT_AUTOEQUIP_BIND_CONFIRM: // no idea about this one...
+ case EQUIP_ERR_NO_OUTPUT: // no idea about this one...
{
data << uint64(0); // item guid
data << uint32(0); // slot
data << uint64(0); // container
break;
}
- case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED:
- case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_SOCKETED_EXCEEDED:
- case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED:
+ case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED_IS:
+ case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_SOCKETED_EXCEEDED_IS:
+ case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS:
{
ItemTemplate const* proto = pItem ? pItem->GetTemplate() : sObjectMgr->GetItemTemplate(itemid);
data << uint32(proto ? proto->ItemLimitCategory : 0);
@@ -13619,26 +13366,22 @@ void Player::SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2, uint
GetSession()->SendPacket(&data);
}
-void Player::SendBuyError(BuyResult msg, Creature* creature, uint32 item, uint32 param)
+void Player::SendBuyError(BuyResult msg, Creature* creature, uint32 item, uint32 /*param*/)
{
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_BUY_FAILED");
WorldPacket data(SMSG_BUY_FAILED, (8+4+4+1));
data << uint64(creature ? creature->GetGUID() : 0);
data << uint32(item);
- if (param > 0)
- data << uint32(param);
data << uint8(msg);
GetSession()->SendPacket(&data);
}
-void Player::SendSellError(SellResult msg, Creature* creature, uint64 guid, uint32 param)
+void Player::SendSellError(SellResult msg, Creature* creature, uint64 guid)
{
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_SELL_ITEM");
- WorldPacket data(SMSG_SELL_ITEM, (8+8+(param?4:0)+1)); // last check 2.0.10
+ WorldPacket data(SMSG_SELL_ITEM, (8+8+1)); // last check 4.3.4
data << uint64(creature ? creature->GetGUID() : 0);
data << uint64(guid);
- if (param > 0)
- data << uint32(param);
data << uint8(msg);
GetSession()->SendPacket(&data);
}
@@ -13754,6 +13497,9 @@ void Player::AddEnchantmentDurations(Item* item)
{
for (int x = 0; x < MAX_ENCHANTMENT_SLOT; ++x)
{
+ if (x > PRISMATIC_ENCHANTMENT_SLOT && x < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
if (!item->GetEnchantmentId(EnchantmentSlot(x)))
continue;
@@ -13848,10 +13594,257 @@ void Player::AddEnchantmentDuration(Item* item, EnchantmentSlot slot, uint32 dur
}
}
+void Player::ApplyReforgeEnchantment(Item* item, bool apply)
+{
+ if (!item)
+ return;
+
+ ItemReforgeEntry const* reforge = sItemReforgeStore.LookupEntry(item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT));
+ if (!reforge)
+ return;
+
+ float removeValue = item->GetReforgableStat(ItemModType(reforge->SourceStat)) * reforge->SourceMultiplier;
+ float addValue = removeValue * reforge->FinalMultiplier;
+
+ switch (reforge->SourceStat)
+ {
+ case ITEM_MOD_MANA:
+ HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, -removeValue, apply);
+ break;
+ case ITEM_MOD_HEALTH:
+ HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, -removeValue, apply);
+ break;
+ case ITEM_MOD_AGILITY:
+ HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, -removeValue, apply);
+ ApplyStatBuffMod(STAT_AGILITY, -removeValue, apply);
+ break;
+ case ITEM_MOD_STRENGTH:
+ HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, -removeValue, apply);
+ ApplyStatBuffMod(STAT_STRENGTH, -removeValue, apply);
+ break;
+ case ITEM_MOD_INTELLECT:
+ HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, -removeValue, apply);
+ ApplyStatBuffMod(STAT_INTELLECT, -removeValue, apply);
+ break;
+ case ITEM_MOD_SPIRIT:
+ HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, -removeValue, apply);
+ ApplyStatBuffMod(STAT_SPIRIT, -removeValue, apply);
+ break;
+ case ITEM_MOD_STAMINA:
+ HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, -removeValue, apply);
+ ApplyStatBuffMod(STAT_STAMINA, -removeValue, apply);
+ break;
+ case ITEM_MOD_DEFENSE_SKILL_RATING:
+ ApplyRatingMod(CR_DEFENSE_SKILL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_DODGE_RATING:
+ ApplyRatingMod(CR_DODGE, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_PARRY_RATING:
+ ApplyRatingMod(CR_PARRY, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_BLOCK_RATING:
+ ApplyRatingMod(CR_BLOCK, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HIT_MELEE_RATING:
+ ApplyRatingMod(CR_HIT_MELEE, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HIT_RANGED_RATING:
+ ApplyRatingMod(CR_HIT_RANGED, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HIT_SPELL_RATING:
+ ApplyRatingMod(CR_HIT_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_CRIT_MELEE_RATING:
+ ApplyRatingMod(CR_CRIT_MELEE, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_CRIT_RANGED_RATING:
+ ApplyRatingMod(CR_CRIT_RANGED, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_CRIT_SPELL_RATING:
+ ApplyRatingMod(CR_CRIT_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HASTE_SPELL_RATING:
+ ApplyRatingMod(CR_HASTE_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HIT_RATING:
+ ApplyRatingMod(CR_HIT_MELEE, -int32(removeValue), apply);
+ ApplyRatingMod(CR_HIT_RANGED, -int32(removeValue), apply);
+ ApplyRatingMod(CR_HIT_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_CRIT_RATING:
+ ApplyRatingMod(CR_CRIT_MELEE, -int32(removeValue), apply);
+ ApplyRatingMod(CR_CRIT_RANGED, -int32(removeValue), apply);
+ ApplyRatingMod(CR_CRIT_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_RESILIENCE_RATING:
+ ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HASTE_RATING:
+ ApplyRatingMod(CR_HASTE_MELEE, -int32(removeValue), apply);
+ ApplyRatingMod(CR_HASTE_RANGED, -int32(removeValue), apply);
+ ApplyRatingMod(CR_HASTE_SPELL, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_EXPERTISE_RATING:
+ ApplyRatingMod(CR_EXPERTISE, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, -removeValue, apply);
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, -removeValue, apply);
+ break;
+ case ITEM_MOD_RANGED_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, -removeValue, apply);
+ break;
+ case ITEM_MOD_MANA_REGENERATION:
+ ApplyManaRegenBonus(-int32(removeValue), apply);
+ break;
+ case ITEM_MOD_ARMOR_PENETRATION_RATING:
+ ApplyRatingMod(CR_ARMOR_PENETRATION, -int32(removeValue), apply);
+ break;
+ case ITEM_MOD_SPELL_POWER:
+ ApplySpellPowerBonus(-int32(removeValue), apply);
+ break;
+ case ITEM_MOD_HEALTH_REGEN:
+ ApplyHealthRegenBonus(-int32(removeValue), apply);
+ break;
+ case ITEM_MOD_SPELL_PENETRATION:
+ ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -int32(removeValue), apply);
+ m_spellPenetrationItemMod += apply ? -int32(removeValue) : int32(removeValue);
+ break;
+ case ITEM_MOD_BLOCK_VALUE:
+ HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, -removeValue, apply);
+ break;
+ case ITEM_MOD_MASTERY_RATING:
+ ApplyRatingMod(CR_MASTERY, -int32(removeValue), apply);
+ break;
+ }
+
+ switch (reforge->FinalStat)
+ {
+ case ITEM_MOD_MANA:
+ HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, addValue, apply);
+ break;
+ case ITEM_MOD_HEALTH:
+ HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, addValue, apply);
+ break;
+ case ITEM_MOD_AGILITY:
+ HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, addValue, apply);
+ ApplyStatBuffMod(STAT_AGILITY, addValue, apply);
+ break;
+ case ITEM_MOD_STRENGTH:
+ HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, addValue, apply);
+ ApplyStatBuffMod(STAT_STRENGTH, addValue, apply);
+ break;
+ case ITEM_MOD_INTELLECT:
+ HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, addValue, apply);
+ ApplyStatBuffMod(STAT_INTELLECT, addValue, apply);
+ break;
+ case ITEM_MOD_SPIRIT:
+ HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, addValue, apply);
+ ApplyStatBuffMod(STAT_SPIRIT, addValue, apply);
+ break;
+ case ITEM_MOD_STAMINA:
+ HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, addValue, apply);
+ ApplyStatBuffMod(STAT_STAMINA, addValue, apply);
+ break;
+ case ITEM_MOD_DEFENSE_SKILL_RATING:
+ ApplyRatingMod(CR_DEFENSE_SKILL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_DODGE_RATING:
+ ApplyRatingMod(CR_DODGE, int32(addValue), apply);
+ break;
+ case ITEM_MOD_PARRY_RATING:
+ ApplyRatingMod(CR_PARRY, int32(addValue), apply);
+ break;
+ case ITEM_MOD_BLOCK_RATING:
+ ApplyRatingMod(CR_BLOCK, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HIT_MELEE_RATING:
+ ApplyRatingMod(CR_HIT_MELEE, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HIT_RANGED_RATING:
+ ApplyRatingMod(CR_HIT_RANGED, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HIT_SPELL_RATING:
+ ApplyRatingMod(CR_HIT_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_CRIT_MELEE_RATING:
+ ApplyRatingMod(CR_CRIT_MELEE, int32(addValue), apply);
+ break;
+ case ITEM_MOD_CRIT_RANGED_RATING:
+ ApplyRatingMod(CR_CRIT_RANGED, int32(addValue), apply);
+ break;
+ case ITEM_MOD_CRIT_SPELL_RATING:
+ ApplyRatingMod(CR_CRIT_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HASTE_SPELL_RATING:
+ ApplyRatingMod(CR_HASTE_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HIT_RATING:
+ ApplyRatingMod(CR_HIT_MELEE, int32(addValue), apply);
+ ApplyRatingMod(CR_HIT_RANGED, int32(addValue), apply);
+ ApplyRatingMod(CR_HIT_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_CRIT_RATING:
+ ApplyRatingMod(CR_CRIT_MELEE, int32(addValue), apply);
+ ApplyRatingMod(CR_CRIT_RANGED, int32(addValue), apply);
+ ApplyRatingMod(CR_CRIT_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_RESILIENCE_RATING:
+ ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, int32(addValue), apply);
+ break;
+ case ITEM_MOD_HASTE_RATING:
+ ApplyRatingMod(CR_HASTE_MELEE, int32(addValue), apply);
+ ApplyRatingMod(CR_HASTE_RANGED, int32(addValue), apply);
+ ApplyRatingMod(CR_HASTE_SPELL, int32(addValue), apply);
+ break;
+ case ITEM_MOD_EXPERTISE_RATING:
+ ApplyRatingMod(CR_EXPERTISE, int32(addValue), apply);
+ break;
+ case ITEM_MOD_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, addValue, apply);
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, addValue, apply);
+ break;
+ case ITEM_MOD_RANGED_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, addValue, apply);
+ break;
+ case ITEM_MOD_MANA_REGENERATION:
+ ApplyManaRegenBonus(int32(addValue), apply);
+ break;
+ case ITEM_MOD_ARMOR_PENETRATION_RATING:
+ ApplyRatingMod(CR_ARMOR_PENETRATION, int32(addValue), apply);
+ break;
+ case ITEM_MOD_SPELL_POWER:
+ ApplySpellPowerBonus(int32(addValue), apply);
+ break;
+ case ITEM_MOD_HEALTH_REGEN:
+ ApplyHealthRegenBonus(int32(addValue), apply);
+ break;
+ case ITEM_MOD_SPELL_PENETRATION:
+ ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, int32(addValue), apply);
+ m_spellPenetrationItemMod += apply ? int32(addValue) : -int32(addValue);
+ break;
+ case ITEM_MOD_BLOCK_VALUE:
+ HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, addValue, apply);
+ break;
+ case ITEM_MOD_MASTERY_RATING:
+ ApplyRatingMod(CR_MASTERY, int32(addValue), apply);
+ break;
+ }
+}
+
void Player::ApplyEnchantment(Item* item, bool apply)
{
for (uint32 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
+ {
+ // Apply reforge as last enchant
+ if (slot == REFORGE_ENCHANTMENT_SLOT)
+ continue;
+
ApplyEnchantment(item, EnchantmentSlot(slot), apply);
+ }
+
+ ApplyEnchantment(item, REFORGE_ENCHANTMENT_SLOT, apply);
}
void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool apply_dur, bool ignore_condition)
@@ -13862,6 +13855,15 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
if (slot >= MAX_ENCHANTMENT_SLOT)
return;
+ if (slot == TRANSMOGRIFY_ENCHANTMENT_SLOT)
+ return;
+
+ if (slot == REFORGE_ENCHANTMENT_SLOT)
+ {
+ ApplyReforgeEnchantment(item, apply);
+ return;
+ }
+
uint32 enchant_id = item->GetEnchantmentId(slot);
if (!enchant_id)
return;
@@ -13879,6 +13881,11 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
if (pEnchant->requiredSkill > 0 && pEnchant->requiredSkillValue > GetSkillValue(pEnchant->requiredSkill))
return;
+ // Cogwheel gems dont have requirement data set in SpellItemEnchantment.dbc, but they do have it in Item-sparse.db2
+ if (ItemTemplate const* gem = sObjectMgr->GetItemTemplate(pEnchant->GemID))
+ if (gem->RequiredSkill && GetSkillValue(gem->RequiredSkill) < gem->RequiredSkillRank)
+ return;
+
// If we're dealing with a gem inside a prismatic socket we need to check the prismatic socket requirements
// rather than the gem requirements itself. If the socket has no color it is a prismatic socket.
if ((slot == SOCK_ENCHANTMENT_SLOT || slot == SOCK_ENCHANTMENT_SLOT_2 || slot == SOCK_ENCHANTMENT_SLOT_3)
@@ -13920,13 +13927,13 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
{
int32 basepoints = 0;
// Random Property Exist - try found basepoints for spell (basepoints depends from item suffix factor)
- if (item->GetItemRandomPropertyId())
+ if (item->GetItemRandomPropertyId() < 0)
{
ItemRandomSuffixEntry const* item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId()));
if (item_rand)
{
// Search enchant_amount
- for (int k = 0; k < MAX_ITEM_ENCHANTMENT_EFFECTS; ++k)
+ for (int k = 0; k < 5; ++k)
{
if (item_rand->enchant_id[k] == enchant_id)
{
@@ -13972,7 +13979,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
ItemRandomSuffixEntry const* item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId()));
if (item_rand_suffix)
{
- for (int k = 0; k < MAX_ITEM_ENCHANTMENT_EFFECTS; ++k)
+ for (int k = 0; k < 5; ++k)
{
if (item_rand_suffix->enchant_id[k] == enchant_id)
{
@@ -14059,32 +14066,32 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply);
TC_LOG_DEBUG("entities.player.items", "+ %u SPELL_CRIT", enchant_amount);
break;
-// Values from ITEM_STAT_MELEE_HA_RATING to ITEM_MOD_HASTE_RANGED_RATING are never used
-// in Enchantments
-// case ITEM_MOD_HIT_TAKEN_MELEE_RATING:
-// ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply);
-// break;
-// case ITEM_MOD_HIT_TAKEN_RANGED_RATING:
-// ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply);
-// break;
-// case ITEM_MOD_HIT_TAKEN_SPELL_RATING:
-// ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply);
-// break;
-// case ITEM_MOD_CRIT_TAKEN_MELEE_RATING:
-// ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply);
-// break;
-// case ITEM_MOD_CRIT_TAKEN_RANGED_RATING:
-// ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply);
-// break;
-// case ITEM_MOD_CRIT_TAKEN_SPELL_RATING:
-// ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply);
-// break;
-// case ITEM_MOD_HASTE_MELEE_RATING:
-// ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply);
-// break;
-// case ITEM_MOD_HASTE_RANGED_RATING:
-// ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply);
-// break;
+ // Values from ITEM_STAT_MELEE_HA_RATING to ITEM_MOD_HASTE_RANGED_RATING are never used
+ // in Enchantments
+ // case ITEM_MOD_HIT_TAKEN_MELEE_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_HIT_TAKEN_RANGED_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_HIT_TAKEN_SPELL_RATING:
+ // ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_MELEE_RATING:
+ // ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_RANGED_RATING:
+ // ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_SPELL_RATING:
+ // ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_HASTE_MELEE_RATING:
+ // ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_HASTE_RANGED_RATING:
+ // ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply);
+ // break;
case ITEM_MOD_HASTE_SPELL_RATING:
ApplyRatingMod(CR_HASTE_SPELL, enchant_amount, apply);
break;
@@ -14100,21 +14107,18 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply);
TC_LOG_DEBUG("entities.player.items", "+ %u CRITICAL", enchant_amount);
break;
-// Values ITEM_MOD_HIT_TAKEN_RATING and ITEM_MOD_CRIT_TAKEN_RATING are never used in Enchantment
-// case ITEM_MOD_HIT_TAKEN_RATING:
-// ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply);
-// ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply);
-// ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply);
-// break;
-// case ITEM_MOD_CRIT_TAKEN_RATING:
-// ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply);
-// ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply);
-// ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply);
-// break;
+ // case ITEM_MOD_HIT_TAKEN_RATING: // Unused since 3.3.5
+ // ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply);
+ // ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply);
+ // ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply);
+ // break;
+ // case ITEM_MOD_CRIT_TAKEN_RATING: // Unused since 3.3.5
+ // ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply);
+ // ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply);
+ // ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply);
+ // break;
case ITEM_MOD_RESILIENCE_RATING:
- ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply);
- ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply);
- ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply);
+ ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, enchant_amount, apply);
TC_LOG_DEBUG("entities.player.items", "+ %u RESILIENCE", enchant_amount);
break;
case ITEM_MOD_HASTE_RATING:
@@ -14136,10 +14140,6 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
TC_LOG_DEBUG("entities.player.items", "+ %u RANGED_ATTACK_POWER", enchant_amount);
break;
-// case ITEM_MOD_FERAL_ATTACK_POWER:
-// ApplyFeralAPBonus(enchant_amount, apply);
-// TC_LOG_DEBUG("entities.player.items", "+ %u FERAL_ATTACK_POWER", enchant_amount);
-// break;
case ITEM_MOD_MANA_REGENERATION:
ApplyManaRegenBonus(enchant_amount, apply);
TC_LOG_DEBUG("entities.player.items", "+ %u MANA_REGENERATION", enchant_amount);
@@ -14164,8 +14164,10 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply);
TC_LOG_DEBUG("entities.player.items", "+ %u BLOCK_VALUE", enchant_amount);
break;
- case ITEM_MOD_SPELL_HEALING_DONE: // deprecated
- case ITEM_MOD_SPELL_DAMAGE_DONE: // deprecated
+ case ITEM_MOD_MASTERY_RATING:
+ ApplyRatingMod(CR_MASTERY, enchant_amount, apply);
+ TC_LOG_DEBUG("entities.player.items", "+ %u MASTERY", enchant_amount);
+ break;
default:
break;
}
@@ -14234,6 +14236,9 @@ void Player::UpdateSkillEnchantments(uint16 skill_id, uint16 curr_value, uint16
{
for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
{
+ if (slot > PRISMATIC_ENCHANTMENT_SLOT && slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id
+ continue;
+
uint32 ench_id = m_items[i]->GetEnchantmentId(EnchantmentSlot(slot));
if (!ench_id)
continue;
@@ -14274,17 +14279,13 @@ void Player::UpdateSkillEnchantments(uint16 skill_id, uint16 curr_value, uint16
void Player::SendEnchantmentDurations()
{
for (EnchantDurationList::const_iterator itr = m_enchantDuration.begin(); itr != m_enchantDuration.end(); ++itr)
- {
GetSession()->SendItemEnchantTimeUpdate(GetGUID(), itr->item->GetGUID(), itr->slot, uint32(itr->leftduration) / 1000);
- }
}
void Player::SendItemDurations()
{
for (ItemDurationList::const_iterator itr = m_itemDuration.begin(); itr != m_itemDuration.end(); ++itr)
- {
(*itr)->SendTimeUpdate(this);
- }
}
void Player::SendNewItem(Item* item, uint32 count, bool received, bool created, bool broadcast)
@@ -14540,7 +14541,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men
return;
int32 cost = int32(item->BoxMoney);
- if (!HasEnoughMoney(cost))
+ if (!HasEnoughMoney(int64(cost)))
{
SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
PlayerTalkClass->SendCloseGossip();
@@ -14709,11 +14710,11 @@ void Player::PrepareQuestMenu(uint64 guid)
//only for quests which cast teleport spells on player
Map* _map = IsInWorld() ? GetMap() : sMapMgr->FindMap(GetMapId(), GetInstanceId());
ASSERT(_map);
- GameObject* pGameObject = _map->GetGameObject(guid);
- if (pGameObject)
+ GameObject* gameObject = _map->GetGameObject(guid);
+ if (gameObject)
{
- objectQR = sObjectMgr->GetGOQuestRelationBounds(pGameObject->GetEntry());
- objectQIR = sObjectMgr->GetGOQuestInvolvedRelationBounds(pGameObject->GetEntry());
+ objectQR = sObjectMgr->GetGOQuestRelationBounds(gameObject->GetEntry());
+ objectQIR = sObjectMgr->GetGOQuestInvolvedRelationBounds(gameObject->GetEntry());
}
else
return;
@@ -14782,7 +14783,7 @@ void Player::SendPreparedQuest(uint64 guid)
if (quest->IsAutoAccept() && CanAddQuest(quest, true) && CanTakeQuest(quest, true))
AddQuestAndCheckCompletion(quest, object);
- if ((quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) || quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
+ if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, CanCompleteRepeatableQuest(quest), true);
else
PlayerTalkClass->SendQuestGiverQuestDetails(quest, guid, true);
@@ -14845,24 +14846,40 @@ bool Player::IsActiveQuest(uint32 quest_id) const
Quest const* Player::GetNextQuest(uint64 guid, Quest const* quest)
{
QuestRelationBounds objectQR;
+ uint32 nextQuestID = quest->GetNextQuestInChain();
- Creature* creature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, guid);
- if (creature)
- objectQR = sObjectMgr->GetCreatureQuestRelationBounds(creature->GetEntry());
- else
+ switch (GUID_HIPART(guid))
{
- //we should obtain map pointer from GetMap() in 99% of cases. Special case
- //only for quests which cast teleport spells on player
- Map* _map = IsInWorld() ? GetMap() : sMapMgr->FindMap(GetMapId(), GetInstanceId());
- ASSERT(_map);
- GameObject* pGameObject = _map->GetGameObject(guid);
- if (pGameObject)
- objectQR = sObjectMgr->GetGOQuestRelationBounds(pGameObject->GetEntry());
- else
+ case HIGHGUID_PLAYER:
+ ASSERT(quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE));
+ return sObjectMgr->GetQuestTemplate(nextQuestID);
+ case HIGHGUID_UNIT:
+ case HIGHGUID_PET:
+ case HIGHGUID_VEHICLE:
+ {
+ if (Creature* creature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, guid))
+ objectQR = sObjectMgr->GetCreatureQuestRelationBounds(creature->GetEntry());
+ else
+ return NULL;
+ break;
+ }
+ case HIGHGUID_GAMEOBJECT:
+ {
+ //we should obtain map pointer from GetMap() in 99% of cases. Special case
+ //only for quests which cast teleport spells on player
+ Map* _map = IsInWorld() ? GetMap() : sMapMgr->FindMap(GetMapId(), GetInstanceId());
+ ASSERT(_map);
+ if (GameObject* gameObject = _map->GetGameObject(guid))
+ objectQR = sObjectMgr->GetGOQuestRelationBounds(gameObject->GetEntry());
+ else
+ return NULL;
+ break;
+ }
+ default:
return NULL;
}
- uint32 nextQuestID = quest->GetNextQuestInChain();
+ // for unit and go state
for (QuestRelations::const_iterator itr = objectQR.first; itr != objectQR.second; ++itr)
{
if (itr->second == nextQuestID)
@@ -14912,7 +14929,7 @@ bool Player::CanAddQuest(Quest const* quest, bool msg)
InventoryResult msg2 = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, srcitem, count);
// player already have max number (in most case 1) source item, no additional item needed and quest can be added.
- if (msg2 == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS)
+ if (msg2 == EQUIP_ERR_ITEM_MAX_COUNT)
return true;
else if (msg2 != EQUIP_ERR_OK)
{
@@ -14935,7 +14952,7 @@ bool Player::CanCompleteQuest(uint32 quest_id)
return false; // not allow re-complete quest
// auto complete quest
- if ((qInfo->IsAutoComplete() || qInfo->GetFlags() & QUEST_FLAGS_AUTOCOMPLETE) && CanTakeQuest(qInfo, false))
+ if (qInfo->IsAutoComplete() && CanTakeQuest(qInfo, false))
return true;
QuestStatusMap::iterator itr = m_QuestStatus.find(quest_id);
@@ -14979,7 +14996,7 @@ bool Player::CanCompleteQuest(uint32 quest_id)
if (qInfo->GetRewOrReqMoney() < 0)
{
- if (!HasEnoughMoney(-qInfo->GetRewOrReqMoney()))
+ if (!HasEnoughMoney(-int64(qInfo->GetRewOrReqMoney())))
return false;
}
@@ -15015,7 +15032,7 @@ bool Player::CanCompleteRepeatableQuest(Quest const* quest)
bool Player::CanRewardQuest(Quest const* quest, bool msg)
{
// not auto complete quest and not completed quest (only cheating case, then ignore without message)
- if (!quest->IsDFQuest() && !quest->IsAutoComplete() && !(quest->GetFlags() & QUEST_FLAGS_AUTOCOMPLETE) && GetQuestStatus(quest->GetQuestId()) != QUEST_STATUS_COMPLETE)
+ if (!quest->IsDFQuest() && !quest->IsAutoComplete() && GetQuestStatus(quest->GetQuestId()) != QUEST_STATUS_COMPLETE)
return false;
// daily quest can't be rewarded (25 daily quest already completed)
@@ -15041,8 +15058,12 @@ bool Player::CanRewardQuest(Quest const* quest, bool msg)
}
}
+ for (uint8 i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; i++)
+ if (quest->RequiredCurrencyId[i] && !HasCurrency(quest->RequiredCurrencyId[i], quest->RequiredCurrencyCount[i]))
+ return false;
+
// prevent receive reward with low money and GetRewOrReqMoney() < 0
- if (quest->GetRewOrReqMoney() < 0 && !HasEnoughMoney(-quest->GetRewOrReqMoney()))
+ if (quest->GetRewOrReqMoney() < 0 && !HasEnoughMoney(-int64(quest->GetRewOrReqMoney())))
return false;
return true;
@@ -15222,7 +15243,7 @@ void Player::CompleteQuest(uint32 quest_id)
if (qInfo->HasFlag(QUEST_FLAGS_TRACKING))
RewardQuest(qInfo, 0, this, false);
else
- SendQuestComplete(quest_id);
+ SendQuestComplete(qInfo);
}
}
}
@@ -15251,6 +15272,10 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
if (quest->RequiredItemId[i])
DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true);
+ for (uint8 i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ if (quest->RequiredCurrencyId[i])
+ ModifyCurrency(quest->RequiredCurrencyId[i], -int32(quest->RequiredCurrencyCount[i]));
+
for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
{
if (quest->RequiredSourceItemId[i])
@@ -15291,6 +15316,13 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
}
}
+ for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ if (quest->RewardCurrencyId[i])
+ ModifyCurrency(quest->RewardCurrencyId[i], quest->RewardCurrencyCount[i]);
+
+ if (uint32 skill = quest->GetRewardSkillId())
+ UpdateSkillPro(skill, 1000, quest->GetRewardSkillPoints());
+
RewardReputation(quest);
uint16 log_slot = FindQuestSlot(quest_id);
@@ -15300,7 +15332,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
bool rewarded = (m_RewardedQuests.find(quest_id) != m_RewardedQuests.end());
// Not give XP in case already completed once repeatable quest
- uint32 XP = rewarded ? 0 : uint32(quest->XPValue(this)*sWorld->getRate(RATE_XP_QUEST));
+ uint32 XP = rewarded ? 0 : uint32(quest->XPValue(this) * sWorld->getRate(RATE_XP_QUEST));
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT);
@@ -15313,6 +15345,9 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
else
moneyRew = int32(quest->GetRewMoneyMaxLevel() * sWorld->getRate(RATE_DROP_MONEY));
+ if (Guild* guild = sGuildMgr->GetGuildById(GetGuildId()))
+ guild->GiveXP(uint32(quest->XPValue(this) * sWorld->getRate(RATE_XP_QUEST) * sWorld->getRate(RATE_XP_GUILD_MODIFIER)), this);
+
// Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative
if (quest->GetRewOrReqMoney())
moneyRew += quest->GetRewOrReqMoney();
@@ -15336,15 +15371,12 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
SetTitle(titleEntry);
}
- if (quest->GetBonusTalents())
+ if (uint32 talents = quest->GetBonusTalents())
{
- m_questRewardTalentCount+=quest->GetBonusTalents();
+ AddQuestRewardedTalentCount(talents);
InitTalentForLevel();
}
- if (quest->GetRewArenaPoints())
- ModifyArenaPoints(quest->GetRewArenaPoints());
-
// Send reward mail
if (uint32 mail_template_id = quest->GetRewMailTemplateId())
{
@@ -15924,7 +15956,7 @@ bool Player::GiveQuestSourceItem(Quest const* quest)
return true;
}
// player already have max amount required item, just report success
- else if (msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS)
+ else if (msg == EQUIP_ERR_ITEM_MAX_COUNT)
return true;
else
SendEquipError(msg, NULL, NULL, srcitem);
@@ -16089,28 +16121,28 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
switch (questgiver->GetTypeId())
{
- case TYPEID_GAMEOBJECT:
- {
- QuestGiverStatus questStatus = QuestGiverStatus(sScriptMgr->GetDialogStatus(this, questgiver->ToGameObject()));
- if (questStatus != DIALOG_STATUS_SCRIPTED_NO_STATUS)
- return questStatus;
- qr = sObjectMgr->GetGOQuestRelationBounds(questgiver->GetEntry());
- qir = sObjectMgr->GetGOQuestInvolvedRelationBounds(questgiver->GetEntry());
- break;
- }
- case TYPEID_UNIT:
- {
- QuestGiverStatus questStatus = QuestGiverStatus(sScriptMgr->GetDialogStatus(this, questgiver->ToCreature()));
- if (questStatus != DIALOG_STATUS_SCRIPTED_NO_STATUS)
- return questStatus;
- qr = sObjectMgr->GetCreatureQuestRelationBounds(questgiver->GetEntry());
- qir = sObjectMgr->GetCreatureQuestInvolvedRelationBounds(questgiver->GetEntry());
- break;
- }
- default:
- // it's impossible, but check
- TC_LOG_ERROR("entities.player.quest", "GetQuestDialogStatus called for unexpected type %u", questgiver->GetTypeId());
- return DIALOG_STATUS_NONE;
+ case TYPEID_GAMEOBJECT:
+ {
+ QuestGiverStatus questStatus = QuestGiverStatus(sScriptMgr->GetDialogStatus(this, questgiver->ToGameObject()));
+ if (questStatus != DIALOG_STATUS_SCRIPTED_NO_STATUS)
+ return questStatus;
+ qr = sObjectMgr->GetGOQuestRelationBounds(questgiver->GetEntry());
+ qir = sObjectMgr->GetGOQuestInvolvedRelationBounds(questgiver->GetEntry());
+ break;
+ }
+ case TYPEID_UNIT:
+ {
+ QuestGiverStatus questStatus = QuestGiverStatus(sScriptMgr->GetDialogStatus(this, questgiver->ToCreature()));
+ if (questStatus != DIALOG_STATUS_SCRIPTED_NO_STATUS)
+ return questStatus;
+ qr = sObjectMgr->GetCreatureQuestRelationBounds(questgiver->GetEntry());
+ qir = sObjectMgr->GetCreatureQuestInvolvedRelationBounds(questgiver->GetEntry());
+ break;
+ }
+ default:
+ // it's impossible, but check
+ TC_LOG_ERROR("entities.player.quest", "GetQuestDialogStatus called for unexpected type %u", questgiver->GetTypeId());
+ return DIALOG_STATUS_NONE;
}
QuestGiverStatus result = DIALOG_STATUS_NONE;
@@ -16357,6 +16389,9 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count)
{
q_status.ItemCount[j] = std::min<uint16>(q_status.ItemCount[j] + count, reqitemcount);
m_QuestStatusSave[questid] = true;
+
+ //SendQuestUpdateAddItem(qInfo, j, additemcount);
+ // FIXME: verify if there's any packet sent updating item
}
if (CanCompleteQuest(questid))
CompleteQuest(questid);
@@ -16435,7 +16470,7 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid /*= 0*/)
}
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_CREATURE, real_entry); // MUST BE CALLED FIRST
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, real_entry, addkillcount, killed);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, real_entry, addkillcount, 0, killed);
for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
{
@@ -16779,39 +16814,50 @@ bool Player::HasQuestForItem(uint32 itemid) const
return false;
}
-void Player::SendQuestComplete(uint32 quest_id)
+void Player::SendQuestComplete(Quest const* quest)
{
- if (quest_id)
+ if (quest)
{
WorldPacket data(SMSG_QUESTUPDATE_COMPLETE, 4);
- data << uint32(quest_id);
+ data << uint32(quest->GetQuestId());
GetSession()->SendPacket(&data);
- TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest_id);
+ TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest->GetQuestId());
}
}
void Player::SendQuestReward(Quest const* quest, uint32 XP)
{
- uint32 questid = quest->GetQuestId();
- TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questid);
- sGameEventMgr->HandleQuestComplete(questid);
- WorldPacket data(SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4));
- data << uint32(questid);
+ uint32 questId = quest->GetQuestId();
+ TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questId);
+ sGameEventMgr->HandleQuestComplete(questId);
+
+ uint32 xp;
+ uint32 moneyReward;
if (getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
- data << uint32(XP);
- data << uint32(quest->GetRewOrReqMoney());
+ xp = XP;
+ moneyReward = quest->GetRewOrReqMoney();
}
- else
+ else // At max level, increase gold reward
{
- data << uint32(0);
- data << uint32(quest->GetRewOrReqMoney() + int32(quest->GetRewMoneyMaxLevel() * sWorld->getRate(RATE_DROP_MONEY)));
+ xp = 0;
+ moneyReward = uint32(quest->GetRewOrReqMoney() + int32(quest->GetRewMoneyMaxLevel() * sWorld->getRate(RATE_DROP_MONEY)));
}
- data << uint32(10 * quest->CalculateHonorGain(GetQuestLevel(quest)));
- data << uint32(quest->GetBonusTalents()); // bonus talents
- data << uint32(quest->GetRewArenaPoints());
+ WorldPacket data(SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4));
+
+ data << uint32(quest->GetBonusTalents()); // bonus talents (not verified for 4.x)
+ data << uint32(quest->GetRewardSkillPoints()); // 4.x bonus skill points
+ data << uint32(moneyReward);
+ data << uint32(xp);
+ data << uint32(questId);
+ data << uint32(quest->GetRewardSkillId()); // 4.x bonus skill id
+
+ data.WriteBit(0); // FIXME: unknown bits, common values sent
+ data.WriteBit(1);
+ data.FlushBits();
+
GetSession()->SendPacket(&data);
}
@@ -16879,15 +16925,6 @@ void Player::SendPushToPartyResponse(Player* player, uint8 msg)
}
}
-void Player::SendQuestUpdateAddItem(Quest const* /*quest*/, uint32 /*item_idx*/, uint16 /*count*/)
-{
- WorldPacket data(SMSG_QUESTUPDATE_ADD_ITEM, 0);
- TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_ADD_ITEM");
- //data << quest->RequiredItemId[item_idx];
- //data << count;
- GetSession()->SendPacket(&data);
-}
-
void Player::SendQuestUpdateAddCreatureOrGo(Quest const* quest, uint64 guid, uint32 creatureOrGO_idx, uint16 old_count, uint16 add_count)
{
ASSERT(old_count + add_count < 65536 && "mob/GO count store in 16 bits 2^16 = 65536 (0..65536)");
@@ -17128,12 +17165,14 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
//QueryResult* result = CharacterDatabase.PQuery("SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
// 12 13 14 15 16 17 18 19 20 21 22 23 24
//"position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
- // 25 26 27 28 29 30 31 32 33 34 35 36 37 38
- //"resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, "
- // 39 40 41 42 43 44 45 46 47 48 49
- //"arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, "
- // 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
- //"health, power1, power2, power3, power4, power5, power6, power7, instance_id, speccount, activespec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars, grantableLevels FROM characters WHERE guid = '%u'", guid);
+ // 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
+ //"resettalents_time, talentTree, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, "
+ // 40 41 42 43 44 45
+ //"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
+ // 46 47 48 49 50 51 52 53 54 55 56
+ //"health, power1, power2, power3, power4, power5, instance_id, speccount, activespec, exploredZones, equipmentCache, "
+ // 57 58 59
+ //"knownTitles, actionBars, grantableLevels FROM characters WHERE guid = '%u'", guid);
PreparedQueryResult result = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_FROM);
if (!result)
{
@@ -17205,8 +17244,8 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8());
SetUInt32Value(PLAYER_XP, fields[7].GetUInt32());
- _LoadIntoDataField(fields[61].GetCString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE);
- _LoadIntoDataField(fields[64].GetCString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2);
+ _LoadIntoDataField(fields[55].GetCString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE);
+ _LoadIntoDataField(fields[57].GetCString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2);
SetObjectScale(1.0f);
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f);
@@ -17214,7 +17253,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
// load achievements before anything else to prevent multiple gains for the same achievement/criteria on every loading (as loading does call UpdateAchievementCriteria)
m_achievementMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ACHIEVEMENTS), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CRITERIA_PROGRESS));
- uint32 money = fields[8].GetUInt32();
+ uint64 money = fields[8].GetUInt64();
if (money > MAX_MONEY_AMOUNT)
money = MAX_MONEY_AMOUNT;
SetMoney(money);
@@ -17222,16 +17261,12 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
SetUInt32Value(PLAYER_BYTES, fields[9].GetUInt32());
SetUInt32Value(PLAYER_BYTES_2, fields[10].GetUInt32());
SetByteValue(PLAYER_BYTES_3, 0, fields[5].GetUInt8());
- SetByteValue(PLAYER_BYTES_3, 1, fields[49].GetUInt8());
+ SetByteValue(PLAYER_BYTES_3, 1, fields[45].GetUInt8());
SetUInt32Value(PLAYER_FLAGS, fields[11].GetUInt32());
- SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[48].GetUInt32());
-
- SetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES, fields[47].GetUInt64());
-
- SetUInt32Value(PLAYER_AMMO_ID, fields[63].GetUInt32());
+ SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[44].GetUInt32());
// set which actionbars the client has active - DO NOT REMOVE EVER AGAIN (can be changed though, if it does change fieldwise)
- SetByteValue(PLAYER_FIELD_BYTES, 2, fields[65].GetUInt8());
+ SetByteValue(PLAYER_FIELD_BYTES, 2, fields[58].GetUInt8());
InitDisplayIds();
@@ -17259,21 +17294,23 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
InitPrimaryProfessions(); // to max set before any spell loaded
// init saved position, and fix it later if problematic
- uint32 transLowGUID = fields[30].GetUInt32();
+ uint32 transLowGUID = uint32(fields[31].GetUInt32());
+
Relocate(fields[12].GetFloat(), fields[13].GetFloat(), fields[14].GetFloat(), fields[16].GetFloat());
+
uint32 mapId = fields[15].GetUInt16();
- uint32 instanceId = fields[58].GetUInt32();
+ uint32 instanceId = fields[52].GetUInt32();
- uint32 dungeonDiff = fields[38].GetUInt8() & 0x0F;
+ uint32 dungeonDiff = fields[39].GetUInt8() & 0x0F;
if (dungeonDiff >= MAX_DUNGEON_DIFFICULTY)
dungeonDiff = DUNGEON_DIFFICULTY_NORMAL;
- uint32 raidDiff = (fields[38].GetUInt8() >> 4) & 0x0F;
+ uint32 raidDiff = (fields[39].GetUInt8() >> 4) & 0x0F;
if (raidDiff >= MAX_RAID_DIFFICULTY)
raidDiff = RAID_DIFFICULTY_10MAN_NORMAL;
SetDungeonDifficulty(Difficulty(dungeonDiff)); // may be changed in _LoadGroup
SetRaidDifficulty(Difficulty(raidDiff)); // may be changed in _LoadGroup
- std::string taxi_nodes = fields[37].GetString();
+ std::string taxi_nodes = fields[38].GetString();
#define RelocateToHomebind(){ mapId = m_homebindMapId; instanceId = 0; Relocate(m_homebindX, m_homebindY, m_homebindZ); }
@@ -17281,8 +17318,6 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
_LoadArenaTeamInfo(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ARENA_INFO));
- SetArenaPoints(fields[39].GetUInt32());
-
// check arena teams integrity
for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
{
@@ -17299,12 +17334,10 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
SetArenaTeamInfoField(arena_slot, ArenaTeamInfoType(j), 0);
}
- SetHonorPoints(fields[40].GetUInt32());
- SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, fields[41].GetUInt32());
- SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, fields[42].GetUInt32());
- SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, fields[43].GetUInt32());
- SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[44].GetUInt16());
- SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[45].GetUInt16());
+ _LoadCurrency(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CURRENCY));
+ SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, fields[40].GetUInt32());
+ SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[41].GetUInt16());
+ SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[42].GetUInt16());
_LoadBoundInstances(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_BOUND_INSTANCES));
_LoadInstanceTimeRestrictions(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES));
@@ -17375,7 +17408,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
if (transport)
{
- float x = fields[26].GetFloat(), y = fields[27].GetFloat(), z = fields[28].GetFloat(), o = fields[29].GetFloat();
+ float x = fields[27].GetFloat(), y = fields[28].GetFloat(), z = fields[29].GetFloat(), o = fields[30].GetFloat();
m_movementInfo.transport.pos.Relocate(x, y, z, o);
transport->CalculatePassengerPosition(x, y, z, &o);
@@ -17402,7 +17435,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
}
else
{
- TC_LOG_ERROR("entities.player", "Player (guidlow %u) have problems with transport guid (%u). Teleport to bind location.",
+ TC_LOG_ERROR("entities.player", "Player (guidlow %d) have problems with transport guid (%u). Teleport to bind location.",
guid, transLowGUID);
RelocateToHomebind();
@@ -17476,7 +17509,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
// NOW player must have valid map
// load the player's map here if it's not already loaded
Map* map = sMapMgr->CreateMap(mapId, this);
- AreaTrigger const* areaTrigger = NULL;
+ AreaTriggerStruct const* areaTrigger = NULL;
bool check = false;
if (!map)
@@ -17555,21 +17588,21 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
m_Played_time[PLAYED_TIME_TOTAL]= fields[19].GetUInt32();
m_Played_time[PLAYED_TIME_LEVEL]= fields[20].GetUInt32();
- m_resetTalentsCost = fields[24].GetUInt32();
- m_resetTalentsTime = time_t(fields[25].GetUInt32());
+ SetTalentResetCost(fields[24].GetUInt32());
+ SetTalentResetTime(time_t(fields[25].GetUInt32()));
m_taxi.LoadTaxiMask(fields[17].GetString()); // must be before InitTaxiNodesForLevel
- uint32 extraflags = fields[31].GetUInt16();
+ uint32 extraflags = fields[32].GetUInt16();
- m_stableSlots = fields[32].GetUInt8();
+ m_stableSlots = fields[33].GetUInt8();
if (m_stableSlots > MAX_PET_STABLES)
{
TC_LOG_ERROR("entities.player", "Player can have not more %u stable slots, but have in DB %u", MAX_PET_STABLES, uint32(m_stableSlots));
m_stableSlots = MAX_PET_STABLES;
}
- m_atLoginFlags = fields[33].GetUInt16();
+ m_atLoginFlags = fields[34].GetUInt16();
if (HasAtLoginFlag(AT_LOGIN_RENAME))
{
@@ -17582,7 +17615,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
m_lastHonorUpdateTime = logoutTime;
UpdateHonorFields();
- m_deathExpireTime = time_t(fields[36].GetUInt32());
+ m_deathExpireTime = time_t(fields[37].GetUInt32());
if (m_deathExpireTime > now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP)
m_deathExpireTime = now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP - 1;
@@ -17643,14 +17676,26 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
//mails are loaded only when needed ;-) - when player in game click on mailbox.
//_LoadMail();
- m_specsCount = fields[59].GetUInt8();
- m_activeSpec = fields[60].GetUInt8();
+ SetSpecsCount(fields[53].GetUInt8());
+ SetActiveSpec(fields[54].GetUInt8());
// sanity check
- if (m_specsCount > MAX_TALENT_SPECS || m_activeSpec > MAX_TALENT_SPEC || m_specsCount < MIN_TALENT_SPECS)
+ if (GetSpecsCount() > MAX_TALENT_SPECS || GetActiveSpec() > MAX_TALENT_SPEC || GetSpecsCount() < MIN_TALENT_SPECS)
{
- m_activeSpec = 0;
- TC_LOG_ERROR("entities.player", "Player %s(GUID: %u) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUIDLow(), m_specsCount, m_activeSpec);
+ SetActiveSpec(0);
+ TC_LOG_ERROR("entities.player", "Player %s(GUID: %u) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUIDLow(), GetSpecsCount(), GetActiveSpec());
+ }
+
+ // Only load selected specializations, learning mastery spells requires this
+ Tokenizer talentTrees(fields[26].GetString(), ' ', MAX_TALENT_SPECS);
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ {
+ if (i >= talentTrees.size())
+ break;
+
+ uint32 talentTree = atol(talentTrees[i]);
+ if (sTalentTabStore.LookupEntry(talentTree))
+ SetPrimaryTalentTree(i, talentTree);
}
_LoadTalents(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TALENTS));
@@ -17682,6 +17727,9 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
_LoadInventory(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_INVENTORY), time_diff);
+ if (IsVoidStorageUnlocked())
+ _LoadVoidStorage(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE));
+
// update items with duration and realtime
UpdateItemDuration(time_diff, true);
@@ -17694,7 +17742,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
// check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES
// note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded
- uint32 curTitle = fields[46].GetUInt32();
+ uint32 curTitle = fields[43].GetUInt32();
if (curTitle && !HasTitle(curTitle))
curTitle = 0;
@@ -17717,12 +17765,35 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
UpdateAllStats();
// restore remembered power/health values (but not more max values)
- uint32 savedHealth = fields[50].GetUInt32();
+ uint32 savedHealth = fields[46].GetUInt32();
SetHealth(savedHealth > GetMaxHealth() ? GetMaxHealth() : savedHealth);
- for (uint8 i = 0; i < MAX_POWERS; ++i)
+ uint32 loadedPowers = 0;
+ for (uint32 i = 0; i < MAX_POWERS; ++i)
{
- uint32 savedPower = fields[51+i].GetUInt32();
- SetPower(Powers(i), savedPower > GetMaxPower(Powers(i)) ? GetMaxPower(Powers(i)) : savedPower);
+ if (GetPowerIndex(i) != MAX_POWERS)
+ {
+ uint32 savedPower = fields[47+loadedPowers].GetUInt32();
+ uint32 maxPower = GetUInt32Value(UNIT_FIELD_MAXPOWER1 + loadedPowers);
+ SetPower(Powers(i), (savedPower > maxPower) ? maxPower : savedPower);
+ if (++loadedPowers >= MAX_POWERS_PER_CLASS)
+ break;
+ }
+ }
+
+ for (; loadedPowers < MAX_POWERS_PER_CLASS; ++loadedPowers)
+ SetUInt32Value(UNIT_FIELD_POWER1 + loadedPowers, 0);
+
+ SetPower(POWER_ECLIPSE, 0);
+
+ // Verify loaded talent specializations
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ {
+ if (i >= talentTrees.size())
+ break;
+
+ uint32 talentTree = atol(talentTrees[i]);
+ if (talentTree != 0 && !sTalentTabStore.LookupEntry(talentTree) && i == GetActiveSpec())
+ SetAtLoginFlag(AT_LOGIN_RESET_TALENTS); // invalid tree, reset talents
}
TC_LOG_DEBUG("entities.player.loading", "The value of player %s after load item and aura is: ", m_name.c_str());
@@ -17777,7 +17848,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
}
// RaF stuff.
- m_grantableLevels = fields[66].GetUInt8();
+ m_grantableLevels = fields[59].GetUInt8();
if (GetSession()->IsARecruiter() || (GetSession()->GetRecruiterId() != 0))
SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_REFER_A_FRIEND);
@@ -17786,13 +17857,50 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
_LoadDeclinedNames(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES));
- m_achievementMgr->CheckAllAchievementCriteria();
+ m_achievementMgr->CheckAllAchievementCriteria(this);
_LoadEquipmentSets(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS));
+ _LoadCUFProfiles(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES));
+
return true;
}
+void Player::_LoadCUFProfiles(PreparedQueryResult result)
+{
+ if (!result)
+ return;
+
+ do
+ {
+ // SELECT id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154 FROM character_cuf_profiles WHERE guid = ?
+ Field* fields = result->Fetch();
+
+ uint8 id = fields[0].GetUInt8();
+ std::string name = fields[1].GetString();
+ uint16 frameHeight = fields[2].GetUInt16();
+ uint16 frameWidth = fields[3].GetUInt16();
+ uint8 sortBy = fields[4].GetUInt8();
+ uint8 healthText = fields[5].GetUInt8();
+ uint32 boolOptions = fields[6].GetUInt32();
+ uint8 unk146 = fields[7].GetUInt8();
+ uint8 unk147 = fields[8].GetUInt8();
+ uint8 unk148 = fields[9].GetUInt8();
+ uint16 unk150 = fields[10].GetUInt16();
+ uint16 unk152 = fields[11].GetUInt16();
+ uint16 unk154 = fields[12].GetUInt16();
+
+ if (id > MAX_CUF_PROFILES)
+ {
+ TC_LOG_ERROR("entities.player", "Player::_LoadCUFProfiles - Player (GUID: %u, name: %s) has an CUF profile with invalid id (id: %u), max is %i.", GetGUIDLow(), GetName().c_str(), id, MAX_CUF_PROFILES);
+ continue;
+ }
+
+ _CUFProfiles[id] = new CUFProfile(name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154);
+ }
+ while (result->NextRow());
+}
+
bool Player::isAllowedToLoot(const Creature* creature)
{
if (!creature->isDead() || !creature->IsDamageEnoughForLootingAndReward())
@@ -17949,7 +18057,7 @@ void Player::_LoadGlyphAuras()
{
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
{
- if (uint32 glyph = GetGlyph(i))
+ if (uint32 glyph = GetGlyph(GetActiveSpec(), i))
{
if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
@@ -18073,7 +18181,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
{
std::map<uint32, Item*>::iterator itr = invalidBagMap.find(bagGuid);
if (std::find(problematicItems.begin(), problematicItems.end(), itr->second) != problematicItems.end())
- err = EQUIP_ERR_INT_BAG_ERROR;
+ err = EQUIP_ERR_INTERNAL_BAG_ERROR;
}
else
{
@@ -18120,6 +18228,53 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
_ApplyAllItemMods();
}
+void Player::_LoadVoidStorage(PreparedQueryResult result)
+{
+ if (!result)
+ return;
+
+ do
+ {
+ // SELECT itemid, itemEntry, slot, creatorGuid FROM character_void_storage WHERE playerGuid = ?
+ Field* fields = result->Fetch();
+
+ uint64 itemId = fields[0].GetUInt64();
+ uint32 itemEntry = fields[1].GetUInt32();
+ uint8 slot = fields[2].GetUInt8();
+ uint32 creatorGuid = fields[3].GetUInt32();
+ uint32 randomProperty = fields[4].GetUInt32();
+ uint32 suffixFactor = fields[5].GetUInt32();
+
+ if (!itemId)
+ {
+ TC_LOG_ERROR("entities.player", "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid id (item id: " UI64FMTD ", entry: %u).", GetGUIDLow(), GetName().c_str(), itemId, itemEntry);
+ continue;
+ }
+
+ if (!sObjectMgr->GetItemTemplate(itemEntry))
+ {
+ TC_LOG_ERROR("entities.player", "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid entry (item id: " UI64FMTD ", entry: %u).", GetGUIDLow(), GetName().c_str(), itemId, itemEntry);
+ continue;
+ }
+
+ if (slot >= VOID_STORAGE_MAX_SLOT)
+ {
+ TC_LOG_ERROR("entities.player", "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid slot (item id: " UI64FMTD ", entry: %u, slot: %u).", GetGUIDLow(), GetName().c_str(), itemId, itemEntry, slot);
+ continue;
+ }
+
+ std::string name;
+ if (creatorGuid && !sObjectMgr->GetPlayerNameByGUID(creatorGuid, name))
+ {
+ TC_LOG_ERROR("entities.player", "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid creator guid, set to 0 (item id: " UI64FMTD ", entry: %u, creatorGuid: %u).", GetGUIDLow(), GetName().c_str(), itemId, itemEntry, creatorGuid);
+ creatorGuid = 0;
+ }
+
+ _voidStorageItems[slot] = new VoidStorageItem(itemId, itemEntry, creatorGuid, randomProperty, suffixFactor);
+ }
+ while (result->NextRow());
+}
+
Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, Field* fields)
{
Item* item = NULL;
@@ -18341,8 +18496,8 @@ void Player::_LoadMail()
bool has_items = fields[6].GetBool();
m->expire_time = time_t(fields[7].GetUInt32());
m->deliver_time = time_t(fields[8].GetUInt32());
- m->money = fields[9].GetUInt32();
- m->COD = fields[10].GetUInt32();
+ m->money = fields[9].GetUInt64();
+ m->COD = fields[10].GetUInt64();
m->checked = fields[11].GetUInt8();
m->stationery = fields[12].GetUInt8();
m->mailTemplateId = fields[13].GetInt16();
@@ -18492,8 +18647,8 @@ void Player::_LoadQuestStatusRewarded(PreparedQueryResult result)
SetTitle(titleEntry);
}
- if (quest->GetBonusTalents())
- m_questRewardTalentCount += quest->GetBonusTalents();
+ if (uint32 talents = quest->GetBonusTalents())
+ AddQuestRewardedTalentCount(talents);
}
m_RewardedQuests.insert(quest_id);
@@ -18688,7 +18843,7 @@ void Player::_LoadBoundInstances(PreparedQueryResult result)
bool deleteInstance = false;
MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
- std::string mapname = mapEntry ? mapEntry->name[sWorld->GetDefaultDbcLocale()] : "Unknown";
+ std::string mapname = mapEntry ? mapEntry->name : "Unknown";
if (!mapEntry || !mapEntry->IsDungeon())
{
@@ -18882,16 +19037,25 @@ void Player::SendRaidInfo()
if (itr->second.perm)
{
InstanceSave* save = itr->second.save;
+ bool isHeroic = save->GetDifficulty() == RAID_DIFFICULTY_10MAN_HEROIC || save->GetDifficulty() == RAID_DIFFICULTY_25MAN_HEROIC;
+ uint32 completedEncounters = 0;
+ if (Map* map = sMapMgr->FindMap(save->GetMapId(), save->GetInstanceId()))
+ if (InstanceScript* instanceScript = ((InstanceMap*)map)->GetInstanceScript())
+ completedEncounters = instanceScript->GetCompletedEncounterMask();
+
data << uint32(save->GetMapId()); // map id
data << uint32(save->GetDifficulty()); // difficulty
+ data << uint32(isHeroic); // heroic
data << uint64(save->GetInstanceId()); // instance id
data << uint8(1); // expired = 0
data << uint8(0); // extended = 1
data << uint32(save->GetResetTime() - now); // reset time
+ data << uint32(completedEncounters); // completed encounters mask
++counter;
}
}
}
+
data.put<uint32>(p_counter, counter);
GetSession()->SendPacket(&data);
}
@@ -18916,8 +19080,8 @@ void Player::SendSavedInstances()
}
}
- //Send opcode 811. true or false means, whether you have current raid/heroic instances
- data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP);
+ //Send opcode SMSG_UPDATE_INSTANCE_OWNERSHIP. true or false means, whether you have current raid/heroic instances
+ data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP, 4);
data << uint32(hasBeenSaved);
GetSession()->SendPacket(&data);
@@ -18930,7 +19094,7 @@ void Player::SendSavedInstances()
{
if (itr->second.perm)
{
- data.Initialize(SMSG_UPDATE_LAST_INSTANCE);
+ data.Initialize(SMSG_UPDATE_LAST_INSTANCE, 4);
data << uint32(itr->second.save->GetMapId());
GetSession()->SendPacket(&data);
}
@@ -19078,7 +19242,8 @@ bool Player::_LoadHomeBind(PreparedQueryResult result)
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass());
if (!info)
{
- TC_LOG_ERROR("entities.player", "Player (Name %s) has incorrect race/class pair. Can't be loaded.", GetName().c_str());
+ TC_LOG_ERROR("entities.player", "Player (Name %s) has incorrect race/class (%u/%u) pair. Can't be loaded.",
+ GetName().c_str(), uint32(getRace()), uint32(getClass()));
return false;
}
@@ -19173,7 +19338,7 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, getGender());
stmt->setUInt8(index++, getLevel());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP));
- stmt->setUInt32(index++, GetMoney());
+ stmt->setUInt64(index++, GetMoney());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES_2));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS));
@@ -19204,8 +19369,13 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0));
//save, far from tavern/city
//save, but in tavern/city
- stmt->setUInt32(index++, m_resetTalentsCost);
- stmt->setUInt32(index++, uint32(m_resetTalentsTime));
+ stmt->setUInt32(index++, GetTalentResetCost());
+ stmt->setUInt32(index++, GetTalentResetTime());
+
+ ss.str("");
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ ss << GetPrimaryTalentTree(i) << " ";
+ stmt->setString(index++, ss.str());
stmt->setUInt16(index++, (uint16)m_ExtraFlags);
stmt->setUInt8(index++, m_stableSlots);
stmt->setUInt16(index++, (uint16)m_atLoginFlags);
@@ -19216,26 +19386,32 @@ void Player::SaveToDB(bool create /*=false*/)
ss << m_taxi.SaveTaxiDestinationsToString();
stmt->setString(index++, ss.str());
- stmt->setUInt32(index++, GetArenaPoints());
- stmt->setUInt32(index++, GetHonorPoints());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION));
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS));
stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 0));
stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 1));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_CHOSEN_TITLE));
- stmt->setUInt64(index++, GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX));
stmt->setUInt8(index++, GetDrunkValue());
stmt->setUInt32(index++, GetHealth());
+ uint32 storedPowers = 0;
for (uint32 i = 0; i < MAX_POWERS; ++i)
- stmt->setUInt32(index++, GetPower(Powers(i)));
+ {
+ if (GetPowerIndex(i) != MAX_POWERS)
+ {
+ stmt->setUInt32(index++, GetUInt32Value(UNIT_FIELD_POWER1 + storedPowers));
+ if (++storedPowers >= MAX_POWERS_PER_CLASS)
+ break;
+ }
+ }
+
+ for (; storedPowers < MAX_POWERS_PER_CLASS; ++storedPowers)
+ stmt->setUInt32(index++, 0);
stmt->setUInt32(index++, GetSession()->GetLatency());
- stmt->setUInt8(index++, m_specsCount);
- stmt->setUInt8(index++, m_activeSpec);
+ stmt->setUInt8(index++, GetSpecsCount());
+ stmt->setUInt8(index++, GetActiveSpec());
ss.str("");
for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i)
@@ -19256,15 +19432,13 @@ void Player::SaveToDB(bool create /*=false*/)
ss << '0';
ss << " 0 ";
}
-
stmt->setString(index++, ss.str());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_AMMO_ID));
ss.str("");
for (uint32 i = 0; i < KNOWN_TITLES_SIZE*2; ++i)
ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i) << ' ';
-
stmt->setString(index++, ss.str());
+
stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, 2));
stmt->setUInt32(index++, m_grantableLevels);
}
@@ -19278,7 +19452,7 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, getGender());
stmt->setUInt8(index++, getLevel());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP));
- stmt->setUInt32(index++, GetMoney());
+ stmt->setUInt64(index++, GetMoney());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES_2));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS));
@@ -19324,8 +19498,13 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0));
//save, far from tavern/city
//save, but in tavern/city
- stmt->setUInt32(index++, m_resetTalentsCost);
- stmt->setUInt32(index++, uint32(m_resetTalentsTime));
+ stmt->setUInt32(index++, GetTalentResetCost());
+ stmt->setUInt32(index++, GetTalentResetTime());
+
+ ss.str("");
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ ss << GetPrimaryTalentTree(i) << " ";
+ stmt->setString(index++, ss.str());
stmt->setUInt16(index++, (uint16)m_ExtraFlags);
stmt->setUInt8(index++, m_stableSlots);
stmt->setUInt16(index++, (uint16)m_atLoginFlags);
@@ -19336,26 +19515,32 @@ void Player::SaveToDB(bool create /*=false*/)
ss << m_taxi.SaveTaxiDestinationsToString();
stmt->setString(index++, ss.str());
- stmt->setUInt32(index++, GetArenaPoints());
- stmt->setUInt32(index++, GetHonorPoints());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION));
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS));
stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 0));
stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 1));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_CHOSEN_TITLE));
- stmt->setUInt64(index++, GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX));
stmt->setUInt8(index++, GetDrunkValue());
stmt->setUInt32(index++, GetHealth());
+ uint32 storedPowers = 0;
for (uint32 i = 0; i < MAX_POWERS; ++i)
- stmt->setUInt32(index++, GetPower(Powers(i)));
+ {
+ if (GetPowerIndex(i) != MAX_POWERS)
+ {
+ stmt->setUInt32(index++, GetUInt32Value(UNIT_FIELD_POWER1 + storedPowers));
+ if (++storedPowers >= MAX_POWERS_PER_CLASS)
+ break;
+ }
+ }
+
+ for (; storedPowers < MAX_POWERS_PER_CLASS; ++storedPowers)
+ stmt->setUInt32(index++, 0);
stmt->setUInt32(index++, GetSession()->GetLatency());
- stmt->setUInt8(index++, m_specsCount);
- stmt->setUInt8(index++, m_activeSpec);
+ stmt->setUInt8(index++, GetSpecsCount());
+ stmt->setUInt8(index++, GetActiveSpec());
ss.str("");
for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i)
@@ -19378,7 +19563,6 @@ void Player::SaveToDB(bool create /*=false*/)
}
stmt->setString(index++, ss.str());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_AMMO_ID));
ss.str("");
for (uint32 i = 0; i < KNOWN_TITLES_SIZE*2; ++i)
@@ -19402,6 +19586,7 @@ void Player::SaveToDB(bool create /*=false*/)
_SaveBGData(trans);
_SaveInventory(trans);
+ _SaveVoidStorage(trans);
_SaveQuestStatus(trans);
_SaveDailyQuestStatus(trans);
_SaveWeeklyQuestStatus(trans);
@@ -19419,6 +19604,8 @@ void Player::SaveToDB(bool create /*=false*/)
GetSession()->SaveTutorialsData(trans); // changed only while character in game
_SaveGlyphs(trans);
_SaveInstanceTimeRestrictions(trans);
+ _SaveCurrency(trans);
+ _SaveCUFProfiles(trans);
// check if stats should only be saved on logout
// save stats can be out of transaction
@@ -19436,13 +19623,14 @@ void Player::SaveToDB(bool create /*=false*/)
void Player::SaveInventoryAndGoldToDB(SQLTransaction& trans)
{
_SaveInventory(trans);
+ _SaveCurrency(trans);
SaveGoldToDB(trans);
}
void Player::SaveGoldToDB(SQLTransaction& trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_MONEY);
- stmt->setUInt32(0, GetMoney());
+ stmt->setUInt64(0, GetMoney());
stmt->setUInt32(1, GetGUIDLow());
trans->Append(stmt);
}
@@ -19458,7 +19646,7 @@ void Player::_SaveActions(SQLTransaction& trans)
case ACTIONBUTTON_NEW:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACTION);
stmt->setUInt32(0, GetGUIDLow());
- stmt->setUInt8(1, m_activeSpec);
+ stmt->setUInt8(1, GetActiveSpec());
stmt->setUInt8(2, itr->first);
stmt->setUInt32(3, itr->second.GetAction());
stmt->setUInt8(4, uint8(itr->second.GetType()));
@@ -19473,7 +19661,7 @@ void Player::_SaveActions(SQLTransaction& trans)
stmt->setUInt8(1, uint8(itr->second.GetType()));
stmt->setUInt32(2, GetGUIDLow());
stmt->setUInt8(3, itr->first);
- stmt->setUInt8(4, m_activeSpec);
+ stmt->setUInt8(4, GetActiveSpec());
trans->Append(stmt);
itr->second.uState = ACTIONBUTTON_UNCHANGED;
@@ -19483,7 +19671,7 @@ void Player::_SaveActions(SQLTransaction& trans)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC);
stmt->setUInt32(0, GetGUIDLow());
stmt->setUInt8(1, itr->first);
- stmt->setUInt8(2, m_activeSpec);
+ stmt->setUInt8(2, GetActiveSpec());
trans->Append(stmt);
m_actionButtons.erase(itr++);
@@ -19642,7 +19830,7 @@ void Player::_SaveInventory(SQLTransaction& trans)
// save all changes to the item...
if (item->GetState() != ITEM_NEW) // only for existing items, no dupes
item->SaveToDB(trans);
- // ...but do not save position in invntory
+ // ...but do not save position in inventory
continue;
}
}
@@ -19671,6 +19859,76 @@ void Player::_SaveInventory(SQLTransaction& trans)
m_itemUpdateQueue.clear();
}
+void Player::_SaveVoidStorage(SQLTransaction& trans)
+{
+ PreparedStatement* stmt = NULL;
+ uint32 lowGuid = GetGUIDLow();
+
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ {
+ if (!_voidStorageItems[i]) // unused item
+ {
+ // DELETE FROM void_storage WHERE slot = ? AND playerGuid = ?
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT);
+ stmt->setUInt8(0, i);
+ stmt->setUInt32(1, lowGuid);
+ }
+ else
+ {
+ // REPLACE INTO character_inventory (itemId, playerGuid, itemEntry, slot, creatorGuid) VALUES (?, ?, ?, ?, ?)
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHAR_VOID_STORAGE_ITEM);
+ stmt->setUInt64(0, _voidStorageItems[i]->ItemId);
+ stmt->setUInt32(1, lowGuid);
+ stmt->setUInt32(2, _voidStorageItems[i]->ItemEntry);
+ stmt->setUInt8(3, i);
+ stmt->setUInt32(4, _voidStorageItems[i]->CreatorGuid);
+ stmt->setUInt32(5, _voidStorageItems[i]->ItemRandomPropertyId);
+ stmt->setUInt32(6, _voidStorageItems[i]->ItemSuffixFactor);
+ }
+
+ trans->Append(stmt);
+ }
+}
+
+
+void Player::_SaveCUFProfiles(SQLTransaction& trans)
+{
+ PreparedStatement* stmt = NULL;
+ uint32 lowGuid = GetGUIDLow();
+
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ {
+ if (!_CUFProfiles[i]) // unused profile
+ {
+ // DELETE FROM character_cuf_profiles WHERE guid = ? and id = ?
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_CUF_PROFILES);
+ stmt->setUInt32(0, lowGuid);
+ stmt->setUInt8(1, i);
+ }
+ else
+ {
+ // REPLACE INTO character_cuf_profiles (guid, id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHAR_CUF_PROFILES);
+ stmt->setUInt32(0, lowGuid);
+ stmt->setUInt8(1, i);
+ stmt->setString(2, _CUFProfiles[i]->ProfileName);
+ stmt->setUInt16(3, _CUFProfiles[i]->FrameHeight);
+ stmt->setUInt16(4, _CUFProfiles[i]->FrameWidth);
+ stmt->setUInt8(5, _CUFProfiles[i]->SortBy);
+ stmt->setUInt8(6, _CUFProfiles[i]->HealthText);
+ stmt->setUInt32(7, _CUFProfiles[i]->BoolOptions.to_ulong()); // 27 of 32 fields used, fits in an int
+ stmt->setUInt8(8, _CUFProfiles[i]->Unk146);
+ stmt->setUInt8(9, _CUFProfiles[i]->Unk147);
+ stmt->setUInt8(10, _CUFProfiles[i]->Unk148);
+ stmt->setUInt16(11, _CUFProfiles[i]->Unk150);
+ stmt->setUInt16(12, _CUFProfiles[i]->Unk152);
+ stmt->setUInt16(13, _CUFProfiles[i]->Unk154);
+ }
+
+ trans->Append(stmt);
+ }
+}
+
void Player::_SaveMail(SQLTransaction& trans)
{
if (!m_mailsLoaded)
@@ -19955,9 +20213,11 @@ void Player::_SaveSkills(SQLTransaction& trans)
continue;
}
- uint32 valueData = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos));
- uint16 value = SKILL_VALUE(valueData);
- uint16 max = SKILL_MAX(valueData);
+ uint16 field = itr->second.pos / 2;
+ uint8 offset = itr->second.pos & 1;
+
+ uint16 value = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset);
+ uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset);
switch (itr->second.uState)
{
@@ -19968,7 +20228,6 @@ void Player::_SaveSkills(SQLTransaction& trans)
stmt->setUInt16(2, value);
stmt->setUInt16(3, max);
trans->Append(stmt);
-
break;
case SKILL_CHANGED:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_SKILLS);
@@ -19977,13 +20236,12 @@ void Player::_SaveSkills(SQLTransaction& trans)
stmt->setUInt32(2, GetGUIDLow());
stmt->setUInt16(3, uint16(itr->first));
trans->Append(stmt);
-
break;
default:
break;
}
- itr->second.uState = SKILL_UNCHANGED;
+ itr->second.uState = SKILL_UNCHANGED;
++itr;
}
}
@@ -20046,7 +20304,7 @@ void Player::_SaveStats(SQLTransaction& trans)
stmt->setUInt32(index++, GetGUIDLow());
stmt->setUInt32(index++, GetMaxHealth());
- for (uint8 i = 0; i < MAX_POWERS; ++i)
+ for (uint8 i = 0; i < MAX_POWERS_PER_CLASS; ++i)
stmt->setUInt32(index++, GetMaxPower(Powers(i)));
for (uint8 i = 0; i < MAX_STATS; ++i)
@@ -20064,7 +20322,7 @@ void Player::_SaveStats(SQLTransaction& trans)
stmt->setUInt32(index++, GetUInt32Value(UNIT_FIELD_ATTACK_POWER));
stmt->setUInt32(index++, GetUInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER));
stmt->setUInt32(index++, GetBaseSpellPowerBonus());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_CRIT_TAKEN_SPELL));
+ stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_RESILIENCE_PLAYER_DAMAGE_TAKEN));
trans->Append(stmt);
}
@@ -20152,15 +20410,15 @@ void Player::SavePositionInDB(uint32 mapid, float x, float y, float z, float o,
CharacterDatabase.Execute(stmt);
}
-void Player::SetUInt32ValueInArray(Tokenizer& tokens, uint16 index, uint32 value)
+void Player::SetUInt32ValueInArray(Tokenizer& Tokenizer, uint16 index, uint32 value)
{
char buf[11];
snprintf(buf, 11, "%u", value);
- if (index >= tokens.size())
+ if (index >= Tokenizer.size())
return;
- tokens[index] = buf;
+ Tokenizer[index] = buf;
}
void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair)
@@ -20247,10 +20505,9 @@ void Player::SendRaidDifficulty(bool IsInGroup, int32 forcedDifficulty)
GetSession()->SendPacket(&data);
}
-void Player::SendResetFailedNotify(uint32 mapid)
+void Player::SendResetFailedNotify(uint32 /*mapid*/)
{
WorldPacket data(SMSG_RESET_FAILED_NOTIFY, 4);
- data << uint32(mapid);
GetSession()->SendPacket(&data);
}
@@ -20317,7 +20574,7 @@ void Player::SendResetInstanceFailed(uint32 reason, uint32 MapId)
// 1: There are players offline in your party.
// 2>: There are players in your party attempting to zone into an instance.
*/
- WorldPacket data(SMSG_INSTANCE_RESET_FAILED, 4);
+ WorldPacket data(SMSG_INSTANCE_RESET_FAILED, 8);
data << uint32(reason);
data << uint32(MapId);
GetSession()->SendPacket(&data);
@@ -20542,12 +20799,25 @@ void Player::TextEmote(const std::string& text)
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, !GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT));
}
+void Player::WhisperAddon(const std::string& text, const std::string& prefix, Player* receiver)
+{
+ std::string _text(text);
+ sScriptMgr->OnPlayerChat(this, CHAT_MSG_WHISPER, uint32(LANG_ADDON), _text, receiver);
+
+ if (!receiver->GetSession()->IsAddonRegistered(prefix))
+ return;
+
+ WorldPacket data;
+ ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, LANG_ADDON, this, this, text, 0, "", DEFAULT_LOCALE, prefix);
+ receiver->GetSession()->SendPacket(&data);
+}
+
void Player::Whisper(const std::string& text, uint32 language, uint64 receiver)
{
bool isAddonMessage = language == LANG_ADDON;
- if (!isAddonMessage) // if not addon data
- language = LANG_UNIVERSAL; // whispers should always be readable
+ if (!isAddonMessage) // if not addon data
+ language = LANG_UNIVERSAL; // whispers should always be readable
Player* rPlayer = ObjectAccessor::FindPlayer(receiver);
@@ -20877,33 +21147,37 @@ bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod
void Player::AddSpellMod(SpellModifier* mod, bool apply)
{
TC_LOG_DEBUG("spells", "Player::AddSpellMod %d", mod->spellId);
- uint16 Opcode = (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER;
+ Opcodes opcode = Opcodes((mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER);
int i = 0;
flag96 _mask = 0;
+ uint32 modTypeCount = 0; // count of mods per one mod->op
+ WorldPacket data(opcode);
+ data << uint32(1); // count of different mod->op's in packet
+ size_t writePos = data.wpos();
+ data << uint32(modTypeCount);
+ data << uint8(mod->op);
for (int eff = 0; eff < 96; ++eff)
{
- if (eff != 0 && eff%32 == 0)
+ if (eff != 0 && (eff % 32) == 0)
_mask[i++] = 0;
- _mask[i] = uint32(1) << (eff-(32*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)
val += (*itr)->value;
- }
val += apply ? mod->value : -(mod->value);
- WorldPacket data(Opcode, (1+1+4));
+
data << uint8(eff);
- data << uint8(mod->op);
- data << int32(val);
- SendDirectMessage(&data);
+ data << float(val);
+ ++modTypeCount;
}
}
-
+ data.put<uint32>(writePos, modTypeCount);
+ SendDirectMessage(&data);
if (apply)
m_spellMods[mod->op].push_back(mod);
else
@@ -21330,7 +21604,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
return false;
}
- uint32 money = GetMoney();
+ uint64 money = GetMoney();
if (npc)
totalcost = (uint32)ceil(totalcost*GetReputationPriceDiscount(npc));
@@ -21343,7 +21617,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
}
//Checks and preparations done, DO FLIGHT
- ModifyMoney(-(int32)totalcost);
+ ModifyMoney(-int64(totalcost));
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1);
@@ -21487,7 +21761,7 @@ void Player::InitDataForForm(bool reapplyMods)
{
ShapeshiftForm form = GetShapeshiftForm();
- SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(form);
+ SpellShapeshiftFormEntry const* ssEntry = sSpellShapeshiftFormStore.LookupEntry(form);
if (ssEntry && ssEntry->attackSpeed)
{
SetAttackTime(BASE_ATTACK, ssEntry->attackSpeed);
@@ -21507,7 +21781,6 @@ void Player::InitDataForForm(bool reapplyMods)
break;
}
case FORM_BEAR:
- case FORM_DIREBEAR:
{
if (getPowerType() != POWER_RAGE)
setPowerType(POWER_RAGE);
@@ -21558,10 +21831,11 @@ void Player::InitDisplayIds()
inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot, int32 price, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore)
{
+ uint32 stacks = count / pProto->BuyCount;
ItemPosCountVec vDest;
uint16 uiDest = 0;
InventoryResult msg = bStore ?
- CanStoreNewItem(bag, slot, vDest, item, pProto->BuyCount * count) :
+ CanStoreNewItem(bag, slot, vDest, item, count) :
CanEquipNewItem(slot, uiDest, item, false);
if (msg != EQUIP_ERR_OK)
{
@@ -21571,20 +21845,23 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
ModifyMoney(-price);
- if (crItem->ExtendedCost) // case for new honor system
+ if (crItem->ExtendedCost) // case for new honor system
{
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
ASSERT(iece);
- if (iece->reqhonorpoints)
- ModifyHonorPoints(-int32(iece->reqhonorpoints * count));
-
- if (iece->reqarenapoints)
- ModifyArenaPoints(-int32(iece->reqarenapoints * count));
+ for (int i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
+ {
+ if (iece->RequiredItem[i])
+ DestroyItemCount(iece->RequiredItem[i], iece->RequiredItemCount[i] * stacks, true);
+ }
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i)
+ for (int i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
{
- if (iece->reqitem[i])
- DestroyItemCount(iece->reqitem[i], (iece->reqitemcount[i] * count), true);
+ if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i))
+ continue;
+
+ if (iece->RequiredCurrency[i])
+ ModifyCurrency(iece->RequiredCurrency[i], -int32(iece->RequiredCurrencyCount[i] * stacks), true, true);
}
}
@@ -21593,7 +21870,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
EquipNewItem(uiDest, item, true);
if (it)
{
- uint32 new_count = pVendor->UpdateVendorItemCurrentCount(crItem, pProto->BuyCount * count);
+ uint32 new_count = pVendor->UpdateVendorItemCurrentCount(crItem, count);
WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4));
data << uint64(pVendor->GetGUID());
@@ -21601,7 +21878,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
data << int32(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
data << uint32(count);
GetSession()->SendPacket(&data);
- SendNewItem(it, pProto->BuyCount * count, true, false, false);
+ SendNewItem(it, count, true, false, false);
if (!bStore)
AutoUnequipOffhandIfNeed();
@@ -21619,6 +21896,165 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
return true;
}
+bool Player::BuyCurrencyFromVendorSlot(uint64 vendorGuid, uint32 vendorSlot, uint32 currency, uint32 count)
+{
+ // cheating attempt
+ if (count < 1) count = 1;
+
+ if (!IsAlive())
+ return false;
+
+ CurrencyTypesEntry const* proto = sCurrencyTypesStore.LookupEntry(currency);
+ if (!proto)
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, currency, 0);
+ return false;
+ }
+
+ Creature* creature = GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR);
+ if (!creature)
+ {
+ TC_LOG_DEBUG("network", "WORLD: BuyCurrencyFromVendorSlot - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(vendorGuid));
+ SendBuyError(BUY_ERR_DISTANCE_TOO_FAR, NULL, currency, 0);
+ return false;
+ }
+
+ VendorItemData const* vItems = creature->GetVendorItems();
+ if (!vItems || vItems->Empty())
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, currency, 0);
+ return false;
+ }
+
+ if (vendorSlot >= vItems->GetItemCount())
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, currency, 0);
+ return false;
+ }
+
+ VendorItem const* crItem = vItems->GetItem(vendorSlot);
+ // store diff item (cheating)
+ if (!crItem || crItem->item != currency || crItem->Type != ITEM_VENDOR_TYPE_CURRENCY)
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, currency, 0);
+ return false;
+ }
+
+ if (count % crItem->maxcount)
+ {
+ SendEquipError(EQUIP_ERR_CANT_BUY_QUANTITY, NULL, NULL);
+ return false;
+ }
+
+ uint32 stacks = count / crItem->maxcount;
+ ItemExtendedCostEntry const* iece = NULL;
+ if (crItem->ExtendedCost)
+ {
+ iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
+ if (!iece)
+ {
+ TC_LOG_ERROR("entities.player", "Currency %u have wrong ExtendedCost field value %u", currency, crItem->ExtendedCost);
+ return false;
+ }
+
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i)
+ {
+ if (iece->RequiredItem[i] && !HasItemCount(iece->RequiredItem[i], (iece->RequiredItemCount[i] * stacks)))
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL);
+ return false;
+ }
+ }
+
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
+ {
+ if (!iece->RequiredCurrency[i])
+ continue;
+
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(iece->RequiredCurrency[i]);
+ if (!entry)
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, currency, 0); // Find correct error
+ return false;
+ }
+
+ if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i))
+ {
+ // Not implemented
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error
+ return false;
+ }
+ else if (!HasCurrency(iece->RequiredCurrency[i], (iece->RequiredCurrencyCount[i] * stacks)))
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error
+ return false;
+ }
+ }
+
+ // check for personal arena rating requirement
+ if (GetMaxPersonalArenaRatingRequirement(iece->RequiredArenaSlot) < iece->RequiredPersonalArenaRating)
+ {
+ // probably not the proper equip err
+ SendEquipError(EQUIP_ERR_CANT_EQUIP_RANK, NULL, NULL);
+ return false;
+ }
+
+ if (iece->RequiredFactionId && uint32(GetReputationRank(iece->RequiredFactionId)) < iece->RequiredFactionStanding)
+ {
+ SendBuyError(BUY_ERR_REPUTATION_REQUIRE, creature, currency, 0);
+ return false;
+ }
+
+ if (iece->RequirementFlags & ITEM_EXT_COST_FLAG_REQUIRE_GUILD && !GetGuildId())
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error
+ return false;
+ }
+
+ if (iece->RequiredGuildLevel && iece->RequiredGuildLevel < GetGuildLevel())
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error
+ return false;
+ }
+
+ if (iece->RequiredAchievement && !HasAchieved(iece->RequiredAchievement))
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error
+ return false;
+ }
+ }
+ else // currencies have no price defined, can only be bought with ExtendedCost
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, currency, 0);
+ return false;
+ }
+
+ ModifyCurrency(currency, count, true, true);
+ if (iece)
+ {
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i)
+ {
+ if (!iece->RequiredItem[i])
+ continue;
+
+ DestroyItemCount(iece->RequiredItem[i], iece->RequiredItemCount[i] * stacks, true);
+ }
+
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
+ {
+ if (!iece->RequiredCurrency[i])
+ continue;
+
+ if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i))
+ continue;
+
+ ModifyCurrency(iece->RequiredCurrency[i], -int32(iece->RequiredCurrencyCount[i]) * stacks, false, true);
+ }
+ }
+
+ return true;
+}
+
// Return true is the bought item has a max count to force refresh of window by caller
bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot)
{
@@ -21703,31 +22139,48 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
if (crItem->ExtendedCost)
{
- ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
- if (!iece)
+ // Can only buy full stacks for extended cost
+ if (count % pProto->BuyCount)
{
- TC_LOG_ERROR("entities.player", "Item %u have wrong ExtendedCost field value %u", pProto->ItemId, crItem->ExtendedCost);
+ SendEquipError(EQUIP_ERR_CANT_BUY_QUANTITY, NULL, NULL);
return false;
}
- // honor points price
- if (GetHonorPoints() < (iece->reqhonorpoints * count))
+ uint32 stacks = count / pProto->BuyCount;
+ ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
+ if (!iece)
{
- SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL);
+ TC_LOG_ERROR("entities.player", "Item %u have wrong ExtendedCost field value %u", pProto->ItemId, crItem->ExtendedCost);
return false;
}
- // arena points price
- if (GetArenaPoints() < (iece->reqarenapoints * count))
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i)
{
- SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL);
- return false;
+ if (iece->RequiredItem[i] && !HasItemCount(iece->RequiredItem[i], iece->RequiredItemCount[i] * stacks))
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL);
+ return false;
+ }
}
- // item base price
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i)
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
{
- if (iece->reqitem[i] && !HasItemCount(iece->reqitem[i], (iece->reqitemcount[i] * count)))
+ if (!iece->RequiredCurrency[i])
+ continue;
+
+ CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(iece->RequiredCurrency[i]);
+ if (!entry)
+ {
+ SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, item, 0);
+ return false;
+ }
+
+ if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i))
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error
+ return false;
+ }
+ else if (!HasCurrency(iece->RequiredCurrency[i], iece->RequiredCurrencyCount[i] * stacks))
{
SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL);
return false;
@@ -21735,12 +22188,36 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
}
// check for personal arena rating requirement
- if (GetMaxPersonalArenaRatingRequirement(iece->reqarenaslot) < iece->reqpersonalarenarating)
+ if (GetMaxPersonalArenaRatingRequirement(iece->RequiredArenaSlot) < iece->RequiredPersonalArenaRating)
{
// probably not the proper equip err
SendEquipError(EQUIP_ERR_CANT_EQUIP_RANK, NULL, NULL);
return false;
}
+
+ if (iece->RequiredFactionId && uint32(GetReputationRank(iece->RequiredFactionId)) < iece->RequiredFactionStanding)
+ {
+ SendBuyError(BUY_ERR_REPUTATION_REQUIRE, creature, item, 0);
+ return false;
+ }
+
+ if (iece->RequirementFlags & ITEM_EXT_COST_FLAG_REQUIRE_GUILD && !GetGuildId())
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error
+ return false;
+ }
+
+ if (iece->RequiredGuildLevel && iece->RequiredGuildLevel < GetGuildLevel())
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error
+ return false;
+ }
+
+ if (iece->RequiredAchievement && !HasAchieved(iece->RequiredAchievement))
+ {
+ SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error
+ return false;
+ }
}
uint32 price = 0;
@@ -21757,7 +22234,10 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
// reputation discount
price = uint32(floor(price * GetReputationPriceDiscount(creature)));
- if (!HasEnoughMoney(price))
+ if (int32 priceMod = GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES))
+ price -= CalculatePct(price, priceMod);
+
+ if (!HasEnoughMoney(uint64(price)))
{
SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, item, 0);
return false;
@@ -21771,9 +22251,9 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
}
else if (IsEquipmentPos(bag, slot))
{
- if (pProto->BuyCount * count != 1)
+ if (count != 1)
{
- SendEquipError(EQUIP_ERR_ITEM_CANT_BE_EQUIPPED, NULL, NULL);
+ SendEquipError(EQUIP_ERR_NOT_EQUIPPABLE, NULL, NULL);
return false;
}
if (!_StoreOrEquipNewItem(vendorslot, item, count, bag, slot, price, pProto, creature, crItem, false))
@@ -21781,11 +22261,19 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
}
else
{
- SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL);
+ SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
return false;
}
- return crItem->maxcount != 0;
+ if (crItem->maxcount != 0) // bought
+ {
+ if (pProto->Quality > ITEM_QUALITY_EPIC || (pProto->Quality == ITEM_QUALITY_EPIC && pProto->ItemLevel >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)]))
+ if (Guild* guild = GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_ITEM_PURCHASED, GetGUID(), 0, item);
+ return true;
+ }
+
+ return false;
}
uint32 Player::GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot) const
@@ -21992,9 +22480,35 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
}
}
+ // Apply SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN modifiers
+ // Note: This aura applies its modifiers to all cooldowns of spells with set category, not to category cooldown only
+ if (cat)
+ {
+ if (int32 categoryModifier = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN, cat))
+ {
+ if (rec > 0)
+ rec += categoryModifier;
+
+ if (catrec > 0)
+ catrec += categoryModifier;
+ }
+
+ SpellCategoryEntry const* categoryEntry = sSpellCategoryStore.LookupEntry(cat);
+ ASSERT(categoryEntry);
+ if (categoryEntry->Flags & SPELL_CATEGORY_FLAG_COOLDOWN_EXPIRES_AT_MIDNIGHT)
+ {
+ tm date;
+ localtime_r(&curTime, &date);
+ catrec = catrec * DAY - (date.tm_hour * HOUR + date.tm_min * MINUTE + date.tm_sec) * IN_MILLISECONDS;
+ }
+ }
+
// replace negative cooldowns by 0
- if (rec < 0) rec = 0;
- if (catrec < 0) catrec = 0;
+ if (rec < 0)
+ rec = 0;
+
+ if (catrec < 0)
+ catrec = 0;
// no cooldown after applying spell mods
if (rec == 0 && catrec == 0)
@@ -22099,15 +22613,15 @@ void Player::UpdatePotionCooldown(Spell* spell)
m_lastPotionId = 0;
}
-void Player::setResurrectRequestData(uint64 guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana)
+void Player::SetResurrectRequestData(Unit* caster, uint32 health, uint32 mana, uint32 appliedAura)
{
- m_resurrectGUID = guid;
- m_resurrectMap = mapId;
- m_resurrectX = X;
- m_resurrectY = Y;
- m_resurrectZ = Z;
- m_resurrectHealth = health;
- m_resurrectMana = mana;
+ ASSERT(!IsResurrectRequested());
+ _resurrectionData = new ResurrectionData();
+ _resurrectionData->GUID = caster->GetGUID();
+ _resurrectionData->Location.WorldRelocate(*caster);
+ _resurrectionData->Health = health;
+ _resurrectionData->Mana = mana;
+ _resurrectionData->Aura = appliedAura;
}
//slot to be excluded while counting
bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot)
@@ -22553,7 +23067,7 @@ void Player::UpdateTriggerVisibility()
if (!IsInWorld())
return;
- UpdateData udata;
+ UpdateData udata(GetMapId());
WorldPacket packet;
for (ClientGUIDs::iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
{
@@ -22658,7 +23172,7 @@ void Player::InitPrimaryProfessions()
SetFreePrimaryProfessions(sWorld->getIntConfig(CONFIG_MAX_PRIMARY_TRADE_SKILL));
}
-bool Player::ModifyMoney(int32 amount, bool sendError /*= true*/)
+bool Player::ModifyMoney(int64 amount, bool sendError /*= true*/)
{
if (!amount)
return true;
@@ -22666,10 +23180,10 @@ bool Player::ModifyMoney(int32 amount, bool sendError /*= true*/)
sScriptMgr->OnPlayerMoneyChanged(this, amount);
if (amount < 0)
- SetMoney (GetMoney() > uint32(-amount) ? GetMoney() + amount : 0);
+ SetMoney(GetMoney() > uint64(-amount) ? GetMoney() + amount : 0);
else
{
- if (GetMoney() < MAX_MONEY_AMOUNT - static_cast<uint32>(amount))
+ if (GetMoney() < MAX_MONEY_AMOUNT - static_cast<uint64>(amount))
SetMoney(GetMoney() + amount);
else
{
@@ -22682,16 +23196,16 @@ bool Player::ModifyMoney(int32 amount, bool sendError /*= true*/)
return true;
}
-bool Player::HasEnoughMoney(int32 amount) const
+bool Player::HasEnoughMoney(int64 amount) const
{
if (amount > 0)
- return (GetMoney() >= (uint32) amount);
+ return (GetMoney() >= (uint64) amount);
return true;
}
-void Player::SetMoney(uint32 value)
+void Player::SetMoney(uint64 value)
{
- SetUInt32Value(PLAYER_FIELD_COINAGE, value);
+ SetUInt64Value(PLAYER_FIELD_COINAGE, value);
MoneyChanged(value);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED);
}
@@ -22837,10 +23351,22 @@ void Player::SendInitialPacketsBeforeAddToMap()
SendTalentsInfoData(false);
- // SMSG_INSTANCE_DIFFICULTY
- data.Initialize(SMSG_INSTANCE_DIFFICULTY, 4+4);
+ data.Initialize(SMSG_WORLD_SERVER_INFO, 1 + 1 + 4 + 4);
+ data.WriteBit(0); // HasRestrictedLevel
+ data.WriteBit(0); // HasRestrictedMoney
+ data.WriteBit(0); // IneligibleForLoot
+ data.FlushBits();
+ //if (IneligibleForLoot)
+ // data << uint32(0); // EncounterMask
+
+ data << uint8(0); // IsOnTournamentRealm
+ //if (HasRestrictedMoney)
+ // data << uint32(100000); // RestrictedMoney (starter accounts)
+ //if (HasRestrictedLevel)
+ // data << uint32(20); // RestrictedLevel (starter accounts)
+
+ data << uint32(sWorld->GetNextWeeklyQuestsResetTime() - WEEK); // LastWeeklyReset (not instance reset)
data << uint32(GetMap()->GetDifficulty());
- data << uint32(GetMap()->GetEntry()->IsDynamicDifficultyMap() && GetMap()->IsHeroic()); // Raid dynamic difficulty
GetSession()->SendPacket(&data);
SendInitialSpells();
@@ -22851,7 +23377,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
SendInitialActionButtons();
m_reputationMgr->SendInitialReputations();
- m_achievementMgr->SendAllAchievementData();
+ m_achievementMgr->SendAllAchievementData(this);
SendEquipmentSetList();
@@ -22868,6 +23394,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
// SMSG_UPDATE_WORLD_STATE
// SMSG_POWER_UPDATE
+ SendCurrencies();
SetMover(this);
}
@@ -22883,6 +23410,8 @@ void Player::SendInitialPacketsAfterAddToMap()
ResetTimeSync();
SendTimeSync();
+ GetSession()->SendLoadCUFProfiles();
+
CastSpell(this, 836, true); // LOGINEFFECT
// set some aura effects that send packet to player client after add player to map
@@ -22902,16 +23431,11 @@ void Player::SendInitialPacketsAfterAddToMap()
}
if (HasAuraType(SPELL_AURA_MOD_STUN))
- SetMovement(MOVE_ROOT);
+ SetRooted(true);
// manual send package (have code in HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true); that must not be re-applied.
if (HasAuraType(SPELL_AURA_MOD_ROOT))
- {
- WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10);
- data2.append(GetPackGUID());
- data2 << (uint32)2;
- SendMessageToSet(&data2, true);
- }
+ SetRooted(true, true);
SendAurasForTarget(this);
SendEnchantmentDurations(); // must be after add to map
@@ -22947,18 +23471,8 @@ void Player::SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8
{
WorldPacket data(SMSG_TRANSFER_ABORTED, 4+2);
data << uint32(mapid);
- data << uint8(reason); // transfer abort reason
- switch (reason)
- {
- case TRANSFER_ABORT_INSUF_EXPAN_LVL:
- case TRANSFER_ABORT_DIFFICULTY:
- case TRANSFER_ABORT_UNIQUE_MESSAGE:
- // these are the ONLY cases that have an extra argument in the packet!!!
- data << uint8(arg);
- break;
- default:
- break;
- }
+ data << uint8(reason); // transfer abort reason
+ data << uint8(arg);
GetSession()->SendPacket(&data);
}
@@ -23382,6 +23896,7 @@ void Player::ResetWeeklyQuestStatus()
m_weeklyquests.clear();
// DB data deleted in caller
m_WeeklyQuestChanged = false;
+
}
void Player::ResetSeasonalQuestStatus(uint16 event_id)
@@ -23608,7 +24123,7 @@ void Player::UpdateForQuestWorldObjects()
if (m_clientGUIDs.empty())
return;
- UpdateData udata;
+ UpdateData udata(GetMapId());
WorldPacket packet;
for (ClientGUIDs::iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
{
@@ -23889,7 +24404,7 @@ uint32 Player::GetResurrectionSpellId()
}
// Used in triggers for check "Only to targets that grant experience or honor" req
-bool Player::isHonorOrXPTarget(Unit* victim) const
+bool Player::isHonorOrXPTarget(Unit const* victim) const
{
uint8 v_level = victim->getLevel();
uint8 k_grey = Trinity::XP::GetGrayLevel(getLevel());
@@ -23898,11 +24413,11 @@ bool Player::isHonorOrXPTarget(Unit* victim) const
if (v_level <= k_grey)
return false;
- if (victim->GetTypeId() == TYPEID_UNIT)
+ if (Creature const* const creature = victim->ToCreature())
{
- if (victim->ToCreature()->IsTotem() ||
- victim->ToCreature()->IsPet() ||
- victim->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)
+ if (creature->IsTotem() ||
+ creature->IsPet() ||
+ creature->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)
return false;
}
return true;
@@ -24009,23 +24524,12 @@ bool Player::IsAtRecruitAFriendDistance(WorldObject const* pOther) const
return pOther->GetDistance(player) <= sWorld->getFloatConfig(CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE);
}
-uint32 Player::GetBaseWeaponSkillValue(WeaponAttackType attType) const
-{
- Item* item = GetWeaponForAttack(attType, true);
-
- // unarmed only with base attack
- if (attType != BASE_ATTACK && !item)
- return 0;
-
- // weapon skill or (unarmed for base attack)
- uint32 skill = item ? item->GetSkill() : uint32(SKILL_UNARMED);
- return GetBaseSkillValue(skill);
-}
-
void Player::ResurrectUsingRequestData()
{
/// Teleport before resurrecting by player, otherwise the player might get attacked from creatures near his corpse
- TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation());
+ float x, y, z, o;
+ _resurrectionData->Location.GetPosition(x, y, z, o);
+ TeleportTo(_resurrectionData->Location.GetMapId(), x, y, z, o);
if (IsBeingTeleported())
{
@@ -24035,19 +24539,23 @@ void Player::ResurrectUsingRequestData()
ResurrectPlayer(0.0f, false);
- if (GetMaxHealth() > m_resurrectHealth)
- SetHealth(m_resurrectHealth);
+ if (GetMaxHealth() > _resurrectionData->Health)
+ SetHealth(_resurrectionData->Health);
else
SetFullHealth();
- if (GetMaxPower(POWER_MANA) > m_resurrectMana)
- SetPower(POWER_MANA, m_resurrectMana);
+ if (uint32(GetMaxPower(POWER_MANA)) > _resurrectionData->Mana)
+ SetPower(POWER_MANA, _resurrectionData->Mana);
else
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
SetPower(POWER_RAGE, 0);
-
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
+ SetPower(POWER_FOCUS, GetMaxPower(POWER_FOCUS));
+ SetPower(POWER_ECLIPSE, 0);
+
+ if (uint32 aura = _resurrectionData->Aura)
+ CastSpell(this, aura, true, NULL, NULL, _resurrectionData->GUID);
SpawnCorpseBones();
}
@@ -24071,6 +24579,29 @@ void Player::SetMover(Unit* target)
m_mover->m_movedPlayer = NULL;
m_mover = target;
m_mover->m_movedPlayer = this;
+
+ ObjectGuid guid = target->GetGUID();
+
+ WorldPacket data(SMSG_MOVE_SET_ACTIVE_MOVER, 9);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
+
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[4]);
+
+ SendDirectMessage(&data);
}
void Player::UpdateZoneDependentAuras(uint32 newZone)
@@ -24551,32 +25082,27 @@ uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 n
void Player::InitGlyphsForLevel()
{
- for (uint32 i = 0; i < sGlyphSlotStore.GetNumRows(); ++i)
+ uint32 slot = 0;
+ for (uint32 i = 0; i < sGlyphSlotStore.GetNumRows() && slot < MAX_GLYPH_SLOT_INDEX; ++i)
if (GlyphSlotEntry const* gs = sGlyphSlotStore.LookupEntry(i))
- if (gs->Order)
- SetGlyphSlot(gs->Order - 1, gs->Id);
+ SetGlyphSlot(slot++, gs->Id);
uint8 level = getLevel();
- uint32 value = 0;
+ uint32 slotMask = 0;
- // 0x3F = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 for 80 level
- if (level >= 15)
- value |= (0x01 | 0x02);
- if (level >= 30)
- value |= 0x08;
+ if (level >= 25)
+ slotMask |= 0x01 | 0x02 | 0x40;
if (level >= 50)
- value |= 0x04;
- if (level >= 70)
- value |= 0x10;
- if (level >= 80)
- value |= 0x20;
+ slotMask |= 0x04 | 0x08 | 0x80;
+ if (level >= 75)
+ slotMask |= 0x10 | 0x20 | 0x100;
- SetUInt32Value(PLAYER_GLYPHS_ENABLED, value);
+ SetUInt32Value(PLAYER_GLYPHS_ENABLED, slotMask);
}
void Player::SetGlyph(uint8 slot, uint32 glyph)
{
- m_Glyphs[m_activeSpec][slot] = glyph;
+ _talentMgr->SpecInfo[GetActiveSpec()].Glyphs[slot] = glyph;
SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph);
}
@@ -24686,17 +25212,25 @@ void Player::UpdateCharmedAI()
}
}
-uint32 Player::GetRuneBaseCooldown(uint8 index)
+uint32 Player::GetRuneTypeBaseCooldown(RuneType runeType) const
{
- uint8 rune = GetBaseRune(index);
- uint32 cooldown = RUNE_BASE_COOLDOWN;
+ float cooldown = RUNE_BASE_COOLDOWN;
+ float hastePct = 0.0f;
AuraEffectList const& regenAura = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
for (AuraEffectList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i)
- {
- if ((*i)->GetMiscValue() == POWER_RUNE && (*i)->GetMiscValueB() == rune)
- cooldown = cooldown*(100-(*i)->GetAmount())/100;
- }
+ if ((*i)->GetMiscValue() == POWER_RUNES && (*i)->GetMiscValueB() == runeType)
+ cooldown *= 1.0f - (*i)->GetAmount() / 100.0f;
+
+ // Runes cooldown are now affected by player's haste from equipment ...
+ hastePct = GetRatingBonusValue(CR_HASTE_MELEE);
+
+ // ... and some auras.
+ hastePct += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_HASTE);
+ hastePct += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_HASTE_2);
+ hastePct += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_HASTE_3);
+
+ cooldown *= 1.0f - (hastePct / 100.0f);
return cooldown;
}
@@ -24807,7 +25341,7 @@ void Player::InitRunes()
}
for (uint8 i = 0; i < NUM_RUNE_TYPES; ++i)
- SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f);
+ SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f); // set a base regen timer equal to 10 sec
}
bool Player::IsBaseRuneSlotsOnCooldown(RuneType runeType) const
@@ -24856,7 +25390,7 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
if (!item)
{
- SendEquipError(EQUIP_ERR_ALREADY_LOOTED, NULL, NULL);
+ SendEquipError(EQUIP_ERR_LOOT_GONE, NULL, NULL);
return;
}
@@ -24912,9 +25446,14 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
--loot->unlootedCount;
+ if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item->itemid))
+ if (proto->Quality > ITEM_QUALITY_EPIC || (proto->Quality == ITEM_QUALITY_EPIC && proto->ItemLevel >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)]))
+ if (Guild* guild = GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_ITEM_LOOTED, GetGUID(), 0, item->itemid);
+
SendNewItem(newitem, uint32(item->count), false, false, true);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, loot->loot_type, item->count);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, item->itemid, item->count, loot->loot_type);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item->itemid, item->count);
// LootItem is being removed (looted) from the container, delete it from the DB.
@@ -24928,16 +25467,30 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
uint32 Player::CalculateTalentsPoints() const
{
- uint32 base_talent = getLevel() < 10 ? 0 : getLevel()-9;
+ // this dbc file has entries only up to level 100
+ NumTalentsAtLevelEntry const* count = sNumTalentsAtLevelStore.LookupEntry(std::min<uint32>(getLevel(), 100));
+ if (!count)
+ return 0;
+
+ float baseForLevel = count->Talents;
if (getClass() != CLASS_DEATH_KNIGHT || GetMapId() != 609)
- return uint32(base_talent * sWorld->getRate(RATE_TALENT));
+ return uint32(baseForLevel * sWorld->getRate(RATE_TALENT));
- uint32 talentPointsForLevel = getLevel() < 56 ? 0 : getLevel() - 55;
- talentPointsForLevel += m_questRewardTalentCount;
+ // Death Knight starting level
+ // hardcoded here - number of quest awarded talents is equal to number of talents any other class would have at level 55
+ if (getLevel() < 55)
+ return 0;
- if (talentPointsForLevel > base_talent)
- talentPointsForLevel = base_talent;
+ NumTalentsAtLevelEntry const* dkBase = sNumTalentsAtLevelStore.LookupEntry(55);
+ if (!dkBase)
+ return 0;
+
+ float talentPointsForLevel = count->Talents - dkBase->Talents;
+ talentPointsForLevel += float(GetQuestRewardedTalentCount());
+
+ if (talentPointsForLevel > baseForLevel)
+ talentPointsForLevel = baseForLevel;
return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT));
}
@@ -24963,6 +25516,7 @@ void Player::_LoadSkills(PreparedQueryResult result)
// SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid));
uint32 count = 0;
+ uint8 professionCount = 0;
if (result)
{
do
@@ -25011,23 +25565,32 @@ void Player::_LoadSkills(PreparedQueryResult result)
continue;
}
- uint16 skillStep = 0;
- if (SkillTiersEntry const* skillTier = sSkillTiersStore.LookupEntry(rcEntry->SkillTier))
+ uint16 field = count / 2;
+ uint8 offset = count & 1;
+
+ SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, skill);
+ uint16 step = 0;
+
+ SkillLineEntry const* skillLine = sSkillLineStore.LookupEntry(rcEntry->SkillId);
+ if (skillLine)
{
- for (uint32 i = 0; i < MAX_SKILL_STEP; ++i)
+ if (skillLine->categoryId == SKILL_CATEGORY_SECONDARY)
+ step = max / 75;
+
+ if (skillLine->categoryId == SKILL_CATEGORY_PROFESSION)
{
- if (skillTier->MaxSkill[skillStep] == max)
- {
- skillStep = i + 1;
- break;
- }
+ step = max / 75;
+
+ if (professionCount < 2)
+ SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + professionCount++, skill);
}
}
- SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, skillStep));
-
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), MAKE_SKILL_VALUE(value, max));
- SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0);
+ SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step);
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, value);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, max);
+ SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0);
mSkillStatus.insert(SkillStatusMap::value_type(skill, SkillStatusData(count, SKILL_UNCHANGED)));
@@ -25046,32 +25609,19 @@ void Player::_LoadSkills(PreparedQueryResult result)
for (; count < PLAYER_MAX_SKILLS; ++count)
{
- SetUInt32Value(PLAYER_SKILL_INDEX(count), 0);
- SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), 0);
- SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0);
- }
+ uint16 field = count / 2;
+ uint8 offset = count & 1;
if (HasSkill(SKILL_FIST_WEAPONS))
SetSkill(SKILL_FIST_WEAPONS, 0, GetSkillValue(SKILL_UNARMED), GetMaxSkillValueForLevel());
-}
-uint32 Player::GetPhaseMaskForSpawn() const
-{
- uint32 phase = PHASEMASK_NORMAL;
- if (!IsGameMaster())
- phase = GetPhaseMask();
- else
- {
- AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE);
- if (!phases.empty())
- phase = phases.front()->GetMiscValue();
+ SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0);
+ SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0);
}
-
- // 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;
}
InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limit_count) const
@@ -25114,7 +25664,7 @@ InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8
{
// there is an equip limit on this item
if (HasItemOrGemWithIdEquipped(itemProto->ItemId, 1, except_slot))
- return EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE;
+ return EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE;
}
// check unique-equipped limit
@@ -25122,12 +25672,12 @@ InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8
{
ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(itemProto->ItemLimitCategory);
if (!limitEntry)
- return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+ return EQUIP_ERR_NOT_EQUIPPABLE;
// NOTE: limitEntry->mode not checked because if item have have-limit then it applied and to equip case
if (limit_count > limitEntry->maxCount)
- return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED;
+ return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS;
// there is an equip limit on this item
if (HasItemOrGemWithLimitCategoryEquipped(itemProto->ItemLimitCategory, limitEntry->maxCount - limit_count + 1, except_slot))
@@ -25147,7 +25697,7 @@ void Player::HandleFall(MovementInfo const& movementInfo)
{
// calculate total z distance of the fall
float z_diff = m_lastFallZ - movementInfo.pos.GetPositionZ();
- //TC_LOG_DEBUG("zDiff = %f", z_diff);
+ //TC_LOG_DEBUG("misc", "zDiff = %f", z_diff);
//Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored
// 14.57 can be calculated by resolving damageperc formula below to 0
@@ -25189,7 +25739,7 @@ void Player::HandleFall(MovementInfo const& movementInfo)
}
//Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction
- TC_LOG_DEBUG("entities.player", "FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d", movementInfo.pos.GetPositionZ(), height, GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall);
+ TC_LOG_DEBUG("entities.player", "FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d", movementInfo.pos.GetPositionZ(), height, GetPositionZ(), movementInfo.jump.fallTime, height, damage, safe_fall);
}
}
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // No fly zone - Parachute
@@ -25202,7 +25752,12 @@ void Player::ResetAchievements()
void Player::SendRespondInspectAchievements(Player* player) const
{
- m_achievementMgr->SendRespondInspectAchievements(player);
+ m_achievementMgr->SendAchievementInfo(player);
+}
+
+uint32 Player::GetAchievementPoints() const
+{
+ return m_achievementMgr->GetAchievementPoints();
}
bool Player::HasAchieved(uint32 achievementId) const
@@ -25220,44 +25775,54 @@ void Player::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 e
m_achievementMgr->RemoveTimedAchievement(type, entry);
}
-void Player::ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, bool evenIfCriteriaComplete /* = false*/)
+void Player::ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, bool evenIfCriteriaComplete /* = false*/)
{
m_achievementMgr->ResetAchievementCriteria(type, miscValue1, miscValue2, evenIfCriteriaComplete);
}
-void Player::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= NULL*/)
+void Player::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit* unit /*= NULL*/)
{
- m_achievementMgr->UpdateAchievementCriteria(type, miscValue1, miscValue2, unit);
+ m_achievementMgr->UpdateAchievementCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
+ Guild* guild = sGuildMgr->GetGuildById(GetGuildId());
+ if (!guild)
+ return;
+
+ // Update only individual achievement criteria here, otherwise we may get multiple updates
+ // from a single boss kill
+ if (sAchievementMgr->IsGroupCriteriaType(type))
+ return;
+
+ guild->UpdateAchievementCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
}
void Player::CompletedAchievement(AchievementEntry const* entry)
{
- m_achievementMgr->CompletedAchievement(entry);
+ m_achievementMgr->CompletedAchievement(entry, this);
}
-void Player::LearnTalent(uint32 talentId, uint32 talentRank)
+bool Player::LearnTalent(uint32 talentId, uint32 talentRank)
{
uint32 CurTalentPoints = GetFreeTalentPoints();
if (CurTalentPoints == 0)
- return;
+ return false;
if (talentRank >= MAX_TALENT_RANK)
- return;
+ return false;
TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId);
if (!talentInfo)
- return;
+ return false;
TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
if (!talentTabInfo)
- return;
+ return false;
// prevent learn talent for different class (cheating)
if ((getClassMask() & talentTabInfo->ClassMask) == 0)
- return;
+ return false;
// find current max talent rank (0~5)
uint8 curtalent_maxrank = 0; // 0 = not learned any rank
@@ -25272,11 +25837,11 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
// we already have same or higher talent rank learned
if (curtalent_maxrank >= (talentRank + 1))
- return;
+ return false;
// check if we have enough talent points
if (CurTalentPoints < (talentRank - curtalent_maxrank + 1))
- return;
+ return false;
// Check if it requires another talent
if (talentInfo->DependsOn > 0)
@@ -25291,33 +25856,32 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
hasEnoughRank = true;
}
if (!hasEnoughRank)
- return;
+ return false;
}
}
// Find out how many points we have in this field
uint32 spentPoints = 0;
-
+ uint32 primaryTreeTalents = 0;
uint32 tTab = talentInfo->TalentTab;
- if (talentInfo->Row > 0)
+ bool isMainTree = GetPrimaryTalentTree(GetActiveSpec()) == tTab || !GetPrimaryTalentTree(GetActiveSpec());
+
+ if (talentInfo->Row > 0 || !isMainTree)
{
- uint32 numRows = sTalentStore.GetNumRows();
- for (uint32 i = 0; i < numRows; i++) // Loop through all talents.
+ for (uint32 i = 0; i < sTalentStore.GetNumRows(); i++) // Loop through all talents.
{
- // Someday, someone needs to revamp
- const TalentEntry* tmpTalent = sTalentStore.LookupEntry(i);
- if (tmpTalent) // the way talents are tracked
+ if (TalentEntry const* tmpTalent = sTalentStore.LookupEntry(i)) // Someday, someone needs to revamp the way talents are tracked
{
- if (tmpTalent->TalentTab == tTab)
+ for (uint8 rank = 0; rank < MAX_TALENT_RANK; rank++)
{
- for (uint8 rank = 0; rank < MAX_TALENT_RANK; rank++)
+ if (tmpTalent->RankID[rank] != 0)
{
- if (tmpTalent->RankID[rank] != 0)
+ if (HasSpell(tmpTalent->RankID[rank]))
{
- if (HasSpell(tmpTalent->RankID[rank]))
- {
+ if (tmpTalent->TalentTab == tTab)
spentPoints += (rank + 1);
- }
+ if (tmpTalent->TalentTab == GetPrimaryTalentTree(GetActiveSpec()))
+ primaryTreeTalents += (rank + 1);
}
}
}
@@ -25327,28 +25891,49 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
// not have required min points spent in talent tree
if (spentPoints < (talentInfo->Row * MAX_TALENT_RANK))
- return;
+ return false;
+
+ // player has not spent 31 talents in main tree before attempting to learn other tree's talents
+ if (!isMainTree && primaryTreeTalents < REQ_PRIMARY_TREE_TALENTS)
+ return false;
// spell not set in talent.dbc
uint32 spellid = talentInfo->RankID[talentRank];
if (spellid == 0)
{
TC_LOG_ERROR("entities.player", "Talent.dbc have for talent: %u Rank: %u spell id = 0", talentId, talentRank);
- return;
+ return false;
}
// already known
if (HasSpell(spellid))
- return;
+ return false;
// learn! (other talent ranks will unlearned at learning)
LearnSpell(spellid, false);
- AddTalent(spellid, m_activeSpec, true);
+ AddTalent(spellid, GetActiveSpec(), true);
- TC_LOG_INFO("entities.player", "TalentID: %u Rank: %u Spell: %u Spec: %u\n", talentId, talentRank, spellid, m_activeSpec);
+ TC_LOG_INFO("misc", "TalentID: %u Rank: %u Spell: %u Spec: %u\n", talentId, talentRank, spellid, GetActiveSpec());
+
+ // set talent tree for player
+ if (!GetPrimaryTalentTree(GetActiveSpec()))
+ {
+ SetPrimaryTalentTree(GetActiveSpec(), talentInfo->TalentTab);
+ std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(talentInfo->TalentTab);
+ if (specSpells)
+ for (size_t i = 0; i < specSpells->size(); ++i)
+ LearnSpell(specSpells->at(i), false);
+
+ if (CanUseMastery())
+ for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
+ if (SpellInfo const* masterySpell = sSpellMgr->GetSpellInfo(talentTabInfo->MasterySpellId[i]))
+ if (masterySpell->IsPassive() && IsNeedCastPassiveSpellAtLearn(masterySpell))
+ CastSpell(this, masterySpell->Id, true);
+ }
// update free talent points
SetFreeTalentPoints(CurTalentPoints - (talentRank - curtalent_maxrank + 1));
+ return true;
}
void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank)
@@ -25489,13 +26074,13 @@ void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank)
void Player::AddKnownCurrency(uint32 itemId)
{
if (CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemId))
- SetFlag64(PLAYER_FIELD_KNOWN_CURRENCIES, (1LL << (ctEntry->BitIndex-1)));
+ SetFlag64(0, (1LL << (ctEntry->ID-1)));
}
void Player::UpdateFallInformationIfNeed(MovementInfo const& minfo, uint16 opcode)
{
- if (m_lastFallTime >= minfo.fallTime || m_lastFallZ <= minfo.pos.GetPositionZ() || opcode == MSG_MOVE_FALL_LAND)
- SetFallInformation(minfo.fallTime, minfo.pos.GetPositionZ());
+ if (m_lastFallTime >= minfo.jump.fallTime || m_lastFallZ <= minfo.pos.GetPositionZ() || opcode == MSG_MOVE_FALL_LAND)
+ SetFallInformation(minfo.jump.fallTime, minfo.pos.GetPositionZ());
}
void Player::UnsummonPetTemporaryIfAny()
@@ -25563,17 +26148,18 @@ bool Player::CanSeeSpellClickOn(Creature const* c) const
void Player::BuildPlayerTalentsInfoData(WorldPacket* data)
{
*data << uint32(GetFreeTalentPoints()); // unspentTalentPoints
- *data << uint8(m_specsCount); // talent group count (0, 1 or 2)
- *data << uint8(m_activeSpec); // talent group index (0 or 1)
+ *data << uint8(GetSpecsCount()); // talent group count (0, 1 or 2)
+ *data << uint8(GetActiveSpec()); // talent group index (0 or 1)
- if (m_specsCount)
+ if (GetSpecsCount())
{
- if (m_specsCount > MAX_TALENT_SPECS)
- m_specsCount = MAX_TALENT_SPECS;
+ if (GetSpecsCount() > MAX_TALENT_SPECS)
+ SetSpecsCount(MAX_TALENT_SPECS);
// loop through all specs (only 1 for now)
- for (uint32 specIdx = 0; specIdx < m_specsCount; ++specIdx)
+ for (uint8 specIdx = 0; specIdx < GetSpecsCount(); ++specIdx)
{
+ *data << uint32(GetPrimaryTalentTree(specIdx));
uint8 talentIdCount = 0;
size_t pos = data->wpos();
*data << uint8(talentIdCount); // [PH], talentIdCount
@@ -25622,7 +26208,7 @@ void Player::BuildPlayerTalentsInfoData(WorldPacket* data)
*data << uint8(MAX_GLYPH_SLOT_INDEX); // glyphs count
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
- *data << uint16(m_Glyphs[specIdx][i]); // GlyphProperties.dbc
+ *data << uint16(GetGlyph(specIdx, i)); // GlyphProperties.dbc
}
}
}
@@ -25933,6 +26519,39 @@ void Player::SendClearCooldown(uint32 spell_id, Unit* target)
SendDirectMessage(&data);
}
+void Player::SendClearAllCooldowns(Unit* target)
+{
+ uint32 spellCount = m_spellCooldowns.size();
+ ObjectGuid guid = target ? target->GetGUID() : 0;
+
+ WorldPacket data(SMSG_CLEAR_COOLDOWNS, 4+8);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[6]);
+ data.WriteBits(spellCount, 24); // Spell Count
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[0]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[3]);
+ for (SpellCooldowns::const_iterator itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr)
+ data << uint32(itr->first); // Spell ID
+
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[6]);
+
+ SendDirectMessage(&data);
+}
+
void Player::ResetMap()
{
// this may be called during Map::Update
@@ -25953,7 +26572,7 @@ void Player::SetMap(Map* map)
void Player::_LoadGlyphs(PreparedQueryResult result)
{
- // SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 from character_glyphs WHERE guid = '%u'
+ // SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9 FROM character_glyphs WHERE guid = '%u'
if (!result)
return;
@@ -25962,15 +26581,11 @@ void Player::_LoadGlyphs(PreparedQueryResult result)
Field* fields = result->Fetch();
uint8 spec = fields[0].GetUInt8();
- if (spec >= m_specsCount)
+ if (spec >= GetSpecsCount())
continue;
- m_Glyphs[spec][0] = fields[1].GetUInt16();
- m_Glyphs[spec][1] = fields[2].GetUInt16();
- m_Glyphs[spec][2] = fields[3].GetUInt16();
- m_Glyphs[spec][3] = fields[4].GetUInt16();
- m_Glyphs[spec][4] = fields[5].GetUInt16();
- m_Glyphs[spec][5] = fields[6].GetUInt16();
+ for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
+ _talentMgr->SpecInfo[spec].Glyphs[i] = fields[i + 1].GetUInt16();
}
while (result->NextRow());
}
@@ -25982,7 +26597,7 @@ void Player::_SaveGlyphs(SQLTransaction& trans)
trans->Append(stmt);
- for (uint8 spec = 0; spec < m_specsCount; ++spec)
+ for (uint8 spec = 0; spec < GetSpecsCount(); ++spec)
{
uint8 index = 0;
@@ -25992,7 +26607,7 @@ void Player::_SaveGlyphs(SQLTransaction& trans)
stmt->setUInt8(index++, spec);
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
- stmt->setUInt16(index++, uint16(m_Glyphs[spec][i]));
+ stmt->setUInt16(index++, uint16(GetGlyph(spec, i)));
trans->Append(stmt);
}
@@ -26015,7 +26630,7 @@ void Player::_SaveTalents(SQLTransaction& trans)
for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
{
- for (PlayerTalentMap::iterator itr = m_talents[i]->begin(); itr != m_talents[i]->end();)
+ for (PlayerTalentMap::iterator itr = GetTalentMap(i)->begin(); itr != GetTalentMap(i)->end();)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED)
{
@@ -26038,7 +26653,7 @@ void Player::_SaveTalents(SQLTransaction& trans)
if (itr->second->state == PLAYERSPELL_REMOVED)
{
delete itr->second;
- m_talents[i]->erase(itr++);
+ GetTalentMap(i)->erase(itr++);
}
else
{
@@ -26055,7 +26670,7 @@ void Player::UpdateSpecCount(uint8 count)
if (curCount == count)
return;
- if (m_activeSpec >= count)
+ if (GetActiveSpec() >= count)
ActivateSpec(0);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -26082,11 +26697,10 @@ void Player::UpdateSpecCount(uint8 count)
_SaveActions(trans);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC);
- stmt->setUInt8(0, m_activeSpec);
+ stmt->setUInt8(0, GetActiveSpec());
stmt->setUInt32(1, GetGUIDLow());
trans->Append(stmt);
- m_activeSpec = 0;
}
CharacterDatabase.CommitTransaction(trans);
@@ -26165,10 +26779,25 @@ void Player::ActivateSpec(uint8 spec)
}
}
+ // Remove spec specific spells
+ for (uint32 i = 0; i < MAX_TALENT_TABS; ++i)
+ {
+ uint32 const* talentTabs = GetTalentTabPages(getClass());
+ std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(talentTabs[i]);
+ if (specSpells)
+ for (size_t i = 0; i < specSpells->size(); ++i)
+ RemoveSpell(specSpells->at(i), true);
+
+ TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentTabs[i]);
+ for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
+ if (uint32 mastery = talentTabInfo->MasterySpellId[i])
+ RemoveSpell(mastery, true);
+ }
+
// set glyphs
for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
// remove secondary glyph
- if (uint32 oldglyph = m_Glyphs[m_activeSpec][slot])
+ if (uint32 oldglyph = GetGlyph(GetActiveSpec(), slot))
if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
RemoveAurasDueToSpell(old_gp->SpellId);
@@ -26198,7 +26827,7 @@ void Player::ActivateSpec(uint8 spec)
if (talentInfo->RankID[rank] == 0)
continue;
// if the talent can be found in the newly activated PlayerTalentMap
- if (HasTalent(talentInfo->RankID[rank], m_activeSpec))
+ if (HasTalent(talentInfo->RankID[rank], GetActiveSpec()))
{
LearnSpell(talentInfo->RankID[rank], false); // add the talent to the PlayerSpellMap
spentTalents += (rank + 1); // increment the spentTalents count
@@ -26206,10 +26835,21 @@ void Player::ActivateSpec(uint8 spec)
}
}
+ std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(GetPrimaryTalentTree(GetActiveSpec()));
+ if (specSpells)
+ for (size_t i = 0; i < specSpells->size(); ++i)
+ LearnSpell(specSpells->at(i), false);
+
+ if (CanUseMastery())
+ if (TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec())))
+ for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
+ if (uint32 mastery = talentTabInfo->MasterySpellId[i])
+ LearnSpell(mastery, false);
+
// set glyphs
for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
{
- uint32 glyph = m_Glyphs[m_activeSpec][slot];
+ uint32 glyph = GetGlyph(GetActiveSpec(), slot);
// apply primary glyph
if (glyph)
@@ -26219,13 +26859,13 @@ void Player::ActivateSpec(uint8 spec)
SetGlyph(slot, glyph);
}
- m_usedTalentCount = spentTalents;
+ SetUsedTalentCount(spentTalents);
InitTalentForLevel();
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC);
stmt->setUInt32(0, GetGUIDLow());
- stmt->setUInt8(1, m_activeSpec);
+ stmt->setUInt8(1, GetActiveSpec());
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
_LoadActions(result);
}
@@ -26237,11 +26877,13 @@ void Player::ActivateSpec(uint8 spec)
SetPower(POWER_MANA, 0); // Mana must be 0 even if it isn't the active power type.
SetPower(pw, 0);
+
+ if (!sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec())))
+ ResetTalents(true);
}
void Player::ResetTimeSync()
{
- m_timeSyncCounter = 0;
m_timeSyncTimer = 0;
m_timeSyncClient = 0;
m_timeSyncServer = getMSTime();
@@ -26249,13 +26891,18 @@ void Player::ResetTimeSync()
void Player::SendTimeSync()
{
+ m_timeSyncQueue.push(m_movementCounter++);
+
WorldPacket data(SMSG_TIME_SYNC_REQ, 4);
- data << uint32(m_timeSyncCounter++);
+ data << uint32(m_timeSyncQueue.back());
GetSession()->SendPacket(&data);
// Schedule next sync in 10 sec
m_timeSyncTimer = 10000;
m_timeSyncServer = getMSTime();
+
+ if (m_timeSyncQueue.size() > 3)
+ TC_LOG_ERROR("network", "Not received CMSG_TIME_SYNC_RESP for over 30 seconds from player %u (%s), possible cheater", GetGUIDLow(), GetName().c_str());
}
void Player::SetReputation(uint32 factionentry, uint32 value)
@@ -26267,9 +26914,9 @@ uint32 Player::GetReputation(uint32 factionentry) const
return GetReputationMgr().GetReputation(sFactionStore.LookupEntry(factionentry));
}
-std::string const& Player::GetGuildName()
+std::string Player::GetGuildName()
{
- return sGuildMgr->GetGuildById(GetGuildId())->GetName();
+ return GetGuildId() ? sGuildMgr->GetGuildById(GetGuildId())->GetName() : "";
}
void Player::SendDuelCountdown(uint32 counter)
@@ -26318,18 +26965,51 @@ void Player::SendRefundInfo(Item* item)
return;
}
+ ObjectGuid guid = item->GetGUID();
WorldPacket data(SMSG_ITEM_REFUND_INFO_RESPONSE, 8+4+4+4+4*4+4*4+4+4);
- data << uint64(item->GetGUID()); // item guid
- data << uint32(item->GetPaidMoney()); // money cost
- data << uint32(iece->reqhonorpoints); // honor point cost
- data << uint32(iece->reqarenapoints); // arena point cost
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i) // item cost data
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[1]);
+ data.FlushBits();
+
+ data.WriteByteSeq(guid[7]);
+ data << uint32(GetTotalPlayedTime() - item->GetPlayedTime());
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i) // item cost data
{
- data << uint32(iece->reqitem[i]);
- data << uint32(iece->reqitemcount[i]);
+ data << uint32(iece->RequiredItemCount[i]);
+ data << uint32(iece->RequiredItem[i]);
}
+
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[2]);
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i) // currency cost data
+ {
+ if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i))
+ {
+ data << uint32(0);
+ data << uint32(0);
+ continue;
+ }
+
+ CurrencyTypesEntry const* currencyType = sCurrencyTypesStore.LookupEntry(iece->RequiredCurrency[i]);
+ uint32 precision = (currencyType && currencyType->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+
+ data << uint32(iece->RequiredCurrencyCount[i] / precision);
+ data << uint32(iece->RequiredCurrency[i]);
+ }
+
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[5]);
data << uint32(0);
- data << uint32(GetTotalPlayedTime() - item->GetPlayedTime());
+ data.WriteByteSeq(guid[0]);
+ data << uint32(item->GetPaidMoney()); // money cost
GetSession()->SendPacket(&data);
}
@@ -26356,6 +27036,61 @@ bool Player::AddItem(uint32 itemId, uint32 count)
return true;
}
+void Player::SendItemRefundResult(Item* item, ItemExtendedCostEntry const* iece, uint8 error)
+{
+ ObjectGuid guid = item->GetGUID();
+ WorldPacket data(SMSG_ITEM_REFUND_RESULT, 1 + 1 + 8 + 4*8 + 4 + 4*8 + 1);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(!error);
+ data.WriteBit(item->GetPaidMoney() > 0);
+ data.FlushBits();
+ if (!error)
+ {
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
+ {
+ if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i))
+ {
+ data << uint32(0);
+ data << uint32(0);
+ continue;
+ }
+
+ CurrencyTypesEntry const* currencyType = sCurrencyTypesStore.LookupEntry(iece->RequiredCurrency[i]);
+ uint32 precision = (currencyType && currencyType->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1;
+
+ data << uint32(iece->RequiredCurrencyCount[i] / precision);
+ data << uint32(iece->RequiredCurrency[i]);
+ }
+
+ data << uint32(item->GetPaidMoney()); // money cost
+
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i) // item cost data
+ {
+ data << uint32(iece->RequiredItemCount[i]);
+ data << uint32(iece->RequiredItem[i]);
+ }
+ }
+
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[5]);
+
+ data << uint8(error); // error code
+ GetSession()->SendPacket(&data);
+}
+
void Player::RefundItem(Item* item)
{
if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE))
@@ -26367,10 +27102,7 @@ void Player::RefundItem(Item* item)
if (item->IsRefundExpired()) // item refund has expired
{
item->SetNotRefundable(this);
- WorldPacket data(SMSG_ITEM_REFUND_RESULT, 8+4);
- data << uint64(item->GetGUID()); // Guid
- data << uint32(10); // Error!
- GetSession()->SendPacket(&data);
+ SendItemRefundResult(item, NULL, 10);
return;
}
@@ -26389,10 +27121,10 @@ void Player::RefundItem(Item* item)
}
bool store_error = false;
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i)
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i)
{
- uint32 count = iece->reqitemcount[i];
- uint32 itemid = iece->reqitem[i];
+ uint32 count = iece->RequiredItemCount[i];
+ uint32 itemid = iece->RequiredItem[i];
if (count && itemid)
{
@@ -26408,25 +27140,11 @@ void Player::RefundItem(Item* item)
if (store_error)
{
- WorldPacket data(SMSG_ITEM_REFUND_RESULT, 8+4);
- data << uint64(item->GetGUID()); // Guid
- data << uint32(10); // Error!
- GetSession()->SendPacket(&data);
+ SendItemRefundResult(item, iece, 10);
return;
}
- WorldPacket data(SMSG_ITEM_REFUND_RESULT, 8+4+4+4+4+4*4+4*4);
- data << uint64(item->GetGUID()); // item guid
- data << uint32(0); // 0, or error code
- data << uint32(item->GetPaidMoney()); // money cost
- data << uint32(iece->reqhonorpoints); // honor point cost
- data << uint32(iece->reqarenapoints); // arena point cost
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i) // item cost data
- {
- data << uint32(iece->reqitem[i]);
- data << uint32(iece->reqitemcount[i]);
- }
- GetSession()->SendPacket(&data);
+ SendItemRefundResult(item, iece, 0);
uint32 moneyRefund = item->GetPaidMoney(); // item-> will be invalidated in DestroyItem
@@ -26440,10 +27158,10 @@ void Player::RefundItem(Item* item)
DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
// Grant back extendedcost items
- for (uint8 i = 0; i < MAX_ITEM_EXTENDED_COST_REQUIREMENTS; ++i)
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_ITEMS; ++i)
{
- uint32 count = iece->reqitemcount[i];
- uint32 itemid = iece->reqitem[i];
+ uint32 count = iece->RequiredItemCount[i];
+ uint32 itemid = iece->RequiredItem[i];
if (count && itemid)
{
ItemPosCountVec dest;
@@ -26454,18 +27172,22 @@ void Player::RefundItem(Item* item)
}
}
+ // Grant back currencies
+ for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i)
+ {
+ if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i))
+ continue;
+
+ uint32 count = iece->RequiredCurrencyCount[i];
+ uint32 currencyid = iece->RequiredCurrency[i];
+ if (count && currencyid)
+ ModifyCurrency(currencyid, count);
+ }
+
// Grant back money
if (moneyRefund)
ModifyMoney(moneyRefund); // Saved in SaveInventoryAndGoldToDB
- // Grant back Honor points
- if (uint32 honorRefund = iece->reqhonorpoints)
- ModifyHonorPoints(honorRefund, trans);
-
- // Grant back Arena points
- if (uint32 arenaRefund = iece->reqarenapoints)
- ModifyArenaPoints(arenaRefund, trans);
-
SaveInventoryAndGoldToDB(trans);
CharacterDatabase.CommitTransaction(trans);
@@ -26552,89 +27274,119 @@ bool Player::IsInWhisperWhiteList(uint64 guid)
return false;
}
-bool Player::SetDisableGravity(bool disable, bool packetOnly /*= false*/)
+uint8 Player::GetNextVoidStorageFreeSlot() const
{
- if (!packetOnly && !Unit::SetDisableGravity(disable))
- return false;
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ if (!_voidStorageItems[i]) // unused item
+ return i;
- WorldPacket data(disable ? SMSG_MOVE_GRAVITY_DISABLE : SMSG_MOVE_GRAVITY_ENABLE, 12);
- data.append(GetPackGUID());
- data << uint32(0); //! movement counter
- SendDirectMessage(&data);
+ return VOID_STORAGE_MAX_SLOT;
+}
- data.Initialize(MSG_MOVE_GRAVITY_CHNG, 64);
- data.append(GetPackGUID());
- BuildMovementPacket(&data);
- SendMessageToSet(&data, false);
- return true;
+uint8 Player::GetNumOfVoidStorageFreeSlots() const
+{
+ uint8 count = 0;
+
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ if (!_voidStorageItems[i])
+ count++;
+
+ return count;
}
-bool Player::SetCanFly(bool apply)
+uint8 Player::AddVoidStorageItem(const VoidStorageItem& item)
{
- if (!Unit::SetCanFly(apply))
- return false;
+ int8 slot = GetNextVoidStorageFreeSlot();
- WorldPacket data(apply ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, 12);
- data.append(GetPackGUID());
- data << uint32(0); //! movement counter
- SendDirectMessage(&data);
+ if (slot >= VOID_STORAGE_MAX_SLOT)
+ {
+ GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL);
+ return 255;
+ }
- data.Initialize(MSG_MOVE_UPDATE_CAN_FLY, 64);
- data.append(GetPackGUID());
- BuildMovementPacket(&data);
- SendMessageToSet(&data, false);
- return true;
+ _voidStorageItems[slot] = new VoidStorageItem(item.ItemId, item.ItemEntry,
+ item.CreatorGuid, item.ItemRandomPropertyId, item.ItemSuffixFactor);
+ return slot;
}
-bool Player::SetHover(bool apply, bool packetOnly /*= false*/)
+void Player::AddVoidStorageItemAtSlot(uint8 slot, const VoidStorageItem& item)
{
- if (!packetOnly && !Unit::SetHover(apply))
- return false;
+ if (slot >= VOID_STORAGE_MAX_SLOT)
+ {
+ GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL);
+ return;
+ }
- WorldPacket data(apply ? SMSG_MOVE_SET_HOVER : SMSG_MOVE_UNSET_HOVER, 12);
- data.append(GetPackGUID());
- data << uint32(0); //! movement counter
- SendDirectMessage(&data);
+ if (_voidStorageItems[slot])
+ {
+ TC_LOG_ERROR("misc", "Player::AddVoidStorageItemAtSlot - Player (GUID: %u, name: %s) tried to add an item to an used slot (item id: " UI64FMTD ", entry: %u, slot: %u).", GetGUIDLow(), GetName().c_str(), _voidStorageItems[slot]->ItemId, _voidStorageItems[slot]->ItemEntry, slot);
+ GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1);
+ return;
+ }
- data.Initialize(MSG_MOVE_HOVER, 64);
- data.append(GetPackGUID());
- BuildMovementPacket(&data);
- SendMessageToSet(&data, false);
- return true;
+ _voidStorageItems[slot] = new VoidStorageItem(item.ItemId, item.ItemId,
+ item.CreatorGuid, item.ItemRandomPropertyId, item.ItemSuffixFactor);
}
-bool Player::SetWaterWalking(bool apply, bool packetOnly /*= false*/)
+void Player::DeleteVoidStorageItem(uint8 slot)
{
- if (!packetOnly && !Unit::SetWaterWalking(apply))
- return false;
+ if (slot >= VOID_STORAGE_MAX_SLOT)
+ {
+ GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1);
+ return;
+ }
- WorldPacket data(apply ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, 12);
- data.append(GetPackGUID());
- data << uint32(0); //! movement counter
- SendDirectMessage(&data);
+ delete _voidStorageItems[slot];
+ _voidStorageItems[slot] = NULL;
+}
- data.Initialize(MSG_MOVE_WATER_WALK, 64);
- data.append(GetPackGUID());
- BuildMovementPacket(&data);
- SendMessageToSet(&data, false);
+bool Player::SwapVoidStorageItem(uint8 oldSlot, uint8 newSlot)
+{
+ if (oldSlot >= VOID_STORAGE_MAX_SLOT || newSlot >= VOID_STORAGE_MAX_SLOT || oldSlot == newSlot)
+ return false;
+
+ std::swap(_voidStorageItems[newSlot], _voidStorageItems[oldSlot]);
return true;
}
-bool Player::SetFeatherFall(bool apply, bool packetOnly /*= false*/)
+VoidStorageItem* Player::GetVoidStorageItem(uint8 slot) const
{
- if (!packetOnly && !Unit::SetFeatherFall(apply))
- return false;
+ if (slot >= VOID_STORAGE_MAX_SLOT)
+ {
+ GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1);
+ return NULL;
+ }
- WorldPacket data(apply ? SMSG_MOVE_FEATHER_FALL : SMSG_MOVE_NORMAL_FALL, 12);
- data.append(GetPackGUID());
- data << uint32(0); //! movement counter
- SendDirectMessage(&data);
+ return _voidStorageItems[slot];
+}
- data.Initialize(MSG_MOVE_FEATHER_FALL, 64);
- data.append(GetPackGUID());
- BuildMovementPacket(&data);
- SendMessageToSet(&data, false);
- return true;
+VoidStorageItem* Player::GetVoidStorageItem(uint64 id, uint8& slot) const
+{
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ {
+ if (_voidStorageItems[i] && _voidStorageItems[i]->ItemId == id)
+ {
+ slot = i;
+ return _voidStorageItems[i];
+ }
+ }
+
+ return NULL;
+}
+
+void Player::SendMovementSetCanTransitionBetweenSwimAndFly(bool apply)
+{
+ Movement::PacketSender(this, NULL_OPCODE, apply ?
+ SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY :
+ SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY).Send();
+}
+
+void Player::SendMovementSetCollisionHeight(float height)
+{
+ static MovementStatusElements const heightElement = MSEExtraFloat;
+ Movement::ExtraMovementStatusElement extra(&heightElement);
+ extra.Data.floatData = height;
+ Movement::PacketSender(this, NULL_OPCODE, SMSG_MOVE_SET_COLLISION_HEIGHT, SMSG_MOVE_UPDATE_COLLISION_HEIGHT, &extra).Send();
}
float Player::GetCollisionHeight(bool mounted) const
@@ -26750,6 +27502,9 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
return NULL;
}
+ for (auto itr : GetPhases())
+ pet->SetInPhase(itr, false, true);
+
pet->SetCreatorGUID(GetGUID());
pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
@@ -26819,10 +27574,334 @@ bool Player::IsLoading() const
return GetSession()->PlayerLoading();
}
+bool Player::CanUseMastery() const
+{
+ return HasSpell(MasterySpells[getClass()]);
+}
+
+void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::ExtraMovementStatusElement* extras /*= NULL*/)
+{
+ MovementStatusElements const* sequence = GetMovementStatusElementsSequence(data.GetOpcode());
+ if (!sequence)
+ {
+ TC_LOG_ERROR("network", "Player::ReadMovementInfo: No movement sequence found for opcode %s", GetOpcodeNameForLogging(data.GetOpcode()).c_str());
+ return;
+ }
+
+ bool hasMovementFlags = false;
+ bool hasMovementFlags2 = false;
+ bool hasTimestamp = false;
+ bool hasOrientation = false;
+ bool hasTransportData = false;
+ bool hasTransportTime2 = false;
+ bool hasTransportTime3 = false;
+ bool hasPitch = false;
+ bool hasFallData = false;
+ bool hasFallDirection = false;
+ bool hasSplineElevation = false;
+
+ ObjectGuid guid;
+ ObjectGuid tguid;
+
+ for (; *sequence != MSEEnd; ++sequence)
+ {
+ MovementStatusElements const& element = *sequence;
+
+ switch (element)
+ {
+ case MSEHasGuidByte0:
+ case MSEHasGuidByte1:
+ case MSEHasGuidByte2:
+ case MSEHasGuidByte3:
+ case MSEHasGuidByte4:
+ case MSEHasGuidByte5:
+ case MSEHasGuidByte6:
+ case MSEHasGuidByte7:
+ guid[element - MSEHasGuidByte0] = data.ReadBit();
+ break;
+ case MSEHasTransportGuidByte0:
+ case MSEHasTransportGuidByte1:
+ case MSEHasTransportGuidByte2:
+ case MSEHasTransportGuidByte3:
+ case MSEHasTransportGuidByte4:
+ case MSEHasTransportGuidByte5:
+ case MSEHasTransportGuidByte6:
+ case MSEHasTransportGuidByte7:
+ if (hasTransportData)
+ tguid[element - MSEHasTransportGuidByte0] = data.ReadBit();
+ break;
+ case MSEGuidByte0:
+ case MSEGuidByte1:
+ case MSEGuidByte2:
+ case MSEGuidByte3:
+ case MSEGuidByte4:
+ case MSEGuidByte5:
+ case MSEGuidByte6:
+ case MSEGuidByte7:
+ data.ReadByteSeq(guid[element - MSEGuidByte0]);
+ break;
+ case MSETransportGuidByte0:
+ case MSETransportGuidByte1:
+ case MSETransportGuidByte2:
+ case MSETransportGuidByte3:
+ case MSETransportGuidByte4:
+ case MSETransportGuidByte5:
+ case MSETransportGuidByte6:
+ case MSETransportGuidByte7:
+ if (hasTransportData)
+ data.ReadByteSeq(tguid[element - MSETransportGuidByte0]);
+ break;
+ case MSEHasMovementFlags:
+ hasMovementFlags = !data.ReadBit();
+ break;
+ case MSEHasMovementFlags2:
+ hasMovementFlags2 = !data.ReadBit();
+ break;
+ case MSEHasTimestamp:
+ hasTimestamp = !data.ReadBit();
+ break;
+ case MSEHasOrientation:
+ hasOrientation = !data.ReadBit();
+ break;
+ case MSEHasTransportData:
+ hasTransportData = data.ReadBit();
+ break;
+ case MSEHasTransportTime2:
+ if (hasTransportData)
+ hasTransportTime2 = data.ReadBit();
+ break;
+ case MSEHasTransportTime3:
+ if (hasTransportData)
+ hasTransportTime3 = data.ReadBit();
+ break;
+ case MSEHasPitch:
+ hasPitch = !data.ReadBit();
+ break;
+ case MSEHasFallData:
+ hasFallData = data.ReadBit();
+ break;
+ case MSEHasFallDirection:
+ if (hasFallData)
+ hasFallDirection = data.ReadBit();
+ break;
+ case MSEHasSplineElevation:
+ hasSplineElevation = !data.ReadBit();
+ break;
+ case MSEHasSpline:
+ data.ReadBit();
+ break;
+ case MSEMovementFlags:
+ if (hasMovementFlags)
+ mi->flags = data.ReadBits(30);
+ break;
+ case MSEMovementFlags2:
+ if (hasMovementFlags2)
+ mi->flags2 = data.ReadBits(12);
+ break;
+ case MSETimestamp:
+ if (hasTimestamp)
+ data >> mi->time;
+ break;
+ case MSEPositionX:
+ data >> mi->pos.m_positionX;
+ break;
+ case MSEPositionY:
+ data >> mi->pos.m_positionY;
+ break;
+ case MSEPositionZ:
+ data >> mi->pos.m_positionZ;
+ break;
+ case MSEOrientation:
+ if (hasOrientation)
+ mi->pos.SetOrientation(data.read<float>());
+ break;
+ case MSETransportPositionX:
+ if (hasTransportData)
+ data >> mi->transport.pos.m_positionX;
+ break;
+ case MSETransportPositionY:
+ if (hasTransportData)
+ data >> mi->transport.pos.m_positionY;
+ break;
+ case MSETransportPositionZ:
+ if (hasTransportData)
+ data >> mi->transport.pos.m_positionZ;
+ break;
+ case MSETransportOrientation:
+ if (hasTransportData)
+ mi->transport.pos.SetOrientation(data.read<float>());
+ break;
+ case MSETransportSeat:
+ if (hasTransportData)
+ data >> mi->transport.seat;
+ break;
+ case MSETransportTime:
+ if (hasTransportData)
+ data >> mi->transport.time;
+ break;
+ case MSETransportTime2:
+ if (hasTransportData && hasTransportTime2)
+ data >> mi->transport.time2;
+ break;
+ case MSETransportTime3:
+ if (hasTransportData && hasTransportTime3)
+ data >> mi->transport.time3;
+ break;
+ case MSEPitch:
+ if (hasPitch)
+ mi->pitch = G3D::wrap(data.read<float>(), float(-M_PI), float(M_PI));
+ break;
+ case MSEFallTime:
+ if (hasFallData)
+ data >> mi->jump.fallTime;
+ break;
+ case MSEFallVerticalSpeed:
+ if (hasFallData)
+ data >> mi->jump.zspeed;
+ break;
+ case MSEFallCosAngle:
+ if (hasFallData && hasFallDirection)
+ data >> mi->jump.cosAngle;
+ break;
+ case MSEFallSinAngle:
+ if (hasFallData && hasFallDirection)
+ data >> mi->jump.sinAngle;
+ break;
+ case MSEFallHorizontalSpeed:
+ if (hasFallData && hasFallDirection)
+ data >> mi->jump.xyspeed;
+ break;
+ case MSESplineElevation:
+ if (hasSplineElevation)
+ data >> mi->splineElevation;
+ break;
+ case MSECounter:
+ data.read_skip<uint32>(); /// @TODO: Maybe compare it with m_movementCounter to verify that packets are sent & received in order?
+ break;
+ case MSEZeroBit:
+ case MSEOneBit:
+ data.ReadBit();
+ break;
+ case MSEExtraElement:
+ extras->ReadNextElement(data);
+ break;
+ default:
+ ASSERT(Movement::PrintInvalidSequenceElement(element, __FUNCTION__));
+ break;
+ }
+ }
+
+ mi->guid = guid;
+ mi->transport.guid = tguid;
+
+ //! Anti-cheat checks. Please keep them in seperate if () blocks to maintain a clear overview.
+ //! Might be subject to latency, so just remove improper flags.
+ #ifdef TRINITY_DEBUG
+ #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
+ { \
+ if (check) \
+ { \
+ TC_LOG_DEBUG("entities.unit", "Player::ReadMovementInfo: Violation of MovementFlags found (%s). " \
+ "MovementFlags: %u, MovementFlags2: %u for player GUID: %u. Mask %u will be removed.", \
+ STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetGUIDLow(), maskToRemove); \
+ mi->RemoveMovementFlag((maskToRemove)); \
+ } \
+ }
+ #else
+ #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
+ if (check) \
+ mi->RemoveMovementFlag((maskToRemove));
+ #endif
+
+ /*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid
+ in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD.
+ It will freeze clients that receive this player's movement info.
+ */
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT),
+ MOVEMENTFLAG_ROOT);
+
+ //! Cannot hover without SPELL_AURA_HOVER
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !HasAuraType(SPELL_AURA_HOVER),
+ MOVEMENTFLAG_HOVER);
+
+ //! Cannot ascend and descend at the same time
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING),
+ MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING);
+
+ //! Cannot move left and right at the same time
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT),
+ MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
+
+ //! Cannot strafe left and right at the same time
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT),
+ MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT);
+
+ //! Cannot pitch up and down at the same time
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN),
+ MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN);
+
+ //! Cannot move forwards and backwards at the same time
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD),
+ MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
+
+ //! Cannot walk on water without SPELL_AURA_WATER_WALK
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !HasAuraType(SPELL_AURA_WATER_WALK),
+ MOVEMENTFLAG_WATERWALKING);
+
+ //! Cannot feather fall without SPELL_AURA_FEATHER_FALL
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !HasAuraType(SPELL_AURA_FEATHER_FALL),
+ MOVEMENTFLAG_FALLING_SLOW);
+
+ /*! Cannot fly if no fly auras present. Exception is being a GM.
+ Note that we check for account level instead of Player::IsGameMaster() because in some
+ situations it may be feasable to use .gm fly on as a GM without having .gm on,
+ e.g. aerial combat.
+ */
+
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && ToPlayer()->GetSession()->GetSecurity() == SEC_PLAYER &&
+ !ToPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) &&
+ !ToPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED),
+ MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY);
+
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_CAN_FLY) && mi->HasMovementFlag(MOVEMENTFLAG_FALLING),
+ MOVEMENTFLAG_FALLING);
+
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING) && (!hasFallData || !hasFallDirection), MOVEMENTFLAG_FALLING);
+
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION) &&
+ (!hasSplineElevation || G3D::fuzzyEq(mi->splineElevation, 0.0f)), MOVEMENTFLAG_SPLINE_ELEVATION);
+
+ // Client first checks if spline elevation != 0, then verifies flag presence
+ if (hasSplineElevation)
+ mi->AddMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION);
+
+ #undef REMOVE_VIOLATING_FLAGS
+}
+
+void Player::UpdatePhasing()
+{
+ if (!IsInWorld())
+ return;
+
+ std::set<uint32> phaseIds;
+ std::set<uint32> terrainswaps;
+ std::set<uint32> worldAreaSwaps;
+
+ for (auto phase : GetPhases())
+ {
+ PhaseInfo const* info = sObjectMgr->GetPhaseInfo(phase);
+ if (!info)
+ continue;
+ terrainswaps.insert(info->terrainSwapMap);
+ worldAreaSwaps.insert(info->worldMapAreaSwap);
+ }
+
+ GetSession()->SendSetPhaseShift(GetPhases(), terrainswaps, worldAreaSwaps);
+}
+
void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell)
{
WorldPacket data(SMSG_SUPERCEDED_SPELL, 8);
- data << uint32(oldSpell) << uint32(newSpell);
+ data << uint32(newSpell) << uint32(oldSpell);
GetSession()->SendPacket(&data);
}
-
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 851afecdbaf..ef65558e13c 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -28,6 +28,8 @@
#include "QuestDef.h"
#include "SpellMgr.h"
#include "Unit.h"
+#include "Opcodes.h"
+#include "WorldSession.h"
#include <limits>
#include <string>
@@ -35,10 +37,11 @@
struct CreatureTemplate;
struct Mail;
+struct ItemExtendedCostEntry;
struct TrainerSpell;
struct VendorItem;
-class AchievementMgr;
+template<class T> class AchievementMgr;
class ReputationMgr;
class Channel;
class CharacterCreateInfo;
@@ -55,9 +58,9 @@ class UpdateMask;
typedef std::deque<Mail*> PlayerMails;
-#define PLAYER_MAX_SKILLS 127
+#define PLAYER_MAX_SKILLS 128
#define PLAYER_MAX_DAILY_QUESTS 25
-#define PLAYER_EXPLORED_ZONES_SIZE 128
+#define PLAYER_EXPLORED_ZONES_SIZE 156
// Note: SPELLMOD_* values is aura types in fact
enum SpellModType
@@ -109,6 +112,42 @@ struct PlayerTalent
uint8 spec : 8;
};
+extern uint32 const MasterySpells[MAX_CLASSES];
+
+enum TalentTree // talent tabs
+{
+ TALENT_TREE_WARRIOR_ARMS = 746,
+ TALENT_TREE_WARRIOR_FURY = 815,
+ TALENT_TREE_WARRIOR_PROTECTION = 845,
+ TALENT_TREE_PALADIN_HOLY = 831,
+ TALENT_TREE_PALADIN_PROTECTION = 839,
+ TALENT_TREE_PALADIN_RETRIBUTION = 855,
+ TALENT_TREE_HUNTER_BEAST_MASTERY = 811,
+ TALENT_TREE_HUNTER_MARKSMANSHIP = 807,
+ TALENT_TREE_HUNTER_SURVIVAL = 809,
+ TALENT_TREE_ROGUE_ASSASSINATION = 182,
+ TALENT_TREE_ROGUE_COMBAT = 181,
+ TALENT_TREE_ROGUE_SUBTLETY = 183,
+ TALENT_TREE_PRIEST_DISCIPLINE = 760,
+ TALENT_TREE_PRIEST_HOLY = 813,
+ TALENT_TREE_PRIEST_SHADOW = 795,
+ TALENT_TREE_DEATH_KNIGHT_BLOOD = 398,
+ TALENT_TREE_DEATH_KNIGHT_FROST = 399,
+ TALENT_TREE_DEATH_KNIGHT_UNHOLY = 400,
+ TALENT_TREE_SHAMAN_ELEMENTAL = 261,
+ TALENT_TREE_SHAMAN_ENHANCEMENT = 263,
+ TALENT_TREE_SHAMAN_RESTORATION = 262,
+ TALENT_TREE_MAGE_ARCANE = 799,
+ TALENT_TREE_MAGE_FIRE = 851,
+ TALENT_TREE_MAGE_FROST = 823,
+ TALENT_TREE_WARLOCK_AFFLICTION = 871,
+ TALENT_TREE_WARLOCK_DEMONOLOGY = 867,
+ TALENT_TREE_WARLOCK_DESTRUCTION = 865,
+ TALENT_TREE_DRUID_BALANCE = 752,
+ TALENT_TREE_DRUID_FERAL_COMBAT = 750,
+ TALENT_TREE_DRUID_RESTORATION = 748
+};
+
// Spell modifier (used for modify other spells)
struct SpellModifier
{
@@ -122,12 +161,121 @@ struct SpellModifier
Aura* const ownerAura;
};
+enum PlayerCurrencyState
+{
+ PLAYERCURRENCY_UNCHANGED = 0,
+ PLAYERCURRENCY_CHANGED = 1,
+ PLAYERCURRENCY_NEW = 2,
+ PLAYERCURRENCY_REMOVED = 3 //not removed just set count == 0
+};
+
+struct PlayerCurrency
+{
+ PlayerCurrencyState state;
+ uint32 totalCount;
+ uint32 weekCount;
+};
+
typedef std::unordered_map<uint32, PlayerTalent*> PlayerTalentMap;
typedef std::unordered_map<uint32, PlayerSpell*> PlayerSpellMap;
typedef std::list<SpellModifier*> SpellModList;
+typedef std::unordered_map<uint32, PlayerCurrency> PlayerCurrenciesMap;
typedef std::list<uint64> WhisperListContainer;
+/// Maximum number of CompactUnitFrames profiles
+#define MAX_CUF_PROFILES 5
+
+/// Bit index used in the many bool options of CompactUnitFrames
+enum CUFBoolOptions
+{
+ CUF_KEEP_GROUPS_TOGETHER,
+ CUF_DISPLAY_PETS,
+ CUF_DISPLAY_MAIN_TANK_AND_ASSIST,
+ CUF_DISPLAY_HEAL_PREDICTION,
+ CUF_DISPLAY_AGGRO_HIGHLIGHT,
+ CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS,
+ CUF_DISPLAY_POWER_BAR,
+ CUF_DISPLAY_BORDER,
+ CUF_USE_CLASS_COLORS,
+ CUF_DISPLAY_NON_BOSS_DEBUFFS,
+ CUF_DISPLAY_HORIZONTAL_GROUPS,
+ CUF_LOCKED,
+ CUF_SHOWN,
+ CUF_AUTO_ACTIVATE_2_PLAYERS,
+ CUF_AUTO_ACTIVATE_3_PLAYERS,
+ CUF_AUTO_ACTIVATE_5_PLAYERS,
+ CUF_AUTO_ACTIVATE_10_PLAYERS,
+ CUF_AUTO_ACTIVATE_15_PLAYERS,
+ CUF_AUTO_ACTIVATE_25_PLAYERS,
+ CUF_AUTO_ACTIVATE_40_PLAYERS,
+ CUF_AUTO_ACTIVATE_SPEC_1,
+ CUF_AUTO_ACTIVATE_SPEC_2,
+ CUF_AUTO_ACTIVATE_PVP,
+ CUF_AUTO_ACTIVATE_PVE,
+ CUF_UNK_145,
+ CUF_UNK_156,
+ CUF_UNK_157,
+
+ // The unks is _LOCKED and _SHOWN and _DYNAMIC, unknown order
+
+ CUF_BOOL_OPTIONS_COUNT,
+};
+
+/// Represents a CompactUnitFrame profile
+struct CUFProfile
+{
+ CUFProfile() : ProfileName(), BoolOptions() // might want to change default value for options
+ {
+ FrameHeight = 0;
+ FrameWidth = 0;
+ SortBy = 0;
+ HealthText = 0;
+ Unk146 = 0;
+ Unk147 = 0;
+ Unk148 = 0;
+ Unk150 = 0;
+ Unk152 = 0;
+ Unk154 = 0;
+ }
+
+ CUFProfile(const std::string& name, uint16 frameHeight, uint16 frameWidth, uint8 sortBy, uint8 healthText, uint32 boolOptions,
+ uint8 unk146, uint8 unk147, uint8 unk148, uint16 unk150, uint16 unk152, uint16 unk154)
+ : ProfileName(name), BoolOptions((int)boolOptions)
+ {
+ FrameHeight = frameHeight;
+ FrameWidth = frameWidth;
+ SortBy = sortBy;
+ HealthText = healthText;
+ Unk146 = unk146;
+ Unk147 = unk147;
+ Unk148 = unk148;
+ Unk150 = unk150;
+ Unk152 = unk152;
+ Unk154 = unk154;
+ }
+
+ std::string ProfileName;
+ uint16 FrameHeight;
+ uint16 FrameWidth;
+ uint8 SortBy;
+ uint8 HealthText;
+
+ // LeftAlign, TopAlight, BottomAllign (unk order)
+ uint8 Unk146;
+ uint8 Unk147;
+ uint8 Unk148;
+
+ // LeftOffset, TopOffset and BottomOffset (unk order)
+ uint16 Unk150;
+ uint16 Unk152;
+ uint16 Unk154;
+
+ std::bitset<CUF_BOOL_OPTIONS_COUNT> BoolOptions;
+
+ // More fields can be added to BoolOptions without changing DB schema (up to 32, currently 27)
+};
+
struct SpellCooldown
{
time_t end;
@@ -139,9 +287,9 @@ typedef std::unordered_map<uint32 /*instanceId*/, time_t/*releaseTime*/> Instanc
enum TrainerSpellState
{
- TRAINER_SPELL_GREEN = 0,
- TRAINER_SPELL_RED = 1,
- TRAINER_SPELL_GRAY = 2,
+ TRAINER_SPELL_GRAY = 0,
+ TRAINER_SPELL_GREEN = 1,
+ TRAINER_SPELL_RED = 2,
TRAINER_SPELL_GREEN_DISABLED = 10 // custom value, not send to client: formally green but learn not allowed
};
@@ -158,6 +306,7 @@ enum ActionButtonType
ACTION_BUTTON_SPELL = 0x00,
ACTION_BUTTON_C = 0x01, // click?
ACTION_BUTTON_EQSET = 0x20,
+ ACTION_BUTTON_DROPDOWN = 0x30,
ACTION_BUTTON_MACRO = 0x40,
ACTION_BUTTON_CMACRO = ACTION_BUTTON_C | ACTION_BUTTON_MACRO,
ACTION_BUTTON_ITEM = 0x80
@@ -214,20 +363,6 @@ struct PlayerCreateInfoItem
typedef std::list<PlayerCreateInfoItem> PlayerCreateInfoItems;
-struct PlayerClassLevelInfo
-{
- PlayerClassLevelInfo() : basehealth(0), basemana(0) { }
- uint16 basehealth;
- uint16 basemana;
-};
-
-struct PlayerClassInfo
-{
- PlayerClassInfo() : levelInfo(NULL) { }
-
- PlayerClassLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1
-};
-
struct PlayerLevelInfo
{
PlayerLevelInfo() { for (uint8 i=0; i < MAX_STATS; ++i) stats[i] = 0; }
@@ -272,6 +407,7 @@ struct PlayerInfo
uint16 displayId_f;
PlayerCreateInfoItems item;
PlayerCreateInfoSpells customSpells;
+ PlayerCreateInfoSpells castSpells;
PlayerCreateInfoActions action;
PlayerCreateInfoSkills skills;
@@ -365,14 +501,6 @@ struct EnchantDuration
typedef std::list<EnchantDuration> EnchantDurationList;
typedef std::list<Item*> ItemDurationList;
-enum PlayerMovementType
-{
- MOVE_ROOT = 1,
- MOVE_UNROOT = 2,
- MOVE_WATER_WALK = 3,
- MOVE_LAND_WALK = 4
-};
-
enum DrunkenState
{
DRUNKEN_SOBER = 0,
@@ -385,87 +513,42 @@ enum DrunkenState
enum PlayerFlags
{
- PLAYER_FLAGS_GROUP_LEADER = 0x00000001,
- PLAYER_FLAGS_AFK = 0x00000002,
- PLAYER_FLAGS_DND = 0x00000004,
- PLAYER_FLAGS_GM = 0x00000008,
- PLAYER_FLAGS_GHOST = 0x00000010,
- PLAYER_FLAGS_RESTING = 0x00000020,
- PLAYER_FLAGS_UNK6 = 0x00000040,
- PLAYER_FLAGS_UNK7 = 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_PLAYED_LONG_TIME = 0x00001000, // played long time
- PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time
- PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000,
- PLAYER_FLAGS_DEVELOPER = 0x00008000, // <Dev> prefix for something?
- PLAYER_FLAGS_UNK16 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary
- PLAYER_FLAGS_TAXI_BENCHMARK = 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_UBER = 0x00080000,
- PLAYER_FLAGS_UNK20 = 0x00100000,
- PLAYER_FLAGS_UNK21 = 0x00200000,
- PLAYER_FLAGS_COMMENTATOR2 = 0x00400000,
- PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree, allowed only spells with SPELL_ATTR0_REQ_AMMO, SPELL_EFFECT_ATTACK, checked only for active player
- PLAYER_FLAGS_UNK24 = 0x01000000, // disabled all melee ability on tab include autoattack
- PLAYER_FLAGS_NO_XP_GAIN = 0x02000000,
- PLAYER_FLAGS_UNK26 = 0x04000000,
- PLAYER_FLAGS_UNK27 = 0x08000000,
- PLAYER_FLAGS_UNK28 = 0x10000000,
- PLAYER_FLAGS_UNK29 = 0x20000000,
- PLAYER_FLAGS_UNK30 = 0x40000000,
- PLAYER_FLAGS_UNK31 = 0x80000000
-};
-
-// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
-// can't use enum for uint64 values
-#define PLAYER_TITLE_DISABLED UI64LIT(0x0000000000000000)
-#define PLAYER_TITLE_NONE UI64LIT(0x0000000000000001)
-#define PLAYER_TITLE_PRIVATE UI64LIT(0x0000000000000002) // 1
-#define PLAYER_TITLE_CORPORAL UI64LIT(0x0000000000000004) // 2
-#define PLAYER_TITLE_SERGEANT_A UI64LIT(0x0000000000000008) // 3
-#define PLAYER_TITLE_MASTER_SERGEANT UI64LIT(0x0000000000000010) // 4
-#define PLAYER_TITLE_SERGEANT_MAJOR UI64LIT(0x0000000000000020) // 5
-#define PLAYER_TITLE_KNIGHT UI64LIT(0x0000000000000040) // 6
-#define PLAYER_TITLE_KNIGHT_LIEUTENANT UI64LIT(0x0000000000000080) // 7
-#define PLAYER_TITLE_KNIGHT_CAPTAIN UI64LIT(0x0000000000000100) // 8
-#define PLAYER_TITLE_KNIGHT_CHAMPION UI64LIT(0x0000000000000200) // 9
-#define PLAYER_TITLE_LIEUTENANT_COMMANDER UI64LIT(0x0000000000000400) // 10
-#define PLAYER_TITLE_COMMANDER UI64LIT(0x0000000000000800) // 11
-#define PLAYER_TITLE_MARSHAL UI64LIT(0x0000000000001000) // 12
-#define PLAYER_TITLE_FIELD_MARSHAL UI64LIT(0x0000000000002000) // 13
-#define PLAYER_TITLE_GRAND_MARSHAL UI64LIT(0x0000000000004000) // 14
-#define PLAYER_TITLE_SCOUT UI64LIT(0x0000000000008000) // 15
-#define PLAYER_TITLE_GRUNT UI64LIT(0x0000000000010000) // 16
-#define PLAYER_TITLE_SERGEANT_H UI64LIT(0x0000000000020000) // 17
-#define PLAYER_TITLE_SENIOR_SERGEANT UI64LIT(0x0000000000040000) // 18
-#define PLAYER_TITLE_FIRST_SERGEANT UI64LIT(0x0000000000080000) // 19
-#define PLAYER_TITLE_STONE_GUARD UI64LIT(0x0000000000100000) // 20
-#define PLAYER_TITLE_BLOOD_GUARD UI64LIT(0x0000000000200000) // 21
-#define PLAYER_TITLE_LEGIONNAIRE UI64LIT(0x0000000000400000) // 22
-#define PLAYER_TITLE_CENTURION UI64LIT(0x0000000000800000) // 23
-#define PLAYER_TITLE_CHAMPION UI64LIT(0x0000000001000000) // 24
-#define PLAYER_TITLE_LIEUTENANT_GENERAL UI64LIT(0x0000000002000000) // 25
-#define PLAYER_TITLE_GENERAL UI64LIT(0x0000000004000000) // 26
-#define PLAYER_TITLE_WARLORD UI64LIT(0x0000000008000000) // 27
-#define PLAYER_TITLE_HIGH_WARLORD UI64LIT(0x0000000010000000) // 28
-#define PLAYER_TITLE_GLADIATOR UI64LIT(0x0000000020000000) // 29
-#define PLAYER_TITLE_DUELIST UI64LIT(0x0000000040000000) // 30
-#define PLAYER_TITLE_RIVAL UI64LIT(0x0000000080000000) // 31
-#define PLAYER_TITLE_CHALLENGER UI64LIT(0x0000000100000000) // 32
-#define PLAYER_TITLE_SCARAB_LORD UI64LIT(0x0000000200000000) // 33
-#define PLAYER_TITLE_CONQUEROR UI64LIT(0x0000000400000000) // 34
-#define PLAYER_TITLE_JUSTICAR UI64LIT(0x0000000800000000) // 35
-#define PLAYER_TITLE_CHAMPION_OF_THE_NAARU UI64LIT(0x0000001000000000) // 36
-#define PLAYER_TITLE_MERCILESS_GLADIATOR UI64LIT(0x0000002000000000) // 37
-#define PLAYER_TITLE_OF_THE_SHATTERED_SUN UI64LIT(0x0000004000000000) // 38
-#define PLAYER_TITLE_HAND_OF_ADAL UI64LIT(0x0000008000000000) // 39
-#define PLAYER_TITLE_VENGEFUL_GLADIATOR UI64LIT(0x0000010000000000) // 40
-
-#define KNOWN_TITLES_SIZE 3
-#define MAX_TITLE_INDEX (KNOWN_TITLES_SIZE*64) // 3 uint64 fields
+ PLAYER_FLAGS_GROUP_LEADER = 0x00000001,
+ PLAYER_FLAGS_AFK = 0x00000002,
+ PLAYER_FLAGS_DND = 0x00000004,
+ PLAYER_FLAGS_GM = 0x00000008,
+ PLAYER_FLAGS_GHOST = 0x00000010,
+ PLAYER_FLAGS_RESTING = 0x00000020,
+ PLAYER_FLAGS_UNK6 = 0x00000040,
+ PLAYER_FLAGS_UNK7 = 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_PLAYED_LONG_TIME = 0x00001000, // played long time
+ PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time
+ PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000,
+ PLAYER_FLAGS_DEVELOPER = 0x00008000, // <Dev> prefix for something?
+ PLAYER_FLAGS_UNK16 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary
+ PLAYER_FLAGS_TAXI_BENCHMARK = 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_UBER = 0x00080000,
+ PLAYER_FLAGS_UNK20 = 0x00100000,
+ PLAYER_FLAGS_UNK21 = 0x00200000,
+ PLAYER_FLAGS_COMMENTATOR2 = 0x00400000,
+ PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree, allowed only spells with SPELL_ATTR0_REQ_AMMO, SPELL_EFFECT_ATTACK, checked only for active player
+ PLAYER_FLAGS_UNK24 = 0x01000000, // disabled all melee ability on tab include autoattack
+ PLAYER_FLAGS_NO_XP_GAIN = 0x02000000,
+ PLAYER_FLAGS_UNK26 = 0x04000000,
+ PLAYER_FLAGS_AUTO_DECLINE_GUILD = 0x08000000, // Automatically declines guild invites
+ PLAYER_FLAGS_GUILD_LEVEL_ENABLED = 0x10000000, // Lua_GetGuildLevelEnabled() - enables guild leveling related UI
+ PLAYER_FLAGS_VOID_UNLOCKED = 0x20000000, // void storage
+ PLAYER_FLAGS_UNK30 = 0x40000000,
+ PLAYER_FLAGS_UNK31 = 0x80000000
+};
+
+#define KNOWN_TITLES_SIZE 4
+#define MAX_TITLE_INDEX (KNOWN_TITLES_SIZE * 64) // 4 uint64 fields
// used in PLAYER_FIELD_BYTES values
enum PlayerFieldByteFlags
@@ -487,7 +570,7 @@ enum MirrorTimerType
{
FATIGUE_TIMER = 0,
BREATH_TIMER = 1,
- FIRE_TIMER = 2
+ FIRE_TIMER = 2 // feign death
};
#define MAX_TIMERS 3
#define DISABLED_MIRROR_TIMER -1
@@ -501,7 +584,6 @@ enum PlayerExtraFlags
PLAYER_EXTRA_TAXICHEAT = 0x0008,
PLAYER_EXTRA_GM_INVISIBLE = 0x0010,
PLAYER_EXTRA_GM_CHAT = 0x0020, // Show GM badge in chat messages
- PLAYER_EXTRA_HAS_310_FLYER = 0x0040, // Marks if player already has 310% speed flying mount
// other states
PLAYER_EXTRA_PVP_DEATH = 0x0100 // store PvP death status until corpse creating.
@@ -573,7 +655,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 = 150,
+ PLAYER_SLOT_END = 86,
PLAYER_SLOTS_COUNT = (PLAYER_SLOT_END - PLAYER_SLOT_START)
};
@@ -635,18 +717,6 @@ enum BuyBackSlots // 12 slots
BUYBACK_SLOT_END = 86
};
-enum KeyRingSlots // 32 slots
-{
- KEYRING_SLOT_START = 86,
- KEYRING_SLOT_END = 118
-};
-
-enum CurrencyTokenSlots // 32 slots
-{
- CURRENCYTOKEN_SLOT_START = 118,
- CURRENCYTOKEN_SLOT_END = 150
-};
-
enum EquipmentSetUpdateState
{
EQUIPMENT_SET_UNCHANGED = 0,
@@ -694,22 +764,24 @@ enum TradeSlots
enum TransferAbortReason
{
- TRANSFER_ABORT_NONE = 0x00,
- TRANSFER_ABORT_ERROR = 0x01,
- TRANSFER_ABORT_MAX_PLAYERS = 0x02, // Transfer Aborted: instance is full
- TRANSFER_ABORT_NOT_FOUND = 0x03, // Transfer Aborted: instance not found
- TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x04, // You have entered too many instances recently.
- TRANSFER_ABORT_ZONE_IN_COMBAT = 0x06, // Unable to zone in while an encounter is in progress.
- TRANSFER_ABORT_INSUF_EXPAN_LVL = 0x07, // You must have <TBC, WotLK> expansion installed to access this area.
- TRANSFER_ABORT_DIFFICULTY = 0x08, // <Normal, Heroic, Epic> difficulty mode is not available for %s.
- TRANSFER_ABORT_UNIQUE_MESSAGE = 0x09, // Until you've escaped TLK's grasp, you cannot leave this place!
- TRANSFER_ABORT_TOO_MANY_REALM_INSTANCES = 0x0A, // Additional instances cannot be launched, please try again later.
- TRANSFER_ABORT_NEED_GROUP = 0x0B, // 3.1
- TRANSFER_ABORT_NOT_FOUND1 = 0x0C, // 3.1
- TRANSFER_ABORT_NOT_FOUND2 = 0x0D, // 3.1
- TRANSFER_ABORT_NOT_FOUND3 = 0x0E, // 3.2
- TRANSFER_ABORT_REALM_ONLY = 0x0F, // All players on party must be from the same realm.
- TRANSFER_ABORT_MAP_NOT_ALLOWED = 0x10 // Map can't be entered at this time.
+ TRANSFER_ABORT_NONE = 0x00,
+ TRANSFER_ABORT_ERROR = 0x01,
+ TRANSFER_ABORT_MAX_PLAYERS = 0x02, // Transfer Aborted: instance is full
+ TRANSFER_ABORT_NOT_FOUND = 0x03, // Transfer Aborted: instance not found
+ TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x04, // You have entered too many instances recently.
+ TRANSFER_ABORT_ZONE_IN_COMBAT = 0x06, // Unable to zone in while an encounter is in progress.
+ TRANSFER_ABORT_INSUF_EXPAN_LVL = 0x07, // You must have <TBC, WotLK> expansion installed to access this area.
+ TRANSFER_ABORT_DIFFICULTY = 0x08, // <Normal, Heroic, Epic> difficulty mode is not available for %s.
+ TRANSFER_ABORT_UNIQUE_MESSAGE = 0x09, // Until you've escaped TLK's grasp, you cannot leave this place!
+ TRANSFER_ABORT_TOO_MANY_REALM_INSTANCES = 0x0A, // Additional instances cannot be launched, please try again later.
+ TRANSFER_ABORT_NEED_GROUP = 0x0B, // 3.1
+ TRANSFER_ABORT_NOT_FOUND1 = 0x0C, // 3.1
+ TRANSFER_ABORT_NOT_FOUND2 = 0x0D, // 3.1
+ TRANSFER_ABORT_NOT_FOUND3 = 0x0E, // 3.2
+ TRANSFER_ABORT_REALM_ONLY = 0x0F, // All players on party must be from the same realm.
+ TRANSFER_ABORT_MAP_NOT_ALLOWED = 0x10, // Map can't be entered at this time.
+ TRANSFER_ABORT_LOCKED_TO_DIFFERENT_INSTANCE = 0x12, // 4.2.2
+ TRANSFER_ABORT_ALREADY_COMPLETED_ENCOUNTER = 0x13 // 4.2.2
};
enum InstanceResetWarningType
@@ -772,7 +844,9 @@ enum PlayerChatTag
CHAT_TAG_DND = 0x02,
CHAT_TAG_GM = 0x04,
CHAT_TAG_COM = 0x08, // Commentator
- CHAT_TAG_DEV = 0x10
+ CHAT_TAG_DEV = 0x10,
+ CHAT_TAG_BOSS_SOUND = 0x20, // Plays "RaidBossEmoteWarning" sound on raid boss emote/whisper
+ CHAT_TAG_MOBILE = 0x40
};
enum PlayedTimeIndex
@@ -819,6 +893,9 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES = 30,
PLAYER_LOGIN_QUERY_LOAD_SEASONAL_QUEST_STATUS = 31,
PLAYER_LOGIN_QUERY_LOAD_MONTHLY_QUEST_STATUS = 32,
+ PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE = 33,
+ PLAYER_LOGIN_QUERY_LOAD_CURRENCY = 34,
+ PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES = 35,
MAX_PLAYER_LOGIN_QUERY
};
@@ -836,7 +913,7 @@ enum PlayerDelayedOperations
// Player summoning auto-decline time (in secs)
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
// Maximum money amount : 2^31 - 1
-extern uint32 const MAX_MONEY_AMOUNT;
+extern uint64 const MAX_MONEY_AMOUNT;
struct InstancePlayerBind
{
@@ -852,7 +929,6 @@ struct AccessRequirement
{
uint8 levelMin;
uint8 levelMax;
- uint16 item_level;
uint32 item;
uint32 item2;
uint32 quest_A;
@@ -868,12 +944,6 @@ enum CharDeleteMethod
// the name gets freed up and appears as deleted ingame
};
-enum CurrencyItems
-{
- ITEM_HONOR_POINTS_ID = 43308,
- ITEM_ARENA_POINTS_ID = 43307
-};
-
enum ReferAFriendError
{
ERR_REFER_A_FRIEND_NONE = 0x00,
@@ -920,14 +990,14 @@ class PlayerTaxi
bool IsTaximaskNodeKnown(uint32 nodeidx) const
{
- uint8 field = uint8((nodeidx - 1) / 32);
- uint32 submask = 1 << ((nodeidx-1) % 32);
+ uint8 field = uint8((nodeidx - 1) / 8);
+ uint32 submask = 1 << ((nodeidx-1) % 8);
return (m_taximask[field] & submask) == submask;
}
bool SetTaximaskNode(uint32 nodeidx)
{
- uint8 field = uint8((nodeidx - 1) / 32);
- uint32 submask = 1 << ((nodeidx - 1) % 32);
+ uint8 field = uint8((nodeidx - 1) / 8);
+ uint32 submask = 1 << ((nodeidx- 1) % 8);
if ((m_taximask[field] & submask) != submask)
{
m_taximask[field] |= submask;
@@ -968,12 +1038,14 @@ class Player;
struct BGData
{
BGData() : bgInstanceID(0), bgTypeID(BATTLEGROUND_TYPE_NONE), bgAfkReportedCount(0), bgAfkReportedTimer(0),
- bgTeam(0), mountSpell(0) { ClearTaxiPath(); }
+ bgTeam(0), mountSpell(0) { bgQueuesJoinedTime.clear(); ClearTaxiPath(); }
uint32 bgInstanceID; ///< This variable is set to bg->m_InstanceID,
/// when player is teleported to BG - (it is battleground's GUID)
BattlegroundTypeId bgTypeID;
+ std::map<uint32, uint32> bgQueuesJoinedTime;
+
std::set<uint32> bgAfkReporter;
uint8 bgAfkReportedCount;
time_t bgAfkReportedTimer;
@@ -989,6 +1061,33 @@ struct BGData
bool HasTaxiPath() const { return taxiPath[0] && taxiPath[1]; }
};
+struct VoidStorageItem
+{
+ VoidStorageItem()
+ {
+ ItemId = 0;
+ ItemEntry = 0;
+ CreatorGuid = 0;
+ ItemRandomPropertyId = 0;
+ ItemSuffixFactor = 0;
+ }
+
+ VoidStorageItem(uint64 id, uint32 entry, uint32 creator, uint32 randomPropertyId, uint32 suffixFactor)
+ {
+ ItemId = id;
+ ItemEntry = entry;
+ CreatorGuid = creator;
+ ItemRandomPropertyId = randomPropertyId;
+ ItemSuffixFactor = suffixFactor;
+ }
+
+ uint64 ItemId;
+ uint32 ItemEntry;
+ uint32 CreatorGuid;
+ uint32 ItemRandomPropertyId;
+ uint32 ItemSuffixFactor;
+};
+
class TradeData
{
public: // constructors
@@ -1010,8 +1109,8 @@ class TradeData
Item* GetSpellCastItem() const;
bool HasSpellCastItem() const { return m_spellCastItem != 0; }
- uint32 GetMoney() const { return m_money; }
- void SetMoney(uint32 money);
+ uint64 GetMoney() const { return m_money; }
+ void SetMoney(uint64 money);
bool IsAccepted() const { return m_accepted; }
void SetAccepted(bool state, bool crosssend = false);
@@ -1031,7 +1130,7 @@ class TradeData
bool m_accepted; // m_player press accept for trade list
bool m_acceptProccess; // one from player/trader press accept and this processed
- uint32 m_money; // m_player place money to trade
+ uint64 m_money; // m_player place money to trade
uint32 m_spell; // m_player apply spell to non-traded slot item
uint64 m_spellCastItem; // applied spell cast by item use
@@ -1039,6 +1138,15 @@ class TradeData
uint64 m_items[TRADE_SLOT_COUNT]; // traded items from m_player side including non-traded slot
};
+struct ResurrectionData
+{
+ uint64 GUID;
+ WorldLocation Location;
+ uint32 Health;
+ uint32 Mana;
+ uint32 Aura;
+};
+
class KillRewarder
{
public:
@@ -1071,6 +1179,50 @@ private:
bool _isPvP;
};
+struct PlayerTalentInfo
+{
+ PlayerTalentInfo() :
+ FreeTalentPoints(0), UsedTalentCount(0), QuestRewardedTalentCount(0),
+ ResetTalentsCost(0), ResetTalentsTime(0),
+ ActiveSpec(0), SpecsCount(1)
+ {
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ {
+ SpecInfo[i].Talents = new PlayerTalentMap();
+ memset(SpecInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32));
+ SpecInfo[i].TalentTree = 0;
+ }
+ }
+
+ ~PlayerTalentInfo()
+ {
+ for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ {
+ for (PlayerTalentMap::const_iterator itr = SpecInfo[i].Talents->begin(); itr != SpecInfo[i].Talents->end(); ++itr)
+ delete itr->second;
+ delete SpecInfo[i].Talents;
+ }
+ }
+
+ struct TalentSpecInfo
+ {
+ PlayerTalentMap* Talents;
+ uint32 Glyphs[MAX_GLYPH_SLOT_INDEX];
+ uint32 TalentTree;
+ } SpecInfo[MAX_TALENT_SPECS];
+
+ uint32 FreeTalentPoints;
+ uint32 UsedTalentCount;
+ uint32 QuestRewardedTalentCount;
+ uint32 ResetTalentsCost;
+ time_t ResetTalentsTime;
+ uint8 ActiveSpec;
+ uint8 SpecsCount;
+
+private:
+ PlayerTalentInfo(PlayerTalentInfo const&);
+};
+
class Player : public Unit, public GridObject<Player>
{
friend class WorldSession;
@@ -1103,13 +1255,12 @@ class Player : public Unit, public GridObject<Player>
void Update(uint32 time);
- static bool BuildEnumData(PreparedQueryResult result, WorldPacket* data);
+ static bool BuildEnumData(PreparedQueryResult result, ByteBuffer* dataBuffer, ByteBuffer* bitBuffer);
void SetInWater(bool apply);
bool IsInWater() const { return m_isInWater; }
bool IsUnderWater() const;
- bool IsFalling() { return GetPositionZ() < m_lastFallZ; }
void SendInitialPacketsBeforeAddToMap();
void SendInitialPacketsAfterAddToMap();
@@ -1149,8 +1300,6 @@ class Player : public Unit, public GridObject<Player>
void SetTaxiCheater(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_TAXICHEAT; else m_ExtraFlags &= ~PLAYER_EXTRA_TAXICHEAT; }
bool isGMVisible() const { return !(m_ExtraFlags & PLAYER_EXTRA_GM_INVISIBLE); }
void SetGMVisible(bool on);
- bool Has310Flyer(bool checkAllSpells, uint32 excludeSpellId = 0);
- void SetHas310Flyer(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_HAS_310_FLYER; else m_ExtraFlags &= ~PLAYER_EXTRA_HAS_310_FLYER; }
void SetPvPDeath(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_PVP_DEATH; else m_ExtraFlags &= ~PLAYER_EXTRA_PVP_DEATH; }
void GiveXP(uint32 xp, Unit* victim, float group_rate=1.0f);
@@ -1191,7 +1340,6 @@ class Player : public Unit, public GridObject<Player>
Pet* GetPet() const;
Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime);
void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false);
- uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn
/// Handles said message in regular chat based on declared language and in config pre-defined Range.
void Say(std::string const& text, const uint32 language);
@@ -1201,6 +1349,7 @@ class Player : public Unit, public GridObject<Player>
void TextEmote(std::string const& text);
/// Handles whispers from Addons and players based on sender, receiver's guid and language.
void Whisper(std::string const& text, const uint32 language, uint64 receiver);
+ void WhisperAddon(std::string const& text, std::string const& prefix, Player* receiver);
/*********************************************************/
/*** STORAGE SYSTEM ***/
@@ -1271,11 +1420,36 @@ class Player : public Unit, public GridObject<Player>
void AddRefundReference(uint32 it);
void DeleteRefundReference(uint32 it);
+ /// send initialization of new currency for client
+ void SendNewCurrency(uint32 id) const;
+ /// send full data about all currencies to client
+ void SendCurrencies() const;
+ /// send conquest currency points and their cap week/arena
+ void SendPvpRewards() const;
+ /// return count of currency witch has plr
+ uint32 GetCurrency(uint32 id, bool usePrecision) const;
+ /// return count of currency gaind on current week
+ uint32 GetCurrencyOnWeek(uint32 id, bool usePrecision) const;
+ /// return week cap by currency id
+ uint32 GetCurrencyWeekCap(uint32 id, bool usePrecision) const;
+ /// return presence related currency
+ bool HasCurrency(uint32 id, uint32 count) const;
+ /// initialize currency count for custom initialization at create character
+ void SetCurrency(uint32 id, uint32 count, bool printLog = true);
+ void ResetCurrencyWeekCap();
+
+ /**
+ * @name ModifyCurrency
+ * @brief Change specific currency and send result to client
+
+ * @param id currency entry from CurrencyTypes.dbc
+ * @param count integer value for adding/removing curent currency
+ * @param printLog used on SMSG_UPDATE_CURRENCY
+ * @param ignore gain multipliers
+ */
+ void ModifyCurrency(uint32 id, int32 count, bool printLog = true, bool ignoreMultipliers = false);
+
void ApplyEquipCooldown(Item* pItem);
- void SetAmmo(uint32 item);
- void RemoveAmmo();
- float GetAmmoDPS() const { return m_ammoDPS; }
- bool CheckAmmoCompatibility(const ItemTemplate* ammo_proto) const;
void QuickEquipItem(uint16 pos, Item* pItem);
void VisualizeItem(uint8 slot, Item* pItem);
void SetVisibleItemSlot(uint8 slot, Item* pItem);
@@ -1296,10 +1470,9 @@ class Player : public Unit, public GridObject<Player>
void AddItemToBuyBackSlot(Item* pItem);
Item* GetItemFromBuyBackSlot(uint32 slot);
void RemoveItemFromBuyBackSlot(uint32 slot, bool del);
- uint32 GetMaxKeyringSize() const { return KEYRING_SLOT_END-KEYRING_SLOT_START; }
void SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2 = NULL, uint32 itemid = 0);
void SendBuyError(BuyResult msg, Creature* creature, uint32 item, uint32 param);
- void SendSellError(SellResult msg, Creature* creature, uint64 guid, uint32 param);
+ void SendSellError(SellResult msg, Creature* creature, uint64 guid);
void AddWeaponProficiency(uint32 newflag) { m_WeaponProficiency |= newflag; }
void AddArmorProficiency(uint32 newflag) { m_ArmorProficiency |= newflag; }
uint32 GetWeaponProficiency() const { return m_WeaponProficiency; }
@@ -1308,6 +1481,7 @@ class Player : public Unit, public GridObject<Player>
bool IsTwoHandUsed() const;
void SendNewItem(Item* item, uint32 count, bool received, bool created, bool broadcast = false);
bool BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot);
+ bool BuyCurrencyFromVendorSlot(uint64 vendorGuid, uint32 vendorSlot, uint32 currency, uint32 count);
bool _StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot, int32 price, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore);
float GetReputationPriceDiscount(Creature const* creature) const;
@@ -1327,6 +1501,7 @@ class Player : public Unit, public GridObject<Player>
void AddEnchantmentDuration(Item* item, EnchantmentSlot slot, uint32 duration);
void ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool apply_dur = true, bool ignore_condition = false);
void ApplyEnchantment(Item* item, bool apply);
+ void ApplyReforgeEnchantment(Item* item, bool apply);
void UpdateSkillEnchantments(uint16 skill_id, uint16 curr_value, uint16 new_value);
void SendEnchantmentDurations();
void BuildEnchantmentsInfoData(WorldPacket* data);
@@ -1441,14 +1616,13 @@ class Player : public Unit, public GridObject<Player>
void UpdateForQuestWorldObjects();
bool CanShareQuest(uint32 questId) const;
- void SendQuestComplete(uint32 questId);
+ void SendQuestComplete(Quest const* quest);
void SendQuestReward(Quest const* quest, uint32 XP);
void SendQuestFailed(uint32 questId, InventoryResult reason = EQUIP_ERR_OK);
void SendQuestTimerFailed(uint32 questId);
void SendCanTakeQuestResponse(QuestFailedReason msg) const;
void SendQuestConfirmAccept(Quest const* quest, Player* pReceiver);
void SendPushToPartyResponse(Player* player, uint8 msg);
- void SendQuestUpdateAddItem(Quest const* quest, uint32 itemIdx, uint16 count);
void SendQuestUpdateAddCreatureOrGo(Quest const* quest, uint64 guid, uint32 creatureOrGOIdx, uint16 oldCount, uint16 addCount);
void SendQuestUpdateAddPlayer(Quest const* quest, uint16 oldCount, uint16 addCount);
@@ -1461,6 +1635,17 @@ class Player : public Unit, public GridObject<Player>
void AddTimedQuest(uint32 questId) { m_timedquests.insert(questId); }
void RemoveTimedQuest(uint32 questId) { m_timedquests.erase(questId); }
+ void SaveCUFProfile(uint8 id, CUFProfile* profile) { delete _CUFProfiles[id]; _CUFProfiles[id] = profile; } ///> Replaces a CUF profile at position 0-4
+ CUFProfile* GetCUFProfile(uint8 id) const { return _CUFProfiles[id]; } ///> Retrieves a CUF profile at position 0-4
+ uint8 GetCUFProfilesCount() const
+ {
+ uint8 count = 0;
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ if (_CUFProfiles[i])
+ ++count;
+ return count;
+ }
+
bool HasPvPForcingQuest() const;
/*********************************************************/
@@ -1478,6 +1663,8 @@ class Player : public Unit, public GridObject<Player>
static bool LoadPositionFromDB(uint32& mapid, float& x, float& y, float& z, float& o, bool& in_flight, uint64 guid);
static bool IsValidGender(uint8 Gender) { return Gender <= GENDER_FEMALE; }
+ static bool IsValidClass(uint8 Class) { return ((1 << (Class - 1)) & CLASSMASK_ALL_PLAYABLE) != 0; }
+ static bool IsValidRace(uint8 Race) { return ((1 << (Race - 1)) & RACEMASK_ALL_PLAYABLE) != 0; }
/*********************************************************/
/*** SAVE SYSTEM ***/
@@ -1509,11 +1696,11 @@ class Player : public Unit, public GridObject<Player>
void setRegenTimerCount(uint32 time) {m_regenTimerCount = time;}
void setWeaponChangeTimer(uint32 time) {m_weaponChangeTimer = time;}
- uint32 GetMoney() const { return GetUInt32Value(PLAYER_FIELD_COINAGE); }
- bool ModifyMoney(int32 amount, bool sendError = true);
- bool HasEnoughMoney(uint32 amount) const { return (GetMoney() >= amount); }
- bool HasEnoughMoney(int32 amount) const;
- void SetMoney(uint32 value);
+ uint64 GetMoney() const { return GetUInt64Value(PLAYER_FIELD_COINAGE); }
+ bool ModifyMoney(int64 amount, bool sendError = true);
+ bool HasEnoughMoney(uint64 amount) const { return (GetMoney() >= amount); }
+ bool HasEnoughMoney(int64 amount) const;
+ void SetMoney(uint64 value);
RewardedQuestSet const& getRewardedQuests() const { return m_RewardedQuests; }
QuestStatusMap& getQuestStatusMap() { return m_QuestStatus; }
@@ -1576,6 +1763,7 @@ class Player : public Unit, public GridObject<Player>
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const;
bool IsSpellFitByClassAndRace(uint32 spell_id) const;
bool IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const;
+ bool IsCurrentSpecMasterySpell(SpellInfo const* spellInfo) const;
void SendProficiency(ItemClass itemClass, uint32 itemSubclassMask);
void SendInitialSpells();
@@ -1593,39 +1781,55 @@ class Player : public Unit, public GridObject<Player>
void RemoveTemporarySpell(uint32 spellId);
void SetReputation(uint32 factionentry, uint32 value);
uint32 GetReputation(uint32 factionentry) const;
- std::string const& GetGuildName();
- uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); }
- void SetFreeTalentPoints(uint32 points);
+ std::string GetGuildName();
+
+ // Talents
+ uint32 GetFreeTalentPoints() const { return _talentMgr->FreeTalentPoints; }
+ void SetFreeTalentPoints(uint32 points) { _talentMgr->FreeTalentPoints = points; }
+ uint32 GetUsedTalentCount() const { return _talentMgr->UsedTalentCount; }
+ void SetUsedTalentCount(uint32 talents) { _talentMgr->UsedTalentCount = talents; }
+ uint32 GetQuestRewardedTalentCount() const { return _talentMgr->QuestRewardedTalentCount; }
+ void AddQuestRewardedTalentCount(uint32 points) { _talentMgr->QuestRewardedTalentCount += points; }
+ uint32 GetTalentResetCost() const { return _talentMgr->ResetTalentsCost; }
+ void SetTalentResetCost(uint32 cost) { _talentMgr->ResetTalentsCost = cost; }
+ uint32 GetTalentResetTime() const { return _talentMgr->ResetTalentsTime; }
+ void SetTalentResetTime(time_t time_) { _talentMgr->ResetTalentsTime = time_; }
+ uint32 GetPrimaryTalentTree(uint8 spec) const { return _talentMgr->SpecInfo[spec].TalentTree; }
+ void SetPrimaryTalentTree(uint8 spec, uint32 tree) { _talentMgr->SpecInfo[spec].TalentTree = tree; }
+ uint8 GetActiveSpec() const { return _talentMgr->ActiveSpec; }
+ void SetActiveSpec(uint8 spec){ _talentMgr->ActiveSpec = spec; }
+ uint8 GetSpecsCount() const { return _talentMgr->SpecsCount; }
+ void SetSpecsCount(uint8 count) { _talentMgr->SpecsCount = count; }
+
bool ResetTalents(bool no_cost = false);
- uint32 ResetTalentsCost() const;
+ uint32 GetNextResetTalentsCost() const;
void InitTalentForLevel();
void BuildPlayerTalentsInfoData(WorldPacket* data);
void BuildPetTalentsInfoData(WorldPacket* data);
void SendTalentsInfoData(bool pet);
- void LearnTalent(uint32 talentId, uint32 talentRank);
+ bool LearnTalent(uint32 talentId, uint32 talentRank);
void LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank);
-
bool AddTalent(uint32 spellId, uint8 spec, bool learning);
bool HasTalent(uint32 spell_id, uint8 spec) const;
-
uint32 CalculateTalentsPoints() const;
// Dual Spec
void UpdateSpecCount(uint8 count);
- uint32 GetActiveSpec() { return m_activeSpec; }
- void SetActiveSpec(uint8 spec){ m_activeSpec = spec; }
- uint8 GetSpecsCount() { return m_specsCount; }
- void SetSpecsCount(uint8 count) { m_specsCount = count; }
void ActivateSpec(uint8 spec);
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); }
+
+ uint32 GetGlyphSlot(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
void SetGlyph(uint8 slot, uint32 glyph);
- uint32 GetGlyph(uint8 slot) { return m_Glyphs[m_activeSpec][slot]; }
+ uint32 GetGlyph(uint8 spec, uint8 slot) const { return _talentMgr->SpecInfo[spec].Glyphs[slot]; }
- uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); }
- void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2, profs); }
+ PlayerTalentMap const* GetTalentMap(uint8 spec) const { return _talentMgr->SpecInfo[spec].Talents; }
+ PlayerTalentMap* GetTalentMap(uint8 spec) { return _talentMgr->SpecInfo[spec].Talents; }
+ ActionButtonList const& GetActionButtons() const { return m_actionButtons; }
+
+ uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS); }
+ void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS, profs); }
void InitPrimaryProfessions();
PlayerSpellMap const& GetSpellMap() const { return m_spells; }
@@ -1654,6 +1858,7 @@ class Player : public Unit, public GridObject<Player>
void RemoveSpellCooldown(uint32 spell_id, bool update = false);
void RemoveSpellCategoryCooldown(uint32 cat, bool update = false);
void SendClearCooldown(uint32 spell_id, Unit* target);
+ void SendClearAllCooldowns(Unit* target);
GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; }
@@ -1666,10 +1871,22 @@ class Player : public Unit, public GridObject<Player>
void SetLastPotionId(uint32 item_id) { m_lastPotionId = item_id; }
void UpdatePotionCooldown(Spell* spell = NULL);
- void setResurrectRequestData(uint64 guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana);
- void clearResurrectRequestData() { setResurrectRequestData(0, 0, 0.0f, 0.0f, 0.0f, 0, 0); }
- bool isResurrectRequestedBy(uint64 guid) const { return m_resurrectGUID == guid; }
- bool isResurrectRequested() const { return m_resurrectGUID != 0; }
+ void SetResurrectRequestData(Unit* caster, uint32 health, uint32 mana, uint32 appliedAura);
+ void ClearResurrectRequestData()
+ {
+ delete _resurrectionData;
+ _resurrectionData = NULL;
+ }
+
+ bool IsResurrectRequestedBy(uint64 guid) const
+ {
+ if (!IsResurrectRequested())
+ return false;
+
+ return _resurrectionData->GUID == guid;
+ }
+
+ bool IsResurrectRequested() const { return _resurrectionData != NULL; }
void ResurrectUsingRequestData();
uint8 getCinematic() { return m_cinematic; }
@@ -1678,7 +1895,7 @@ class Player : public Unit, public GridObject<Player>
ActionButton* addActionButton(uint8 button, uint32 action, uint8 type);
void removeActionButton(uint8 button);
ActionButton const* GetActionButton(uint8 button);
- void SendInitialActionButtons() const { SendActionButtons(1); }
+ void SendInitialActionButtons() const { SendActionButtons(0); }
void SendActionButtons(uint32 state) const;
bool IsActionButtonDataValid(uint8 button, uint32 action, uint8 type);
@@ -1714,11 +1931,13 @@ class Player : public Unit, public GridObject<Player>
void RemoveFromGroup(RemoveMethod method = GROUP_REMOVEMETHOD_DEFAULT) { RemoveFromGroup(GetGroup(), GetGUID(), method); }
void SendUpdateToOutOfRangeGroupMembers();
- void SetInGuild(uint32 GuildId) { SetUInt32Value(PLAYER_GUILDID, GuildId); }
+ void SetInGuild(uint32 guildId);
void SetRank(uint8 rankId) { SetUInt32Value(PLAYER_GUILDRANK, rankId); }
uint8 GetRank() const { return uint8(GetUInt32Value(PLAYER_GUILDRANK)); }
+ void SetGuildLevel(uint32 level) { SetUInt32Value(PLAYER_GUILDLEVEL, level); }
+ uint32 GetGuildLevel() { return GetUInt32Value(PLAYER_GUILDLEVEL); }
void SetGuildIdInvited(uint32 GuildId) { m_GuildIdInvited = GuildId; }
- uint32 GetGuildId() const { return GetUInt32Value(PLAYER_GUILDID); }
+ uint32 GetGuildId() const { return GetUInt32Value(OBJECT_FIELD_DATA); /* return only lower part */ }
Guild* GetGuild();
static uint32 GetGuildIdFromDB(uint64 guid);
static uint8 GetRankFromDB(uint64 guid);
@@ -1734,6 +1953,7 @@ class Player : public Unit, public GridObject<Player>
uint32 GetArenaPersonalRating(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING); }
void SetArenaTeamIdInvited(uint32 ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; }
uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; }
+ uint32 GetRBGPersonalRating() const { return 0; }
Difficulty GetDifficulty(bool isRaid) const { return isRaid ? m_raidDifficulty : m_dungeonDifficulty; }
Difficulty GetDungeonDifficulty() const { return m_dungeonDifficulty; }
@@ -1744,15 +1964,12 @@ class Player : public Unit, public GridObject<Player>
void StoreRaidMapDifficulty() { m_raidMapDifficulty = GetMap()->GetDifficulty(); }
bool UpdateSkill(uint32 skill_id, uint32 step);
- bool UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step);
+ bool UpdateSkillPro(uint16 skillId, int32 chance, uint32 step);
bool UpdateCraftSkill(uint32 spellid);
bool UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 RedLevel, uint32 Multiplicator = 1);
bool UpdateFishingSkill();
- uint32 GetBaseDefenseSkillValue() const { return GetBaseSkillValue(SKILL_DEFENSE); }
- uint32 GetBaseWeaponSkillValue(WeaponAttackType attType) const;
-
uint32 GetSpellByProto(ItemTemplate* proto);
float GetHealthBonusFromStamina();
@@ -1765,27 +1982,26 @@ class Player : public Unit, public GridObject<Player>
void UpdateArmor();
void UpdateMaxHealth();
void UpdateMaxPower(Powers power);
- void ApplyFeralAPBonus(int32 amount, bool apply);
void UpdateAttackPowerAndDamage(bool ranged = false);
- void UpdateShieldBlockValue();
void ApplySpellPowerBonus(int32 amount, bool apply);
void UpdateSpellDamageAndHealingBonus();
void ApplyRatingMod(CombatRating cr, int32 value, bool apply);
void UpdateRating(CombatRating cr);
void UpdateAllRatings();
+ void UpdateMastery();
+ bool CanUseMastery() const;
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override;
- void UpdateDefenseBonusesMod();
inline void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);}
float GetMeleeCritFromAgility();
void GetDodgeFromAgility(float &diminishing, float &nondiminishing);
- float GetMissPercentageFromDefence() const;
float GetSpellCritFromIntellect();
- float OCTRegenHPPerSpirit();
float OCTRegenMPPerSpirit();
float GetRatingMultiplier(CombatRating cr) const;
float GetRatingBonusValue(CombatRating cr) const;
+
+ /// Returns base spellpower bonus from spellpower stat on items, without spellpower from intellect stat
uint32 GetBaseSpellPowerBonus() const { return m_baseSpellPower; }
int32 GetSpellPenetrationItemMod() const { return m_spellPenetrationItemMod; }
@@ -1807,6 +2023,7 @@ class Player : public Unit, public GridObject<Player>
void ApplyHealthRegenBonus(int32 amount, bool apply);
void UpdateManaRegen();
void UpdateRuneRegen(RuneType rune);
+ void UpdateAllRunesRegen();
uint64 GetLootGUID() const { return m_lootGuid; }
void SetLootGUID(uint64 guid) { m_lootGuid = guid; }
@@ -1844,8 +2061,6 @@ class Player : public Unit, public GridObject<Player>
void SendMessageToSetInRange(WorldPacket* data, float dist, bool self, bool own_team_only);
void SendMessageToSet(WorldPacket* data, Player const* skipped_rcvr);
- void SendTeleportAckPacket();
-
Corpse* GetCorpse() const;
void SpawnCorpseBones();
void CreateCorpse();
@@ -1867,8 +2082,6 @@ class Player : public Unit, public GridObject<Player>
void StopMirrorTimers();
bool IsMirrorTimerActive(MirrorTimerType type);
- void SetMovement(PlayerMovementType pType);
-
bool CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone);
void JoinedChannel(Channel* c);
@@ -1877,10 +2090,6 @@ class Player : public Unit, public GridObject<Player>
void UpdateLocalChannels(uint32 newZone);
void LeaveLFGChannel();
- void UpdateDefense();
- void UpdateWeaponSkill (WeaponAttackType attType);
- void UpdateCombatSkills(Unit* victim, WeaponAttackType attType, bool defence);
-
void SetSkill(uint16 id, uint16 step, uint16 currVal, uint16 maxVal);
uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + temp bonus
uint16 GetPureMaxSkillValue(uint32 skill) const; // max
@@ -1914,7 +2123,7 @@ class Player : public Unit, public GridObject<Player>
bool IsAtRecruitAFriendDistance(WorldObject const* pOther) const;
void RewardPlayerAndGroupAtKill(Unit* victim, bool isBattleGround);
void RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject* pRewardSource);
- bool isHonorOrXPTarget(Unit* victim) const;
+ bool isHonorOrXPTarget(Unit const* victim) const;
bool GetsRecruitAFriendBonus(bool forXP);
uint8 GetGrantableLevels() { return m_grantableLevels; }
@@ -1935,15 +2144,10 @@ class Player : public Unit, public GridObject<Player>
/*********************************************************/
/*** PVP SYSTEM ***/
/*********************************************************/
+ // TODO: Properly implement correncies as of Cataclysm
void UpdateHonorFields();
bool RewardHonor(Unit* victim, uint32 groupsize, int32 honor = -1, bool pvptoken = false);
- uint32 GetHonorPoints() const { return GetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY); }
- uint32 GetArenaPoints() const { return GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY); }
- void ModifyHonorPoints(int32 value, SQLTransaction trans = SQLTransaction(nullptr)); //! If trans is specified, honor save query will be added to trans
- void ModifyArenaPoints(int32 value, SQLTransaction trans = SQLTransaction(nullptr)); //! If trans is specified, arena point save query will be added to trans
uint32 GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot) const;
- void SetHonorPoints(uint32 value);
- void SetArenaPoints(uint32 value);
//End of PvP System
@@ -1959,7 +2163,7 @@ class Player : public Unit, public GridObject<Player>
int32 CalculateCorpseReclaimDelay(bool load = false);
void SendCorpseReclaimDelay(uint32 delay);
- uint32 GetShieldBlockValue() const; // overwrite Unit version (virtual)
+ uint32 GetBlockPercent() const { return GetUInt32Value(PLAYER_SHIELD_BLOCK); }
bool CanParry() const { return m_canParry; }
void SetCanParry(bool value);
bool CanBlock() const { return m_canBlock; }
@@ -1989,7 +2193,6 @@ class Player : public Unit, public GridObject<Player>
void _ApplyAllLevelScaleItemMods(bool apply);
void _ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply, bool only_level_scale = false);
void _ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv, bool apply);
- void _ApplyAmmoBonuses();
bool EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot);
void ToggleMetaGemsActive(uint8 exceptslot, bool apply);
void CorrectMetaGemEnchants(uint8 slot, bool apply);
@@ -2032,6 +2235,16 @@ class Player : public Unit, public GridObject<Player>
BattlegroundTypeId GetBattlegroundTypeId() const { return m_bgData.bgTypeID; }
Battleground* GetBattleground() const;
+ uint32 GetBattlegroundQueueJoinTime(uint32 bgTypeId) const { return m_bgData.bgQueuesJoinedTime.find(bgTypeId)->second; }
+ void AddBattlegroundQueueJoinTime(uint32 bgTypeId, uint32 joinTime)
+ {
+ m_bgData.bgQueuesJoinedTime[bgTypeId] = joinTime;
+ }
+ void RemoveBattlegroundQueueJoinTime(uint32 bgTypeId)
+ {
+ m_bgData.bgQueuesJoinedTime.erase(m_bgData.bgQueuesJoinedTime.find(bgTypeId)->second);
+ }
+
bool InBattlegroundQueue() const;
BattlegroundQueueTypeId GetBattlegroundQueueTypeId(uint32 index) const;
@@ -2157,6 +2370,8 @@ class Player : public Unit, public GridObject<Player>
void UpdateVisibilityOf(WorldObject* target);
void UpdateTriggerVisibility();
+ void UpdatePhasing();
+
template<class T>
void UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow);
@@ -2257,7 +2472,8 @@ class Player : public Unit, public GridObject<Player>
RuneType GetBaseRune(uint8 index) const { return RuneType(m_runes->runes[index].BaseRune); }
RuneType GetCurrentRune(uint8 index) const { return RuneType(m_runes->runes[index].CurrentRune); }
uint32 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; }
- uint32 GetRuneBaseCooldown(uint8 index);
+ uint32 GetRuneBaseCooldown(uint8 index) const { return GetRuneTypeBaseCooldown(GetBaseRune(index)); }
+ uint32 GetRuneTypeBaseCooldown(RuneType runeType) const;
bool IsBaseRuneSlotsOnCooldown(RuneType runeType) const;
RuneType GetLastUsedRune() { return m_runes->lastUsedRune; }
void SetLastUsedRune(RuneType type) { m_runes->lastUsedRune = type; }
@@ -2274,11 +2490,12 @@ class Player : public Unit, public GridObject<Player>
void InitRunes();
void SendRespondInspectAchievements(Player* player) const;
+ uint32 GetAchievementPoints() const;
bool HasAchieved(uint32 achievementId) const;
void ResetAchievements();
void CheckAllAchievementCriteria();
- void ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, bool evenIfCriteriaComplete = false);
- void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, Unit* unit = NULL);
+ void ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, bool evenIfCriteriaComplete = false);
+ void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, Unit* unit = NULL);
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
void CompletedAchievement(AchievementEntry const* entry);
@@ -2302,11 +2519,13 @@ class Player : public Unit, public GridObject<Player>
bool IsInWhisperWhiteList(uint64 guid);
void RemoveFromWhisperWhiteList(uint64 guid) { WhisperList.remove(guid); }
- bool SetDisableGravity(bool disable, bool packetOnly /* = false */);
- bool SetCanFly(bool apply);
- bool SetWaterWalking(bool apply, bool packetOnly = false);
- bool SetFeatherFall(bool apply, bool packetOnly = false);
- bool SetHover(bool enable, bool packetOnly = false);
+ void ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::ExtraMovementStatusElement* extras = NULL);
+
+ /*! These methods send different packets to the client in apply and unapply case.
+ These methods are only sent to the current unit.
+ */
+ void SendMovementSetCanTransitionBetweenSwimAndFly(bool apply);
+ void SendMovementSetCollisionHeight(float height);
bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); }
@@ -2318,11 +2537,26 @@ class Player : public Unit, public GridObject<Player>
bool IsLoading() const;
+ // Void Storage
+ bool IsVoidStorageUnlocked() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_VOID_UNLOCKED); }
+ void UnlockVoidStorage() { SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_VOID_UNLOCKED); }
+ void LockVoidStorage() { RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_VOID_UNLOCKED); }
+ uint8 GetNextVoidStorageFreeSlot() const;
+ uint8 GetNumOfVoidStorageFreeSlots() const;
+ uint8 AddVoidStorageItem(const VoidStorageItem& item);
+ void AddVoidStorageItemAtSlot(uint8 slot, const VoidStorageItem& item);
+ void DeleteVoidStorageItem(uint8 slot);
+ bool SwapVoidStorageItem(uint8 oldSlot, uint8 newSlot);
+ VoidStorageItem* GetVoidStorageItem(uint8 slot) const;
+ VoidStorageItem* GetVoidStorageItem(uint64 id, uint8& slot) const;
+
protected:
// Gamemaster whisper whitelist
WhisperListContainer WhisperList;
uint32 m_regenTimerCount;
- float m_powerFraction[MAX_POWERS];
+ uint32 m_holyPowerRegenTimerCount;
+ uint32 m_focusRegenTimerCount;
+ float m_powerFraction[MAX_POWERS_PER_CLASS];
uint32 m_contestedPvPTimer;
/*********************************************************/
@@ -2368,6 +2602,7 @@ class Player : public Unit, public GridObject<Player>
void _LoadGlyphAuras();
void _LoadBoundInstances(PreparedQueryResult result);
void _LoadInventory(PreparedQueryResult result, uint32 timeDiff);
+ void _LoadVoidStorage(PreparedQueryResult result);
void _LoadMailInit(PreparedQueryResult resultUnread, PreparedQueryResult resultDelivery);
void _LoadMail();
void _LoadMailedItems(Mail* mail);
@@ -2390,6 +2625,8 @@ class Player : public Unit, public GridObject<Player>
void _LoadGlyphs(PreparedQueryResult result);
void _LoadTalents(PreparedQueryResult result);
void _LoadInstanceTimeRestrictions(PreparedQueryResult result);
+ void _LoadCurrency(PreparedQueryResult result);
+ void _LoadCUFProfiles(PreparedQueryResult result);
/*********************************************************/
/*** SAVE SYSTEM ***/
@@ -2398,6 +2635,7 @@ class Player : public Unit, public GridObject<Player>
void _SaveActions(SQLTransaction& trans);
void _SaveAuras(SQLTransaction& trans);
void _SaveInventory(SQLTransaction& trans);
+ void _SaveVoidStorage(SQLTransaction& trans);
void _SaveMail(SQLTransaction& trans);
void _SaveQuestStatus(SQLTransaction& trans);
void _SaveDailyQuestStatus(SQLTransaction& trans);
@@ -2412,6 +2650,8 @@ class Player : public Unit, public GridObject<Player>
void _SaveTalents(SQLTransaction& trans);
void _SaveStats(SQLTransaction& trans);
void _SaveInstanceTimeRestrictions(SQLTransaction& trans);
+ void _SaveCurrency(SQLTransaction& trans);
+ void _SaveCUFProfiles(SQLTransaction& trans);
/*********************************************************/
/*** ENVIRONMENTAL SYSTEM ***/
@@ -2443,6 +2683,29 @@ class Player : public Unit, public GridObject<Player>
Item* m_items[PLAYER_SLOTS_COUNT];
uint32 m_currentBuybackSlot;
+ PlayerCurrenciesMap _currencyStorage;
+
+ /**
+ * @name GetCurrencyWeekCap
+ * @brief return week cap for selected currency
+
+ * @param CurrencyTypesEntry for which to retrieve weekly cap
+ */
+ uint32 GetCurrencyWeekCap(CurrencyTypesEntry const* currency) const;
+
+ /*
+ * @name GetCurrencyTotalCap
+ * @brief return total cap for selected currency
+
+ * @param CurrencyTypesEntry for which to retrieve total cap
+ */
+ uint32 GetCurrencyTotalCap(CurrencyTypesEntry const* currency) const;
+
+ /// Updates weekly conquest point cap (dynamic cap)
+ void UpdateConquestCurrencyCap(uint32 currency);
+
+ VoidStorageItem* _voidStorageItems[VOID_STORAGE_MAX_SLOT];
+
std::vector<Item*> m_itemUpdateQueue;
bool m_itemUpdateQueueBlocked;
@@ -2464,22 +2727,17 @@ class Player : public Unit, public GridObject<Player>
PlayerMails m_mail;
PlayerSpellMap m_spells;
- PlayerTalentMap* m_talents[MAX_TALENT_SPECS];
uint32 m_lastPotionId; // last used health/mana potion in combat, that block next potion use
GlobalCooldownMgr m_GlobalCooldownMgr;
- uint8 m_activeSpec;
- uint8 m_specsCount;
-
- uint32 m_Glyphs[MAX_TALENT_SPECS][MAX_GLYPH_SLOT_INDEX];
+ PlayerTalentInfo* _talentMgr;
ActionButtonList m_actionButtons;
float m_auraBaseMod[BASEMOD_END][MOD_END];
int16 m_baseRatingValue[MAX_COMBAT_RATING];
uint32 m_baseSpellPower;
- uint32 m_baseFeralAP;
uint32 m_baseManaRegen;
uint32 m_baseHealthRegen;
int32 m_spellPenetrationItemMod;
@@ -2493,10 +2751,7 @@ class Player : public Unit, public GridObject<Player>
void ResetTimeSync();
void SendTimeSync();
- uint64 m_resurrectGUID;
- uint32 m_resurrectMap;
- float m_resurrectX, m_resurrectY, m_resurrectZ;
- uint32 m_resurrectHealth, m_resurrectMana;
+ ResurrectionData* _resurrectionData;
WorldSession* m_session;
@@ -2531,7 +2786,6 @@ class Player : public Unit, public GridObject<Player>
bool m_canBlock;
bool m_canTitanGrip;
uint8 m_swingErrorMsg;
- float m_ammoDPS;
////////////////////Rest System/////////////////////
time_t time_inn_enter;
@@ -2542,10 +2796,6 @@ class Player : public Unit, public GridObject<Player>
float m_rest_bonus;
RestType rest_type;
////////////////////Rest System/////////////////////
- uint32 m_resetTalentsCost;
- time_t m_resetTalentsTime;
- uint32 m_usedTalentCount;
- uint32 m_questRewardTalentCount;
// Social
PlayerSocial *m_social;
@@ -2580,6 +2830,8 @@ class Player : public Unit, public GridObject<Player>
bool m_needsZoneUpdate;
+ CUFProfile* _CUFProfiles[MAX_CUF_PROFILES];
+
private:
// internal common parts for CanStore/StoreItem functions
InventoryResult CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemTemplate const* pProto, uint32& count, bool swap, Item* pSrcItem) const;
@@ -2591,6 +2843,7 @@ class Player : public Unit, public GridObject<Player>
std::set<uint32> m_refundableItems;
void SendRefundInfo(Item* item);
void RefundItem(Item* item);
+ void SendItemRefundResult(Item* item, ItemExtendedCostEntry const* iece, uint8 error);
// know currencies are not removed at any point (0 displayed)
void AddKnownCurrency(uint32 itemId);
@@ -2629,14 +2882,14 @@ class Player : public Unit, public GridObject<Player>
uint32 m_temporaryUnsummonedPetNumber;
uint32 m_oldpetspell;
- AchievementMgr* m_achievementMgr;
+ AchievementMgr<Player>* m_achievementMgr;
ReputationMgr* m_reputationMgr;
SpellCooldowns m_spellCooldowns;
uint32 m_ChampioningFaction;
- uint32 m_timeSyncCounter;
+ std::queue<uint32> m_timeSyncQueue;
uint32 m_timeSyncTimer;
uint32 m_timeSyncClient;
uint32 m_timeSyncServer;
@@ -2646,6 +2899,7 @@ class Player : public Unit, public GridObject<Player>
uint32 _pendingBindTimer;
uint32 _activeCheats;
+ uint32 _maxPersonalArenaRate;
};
void AddItemsSetItem(Player* player, Item* item);
diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp
index f2c2ada5666..c351aeac482 100644
--- a/src/server/game/Entities/Player/SocialMgr.cpp
+++ b/src/server/game/Entities/Player/SocialMgr.cpp
@@ -26,6 +26,7 @@
#include "World.h"
#include "Util.h"
#include "AccountMgr.h"
+#include "WorldSession.h"
PlayerSocial::PlayerSocial(): m_playerGUID()
{ }
diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp
index b8f5fd1833d..92aa34371f8 100644
--- a/src/server/game/Entities/Totem/Totem.cpp
+++ b/src/server/game/Entities/Totem/Totem.cpp
@@ -74,12 +74,9 @@ void Totem::InitStats(uint32 duration)
// Get spell cast by totem
if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(GetSpell()))
- if (totemSpell->CalcCastTime()) // If spell has cast time -> its an active totem
+ if (totemSpell->CalcCastTime(getLevel())) // If spell has cast time -> its an active totem
m_type = TOTEM_ACTIVE;
- if (GetEntry() == SENTRY_TOTEM_ENTRY)
- SetReactState(REACT_AGGRESSIVE);
-
m_duration = duration;
SetLevel(GetOwner()->getLevel());
@@ -88,13 +85,14 @@ void Totem::InitStats(uint32 duration)
void Totem::InitSummon()
{
if (m_type == TOTEM_PASSIVE && GetSpell())
- {
CastSpell(this, GetSpell(), true);
- }
// Some totems can have both instant effect and passive spell
if (GetSpell(1))
CastSpell(this, GetSpell(1), true);
+
+ if (m_Properties->Id == SUMMON_TYPE_TOTEM_FIRE && GetOwner()->HasAura(SPELL_TOTEMIC_WRATH_TALENT))
+ CastSpell(this, SPELL_TOTEMIC_WRATH, true);
}
void Totem::UnSummon(uint32 msTime)
@@ -120,11 +118,7 @@ void Totem::UnSummon(uint32 msTime)
GetOwner()->RemoveAurasDueToSpell(GetSpell(), GetGUID());
- // Remove Sentry Totem Aura
- if (GetEntry() == SENTRY_TOTEM_ENTRY)
- GetOwner()->RemoveAurasDueToSpell(SENTRY_TOTEM_SPELLID);
-
- //remove aura all party members too
+ // remove aura all party members too
if (Player* owner = GetOwner()->ToPlayer())
{
owner->SendAutoRepeatCancel(this);
diff --git a/src/server/game/Entities/Totem/Totem.h b/src/server/game/Entities/Totem/Totem.h
index da0398f3a96..5a2f3f5773a 100644
--- a/src/server/game/Entities/Totem/Totem.h
+++ b/src/server/game/Entities/Totem/Totem.h
@@ -28,9 +28,12 @@ enum TotemType
TOTEM_STATUE = 2 // copied straight from MaNGOS, may need more implementation to work
};
// Some Totems cast spells that are not in creature DB
-#define SENTRY_TOTEM_SPELLID 6495
-
-#define SENTRY_TOTEM_ENTRY 3968
+enum TotemSpells
+{
+ // Totemic Wrath
+ SPELL_TOTEMIC_WRATH_TALENT = 77746,
+ SPELL_TOTEMIC_WRATH = 77747
+};
class Totem : public Minion
{
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index d907274f8d1..0c22caed882 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -229,7 +229,6 @@ void Transport::AddPassenger(WorldObject* passenger)
if (_passengers.insert(passenger).second)
{
passenger->SetTransport(this);
- passenger->m_movementInfo.AddMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
passenger->m_movementInfo.transport.guid = GetGUID();
TC_LOG_DEBUG("entities.transport", "Object %s boarded transport %s.", passenger->GetName().c_str(), GetName().c_str());
@@ -259,7 +258,6 @@ void Transport::RemovePassenger(WorldObject* passenger)
if (erased || _staticPassengers.erase(passenger)) // static passenger can remove itself in case of grid unload
{
passenger->SetTransport(NULL);
- passenger->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
passenger->m_movementInfo.transport.Reset();
TC_LOG_DEBUG("entities.transport", "Object %s removed from transport %s.", passenger->GetName().c_str(), GetName().c_str());
@@ -285,7 +283,6 @@ Creature* Transport::CreateNPCPassenger(uint32 guid, CreatureData const* data)
float o = data->orientation;
creature->SetTransport(this);
- creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
creature->m_movementInfo.transport.guid = GetGUID();
creature->m_movementInfo.transport.pos.Relocate(x, y, z, o);
CalculatePassengerPosition(x, y, z, &o);
@@ -304,6 +301,15 @@ Creature* Transport::CreateNPCPassenger(uint32 guid, CreatureData const* data)
return NULL;
}
+ if (data->phaseid)
+ creature->SetInPhase(data->phaseid, false, true);
+ else if (data->phaseGroup)
+ for (auto phase : GetPhasesForGroup(data->phaseGroup))
+ creature->SetInPhase(phase, false, true);
+ else
+ for (auto phase : GetPhases()) // Set the creature to the transport's phases
+ creature->SetInPhase(phase, false, true);
+
if (!map->AddToMap(creature))
{
delete creature;
@@ -408,9 +414,11 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu
}
}
- uint32 phase = PHASEMASK_NORMAL;
+ std::set<uint32> phases;
if (summoner)
- phase = summoner->GetPhaseMask();
+ phases = summoner->GetPhases();
+ else
+ phases = GetPhases(); // If there was no summoner, try to use the transport phases
TempSummon* summon = NULL;
switch (mask)
@@ -436,16 +444,18 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu
pos.GetPosition(x, y, z, o);
CalculatePassengerPosition(x, y, z, &o);
- if (!summon->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, phase, entry, x, y, z, o, nullptr, vehId))
+ if (!summon->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, 0, entry, x, y, z, o, nullptr, vehId))
{
delete summon;
return NULL;
}
+ for (auto itr : phases)
+ summon->SetInPhase(itr, false, true);
+
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId);
summon->SetTransport(this);
- summon->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
summon->m_movementInfo.transport.guid = GetGUID();
summon->m_movementInfo.transport.pos.Relocate(pos);
summon->Relocate(x, y, z, o);
diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h
index e644417f1ac..7da8c11861c 100644
--- a/src/server/game/Entities/Transport/Transport.h
+++ b/src/server/game/Entities/Transport/Transport.h
@@ -27,7 +27,7 @@ struct CreatureData;
class Transport : public GameObject, public TransportBase
{
- friend Transport* TransportMgr::CreateTransport(uint32, uint32, Map*);
+ friend Transport* TransportMgr::CreateTransport(uint32, uint32, Map*, uint32, uint32);
Transport();
public:
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 04136221d0d..06179692845 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -108,9 +108,6 @@ bool Player::UpdateStats(Stats stat)
switch (stat)
{
- case STAT_STRENGTH:
- UpdateShieldBlockValue();
- break;
case STAT_AGILITY:
UpdateArmor();
UpdateAllCritPercentages();
@@ -131,24 +128,12 @@ bool Player::UpdateStats(Stats stat)
}
if (stat == STAT_STRENGTH)
- {
UpdateAttackPowerAndDamage(false);
- if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, stat))
- UpdateAttackPowerAndDamage(true);
- }
else if (stat == STAT_AGILITY)
{
UpdateAttackPowerAndDamage(false);
UpdateAttackPowerAndDamage(true);
}
- else
- {
- // Need update (exist AP from stat auras)
- if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT, stat))
- UpdateAttackPowerAndDamage(false);
- if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, stat))
- UpdateAttackPowerAndDamage(true);
- }
UpdateSpellDamageAndHealingBonus();
UpdateManaRegen();
@@ -208,8 +193,9 @@ bool Player::UpdateAllStats()
UpdateAllRatings();
UpdateAllCritPercentages();
UpdateAllSpellCritChances();
- UpdateDefenseBonusesMod();
- UpdateShieldBlockValue();
+ UpdateBlockPercentage();
+ UpdateParryPercentage();
+ UpdateDodgePercentage();
UpdateSpellDamageAndHealingBonus();
UpdateManaRegen();
UpdateExpertise(BASE_ATTACK);
@@ -247,7 +233,6 @@ void Player::UpdateArmor()
float value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items)
value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items
- value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats
value += GetModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
@@ -271,15 +256,21 @@ void Player::UpdateArmor()
float Player::GetHealthBonusFromStamina()
{
+ // Taken from PaperDollFrame.lua - 4.3.4.15595
+ float ratio = 10.0f;
+ if (gtOCTHpPerStaminaEntry const* hpBase = sGtOCTHpPerStaminaStore.LookupEntry((getClass() - 1) * GT_MAX_LEVEL + getLevel() - 1))
+ ratio = hpBase->ratio;
+
float stamina = GetStat(STAT_STAMINA);
float baseStam = std::min(20.0f, stamina);
float moreStam = stamina - baseStam;
- return baseStam + (moreStam*10.0f);
+ return baseStam + moreStam * ratio;
}
float Player::GetManaBonusFromIntellect()
{
+ // Taken from PaperDollFrame.lua - 4.3.4.15595
float intellect = GetStat(STAT_INTELLECT);
float baseInt = std::min(20.0f, intellect);
@@ -314,140 +305,32 @@ void Player::UpdateMaxPower(Powers power)
SetMaxPower(power, uint32(value));
}
-void Player::ApplyFeralAPBonus(int32 amount, bool apply)
-{
- _ModifyUInt32(apply, m_baseFeralAP, amount);
- UpdateAttackPowerAndDamage();
-}
-
void Player::UpdateAttackPowerAndDamage(bool ranged)
{
float val2 = 0.0f;
float level = float(getLevel());
+ ChrClassesEntry const* entry = sChrClassesStore.LookupEntry(getClass());
UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER;
uint16 index = UNIT_FIELD_ATTACK_POWER;
- uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS;
- uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER;
if (ranged)
{
index = UNIT_FIELD_RANGED_ATTACK_POWER;
- index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
- index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
-
- switch (getClass())
- {
- case CLASS_HUNTER:
- val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f;
- break;
- case CLASS_ROGUE:
- val2 = level + GetStat(STAT_AGILITY) - 10.0f;
- break;
- case CLASS_WARRIOR:
- val2 = level + GetStat(STAT_AGILITY) - 10.0f;
- break;
- case CLASS_DRUID:
- switch (GetShapeshiftForm())
- {
- case FORM_CAT:
- case FORM_BEAR:
- case FORM_DIREBEAR:
- val2 = 0.0f; break;
- default:
- val2 = GetStat(STAT_AGILITY) - 10.0f; break;
- }
- break;
- default: val2 = GetStat(STAT_AGILITY) - 10.0f; break;
- }
+ val2 = (level + std::max(GetStat(STAT_AGILITY) - 10.0f, 0.0f)) * entry->RAPPerAgility;
}
else
{
- 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_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
- float mLevelMult = 0.0f;
- float weapon_bonus = 0.0f;
- if (IsInFeralForm())
- {
- Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
- {
- AuraEffect* aurEff = *itr;
- if (aurEff->GetSpellInfo()->SpellIconID == 1563)
- {
- switch (aurEff->GetEffIndex())
- {
- case 0: // Predatory Strikes (effect 0)
- mLevelMult = CalculatePct(1.0f, aurEff->GetAmount());
- break;
- case 1: // Predatory Strikes (effect 1)
- if (Item* mainHand = m_items[EQUIPMENT_SLOT_MAINHAND])
- {
- // also gains % attack power from equipped weapon
- ItemTemplate const* proto = mainHand->GetTemplate();
- if (!proto)
- continue;
-
- weapon_bonus = CalculatePct(float(proto->getFeralBonus()), aurEff->GetAmount());
- }
- break;
- default:
- break;
- }
- }
- }
- }
-
- switch (GetShapeshiftForm())
- {
- case FORM_CAT:
- val2 = getLevel() * (mLevelMult + 2.0f) + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f + weapon_bonus + m_baseFeralAP;
- break;
- case FORM_BEAR:
- case FORM_DIREBEAR:
- val2 = getLevel() * (mLevelMult + 3.0f) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + weapon_bonus + m_baseFeralAP;
- break;
- case FORM_MOONKIN:
- 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;
- }
- break;
- }
- case CLASS_MAGE:
- val2 = GetStat(STAT_STRENGTH) - 10.0f;
- break;
- case CLASS_PRIEST:
- val2 = GetStat(STAT_STRENGTH) - 10.0f;
- break;
- case CLASS_WARLOCK:
- val2 = GetStat(STAT_STRENGTH) - 10.0f;
- break;
- }
+ float strengthValue = std::max((GetStat(STAT_STRENGTH) - 10.0f) * entry->APPerStrenth, 0.0f);
+ float agilityValue = std::max((GetStat(STAT_AGILITY) - 10.0f) * entry->APPerAgility, 0.0f);
+
+ SpellShapeshiftFormEntry const* form = sSpellShapeshiftFormStore.LookupEntry(GetShapeshiftForm());
+ // Directly taken from client, SHAPESHIFT_FLAG_AP_FROM_STRENGTH ?
+ if (form && form->flags1 & 0x20)
+ agilityValue += std::max((GetStat(STAT_AGILITY) - 10.0f) * entry->APPerStrenth, 0.0f);
+
+ val2 = strengthValue + agilityValue;
}
SetModifierValue(unitMod, BASE_VALUE, val2);
@@ -456,32 +339,15 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
- if (ranged)
+ if (!ranged)
{
- if ((getClassMask() & CLASSMASK_WAND_USERS) == 0)
- {
- AuraEffectList const& mRAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT);
- for (AuraEffectList::const_iterator i = mRAPbyStat.begin(); i != mRAPbyStat.end(); ++i)
- attPowerMod += CalculatePct(GetStat(Stats((*i)->GetMiscValue())), (*i)->GetAmount());
- }
- }
- else
- {
- AuraEffectList const& mAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT);
- for (AuraEffectList::const_iterator i = mAPbyStat.begin(); i != mAPbyStat.end(); ++i)
- attPowerMod += CalculatePct(GetStat(Stats((*i)->GetMiscValue())), (*i)->GetAmount());
-
AuraEffectList const& mAPbyArmor = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR);
for (AuraEffectList::const_iterator iter = mAPbyArmor.begin(); iter != mAPbyArmor.end(); ++iter)
// always: ((*i)->GetModifier()->m_miscvalue == 1 == SPELL_SCHOOL_MASK_NORMAL)
attPowerMod += int32(GetArmor() / (*iter)->GetAmount());
}
- float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
-
SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
- SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
- SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
Pet* pet = GetPet(); //update pet's AP
Guardian* guardian = GetGuardianPet();
@@ -508,11 +374,6 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
}
}
-void Player::UpdateShieldBlockValue()
-{
- SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue());
-}
-
void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage)
{
UnitMods unitMod;
@@ -543,12 +404,20 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
if (IsInFeralForm()) // check if player is druid and in cat or bear forms
{
- uint8 lvl = getLevel();
- if (lvl > 60)
- lvl = 60;
+ float weaponSpeed = BASE_ATTACK_TIME / 1000.f;
+ if (Item* weapon = GetWeaponForAttack(BASE_ATTACK, true))
+ weaponSpeed = weapon->GetTemplate()->Delay / 1000;
- weaponMinDamage = lvl * 0.85f * attackSpeedMod;
- weaponMaxDamage = lvl * 1.25f * attackSpeedMod;
+ if (GetShapeshiftForm() == FORM_CAT)
+ {
+ weaponMinDamage = weaponMinDamage / weaponSpeed;
+ weaponMaxDamage = weaponMaxDamage / weaponSpeed;
+ }
+ else if (GetShapeshiftForm() == FORM_BEAR)
+ {
+ weaponMinDamage = weaponMinDamage / weaponSpeed + weaponMinDamage / 2.5;
+ weaponMaxDamage = weaponMinDamage / weaponSpeed + weaponMaxDamage / 2.5;
+ }
}
else if (!CanUseAttackType(attType)) // check if player not in form but still can't use (disarm case)
{
@@ -562,23 +431,18 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
weaponMinDamage = BASE_MINDAMAGE;
weaponMaxDamage = BASE_MAXDAMAGE;
}
+ /*
+ TODO: Is this still needed after ammo has been removed?
else if (attType == RANGED_ATTACK) // add ammo DPS to ranged damage
{
weaponMinDamage += GetAmmoDPS() * attackSpeedMod;
weaponMaxDamage += GetAmmoDPS() * attackSpeedMod;
- }
+ }*/
minDamage = ((weaponMinDamage + baseValue) * basePct + totalValue) * totalPct;
maxDamage = ((weaponMaxDamage + baseValue) * basePct + totalValue) * totalPct;
}
-void Player::UpdateDefenseBonusesMod()
-{
- UpdateBlockPercentage();
- UpdateParryPercentage();
- UpdateDodgePercentage();
-}
-
void Player::UpdateBlockPercentage()
{
// No block
@@ -587,8 +451,6 @@ void Player::UpdateBlockPercentage()
{
// Base value
value = 5.0f;
- // Modify value from defense skill
- value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f;
// Increase from SPELL_AURA_MOD_BLOCK_PERCENT aura
value += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT);
// Increase from rating
@@ -630,7 +492,7 @@ void Player::UpdateCritPercentage(WeaponAttackType attType)
float value = GetTotalPercentageModValue(modGroup) + GetRatingBonusValue(cr);
// Modify crit from weapon skill and maximized defense skill of same level victim difference
- value += (int32(GetWeaponSkillValue(attType)) - int32(GetMaxSkillValueForLevel())) * 0.04f;
+ value += (int32(GetMaxSkillValueForLevel()) - int32(GetMaxSkillValueForLevel())) * 0.04f;
if (sWorld->getBoolConfig(CONFIG_STATS_LIMITS_ENABLE))
value = value > sWorld->getFloatConfig(CONFIG_STATS_LIMITS_CRIT) ? sWorld->getFloatConfig(CONFIG_STATS_LIMITS_CRIT) : value;
@@ -652,6 +514,44 @@ void Player::UpdateAllCritPercentages()
UpdateCritPercentage(RANGED_ATTACK);
}
+void Player::UpdateMastery()
+{
+ if (!CanUseMastery())
+ {
+ SetFloatValue(PLAYER_MASTERY, 0.0f);
+ return;
+ }
+
+ float value = GetTotalAuraModifier(SPELL_AURA_MASTERY);
+ value += GetRatingBonusValue(CR_MASTERY);
+ SetFloatValue(PLAYER_MASTERY, value);
+
+ TalentTabEntry const* talentTab = sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec()));
+ if (!talentTab)
+ return;
+
+ for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
+ {
+ if (!talentTab->MasterySpellId[i])
+ continue;
+
+ if (Aura* aura = GetAura(talentTab->MasterySpellId[i]))
+ {
+ for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
+ {
+ if (!aura->HasEffect(j))
+ continue;
+
+ float mult = aura->GetSpellInfo()->Effects[j].BonusMultiplier;
+ if (G3D::fuzzyEq(mult, 0.0f))
+ continue;
+
+ aura->GetEffect(j)->ChangeAmount(int32(value * aura->GetSpellInfo()->Effects[j].BonusMultiplier));
+ }
+ }
+ }
+}
+
const float m_diminishing_k[MAX_CLASSES] =
{
0.9560f, // Warrior
@@ -667,43 +567,16 @@ const float m_diminishing_k[MAX_CLASSES] =
0.9720f // Druid
};
-float Player::GetMissPercentageFromDefence() const
-{
- float const miss_cap[MAX_CLASSES] =
- {
- 16.00f, // Warrior //correct
- 16.00f, // Paladin //correct
- 16.00f, // Hunter //?
- 16.00f, // Rogue //?
- 16.00f, // Priest //?
- 16.00f, // DK //correct
- 16.00f, // Shaman //?
- 16.00f, // Mage //?
- 16.00f, // Warlock //?
- 0.0f, // ??
- 16.00f // Druid //?
- };
-
- float diminishing = 0.0f, nondiminishing = 0.0f;
- // Modify value from defense skill (only bonus from defense rating diminishes)
- nondiminishing += (GetSkillValue(SKILL_DEFENSE) - GetMaxSkillValueForLevel()) * 0.04f;
- diminishing += (int32(GetRatingBonusValue(CR_DEFENSE_SKILL))) * 0.04f;
-
- // apply diminishing formula to diminishing miss chance
- uint32 pclass = getClass()-1;
- return nondiminishing + (diminishing * miss_cap[pclass] / (diminishing + miss_cap[pclass] * m_diminishing_k[pclass]));
-}
-
void Player::UpdateParryPercentage()
{
const float parry_cap[MAX_CLASSES] =
{
- 47.003525f, // Warrior
- 47.003525f, // Paladin
+ 65.631440f, // Warrior
+ 65.631440f, // Paladin
145.560408f, // Hunter
145.560408f, // Rogue
0.0f, // Priest
- 47.003525f, // DK
+ 65.631440f, // DK
145.560408f, // Shaman
0.0f, // Mage
0.0f, // Warlock
@@ -719,9 +592,6 @@ void Player::UpdateParryPercentage()
float nondiminishing = 5.0f;
// Parry from rating
float diminishing = GetRatingBonusValue(CR_PARRY);
- // Modify value from defense skill (only bonus from defense rating diminishes)
- nondiminishing += (GetSkillValue(SKILL_DEFENSE) - GetMaxSkillValueForLevel()) * 0.04f;
- diminishing += (int32(GetRatingBonusValue(CR_DEFENSE_SKILL))) * 0.04f;
// Parry from SPELL_AURA_MOD_PARRY_PERCENT aura
nondiminishing += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT);
// apply diminishing formula to diminishing parry chance
@@ -739,12 +609,12 @@ void Player::UpdateDodgePercentage()
{
const float dodge_cap[MAX_CLASSES] =
{
- 88.129021f, // Warrior
- 88.129021f, // Paladin
+ 65.631440f, // Warrior
+ 65.631440f, // Paladin
145.560408f, // Hunter
145.560408f, // Rogue
150.375940f, // Priest
- 88.129021f, // DK
+ 65.631440f, // DK
145.560408f, // Shaman
150.375940f, // Mage
150.375940f, // Warlock
@@ -754,9 +624,6 @@ void Player::UpdateDodgePercentage()
float diminishing = 0.0f, nondiminishing = 0.0f;
GetDodgeFromAgility(diminishing, nondiminishing);
- // Modify value from defense skill (only bonus from defense rating diminishes)
- nondiminishing += (GetSkillValue(SKILL_DEFENSE) - GetMaxSkillValueForLevel()) * 0.04f;
- diminishing += (int32(GetRatingBonusValue(CR_DEFENSE_SKILL))) * 0.04f;
// Dodge from SPELL_AURA_MOD_DODGE_PERCENT aura
nondiminishing += GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT);
// Dodge from rating
@@ -876,29 +743,23 @@ void Player::ApplyHealthRegenBonus(int32 amount, bool apply)
void Player::UpdateManaRegen()
{
- float Intellect = GetStat(STAT_INTELLECT);
- // Mana regen from spirit and intellect
- float power_regen = sqrt(Intellect) * OCTRegenMPPerSpirit();
+ // Mana regen from spirit
+ float spirit_regen = OCTRegenMPPerSpirit();
// Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen
- power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA);
+ spirit_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) + m_baseManaRegen) / 5.0f;
+ // SpiritRegen(SPI, INT, LEVEL) = (0.001 + (SPI x sqrt(INT) x BASE_REGEN[LEVEL])) x 5
+ if (GetStat(STAT_INTELLECT) > 0.0f)
+ spirit_regen *= sqrt(GetStat(STAT_INTELLECT));
- // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura
- AuraEffectList const& regenAura = GetAuraEffectsByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT);
- for (AuraEffectList::const_iterator i = regenAura.begin(); i != regenAura.end(); ++i)
- {
- power_regen_mp5 += GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 500.0f;
- }
+ // CombatRegen = 5% of Base Mana
+ float base_regen = GetCreateMana() * 0.01f + GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f;
// Set regen rate in cast state apply only on spirit based regen
int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT);
- if (modManaRegenInterrupt > 100)
- modManaRegenInterrupt = 100;
- SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, power_regen_mp5 + CalculatePct(power_regen, modManaRegenInterrupt));
- SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, power_regen_mp5 + power_regen);
+ SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, base_regen + CalculatePct(spirit_regen, modManaRegenInterrupt));
+ SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, 0.001f + spirit_regen + base_regen);
}
void Player::UpdateRuneRegen(RuneType rune)
@@ -922,6 +783,13 @@ void Player::UpdateRuneRegen(RuneType rune)
SetFloatValue(PLAYER_RUNE_REGEN_1 + uint8(rune), regen);
}
+void Player::UpdateAllRunesRegen()
+{
+ for (uint8 i = 0; i < NUM_RUNE_TYPES; ++i)
+ if (uint32 cooldown = GetRuneTypeBaseCooldown(RuneType(i)))
+ SetFloatValue(PLAYER_RUNE_REGEN_1 + i, float(1 * IN_MILLISECONDS) / float(cooldown));
+}
+
void Player::_ApplyAllStatBonuses()
{
SetCanModifyStats(false);
@@ -1007,22 +875,18 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER;
uint16 index = UNIT_FIELD_ATTACK_POWER;
- uint16 indexMod = UNIT_FIELD_ATTACK_POWER_MODS;
uint16 indexMulti = UNIT_FIELD_ATTACK_POWER_MULTIPLIER;
if (ranged)
{
index = UNIT_FIELD_RANGED_ATTACK_POWER;
- indexMod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
indexMulti = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
}
float baseAttackPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attackPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
float attackPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
SetInt32Value(index, uint32(baseAttackPower)); // UNIT_FIELD_(RANGED)_ATTACK_POWER
- SetInt32Value(indexMod, uint32(attackPowerMod)); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS
SetFloatValue(indexMulti, attackPowerMultiplier); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER
// automatically update weapon damage after attack power modification
@@ -1122,7 +986,7 @@ bool Guardian::UpdateStats(Stats stat)
if (aurEff)
{
SpellInfo const* spellInfo = aurEff->GetSpellInfo(); // Then get the SpellProto and add the dummy effect value
- AddPct(mod, spellInfo->Effects[EFFECT_1].CalcValue()); // Ravenous Dead edits the original scale
+ AddPct(mod, spellInfo->Effects[EFFECT_1].CalcValue(owner)); // Ravenous Dead edits the original scale
}
// Glyph of the Ghoul
aurEff = owner->GetAuraEffect(58686, 0);
@@ -1133,29 +997,8 @@ bool Guardian::UpdateStats(Stats stat)
}
else if (stat == STAT_STAMINA)
{
- if (owner->getClass() == CLASS_WARLOCK && IsPet())
- {
- ownersBonus = CalculatePct(owner->GetStat(STAT_STAMINA), 75);
- value += ownersBonus;
- }
- else
- {
- mod = 0.45f;
- if (IsPet())
- {
- PetSpellMap::const_iterator itr = (ToPet()->m_spells.find(62758)); // Wild Hunt rank 1
- if (itr == ToPet()->m_spells.end())
- itr = ToPet()->m_spells.find(62762); // Wild Hunt rank 2
-
- if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt
- {
- SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
- AddPct(mod, spellInfo->Effects[EFFECT_0].CalcValue());
- }
- }
- ownersBonus = float(owner->GetStat(stat)) * mod;
- value += ownersBonus;
- }
+ ownersBonus = CalculatePct(owner->GetStat(STAT_STAMINA), 30);
+ value += ownersBonus;
}
//warlock's and mage's pets gain 30% of owner's intellect
else if (stat == STAT_INTELLECT)
@@ -1227,13 +1070,14 @@ void Guardian::UpdateArmor()
float bonus_armor = 0.0f;
UnitMods unitMod = UNIT_MOD_ARMOR;
- // hunter and warlock pets gain 35% of owner's armor value
- if (IsPet())
- bonus_armor = float(CalculatePct(m_owner->GetArmor(), 35));
+ // hunter pets gain 35% of owner's armor value, warlock pets gain 100% of owner's armor
+ if (IsHunterPet())
+ bonus_armor = float(CalculatePct(m_owner->GetArmor(), 70));
+ else if (IsPet())
+ bonus_armor = m_owner->GetArmor();
value = GetModifierValue(unitMod, BASE_VALUE);
value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetStat(STAT_AGILITY) * 2.0f;
value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor;
value *= GetModifierValue(unitMod, TOTAL_PCT);
@@ -1310,19 +1154,6 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
if (IsHunterPet()) //hunter pets benefit from owner's attack power
{
float mod = 1.0f; //Hunter contribution modifier
- if (IsPet())
- {
- PetSpellMap::const_iterator itr = ToPet()->m_spells.find(62758); //Wild Hunt rank 1
- if (itr == ToPet()->m_spells.end())
- itr = ToPet()->m_spells.find(62762); //Wild Hunt rank 2
-
- if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt
- {
- SpellInfo const* sProto = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
- mod += CalculatePct(1.0f, sProto->Effects[1].CalcValue());
- }
- }
-
bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod;
SetBonusDamage(int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod));
}
@@ -1342,8 +1173,8 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
//demons benefit from warlocks shadow or fire damage
else if (IsPet())
{
- int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
- int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW);
+ int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) + owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
+ int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) + owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW);
int32 maximum = (fire > shadow) ? fire : shadow;
if (maximum < 0)
maximum = 0;
@@ -1353,7 +1184,7 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
//water elementals benefit from mage's frost damage
else if (GetEntry() == ENTRY_WATER_ELEMENTAL)
{
- int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST);
+ int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) + owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST);
if (frost < 0)
frost = 0;
SetBonusDamage(int32(frost * 0.4f));
@@ -1364,13 +1195,10 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
//in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB
float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
//UNIT_FIELD_(RANGED)_ATTACK_POWER field
SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)base_attPower);
- //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
- SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (int32)attPowerMod);
//UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, attPowerMultiplier);
@@ -1389,14 +1217,14 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
//force of nature
if (GetEntry() == ENTRY_TREANT)
{
- int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_NATURE)) - m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_NATURE);
+ int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_NATURE)) + m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_NATURE);
if (spellDmg > 0)
bonusDamage = spellDmg * 0.09f;
}
//greater fire elemental
else if (GetEntry() == ENTRY_FIRE_ELEMENTAL)
{
- int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
+ int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) + m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
if (spellDmg > 0)
bonusDamage = spellDmg * 0.4f;
}
@@ -1417,27 +1245,6 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct;
float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct;
- // Pet's base damage changes depending on happiness
- if (IsHunterPet() && attType == BASE_ATTACK)
- {
- switch (ToPet()->GetHappinessState())
- {
- case HAPPY:
- // 125% of normal damage
- mindamage = mindamage * 1.25f;
- maxdamage = maxdamage * 1.25f;
- break;
- case CONTENT:
- // 100% of normal damage, nothing to modify
- break;
- case UNHAPPY:
- // 75% of normal damage
- mindamage = mindamage * 0.75f;
- maxdamage = maxdamage * 0.75f;
- break;
- }
- }
-
/// @todo: remove this
Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACKSPEED);
for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index f5b72b845a5..f096170c46d 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -36,7 +36,6 @@
#include "Log.h"
#include "MapManager.h"
#include "MoveSpline.h"
-#include "MoveSplineInit.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
@@ -60,6 +59,7 @@
#include "Vehicle.h"
#include "World.h"
#include "WorldPacket.h"
+#include "MovementStructures.h"
#include "WorldSession.h"
#include <math.h>
@@ -168,7 +168,7 @@ Unit::Unit(bool isWorldObject) :
m_objectType |= TYPEMASK_UNIT;
m_objectTypeId = TYPEID_UNIT;
- m_updateFlag = (UPDATEFLAG_LIVING | UPDATEFLAG_STATIONARY_POSITION);
+ m_updateFlag = UPDATEFLAG_LIVING;
m_attackTimer[BASE_ATTACK] = 0;
m_attackTimer[OFF_ATTACK] = 0;
@@ -180,7 +180,7 @@ Unit::Unit(bool isWorldObject) :
m_extraAttacks = 0;
m_canDualWield = false;
- m_rootTimes = 0;
+ m_movementCounter = 0;
m_state = 0;
m_deathState = ALIVE;
@@ -229,7 +229,6 @@ Unit::Unit(bool isWorldObject) :
m_baseSpellCritChance = 5;
m_CombatTimer = 0;
- m_lastManaUse = 0;
for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
m_threatModifier[i] = 1.0f;
@@ -406,7 +405,7 @@ void Unit::UpdateSplinePosition()
pos.m_positionX = loc.x;
pos.m_positionY = loc.y;
pos.m_positionZ = loc.z;
- pos.m_orientation = loc.orientation;
+ pos.SetOrientation(loc.orientation);
if (TransportBase* transport = GetDirectTransport())
transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, &loc.orientation);
@@ -420,7 +419,7 @@ void Unit::UpdateSplinePosition()
void Unit::DisableSpline()
{
- m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD));
+ m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FORWARD);
movespline->_Interrupt();
}
@@ -437,7 +436,7 @@ float Unit::GetMeleeReach() const
bool Unit::IsWithinCombatRange(const Unit* obj, float dist2compare) const
{
- if (!obj || !IsInMap(obj) || !InSamePhase(obj))
+ if (!obj || !IsInMap(obj) || !IsInPhase(obj))
return false;
float dx = GetPositionX() - obj->GetPositionX();
@@ -453,7 +452,7 @@ bool Unit::IsWithinCombatRange(const Unit* obj, float dist2compare) const
bool Unit::IsWithinMeleeRange(const Unit* obj, float dist) const
{
- if (!obj || !IsInMap(obj) || !InSamePhase(obj))
+ if (!obj || !IsInMap(obj) || !IsInPhase(obj))
return false;
float dx = GetPositionX() - obj->GetPositionX();
@@ -623,32 +622,13 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
// Rage from Damage made (only from direct weapon damage)
if (cleanDamage && damagetype == DIRECT_DAMAGE && this != victim && getPowerType() == POWER_RAGE)
{
- uint32 weaponSpeedHitFactor;
- uint32 rage_damage = damage + cleanDamage->absorbed_damage;
-
+ uint32 rage = uint32(GetAttackTime(cleanDamage->attackType) / 1000 * 8.125f);
switch (cleanDamage->attackType)
{
- case BASE_ATTACK:
- {
- weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType) / 1000.0f * 3.5f);
- if (cleanDamage->hitOutCome == MELEE_HIT_CRIT)
- weaponSpeedHitFactor *= 2;
-
- RewardRage(rage_damage, weaponSpeedHitFactor, true);
-
- break;
- }
case OFF_ATTACK:
- {
- weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType) / 1000.0f * 1.75f);
- if (cleanDamage->hitOutCome == MELEE_HIT_CRIT)
- weaponSpeedHitFactor *= 2;
-
- RewardRage(rage_damage, weaponSpeedHitFactor, true);
-
- break;
- }
- case RANGED_ATTACK:
+ rage /= 2;
+ case BASE_ATTACK:
+ RewardRage(rage, true);
break;
default:
break;
@@ -659,7 +639,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
{
// Rage from absorbed damage
if (cleanDamage && cleanDamage->absorbed_damage && victim->getPowerType() == POWER_RAGE)
- victim->RewardRage(cleanDamage->absorbed_damage, 0, false);
+ victim->RewardRage(cleanDamage->absorbed_damage, false);
return 0;
}
@@ -704,7 +684,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (Battleground* bg = killer->GetBattleground())
bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage);
- killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, damage, 0, victim);
+ killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, damage, 0, 0, victim);
killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT, damage);
}
@@ -760,7 +740,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (this != victim && victim->getPowerType() == POWER_RAGE)
{
uint32 rage_damage = damage + (cleanDamage ? cleanDamage->absorbed_damage : 0);
- victim->RewardRage(rage_damage, 0, false);
+ victim->RewardRage(rage_damage, false);
}
if (GetTypeId() == TYPEID_PLAYER)
@@ -977,7 +957,6 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
return;
SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask);
- uint32 crTypeMask = victim->GetCreatureTypeMask();
// Spells with SPELL_ATTR4_FIXED_DAMAGE ignore resilience because their damage is based off another spell's damage.
if (!(spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
@@ -1021,9 +1000,6 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
// Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
critPctDamageMod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellInfo->GetSchoolMask()) - 1.0f) * 100;
- // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
- critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
-
if (critPctDamageMod != 0)
AddPct(damage, critPctDamageMod);
}
@@ -1031,22 +1007,18 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
// Spell weapon based damage CAN BE crit & blocked at same time
if (blocked)
{
- damageInfo->blocked = victim->GetShieldBlockValue();
// double blocked amount if block is critical
+ uint32 value = victim->GetBlockPercent();
if (victim->isBlockCritical())
- damageInfo->blocked += damageInfo->blocked;
- if (damage < int32(damageInfo->blocked))
- damageInfo->blocked = uint32(damage);
+ value *= 2; // double blocked percent
+ damageInfo->blocked = CalculatePct(damage, value);
damage -= damageInfo->blocked;
}
- if (attackType != RANGED_ATTACK)
- ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_MELEE);
- else
- ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_RANGED);
+ ApplyResilience(victim, &damage);
break;
}
- // Magical Attacks
+ // Magical Attacks
case SPELL_DAMAGE_CLASS_NONE:
case SPELL_DAMAGE_CLASS_MAGIC:
{
@@ -1055,10 +1027,12 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
{
damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
damage = SpellCriticalDamageBonus(spellInfo, damage, victim);
+
}
- ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_SPELL);
+ ApplyResilience(victim, &damage);
break;
+
}
default:
break;
@@ -1216,10 +1190,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
// Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
mod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, damageInfo->damageSchoolMask) - 1.0f) * 100;
- uint32 crTypeMask = damageInfo->target->GetCreatureTypeMask();
-
- // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
- mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
if (mod != 0)
AddPct(damageInfo->damage, mod);
break;
@@ -1239,19 +1209,9 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
case MELEE_HIT_BLOCK:
damageInfo->TargetState = VICTIMSTATE_HIT;
damageInfo->HitInfo |= HITINFO_BLOCK;
- damageInfo->procEx |= PROC_EX_BLOCK;
- damageInfo->blocked_amount = damageInfo->target->GetShieldBlockValue();
- // double blocked amount if block is critical
- if (damageInfo->target->isBlockCritical())
- damageInfo->blocked_amount+=damageInfo->blocked_amount;
- if (damageInfo->blocked_amount >= damageInfo->damage)
- {
- damageInfo->TargetState = VICTIMSTATE_BLOCKS;
- damageInfo->blocked_amount = damageInfo->damage;
- damageInfo->procEx |= PROC_EX_FULL_BLOCK;
- }
- else
- damageInfo->procEx |= PROC_EX_NORMAL_HIT;
+ damageInfo->procEx |= PROC_EX_BLOCK | PROC_EX_NORMAL_HIT;
+ // 30% damage blocked, double blocked amount if block is critical
+ damageInfo->blocked_amount = CalculatePct(damageInfo->damage, damageInfo->target->isBlockCritical() ? damageInfo->target->GetBlockPercent() * 2 : damageInfo->target->GetBlockPercent());
damageInfo->damage -= damageInfo->blocked_amount;
damageInfo->cleanDamage += damageInfo->blocked_amount;
break;
@@ -1284,8 +1244,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
damageInfo->HitInfo |= HITINFO_AFFECTS_VICTIM;
int32 resilienceReduction = damageInfo->damage;
- // attackType is checked already for BASE_ATTACK or OFF_ATTACK so it can't be RANGED_ATTACK here
- ApplyResilience(victim, NULL, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_MELEE);
+ ApplyResilience(victim, &resilienceReduction);
resilienceReduction = damageInfo->damage - resilienceReduction;
damageInfo->damage -= resilienceReduction;
damageInfo->cleanDamage += resilienceReduction;
@@ -1374,8 +1333,8 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
if (victim->getLevel() < 30)
Probability = 0.65f * victim->getLevel() + 0.5f;
- uint32 VictimDefense=victim->GetDefenseSkillValue();
- uint32 AttackerMeleeSkill=GetUnitMeleeSkill();
+ uint32 VictimDefense = victim->GetMaxSkillValueForLevel(this);
+ uint32 AttackerMeleeSkill = GetMaxSkillValueForLevel();
Probability *= AttackerMeleeSkill/(float)VictimDefense*0.16;
@@ -1435,6 +1394,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
int32 overkill = int32(damage) - int32(GetHealth());
data << uint32(overkill > 0 ? overkill : 0); // Overkill
data << uint32(i_spellProto->SchoolMask);
+ data << uint32(0); // FIX ME: Send resisted damage, both fully resisted and partly resisted
victim->SendMessageToSet(&data, true);
victim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, i_spellProto->GetSchoolMask(), i_spellProto, true);
@@ -1477,6 +1437,14 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
{
float armor = float(victim->GetArmor());
+ // bypass enemy armor by SPELL_AURA_BYPASS_ARMOR_FOR_CASTER
+ int32 armorBypassPct = 0;
+ AuraEffectList const & reductionAuras = victim->GetAuraEffectsByType(SPELL_AURA_BYPASS_ARMOR_FOR_CASTER);
+ for (AuraEffectList::const_iterator i = reductionAuras.begin(); i != reductionAuras.end(); ++i)
+ if ((*i)->GetCasterGUID() == GetGUID())
+ armorBypassPct += (*i)->GetAmount();
+ armor = CalculatePct(armor, 100 - std::min(armorBypassPct, 100));
+
// Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
armor += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL);
@@ -1484,14 +1452,6 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor);
- AuraEffectList const& resIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
- for (AuraEffectList::const_iterator j = resIgnoreAurasAb.begin(); j != resIgnoreAurasAb.end(); ++j)
- {
- if ((*j)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL
- && (*j)->IsAffectedOnSpell(spellInfo))
- armor = floor(AddPct(armor, -(*j)->GetAmount()));
- }
-
AuraEffectList const& resIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
for (AuraEffectList::const_iterator j = resIgnoreAuras.begin(); j != resIgnoreAuras.end(); ++j)
{
@@ -1499,27 +1459,9 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
armor = floor(AddPct(armor, -(*j)->GetAmount()));
}
- // Apply Player CR_ARMOR_PENETRATION rating and buffs from stances\specializations etc.
+ // Apply Player CR_ARMOR_PENETRATION rating
if (GetTypeId() == TYPEID_PLAYER)
{
- float bonusPct = 0;
- AuraEffectList const& armorPenAuras = GetAuraEffectsByType(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT);
- for (AuraEffectList::const_iterator itr = armorPenAuras.begin(); itr != armorPenAuras.end(); ++itr)
- {
- if ((*itr)->GetSpellInfo()->EquippedItemClass == -1)
- {
- if (!spellInfo || (*itr)->IsAffectedOnSpell(spellInfo) || (*itr)->GetMiscValue() & spellInfo->GetSchoolMask())
- bonusPct += (*itr)->GetAmount();
- else if (!(*itr)->GetMiscValue() && !(*itr)->HasSpellClassMask())
- bonusPct += (*itr)->GetAmount();
- }
- else
- {
- if (ToPlayer()->HasItemFitToSpellRequirements((*itr)->GetSpellInfo()))
- bonusPct += (*itr)->GetAmount();
- }
- }
-
float maxArmorPen = 0;
if (victim->getLevel() < 60)
maxArmorPen = float(400 + 85 * victim->getLevel());
@@ -1529,7 +1471,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
// Cap armor penetration to this number
maxArmorPen = std::min((armor + maxArmorPen) / 3, armor);
// Figure out how much armor do we ignore
- float armorPen = CalculatePct(maxArmorPen, bonusPct + ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION));
+ float armorPen = CalculatePct(maxArmorPen, ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION));
// Got the value, apply it
armor -= std::min(armorPen, maxArmorPen);
}
@@ -1562,13 +1504,13 @@ uint32 Unit::CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, Spell
if (spellInfo && spellInfo->AttributesEx4 & SPELL_ATTR4_IGNORE_RESISTANCES)
return 0;
- uint32 const BOSS_LEVEL = 83;
- uint32 const BOSS_RESISTANCE_CONSTANT = 510;
+ uint8 const bossLevel = 83;
+ uint32 const bossResistanceConstant = 510;
uint32 resistanceConstant = 0;
uint8 level = victim->getLevel();
- if (level == BOSS_LEVEL)
- resistanceConstant = BOSS_RESISTANCE_CONSTANT;
+ if (level == bossLevel)
+ resistanceConstant = bossResistanceConstant;
else
resistanceConstant = level * 5;
@@ -1585,11 +1527,6 @@ uint32 Unit::CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, Spell
{
int32 ignoredResistance = 0;
- AuraEffectList const& ResIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
- for (AuraEffectList::const_iterator itr = ResIgnoreAurasAb.begin(); itr != ResIgnoreAurasAb.end(); ++itr)
- if (((*itr)->GetMiscValue() & schoolMask) && (*itr)->IsAffectedOnSpell(spellInfo))
- ignoredResistance += (*itr)->GetAmount();
-
AuraEffectList const& ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
for (AuraEffectList::const_iterator itr = ResIgnoreAuras.begin(); itr != ResIgnoreAuras.end(); ++itr)
if ((*itr)->GetMiscValue() & schoolMask)
@@ -1657,7 +1594,7 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
if (!((*itr)->GetMiscValue() & schoolMask))
continue;
- if (((*itr)->GetAmount() > auraAbsorbMod) && (*itr)->IsAffectedOnSpell(spellInfo))
+ if (((*itr)->GetAmount() > auraAbsorbMod) && (*itr)->IsAffectingSpell(spellInfo))
auraAbsorbMod = float((*itr)->GetAmount());
}
@@ -1781,40 +1718,6 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
{
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
- AuraEffectList vSplitDamageFlatCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
- for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
- {
- // Check if aura was removed during iteration - we don't need to work on such auras
- if (!((*itr)->GetBase()->IsAppliedOnTarget(victim->GetGUID())))
- continue;
- // check damage school mask
- if (!((*itr)->GetMiscValue() & schoolMask))
- continue;
-
- // Damage can be splitted only if aura has an alive caster
- Unit* caster = (*itr)->GetCaster();
- if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
- continue;
-
- int32 splitDamage = (*itr)->GetAmount();
-
- // absorb must be smaller than the damage itself
- splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage()));
-
- dmgInfo.AbsorbDamage(splitDamage);
-
- uint32 splitted = splitDamage;
- uint32 splitted_absorb = 0;
- DealDamageMods(caster, splitted, &splitted_absorb);
-
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
-
- CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
- }
-
- // We're going to call functions which can modify content of the list during iteration over it's elements
- // Let's copy the list so we can prevent iterator invalidation
AuraEffectList vSplitDamagePctCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && dmgInfo.GetDamage() > 0; ++itr)
{
@@ -1978,7 +1881,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackTy
// Miss chance based on melee
//float miss_chance = MeleeMissChanceCalc(victim, attType);
- float miss_chance = MeleeSpellMissChance(victim, attType, int32(GetWeaponSkillValue(attType, victim)) - int32(GetMaxSkillValueForLevel(this)), 0);
+ float miss_chance = MeleeSpellMissChance(victim, attType, 0);
// Critical hit chance
float crit_chance = GetUnitCriticalChance(attType, victim);
@@ -2002,11 +1905,8 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(victim);
int32 victimMaxSkillValueForLevel = victim->GetMaxSkillValueForLevel(this);
- int32 attackerWeaponSkill = GetWeaponSkillValue(attType, victim);
- int32 victimDefenseSkill = victim->GetDefenseSkillValue(this);
-
// bonus from skills is 0.04%
- int32 skillBonus = 4 * (attackerWeaponSkill - victimMaxSkillValueForLevel);
+ int32 skillBonus = 4 * (attackerMaxSkillValueForLevel - victimMaxSkillValueForLevel);
int32 sum = 0, tmp = 0;
int32 roll = urand (0, 10000);
@@ -2115,11 +2015,9 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
getLevel() < victim->getLevelForTarget(this))
{
// cap possible value (with bonuses > max skill)
- int32 skill = attackerWeaponSkill;
- int32 maxskill = attackerMaxSkillValueForLevel;
- skill = (skill > maxskill) ? maxskill : skill;
+ int32 skill = attackerMaxSkillValueForLevel;
- tmp = (10 + (victimDefenseSkill - skill)) * 100;
+ tmp = (10 + (victimMaxSkillValueForLevel - skill)) * 100;
tmp = tmp > 4000 ? 4000 : tmp;
if (roll < (sum += tmp))
{
@@ -2135,10 +2033,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
!(GetTypeId() == TYPEID_UNIT && ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRUSH))
{
// 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
- tmp = tmp > tmpmax ? tmpmax : tmp;
+ tmp = victimMaxSkillValueForLevel;
// tmp = mob's level * 5 - player's current defense skill
tmp = attackerMaxSkillValueForLevel - tmp;
if (tmp >= 15)
@@ -2238,7 +2133,7 @@ void Unit::SendMeleeAttackStop(Unit* victim)
TC_LOG_INFO("entities.unit", "%s %u stopped attacking", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUIDLow());
}
-bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType)
+bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType /*attackType*/)
{
// These spells can't be blocked
if (spellProto && spellProto->Attributes & SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK)
@@ -2251,9 +2146,7 @@ bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttac
victim->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_BLOCK)
return false;
- float blockChance = victim->GetUnitBlockChance();
- blockChance += (int32(GetWeaponSkillValue(attackType)) - int32(victim->GetMaxSkillValueForLevel())) * 0.04f;
- if (roll_chance_f(blockChance))
+ if (roll_chance_f(victim->GetUnitBlockChance()))
return true;
}
return false;
@@ -2318,19 +2211,10 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)
attType = RANGED_ATTACK;
- int32 attackerWeaponSkill;
- // skill value for these spells (for example judgements) is 5* level
- if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED && !spellInfo->IsRangedWeaponSpell())
- attackerWeaponSkill = getLevel() * 5;
- // bonus from skills is 0.04% per skill Diff
- else
- attackerWeaponSkill = int32(GetWeaponSkillValue(attType, victim));
-
- int32 skillDiff = attackerWeaponSkill - int32(victim->GetMaxSkillValueForLevel(this));
+ uint32 roll = urand(0, 10000);
- uint32 roll = urand (0, 10000);
+ uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, spellInfo->Id) * 100.0f);
- uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, skillDiff, spellInfo->Id) * 100.0f);
// Roll miss
uint32 tmp = missChance;
if (roll < tmp)
@@ -2417,7 +2301,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
AuraEffectList const& ignore = GetAuraEffectsByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
for (AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(spellInfo))
+ if (!(*i)->IsAffectingSpell(spellInfo))
continue;
switch ((*i)->GetMiscValue())
{
@@ -2439,7 +2323,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (canDodge)
{
// Roll dodge
- int32 dodgeChance = int32(victim->GetUnitDodgeChance() * 100.0f) - skillDiff * 4;
+ int32 dodgeChance = int32(victim->GetUnitDodgeChance() * 100.0f);
// Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
dodgeChance += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE) * 100;
dodgeChance = int32(float(dodgeChance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE));
@@ -2458,7 +2342,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (canParry)
{
// Roll parry
- int32 parryChance = int32(victim->GetUnitParryChance() * 100.0f) - skillDiff * 4;
+ int32 parryChance = int32(victim->GetUnitParryChance() * 100.0f);
// Reduce parry chance by attacker expertise rating
if (GetTypeId() == TYPEID_PLAYER)
parryChance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
@@ -2474,7 +2358,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (canBlock)
{
- int32 blockChance = int32(victim->GetUnitBlockChance() * 100.0f) - skillDiff * 4;
+ int32 blockChance = int32(victim->GetUnitBlockChance() * 100.0f);
if (blockChance < 0)
blockChance = 0;
tmp += blockChance;
@@ -2512,18 +2396,12 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance);
- // Increase from attacker SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT auras
- modHitChance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT, schoolMask);
-
- // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
- modHitChance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
- // Reduce spell hit chance for Area of effect spells from victim SPELL_AURA_MOD_AOE_AVOIDANCE aura
- if (spellInfo->IsAffectingArea())
- modHitChance -= victim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE);
-
- // Decrease hit chance from victim rating bonus
- if (victim->GetTypeId() == TYPEID_PLAYER)
- modHitChance -= int32(victim->ToPlayer()->GetRatingBonusValue(CR_HIT_TAKEN_SPELL));
+ // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will ignore target's avoidance effects
+ if (!(spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT))
+ {
+ // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
+ modHitChance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
+ }
int32 HitChance = modHitChance * 100;
// Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
@@ -2542,26 +2420,6 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo
int32 resist_chance = victim->GetMechanicResistChance(spellInfo) * 100;
tmp += resist_chance;
- // Chance resist debuff
- if (!spellInfo->IsPositive())
- {
- bool hasAura = false;
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (spellInfo->Effects[i].IsAura())
- {
- hasAura = true;
- break;
- }
- }
-
- if (hasAura)
- {
- tmp += victim->GetMaxPositiveAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spellInfo->Dispel)) * 100;
- tmp += victim->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spellInfo->Dispel)) * 100;
- }
- }
-
// Roll chance
if (rand < tmp)
return SPELL_MISS_RESIST;
@@ -2637,41 +2495,11 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, boo
return SPELL_MISS_NONE;
}
-uint32 Unit::GetShieldBlockValue(uint32 soft_cap, uint32 hard_cap) const
-{
- uint32 value = GetShieldBlockValue();
- if (value >= hard_cap)
- {
- value = (soft_cap + hard_cap) / 2;
- }
- else if (value > soft_cap)
- {
- value = soft_cap + ((value - soft_cap) / 2);
- }
-
- return value;
-}
-
uint32 Unit::GetUnitMeleeSkill(Unit const* target) const
{
return (target ? getLevelForTarget(target) : getLevel()) * 5;
}
-uint32 Unit::GetDefenseSkillValue(Unit const* target) const
-{
- if (GetTypeId() == TYPEID_PLAYER)
- {
- // in PvP use full skill instead current skill value
- uint32 value = (target && target->GetTypeId() == TYPEID_PLAYER)
- ? ToPlayer()->GetMaxSkillValue(SKILL_DEFENSE)
- : ToPlayer()->GetSkillValue(SKILL_DEFENSE);
- value += uint32(ToPlayer()->GetRatingBonusValue(CR_DEFENSE_SKILL));
- return value;
- }
- else
- return GetUnitMeleeSkill(target);
-}
-
float Unit::GetUnitDodgeChance() const
{
if (IsNonMeleeSpellCast(false) || HasUnitState(UNIT_STATE_CONTROLLED))
@@ -2727,9 +2555,6 @@ float Unit::GetUnitMissChance(WeaponAttackType attType) const
{
float miss_chance = 5.00f;
- if (Player const* player = ToPlayer())
- miss_chance += player->GetMissPercentageFromDefence();
-
if (attType == RANGED_ATTACK)
miss_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE);
else
@@ -2748,7 +2573,7 @@ float Unit::GetUnitBlockChance() const
if (player->CanBlock())
{
Item* tmpitem = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
- if (tmpitem && !tmpitem->IsBroken() && tmpitem->GetTemplate()->Block)
+ if (tmpitem && !tmpitem->IsBroken())
return GetFloatValue(PLAYER_BLOCK_PERCENTAGE);
}
// is player but has no block ability or no not broken shield equipped
@@ -2805,63 +2630,11 @@ float Unit::GetUnitCriticalChance(WeaponAttackType attackType, const Unit* victi
crit += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE);
- // reduce crit chance from Rating for players
- if (attackType != RANGED_ATTACK)
- {
- ApplyResilience(victim, &crit, NULL, false, CR_CRIT_TAKEN_MELEE);
- // Glyph of barkskin
- if (victim->HasAura(63057) && victim->HasAura(22812))
- crit -= 25.0f;
- }
- else
- ApplyResilience(victim, &crit, NULL, false, CR_CRIT_TAKEN_RANGED);
-
- // Apply crit chance from defence skill
- crit += (int32(GetMaxSkillValueForLevel(victim)) - int32(victim->GetDefenseSkillValue(this))) * 0.04f;
-
if (crit < 0.0f)
crit = 0.0f;
return crit;
}
-uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target) const
-{
- uint32 value = 0;
- if (Player const* player = ToPlayer())
- {
- Item* item = player->GetWeaponForAttack(attType, true);
-
- // feral or unarmed skill only for base attack
- if (attType != BASE_ATTACK && !item)
- return 0;
-
- if (IsInFeralForm())
- return GetMaxSkillValueForLevel(); // always maximized SKILL_FERAL_COMBAT in fact
-
- // weapon skill or (unarmed for base attack)
- uint32 skill = SKILL_UNARMED;
- if (item)
- skill = item->GetSkill();
-
- // in PvP use full skill instead current skill value
- value = (target && target->IsControlledByPlayer())
- ? player->GetMaxSkillValue(skill)
- : player->GetSkillValue(skill);
- // Modify value from ratings
- value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL));
- switch (attType)
- {
- case BASE_ATTACK: value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL_MAINHAND)); break;
- case OFF_ATTACK: value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL_OFFHAND)); break;
- case RANGED_ATTACK: value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL_RANGED)); break;
- default: break;
- }
- }
- else
- value = GetUnitMeleeSkill(target);
- return value;
-}
-
void Unit::_DeleteRemovedAuras()
{
while (!m_removedAuras.empty())
@@ -2930,7 +2703,9 @@ void Unit::_UpdateSpells(uint32 time)
void Unit::_UpdateAutoRepeatSpell()
{
// check "realtime" interrupts
- if ((GetTypeId() == TYPEID_PLAYER && ToPlayer()->isMoving()) || IsNonMeleeSpellCast(false, false, true, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id == 75))
+ // don't cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect
+ if (((GetTypeId() == TYPEID_PLAYER && ToPlayer()->isMoving()) || IsNonMeleeSpellCast(false, false, true, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id == 75)) &&
+ !HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo))
{
// cancel wand shoot
if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != 75)
@@ -3873,7 +3648,7 @@ void Unit::RemoveAurasWithAttribute(uint32 flags)
}
}
-void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase)
+void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase, bool phaseid)
{
// single target auras from other casters
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
@@ -3883,12 +3658,12 @@ void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase)
if (aura->GetCasterGUID() != GetGUID() && aura->GetSpellInfo()->IsSingleTarget())
{
- if (!newPhase)
+ if (!newPhase && !phaseid)
RemoveAura(iter);
else
{
Unit* caster = aura->GetCaster();
- if (!caster || !caster->InSamePhase(newPhase))
+ if (!caster || (newPhase && !caster->InSamePhase(newPhase)) || (!newPhase && !caster->IsInPhase(this)))
RemoveAura(iter);
else
++iter;
@@ -3923,7 +3698,8 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except)
{
Aura* aura = (*iter)->GetBase();
++iter;
- if ((aura->GetSpellInfo()->AuraInterruptFlags & flag) && (!except || aura->GetId() != except))
+ if ((aura->GetSpellInfo()->AuraInterruptFlags & flag) && (!except || aura->GetId() != except)
+ && !(flag & AURA_INTERRUPT_FLAG_MOVE && HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, aura->GetSpellInfo())))
{
uint32 removedAuras = m_removedAurasCount;
RemoveAura(aura);
@@ -3936,7 +3712,8 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except)
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
if (spell->getState() == SPELL_STATE_CASTING
&& (spell->m_spellInfo->ChannelInterruptFlags & flag)
- && spell->m_spellInfo->Id != except)
+ && spell->m_spellInfo->Id != except
+ && !(flag & AURA_INTERRUPT_FLAG_MOVE && HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, spell->GetSpellInfo())))
InterruptNonMeleeSpells(false);
UpdateInterruptMask();
@@ -4373,7 +4150,7 @@ bool Unit::HasAuraTypeWithAffectMask(AuraType auratype, SpellInfo const* affecte
{
AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
- if ((*i)->IsAffectedOnSpell(affectedSpell))
+ if ((*i)->IsAffectingSpell(affectedSpell))
return true;
return false;
}
@@ -4433,7 +4210,7 @@ AuraEffect* Unit::IsScriptOverriden(SpellInfo const* spell, int32 script) const
for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
{
if ((*i)->GetMiscValue() == script)
- if ((*i)->IsAffectedOnSpell(spell))
+ if ((*i)->IsAffectingSpell(spell))
return (*i);
}
return NULL;
@@ -4694,7 +4471,7 @@ int32 Unit::GetTotalAuraModifierByAffectMask(AuraType auratype, SpellInfo const*
AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
{
- if ((*i)->IsAffectedOnSpell(affectedSpell))
+ if ((*i)->IsAffectingSpell(affectedSpell))
if (!sSpellMgr->AddSameEffectStackRuleSpellGroups((*i)->GetSpellInfo(), (*i)->GetAmount(), SameEffectSpellGroup))
modifier += (*i)->GetAmount();
}
@@ -4713,7 +4490,7 @@ float Unit::GetTotalAuraMultiplierByAffectMask(AuraType auratype, SpellInfo cons
AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
{
- if ((*i)->IsAffectedOnSpell(affectedSpell))
+ if ((*i)->IsAffectingSpell(affectedSpell))
if (!sSpellMgr->AddSameEffectStackRuleSpellGroups((*i)->GetSpellInfo(), (*i)->GetAmount(), SameEffectSpellGroup))
AddPct(multiplier, (*i)->GetAmount());
}
@@ -4731,7 +4508,7 @@ int32 Unit::GetMaxPositiveAuraModifierByAffectMask(AuraType auratype, SpellInfo
AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
{
- if ((*i)->IsAffectedOnSpell(affectedSpell) && (*i)->GetAmount() > modifier)
+ if ((*i)->IsAffectingSpell(affectedSpell) && (*i)->GetAmount() > modifier)
modifier = (*i)->GetAmount();
}
@@ -4745,7 +4522,7 @@ int32 Unit::GetMaxNegativeAuraModifierByAffectMask(AuraType auratype, SpellInfo
AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
{
- if ((*i)->IsAffectedOnSpell(affectedSpell) && (*i)->GetAmount() < modifier)
+ if ((*i)->IsAffectingSpell(affectedSpell) && (*i)->GetAmount() < modifier)
modifier = (*i)->GetAmount();
}
@@ -5122,8 +4899,11 @@ void Unit::SendAttackStateUpdate(CalcDamageInfo* damageInfo)
data << float(0);
data << float(0);
data << float(0);
- data << float(0); // Found in a loop with 1 iteration
- data << float(0); // ditto ^
+ for (uint8 i = 0; i < 2; ++i)
+ {
+ data << float(0);
+ data << float(0);
+ }
data << uint32(0);
}
@@ -5145,6 +4925,133 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType
SendAttackStateUpdate(&dmgInfo);
}
+bool Unit::HandleAuraProcOnPowerAmount(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 /*procEx*/, uint32 cooldown)
+{
+ // Get triggered aura spell info
+ SpellInfo const* auraSpellInfo = triggeredByAura->GetSpellInfo();
+
+ // Get effect index used for the proc
+ uint32 effIndex = triggeredByAura->GetEffIndex();
+
+ // Power amount required to proc the spell
+ int32 powerAmountRequired = triggeredByAura->GetAmount();
+ // Power type required to proc
+ Powers powerRequired = Powers(auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].MiscValue);
+
+ // Set trigger spell id, target, custom basepoints
+ uint32 trigger_spell_id = auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].TriggerSpell;
+
+ Unit* target = NULL;
+ int32 basepoints0 = 0;
+
+ Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
+ ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;
+
+ /* Try handle unknown trigger spells or with invalid power amount or misc value
+ if (sSpellMgr->GetSpellInfo(trigger_spell_id) == NULL || powerAmountRequired == NULL || powerRequired >= MAX_POWER)
+ {
+ switch (auraSpellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ {
+ break;
+ }
+ }
+ }*/
+
+ // All ok. Check current trigger spell
+ SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(trigger_spell_id);
+ if (triggerEntry == NULL)
+ {
+ // Not cast unknown spell
+ // TC_LOG_ERROR("Unit::HandleAuraProcOnPowerAmount: Spell %u have 0 in EffectTriggered[%d], not handled custom case?", auraSpellInfo->Id, triggeredByAura->GetEffIndex());
+ return false;
+ }
+
+ // not allow proc extra attack spell at extra attack
+ if (m_extraAttacks && triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
+ return false;
+
+ if (!powerRequired || !powerAmountRequired)
+ {
+ TC_LOG_ERROR("spells", "Unit::HandleAuraProcOnPowerAmount: Spell %u have 0 powerAmountRequired in EffectAmount[%d] or 0 powerRequired in EffectMiscValue, not handled custom case?", auraSpellInfo->Id, triggeredByAura->GetEffIndex());
+ return false;
+ }
+
+ if (GetPower(powerRequired) != powerAmountRequired)
+ return false;
+
+ // Custom requirements (not listed in procEx) Warning! damage dealing after this
+ // Custom triggered spells
+ switch (auraSpellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_DRUID:
+ {
+ // Eclipse Mastery Driver Passive
+ if (auraSpellInfo->Id == 79577)
+ {
+ uint32 solarEclipseMarker = 67483;
+ uint32 lunarEclipseMarker = 67484;
+
+ switch (effIndex)
+ {
+ case 0:
+ {
+ if (HasAura(trigger_spell_id))
+ return false;
+
+ // Do not proc if proc spell isnt starfire and starsurge
+ if (procSpell->Id != 2912 && procSpell->Id != 78674)
+ return false;
+
+ if (HasAura(solarEclipseMarker))
+ {
+ RemoveAurasDueToSpell(solarEclipseMarker);
+ CastSpell(this, lunarEclipseMarker, true);
+ }
+ break;
+ }
+ case 1:
+ {
+ if (HasAura(trigger_spell_id))
+ return false;
+
+ // Do not proc if proc spell isnt wrath and starsurge
+ if (procSpell->Id != 5176 && procSpell->Id != 78674)
+ return false;
+
+ if (HasAura(lunarEclipseMarker))
+ {
+ RemoveAurasDueToSpell(lunarEclipseMarker);
+ CastSpell(this, solarEclipseMarker, true);
+ }
+
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(trigger_spell_id))
+ return false;
+
+ // try detect target manually if not set
+ if (target == NULL)
+ target = !(procFlag & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry && triggerEntry->IsPositive() ? this : victim;
+
+ if (basepoints0)
+ CastCustomSpell(target, trigger_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
+ else
+ CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura);
+
+ if (cooldown && GetTypeId() == TYPEID_PLAYER)
+ ToPlayer()->AddSpellCooldown(trigger_spell_id, 0, time(NULL) + cooldown);
+
+ return true;
+}
+
//victim may be NULL
bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
{
@@ -5417,18 +5324,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
victim->RemoveAurasWithMechanic(1<<MECHANIC_STUN, AURA_REMOVE_BY_ENEMY_SPELL);
return true;
}
- // Glyph of Scourge Strike
- case 58642:
- {
- triggered_spell_id = 69961; // Glyph of Scourge Strike
- break;
- }
- // Glyph of Life Tap
- case 63320:
- {
- triggered_spell_id = 63321; // Life Tap
- break;
- }
// Purified Shard of the Scale - Onyxia 10 Caster Trinket
case 69755:
{
@@ -5545,41 +5440,25 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
instance->DoCastSpellOnPlayers(65037); // Achievement criteria marker
break;
}
+ case 47020: // Enter vehicle XT-002 (Scrapbot)
+ {
+ if (GetTypeId() != TYPEID_UNIT)
+ return false;
+
+ Unit* vehicleBase = GetVehicleBase();
+ if (!vehicleBase)
+ return false;
+
+ // Todo: Check if this amount is blizzlike
+ vehicleBase->ModifyHealth(int32(vehicleBase->CountPctFromMaxHealth(1)));
+ break;
+ }
}
break;
}
case SPELLFAMILY_MAGE:
{
- // Magic Absorption
- if (dummySpell->SpellIconID == 459) // only this spell has SpellIconID == 459 and dummy aura
- {
- if (getPowerType() != POWER_MANA)
- return false;
-
- // mana reward
- basepoints0 = CalculatePct(int32(GetMaxPower(POWER_MANA)), triggerAmount);
- target = this;
- triggered_spell_id = 29442;
- break;
- }
- // Arcane Potency
- if (dummySpell->SpellIconID == 2120)
- {
- if (!procSpell)
- return false;
-
- target = this;
- switch (dummySpell->Id)
- {
- case 31571: triggered_spell_id = 57529; break;
- case 31572: triggered_spell_id = 57531; break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non handled spell id: %u", dummySpell->Id);
- return false;
- }
- break;
- }
- // Hot Streak
+ // Hot Streak & Improved Hot Streak
if (dummySpell->SpellIconID == 2999)
{
if (effIndex != 0)
@@ -5592,7 +5471,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (procEx & PROC_EX_CRITICAL_HIT)
{
counter->SetAmount(counter->GetAmount() * 2);
- if (counter->GetAmount() < 100) // not enough
+ if (counter->GetAmount() < 100 && dummySpell->Id != 44445) // not enough or Hot Streak spell
return true;
// Crititcal counted -> roll chance
if (roll_chance_i(triggerAmount))
@@ -5611,109 +5490,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 37436;
break;
}
- switch (dummySpell->Id)
- {
- // Glyph of Polymorph
- case 56375:
- {
- if (!target)
- return false;
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE, 0, target->GetAura(32409)); // SW:D shall not be removed.
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT);
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_LEECH);
- return true;
- }
- // Glyph of Icy Veins
- case 56374:
- {
- RemoveAurasByType(SPELL_AURA_HASTE_SPELLS, 0, 0, true, false);
- RemoveAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
- return true;
- }
- // Glyph of Ice Block
- case 56372:
- {
- Player* player = ToPlayer();
- if (!player)
- return false;
-
- SpellCooldowns const cooldowns = player->GetSpellCooldowns();
- // remove cooldowns on all ranks of Frost Nova
- for (SpellCooldowns::const_iterator itr = cooldowns.begin(); itr != cooldowns.end(); ++itr)
- {
- SpellInfo const* cdSpell = sSpellMgr->GetSpellInfo(itr->first);
- // Frost Nova
- if (cdSpell && cdSpell->SpellFamilyName == SPELLFAMILY_MAGE
- && cdSpell->SpellFamilyFlags[0] & 0x00000040)
- player->RemoveSpellCooldown(cdSpell->Id, true);
- }
- break;
- }
- case 47020: // Enter vehicle XT-002 (Scrapbot)
- {
- if (GetTypeId() != TYPEID_UNIT)
- return false;
-
- Unit* vehicleBase = GetVehicleBase();
- if (!vehicleBase)
- return false;
-
- /// @todo Check if this amount is blizzlike
- vehicleBase->ModifyHealth(int32(vehicleBase->CountPctFromMaxHealth(1)));
- break;
- }
- }
- break;
- }
- case SPELLFAMILY_WARRIOR:
- {
- switch (dummySpell->Id)
- {
- // Victorious
- case 32216:
- {
- RemoveAura(dummySpell->Id);
- return false;
- }
- // Improved Spell Reflection
- case 59088:
- case 59089:
- {
- triggered_spell_id = 59725;
- target = this;
- break;
- }
- }
- // Second Wind
- if (dummySpell->SpellIconID == 1697)
- {
- // only for spells and hit/crit (trigger start always) and not start from self cast spells (5530 Mace Stun Effect for example)
- if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim)
- return false;
- // Need stun or root mechanic
- if (!(procSpell->GetAllEffectsMechanicMask() & ((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:
- TC_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non handled spell id: %u (SW)", dummySpell->Id);
- return false;
- }
-
- target = this;
- break;
- }
- // Glyph of Blocking
- if (dummySpell->Id == 58375)
- {
- triggered_spell_id = 58374;
- break;
- }
- break;
}
case SPELLFAMILY_WARLOCK:
{
@@ -5766,54 +5542,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
}
switch (dummySpell->Id)
{
- // Nightfall
- case 18094:
- case 18095:
- // Glyph of corruption
- case 56218:
- {
- target = this;
- triggered_spell_id = 17941;
- break;
- }
- // Soul Leech
- case 30293:
- case 30295:
- case 30296:
- {
- // Improved Soul Leech
- AuraEffectList const& SoulLeechAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (Unit::AuraEffectList::const_iterator i = SoulLeechAuras.begin(); i != SoulLeechAuras.end(); ++i)
- {
- if ((*i)->GetId() == 54117 || (*i)->GetId() == 54118)
- {
- if ((*i)->GetEffIndex() != 0)
- continue;
- basepoints0 = int32((*i)->GetAmount());
- target = GetGuardianPet();
- if (target)
- {
- // regen mana for pet
- CastCustomSpell(target, 54607, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- }
- // regen mana for caster
- CastCustomSpell(this, 59117, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- // Get second aura of spell for replenishment effect on party
- if (AuraEffect const* aurEff = (*i)->GetBase()->GetEffect(EFFECT_1))
- {
- // Replenishment - roll chance
- if (roll_chance_i(aurEff->GetAmount()))
- CastSpell(this, 57669, true, castItem, triggeredByAura);
- }
- break;
- }
- }
- // health
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- target = this;
- triggered_spell_id = 30294;
- break;
- }
// Shadowflame (Voidheart Raiment set bonus)
case 37377:
{
@@ -5838,63 +5566,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 37378;
break;
}
- // Glyph of Succubus
- case 56250:
- {
- if (!target)
- return false;
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE, 0, target->GetAura(32409)); // SW:D shall not be removed.
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT);
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_LEECH);
- return true;
- }
}
break;
}
case SPELLFAMILY_PRIEST:
{
- // Vampiric Touch
- if (dummySpell->SpellFamilyFlags[1] & 0x00000400)
- {
- if (!victim || !victim->IsAlive())
- return false;
-
- if (effIndex != 0)
- return false;
-
- // victim is caster of aura
- if (triggeredByAura->GetCasterGUID() != victim->GetGUID())
- return false;
-
- // Energize 0.25% of max. mana
- victim->CastSpell(victim, 57669, true, castItem, triggeredByAura);
- return true; // no hidden cooldown
- }
- // Body and Soul
- if (dummySpell->SpellIconID == 2218)
- {
- // Proc only from Abolish desease on self cast
- if (procSpell->Id != 552 || victim != this || !roll_chance_i(triggerAmount))
- return false;
- triggered_spell_id = 64136;
- target = this;
- break;
- }
switch (dummySpell->Id)
{
- // Vampiric Embrace
- case 15286:
- {
- if (!victim || !victim->IsAlive() || procSpell->SpellFamilyFlags[1] & 0x80000)
- return false;
-
- // heal amount
- int32 total = CalculatePct(int32(damage), triggerAmount);
- int32 team = total / 5;
- int32 self = total - team;
- CastCustomSpell(this, 15290, &team, &self, NULL, true, castItem, triggeredByAura);
- return true; // no hidden cooldown
- }
// Priest Tier 6 Trinket (Ashtongue Talisman of Acumen)
case 40438:
{
@@ -5910,29 +5588,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
target = this;
break;
}
- // Improved Shadowform
- case 47570:
- case 47569:
- {
- if (!roll_chance_i(triggerAmount))
- return false;
-
- RemoveMovementImpairingAuras();
- break;
- }
- // Glyph of Dispel Magic
- case 55677:
- {
- // Dispel Magic shares spellfamilyflag with abolish disease
- if (procSpell->SpellIconID != 74)
- return false;
- if (!target || !target->IsFriendlyTo(this))
- return false;
-
- basepoints0 = int32(target->CountPctFromMaxHealth(triggerAmount));
- triggered_spell_id = 56131;
- break;
- }
// Oracle Healing Bonus ("Garments of the Oracle" set)
case 26169:
{
@@ -5979,25 +5634,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
{
switch (dummySpell->Id)
{
- // Glyph of Innervate
- case 54832:
- {
- if (procSpell->SpellIconID != 62)
- return false;
-
- int32 mana_perc = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcValue();
- basepoints0 = int32(CalculatePct(GetCreatePowers(POWER_MANA), mana_perc) / 10);
- triggered_spell_id = 54833;
- target = this;
- break;
- }
- // Glyph of Starfire
- case 54845:
- {
- triggered_spell_id = 54846;
- break;
- }
- // Glyph of Shred
+ // Glyph of Bloodletting
case 54815:
{
if (!target)
@@ -6006,15 +5643,14 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// try to find spell Rip on the target
if (AuraEffect const* AurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00800000, 0x0, 0x0, GetGUID()))
{
- // Rip's max duration, note: spells which modifies Rip's duration also counted like Glyph of Rip
+ // Rip's max duration, note: spells which modifies Rip's duration also counted
uint32 CountMin = AurEff->GetBase()->GetMaxDuration();
// just Rip's max duration without other spells
uint32 CountMax = AurEff->GetSpellInfo()->GetMaxDuration();
// add possible auras' and Glyph of Shred's max duration
- CountMax += 3 * triggerAmount * IN_MILLISECONDS; // Glyph of Shred -> +6 seconds
- CountMax += HasAura(54818) ? 4 * IN_MILLISECONDS : 0; // Glyph of Rip -> +4 seconds
+ CountMax += 3 * triggerAmount * IN_MILLISECONDS; // Glyph of Bloodletting -> +6 seconds
CountMax += HasAura(60141) ? 4 * IN_MILLISECONDS : 0; // Rip Duration/Lacerate Damage -> +4 seconds
// if min < max -> that means caster didn't cast 3 shred yet
@@ -6029,19 +5665,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// if not found Rip
return false;
}
- // Glyph of Rake
- case 54821:
- {
- if (procSpell->SpellVisual[0] == 750 && procSpell->Effects[1].ApplyAuraName == 3)
- {
- if (target && target->GetTypeId() == TYPEID_UNIT)
- {
- triggered_spell_id = 54820;
- break;
- }
- }
- return false;
- }
// Leader of the Pack
case 24932:
{
@@ -6050,13 +5673,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
target = this;
triggered_spell_id = 34299;
- if (triggeredByAura->GetCasterGUID() != GetGUID())
- break;
- int32 basepoints1 = CalculatePct(GetMaxPower(Powers(POWER_MANA)), triggerAmount * 2);
- // Improved Leader of the Pack
- // Check cooldown of heal spell cooldown
- if (GetTypeId() == TYPEID_PLAYER && !ToPlayer()->HasSpellCooldown(34299))
- CastCustomSpell(this, 68285, &basepoints1, 0, 0, true, 0, triggeredByAura);
+ // Regenerate 4% mana
+ int32 mana = CalculatePct(GetCreateMana(), triggerAmount);
+ CastCustomSpell(this, 68285, &mana, NULL, NULL, true, castItem, triggeredByAura);
break;
}
// Healing Touch (Dreamwalker Raiment set)
@@ -6068,15 +5687,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 28742;
break;
}
- // Glyph of Rejuvenation
- case 54754:
- {
- if (!victim || !victim->HealthBelowPct(uint32(triggerAmount)))
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 54755;
- break;
- }
// Healing Touch Refund (Idol of Longevity trinket)
case 28847:
{
@@ -6124,13 +5734,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
target = this;
break;
}
- // Maim Interrupt
- case 44835:
- {
- // Deadly Interrupt Effect
- triggered_spell_id = 32747;
- break;
- }
// Item - Druid T10 Balance 4P Bonus
case 70723:
{
@@ -6164,236 +5767,15 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return true;
}
}
- // Eclipse
- if (dummySpell->SpellIconID == 2856 && GetTypeId() == TYPEID_PLAYER)
- {
- if (!procSpell || effIndex != 0)
- return false;
-
- bool isWrathSpell = (procSpell->SpellFamilyFlags[0] & 1);
-
- if (!roll_chance_f(dummySpell->ProcChance * (isWrathSpell ? 0.6f : 1.0f)))
- return false;
-
- target = this;
- if (target->HasAura(isWrathSpell ? 48517 : 48518))
- return false;
-
- triggered_spell_id = isWrathSpell ? 48518 : 48517;
- break;
- }
- break;
- }
- case SPELLFAMILY_ROGUE:
- {
- switch (dummySpell->Id)
- {
- case 56800: // Glyph of Backstab
- {
- triggered_spell_id = 63975;
- break;
- }
- case 32748: // Deadly Throw Interrupt
- {
- // Prevent cast Deadly Throw Interrupt on self from last effect (apply dummy) of Deadly Throw
- if (this == victim)
- return false;
-
- triggered_spell_id = 32747;
- break;
- }
- }
-
- switch (dummySpell->SpellIconID)
- {
- case 2116: // Quick Recovery
- {
- if (!procSpell)
- return false;
-
- // energy cost save
- basepoints0 = CalculatePct(int32(procSpell->ManaCost), triggerAmount);
- if (basepoints0 <= 0)
- return false;
-
- target = this;
- triggered_spell_id = 31663;
- break;
- }
- case 2909: // Cut to the Chase
- {
- // "refresh your Slice and Dice duration to its 5 combo point maximum"
- // lookup Slice and Dice
- if (AuraEffect const* aur = GetAuraEffect(SPELL_AURA_MOD_MELEE_HASTE, SPELLFAMILY_ROGUE, 0x40000, 0, 0))
- {
- aur->GetBase()->SetDuration(aur->GetSpellInfo()->GetMaxDuration(), true);
- return true;
- }
- return false;
- }
- case 2963: // Deadly Brew
- {
- triggered_spell_id = 3409;
- break;
- }
- }
- break;
- }
- case SPELLFAMILY_HUNTER:
- {
- switch (dummySpell->SpellIconID)
- {
- case 2236: // Thrill of the Hunt
- {
- if (!procSpell)
- return false;
-
- Spell* spell = ToPlayer()->m_spellModTakingSpell;
-
- // Disable charge drop because of Lock and Load
- ToPlayer()->SetSpellModTakingSpell(spell, false);
-
- // Explosive Shot
- if (procSpell->SpellFamilyFlags[2] & 0x200)
- {
- if (!victim)
- return false;
- if (AuraEffect const* pEff = victim->GetAuraEffect(SPELL_AURA_PERIODIC_DUMMY, SPELLFAMILY_HUNTER, 0x0, 0x80000000, 0x0, GetGUID()))
- basepoints0 = pEff->GetSpellInfo()->CalcPowerCost(this, SpellSchoolMask(pEff->GetSpellInfo()->SchoolMask)) * 4/10/3;
- }
- else
- basepoints0 = procSpell->CalcPowerCost(this, SpellSchoolMask(procSpell->SchoolMask)) * 4/10;
-
- ToPlayer()->SetSpellModTakingSpell(spell, true);
-
- if (basepoints0 <= 0)
- return false;
-
- target = this;
- triggered_spell_id = 34720;
- break;
- }
- case 3406: // Hunting Party
- {
- triggered_spell_id = 57669;
- target = this;
- break;
- }
- case 3560: // Rapid Recuperation
- {
- // This effect only from Rapid Killing (mana regen)
- if (!(procSpell->SpellFamilyFlags[1] & 0x01000000))
- return false;
-
- target = this;
-
- switch (dummySpell->Id)
- {
- case 53228: // Rank 1
- triggered_spell_id = 56654;
- break;
- case 53232: // Rank 2
- triggered_spell_id = 58882;
- break;
- }
- break;
- }
- case 3579: // Lock and Load
- {
- // Proc only from periodic (from trap activation proc another aura of this spell)
- if (!(procFlag & PROC_FLAG_DONE_PERIODIC) || !roll_chance_i(triggerAmount))
- return false;
- triggered_spell_id = 56453;
- target = this;
- break;
- }
- }
-
- switch (dummySpell->Id)
- {
- case 57870: // Glyph of Mend Pet
- {
- victim->CastSpell(victim, 57894, true, NULL, NULL, GetGUID());
- return true;
- }
- }
break;
}
case SPELLFAMILY_PALADIN:
{
- // Light's Beacon - Beacon of Light
- if (dummySpell->Id == 53651)
- {
- if (!victim)
- return false;
- triggered_spell_id = 0;
- Unit* beaconTarget = NULL;
- if (GetTypeId() != TYPEID_PLAYER)
- {
- beaconTarget = triggeredByAura->GetBase()->GetCaster();
- if (!beaconTarget || beaconTarget == this || !(beaconTarget->GetAura(53563, victim->GetGUID())))
- return false;
- basepoints0 = int32(damage);
- triggered_spell_id = procSpell->IsRankOf(sSpellMgr->GetSpellInfo(635)) ? 53652 : 53654;
- }
- else
- { // Check Party/Raid Group
- if (Group* group = ToPlayer()->GetGroup())
- {
- for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
- {
- if (Player* member = itr->GetSource())
- {
- // check if it was heal by paladin which cast this beacon of light
- if (member->GetAura(53563, victim->GetGUID()))
- {
- // do not proc when target of beacon of light is healed
- if (member == this)
- return false;
-
- beaconTarget = member;
- basepoints0 = int32(damage);
- triggered_spell_id = procSpell->IsRankOf(sSpellMgr->GetSpellInfo(635)) ? 53652 : 53654;
- break;
- }
- }
- }
- }
- }
-
- if (triggered_spell_id && beaconTarget)
- {
- victim->CastCustomSpell(beaconTarget, triggered_spell_id, &basepoints0, NULL, NULL, true);
- return true;
- }
-
- return false;
- }
// Judgements of the Wise
if (dummySpell->SpellIconID == 3017)
{
target = this;
triggered_spell_id = 31930;
- // replenishment
- CastSpell(this, 57669, true, castItem, triggeredByAura);
- break;
- }
- // Righteous Vengeance
- if (dummySpell->SpellIconID == 3025)
- {
- // 4 damage tick
- basepoints0 = triggerAmount * damage / 400;
- triggered_spell_id = 61840;
- // Add remaining ticks to damage done
- basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE);
- break;
- }
- // Sheath of Light
- if (dummySpell->SpellIconID == 3030)
- {
- // 4 healing tick
- basepoints0 = triggerAmount * damage / 400;
- triggered_spell_id = 54203;
break;
}
switch (dummySpell->Id)
@@ -6415,38 +5797,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
target = this;
break;
}
- // Heart of the Crusader
- case 20335: // rank 1
- triggered_spell_id = 21183;
- break;
- case 20336: // rank 2
- triggered_spell_id = 54498;
- break;
- case 20337: // rank 3
- triggered_spell_id = 54499;
- break;
- // Judgement of Light
- case 20185:
- {
- if (!victim)
- return false;
-
- // 2% of maximum health
- basepoints0 = int32(victim->CountPctFromMaxHealth(2));
- victim->CastCustomSpell(victim, 20267, &basepoints0, 0, 0, true, 0, triggeredByAura);
- return true;
- }
- // Judgement of Wisdom
- case 20186:
- {
- if (victim && victim->IsAlive() && victim->getPowerType() == POWER_MANA)
- {
- // 2% of base mana
- basepoints0 = int32(CalculatePct(victim->GetCreateMana(), 2));
- victim->CastCustomSpell(victim, 20268, &basepoints0, NULL, NULL, true, 0, triggeredByAura);
- }
- return true;
- }
// Holy Power (Redemption Armor set)
case 28789:
{
@@ -6478,10 +5828,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
}
break;
}
- // Seal of Vengeance (damage calc on apply aura)
case 31801:
{
- if (effIndex != 0) // effect 1, 2 used by seal unleashing code
+ if (effIndex != 0) // effect 2 used by seal unleashing code
return false;
// At melee attack or Hammer of the Righteous spell damage considered as melee attack
@@ -6494,7 +5843,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 31803;
- // On target with 5 stacks of Holy Vengeance direct damage is done
+ // On target with 5 stacks of Censure direct damage is done
if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
{
if (aur->GetStackAmount() == 5)
@@ -6510,61 +5859,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return false;
break;
}
- // Seal of Corruption
- case 53736:
- {
- if (effIndex != 0) // effect 1, 2 used by seal unleashing code
- return false;
-
- // At melee attack or Hammer of the Righteous spell damage considered as melee attack
- bool stacker = !procSpell || procSpell->Id == 53595;
- // spells with SPELL_DAMAGE_CLASS_MELEE excluding Judgements
- bool damager = procSpell && (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39));
-
- if (!stacker && !damager)
- return false;
-
- triggered_spell_id = 53742;
-
- // On target with 5 stacks of Blood Corruption direct damage is done
- if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
- {
- if (aur->GetStackAmount() == 5)
- {
- if (stacker)
- aur->RefreshDuration();
- CastSpell(victim, 53739, true);
- return true;
- }
- }
-
- if (!stacker)
- return false;
- break;
- }
- // Spiritual Attunement
- case 31785:
- case 33776:
- {
- // if healed by another unit (victim)
- if (this == victim)
- return false;
-
- // heal amount
- basepoints0 = int32(CalculatePct(std::min(damage, GetMaxHealth() - GetHealth()), triggerAmount));
- target = this;
-
- if (basepoints0)
- triggered_spell_id = 31786;
- break;
- }
// Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
case 40470:
{
if (!procSpell)
return false;
- float chance;
+ float chance;
// Flash of light/Holy light
if (procSpell->SpellFamilyFlags[0] & 0xC0000000)
@@ -6586,13 +5887,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
break;
}
- // Glyph of Holy Light
- case 54937:
- {
- triggered_spell_id = 54968;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- break;
- }
// Item - Paladin T8 Holy 2P Bonus
case 64890:
{
@@ -6672,14 +5966,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
{
switch (dummySpell->Id)
{
- // Tidal Force
- case 55198:
- {
- // Remove aura stack from caster
- RemoveAuraFromStack(55166);
- // drop charges
- return false;
- }
// Totemic Power (The Earthshatterer set)
case 28823:
{
@@ -6752,26 +6038,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
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 = 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:
- {
- TC_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non handled item enchantment (rank?) %u for spell id: %u (Windfury)",
- castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)), dummySpell->Id);
- return false;
- }
- }
-
+ uint32 spellId = 8232;
SpellInfo const* windfurySpellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!windfurySpellInfo)
{
@@ -6831,17 +6098,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
target = this;
break;
}
- // Glyph of Healing Wave
- case 55440:
- {
- // Not proc from self heals
- if (this == victim)
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- target = this;
- triggered_spell_id = 55533;
- break;
- }
// Spirit Hunt
case 58877:
{
@@ -6914,23 +6170,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// if not found Flame Shock
return false;
}
- case 63280: // Glyph of Totem of Wrath
- {
- if (procSpell->SpellIconID != 2019)
- return false;
-
- if (Creature* totem = GetMap()->GetCreature(m_SummonSlot[1])) // Fire totem summon slot
- {
- if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(totem->m_spells[0]))
- {
- int32 bp0 = CalculatePct(totemSpell->Effects[EFFECT_0].CalcValue(), triggerAmount);
- int32 bp1 = CalculatePct(totemSpell->Effects[EFFECT_1].CalcValue(), triggerAmount);
- CastCustomSpell(this, 63283, &bp0, &bp1, NULL, true);
- return true;
- }
- }
- return false;
- }
break;
}
// Frozen Power
@@ -6947,14 +6186,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 63685;
break;
}
- // Ancestral Awakening
- if (dummySpell->SpellIconID == 3065)
- {
- triggered_spell_id = 52759;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- target = this;
- break;
- }
// Flametongue Weapon (Passive)
if (dummySpell->SpellFamilyFlags[0] & 0x200000)
{
@@ -7002,109 +6233,19 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
CastCustomSpell(victim, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
return true;
}
- // Improved Water Shield
- if (dummySpell->SpellIconID == 2287)
- {
- // Default chance for Healing Wave and Riptide
- float chance = (float)triggeredByAura->GetAmount();
-
- if (procSpell->SpellFamilyFlags[0] & 0x80)
- // Lesser Healing Wave - 0.6 of default
- chance *= 0.6f;
- else if (procSpell->SpellFamilyFlags[0] & 0x100)
- // Chain heal - 0.3 of default
- chance *= 0.3f;
-
- if (!roll_chance_f(chance))
- return false;
-
- // Water Shield
- if (AuraEffect const* aurEff = GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0, 0x00000020, 0))
- {
- uint32 spell = aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
- CastSpell(this, spell, true, castItem, triggeredByAura);
- return true;
- }
- return false;
- }
- // Lightning Overload
- if (dummySpell->SpellIconID == 2018) // only this spell has SpellFamily Shaman SpellIconID == 2018 and dummy aura
- {
- if (!procSpell || GetTypeId() != TYPEID_PLAYER || !victim)
- return false;
-
- // custom cooldown processing case
- if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(dummySpell->Id))
- return false;
-
- uint32 spellId = 0;
- // Every Lightning Bolt and Chain Lightning spell have duplicate vs half damage and zero cost
- switch (procSpell->Id)
- {
- // Lightning Bolt
- case 403: spellId = 45284; break; // Rank 1
- case 529: spellId = 45286; break; // Rank 2
- case 548: spellId = 45287; break; // Rank 3
- case 915: spellId = 45288; break; // Rank 4
- case 943: spellId = 45289; break; // Rank 5
- case 6041: spellId = 45290; break; // Rank 6
- case 10391: spellId = 45291; break; // Rank 7
- case 10392: spellId = 45292; break; // Rank 8
- case 15207: spellId = 45293; break; // Rank 9
- 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
- case 2860: spellId = 45299; break; // Rank 3
- case 10605: spellId = 45300; break; // Rank 4
- case 25439: spellId = 45301; break; // Rank 5
- case 25442: spellId = 45302; break; // Rank 6
- case 49270: spellId = 49268; break; // Rank 7
- case 49271: spellId = 49269; break; // Rank 8
- default:
- TC_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id);
- return false;
- }
-
- // Chain Lightning
- if (procSpell->SpellFamilyFlags[0] & 0x2)
- {
- // Chain lightning has [LightOverload_Proc_Chance] / [Max_Number_of_Targets] chance to proc of each individual target hit.
- // A maxed LO would have a 33% / 3 = 11% chance to proc of each target.
- // LO chance was already "accounted" at the proc chance roll, now need to divide the chance by [Max_Number_of_Targets]
- float chance = 100.0f / procSpell->Effects[effIndex].ChainTarget;
- if (!roll_chance_f(chance))
- return false;
-
- // Remove cooldown (Chain Lightning - has Category Recovery time)
- ToPlayer()->RemoveSpellCooldown(spellId);
- }
-
- CastSpell(victim, spellId, true, castItem, triggeredByAura);
-
- if (cooldown && GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->AddSpellCooldown(dummySpell->Id, 0, time(NULL) + cooldown);
-
- return true;
- }
// Static Shock
if (dummySpell->SpellIconID == 3059)
{
// Lightning Shield
- if (AuraEffect const* aurEff = GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400, 0, 0))
+ if (GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400, 0, 0))
{
- uint32 spell = sSpellMgr->GetSpellWithRank(26364, aurEff->GetSpellInfo()->GetRank());
+ uint32 spell = 26364;
// custom cooldown processing case
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(spell))
ToPlayer()->RemoveSpellCooldown(spell);
CastSpell(target, spell, true, castItem, triggeredByAura);
- aurEff->GetBase()->DropCharge();
return true;
}
return false;
@@ -7113,7 +6254,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
}
case SPELLFAMILY_DEATHKNIGHT:
{
- // Blood-Caked Strike - Blood-Caked Blade
+ // Blood-Caked Blade
if (dummySpell->SpellIconID == 138)
{
if (!target || !target->IsAlive())
@@ -7122,22 +6263,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = dummySpell->Effects[effIndex].TriggerSpell;
break;
}
- // Improved Blood Presence
- if (dummySpell->SpellIconID == 2636)
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- break;
- }
- // Butchery
- if (dummySpell->SpellIconID == 2664)
- {
- basepoints0 = triggerAmount;
- triggered_spell_id = 50163;
- target = this;
- break;
- }
// Dancing Rune Weapon
if (dummySpell->Id == 49028)
{
@@ -7163,13 +6288,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
else
return false;
}
- // Mark of Blood
- if (dummySpell->Id == 49005)
- {
- /// @todo need more info (cooldowns/PPM)
- triggered_spell_id = 61607;
- break;
- }
// Unholy Blight
if (dummySpell->Id == 49194)
{
@@ -7188,21 +6306,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE);
break;
}
- // Vendetta
- if (dummySpell->SpellFamilyFlags[0] & 0x10000)
- {
- basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
- triggered_spell_id = 50181;
- target = this;
- break;
- }
- // Necrosis
- if (dummySpell->SpellIconID == 2709)
- {
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 51460;
- break;
- }
// Threat of Thassarian
if (dummySpell->SpellIconID == 2023)
{
@@ -7215,45 +6318,12 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
switch (procSpell->Id)
{
- // Obliterate
- case 49020: triggered_spell_id = 66198; break; // Rank 1
- case 51423: triggered_spell_id = 66972; break; // Rank 2
- case 51424: triggered_spell_id = 66973; break; // Rank 3
- case 51425: triggered_spell_id = 66974; break; // Rank 4
-
- // Frost Strike
- case 49143: triggered_spell_id = 66196; break; // Rank 1
- case 51416: triggered_spell_id = 66958; break; // Rank 2
- case 51417: triggered_spell_id = 66959; break; // Rank 3
- case 51418: triggered_spell_id = 66960; break; // Rank 4
- case 51419: triggered_spell_id = 66961; break; // Rank 5
- case 55268: triggered_spell_id = 66962; break; // Rank 6
-
- // Plague Strike
- case 45462: triggered_spell_id = 66216; break; // Rank 1
- case 49917: triggered_spell_id = 66988; break; // Rank 2
- case 49918: triggered_spell_id = 66989; break; // Rank 3
- case 49919: triggered_spell_id = 66990; break; // Rank 4
- case 49920: triggered_spell_id = 66991; break; // Rank 5
- case 49921: triggered_spell_id = 66992; break; // Rank 6
-
- // Death Strike
- case 49998: triggered_spell_id = 66188; break; // Rank 1
- case 49999: triggered_spell_id = 66950; break; // Rank 2
- case 45463: triggered_spell_id = 66951; break; // Rank 3
- case 49923: triggered_spell_id = 66952; break; // Rank 4
- case 49924: triggered_spell_id = 66953; break; // Rank 5
-
- // Rune Strike
- case 56815: triggered_spell_id = 66217; break; // Rank 1
-
- // Blood Strike
- case 45902: triggered_spell_id = 66215; break; // Rank 1
- case 49926: triggered_spell_id = 66975; break; // Rank 2
- case 49927: triggered_spell_id = 66976; break; // Rank 3
- case 49928: triggered_spell_id = 66977; break; // Rank 4
- case 49929: triggered_spell_id = 66978; break; // Rank 5
- case 49930: triggered_spell_id = 66979; break; // Rank 6
+ case 49020: triggered_spell_id = 66198; break; // Obliterate
+ case 49143: triggered_spell_id = 66196; break; // Frost Strike
+ case 45462: triggered_spell_id = 66216; break; // Plague Strike
+ case 49998: triggered_spell_id = 66188; break; // Death Strike
+ case 56815: triggered_spell_id = 66217; break; // Rune Strike
+ case 45902: triggered_spell_id = 66215; break; // Blood Strike
default:
return false;
}
@@ -7272,79 +6342,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
target = this;
break;
}
- // Wandering Plague
- if (dummySpell->SpellIconID == 1614)
- {
- if (!roll_chance_f(GetUnitCriticalChance(BASE_ATTACK, victim)))
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 50526;
- break;
- }
- // Sudden Doom
- if (dummySpell->SpellIconID == 1939 && GetTypeId() == TYPEID_PLAYER)
- {
- SpellChainNode const* chain = NULL;
- // get highest rank of the Death Coil spell
- PlayerSpellMap const& sp_list = ToPlayer()->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
- {
- // check if shown in spell book
- if (!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
- continue;
-
- SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(itr->first);
- if (!spellProto)
- continue;
-
- if (spellProto->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT
- && spellProto->SpellFamilyFlags[0] & 0x2000)
- {
- SpellChainNode const* newChain = sSpellMgr->GetSpellChainNode(itr->first);
-
- // No chain entry or entry lower than found entry
- if (!chain || !newChain || (chain->rank < newChain->rank))
- {
- triggered_spell_id = itr->first;
- chain = newChain;
- }
- else
- continue;
- // Found spell is last in chain - do not need to look more
- // Optimisation for most common case
- if (chain && chain->last->Id == itr->first)
- break;
- }
- }
- }
- break;
- }
- case SPELLFAMILY_POTION:
- {
- // alchemist's stone
- if (dummySpell->Id == 17619)
- {
- if (procSpell->SpellFamilyName == SPELLFAMILY_POTION)
- {
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
- {
- if (procSpell->Effects[i].Effect == SPELL_EFFECT_HEAL)
- {
- triggered_spell_id = 21399;
- }
- else if (procSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE)
- {
- triggered_spell_id = 21400;
- }
- else
- continue;
-
- basepoints0 = int32(CalculateSpellDamage(this, procSpell, i) * 0.4f);
- CastCustomSpell(this, triggered_spell_id, &basepoints0, NULL, NULL, true, NULL, triggeredByAura);
- }
- return true;
- }
- }
break;
}
case SPELLFAMILY_PET:
@@ -7407,9 +6404,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return true;
}
+ /*
+ */
+
+
// Used in case when access to whole aura is needed
// All procs should be handled like this...
-bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 /*procFlag*/, uint32 procEx, uint32 cooldown, bool * handled)
+bool Unit::HandleAuraProc(Unit* victim, uint32 /*damage*/, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown, bool * handled)
{
SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();
@@ -7467,30 +6468,8 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
break;
case SPELLFAMILY_PALADIN:
{
- // Infusion of Light
- if (procSpell && dummySpell->SpellIconID == 3021)
- {
- // Flash of Light HoT on Flash of Light when Sacred Shield active
- if (procSpell->SpellFamilyFlags[0] & 0x40000000 && procSpell->SpellIconID == 242)
- {
- *handled = true;
- if (victim && victim->HasAura(53601))
- {
- int32 bp0 = CalculatePct(int32(damage / 12), dummySpell->Effects[EFFECT_2].CalcValue());
- // Item - Paladin T9 Holy 4P Bonus
- if (AuraEffect const* aurEff = GetAuraEffect(67191, 0))
- AddPct(bp0, aurEff->GetAmount());
- CastCustomSpell(victim, 66922, &bp0, NULL, NULL, true);
- return true;
- }
- }
- // but should not proc on non-critical Holy Shocks
- else if ((procSpell->SpellFamilyFlags[0] & 0x200000 || procSpell->SpellFamilyFlags[1] & 0x10000) && !(procEx & PROC_EX_CRITICAL_HIT))
- *handled = true;
- break;
- }
// Judgements of the Just
- else if (dummySpell->SpellIconID == 3015)
+ if (dummySpell->SpellIconID == 3015)
{
*handled = true;
CastSpell(victim, 68055, true);
@@ -7521,24 +6500,8 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
}
case SPELLFAMILY_MAGE:
{
- // Combustion
switch (dummySpell->Id)
{
- case 11129:
- {
- *handled = true;
- Unit* caster = triggeredByAura->GetCaster();
- if (!caster || !damage)
- return false;
-
- // last charge and crit
- if (triggeredByAura->GetCharges() <= 1 && (procEx & PROC_EX_CRITICAL_HIT))
- return true; // charge counting (will removed)
-
- CastSpell(this, 28682, true);
-
- return (procEx & PROC_EX_CRITICAL_HIT) != 0;
- }
// Empowered Fire
case 31656:
case 31657:
@@ -7629,13 +6592,6 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
}
return true;
}
- // Hungering Cold aura drop
- case 51209:
- *handled = true;
- // Drop only in not disease case
- if (procSpell && procSpell->Dispel == DISPEL_DISEASE)
- return false;
- return true;
}
break;
}
@@ -7765,85 +6721,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
}
}
break;
- case SPELLFAMILY_MAGE:
- if (auraSpellInfo->SpellIconID == 2127) // Blazing Speed
- {
- switch (auraSpellInfo->Id)
- {
- case 31641: // Rank 1
- case 31642: // Rank 2
- trigger_spell_id = 31643;
- break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u miss posibly Blazing Speed", auraSpellInfo->Id);
- return false;
- }
- }
- break;
- case SPELLFAMILY_WARLOCK:
- {
- // Drain Soul
- if (auraSpellInfo->SpellFamilyFlags[0] & 0x4000)
- {
- // Improved Drain Soul
- Unit::AuraEffectList const& mAddFlatModifier = GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (Unit::AuraEffectList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i)
- {
- if ((*i)->GetMiscValue() == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellInfo()->SpellIconID == 113)
- {
- int32 value2 = CalculateSpellDamage(this, (*i)->GetSpellInfo(), 2);
- basepoints0 = int32(CalculatePct(GetMaxPower(POWER_MANA), value2));
- // 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;
- }
- // Nether Protection
- else if (auraSpellInfo->SpellIconID == 1985)
- {
- if (!procSpell)
- return false;
- switch (GetFirstSchoolInMask(procSpell->GetSchoolMask()))
- {
- case SPELL_SCHOOL_NORMAL:
- return false; // ignore
- case SPELL_SCHOOL_HOLY: trigger_spell_id = 54370; break;
- 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;
- }
- }
- break;
- }
- case SPELLFAMILY_PRIEST:
- {
- // Blessed Recovery
- 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:
- TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id);
- return false;
- }
- basepoints0 = CalculatePct(int32(damage), triggerAmount) / 3;
- target = this;
- // Add remaining ticks to healing done
- basepoints0 += GetRemainingPeriodicAmount(GetGUID(), trigger_spell_id, SPELL_AURA_PERIODIC_HEAL);
- }
- break;
- }
case SPELLFAMILY_DRUID:
{
switch (auraSpellInfo->Id)
@@ -7855,8 +6732,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
{
case FORM_NONE: 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_BEAR: trigger_spell_id = 37340; break;
case FORM_TREE: trigger_spell_id = 37342; break;
case FORM_MOONKIN: trigger_spell_id = 37343; break;
default:
@@ -7870,8 +6746,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
switch (GetShapeshiftForm())
{
case FORM_CAT: trigger_spell_id = 67355; break;
- case FORM_BEAR:
- case FORM_DIREBEAR: trigger_spell_id = 67354; break;
+ case FORM_BEAR: trigger_spell_id = 67354; break;
default:
return false;
}
@@ -7980,124 +6855,14 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
break;
}
default:
- // Illumination
- if (auraSpellInfo->SpellIconID == 241)
- {
- if (!procSpell)
- return false;
- // procspell is triggered spell but we need mana cost of original cast spell
- uint32 originalSpellId = procSpell->Id;
- // Holy Shock heal
- if (procSpell->SpellFamilyFlags[1] & 0x00010000)
- {
- 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;
- case 48820: originalSpellId = 48824; break;
- case 48821: originalSpellId = 48825; break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u not handled in HShock", procSpell->Id);
- return false;
- }
- }
- SpellInfo const* originalSpell = sSpellMgr->GetSpellInfo(originalSpellId);
- if (!originalSpell)
- {
- TC_LOG_ERROR("entities.unit", "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 = int32(originalSpell->ManaCost + CalculatePct(GetCreateMana(), originalSpell->ManaCostPercentage));
- basepoints0 = CalculatePct(cost, auraSpellInfo->Effects[1].CalcValue());
- trigger_spell_id = 20272;
- target = this;
- }
break;
}
break;
}
- case SPELLFAMILY_SHAMAN:
- {
- switch (auraSpellInfo->Id)
- {
- case 30881: // Nature's Guardian Rank 1
- case 30883: // Nature's Guardian Rank 2
- case 30884: // Nature's Guardian Rank 3
- case 30885: // Nature's Guardian Rank 4
- case 30886: // Nature's Guardian Rank 5
- {
- if (HealthBelowPct(30))
- {
- basepoints0 = int32(auraSpellInfo->Effects[EFFECT_0].CalcValue() * GetMaxHealth() / 100.0f);
- target = this;
- trigger_spell_id = 31616;
- /// @todo Threat part
- }
- else
- return false;
- break;
- }
- default:
- {
- // Lightning Shield (overwrite non existing triggered spell call in spell.dbc
- if (auraSpellInfo->SpellFamilyFlags[0] & 0x400)
- {
- trigger_spell_id = sSpellMgr->GetSpellWithRank(26364, auraSpellInfo->GetRank());
- }
- // Nature's Guardian
- else if (auraSpellInfo->SpellIconID == 2013)
- {
- // Check health condition - should drop to less 30% (damage deal after this!)
- if (!HealthBelowPctDamaged(30, damage))
- return false;
-
- if (victim && victim->IsAlive())
- victim->getThreatManager().modifyThreatPercent(this, -10);
-
- basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
- trigger_spell_id = 31616;
- target = this;
- }
- }
- }
- break;
- }
case SPELLFAMILY_DEATHKNIGHT:
{
- // Acclimation
- if (auraSpellInfo->SpellIconID == 1930)
- {
- if (!procSpell)
- return false;
- switch (GetFirstSchoolInMask(procSpell->GetSchoolMask()))
- {
- 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 = 50486; break;
- default:
- return false;
- }
- }
- // Blood Presence (Improved)
- else if (auraSpellInfo->Id == 63611)
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- trigger_spell_id = 50475;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- }
// Item - Death Knight T10 Melee 4P Bonus
- else if (auraSpellInfo->Id == 70656)
+ if (auraSpellInfo->Id == 70656)
{
if (GetTypeId() != TYPEID_PLAYER || getClass() != CLASS_DEATH_KNIGHT)
return false;
@@ -8181,7 +6946,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
// Deflection
case 52420:
{
- if (!HealthBelowPct(35))
+ if (!HealthBelowPctDamaged(35, damage))
return false;
break;
}
@@ -8194,16 +6959,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
return false;
break;
}
- // Deadly Swiftness (Rank 1)
- case 31255:
- {
- // whenever you deal damage to a target who is below 20% health.
- if (!victim || !victim->IsAlive() || victim->HealthAbovePct(20))
- return false;
-
- target = this;
- trigger_spell_id = 22588;
- }
// Greater Heal Refund (Avatar Raiment set)
case 37594:
{
@@ -8226,36 +6981,17 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
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;
- }
// Decimation
case 63156:
case 63158:
- // Can proc only if target has hp below 35%
- if (!victim || !victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, procSpell, this))
+ // Can proc only if target has hp below 25%
+ if (!victim || !victim->HealthBelowPct(auraSpellInfo->Effects[EFFECT_1].CalcValue()))
return false;
break;
// Deathbringer Saurfang - Blood Beast's Blood Link
case 72176:
basepoints0 = 3;
break;
- case 15337: // Improved Spirit Tap (Rank 1)
- case 15338: // Improved Spirit Tap (Rank 2)
- {
- if (procSpell->SpellFamilyFlags[0] & 0x800000)
- if ((procSpell->Id != 58381) || !roll_chance_i(50))
- return false;
-
- target = victim;
- break;
- }
// Professor Putricide - Ooze Spell Tank Protection
case 71770:
if (victim)
@@ -8276,52 +7012,11 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
break;
}
- // Blade Barrier
- if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 85 && procSpell)
- {
- Player* player = ToPlayer();
- if (!player || player->getClass() != CLASS_DEATH_KNIGHT)
- return false;
-
- if (!player->IsBaseRuneSlotsOnCooldown(RUNE_BLOOD))
- return false;
- }
-
- // Rime
- else if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 56)
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- // Howling Blast
- ToPlayer()->RemoveSpellCategoryCooldown(1248, true);
- }
-
// Custom basepoints/target for exist spell
// dummy basepoints or other customs
switch (trigger_spell_id)
{
// Auras which should proc on area aura source (caster in this case):
- // Turn the Tables
- case 52914:
- case 52915:
- case 52910:
- // Honor Among Thieves
- case 52916:
- {
- target = triggeredByAura->GetBase()->GetCaster();
- if (!target)
- return false;
-
- if (cooldown && target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->HasSpellCooldown(trigger_spell_id))
- return false;
-
- target->CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura);
-
- if (cooldown && GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->AddSpellCooldown(trigger_spell_id, 0, time(NULL) + cooldown);
- return true;
- }
// Cast positive spell on enemy target
case 7099: // Curse of Mending
case 39703: // Curse of Mending
@@ -8331,14 +7026,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
target = victim;
break;
}
- // Combo points add triggers (need add combopoint only for main target, and after possible combopoints reset)
- case 15250: // Rogue Setup
- {
- // applied only for main target
- if (!victim || (GetTypeId() == TYPEID_PLAYER && victim != ToPlayer()->GetSelectedUnit()))
- return false;
- break; // continue normal case
- }
// Finish movies that add combo
case 14189: // Seal Fate (Netherblade set)
case 14157: // Ruthlessness
@@ -8355,12 +7042,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
CastSpell(this, 70721, true);
break;
}
- // Shamanistic Rage triggered spell
- case 30824:
- {
- basepoints0 = int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), triggerAmount));
- break;
- }
// Enlightenment (trigger only from mana cost spells)
case 35095:
{
@@ -8368,22 +7049,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
return false;
break;
}
- // Demonic Pact
- case 48090:
- {
- // Get talent aura from owner
- if (IsPet())
- if (Unit* owner = GetOwner())
- {
- if (AuraEffect* aurEff = owner->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, 3220, 0))
- {
- basepoints0 = int32((aurEff->GetAmount() * owner->SpellBaseDamageBonusDone(SpellSchoolMask(SPELL_SCHOOL_MASK_MAGIC)) + 100.0f) / 100.0f); /// @todo Is it right?
- CastCustomSpell(this, trigger_spell_id, &basepoints0, &basepoints0, NULL, true, castItem, triggeredByAura);
- return true;
- }
- }
- break;
- }
case 46916: // Slam! (Bloodsurge proc)
case 52437: // Sudden Death
{
@@ -8398,14 +7063,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
}
break;
}
- // Sword and Board
- case 50227:
- {
- // Remove cooldown on Shield Slam
- if (GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->RemoveSpellCategoryCooldown(1209, true);
- break;
- }
// Maelstrom Weapon
case 53817:
{
@@ -8422,35 +7079,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
CastSpell(this, 70831, true, castItem, triggeredByAura);
break;
}
- // Astral Shift
- case 52179:
- {
- if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim)
- return false;
-
- // Need stun, fear or silence mechanic
- if (!(procSpell->GetAllEffectsMechanicMask() & ((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 (!(procSpell->GetAllEffectsMechanicMask() & ((1<<MECHANIC_INTERRUPT)|(1<<MECHANIC_SILENCE))))
- return false;
- break;
- }
- // Lock and Load
- case 56453:
- {
- // Proc only from Frost/Freezing trap activation or from Freezing Arrow (the periodic dmg proc handled elsewhere)
- if (!(procFlags & PROC_FLAG_DONE_TRAP_ACTIVATION) || !procSpell || !(procSpell->SchoolMask & SPELL_SCHOOL_MASK_FROST) || !roll_chance_i(triggerAmount))
- return false;
- break;
- }
// Glyph of Death's Embrace
case 58679:
{
@@ -8459,14 +7087,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
return false;
break;
}
- // Glyph of Death Grip
- case 58628:
- {
- // remove cooldown of Death Grip
- if (GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->RemoveSpellCooldown(49576, true);
- return true;
- }
// Savage Defense
case 62606:
{
@@ -8513,7 +7133,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
return true;
}
-bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown)
+bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* /*procSpell*/, uint32 cooldown)
{
int32 scriptId = triggeredByAura->GetMiscValue();
@@ -8527,27 +7147,6 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, Au
switch (scriptId)
{
- case 836: // Improved Blizzard (Rank 1)
- {
- if (!procSpell || procSpell->SpellVisual[0] != 9487)
- return false;
- triggered_spell_id = 12484;
- break;
- }
- case 988: // Improved Blizzard (Rank 2)
- {
- if (!procSpell || procSpell->SpellVisual[0] != 9487)
- return false;
- triggered_spell_id = 12485;
- break;
- }
- case 989: // Improved Blizzard (Rank 3)
- {
- if (!procSpell || procSpell->SpellVisual[0] != 9487)
- return false;
- triggered_spell_id = 12486;
- break;
- }
case 4533: // Dreamwalker Raiment 2 pieces bonus
{
// Chance 50%
@@ -8567,26 +7166,6 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, Au
case 4537: // Dreamwalker Raiment 6 pieces bonus
triggered_spell_id = 28750; // Blessing of the Claw
break;
- case 5497: // Improved Mana Gems
- triggered_spell_id = 37445; // Mana Surge
- break;
- case 7010: // Revitalize - can proc on full hp target
- case 7011:
- case 7012:
- {
- if (!roll_chance_i(triggeredByAura->GetAmount()))
- return false;
- switch (victim->getPowerType())
- {
- case POWER_MANA: triggered_spell_id = 48542; break;
- case POWER_RAGE: triggered_spell_id = 48541; break;
- case POWER_ENERGY: triggered_spell_id = 48540; break;
- case POWER_RUNIC_POWER: triggered_spell_id = 48543; break;
- default:
- break;
- }
- break;
- }
default:
break;
}
@@ -8658,10 +7237,6 @@ void Unit::setPowerType(Powers new_powertype)
case POWER_ENERGY:
SetMaxPower(POWER_ENERGY, uint32(std::ceil(GetCreatePowers(POWER_ENERGY) * powerMultiplier)));
break;
- case POWER_HAPPINESS:
- SetMaxPower(POWER_HAPPINESS, uint32(std::ceil(GetCreatePowers(POWER_HAPPINESS) * powerMultiplier)));
- SetPower(POWER_HAPPINESS, uint32(std::ceil(GetCreatePowers(POWER_HAPPINESS) * powerMultiplier)));
- break;
}
}
@@ -9149,7 +7724,7 @@ bool Unit::HasAuraState(AuraStateType flag, SpellInfo const* spellProto, Unit co
{
AuraEffectList const& stateAuras = Caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE);
for (AuraEffectList::const_iterator j = stateAuras.begin(); j != stateAuras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(spellProto))
+ if ((*j)->IsAffectingSpell(spellProto))
return true;
}
// Check per caster aura state
@@ -9183,7 +7758,7 @@ void Unit::SetOwnerGUID(uint64 owner)
SetFieldNotifyFlag(UF_FLAG_OWNER);
- UpdateData udata;
+ UpdateData udata(GetMapId());
WorldPacket packet;
BuildValuesUpdateBlockForPlayer(&udata, player);
udata.BuildPacket(&packet);
@@ -9228,7 +7803,7 @@ Player* Unit::GetAffectingPlayer() const
return NULL;
}
-Minion *Unit::GetFirstMinion() const
+Minion* Unit::GetFirstMinion() const
{
if (uint64 pet_guid = GetMinionGUID())
{
@@ -9494,10 +8069,7 @@ void Unit::SetCharm(Unit* charm, bool apply)
_isWalkingBeforeCharm = charm->IsWalking();
if (_isWalkingBeforeCharm)
- {
charm->SetWalk(false);
- charm->SendMovementFlagUpdate();
- }
m_Controlled.insert(charm);
}
@@ -9532,10 +8104,7 @@ void Unit::SetCharm(Unit* charm, bool apply)
}
if (charm->IsWalking() != _isWalkingBeforeCharm)
- {
charm->SetWalk(_isWalkingBeforeCharm);
- charm->SendMovementFlagUpdate(true); // send packet to self, to update movement state on player.
- }
if (charm->GetTypeId() == TYPEID_PLAYER
|| !charm->ToCreature()->HasUnitTypeMask(UNIT_MASK_MINION)
@@ -9574,7 +8143,7 @@ int32 Unit::DealHeal(Unit* victim, uint32 addhealth)
// use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria)
if (gain)
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, victim);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, 0, victim);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST, addhealth);
}
@@ -9850,7 +8419,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(spellProto))
+ if (!(*i)->IsAffectingSpell(spellProto))
continue;
switch ((*i)->GetMiscValue())
@@ -10009,26 +8578,40 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage
if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue())))
AddPct(DoneTotalMod, (*i)->GetAmount());
+ // Add SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC percent bonus
+ AddPct(DoneTotalMod, GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC, spellProto->Mechanic));
+
// done scripted mod (take it from owner)
Unit const* owner = GetOwner() ? GetOwner() : this;
AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(spellProto))
+ if (!(*i)->IsAffectingSpell(spellProto))
continue;
switch ((*i)->GetMiscValue())
{
case 4920: // Molten Fury
case 4919:
- case 6917: // Death's Embrace
- case 6926:
- case 6928:
{
if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
AddPct(DoneTotalMod, (*i)->GetAmount());
break;
}
+ case 6917: // Death's Embrace damage effect
+ case 6926:
+ case 6928:
+ {
+ // Health at 25% or less (25% stored at effect 2 of the spell)
+ if (victim->HealthBelowPct(CalculateSpellDamage(this, (*i)->GetSpellInfo(), EFFECT_2)))
+ AddPct(DoneTotalMod, (*i)->GetAmount());
+ }
+ case 6916: // Death's Embrace heal effect
+ case 6925:
+ case 6927:
+ if (HealthBelowPct(CalculateSpellDamage(this, (*i)->GetSpellInfo(), EFFECT_2)))
+ AddPct(DoneTotalMod, (*i)->GetAmount());
+ break;
// Soul Siphon
case 4992:
case 4993:
@@ -10056,77 +8639,12 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage
AddPct(DoneTotalMod, modPercent);
break;
}
- case 6916: // Death's Embrace
- case 6925:
- case 6927:
- if (HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, spellProto, this))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
case 5481: // Starfire Bonus
{
if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x200002, 0, 0))
AddPct(DoneTotalMod, (*i)->GetAmount());
break;
}
- // Tundra Stalker
- // Merciless Combat
- case 7277:
- {
- // Merciless Combat
- if ((*i)->GetSpellInfo()->SpellIconID == 2656)
- {
- if (!victim->HealthAbovePct(35))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- }
- // Tundra Stalker
- else
- {
- // Frost Fever (target debuff)
- if (victim->HasAura(55095))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
- }
- break;
- }
- // Rage of Rivendare
- case 7293:
- {
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0x02000000, 0))
- AddPct(DoneTotalMod, (*i)->GetSpellInfo()->GetRank() * 2.0f);
- break;
- }
- // Twisted Faith
- case 7377:
- {
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetGUID()))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
- }
- // Marked for Death
- case 7598:
- case 7599:
- case 7600:
- case 7601:
- case 7602:
- {
- if (victim->GetAuraEffect(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, 0x400, 0, 0))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
- }
- // Dirty Deeds
- case 6427:
- case 6428:
- case 6579:
- case 6580:
- {
- if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
- {
- // effect 0 has expected value but in negative state
- int32 bonus = -(*i)->GetBase()->GetEffect(0)->GetAmount();
- AddPct(DoneTotalMod, bonus);
- }
- break;
- }
}
}
@@ -10136,89 +8654,35 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage
case SPELLFAMILY_MAGE:
// Ice Lance
if (spellProto->SpellIconID == 186)
- {
if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
- {
- // Glyph of Ice Lance
- if (owner->HasAura(56377) && victim->getLevel() > owner->getLevel())
- DoneTotalMod *= 4.0f;
- else
- DoneTotalMod *= 3.0f;
- }
- }
+ DoneTotalMod *= 2.0f;
// Torment the weak
- if (spellProto->SpellFamilyFlags[0] & 0x20600021 || spellProto->SpellFamilyFlags[1] & 0x9000)
+ if (spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_ARCANE)
+ {
if (victim->HasAuraWithMechanic((1<<MECHANIC_SNARE)|(1<<MECHANIC_SLOW_ATTACK)))
{
AuraEffectList const& mDumyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
for (AuraEffectList::const_iterator i = mDumyAuras.begin(); i != mDumyAuras.end(); ++i)
- if ((*i)->GetSpellInfo()->SpellIconID == 3263)
+ {
+ if ((*i)->GetSpellInfo()->SpellIconID == 2215)
{
AddPct(DoneTotalMod, (*i)->GetAmount());
break;
}
+ }
}
+ }
break;
case SPELLFAMILY_PRIEST:
- // Mind Flay
- if (spellProto->SpellFamilyFlags[0] & 0x800000)
- {
- // Glyph of Shadow Word: Pain
- if (AuraEffect* aurEff = GetAuraEffect(55687, 0))
- // Increase Mind Flay damage if Shadow Word: Pain present on target
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetGUID()))
- AddPct(DoneTotalMod, aurEff->GetAmount());
-
- // Twisted Faith - Mind Flay part
- if (AuraEffect* aurEff = GetAuraEffect(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS, SPELLFAMILY_PRIEST, 2848, 1))
- // Increase Mind Flay damage if Shadow Word: Pain present on target
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetGUID()))
- AddPct(DoneTotalMod, aurEff->GetAmount());
- }
// Smite
- else if (spellProto->SpellFamilyFlags[0] & 0x80)
+ if (spellProto->SpellFamilyFlags[0] & 0x80)
{
// Glyph of Smite
if (AuraEffect* aurEff = GetAuraEffect(55692, 0))
if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x100000, 0, 0, GetGUID()))
AddPct(DoneTotalMod, aurEff->GetAmount());
}
- // Shadow Word: Death
- else if (spellProto->SpellFamilyFlags[1] & 0x2)
- {
- // Glyph of Shadow Word: Death
- if (AuraEffect* aurEff = GetAuraEffect(55682, 1))
- if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
- AddPct(DoneTotalMod, aurEff->GetAmount());
- }
- break;
- case SPELLFAMILY_PALADIN:
- // Judgement of Vengeance/Judgement of Corruption
- if ((spellProto->SpellFamilyFlags[1] & 0x400000) && spellProto->SpellIconID == 2292)
- {
- // Get stack of Holy Vengeance/Blood Corruption on the target added by caster
- uint32 stacks = 0;
- Unit::AuraEffectList const& auras = victim->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE);
- for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
- if (((*itr)->GetId() == 31803 || (*itr)->GetId() == 53742) && (*itr)->GetCasterGUID() == GetGUID())
- {
- stacks = (*itr)->GetBase()->GetStackAmount();
- break;
- }
- // + 10% for each application of Holy Vengeance/Blood Corruption on the target
- if (stacks)
- AddPct(DoneTotalMod, 10 * stacks);
- }
- break;
- case SPELLFAMILY_DRUID:
- // Thorns
- if (spellProto->SpellFamilyFlags[0] & 0x100)
- {
- // Brambles
- if (AuraEffect* aurEff = GetAuraEffectOfRankedSpell(16836, 0))
- AddPct(DoneTotalMod, aurEff->GetAmount());
- }
break;
case SPELLFAMILY_WARLOCK:
// Fire and Brimstone
@@ -10233,33 +8697,22 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage
break;
}
}
- // Shadow Bite (15% increase from each dot)
+
+ // Shadow Bite (30% increase from each dot)
if (spellProto->SpellFamilyFlags[1] & 0x00400000 && IsPet())
if (uint8 count = victim->GetDoTsByCaster(GetOwnerGUID()))
- AddPct(DoneTotalMod, 15 * count);
+ AddPct(DoneTotalMod, 30 * count);
- // Drain Soul - If the target is at or below 25% health, Drain Soul causes four times the normal damage
- if (spellProto->SpellFamilyFlags[0] & 0x00004000 && !victim->HealthAbovePct(25))
- DoneTotalMod *= 4;
- break;
- case SPELLFAMILY_HUNTER:
- // Steady Shot
- if (spellProto->SpellFamilyFlags[1] & 0x1)
- if (AuraEffect* aurEff = GetAuraEffect(56826, 0)) // Glyph of Steady Shot
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_HUNTER, 0x00004000, 0, 0, GetGUID()))
- AddPct(DoneTotalMod, aurEff->GetAmount());
+ // Drain Soul - increased damage for targets under 25 % HP
+ if (spellProto->SpellFamilyFlags[0] & 0x00004000)
+ if (HasAura(100001))
+ DoneTotalMod *= 2;
break;
case SPELLFAMILY_DEATHKNIGHT:
- // Improved Icy Touch
- if (spellProto->SpellFamilyFlags[0] & 0x2)
- if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2721, 0))
- AddPct(DoneTotalMod, aurEff->GetAmount());
-
- // Glacier Rot
- if (spellProto->SpellFamilyFlags[0] & 0x2 || spellProto->SpellFamilyFlags[1] & 0x6)
- if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0))
- if (victim->GetDiseasesByCaster(owner->GetGUID()) > 0)
- AddPct(DoneTotalMod, aurEff->GetAmount());
+ // Sigil of the Vengeful Heart
+ if (spellProto->SpellFamilyFlags[0] & 0x2000)
+ if (AuraEffect* aurEff = GetAuraEffect(64962, EFFECT_1))
+ DoneTotalMod += aurEff->GetAmount();
break;
}
@@ -10293,13 +8746,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
// Cheat Death
case 2109:
if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
- {
- // Patch 2.4.3: The resilience required to reach the 90% damage reduction cap
- // is 22.5% critical strike damage reduction, or 444 resilience.
- // To calculate for 90%, we multiply the 100% by 4 (22.5% * 4 = 90%)
- float mod = -1.0f * GetMeleeCritDamageReduction(400);
- AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount())));
- }
+ AddPct(TakenTotalMod, (*i)->GetAmount());
break;
}
}
@@ -10314,14 +8761,10 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
TakenTotalCasterMod += (float((*i)->GetAmount()));
}
- // from positive and negative SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
- // multiplicative bonus, for example Dispersion + Shadowform (0.10*0.85=0.085)
- TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, spellProto->GetSchoolMask());
-
// From caster spells
AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
- if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectedOnSpell(spellProto))
+ if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectingSpell(spellProto))
AddPct(TakenTotalMod, (*i)->GetAmount());
int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask());
@@ -10388,6 +8831,10 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
// Base value
DoneAdvertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus();
+ // Check if we are ever using mana - PaperDollFrame.lua
+ if (GetPowerIndex(POWER_MANA) != MAX_POWERS)
+ DoneAdvertisedBenefit += std::max(0, int32(GetStat(STAT_INTELLECT)) - 10); // spellpower from intellect
+
// Damage bonus from stats
AuraEffectList const& mDamageDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT);
for (AuraEffectList::const_iterator i = mDamageDoneOfStatPercent.begin(); i != mDamageDoneOfStatPercent.end(); ++i)
@@ -10475,29 +8922,21 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto
crit_chance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE, schoolMask);
// Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE
crit_chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE);
- ApplyResilience(victim, &crit_chance, NULL, false, CR_CRIT_TAKEN_SPELL);
}
// scripted (increase crit chance ... against ... target by x%
AuraEffectList const& mOverrideClassScript = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
- if (!((*i)->IsAffectedOnSpell(spellProto)))
+ if (!((*i)->IsAffectingSpell(spellProto)))
continue;
switch ((*i)->GetMiscValue())
{
- case 911: // Shatter (Rank 1)
+ // Shatter
+ case 911:
if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
- crit_chance += 17;
+ AddPct(crit_chance, (*i)->GetAmount()*20);
break;
- case 910: // Shatter (Rank 2)
- if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
- crit_chance += 34;
- break;
- case 849: // Shatter (Rank 3)
- if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
- crit_chance += 50;
- break;
case 7917: // Glyph of Shadowburn
if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
crit_chance+=(*i)->GetAmount();
@@ -10592,16 +9031,6 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto
break;
}
break;
- case SPELLFAMILY_WARRIOR:
- // Victory Rush
- if (spellProto->SpellFamilyFlags[1] & 0x100)
- {
- // Glyph of Victory Rush
- if (AuraEffect const* aurEff = GetAuraEffect(58382, 0))
- crit_chance += aurEff->GetAmount();
- break;
- }
- break;
}
}
/// Intentional fallback. Calculate critical strike chance for both Ranged and Melee spells
@@ -10622,10 +9051,15 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance);
+ AuraEffectList const& critAuras = victim->GetAuraEffectsByType(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER);
+ for (AuraEffectList::const_iterator i = critAuras.begin(); i != critAuras.end(); ++i)
+ if ((*i)->GetCasterGUID() == GetGUID() && (*i)->IsAffectingSpell(spellProto))
+ crit_chance += (*i)->GetAmount();
+
return crit_chance > 0.0f ? crit_chance : 0.0f;
}
-uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim)
+uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* /*victim*/)
{
// Calculate critical bonus
int32 crit_bonus = damage;
@@ -10645,9 +9079,6 @@ uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage
crit_mod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellProto->GetSchoolMask()) - 1.0f) * 100;
- if (victim)
- crit_mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, victim->GetCreatureTypeMask());
-
if (crit_bonus != 0)
AddPct(crit_bonus, crit_mod);
@@ -10665,30 +9096,12 @@ uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage
return crit_bonus;
}
-uint32 Unit::SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim)
+uint32 Unit::SpellCriticalHealingBonus(SpellInfo const* /*spellProto*/, uint32 damage, Unit* /*victim*/)
{
// 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 (victim)
- {
- uint32 creatureTypeMask = victim->GetCreatureTypeMask();
- crit_bonus = int32(crit_bonus * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask));
- }
+ int32 crit_bonus = damage;
- if (crit_bonus > 0)
- damage += crit_bonus;
+ damage += crit_bonus;
damage = int32(float(damage) * GetTotalAuraMultiplier(SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT));
@@ -10713,7 +9126,7 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(spellProto))
+ if (!(*i)->IsAffectingSpell(spellProto))
continue;
switch ((*i)->GetMiscValue())
{
@@ -10722,6 +9135,31 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
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)->GetAmount();
break;
+ case 21: // Test of Faith
+ case 6935:
+ case 6918:
+ if (victim->HealthBelowPct(50))
+ AddPct(DoneTotal, (*i)->GetAmount());
+ break;
+ case 8477: // Nourish Heal Boost
+ {
+ int32 stepPercent = (*i)->GetAmount();
+ int32 modPercent = 0;
+ AuraApplicationMap const& victimAuras = victim->GetAppliedAuras();
+ for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
+ {
+ Aura const* aura = itr->second->GetBase();
+ if (aura->GetCasterGUID() != GetGUID())
+ continue;
+ SpellInfo const* m_spell = aura->GetSpellInfo();
+ if (m_spell->SpellFamilyName != SPELLFAMILY_DRUID ||
+ !(m_spell->SpellFamilyFlags[1] & 0x00000010 || m_spell->SpellFamilyFlags[0] & 0x50))
+ continue;
+ modPercent += stepPercent * aura->GetStackAmount();
+ }
+ AddPct(DoneTotal, modPercent);
+ break;
+ }
default:
break;
}
@@ -10773,10 +9211,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
coeff /= 100.0f;
}
- // Earthliving - 0.45% of normal hot coeff
- if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[1] & 0x80000)
- factorMod *= 0.45f;
-
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
}
@@ -10825,8 +9259,9 @@ float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const
AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(spellProto))
+ if (!(*i)->IsAffectingSpell(spellProto))
continue;
+
switch ((*i)->GetMiscValue())
{
case 21: // Test of Faith
@@ -10906,18 +9341,6 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
TakenTotalMod *= 1.2f;
}
- if (damagetype == DOT)
- {
- // Healing over time taken percent
- float minval_hot = float(GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT));
- if (minval_hot)
- AddPct(TakenTotalMod, minval_hot);
-
- float maxval_hot = float(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT));
- if (maxval_hot)
- AddPct(TakenTotalMod, maxval_hot);
- }
-
// Check for table values
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
float coeff = 0;
@@ -10948,16 +9371,12 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
coeff /= 100.0f;
}
- // Earthliving - 0.45% of normal hot coeff
- if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[1] & 0x80000)
- factorMod *= 0.45f;
-
TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
}
AuraEffectList const& mHealingGet= GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_RECEIVED);
for (AuraEffectList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i)
- if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectedOnSpell(spellProto))
+ if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectingSpell(spellProto))
AddPct(TakenTotalMod, (*i)->GetAmount());
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -10994,6 +9413,10 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const
// Base value
advertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus();
+ // Check if we are ever using mana - PaperDollFrame.lua
+ if (GetPowerIndex(POWER_MANA) != MAX_POWERS)
+ advertisedBenefit += std::max(0, int32(GetStat(STAT_INTELLECT)) - 10); // spellpower from intellect
+
// Healing bonus from stats
AuraEffectList const& mHealingDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT);
for (AuraEffectList::const_iterator i = mHealingDoneOfStatPercent.begin(); i != mHealingDoneOfStatPercent.end(); ++i)
@@ -11260,80 +9683,13 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue())))
AddPct(DoneTotalMod, (*i)->GetAmount());
- // done scripted mod (take it from owner)
- Unit* owner = GetOwner() ? GetOwner() : this;
- AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
- {
- if (!(*i)->IsAffectedOnSpell(spellProto))
- continue;
-
- switch ((*i)->GetMiscValue())
- {
- // Tundra Stalker
- // Merciless Combat
- case 7277:
- {
- // Merciless Combat
- if ((*i)->GetSpellInfo()->SpellIconID == 2656)
- {
- if (!victim->HealthAbovePct(35))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- }
- // Tundra Stalker
- else
- {
- // Frost Fever (target debuff)
- if (victim->HasAura(55095))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- }
- break;
- }
- // Rage of Rivendare
- case 7293:
- {
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0x02000000, 0))
- AddPct(DoneTotalMod, (*i)->GetSpellInfo()->GetRank() * 2.0f);
- break;
- }
- // Marked for Death
- case 7598:
- case 7599:
- case 7600:
- case 7601:
- case 7602:
- {
- if (victim->GetAuraEffect(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, 0x400, 0, 0))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- break;
- }
- // Dirty Deeds
- case 6427:
- case 6428:
- {
- if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
- {
- // effect 0 has expected value but in negative state
- int32 bonus = -(*i)->GetBase()->GetEffect(0)->GetAmount();
- AddPct(DoneTotalMod, bonus);
- }
- break;
- }
- }
- }
-
- // Custom scripted damage
+ // Add SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC percent bonus
if (spellProto)
- switch (spellProto->SpellFamilyName)
- {
- case SPELLFAMILY_DEATHKNIGHT:
- // Glacier Rot
- if (spellProto->SpellFamilyFlags[0] & 0x2 || spellProto->SpellFamilyFlags[1] & 0x6)
- if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0))
- if (victim->GetDiseasesByCaster(owner->GetGUID()) > 0)
- AddPct(DoneTotalMod, aurEff->GetAmount());
- break;
- }
+ AddPct(DoneTotalMod, GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC, spellProto->Mechanic));
+
+ // done scripted mod (take it from owner)
+ // Unit* owner = GetOwner() ? GetOwner() : this;
+ // AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
float tmpDamage = float(int32(pdamage) + DoneFlatBenefit) * DoneTotalMod;
@@ -11386,7 +9742,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
// From caster spells
AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
- if ((*i)->GetCasterGUID() == attacker->GetGUID() && (*i)->IsAffectedOnSpell(spellProto))
+ if ((*i)->GetCasterGUID() == attacker->GetGUID() && (*i)->IsAffectingSpell(spellProto))
AddPct(TakenTotalMod, (*i)->GetAmount());
// Mod damage from spell mechanic
@@ -11415,11 +9771,11 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
case 2109:
if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
{
- // Patch 2.4.3: The resilience required to reach the 90% damage reduction cap
- // is 22.5% critical strike damage reduction, or 444 resilience.
- // To calculate for 90%, we multiply the 100% by 4 (22.5% * 4 = 90%)
- float mod = -1.0f * GetMeleeCritDamageReduction(400);
- AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount())));
+ if (Player* player = ToPlayer())
+ {
+ float mod = player->GetRatingBonusValue(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN) * (-8.0f);
+ AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount())));
+ }
}
break;
}
@@ -11568,8 +9924,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
data << uint32(VehicleId);
SendMessageToSet(&data, true);
- data.Initialize(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
- player->GetSession()->SendPacket(&data);
+ player->SendOnCancelExpectedVehicleRideAura();
// mounts can also have accessories
GetVehicleKit()->InstallAllAccessories(false);
@@ -11588,11 +9943,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
player->UnsummonPetTemporaryIfAny();
}
- WorldPacket data(SMSG_MOVE_SET_COLLISION_HGT, GetPackGUID().size() + 4 + 4);
- data.append(GetPackGUID());
- data << uint32(sWorld->GetGameTime()); // Packet counter
- data << player->GetCollisionHeight(true);
- player->GetSession()->SendPacket(&data);
+ player->SendMovementSetCollisionHeight(player->GetCollisionHeight(true));
}
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT);
@@ -11607,13 +9958,7 @@ void Unit::Dismount()
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT);
if (Player* thisPlayer = ToPlayer())
- {
- WorldPacket data(SMSG_MOVE_SET_COLLISION_HGT, GetPackGUID().size() + 4 + 4);
- data.append(GetPackGUID());
- data << uint32(sWorld->GetGameTime()); // Packet counter
- data << thisPlayer->GetCollisionHeight(false);
- thisPlayer->GetSession()->SendPacket(&data);
- }
+ thisPlayer->SendMovementSetCollisionHeight(thisPlayer->GetCollisionHeight(false));
WorldPacket data(SMSG_DISMOUNT, 8);
data.appendPackGUID(GetGUID());
@@ -11648,6 +9993,64 @@ void Unit::Dismount()
}
}
+MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const
+{
+ if (!mountType)
+ return NULL;
+
+ MountTypeEntry const* mountTypeEntry = sMountTypeStore.LookupEntry(mountType);
+ if (!mountTypeEntry)
+ return NULL;
+
+ uint32 zoneId, areaId;
+ GetZoneAndAreaId(zoneId, areaId);
+ uint32 ridingSkill = 5000;
+ if (GetTypeId() == TYPEID_PLAYER)
+ ridingSkill = ToPlayer()->GetSkillValue(SKILL_RIDING);
+
+ for (uint32 i = MAX_MOUNT_CAPABILITIES; i > 0; --i)
+ {
+ MountCapabilityEntry const* mountCapability = sMountCapabilityStore.LookupEntry(mountTypeEntry->MountCapability[i - 1]);
+ if (!mountCapability)
+ continue;
+
+ if (ridingSkill < mountCapability->RequiredRidingSkill)
+ continue;
+
+ if (HasExtraUnitMovementFlag(MOVEMENTFLAG2_FULL_SPEED_PITCHING))
+ {
+ if (!(mountCapability->Flags & MOUNT_FLAG_CAN_PITCH))
+ continue;
+ }
+ else if (HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING))
+ {
+ if (!(mountCapability->Flags & MOUNT_FLAG_CAN_SWIM))
+ continue;
+ }
+ else if (!(mountCapability->Flags & 0x1)) // unknown flags, checked in 4.2.2 14545 client
+ {
+ if (!(mountCapability->Flags & 0x2))
+ continue;
+ }
+
+ if (mountCapability->RequiredMap != -1 && int32(GetMapId()) != mountCapability->RequiredMap)
+ continue;
+
+ if (mountCapability->RequiredArea && (mountCapability->RequiredArea != zoneId && mountCapability->RequiredArea != areaId))
+ continue;
+
+ if (mountCapability->RequiredAura && !HasAura(mountCapability->RequiredAura))
+ continue;
+
+ if (mountCapability->RequiredSpell && (GetTypeId() != TYPEID_PLAYER || !ToPlayer()->HasSpell(mountCapability->RequiredSpell)))
+ continue;
+
+ return mountCapability;
+ }
+
+ return NULL;
+}
+
bool Unit::IsServiceProvider() const
{
return HasFlag(UNIT_NPC_FLAGS,
@@ -11851,13 +10254,17 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
if (playerAttacker->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_UBER))
return false;
}
+
// check flags
if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_TAXI_FLIGHT | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_UNK_16)
|| (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC))
- || (!target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC))
- || (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC))
+ || (!target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)))
+ return false;
+
+ if ((!bySpell || !(bySpell->AttributesEx8 & SPELL_ATTR8_ATTACK_IGNORE_IMMUNE_TO_PC_FLAG))
+ && (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC))
// check if this is a world trigger cast - GOs are using world triggers to cast their spells, so we need to ignore their immunity flag here, this is a temp workaround, needs removal when go cast is implemented properly
- || (GetEntry() != WORLD_TRIGGER && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)))
+ && GetEntry() != WORLD_TRIGGER)
return false;
// CvC case - can attack each other only when one of them is hostile
@@ -12084,16 +10491,16 @@ int32 Unit::ModifyPower(Powers power, int32 dVal)
if (dVal == 0)
return 0;
- int32 curPower = (int32)GetPower(power);
+ int32 curPower = GetPower(power);
int32 val = dVal + curPower;
- if (val <= 0)
+ if (val <= GetMinPower(power))
{
- SetPower(power, 0);
+ SetPower(power, GetMinPower(power));
return -curPower;
}
- int32 maxPower = (int32)GetMaxPower(power);
+ int32 maxPower = GetMaxPower(power);
if (val < maxPower)
{
@@ -12115,7 +10522,7 @@ int32 Unit::ModifyPowerPct(Powers power, float pct, bool apply)
float amount = (float)GetMaxPower(power);
ApplyPercentModFloatVar(amount, pct, apply);
- return ModifyPower(power, (int32)amount - (int32)GetMaxPower(power));
+ return ModifyPower(power, (int32)amount - GetMaxPower(power));
}
uint32 Unit::GetAttackTime(WeaponAttackType att) const
@@ -12328,100 +10735,35 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
propagateSpeedChange();
- WorldPacket data;
- if (!forced)
+ static Opcodes const moveTypeToOpcode[MAX_MOVE_TYPE][3] =
+ {
+ {SMSG_SPLINE_MOVE_SET_WALK_SPEED, SMSG_MOVE_SET_WALK_SPEED, SMSG_MOVE_UPDATE_WALK_SPEED },
+ {SMSG_SPLINE_MOVE_SET_RUN_SPEED, SMSG_MOVE_SET_RUN_SPEED, SMSG_MOVE_UPDATE_RUN_SPEED },
+ {SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED, SMSG_MOVE_SET_RUN_BACK_SPEED, SMSG_MOVE_UPDATE_RUN_BACK_SPEED },
+ {SMSG_SPLINE_MOVE_SET_SWIM_SPEED, SMSG_MOVE_SET_SWIM_SPEED, SMSG_MOVE_UPDATE_SWIM_SPEED },
+ {SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED, SMSG_MOVE_SET_SWIM_BACK_SPEED, SMSG_MOVE_UPDATE_SWIM_BACK_SPEED },
+ {SMSG_SPLINE_MOVE_SET_TURN_RATE, SMSG_MOVE_SET_TURN_RATE, SMSG_MOVE_UPDATE_TURN_RATE },
+ {SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED, SMSG_MOVE_SET_FLIGHT_SPEED, SMSG_MOVE_UPDATE_FLIGHT_SPEED },
+ {SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED, SMSG_MOVE_SET_FLIGHT_BACK_SPEED, SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED},
+ {SMSG_SPLINE_MOVE_SET_PITCH_RATE, SMSG_MOVE_SET_PITCH_RATE, SMSG_MOVE_UPDATE_PITCH_RATE },
+ };
+
+ if (GetTypeId() == TYPEID_PLAYER)
{
- switch (mtype)
- {
- case MOVE_WALK:
- 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+2+4+4+4+4+4+4+4);
- break;
- case MOVE_RUN_BACK:
- data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_SWIM:
- data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_SWIM_BACK:
- data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_TURN_RATE:
- 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+2+4+4+4+4+4+4+4);
- break;
- case MOVE_FLIGHT_BACK:
- data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_PITCH_RATE:
- data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8+4+2+4+4+4+4+4+4+4);
- break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype);
- return;
- }
+ // register forced speed changes for WorldSession::HandleForceSpeedChangeAck
+ // and do it only for real sent packets and use run for run/mounted as client expected
+ ++ToPlayer()->m_forced_speed_changes[mtype];
- BuildMovementPacket(&data);
- data << float(GetSpeed(mtype));
- SendMessageToSet(&data, true);
+ if (!IsInCombat())
+ if (Pet* pet = ToPlayer()->GetPet())
+ pet->SetSpeed(mtype, m_speed_rate[mtype], forced);
}
- else
- {
- 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
- ++ToPlayer()->m_forced_speed_changes[mtype];
- if (!IsInCombat())
- if (Pet* pet = ToPlayer()->GetPet())
- pet->SetSpeed(mtype, m_speed_rate[mtype], forced);
- }
+ static MovementStatusElements const speedVal = MSEExtraFloat;
+ Movement::ExtraMovementStatusElement extra(&speedVal);
+ extra.Data.floatData = GetSpeed(mtype);
- switch (mtype)
- {
- case MOVE_WALK:
- data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16);
- break;
- case MOVE_RUN:
- data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17);
- break;
- case MOVE_RUN_BACK:
- data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16);
- break;
- case MOVE_SWIM:
- data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16);
- break;
- case MOVE_SWIM_BACK:
- data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16);
- break;
- case MOVE_TURN_RATE:
- data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16);
- break;
- case MOVE_FLIGHT:
- data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16);
- break;
- 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:
- TC_LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype);
- return;
- }
- data.append(GetPackGUID());
- data << (uint32)0; // moveEvent, NUM_PMOVE_EVTS = 0x39
- if (mtype == MOVE_RUN)
- data << uint8(0); // new 2.1.0
- data << float(GetSpeed(mtype));
- SendMessageToSet(&data, true);
- }
+ Movement::PacketSender(this, moveTypeToOpcode[mtype][0], moveTypeToOpcode[mtype][1], moveTypeToOpcode[mtype][2], &extra).Send();
}
void Unit::setDeathState(DeathState s)
@@ -12868,20 +11210,6 @@ int32 Unit::ModSpellDuration(SpellInfo const* spellProto, Unit const* target, in
duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
}
break;
- case SPELLFAMILY_PALADIN:
- if ((spellProto->SpellFamilyFlags[0] & 0x00000002) && spellProto->SpellIconID == 298)
- {
- // Glyph of Blessing of Might
- if (AuraEffect* aurEff = GetAuraEffect(57958, 0))
- duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
- }
- else if ((spellProto->SpellFamilyFlags[0] & 0x00010000) && spellProto->SpellIconID == 306)
- {
- // Glyph of Blessing of Wisdom
- if (AuraEffect* aurEff = GetAuraEffect(57979, 0))
- duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
- }
- break;
}
}
return std::max(duration, 0);
@@ -13054,7 +11382,7 @@ uint32 Unit::GetCreatureType() const
if (GetTypeId() == TYPEID_PLAYER)
{
ShapeshiftForm form = GetShapeshiftForm();
- SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(form);
+ SpellShapeshiftFormEntry const* ssEntry = sSpellShapeshiftFormStore.LookupEntry(form);
if (ssEntry && ssEntry->creatureType > 0)
return ssEntry->creatureType;
else
@@ -13078,14 +11406,14 @@ void Unit::SetShapeshiftForm(ShapeshiftForm form)
bool Unit::IsInFeralForm() const
{
ShapeshiftForm form = GetShapeshiftForm();
- return form == FORM_CAT || form == FORM_BEAR || form == FORM_DIREBEAR;
+ return form == FORM_CAT || form == FORM_BEAR;
}
bool Unit::IsInDisallowedMountForm() const
{
if (ShapeshiftForm form = GetShapeshiftForm())
{
- SpellShapeshiftEntry const* shapeshift = sSpellShapeshiftStore.LookupEntry(form);
+ SpellShapeshiftFormEntry const* shapeshift = sSpellShapeshiftFormStore.LookupEntry(form);
if (!shapeshift)
return true;
@@ -13160,7 +11488,6 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f
case UNIT_MOD_RAGE:
case UNIT_MOD_FOCUS:
case UNIT_MOD_ENERGY:
- case UNIT_MOD_HAPPINESS:
case UNIT_MOD_RUNE:
case UNIT_MOD_RUNIC_POWER: UpdateMaxPower(GetPowerTypeByAuraGroup(unitMod)); break;
@@ -13280,8 +11607,7 @@ Powers Unit::GetPowerTypeByAuraGroup(UnitMods unitMod) const
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_RUNE: return POWER_RUNES;
case UNIT_MOD_RUNIC_POWER: return POWER_RUNIC_POWER;
default:
case UNIT_MOD_MANA: return POWER_MANA;
@@ -13292,14 +11618,14 @@ float Unit::GetTotalAttackPowerValue(WeaponAttackType attType) const
{
if (attType == RANGED_ATTACK)
{
- int32 ap = GetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER) + GetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS);
+ int32 ap = GetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER);
if (ap < 0)
return 0.0f;
return ap * (1.0f + GetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER));
}
else
{
- int32 ap = GetInt32Value(UNIT_FIELD_ATTACK_POWER) + GetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS);
+ int32 ap = GetInt32Value(UNIT_FIELD_ATTACK_POWER);
if (ap < 0)
return 0.0f;
return ap * (1.0f + GetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER));
@@ -13394,22 +11720,45 @@ void Unit::SetMaxHealth(uint32 val)
SetHealth(val);
}
-void Unit::SetPower(Powers power, uint32 val)
+int32 Unit::GetPower(Powers power) const
{
- if (GetPower(power) == val)
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS)
+ return 0;
+
+ return GetUInt32Value(UNIT_FIELD_POWER1 + powerIndex);
+}
+
+int32 Unit::GetMaxPower(Powers power) const
+{
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS)
+ return 0;
+
+ return GetInt32Value(UNIT_FIELD_MAXPOWER1 + powerIndex);
+}
+
+void Unit::SetPower(Powers power, int32 val)
+{
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS)
return;
- uint32 maxPower = GetMaxPower(power);
+ int32 maxPower = int32(GetMaxPower(power));
if (maxPower < val)
val = maxPower;
- SetStatInt32Value(UNIT_FIELD_POWER1 + power, val);
+ SetInt32Value(UNIT_FIELD_POWER1 + powerIndex, val);
- WorldPacket data(SMSG_POWER_UPDATE);
- data.append(GetPackGUID());
- data << uint8(power);
- data << uint32(val);
- SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER);
+ if (IsInWorld())
+ {
+ WorldPacket data(SMSG_POWER_UPDATE, 8 + 4 + 1 + 4);
+ data.append(GetPackGUID());
+ data << uint32(1); //power count
+ data << uint8(powerIndex);
+ data << int32(val);
+ SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER);
+ }
// group update
if (Player* player = ToPlayer())
@@ -13425,17 +11774,17 @@ void Unit::SetPower(Powers power, uint32 val)
if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
}
-
- // Update the pet's character sheet with happiness damage bonus
- if (pet->getPetType() == HUNTER_PET && power == POWER_HAPPINESS)
- pet->UpdateDamagePhysical(BASE_ATTACK);
}
}
-void Unit::SetMaxPower(Powers power, uint32 val)
+void Unit::SetMaxPower(Powers power, int32 val)
{
- uint32 cur_power = GetPower(power);
- SetStatInt32Value(UNIT_FIELD_MAXPOWER1 + power, val);
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS)
+ return;
+
+ int32 cur_power = GetPower(power);
+ SetInt32Value(UNIT_FIELD_MAXPOWER1 + powerIndex, val);
// group update
if (GetTypeId() == TYPEID_PLAYER)
@@ -13457,19 +11806,45 @@ void Unit::SetMaxPower(Powers power, uint32 val)
SetPower(power, val);
}
-uint32 Unit::GetCreatePowers(Powers power) const
+uint32 Unit::GetPowerIndex(uint32 powerType) const
+{
+ /// This is here because hunter pets are of the warrior class.
+ /// With the current implementation, the core only gives them
+ /// POWER_RAGE, so we enforce the class to hunter so that they
+ /// effectively get focus power.
+ uint32 classId = getClass();
+ if (ToPet() && ToPet()->getPetType() == HUNTER_PET)
+ classId = CLASS_HUNTER;
+
+ return GetPowerIndexByClass(powerType, classId);
+}
+
+int32 Unit::GetCreatePowers(Powers power) const
{
- // Only hunter pets have POWER_FOCUS and POWER_HAPPINESS
switch (power)
{
- case POWER_MANA: return GetCreateMana();
- case POWER_RAGE: return 1000;
- 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;
- case POWER_RUNE: return 0;
- case POWER_HEALTH: return 0;
+ case POWER_MANA:
+ return GetCreateMana();
+ case POWER_RAGE:
+ return 1000;
+ case POWER_FOCUS:
+ if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_HUNTER)
+ return 100;
+ return (GetTypeId() == TYPEID_PLAYER || !((Creature const*)this)->IsPet() || ((Pet const*)this)->getPetType() != HUNTER_PET ? 0 : 100);
+ case POWER_ENERGY:
+ return 100;
+ case POWER_RUNIC_POWER:
+ return 1000;
+ case POWER_RUNES:
+ return 0;
+ case POWER_SOUL_SHARDS:
+ return 3;
+ case POWER_ECLIPSE:
+ return 100;
+ case POWER_HOLY_POWER:
+ return 3;
+ case POWER_HEALTH:
+ return 0;
default:
break;
}
@@ -13890,6 +12265,7 @@ bool InitTriggerAuraData()
isNonTriggerAura[i] = false;
isAlwaysTriggeredAura[i] = false;
}
+ isTriggerAura[SPELL_AURA_PROC_ON_POWER_AMOUNT] = true;
isTriggerAura[SPELL_AURA_DUMMY] = true;
isTriggerAura[SPELL_AURA_MOD_CONFUSE] = true;
isTriggerAura[SPELL_AURA_MOD_THREAT] = true;
@@ -13914,11 +12290,13 @@ bool InitTriggerAuraData()
isTriggerAura[SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN] = true;
isTriggerAura[SPELL_AURA_SPELL_MAGNET] = true;
isTriggerAura[SPELL_AURA_MOD_ATTACK_POWER] = true;
+ isTriggerAura[SPELL_AURA_MOD_POWER_REGEN_PERCENT] = true;
isTriggerAura[SPELL_AURA_ADD_CASTER_HIT_TRIGGER] = true;
isTriggerAura[SPELL_AURA_OVERRIDE_CLASS_SCRIPTS] = true;
isTriggerAura[SPELL_AURA_MOD_MECHANIC_RESISTANCE] = true;
isTriggerAura[SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS] = true;
isTriggerAura[SPELL_AURA_MOD_MELEE_HASTE] = true;
+ isTriggerAura[SPELL_AURA_MOD_MELEE_HASTE_3] = true;
isTriggerAura[SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE] = true;
isTriggerAura[SPELL_AURA_RAID_PROC_FROM_CHARGE] = true;
isTriggerAura[SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE] = true;
@@ -13988,19 +12366,6 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
// For melee/ranged based attack need update skills and set some Aura states if victim present
if (procFlag & MELEE_BASED_TRIGGER_MASK && target)
{
- // Update skills here for players
- if (GetTypeId() == TYPEID_PLAYER)
- {
- // On melee based hit/miss/resist need update skill (for victim and attacker)
- if (procExtra & (PROC_EX_NORMAL_HIT|PROC_EX_MISS|PROC_EX_RESIST))
- {
- if (target->GetTypeId() != TYPEID_PLAYER && target->GetCreatureType() != CREATURE_TYPE_CRITTER)
- ToPlayer()->UpdateCombatSkills(target, attType, isVictim);
- }
- // Update defence if player is victim and parry/dodge/block
- else if (isVictim && procExtra & (PROC_EX_DODGE|PROC_EX_PARRY|PROC_EX_BLOCK))
- ToPlayer()->UpdateCombatSkills(target, attType, true);
- }
// If exist crit/parry/dodge/block need update aura state (for victim and attacker)
if (procExtra & (PROC_EX_CRITICAL_HIT|PROC_EX_PARRY|PROC_EX_DODGE|PROC_EX_BLOCK))
{
@@ -14181,6 +12546,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
switch (triggeredByAura->GetAuraType())
{
case SPELL_AURA_PROC_TRIGGER_SPELL:
+ case SPELL_AURA_PROC_TRIGGER_SPELL_2:
{
TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
// Don`t drop charge or add cooldown for not started trigger
@@ -14206,10 +12572,19 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
takeCharges = true;
break;
}
+ case SPELL_AURA_PROC_ON_POWER_AMOUNT:
+ {
+ TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ if (HandleAuraProcOnPowerAmount(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges = true;
+ break;
+ }
case SPELL_AURA_OBS_MOD_POWER:
case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
+ case SPELL_AURA_MOD_POWER_REGEN_PERCENT:
case SPELL_AURA_MOD_MELEE_HASTE:
+ case SPELL_AURA_MOD_MELEE_HASTE_3:
TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, isVictim ? "a victim's" : "an attacker's", triggeredByAura->GetId());
takeCharges = true;
break;
@@ -14248,7 +12623,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
}
case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
// Skip melee hits or instant cast spells
- if (procSpell && procSpell->CalcCastTime() != 0)
+ if (procSpell && procSpell->CalcCastTime(getLevel()) > 0)
takeCharges = true;
break;
case SPELL_AURA_REFLECT_SPELLS_SCHOOL:
@@ -14489,13 +12864,6 @@ void Unit::StopMoving()
init.Stop();
}
-void Unit::SendMovementFlagUpdate(bool self /* = false */)
-{
- WorldPacket data;
- BuildHeartBeatMsg(&data);
- SendMessageToSet(&data, self);
-}
-
bool Unit::IsSitState() const
{
uint8 s = getStandState();
@@ -14679,11 +13047,27 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply
{
ApplyPercentModFloatVar(m_modAttackSpeedPct[att], val, !apply);
ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att, val, !apply);
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ if (att == BASE_ATTACK)
+ ApplyPercentModFloatValue(PLAYER_FIELD_MOD_HASTE, val, !apply);
+ else if (att == RANGED_ATTACK)
+ ApplyPercentModFloatValue(PLAYER_FIELD_MOD_RANGED_HASTE, val, !apply);
+ }
}
else
{
ApplyPercentModFloatVar(m_modAttackSpeedPct[att], -val, apply);
ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att, -val, apply);
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ if (att == BASE_ATTACK)
+ ApplyPercentModFloatValue(PLAYER_FIELD_MOD_HASTE, -val, apply);
+ else if (att == RANGED_ATTACK)
+ ApplyPercentModFloatValue(PLAYER_FIELD_MOD_RANGED_HASTE, -val, apply);
+ }
}
m_attackTimer[att] = uint32(GetAttackTime(att) * m_modAttackSpeedPct[att] * remainingTimePct);
}
@@ -14691,9 +13075,15 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply
void Unit::ApplyCastTimePercentMod(float val, bool apply)
{
if (val > 0)
+ {
ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED, val, !apply);
+ ApplyPercentModFloatValue(UNIT_MOD_CAST_HASTE, val, !apply);
+ }
else
+ {
ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED, -val, apply);
+ ApplyPercentModFloatValue(UNIT_MOD_CAST_HASTE, -val, apply);
+ }
}
uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectType damagetype, uint32 CastingTime) const
@@ -14751,7 +13141,7 @@ uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectTyp
if (overTime > 0 && CastingTime > 0 && DirectDamage)
{
// mainly for DoTs which are 3500 here otherwise
- uint32 OriginalCastTime = spellProto->CalcCastTime();
+ uint32 OriginalCastTime = spellProto->CalcCastTime(getLevel());
if (OriginalCastTime > 7000) OriginalCastTime = 7000;
if (OriginalCastTime < 1500) OriginalCastTime = 1500;
// Portion to Over Time
@@ -14840,7 +13230,7 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect
DotFactor /= DotTicks;
}
- int32 CastingTime = spellInfo->IsChanneled() ? spellInfo->GetDuration() : spellInfo->CalcCastTime();
+ int32 CastingTime = spellInfo->IsChanneled() ? spellInfo->GetDuration() : spellInfo->CalcCastTime(getLevel());
// Distribute Damage over multiple effects, reduce by AoE
CastingTime = GetCastingTimeForBonus(spellInfo, damagetype, CastingTime);
@@ -14873,11 +13263,6 @@ float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized)
}
}
-bool Unit::IsUnderLastManaUseEffect() const
-{
- return getMSTimeDiff(m_lastManaUse, getMSTime()) < 5000;
-}
-
void Unit::SetContestedPvP(Player* attackedPlayer)
{
Player* player = GetCharmerOrOwnerPlayerOrPlayerItself();
@@ -15182,6 +13567,21 @@ bool Unit::HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura)
return true;
}
+void Unit::SendDurabilityLoss(Player* receiver, uint32 percent)
+{
+ WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 4);
+ data << uint32(percent);
+ receiver->GetSession()->SendPacket(&data);
+}
+
+void Unit::PlayOneShotAnimKit(uint32 id)
+{
+ WorldPacket data(SMSG_PLAY_ONE_SHOT_ANIM_KIT, 7+2);
+ data.appendPackGUID(GetGUID());
+ data << uint16(id);
+ SendMessageToSet(&data, true);
+}
+
void Unit::Kill(Unit* victim, bool durabilityLoss)
{
// Prevent killing unit twice (and giving reward from kill twice)
@@ -15290,7 +13690,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
// update get killing blow achievements, must be done before setDeathState to be able to require auras on target
// and before Spirit of Redemption as it also removes auras
if (Player* killerPlayer = GetCharmerOrOwnerPlayerOrPlayerItself())
- killerPlayer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, victim);
+ killerPlayer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, 0, victim);
// if talent known but not triggered (check priest class for speedup check)
bool spiritOfRedemption = false;
@@ -15346,11 +13746,13 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
// only if not player and not controlled by player pet. And not at BG
if ((durabilityLoss && !player && !victim->ToPlayer()->InBattleground()) || (player && sWorld->getBoolConfig(CONFIG_DURABILITY_LOSS_IN_PVP)))
{
- TC_LOG_DEBUG("entities.unit", "We are dead, losing %f percent durability", sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH));
- plrVictim->DurabilityLossAll(sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH), false);
+ double baseLoss = sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH);
+ uint32 loss = uint32(baseLoss - (baseLoss * plrVictim->GetTotalAuraMultiplier(SPELL_AURA_MOD_DURABILITY_LOSS)));
+ TC_LOG_DEBUG("entities.unit", "We are dead, losing %u percent durability", loss);
+ // Durability loss is calculated more accurately again for each item in Player::DurabilityLoss
+ plrVictim->DurabilityLossAll(baseLoss, false);
// durability lost message
- WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0);
- plrVictim->GetSession()->SendPacket(&data);
+ SendDurabilityLoss(plrVictim, loss);
}
// Call KilledUnit for creatures
if (GetTypeId() == TYPEID_UNIT && IsAIEnabled)
@@ -15534,7 +13936,8 @@ void Unit::SetControlled(bool apply, UnitState state)
if (HasAuraType(SPELL_AURA_MOD_ROOT) || GetVehicle())
return;
- SetRooted(false);
+ if (!HasUnitState(UNIT_STATE_STUNNED))
+ SetRooted(false);
break;
case UNIT_STATE_CONFUSED:
if (HasAuraType(SPELL_AURA_MOD_CONFUSE))
@@ -15576,22 +13979,13 @@ void Unit::SetStunned(bool apply)
SetTarget(0);
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
- // MOVEMENTFLAG_ROOT cannot be used in conjunction with MOVEMENTFLAG_MASK_MOVING (tested 3.3.5a)
- // this will freeze clients. That's why we remove MOVEMENTFLAG_MASK_MOVING before
- // setting MOVEMENTFLAG_ROOT
- RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING);
- AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
-
// Creature specific
if (GetTypeId() != TYPEID_PLAYER)
StopMoving();
else
SetStandState(UNIT_STAND_STATE_STAND);
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
- data.append(GetPackGUID());
- data << uint32(0);
- SendMessageToSet(&data, true);
+ SetRooted(true);
CastStop();
}
@@ -15606,66 +14000,30 @@ void Unit::SetStunned(bool apply)
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
if (!HasUnitState(UNIT_STATE_ROOT)) // prevent moving if it also has root effect
- {
- WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
- data.append(GetPackGUID());
- data << uint32(0);
- SendMessageToSet(&data, true);
-
- RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT);
- }
+ SetRooted(false);
}
}
-void Unit::SetRooted(bool apply)
+void Unit::SetRooted(bool apply, bool packetOnly /*= false*/)
{
- if (apply)
+ if (!packetOnly)
{
- if (m_rootTimes > 0) // blizzard internal check?
- m_rootTimes++;
-
- // MOVEMENTFLAG_ROOT cannot be used in conjunction with MOVEMENTFLAG_MASK_MOVING (tested 3.3.5a)
- // this will freeze clients. That's why we remove MOVEMENTFLAG_MASK_MOVING before
- // setting MOVEMENTFLAG_ROOT
- RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING);
- AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
-
- if (GetTypeId() == TYPEID_PLAYER)
+ if (apply)
{
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
- data.append(GetPackGUID());
- data << m_rootTimes;
- SendMessageToSet(&data, true);
+ // MOVEMENTFLAG_ROOT cannot be used in conjunction with MOVEMENTFLAG_MASK_MOVING (tested 3.3.5a)
+ // this will freeze clients. That's why we remove MOVEMENTFLAG_MASK_MOVING before
+ // setting MOVEMENTFLAG_ROOT
+ RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING);
+ AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
}
else
- {
- WorldPacket data(SMSG_SPLINE_MOVE_ROOT, 8);
- data.append(GetPackGUID());
- SendMessageToSet(&data, true);
- StopMoving();
- }
- }
- else
- {
- if (!HasUnitState(UNIT_STATE_STUNNED)) // prevent moving if it also has stun effect
- {
- if (GetTypeId() == TYPEID_PLAYER)
- {
- WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
- data.append(GetPackGUID());
- data << ++m_rootTimes;
- SendMessageToSet(&data, true);
- }
- else
- {
- WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8);
- data.append(GetPackGUID());
- SendMessageToSet(&data, true);
- }
-
RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT);
- }
}
+
+ if (apply)
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_ROOT, SMSG_MOVE_ROOT, SMSG_MOVE_ROOT).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_UNROOT, SMSG_MOVE_UNROOT, SMSG_MOVE_UNROOT).Send();
}
void Unit::SetFeared(bool apply)
@@ -16199,33 +14557,43 @@ void Unit::SetAuraStack(uint32 spellId, Unit* target, uint32 stack)
aura->SetStackAmount(stack);
}
-void Unit::SendPlaySpellVisual(uint32 id)
-{
- WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 8 + 4);
- data << uint64(GetGUID());
- data << uint32(id); // SpellVisualKit.dbc index
- SendMessageToSet(&data, false);
-}
-
-void Unit::SendPlaySpellImpact(uint64 guid, uint32 id)
-{
- WorldPacket data(SMSG_PLAY_SPELL_IMPACT, 8 + 4);
- data << uint64(guid); // target
- data << uint32(id); // SpellVisualKit.dbc index
- SendMessageToSet(&data, false);
+void Unit::SendPlaySpellVisualKit(uint32 id, uint32 unkParam)
+{
+ ObjectGuid guid = GetGUID();
+
+ WorldPacket data(SMSG_PLAY_SPELL_VISUAL_KIT, 4 + 4+ 4 + 8);
+ data << uint32(0);
+ data << uint32(id); // SpellVisualKit.dbc index
+ data << uint32(unkParam);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[6]);
+ data.FlushBits();
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[5]);
+ SendMessageToSet(&data, true);
}
-void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type) const
+void Unit::ApplyResilience(Unit const* victim, int32* damage) const
{
// player mounted on multi-passenger mount is also classified as vehicle
if (IsVehicle() || (victim->IsVehicle() && victim->GetTypeId() != TYPEID_PLAYER))
return;
- Unit const* source = NULL;
- if (GetTypeId() == TYPEID_PLAYER)
- source = this;
- else if (GetTypeId() == TYPEID_UNIT && GetOwner() && GetOwner()->GetTypeId() == TYPEID_PLAYER)
- source = GetOwner();
+ // Don't consider resilience if not in PvP - player or pet
+ if (!GetCharmerOrOwnerPlayerOrPlayerItself())
+ return;
Unit const* target = NULL;
if (victim->GetTypeId() == TYPEID_PLAYER)
@@ -16236,49 +14604,12 @@ void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool
if (!target)
return;
- switch (type)
- {
- case CR_CRIT_TAKEN_MELEE:
- // Crit chance reduction works against nonpets
- if (crit)
- *crit -= target->GetMeleeCritChanceReduction();
- if (source && damage)
- {
- if (isCrit)
- *damage -= target->GetMeleeCritDamageReduction(*damage);
- *damage -= target->GetMeleeDamageReduction(*damage);
- }
- break;
- case CR_CRIT_TAKEN_RANGED:
- // Crit chance reduction works against nonpets
- if (crit)
- *crit -= target->GetRangedCritChanceReduction();
- if (source && damage)
- {
- if (isCrit)
- *damage -= target->GetRangedCritDamageReduction(*damage);
- *damage -= target->GetRangedDamageReduction(*damage);
- }
- break;
- case CR_CRIT_TAKEN_SPELL:
- // Crit chance reduction works against nonpets
- if (crit)
- *crit -= target->GetSpellCritChanceReduction();
- if (source && damage)
- {
- if (isCrit)
- *damage -= target->GetSpellCritDamageReduction(*damage);
- *damage -= target->GetSpellDamageReduction(*damage);
- }
- break;
- default:
- break;
- }
+ *damage -= target->GetDamageReduction(*damage);
}
// 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* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const
+float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, uint32 spellId) const
{
//calculate miss chance
float missChance = victim->GetUnitMissChance(attType);
@@ -16286,14 +14617,6 @@ float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, i
if (!spellId && haveOffhandWeapon())
missChance += 19;
- // bonus from skills is 0.04%
- //miss_chance -= skillDiff * 0.04f;
- int32 diff = -skillDiff;
- if (victim->GetTypeId() == TYPEID_PLAYER)
- missChance += diff > 0 ? diff * 0.04f : diff * 0.02f;
- else
- missChance += diff > 10 ? 1 + (diff - 10) * 0.4f : diff * 0.1f;
-
// Calculate hit chance
float hitChance = 100.0f;
@@ -16319,67 +14642,54 @@ float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, i
return missChance;
}
-void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
+void Unit::SetInPhase(uint32 id, bool update, bool apply)
{
- if (newPhaseMask == GetPhaseMask())
+ WorldObject::SetInPhase(id, update, apply);
+
+ if (!IsInWorld())
return;
- if (IsInWorld())
+ RemoveNotOwnSingleTargetAuras(0, true);
+
+ if (GetTypeId() == TYPEID_UNIT || (!ToPlayer()->IsGameMaster() && !ToPlayer()->GetSession()->PlayerLogout()))
{
- RemoveNotOwnSingleTargetAuras(newPhaseMask); // we can lost access to caster or target
+ HostileRefManager& refManager = getHostileRefManager();
+ HostileReference* ref = refManager.getFirst();
- // modify hostile references for new phasemask, some special cases deal with hostile references themselves
- if (GetTypeId() == TYPEID_UNIT || (!ToPlayer()->IsGameMaster() && !ToPlayer()->GetSession()->PlayerLogout()))
+ while (ref)
{
- HostileRefManager& refManager = getHostileRefManager();
- HostileReference* ref = refManager.getFirst();
+ if (Unit* unit = ref->GetSource()->GetOwner())
+ if (Creature* creature = unit->ToCreature())
+ refManager.setOnlineOfflineState(creature, creature->IsInPhase(this));
- while (ref)
- {
- if (Unit* unit = ref->GetSource()->GetOwner())
- if (Creature* creature = unit->ToCreature())
- refManager.setOnlineOfflineState(creature, creature->InSamePhase(newPhaseMask));
-
- ref = ref->next();
- }
+ ref = ref->next();
+ }
- // modify threat lists for new phasemask
- if (GetTypeId() != TYPEID_PLAYER)
- {
- std::list<HostileReference*> threatList = getThreatManager().getThreatList();
- std::list<HostileReference*> offlineThreatList = getThreatManager().getOfflineThreatList();
+ // modify threat lists for new phasemask
+ if (GetTypeId() != TYPEID_PLAYER)
+ {
+ std::list<HostileReference*> threatList = getThreatManager().getThreatList();
+ std::list<HostileReference*> offlineThreatList = getThreatManager().getOfflineThreatList();
- // merge expects sorted lists
- threatList.sort();
- offlineThreatList.sort();
- threatList.merge(offlineThreatList);
+ // merge expects sorted lists
+ threatList.sort();
+ offlineThreatList.sort();
+ threatList.merge(offlineThreatList);
- for (std::list<HostileReference*>::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
- if (Unit* unit = (*itr)->getTarget())
- unit->getHostileRefManager().setOnlineOfflineState(ToCreature(), unit->InSamePhase(newPhaseMask));
- }
+ for (std::list<HostileReference*>::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
+ if (Unit* unit = (*itr)->getTarget())
+ unit->getHostileRefManager().setOnlineOfflineState(ToCreature(), unit->IsInPhase(this));
}
}
- // Phase player, dont update
- WorldObject::SetPhaseMask(newPhaseMask, false);
-
- // Phase pets and summons
- if (IsInWorld())
- {
- for (ControlList::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
- if ((*itr)->GetTypeId() == TYPEID_UNIT)
- (*itr)->SetPhaseMask(newPhaseMask, true);
-
- for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i)
- if (m_SummonSlot[i])
- if (Creature* summon = GetMap()->GetCreature(m_SummonSlot[i]))
- summon->SetPhaseMask(newPhaseMask, true);
- }
+ for (ControlList::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
+ if ((*itr)->GetTypeId() == TYPEID_UNIT)
+ (*itr)->SetInPhase(id, true, apply);
- // Update visibility after phasing pets and summons so they wont despawn
- if (update)
- UpdateObjectVisibility();
+ for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i)
+ if (m_SummonSlot[i])
+ if (Creature* summon = GetMap()->GetCreature(m_SummonSlot[i]))
+ summon->SetInPhase(id, true, apply);
}
void Unit::UpdateObjectVisibility(bool forced)
@@ -16395,6 +14705,42 @@ void Unit::UpdateObjectVisibility(bool forced)
}
}
+void Unit::SendMoveKnockBack(Player* player, float speedXY, float speedZ, float vcos, float vsin)
+{
+ ObjectGuid guid = GetGUID();
+ WorldPacket data(SMSG_MOVE_KNOCK_BACK, (1+8+4+4+4+4+4));
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[4]);
+
+ data.WriteByteSeq(guid[1]);
+
+ data << float(vsin);
+ data << uint32(0);
+
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[7]);
+
+ data << float(speedXY);
+
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[3]);
+
+ data << float(speedZ);
+ data << float(vcos);
+
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[0]);
+
+ player->GetSession()->SendPacket(&data);
+}
+
void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
{
Player* player = ToPlayer();
@@ -16409,23 +14755,12 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
}
if (!player)
- {
GetMotionMaster()->MoveKnockbackFrom(x, y, speedXY, speedZ);
- }
else
{
float vcos, vsin;
GetSinCos(x, y, vsin, vcos);
-
- WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
- data.append(GetPackGUID());
- data << uint32(0); // counter
- data << float(vcos); // x direction
- data << float(vsin); // y direction
- data << float(speedXY); // Horizontal speed
- data << float(-speedZ); // Z Movement speed (vertical)
-
- player->GetSession()->SendPacket(&data);
+ SendMoveKnockBack(player, speedXY, -speedZ, vcos, vsin);
}
}
@@ -16475,6 +14810,72 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
return 892;
}
}
+ else if (getRace() == RACE_TROLL)
+ {
+ uint8 hairColor = GetByteValue(PLAYER_BYTES, 3);
+ switch (hairColor)
+ {
+ case 0: // Red
+ case 1:
+ return 33668;
+ case 2: // Yellow
+ case 3:
+ return 33667;
+ case 4: // Blue
+ case 5:
+ case 6:
+ return 33666;
+ case 7: // Purple
+ case 10:
+ return 33665;
+ default: // original - white
+ return 33669;
+ }
+ }
+ else if (getRace() == RACE_WORGEN)
+ {
+ // Based on Skin color
+ uint8 skinColor = GetByteValue(PLAYER_BYTES, 0);
+ // Male
+ if (getGender() == GENDER_MALE)
+ {
+ switch (skinColor)
+ {
+ case 1: // Brown
+ return 33662;
+ case 2: // Black
+ case 7:
+ return 33661;
+ case 4: // yellow
+ return 33664;
+ case 3: // White
+ case 5:
+ return 33663;
+ default: // original - Gray
+ return 33660;
+ }
+ }
+ // Female
+ else
+ {
+ switch (skinColor)
+ {
+ case 5: // Brown
+ case 6:
+ return 33662;
+ case 7: // Black
+ case 8:
+ return 33661;
+ case 3: // yellow
+ case 4:
+ return 33664;
+ case 2: // White
+ return 33663;
+ default: // original - Gray
+ return 33660;
+ }
+ }
+ }
// Based on Skin color
else if (getRace() == RACE_TAUREN)
{
@@ -16509,30 +14910,32 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
}
}
// Female
- else switch (skinColor)
+ else
{
- case 10: // White
- return 29409;
- case 6: // Light Brown
- case 7:
- return 29410;
- case 4: // Brown
- case 5:
- return 29411;
- case 0: // Dark
- case 1:
- case 2:
- case 3:
- return 29412;
- default: // original - Grey
- return 8571;
+ switch (skinColor)
+ {
+ case 10: // White
+ return 29409;
+ case 6: // Light Brown
+ case 7:
+ return 29410;
+ case 4: // Brown
+ case 5:
+ return 29411;
+ case 0: // Dark
+ case 1:
+ case 2:
+ case 3:
+ return 29412;
+ default: // original - Grey
+ return 8571;
+ }
}
}
else if (Player::TeamForRace(getRace()) == ALLIANCE)
return 892;
else
return 8571;
- case FORM_DIREBEAR:
case FORM_BEAR:
// Based on Hair color
if (getRace() == RACE_NIGHTELF)
@@ -16554,6 +14957,73 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
return 2281;
}
}
+ else if (getRace() == RACE_TROLL)
+ {
+ uint8 hairColor = GetByteValue(PLAYER_BYTES, 3);
+ switch (hairColor)
+ {
+ case 0: // Red
+ case 1:
+ return 33657;
+ case 2: // Yellow
+ case 3:
+ return 33659;
+ case 7: // Purple
+ case 10:
+ return 33656;
+ case 8: // White
+ case 9:
+ case 11:
+ case 12:
+ return 33658;
+ default: // original - Blue
+ return 33655;
+ }
+ }
+ else if (getRace() == RACE_WORGEN)
+ {
+ // Based on Skin color
+ uint8 skinColor = GetByteValue(PLAYER_BYTES, 0);
+ // Male
+ if (getGender() == GENDER_MALE)
+ {
+ switch (skinColor)
+ {
+ case 1: // Brown
+ return 33652;
+ case 2: // Black
+ case 7:
+ return 33651;
+ case 4: // Yellow
+ return 33653;
+ case 3: // White
+ case 5:
+ return 33654;
+ default: // original - Gray
+ return 33650;
+ }
+ }
+ // Female
+ else
+ {
+ switch (skinColor)
+ {
+ case 5: // Brown
+ case 6:
+ return 33652;
+ case 7: // Black
+ case 8:
+ return 33651;
+ case 3: // yellow
+ case 4:
+ return 33654;
+ case 2: // White
+ return 33653;
+ default: // original - Gray
+ return 33650;
+ }
+ }
+ }
// Based on Skin color
else if (getRace() == RACE_TAUREN)
{
@@ -16588,23 +15058,26 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
}
}
// Female
- else switch (skinColor)
+ else
{
- case 0: // Dark (Black)
- case 1:
- return 29418;
- case 2: // White
- case 3:
- return 29419;
- case 6: // Light Brown/Grey
- case 7:
- case 8:
- case 9:
- return 29420;
- case 10: // Completly White
- return 29421;
- default: // original - Brown
- return 2289;
+ switch (skinColor)
+ {
+ case 0: // Dark (Black)
+ case 1:
+ return 29418;
+ case 2: // White
+ case 3:
+ return 29419;
+ case 6: // Light Brown/Grey
+ case 7:
+ case 8:
+ case 9:
+ return 29420;
+ case 10: // Completly White
+ return 29421;
+ default: // original - Brown
+ return 2289;
+ }
}
}
else if (Player::TeamForRace(getRace()) == ALLIANCE)
@@ -16617,15 +15090,25 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
return 20872;
case FORM_FLIGHT_EPIC:
if (Player::TeamForRace(getRace()) == ALLIANCE)
- return 21243;
+ return (getRace() == RACE_WORGEN ? 37729 : 21243);
+ if (getRace() == RACE_TROLL)
+ return 37730;
return 21244;
+ case FORM_MOONKIN:
+ if (getRace() == RACE_TROLL)
+ return 37174;
+ if (getRace() == RACE_WORGEN)
+ return 37173;
+ case FORM_GHOSTWOLF:
+ if (HasAura(58135)) //! Glyph of Arctic Wolf
+ return 27312;
default:
break;
}
}
uint32 modelid = 0;
- SpellShapeshiftEntry const* formEntry = sSpellShapeshiftStore.LookupEntry(form);
+ SpellShapeshiftFormEntry const* formEntry = sSpellShapeshiftFormStore.LookupEntry(form);
if (formEntry && formEntry->modelID_A)
{
// Take the alliance modelid as default
@@ -16726,6 +15209,21 @@ uint32 Unit::GetModelForTotem(PlayerTotemType totemType)
}
break;
}
+ case RACE_GOBLIN:
+ {
+ switch (totemType)
+ {
+ case SUMMON_TYPE_TOTEM_FIRE: // fire
+ return 30783;
+ case SUMMON_TYPE_TOTEM_EARTH: // earth
+ return 30782;
+ case SUMMON_TYPE_TOTEM_WATER: // water
+ return 30784;
+ case SUMMON_TYPE_TOTEM_AIR: // air
+ return 30781;
+ }
+ break;
+ }
}
return 0;
}
@@ -16739,16 +15237,7 @@ void Unit::JumpTo(float speedXY, float speedZ, bool forward)
{
float vcos = std::cos(angle+GetOrientation());
float vsin = std::sin(angle+GetOrientation());
-
- WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
- data.append(GetPackGUID());
- data << uint32(0); // Sequence
- data << float(vcos); // x direction
- data << float(vsin); // y direction
- data << float(speedXY); // Horizontal speed
- data << float(-speedZ); // Z Movement speed (vertical)
-
- ToPlayer()->GetSession()->SendPacket(&data);
+ SendMoveKnockBack(ToPlayer(), speedXY, -speedZ, vcos, vsin);
}
}
@@ -16955,12 +15444,6 @@ void Unit::_ExitVehicle(Position const* exitPosition)
if (player)
player->SetFallInformation(0, GetPositionZ());
- else if (HasUnitMovementFlag(MOVEMENTFLAG_ROOT))
- {
- WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8);
- data.append(GetPackGUID());
- SendMessageToSet(&data, false);
- }
float height = pos.GetPositionZ();
@@ -16993,58 +15476,6 @@ void Unit::_ExitVehicle(Position const* exitPosition)
}
}
-void Unit::BuildMovementPacket(ByteBuffer *data) const
-{
- *data << uint32(GetUnitMovementFlags()); // movement flags
- *data << uint16(GetExtraUnitMovementFlags()); // 2.3.0
- *data << uint32(getMSTime()); // time / counter
- *data << GetPositionX();
- *data << GetPositionY();
- *data << GetPositionZMinusOffset();
- *data << GetOrientation();
-
- // 0x00000200
- if (GetUnitMovementFlags() & MOVEMENTFLAG_ONTRANSPORT)
- {
- if (m_vehicle)
- data->append(m_vehicle->GetBase()->GetPackGUID());
- else if (GetTransport())
- data->append(GetTransport()->GetPackGUID());
- else
- *data << (uint8)0;
-
- *data << float (GetTransOffsetX());
- *data << float (GetTransOffsetY());
- *data << float (GetTransOffsetZ());
- *data << float (GetTransOffsetO());
- *data << uint32(GetTransTime());
- *data << uint8 (GetTransSeat());
-
- if (GetExtraUnitMovementFlags() & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT)
- *data << uint32(m_movementInfo.transport.time2);
- }
-
- // 0x02200000
- if ((GetUnitMovementFlags() & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING))
- || (m_movementInfo.flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING))
- *data << (float)m_movementInfo.pitch;
-
- *data << (uint32)m_movementInfo.fallTime;
-
- // 0x00001000
- if (GetUnitMovementFlags() & MOVEMENTFLAG_FALLING)
- {
- *data << (float)m_movementInfo.jump.zspeed;
- *data << (float)m_movementInfo.jump.sinAngle;
- *data << (float)m_movementInfo.jump.cosAngle;
- *data << (float)m_movementInfo.jump.xyspeed;
- }
-
- // 0x04000000
- if (GetUnitMovementFlags() & MOVEMENTFLAG_SPLINE_ELEVATION)
- *data << (float)m_movementInfo.splineElevation;
-}
-
bool Unit::IsFalling() const
{
return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR) || movespline->isFalling();
@@ -17064,20 +15495,304 @@ void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool cas
}
}
+void Unit::WriteMovementInfo(WorldPacket& data, Movement::ExtraMovementStatusElement* extras /*= NULL*/)
+{
+ MovementInfo const& mi = m_movementInfo;
+
+ bool hasMovementFlags = GetUnitMovementFlags() != 0;
+ bool hasMovementFlags2 = GetExtraUnitMovementFlags() != 0;
+ bool hasTimestamp = true;
+ bool hasOrientation = !G3D::fuzzyEq(GetOrientation(), 0.0f);
+ bool hasTransportData = GetTransGUID() != 0;
+ bool hasSpline = IsSplineEnabled();
+
+ bool hasTransportTime2 = hasTransportData && m_movementInfo.transport.time2 != 0;
+ bool hasTransportTime3 = false;
+ bool hasPitch = HasUnitMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || HasExtraUnitMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING);
+ bool hasFallDirection = HasUnitMovementFlag(MOVEMENTFLAG_FALLING);
+ bool hasFallData = hasFallDirection || m_movementInfo.jump.fallTime != 0;
+ bool hasSplineElevation = HasUnitMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION);
+
+ MovementStatusElements const* sequence = GetMovementStatusElementsSequence(data.GetOpcode());
+ if (!sequence)
+ {
+ TC_LOG_ERROR("network", "Unit::WriteMovementInfo: No movement sequence found for opcode %s", GetOpcodeNameForLogging(data.GetOpcode()).c_str());
+ return;
+ }
+
+ ObjectGuid guid = GetGUID();
+ ObjectGuid tguid = hasTransportData ? GetTransGUID() : 0;
+
+ for (; *sequence != MSEEnd; ++sequence)
+ {
+ MovementStatusElements const& element = *sequence;
+
+ switch (element)
+ {
+ case MSEHasGuidByte0:
+ case MSEHasGuidByte1:
+ case MSEHasGuidByte2:
+ case MSEHasGuidByte3:
+ case MSEHasGuidByte4:
+ case MSEHasGuidByte5:
+ case MSEHasGuidByte6:
+ case MSEHasGuidByte7:
+ data.WriteBit(guid[element - MSEHasGuidByte0]);
+ break;
+ case MSEHasTransportGuidByte0:
+ case MSEHasTransportGuidByte1:
+ case MSEHasTransportGuidByte2:
+ case MSEHasTransportGuidByte3:
+ case MSEHasTransportGuidByte4:
+ case MSEHasTransportGuidByte5:
+ case MSEHasTransportGuidByte6:
+ case MSEHasTransportGuidByte7:
+ if (hasTransportData)
+ data.WriteBit(tguid[element - MSEHasTransportGuidByte0]);
+ break;
+ case MSEGuidByte0:
+ case MSEGuidByte1:
+ case MSEGuidByte2:
+ case MSEGuidByte3:
+ case MSEGuidByte4:
+ case MSEGuidByte5:
+ case MSEGuidByte6:
+ case MSEGuidByte7:
+ data.WriteByteSeq(guid[element - MSEGuidByte0]);
+ break;
+ case MSETransportGuidByte0:
+ case MSETransportGuidByte1:
+ case MSETransportGuidByte2:
+ case MSETransportGuidByte3:
+ case MSETransportGuidByte4:
+ case MSETransportGuidByte5:
+ case MSETransportGuidByte6:
+ case MSETransportGuidByte7:
+ if (hasTransportData)
+ data.WriteByteSeq(tguid[element - MSETransportGuidByte0]);
+ break;
+ case MSEHasMovementFlags:
+ data.WriteBit(!hasMovementFlags);
+ break;
+ case MSEHasMovementFlags2:
+ data.WriteBit(!hasMovementFlags2);
+ break;
+ case MSEHasTimestamp:
+ data.WriteBit(!hasTimestamp);
+ break;
+ case MSEHasOrientation:
+ data.WriteBit(!hasOrientation);
+ break;
+ case MSEHasTransportData:
+ data.WriteBit(hasTransportData);
+ break;
+ case MSEHasTransportTime2:
+ if (hasTransportData)
+ data.WriteBit(hasTransportTime2);
+ break;
+ case MSEHasTransportTime3:
+ if (hasTransportData)
+ data.WriteBit(hasTransportTime3);
+ break;
+ case MSEHasPitch:
+ data.WriteBit(!hasPitch);
+ break;
+ case MSEHasFallData:
+ data.WriteBit(hasFallData);
+ break;
+ case MSEHasFallDirection:
+ if (hasFallData)
+ data.WriteBit(hasFallDirection);
+ break;
+ case MSEHasSplineElevation:
+ data.WriteBit(!hasSplineElevation);
+ break;
+ case MSEHasSpline:
+ data.WriteBit(hasSpline);
+ break;
+ case MSEMovementFlags:
+ if (hasMovementFlags)
+ data.WriteBits(GetUnitMovementFlags(), 30);
+ break;
+ case MSEMovementFlags2:
+ if (hasMovementFlags2)
+ data.WriteBits(GetExtraUnitMovementFlags(), 12);
+ break;
+ case MSETimestamp:
+ if (hasTimestamp)
+ data << getMSTime();
+ break;
+ case MSEPositionX:
+ data << GetPositionX();
+ break;
+ case MSEPositionY:
+ data << GetPositionY();
+ break;
+ case MSEPositionZ:
+ data << GetPositionZ();
+ break;
+ case MSEOrientation:
+ if (hasOrientation)
+ data << GetOrientation();
+ break;
+ case MSETransportPositionX:
+ if (hasTransportData)
+ data << GetTransOffsetX();
+ break;
+ case MSETransportPositionY:
+ if (hasTransportData)
+ data << GetTransOffsetY();
+ break;
+ case MSETransportPositionZ:
+ if (hasTransportData)
+ data << GetTransOffsetZ();
+ break;
+ case MSETransportOrientation:
+ if (hasTransportData)
+ data << GetTransOffsetO();
+ break;
+ case MSETransportSeat:
+ if (hasTransportData)
+ data << GetTransSeat();
+ break;
+ case MSETransportTime:
+ if (hasTransportData)
+ data << GetTransTime();
+ break;
+ case MSETransportTime2:
+ if (hasTransportData && hasTransportTime2)
+ data << mi.transport.time2;
+ break;
+ case MSETransportTime3:
+ if (hasTransportData && hasTransportTime3)
+ data << mi.transport.time3;
+ break;
+ case MSEPitch:
+ if (hasPitch)
+ data << mi.pitch;
+ break;
+ case MSEFallTime:
+ if (hasFallData)
+ data << mi.jump.fallTime;
+ break;
+ case MSEFallVerticalSpeed:
+ if (hasFallData)
+ data << mi.jump.zspeed;
+ break;
+ case MSEFallCosAngle:
+ if (hasFallData && hasFallDirection)
+ data << mi.jump.cosAngle;
+ break;
+ case MSEFallSinAngle:
+ if (hasFallData && hasFallDirection)
+ data << mi.jump.sinAngle;
+ break;
+ case MSEFallHorizontalSpeed:
+ if (hasFallData && hasFallDirection)
+ data << mi.jump.xyspeed;
+ break;
+ case MSESplineElevation:
+ if (hasSplineElevation)
+ data << mi.splineElevation;
+ break;
+ case MSECounter:
+ data << m_movementCounter++;
+ break;
+ case MSEZeroBit:
+ data.WriteBit(0);
+ break;
+ case MSEOneBit:
+ data.WriteBit(1);
+ break;
+ case MSEExtraElement:
+ extras->WriteNextElement(data);
+ break;
+ default:
+ ASSERT(Movement::PrintInvalidSequenceElement(element, __FUNCTION__));
+ break;
+ }
+ }
+}
+
void Unit::SendTeleportPacket(Position& pos)
{
- Position oldPos = { GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), GetOrientation() };
- if (GetTypeId() == TYPEID_UNIT)
- Relocate(&pos);
+ // SMSG_MOVE_UPDATE_TELEPORT is sent to nearby players to signal the teleport
+ // MSG_MOVE_TELEPORT is sent to self in order to trigger MSG_MOVE_TELEPORT_ACK and update the position server side
+
+ // This oldPos actually contains the destination position if the Unit is a Player.
+ Position oldPos = {GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), GetOrientation()};
- WorldPacket data2(MSG_MOVE_TELEPORT, 38);
- data2.append(GetPackGUID());
- BuildMovementPacket(&data2);
if (GetTypeId() == TYPEID_UNIT)
- Relocate(&oldPos);
+ Relocate(&pos); // Relocate the unit to its new position in order to build the packets correctly.
+
+ ObjectGuid guid = GetGUID();
+ ObjectGuid transGuid = GetTransGUID();
+
+ WorldPacket data(SMSG_MOVE_UPDATE_TELEPORT, 38);
+ WriteMovementInfo(data);
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data2(MSG_MOVE_TELEPORT, 38);
+ data2.WriteBit(guid[6]);
+ data2.WriteBit(guid[0]);
+ data2.WriteBit(guid[3]);
+ data2.WriteBit(guid[2]);
+ data2.WriteBit(0); // unknown
+ data2.WriteBit(uint64(transGuid));
+ data2.WriteBit(guid[1]);
+ if (transGuid)
+ {
+ data2.WriteBit(transGuid[1]);
+ data2.WriteBit(transGuid[3]);
+ data2.WriteBit(transGuid[2]);
+ data2.WriteBit(transGuid[5]);
+ data2.WriteBit(transGuid[0]);
+ data2.WriteBit(transGuid[7]);
+ data2.WriteBit(transGuid[6]);
+ data2.WriteBit(transGuid[4]);
+ }
+ data2.WriteBit(guid[4]);
+ data2.WriteBit(guid[7]);
+ data2.WriteBit(guid[5]);
+ data2.FlushBits();
+
+ if (transGuid)
+ {
+ data2.WriteByteSeq(transGuid[6]);
+ data2.WriteByteSeq(transGuid[5]);
+ data2.WriteByteSeq(transGuid[1]);
+ data2.WriteByteSeq(transGuid[7]);
+ data2.WriteByteSeq(transGuid[0]);
+ data2.WriteByteSeq(transGuid[2]);
+ data2.WriteByteSeq(transGuid[4]);
+ data2.WriteByteSeq(transGuid[3]);
+ }
+
+ data2 << uint32(0); // counter
+ data2.WriteByteSeq(guid[1]);
+ data2.WriteByteSeq(guid[2]);
+ data2.WriteByteSeq(guid[3]);
+ data2.WriteByteSeq(guid[5]);
+ data2 << float(GetPositionX());
+ data2.WriteByteSeq(guid[4]);
+ data2 << float(GetOrientation());
+ data2.WriteByteSeq(guid[7]);
+ data2 << float(GetPositionZMinusOffset());
+ data2.WriteByteSeq(guid[0]);
+ data2.WriteByteSeq(guid[6]);
+ data2 << float(GetPositionY());
+ ToPlayer()->SendDirectMessage(&data2); // Send the MSG_MOVE_TELEPORT packet to self.
+ }
+
+ // Relocate the player/creature to its old position, so we can broadcast to nearby players correctly
if (GetTypeId() == TYPEID_PLAYER)
Relocate(&pos);
- SendMessageToSet(&data2, false);
+ else
+ Relocate(&oldPos);
+
+ // Broadcast the packet to everyone except self.
+ SendMessageToSet(&data, false);
}
bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool teleport)
@@ -17143,7 +15858,7 @@ void Unit::SendThreatListUpdate()
{
uint32 count = getThreatManager().getThreatList().size();
- //TC_LOG_DEBUG("entities.unit", "WORLD: Send SMSG_THREAT_UPDATE Message");
+ TC_LOG_DEBUG("entities.unit", "WORLD: Send SMSG_THREAT_UPDATE Message");
WorldPacket data(SMSG_THREAT_UPDATE, 8 + count * 8);
data.append(GetPackGUID());
data << uint32(count);
@@ -17195,27 +15910,22 @@ void Unit::SendRemoveFromThreatListOpcode(HostileReference* pHostileReference)
SendMessageToSet(&data, false);
}
-void Unit::RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker)
+// baseRage means damage taken when attacker = false
+void Unit::RewardRage(uint32 baseRage, bool attacker)
{
float addRage;
- float rageconversion = ((0.0091107836f * getLevel() * getLevel()) + 3.225598133f * getLevel()) + 4.2652911f;
-
- // Unknown if correct, but lineary adjust rage conversion above level 70
- if (getLevel() > 70)
- rageconversion += 13.27f * (getLevel() - 70);
-
if (attacker)
{
- addRage = (damage / rageconversion * 7.5f + weaponSpeedHitFactor) / 2;
-
+ addRage = baseRage;
// talent who gave more rage on attack
AddPct(addRage, GetTotalAuraModifier(SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT));
}
else
{
- addRage = damage / rageconversion * 2.5f;
-
+ // Calculate rage from health and damage taken
+ //! ToDo: Check formula
+ addRage = floor(0.5f + (25.7f * baseRage / GetMaxHealth()));
// Berserker Rage effect
if (HasAura(18499))
addRage *= 2.0f;
@@ -17416,7 +16126,7 @@ void Unit::SetFacingTo(float ori)
{
Movement::MoveSplineInit init(this);
init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), false);
- if (HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && GetTransGUID())
+ if (GetTransport())
init.DisableTransportPathTransformations(); // It makes no sense to target global orientation
init.SetFacing(ori);
init.Launch();
@@ -17445,28 +16155,56 @@ bool Unit::SetWalk(bool enable)
else
RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ ///@ TODO: Find proper opcode for walk mode setting in player mind controlling a player case
+ if (enable)
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_WALK_MODE, SMSG_SPLINE_MOVE_SET_WALK_MODE).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_RUN_MODE, SMSG_SPLINE_MOVE_SET_RUN_MODE).Send();
+
return true;
}
-bool Unit::SetDisableGravity(bool disable, bool /*packetOnly = false*/)
+bool Unit::SetDisableGravity(bool disable, bool packetOnly /*= false*/)
{
- if (disable == IsLevitating())
- return false;
-
- if (disable)
+ if (!packetOnly)
{
- AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
- RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING);
+ if (disable == IsLevitating())
+ return false;
+
+ if (disable)
+ {
+ AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
+ RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_SPLINE_ELEVATION);
+ SetFall(false);
+ }
+ else
+ {
+ RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
+ if (!HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY))
+ SetFall(true);
+ }
}
+
+ if (disable)
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_GRAVITY_DISABLE, SMSG_MOVE_GRAVITY_DISABLE).Send();
else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_GRAVITY_ENABLE, SMSG_MOVE_GRAVITY_ENABLE).Send();
+
+ return true;
+}
+
+bool Unit::SetFall(bool enable)
+{
+ if (enable == HasUnitMovementFlag(MOVEMENTFLAG_FALLING))
+ return false;
+
+ if (enable)
{
- RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
- if (!HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY))
- {
- m_movementInfo.SetFallTime(0);
- AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
- }
+ AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
+ m_movementInfo.SetFallTime(0);
}
+ else
+ RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR);
return true;
}
@@ -17481,6 +16219,11 @@ bool Unit::SetSwim(bool enable)
else
RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
+ if (enable)
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_START_SWIM, NULL_OPCODE).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_STOP_SWIM, NULL_OPCODE).Send();
+
return true;
}
@@ -17492,90 +16235,161 @@ bool Unit::SetCanFly(bool enable)
if (enable)
{
AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
- RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING);
+ RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_SPLINE_ELEVATION);
+ SetFall(false);
}
else
{
RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_MASK_MOVING_FLY);
if (!IsLevitating())
- {
- m_movementInfo.SetFallTime(0);
- AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
- }
+ SetFall(true);
}
+ if (enable)
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_FLYING, SMSG_MOVE_SET_CAN_FLY).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_UNSET_FLYING, SMSG_MOVE_UNSET_CAN_FLY).Send();
+
return true;
}
-bool Unit::SetWaterWalking(bool enable, bool /*packetOnly = false */)
+bool Unit::SetWaterWalking(bool enable, bool packetOnly /*= false */)
{
- if (enable == HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING))
- return false;
+ if (!packetOnly)
+ {
+ if (enable == HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING))
+ return false;
+
+ if (enable)
+ AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ else
+ RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ }
if (enable)
- AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_WATER_WALK, SMSG_MOVE_WATER_WALK).Send();
else
- RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_LAND_WALK, SMSG_MOVE_LAND_WALK).Send();
return true;
}
-bool Unit::SetFeatherFall(bool enable, bool /*packetOnly = false */)
+bool Unit::SetFeatherFall(bool enable, bool packetOnly /*= false */)
{
- if (enable == HasUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW))
- return false;
+ if (!packetOnly)
+ {
+ if (enable == HasUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW))
+ return false;
+
+ if (enable)
+ AddUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
+ else
+ RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
+ }
if (enable)
- AddUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_FEATHER_FALL, SMSG_MOVE_FEATHER_FALL).Send();
else
- RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_NORMAL_FALL, SMSG_MOVE_NORMAL_FALL).Send();
return true;
}
-bool Unit::SetHover(bool enable, bool /*packetOnly = false*/)
+bool Unit::SetHover(bool enable, bool packetOnly /*= false*/)
{
- if (enable == HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
- return false;
+ if (!packetOnly)
+ {
+ if (enable == HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
+ return false;
- float hoverHeight = GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
+ float hoverHeight = GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
- if (enable)
- {
- //! No need to check height on ascent
- AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
- if (hoverHeight)
- UpdateHeight(GetPositionZ() + hoverHeight);
- }
- else
- {
- RemoveUnitMovementFlag(MOVEMENTFLAG_HOVER);
- if (hoverHeight)
+ if (enable)
{
- float newZ = GetPositionZ() - hoverHeight;
- UpdateAllowedPositionZ(GetPositionX(), GetPositionY(), newZ);
- UpdateHeight(newZ);
+ //! No need to check height on ascent
+ AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
+ if (hoverHeight)
+ UpdateHeight(GetPositionZ() + hoverHeight);
+ }
+ else
+ {
+ RemoveUnitMovementFlag(MOVEMENTFLAG_HOVER);
+ if (hoverHeight)
+ {
+ float newZ = GetPositionZ() - hoverHeight;
+ UpdateAllowedPositionZ(GetPositionX(), GetPositionY(), newZ);
+ UpdateHeight(newZ);
+ }
}
}
+ if (enable)
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_HOVER, SMSG_MOVE_SET_HOVER).Send();
+ else
+ Movement::PacketSender(this, SMSG_SPLINE_MOVE_UNSET_HOVER, SMSG_MOVE_UNSET_HOVER).Send();
+
return true;
}
+void Unit::SendSetPlayHoverAnim(bool enable)
+{
+ ObjectGuid guid = GetGUID();
+ WorldPacket data(SMSG_SET_PLAY_HOVER_ANIM, 10);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(enable);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[6]);
+
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[6]);
+
+ SendMessageToSet(&data, true);
+}
+
+void Unit::SendMovementSetSplineAnim(Movement::AnimType anim)
+{
+ WorldPacket data(SMSG_SPLINE_MOVE_SET_ANIM, 8 + 4);
+ data.append(GetPackGUID());
+ data << uint32(anim);
+ SendMessageToSet(&data, false);
+}
+
+bool Unit::IsSplineEnabled() const
+{
+ return movespline->Initialized() && !movespline->Finalized();
+}
+
+
void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
{
if (!target)
return;
ByteBuffer fieldBuffer;
-
UpdateMask updateMask;
- updateMask.SetCount(m_valuesCount);
+
+ uint32 valCount = m_valuesCount;
uint32* flags = UnitUpdateFieldFlags;
uint32 visibleFlag = UF_FLAG_PUBLIC;
if (target == this)
visibleFlag |= UF_FLAG_PRIVATE;
+ else if (GetTypeId() == TYPEID_PLAYER)
+ valCount = PLAYER_END_NOT_SELF;
+
+ updateMask.SetCount(valCount);
Player* plr = GetCharmerOrOwnerPlayerOrPlayerItself();
if (GetOwnerGUID() == target->GetGUID())
@@ -17589,7 +16403,7 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
visibleFlag |= UF_FLAG_PARTY_MEMBER;
Creature const* creature = ToCreature();
- for (uint16 index = 0; index < m_valuesCount; ++index)
+ for (uint16 index = 0; index < valCount; ++index)
{
if (_fieldNotifyFlags & flags[index] ||
((flags[index] & visibleFlag) & UF_FLAG_SPECIAL_INFO) ||
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index e87eb957de8..035c3a6aa0e 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -28,6 +28,7 @@
#include "Object.h"
#include "SpellAuraDefines.h"
#include "ThreatManager.h"
+#include "MoveSplineInit.h"
#define WORLD_TRIGGER 12999
@@ -210,7 +211,7 @@ enum ShapeshiftForm
FORM_BEAR = 0x05,
FORM_AMBIENT = 0x06,
FORM_GHOUL = 0x07,
- FORM_DIREBEAR = 0x08,
+ FORM_DIREBEAR = 0x08, // Removed in 4.0.1
FORM_STEVES_GHOUL = 0x09,
FORM_THARONJA_SKELETON = 0x0A,
FORM_TEST_OF_STRENGTH = 0x0B,
@@ -354,6 +355,11 @@ class Vehicle;
class VehicleJoinEvent;
class TransportBase;
class SpellCastTargets;
+namespace Movement
+{
+ class ExtraMovementStatusElement;
+ class MoveSpline;
+}
typedef std::list<Unit*> UnitList;
typedef std::list< std::pair<Aura*, uint8> > DispelChargesList;
@@ -418,6 +424,7 @@ enum TriggerCastFlags
TRIGGERED_DISALLOW_PROC_EVENTS = 0x00020000, //! Disallows proc events from triggered spell (default)
TRIGGERED_DONT_REPORT_CAST_ERROR = 0x00040000, //! Will return SPELL_FAILED_DONT_REPORT in CheckCast functions
TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT = 0x00080000, //! Will ignore equipped item requirements
+ TRIGGERED_IGNORE_TARGET_CHECK = 0x00100000, //! Will ignore most target checks (mostly DBC target checks)
TRIGGERED_FULL_MASK = 0xFFFFFFFF
};
@@ -433,9 +440,13 @@ enum UnitMods
UNIT_MOD_RAGE,
UNIT_MOD_FOCUS,
UNIT_MOD_ENERGY,
- UNIT_MOD_HAPPINESS,
+ UNIT_MOD_UNUSED, // Old UNIT_MOD_HAPPINESS
UNIT_MOD_RUNE,
UNIT_MOD_RUNIC_POWER,
+ UNIT_MOD_SOUL_SHARDS,
+ UNIT_MOD_ECLIPSE,
+ UNIT_MOD_HOLY_POWER,
+ UNIT_MOD_ALTERNATIVE,
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,
@@ -455,7 +466,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_RUNIC_POWER + 1
+ UNIT_MOD_POWER_END = UNIT_MOD_ALTERNATIVE + 1
};
enum BaseModGroup
@@ -560,34 +571,35 @@ enum WeaponAttackType
enum CombatRating
{
- CR_WEAPON_SKILL = 0,
- CR_DEFENSE_SKILL = 1,
- CR_DODGE = 2,
- CR_PARRY = 3,
- CR_BLOCK = 4,
- CR_HIT_MELEE = 5,
- CR_HIT_RANGED = 6,
- CR_HIT_SPELL = 7,
- CR_CRIT_MELEE = 8,
- CR_CRIT_RANGED = 9,
- CR_CRIT_SPELL = 10,
- CR_HIT_TAKEN_MELEE = 11,
- CR_HIT_TAKEN_RANGED = 12,
- CR_HIT_TAKEN_SPELL = 13,
- CR_CRIT_TAKEN_MELEE = 14,
- CR_CRIT_TAKEN_RANGED = 15,
- CR_CRIT_TAKEN_SPELL = 16,
- CR_HASTE_MELEE = 17,
- CR_HASTE_RANGED = 18,
- CR_HASTE_SPELL = 19,
- CR_WEAPON_SKILL_MAINHAND = 20,
- CR_WEAPON_SKILL_OFFHAND = 21,
- CR_WEAPON_SKILL_RANGED = 22,
- CR_EXPERTISE = 23,
- CR_ARMOR_PENETRATION = 24
-};
-
-#define MAX_COMBAT_RATING 25
+ CR_WEAPON_SKILL = 0,
+ CR_DEFENSE_SKILL = 1, // Removed in 4.0.1
+ CR_DODGE = 2,
+ CR_PARRY = 3,
+ CR_BLOCK = 4,
+ CR_HIT_MELEE = 5,
+ CR_HIT_RANGED = 6,
+ CR_HIT_SPELL = 7,
+ CR_CRIT_MELEE = 8,
+ CR_CRIT_RANGED = 9,
+ CR_CRIT_SPELL = 10,
+ CR_HIT_TAKEN_MELEE = 11, // Deprecated since Cataclysm
+ CR_HIT_TAKEN_RANGED = 12, // Deprecated since Cataclysm
+ CR_HIT_TAKEN_SPELL = 13, // Deprecated since Cataclysm
+ CR_RESILIENCE_CRIT_TAKEN = 14,
+ CR_RESILIENCE_PLAYER_DAMAGE_TAKEN = 15,
+ CR_CRIT_TAKEN_SPELL = 16, // Deprecated since Cataclysm
+ CR_HASTE_MELEE = 17,
+ CR_HASTE_RANGED = 18,
+ CR_HASTE_SPELL = 19,
+ CR_WEAPON_SKILL_MAINHAND = 20,
+ CR_WEAPON_SKILL_OFFHAND = 21,
+ CR_WEAPON_SKILL_RANGED = 22,
+ CR_EXPERTISE = 23,
+ CR_ARMOR_PENETRATION = 24,
+ CR_MASTERY = 25,
+};
+
+#define MAX_COMBAT_RATING 26
enum DamageEffectType
{
@@ -665,7 +677,7 @@ enum NPCFlags
{
UNIT_NPC_FLAG_NONE = 0x00000000,
UNIT_NPC_FLAG_GOSSIP = 0x00000001, // 100%
- UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // guessed, probably ok
+ UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // 100%
UNIT_NPC_FLAG_UNK1 = 0x00000004,
UNIT_NPC_FLAG_UNK2 = 0x00000008,
UNIT_NPC_FLAG_TRAINER = 0x00000010, // 100%
@@ -690,7 +702,10 @@ enum NPCFlags
UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode
UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click)
UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set
- UNIT_NPC_FLAG_MAILBOX = 0x04000000 //
+ UNIT_NPC_FLAG_MAILBOX = 0x04000000, // mailbox
+ UNIT_NPC_FLAG_REFORGER = 0x08000000, // reforging
+ UNIT_NPC_FLAG_TRANSMOGRIFIER = 0x10000000, // transmogrification
+ UNIT_NPC_FLAG_VAULTKEEPER = 0x20000000 // void storage
};
enum MovementFlags
@@ -705,28 +720,27 @@ enum MovementFlags
MOVEMENTFLAG_PITCH_UP = 0x00000040,
MOVEMENTFLAG_PITCH_DOWN = 0x00000080,
MOVEMENTFLAG_WALKING = 0x00000100, // Walking
- MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures
- MOVEMENTFLAG_DISABLE_GRAVITY = 0x00000400, // Former MOVEMENTFLAG_LEVITATING. This is used when walking is not possible.
- MOVEMENTFLAG_ROOT = 0x00000800, // Must not be set along with MOVEMENTFLAG_MASK_MOVING
- MOVEMENTFLAG_FALLING = 0x00001000, // damage dealt on that type of falling
- MOVEMENTFLAG_FALLING_FAR = 0x00002000,
- MOVEMENTFLAG_PENDING_STOP = 0x00004000,
- MOVEMENTFLAG_PENDING_STRAFE_STOP = 0x00008000,
- MOVEMENTFLAG_PENDING_FORWARD = 0x00010000,
- MOVEMENTFLAG_PENDING_BACKWARD = 0x00020000,
- MOVEMENTFLAG_PENDING_STRAFE_LEFT = 0x00040000,
- MOVEMENTFLAG_PENDING_STRAFE_RIGHT = 0x00080000,
- MOVEMENTFLAG_PENDING_ROOT = 0x00100000,
- MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also
- MOVEMENTFLAG_ASCENDING = 0x00400000, // press "space" when flying
- MOVEMENTFLAG_DESCENDING = 0x00800000,
- MOVEMENTFLAG_CAN_FLY = 0x01000000, // Appears when unit can fly AND also walk
- MOVEMENTFLAG_FLYING = 0x02000000, // unit is actually flying. pretty sure this is only used for players. creatures use disable_gravity
- MOVEMENTFLAG_SPLINE_ELEVATION = 0x04000000, // used for flight paths
- MOVEMENTFLAG_SPLINE_ENABLED = 0x08000000, // used for flight paths
- MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water
- MOVEMENTFLAG_FALLING_SLOW = 0x20000000, // active rogue safe fall spell (passive)
- MOVEMENTFLAG_HOVER = 0x40000000, // hover, cannot jump
+ MOVEMENTFLAG_DISABLE_GRAVITY = 0x00000200, // Former MOVEMENTFLAG_LEVITATING. This is used when walking is not possible.
+ MOVEMENTFLAG_ROOT = 0x00000400, // Must not be set along with MOVEMENTFLAG_MASK_MOVING
+ MOVEMENTFLAG_FALLING = 0x00000800, // damage dealt on that type of falling
+ MOVEMENTFLAG_FALLING_FAR = 0x00001000,
+ MOVEMENTFLAG_PENDING_STOP = 0x00002000,
+ MOVEMENTFLAG_PENDING_STRAFE_STOP = 0x00004000,
+ MOVEMENTFLAG_PENDING_FORWARD = 0x00008000,
+ MOVEMENTFLAG_PENDING_BACKWARD = 0x00010000,
+ MOVEMENTFLAG_PENDING_STRAFE_LEFT = 0x00020000,
+ MOVEMENTFLAG_PENDING_STRAFE_RIGHT = 0x00040000,
+ MOVEMENTFLAG_PENDING_ROOT = 0x00080000,
+ MOVEMENTFLAG_SWIMMING = 0x00100000, // appears with fly flag also
+ MOVEMENTFLAG_ASCENDING = 0x00200000, // press "space" when flying
+ MOVEMENTFLAG_DESCENDING = 0x00400000,
+ MOVEMENTFLAG_CAN_FLY = 0x00800000, // Appears when unit can fly AND also walk
+ MOVEMENTFLAG_FLYING = 0x01000000, // unit is actually flying. pretty sure this is only used for players. creatures use disable_gravity
+ MOVEMENTFLAG_SPLINE_ELEVATION = 0x02000000, // used for flight paths
+ MOVEMENTFLAG_WATERWALKING = 0x04000000, // prevent unit from falling through water
+ MOVEMENTFLAG_FALLING_SLOW = 0x08000000, // active rogue safe fall spell (passive)
+ MOVEMENTFLAG_HOVER = 0x10000000, // hover, cannot jump
+ MOVEMENTFLAG_DISABLE_COLLISION = 0x20000000,
/// @todo Check if PITCH_UP and PITCH_DOWN really belong here..
MOVEMENTFLAG_MASK_MOVING =
@@ -740,6 +754,12 @@ enum MovementFlags
MOVEMENTFLAG_MASK_MOVING_FLY =
MOVEMENTFLAG_FLYING | MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING,
+ // Movement flags allowed for creature in CreateObject - we need to keep all other enabled serverside
+ // to properly calculate all movement
+ MOVEMENTFLAG_MASK_CREATURE_ALLOWED =
+ MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_ROOT | MOVEMENTFLAG_SWIMMING |
+ MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_WATERWALKING | MOVEMENTFLAG_FALLING_SLOW | MOVEMENTFLAG_HOVER,
+
/// @todo if needed: add more flags to this masks that are exclusive to players
MOVEMENTFLAG_MASK_PLAYER_ONLY =
MOVEMENTFLAG_FLYING,
@@ -754,20 +774,20 @@ enum MovementFlags2
MOVEMENTFLAG2_NONE = 0x00000000,
MOVEMENTFLAG2_NO_STRAFE = 0x00000001,
MOVEMENTFLAG2_NO_JUMPING = 0x00000002,
- MOVEMENTFLAG2_UNK3 = 0x00000004, // Overrides various clientside checks
- MOVEMENTFLAG2_FULL_SPEED_TURNING = 0x00000008,
- MOVEMENTFLAG2_FULL_SPEED_PITCHING = 0x00000010,
- MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING = 0x00000020,
- MOVEMENTFLAG2_UNK7 = 0x00000040,
- MOVEMENTFLAG2_UNK8 = 0x00000080,
- MOVEMENTFLAG2_UNK9 = 0x00000100,
- MOVEMENTFLAG2_UNK10 = 0x00000200,
- MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00000400,
- MOVEMENTFLAG2_INTERPOLATED_TURNING = 0x00000800,
- MOVEMENTFLAG2_INTERPOLATED_PITCHING = 0x00001000,
- MOVEMENTFLAG2_UNK14 = 0x00002000,
- MOVEMENTFLAG2_UNK15 = 0x00004000,
- MOVEMENTFLAG2_UNK16 = 0x00008000
+ MOVEMENTFLAG2_FULL_SPEED_TURNING = 0x00000004,
+ MOVEMENTFLAG2_FULL_SPEED_PITCHING = 0x00000008,
+ MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING = 0x00000010,
+ MOVEMENTFLAG2_UNK5 = 0x00000020,
+ MOVEMENTFLAG2_UNK6 = 0x00000040,
+ MOVEMENTFLAG2_UNK7 = 0x00000080,
+ MOVEMENTFLAG2_UNK8 = 0x00000100,
+ MOVEMENTFLAG2_UNK9 = 0x00000200,
+ MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS = 0x00000400,
+ MOVEMENTFLAG2_UNK11 = 0x00000800,
+ MOVEMENTFLAG2_UNK12 = 0x00001000,
+ MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00002000,
+ MOVEMENTFLAG2_INTERPOLATED_TURNING = 0x00004000,
+ MOVEMENTFLAG2_INTERPOLATED_PITCHING = 0x00008000
};
enum UnitTypeMask
@@ -785,10 +805,6 @@ enum UnitTypeMask
UNIT_MASK_ACCESSORY = 0x00000200
};
-namespace Movement{
- class MoveSpline;
-}
-
struct DiminishingReturn
{
DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count)
@@ -1078,7 +1094,8 @@ enum CommandStates
COMMAND_STAY = 0,
COMMAND_FOLLOW = 1,
COMMAND_ATTACK = 2,
- COMMAND_ABANDON = 3
+ COMMAND_ABANDON = 3,
+ COMMAND_MOVE_TO = 4
};
#define UNIT_ACTION_BUTTON_ACTION(X) (uint32(X) & 0x00FFFFFF)
@@ -1394,10 +1411,12 @@ class Unit : public WorldObject
Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); }
void setPowerType(Powers power);
- uint32 GetPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_POWER1 +power); }
- uint32 GetMaxPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_MAXPOWER1+power); }
- void SetPower(Powers power, uint32 val);
- void SetMaxPower(Powers power, uint32 val);
+ int32 GetPower(Powers power) const;
+ int32 GetMinPower(Powers power) const { return power == POWER_ECLIPSE ? -100 : 0; }
+ int32 GetMaxPower(Powers power) const;
+ int32 CountPctFromMaxPower(Powers power, int32 pct) const { return CalculatePct(GetMaxPower(power), pct); }
+ void SetPower(Powers power, int32 val);
+ void SetMaxPower(Powers power, int32 val);
// returns the change in power
int32 ModifyPower(Powers power, int32 val);
int32 ModifyPowerPct(Powers power, float pct, bool apply = true);
@@ -1444,6 +1463,10 @@ class Unit : public WorldObject
uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
void Mount(uint32 mount, uint32 vehicleId = 0, uint32 creatureEntry = 0);
void Dismount();
+ MountCapabilityEntry const* GetMountCapability(uint32 mountType) const;
+
+ void SendDurabilityLoss(Player* receiver, uint32 percent);
+ void PlayOneShotAnimKit(uint32 id);
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
void DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb);
@@ -1473,23 +1496,11 @@ class Unit : public WorldObject
void DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss);
// player or player's pet resilience (-1%)
- float GetMeleeCritChanceReduction() const { return GetCombatRatingReduction(CR_CRIT_TAKEN_MELEE); }
- float GetRangedCritChanceReduction() const { return GetCombatRatingReduction(CR_CRIT_TAKEN_RANGED); }
- float GetSpellCritChanceReduction() const { return GetCombatRatingReduction(CR_CRIT_TAKEN_SPELL); }
-
- // player or player's pet resilience (-1%)
- uint32 GetMeleeCritDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_MELEE, 2.2f, 33.0f, damage); }
- uint32 GetRangedCritDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_RANGED, 2.2f, 33.0f, damage); }
- uint32 GetSpellCritDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_SPELL, 2.2f, 33.0f, damage); }
+ uint32 GetDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, 1.0f, 100.0f, damage); }
- // player or player's pet resilience (-1%), cap 100%
- uint32 GetMeleeDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_MELEE, 2.0f, 100.0f, damage); }
- uint32 GetRangedDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_RANGED, 2.0f, 100.0f, damage); }
- uint32 GetSpellDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_SPELL, 2.0f, 100.0f, damage); }
+ void ApplyResilience(Unit const* victim, int32* damage) const;
- void ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type) const;
-
- float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const;
+ float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, uint32 spellId) const;
SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo);
SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo);
SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect = false);
@@ -1502,11 +1513,10 @@ class Unit : public WorldObject
int32 GetMechanicResistChance(SpellInfo const* spellInfo) const;
bool CanUseAttackType(uint8 attacktype) const;
- virtual uint32 GetShieldBlockValue() const =0;
- uint32 GetShieldBlockValue(uint32 soft_cap, uint32 hard_cap) const;
+ virtual uint32 GetBlockPercent() const { return 30; }
+
uint32 GetUnitMeleeSkill(Unit const* target = NULL) const;
- uint32 GetDefenseSkillValue(Unit const* target = NULL) const;
- uint32 GetWeaponSkillValue(WeaponAttackType attType, Unit const* target = NULL) const;
+
float GetWeaponProcChance() const;
float GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellInfo* spellProto) const;
@@ -1567,7 +1577,7 @@ class Unit : public WorldObject
void SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical = false);
int32 HealBySpell(Unit* victim, SpellInfo const* spellInfo, uint32 addHealth, bool critical = false);
- void SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, Powers powerType);
+ void SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, Powers powertype);
void EnergizeBySpell(Unit* victim, uint32 SpellID, int32 Damage, Powers powertype);
uint32 SpellNonMeleeDamageLog(Unit* victim, uint32 spellID, uint32 damage);
@@ -1585,8 +1595,7 @@ class Unit : public WorldObject
Aura* AddAura(uint32 spellId, Unit* target);
Aura* AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target);
void SetAuraStack(uint32 spellId, Unit* target, uint32 stack);
- void SendPlaySpellVisual(uint32 id);
- void SendPlaySpellImpact(uint64 guid, uint32 id);
+ void SendPlaySpellVisualKit(uint32 id, uint32 unkParam);
void BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown);
void BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns);
@@ -1609,24 +1618,27 @@ class Unit : public WorldObject
void UpdateOrientation(float orientation);
void UpdateHeight(float newZ);
+ void SendMoveKnockBack(Player* player, float speedXY, float speedZ, float vcos, float vsin);
void KnockbackFrom(float x, float y, float speedXY, float speedZ);
void JumpTo(float speedXY, float speedZ, bool forward = true);
void JumpTo(WorldObject* obj, float speedZ);
void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath = false, bool forceDestination = false);
- //void SetFacing(float ori, WorldObject* obj = NULL);
- //void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL);
- void SendMovementFlagUpdate(bool self = false);
+
+
+ void SendSetPlayHoverAnim(bool enable);
+ void SendMovementSetSplineAnim(Movement::AnimType anim);
bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); }
bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING); }
- virtual bool SetWalk(bool enable);
- virtual bool SetDisableGravity(bool disable, bool packetOnly = false);
- virtual bool SetSwim(bool enable);
- virtual bool SetCanFly(bool enable);
- virtual bool SetWaterWalking(bool enable, bool packetOnly = false);
- virtual bool SetFeatherFall(bool enable, bool packetOnly = false);
- virtual bool SetHover(bool enable, bool packetOnly = false);
+ bool SetWalk(bool enable);
+ bool SetDisableGravity(bool disable, bool packetOnly = false);
+ bool SetFall(bool enable);
+ bool SetSwim(bool enable);
+ bool SetCanFly(bool enable);
+ bool SetWaterWalking(bool enable, bool packetOnly = false);
+ bool SetFeatherFall(bool enable, bool packetOnly = false);
+ bool SetHover(bool enable, bool packetOnly = false);
void SetInFront(WorldObject const* target);
void SetFacingTo(float ori);
@@ -1639,8 +1651,6 @@ class Unit : public WorldObject
void SendClearTarget();
- void BuildHeartBeatMsg(WorldPacket* data) const;
-
bool IsAlive() const { return (m_deathState == ALIVE); }
bool isDying() const { return (m_deathState == JUST_DIED); }
bool isDead() const { return (m_deathState == DEAD || m_deathState == CORPSE); }
@@ -1752,7 +1762,7 @@ class Unit : public WorldObject
void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit* stealer);
void RemoveAurasDueToItemSpell(uint32 spellId, uint64 castItemGuid);
void RemoveAurasByType(AuraType auraType, uint64 casterGUID = 0, Aura* except = NULL, bool negative = true, bool positive = true);
- void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0);
+ void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0, bool phaseid = false);
void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except = 0);
void RemoveAurasWithAttribute(uint32 flags);
void RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID);
@@ -1837,7 +1847,8 @@ class Unit : public WorldObject
uint32 GetCreateHealth() const { return GetUInt32Value(UNIT_FIELD_BASE_HEALTH); }
void SetCreateMana(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_MANA, val); }
uint32 GetCreateMana() const { return GetUInt32Value(UNIT_FIELD_BASE_MANA); }
- uint32 GetCreatePowers(Powers power) const;
+ uint32 GetPowerIndex(uint32 powerType) const;
+ int32 GetCreatePowers(Powers power) const;
float GetPosStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_POSSTAT0+stat); }
float GetNegStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_NEGSTAT0+stat); }
float GetCreateStat(Stats stat) const { return m_createStats[stat]; }
@@ -1917,7 +1928,7 @@ class Unit : public WorldObject
void SetVisible(bool x);
// common function for visibility checks for player/creatures with detection code
- void SetPhaseMask(uint32 newPhaseMask, bool update);// overwrite WorldObject::SetPhaseMask
+ void SetInPhase(uint32 id, bool update, bool apply);
void UpdateObjectVisibility(bool forced = true);
SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
@@ -1993,9 +2004,6 @@ class Unit : public WorldObject
uint32 SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim);
uint32 SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim);
- void SetLastManaUse(uint32 spellCastTime) { m_lastManaUse = spellCastTime; }
- bool IsUnderLastManaUseEffect() const;
-
void SetContestedPvP(Player* attackedPlayer = NULL);
uint32 GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectType damagetype, uint32 CastingTime) const;
@@ -2038,17 +2046,18 @@ class Unit : public WorldObject
bool IsStopped() const { return !(HasUnitState(UNIT_STATE_MOVING)); }
void StopMoving();
- void AddUnitMovementFlag(uint32 f) { m_movementInfo.flags |= f; }
- void RemoveUnitMovementFlag(uint32 f) { m_movementInfo.flags &= ~f; }
- bool HasUnitMovementFlag(uint32 f) const { return (m_movementInfo.flags & f) == f; }
- uint32 GetUnitMovementFlags() const { return m_movementInfo.flags; }
- void SetUnitMovementFlags(uint32 f) { m_movementInfo.flags = f; }
+ void AddUnitMovementFlag(uint32 f) { m_movementInfo.AddMovementFlag(f); }
+ void RemoveUnitMovementFlag(uint32 f) { m_movementInfo.RemoveMovementFlag(f); }
+ bool HasUnitMovementFlag(uint32 f) const { return m_movementInfo.HasMovementFlag(f); }
+ uint32 GetUnitMovementFlags() const { return m_movementInfo.GetMovementFlags(); }
+ void SetUnitMovementFlags(uint32 f) { m_movementInfo.SetMovementFlags(f); }
- void AddExtraUnitMovementFlag(uint16 f) { m_movementInfo.flags2 |= f; }
- void RemoveExtraUnitMovementFlag(uint16 f) { m_movementInfo.flags2 &= ~f; }
- uint16 HasExtraUnitMovementFlag(uint16 f) const { return m_movementInfo.flags2 & f; }
- uint16 GetExtraUnitMovementFlags() const { return m_movementInfo.flags2; }
- void SetExtraUnitMovementFlags(uint16 f) { m_movementInfo.flags2 = f; }
+ void AddExtraUnitMovementFlag(uint16 f) { m_movementInfo.AddExtraMovementFlag(f); }
+ void RemoveExtraUnitMovementFlag(uint16 f) { m_movementInfo.RemoveExtraMovementFlag(f); }
+ uint16 HasExtraUnitMovementFlag(uint16 f) const { return m_movementInfo.HasExtraMovementFlag(f); }
+ uint16 GetExtraUnitMovementFlags() const { return m_movementInfo.GetExtraMovementFlags(); }
+ void SetExtraUnitMovementFlags(uint16 f) { m_movementInfo.SetExtraMovementFlags(f); }
+ bool IsSplineEnabled() const;
float GetPositionZMinusOffset() const;
@@ -2120,7 +2129,7 @@ class Unit : public WorldObject
void _ExitVehicle(Position const* exitPosition = NULL);
void _EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* aurApp = NULL);
- void BuildMovementPacket(ByteBuffer *data) const;
+ void WriteMovementInfo(WorldPacket& data, Movement::ExtraMovementStatusElement* extras = NULL);
bool isMoving() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING); }
bool isTurning() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_TURNING); }
@@ -2128,7 +2137,7 @@ class Unit : public WorldObject
bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY); }
bool IsFalling() const;
- void RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker);
+ void RewardRage(uint32 baseRage, bool attacker);
virtual float GetFollowAngle() const { return static_cast<float>(M_PI/2); }
@@ -2236,6 +2245,7 @@ class Unit : public WorldObject
void DisableSpline();
private:
bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const* & spellProcEvent);
+ bool HandleAuraProcOnPowerAmount(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool * handled);
bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
@@ -2250,16 +2260,18 @@ class Unit : public WorldObject
float GetCombatRatingReduction(CombatRating cr) const;
uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const;
+ protected:
void SetFeared(bool apply);
void SetConfused(bool apply);
void SetStunned(bool apply);
- void SetRooted(bool apply);
+ void SetRooted(bool apply, bool packetOnly = false);
- uint32 m_rootTimes;
+ uint32 m_movementCounter; ///< Incrementing counter used in movement packets
+
+ private:
uint32 m_state; // Even derived shouldn't modify
uint32 m_CombatTimer;
- uint32 m_lastManaUse; // msecs
TimeTrackerSmall m_movesplineTimer;
Diminishing m_Diminishing;
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index 915e6016e22..1e7779065d2 100755..100644
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -493,10 +493,7 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit)
if (_me->IsInWorld())
{
if (!_me->GetTransport())
- {
- unit->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
- unit->m_movementInfo.transport.Reset();
- }
+ unit->m_movementInfo.ResetTransport();
else
unit->m_movementInfo.transport = _me->m_movementInfo.transport;
}
@@ -538,6 +535,7 @@ void Vehicle::RelocatePassengers()
float px, py, pz, po;
passenger->m_movementInfo.transport.pos.GetPosition(px, py, pz, po);
CalculatePassengerPosition(px, py, pz, &po);
+
passenger->UpdatePosition(px, py, pz, po);
}
}
@@ -798,7 +796,6 @@ bool VehicleJoinEvent::Execute(uint64, uint32)
if (Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE)
Passenger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- Passenger->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
Passenger->m_movementInfo.transport.pos.Relocate(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ);
Passenger->m_movementInfo.transport.time = 0;
Passenger->m_movementInfo.transport.seat = Seat->first;
diff --git a/src/server/game/Entities/Vehicle/VehicleDefines.h b/src/server/game/Entities/Vehicle/VehicleDefines.h
index fdc5c94282b..2a800008e8b 100644
--- a/src/server/game/Entities/Vehicle/VehicleDefines.h
+++ b/src/server/game/Entities/Vehicle/VehicleDefines.h
@@ -32,7 +32,29 @@ enum PowerType
POWER_HEAT = 101,
POWER_OOZE = 121,
POWER_BLOOD = 141,
- POWER_WRATH = 142
+ POWER_WRATH = 142,
+ POWER_ARCANE_ENERGY = 143,
+ POWER_LIFE_ENERGY = 144,
+ POWER_SUN_ENERGY = 145,
+ POWER_SWING_VELOCITY = 146,
+ POWER_SHADOWFLAME_ENERGY = 147,
+ POWER_BLUE_POWER = 148,
+ POWER_PURPLE_POWER = 149,
+ POWER_GREEN_POWER = 150,
+ POWER_ORANGE_POWER = 151,
+ POWER_ENERGY_2 = 153,
+ POWER_ARCANEENERGY = 161,
+ POWER_WIND_POWER_1 = 162,
+ POWER_WIND_POWER_2 = 163,
+ POWER_WIND_POWER_3 = 164,
+ POWER_FUEL = 165,
+ POWER_SUN_POWER = 166,
+ POWER_TWILIGHT_ENERGY = 169,
+ POWER_VENOM = 174,
+ POWER_ORANGE_POWER_2 = 176,
+ POWER_CONSUMING_FLAME = 177,
+ POWER_PYROCLASTIC_FRENZY = 178,
+ POWER_FLASHFIRE = 179,
};
enum VehicleFlags
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index 9e1514f11bd..217919ff574 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -777,8 +777,8 @@ void GameEventMgr::LoadFromDB()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5
- QueryResult result = WorldDatabase.Query("SELECT eventEntry, guid, item, maxcount, incrtime, ExtendedCost FROM game_event_npc_vendor ORDER BY guid, slot ASC");
+ // 0 1 2 3 4 5 6
+ QueryResult result = WorldDatabase.Query("SELECT eventEntry, guid, item, maxcount, incrtime, ExtendedCost, type FROM game_event_npc_vendor ORDER BY guid, slot ASC");
if (!result)
TC_LOG_INFO("server.loading", ">> Loaded 0 vendor additions in game events. DB table `game_event_npc_vendor` is empty.");
@@ -804,6 +804,7 @@ void GameEventMgr::LoadFromDB()
newEntry.maxcount = fields[3].GetUInt32();
newEntry.incrtime = fields[4].GetUInt32();
newEntry.ExtendedCost = fields[5].GetUInt32();
+ newEntry.Type = fields[6].GetUInt8();
// get the event npc flag for checking if the npc will be vendor during the event or not
uint32 event_npc_flag = 0;
NPCFlagList& flist = mGameEventNPCFlags[event_id];
@@ -822,7 +823,7 @@ void GameEventMgr::LoadFromDB()
newEntry.entry = data->id;
// check validity with event's npcflag
- if (!sObjectMgr->IsVendorItemValid(newEntry.entry, newEntry.item, newEntry.maxcount, newEntry.incrtime, newEntry.ExtendedCost, NULL, NULL, event_npc_flag))
+ if (!sObjectMgr->IsVendorItemValid(newEntry.entry, newEntry.item, newEntry.maxcount, newEntry.incrtime, newEntry.ExtendedCost, newEntry.Type, NULL, NULL, event_npc_flag))
continue;
vendors.push_back(newEntry);
@@ -1151,9 +1152,9 @@ void GameEventMgr::UpdateEventNPCVendor(uint16 event_id, bool activate)
for (NPCVendorList::iterator itr = mGameEventVendors[event_id].begin(); itr != mGameEventVendors[event_id].end(); ++itr)
{
if (activate)
- sObjectMgr->AddVendorItem(itr->entry, itr->item, itr->maxcount, itr->incrtime, itr->ExtendedCost, false);
+ sObjectMgr->AddVendorItem(itr->entry, itr->item, itr->maxcount, itr->incrtime, itr->ExtendedCost, itr->Type, false);
else
- sObjectMgr->RemoveVendorItem(itr->entry, itr->item, false);
+ sObjectMgr->RemoveVendorItem(itr->entry, itr->item, itr->Type, false);
}
}
diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index e5c00da5e91..5afa26ec746 100644
--- a/src/server/game/Events/GameEventMgr.h
+++ b/src/server/game/Events/GameEventMgr.h
@@ -86,6 +86,7 @@ struct NPCVendorEntry
int32 maxcount; // 0 for infinite
uint32 incrtime; // time for restore items amount if maxcount != 0
uint32 ExtendedCost;
+ uint8 Type; // 1 item, 2 currency
};
class Player;
diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp
index 931ec0e607d..a464d0c57eb 100644
--- a/src/server/game/Globals/ObjectAccessor.cpp
+++ b/src/server/game/Globals/ObjectAccessor.cpp
@@ -93,6 +93,7 @@ WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, uint64 guid)
case HIGHGUID_UNIT: return GetCreature(p, guid);
case HIGHGUID_PET: return GetPet(p, guid);
case HIGHGUID_DYNAMICOBJECT: return GetDynamicObject(p, guid);
+ case HIGHGUID_AREATRIGGER: return GetAreaTrigger(p, guid);
case HIGHGUID_CORPSE: return GetCorpse(p, guid);
default: return NULL;
}
@@ -129,6 +130,9 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, uint64 guid, u
if (typemask & TYPEMASK_DYNAMICOBJECT)
return GetDynamicObject(p, guid);
break;
+ case HIGHGUID_AREATRIGGER:
+ if (typemask & TYPEMASK_AREATRIGGER)
+ return GetAreaTrigger(p, guid);
case HIGHGUID_CORPSE:
break;
}
@@ -160,6 +164,11 @@ DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, uint64 gui
return GetObjectInMap(guid, u.GetMap(), (DynamicObject*)NULL);
}
+AreaTrigger* ObjectAccessor::GetAreaTrigger(WorldObject const& u, uint64 guid)
+{
+ return GetObjectInMap(guid, u.GetMap(), (AreaTrigger*)NULL);
+}
+
Unit* ObjectAccessor::GetUnit(WorldObject const& u, uint64 guid)
{
return GetObjectInMap(guid, u.GetMap(), (Unit*)NULL);
@@ -369,7 +378,6 @@ Corpse* ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia
// bones->m_time = m_time; // don't overwrite time
// bones->m_type = m_type; // don't overwrite type
bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation());
- bones->SetPhaseMask(corpse->GetPhaseMask(), false);
bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES);
bones->SetUInt64Value(CORPSE_FIELD_OWNER, 0);
diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h
index 849ae25a335..f466d8bd328 100644
--- a/src/server/game/Globals/ObjectAccessor.h
+++ b/src/server/game/Globals/ObjectAccessor.h
@@ -155,6 +155,7 @@ class ObjectAccessor
static GameObject* GetGameObject(WorldObject const& u, uint64 guid);
static Transport* GetTransport(WorldObject const& u, uint64 guid);
static DynamicObject* GetDynamicObject(WorldObject const& u, uint64 guid);
+ static AreaTrigger* GetAreaTrigger(WorldObject const& u, uint64 guid);
static Unit* GetUnit(WorldObject const&, uint64 guid);
static Creature* GetCreature(WorldObject const& u, uint64 guid);
static Pet* GetPet(WorldObject const&, uint64 guid);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index b7f2cd3dae4..93c06146c06 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -24,6 +24,8 @@
#include "Chat.h"
#include "Common.h"
#include "DatabaseEnv.h"
+#include "DB2Structure.h"
+#include "DB2Stores.h"
#include "DisableMgr.h"
#include "GameEventMgr.h"
#include "GossipDef.h"
@@ -172,7 +174,9 @@ LanguageDesc lang_description[LANGUAGES_COUNT] =
{ LANG_DRAENEI, 29932, SKILL_LANG_DRAENEI },
{ LANG_ZOMBIE, 0, 0 },
{ LANG_GNOMISH_BINARY, 0, 0 },
- { LANG_GOBLIN_BINARY, 0, 0 }
+ { LANG_GOBLIN_BINARY, 0, 0 },
+ { LANG_WORGEN, 69270, SKILL_LANG_WORGEN },
+ { LANG_GOBLIN, 69269, SKILL_LANG_GOBLIN }
};
LanguageDesc const* GetLanguageDescByID(uint32 lang)
@@ -227,6 +231,7 @@ ObjectMgr::ObjectMgr():
_itemTextId(1),
_mailId(1),
_hiPetNumber(1),
+ _voidItemId(1),
_hiCharGuid(1),
_hiCreatureGuid(1),
_hiPetGuid(1),
@@ -235,15 +240,13 @@ ObjectMgr::ObjectMgr():
_hiGoGuid(1),
_hiDoGuid(1),
_hiCorpseGuid(1),
+ _hiAreaTriggerGuid(1),
_hiMoTransGuid(1),
DBCLocaleIndex(LOCALE_enUS)
{
for (uint8 i = 0; i < MAX_CLASSES; ++i)
- {
- _playerClassInfo[i] = NULL;
for (uint8 j = 0; j < MAX_RACES; ++j)
_playerInfo[j][i] = NULL;
- }
}
ObjectMgr::~ObjectMgr()
@@ -254,14 +257,6 @@ ObjectMgr::~ObjectMgr()
for (PetLevelInfoContainer::iterator i = _petInfoStore.begin(); i != _petInfoStore.end(); ++i)
delete[] i->second;
- // free only if loaded
- for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
- {
- if (_playerClassInfo[class_])
- delete[] _playerClassInfo[class_]->levelInfo;
- delete _playerClassInfo[class_];
- }
-
for (int race = 0; race < MAX_RACES; ++race)
{
for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
@@ -276,6 +271,7 @@ ObjectMgr::~ObjectMgr()
itr->second.Clear();
_cacheTrainerSpellStore.clear();
+ _graveyardOrientations.clear();
for (DungeonEncounterContainer::iterator itr =_dungeonEncounterStore.begin(); itr != _dungeonEncounterStore.end(); ++itr)
for (DungeonEncounterList::iterator encounterItr = itr->second.begin(); encounterItr != itr->second.end(); ++encounterItr)
@@ -296,13 +292,50 @@ void ObjectMgr::AddLocaleString(std::string const& s, LocaleConstant locale, Str
}
}
+void ObjectMgr::LoadGraveyardOrientations()
+{
+ uint32 oldMSTime = getMSTime();
+
+ _graveyardOrientations.clear();
+
+ QueryResult result = WorldDatabase.Query("SELECT id, orientation FROM graveyard_orientation");
+
+ if (!result)
+ return;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 id = fields[0].GetUInt32();
+ if (!sWorldSafeLocsStore.LookupEntry(id))
+ {
+ TC_LOG_ERROR("server.loading", "Graveyard %u referenced in graveyard_orientation doesn't exist.", id);
+ continue;
+ }
+ _graveyardOrientations[id] = fields[1].GetFloat();
+
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %lu graveyard orientations in %u ms", (unsigned long)_graveyardOrientations.size(), GetMSTimeDiffToNow(oldMSTime));
+}
+
void ObjectMgr::LoadCreatureLocales()
{
uint32 oldMSTime = getMSTime();
- _creatureLocaleStore.clear(); // need for reload case
+ _creatureLocaleStore.clear(); // need for reload case
- QueryResult result = WorldDatabase.Query("SELECT entry, name_loc1, subname_loc1, name_loc2, subname_loc2, name_loc3, subname_loc3, name_loc4, subname_loc4, name_loc5, subname_loc5, name_loc6, subname_loc6, name_loc7, subname_loc7, name_loc8, subname_loc8 FROM locales_creature");
+ QueryResult result = WorldDatabase.Query("SELECT entry, "
+ "name_loc1, femaleName_loc1, subname_loc1, "
+ "name_loc2, femaleName_loc2, subname_loc2, "
+ "name_loc3, femaleName_loc3, subname_loc3, "
+ "name_loc4, femaleName_loc4, subname_loc4, "
+ "name_loc5, femaleName_loc5, subname_loc5, "
+ "name_loc6, femaleName_loc6, subname_loc6, "
+ "name_loc7, femaleName_loc7, subname_loc7, "
+ "name_loc8, femaleName_loc8, subname_loc8 "
+ "FROM locales_creature");
if (!result)
return;
@@ -318,8 +351,9 @@ void ObjectMgr::LoadCreatureLocales()
for (uint8 i = 1; i < TOTAL_LOCALES; ++i)
{
LocaleConstant locale = (LocaleConstant) i;
- AddLocaleString(fields[1 + 2 * (i - 1)].GetString(), locale, data.Name);
- AddLocaleString(fields[1 + 2 * (i - 1) + 1].GetString(), locale, data.SubName);
+ AddLocaleString(fields[1 + 3 * (i - 1)].GetString(), locale, data.Name);
+ AddLocaleString(fields[1 + 3 * (i - 1) + 1].GetString(), locale, data.FemaleName);
+ AddLocaleString(fields[1 + 3 * (i - 1) + 2].GetString(), locale, data.SubName);
}
} while (result->NextRow());
@@ -395,19 +429,19 @@ void ObjectMgr::LoadCreatureTemplates()
// 0 1 2 3 4 5 6 7 8
QueryResult result = WorldDatabase.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, "
- // 9 10 11 12 13 14 15 16 17 18 19 20 21
- "modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, "
- // 22 23 24 25 26 27 28 29 30 31 32 33
+ // 9 10 11 12 13 14 15 16 17 18 19 20 21 22
+ "modelid4, name, femaleName, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, exp_unk, faction, npcflag, speed_walk, speed_run, "
+ // 23 24 25 26 27 28 29 30 31 32 33 34
"scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, "
- // 34 35 36 37 38 39 40 41 42 43
- "dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, "
- // 44 45 46 47 48 49 50 51 52 53 54
- "type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, "
- // 55 56 57 58 59 60 61 62 63 64 65 66 67
- "spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, "
- // 68 69 70 71 72 73 74 75 76 77 78
- "InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, "
- // 79 80 81 82 83 84
+ // 35 36 37 38 39 40 41 42 43
+ "dynamicflags, family, trainer_type, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, "
+ // 44 45 46 47 48 49 50 51 52 53 54
+ "type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, "
+ // 55 56 57 58 59 60 61 62 63 64 65 66 67 68
+ "spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, "
+ // 69 70 71 72 73 74 75 76 77 78 79 80
+ "InhabitType, HoverHeight, Health_mod, Mana_mod, Mana_mod_extra, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, "
+ // 81 82 83 84 85 86
" questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName "
"FROM creature_template;");
@@ -441,70 +475,73 @@ void ObjectMgr::LoadCreatureTemplates()
creatureTemplate.Modelid3 = fields[8].GetUInt32();
creatureTemplate.Modelid4 = fields[9].GetUInt32();
creatureTemplate.Name = fields[10].GetString();
- creatureTemplate.SubName = fields[11].GetString();
- creatureTemplate.IconName = fields[12].GetString();
- creatureTemplate.GossipMenuId = fields[13].GetUInt32();
- creatureTemplate.minlevel = fields[14].GetUInt8();
- creatureTemplate.maxlevel = fields[15].GetUInt8();
- creatureTemplate.expansion = uint32(fields[16].GetInt16());
- creatureTemplate.faction = uint32(fields[17].GetUInt16());
- creatureTemplate.npcflag = fields[18].GetUInt32();
- creatureTemplate.speed_walk = fields[19].GetFloat();
- creatureTemplate.speed_run = fields[20].GetFloat();
- creatureTemplate.scale = fields[21].GetFloat();
- creatureTemplate.rank = uint32(fields[22].GetUInt8());
- creatureTemplate.mindmg = fields[23].GetFloat();
- creatureTemplate.maxdmg = fields[24].GetFloat();
- creatureTemplate.dmgschool = uint32(fields[25].GetInt8());
- creatureTemplate.attackpower = fields[26].GetUInt32();
- creatureTemplate.dmg_multiplier = fields[27].GetFloat();
- creatureTemplate.baseattacktime = fields[28].GetUInt32();
- creatureTemplate.rangeattacktime = fields[29].GetUInt32();
- creatureTemplate.unit_class = uint32(fields[30].GetUInt8());
- creatureTemplate.unit_flags = fields[31].GetUInt32();
- creatureTemplate.unit_flags2 = fields[32].GetUInt32();
- creatureTemplate.dynamicflags = fields[33].GetUInt32();
- creatureTemplate.family = uint32(fields[34].GetUInt8());
- creatureTemplate.trainer_type = uint32(fields[35].GetUInt8());
- creatureTemplate.trainer_spell = fields[36].GetUInt32();
- creatureTemplate.trainer_class = uint32(fields[37].GetUInt8());
- creatureTemplate.trainer_race = uint32(fields[38].GetUInt8());
- creatureTemplate.minrangedmg = fields[39].GetFloat();
- creatureTemplate.maxrangedmg = fields[40].GetFloat();
- creatureTemplate.rangedattackpower = uint32(fields[41].GetUInt16());
- creatureTemplate.type = uint32(fields[42].GetUInt8());
- creatureTemplate.type_flags = fields[43].GetUInt32();
- creatureTemplate.lootid = fields[44].GetUInt32();
- creatureTemplate.pickpocketLootId = fields[45].GetUInt32();
- creatureTemplate.SkinLootId = fields[46].GetUInt32();
+ creatureTemplate.FemaleName = fields[11].GetString();
+ creatureTemplate.SubName = fields[12].GetString();
+ creatureTemplate.IconName = fields[13].GetString();
+ creatureTemplate.GossipMenuId = fields[14].GetUInt32();
+ creatureTemplate.minlevel = fields[15].GetUInt8();
+ creatureTemplate.maxlevel = fields[16].GetUInt8();
+ creatureTemplate.expansion = uint32(fields[17].GetInt16());
+ creatureTemplate.expansionUnknown = uint32(fields[18].GetUInt16());
+ creatureTemplate.faction = uint32(fields[19].GetUInt16());
+ creatureTemplate.npcflag = fields[20].GetUInt32();
+ creatureTemplate.speed_walk = fields[21].GetFloat();
+ creatureTemplate.speed_run = fields[22].GetFloat();
+ creatureTemplate.scale = fields[23].GetFloat();
+ creatureTemplate.rank = uint32(fields[24].GetUInt8());
+ creatureTemplate.mindmg = fields[25].GetFloat();
+ creatureTemplate.maxdmg = fields[26].GetFloat();
+ creatureTemplate.dmgschool = uint32(fields[27].GetInt8());
+ creatureTemplate.attackpower = fields[28].GetUInt32();
+ creatureTemplate.dmg_multiplier = fields[29].GetFloat();
+ creatureTemplate.baseattacktime = fields[30].GetUInt32();
+ creatureTemplate.rangeattacktime = fields[31].GetUInt32();
+ creatureTemplate.unit_class = uint32(fields[32].GetUInt8());
+ creatureTemplate.unit_flags = fields[33].GetUInt32();
+ creatureTemplate.unit_flags2 = fields[34].GetUInt32();
+ creatureTemplate.dynamicflags = fields[35].GetUInt32();
+ creatureTemplate.family = uint32(fields[36].GetUInt8());
+ creatureTemplate.trainer_type = uint32(fields[37].GetUInt8());
+ creatureTemplate.trainer_class = uint32(fields[38].GetUInt8());
+ creatureTemplate.trainer_race = uint32(fields[39].GetUInt8());
+ creatureTemplate.minrangedmg = fields[40].GetFloat();
+ creatureTemplate.maxrangedmg = fields[41].GetFloat();
+ creatureTemplate.rangedattackpower = uint32(fields[42].GetUInt16());
+ creatureTemplate.type = uint32(fields[43].GetUInt8());
+ creatureTemplate.type_flags = fields[44].GetUInt32();
+ creatureTemplate.type_flags2 = fields[45].GetUInt32();
+ creatureTemplate.lootid = fields[46].GetUInt32();
+ creatureTemplate.pickpocketLootId = fields[47].GetUInt32();
+ creatureTemplate.SkinLootId = fields[48].GetUInt32();
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- creatureTemplate.resistance[i] = fields[47 + i -1].GetInt16();
+ creatureTemplate.resistance[i] = fields[49 + i - 1].GetInt16();
for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i)
- creatureTemplate.spells[i] = fields[53 + i].GetUInt32();
-
- creatureTemplate.PetSpellDataId = fields[61].GetUInt32();
- creatureTemplate.VehicleId = fields[62].GetUInt32();
- creatureTemplate.mingold = fields[63].GetUInt32();
- creatureTemplate.maxgold = fields[64].GetUInt32();
- creatureTemplate.AIName = fields[65].GetString();
- creatureTemplate.MovementType = uint32(fields[66].GetUInt8());
- creatureTemplate.InhabitType = uint32(fields[67].GetUInt8());
- creatureTemplate.HoverHeight = fields[68].GetFloat();
- creatureTemplate.ModHealth = fields[69].GetFloat();
- creatureTemplate.ModMana = fields[70].GetFloat();
- creatureTemplate.ModArmor = fields[71].GetFloat();
- creatureTemplate.RacialLeader = fields[72].GetBool();
+ creatureTemplate.spells[i] = fields[55 + i].GetUInt32();
+
+ creatureTemplate.PetSpellDataId = fields[63].GetUInt32();
+ creatureTemplate.VehicleId = fields[64].GetUInt32();
+ creatureTemplate.mingold = fields[65].GetUInt32();
+ creatureTemplate.maxgold = fields[66].GetUInt32();
+ creatureTemplate.AIName = fields[67].GetString();
+ creatureTemplate.MovementType = uint32(fields[68].GetUInt8());
+ creatureTemplate.InhabitType = uint32(fields[69].GetUInt8());
+ creatureTemplate.HoverHeight = fields[70].GetFloat();
+ creatureTemplate.ModHealth = fields[71].GetFloat();
+ creatureTemplate.ModMana = fields[72].GetFloat();
+ creatureTemplate.ModManaExtra = fields[73].GetFloat();
+ creatureTemplate.ModArmor = fields[74].GetFloat();
+ creatureTemplate.RacialLeader = fields[75].GetBool();
for (uint8 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
- creatureTemplate.questItems[i] = fields[73 + i].GetUInt32();
+ creatureTemplate.questItems[i] = fields[76 + i].GetUInt32();
- creatureTemplate.movementId = fields[79].GetUInt32();
- creatureTemplate.RegenHealth = fields[80].GetBool();
- creatureTemplate.MechanicImmuneMask = fields[81].GetUInt32();
- creatureTemplate.flags_extra = fields[82].GetUInt32();
- creatureTemplate.ScriptID = GetScriptId(fields[83].GetCString());
+ creatureTemplate.movementId = fields[82].GetUInt32();
+ creatureTemplate.RegenHealth = fields[83].GetBool();
+ creatureTemplate.MechanicImmuneMask = fields[84].GetUInt32();
+ creatureTemplate.flags_extra = fields[85].GetUInt32();
+ creatureTemplate.ScriptID = GetScriptId(fields[86].GetCString());
++count;
}
@@ -719,12 +756,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
continue;
}
- if (cInfo->trainer_spell != difficultyInfo->trainer_spell)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has different `trainer_spell` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]);
- continue;
- }
-
if (cInfo->type != difficultyInfo->type)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, type %u) has different `type` in difficulty %u mode (Entry: %u, type %u).",
@@ -945,10 +976,16 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
if (cInfo->expansion > (MAX_EXPANSIONS - 1))
{
- TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: %u) with expansion %u. Ignored and set to 0.", cInfo->Entry, cInfo->expansion);
+ TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: %u) with `exp` %u. Ignored and set to 0.", cInfo->Entry, cInfo->expansion);
const_cast<CreatureTemplate*>(cInfo)->expansion = 0;
}
+ if (cInfo->expansionUnknown > MAX_EXPANSIONS)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: %u) with `exp_unk` %u. Ignored and set to 0.", cInfo->Entry, cInfo->expansionUnknown);
+ const_cast<CreatureTemplate*>(cInfo)->expansionUnknown = 0;
+ }
+
if (uint32 badFlags = (cInfo->flags_extra & ~CREATURE_FLAG_EXTRA_DB_ALLOWED))
{
TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: %u) with disallowed `flags_extra` %u, removing incorrect flag.", cInfo->Entry, badFlags);
@@ -1601,8 +1638,8 @@ void ObjectMgr::LoadCreatures()
// 0 1 2 3 4 5 6 7 8 9 10
QueryResult result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, "
- // 11 12 13 14 15 16 17 18 19 20 21
- "currentwaypoint, curhealth, curmana, MovementType, spawnMask, phaseMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags "
+ // 11 12 13 14 15 16 17 18 19 20 21 22 23
+ "currentwaypoint, curhealth, curmana, MovementType, spawnMask, phaseMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags, creature.phaseid, creature.phasegroup "
"FROM creature "
"LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid "
"LEFT OUTER JOIN pool_creature ON creature.guid = pool_creature.guid");
@@ -1659,17 +1696,19 @@ void ObjectMgr::LoadCreatures()
data.npcflag = fields[19].GetUInt32();
data.unit_flags = fields[20].GetUInt32();
data.dynamicflags = fields[21].GetUInt32();
+ data.phaseid = fields[22].GetUInt32();
+ data.phaseGroup = fields[23].GetUInt32();
MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid);
if (!mapEntry)
{
- TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u) that spawned at not existed map (Id: %u), skipped.", guid, data.mapid);
+ TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u Entry: %u) that spawned at not existed map (Id: %u), skipped.", guid, data.id, data.mapid);
continue;
}
// Skip spawnMask check for transport maps
if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid])
- TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.mapid);
+ TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u Entry: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u) spawnMasks[data.mapid]: %u.", guid, data.id, data.spawnMask, data.mapid, spawnMasks[data.mapid]);
bool ok = true;
for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff)
@@ -1728,6 +1767,12 @@ void ObjectMgr::LoadCreatures()
data.phaseMask = 1;
}
+ if (data.phaseGroup && data.phaseid)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u Entry: %u) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0", guid, data.id);
+ data.phaseGroup = 0;
+ }
+
// Add to grid if not managed by the game event or pool system
if (gameEvent == 0 && PoolId == 0)
AddCreatureToGrid(guid, &data);
@@ -1911,8 +1956,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 16 17
- "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, eventEntry, pool_entry "
+ // 7 8 9 10 11 12 13 14 15 16 17 18 19
+ "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, eventEntry, pool_entry, phaseid, phasegroup "
"FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid "
"LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid");
@@ -2008,7 +2053,15 @@ void ObjectMgr::LoadGameobjects()
data.phaseMask = fields[15].GetUInt32();
int16 gameEvent = fields[16].GetInt8();
- uint32 PoolId = fields[17].GetUInt32();
+ uint32 PoolId = fields[17].GetUInt32();
+ data.phaseid = fields[18].GetUInt32();
+ data.phaseGroup = fields[19].GetUInt32();
+
+ if (data.phaseGroup && data.phaseid)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `gameobject` have gameobject (GUID: %u Entry: %u) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0", guid, data.id);
+ data.phaseGroup = 0;
+ }
if (data.rotation2 < -1.0f || data.rotation2 > 1.0f)
{
@@ -2210,582 +2263,504 @@ void ObjectMgr::LoadItemLocales()
TC_LOG_INFO("server.loading", ">> Loaded %lu Item locale strings in %u ms", (unsigned long)_itemLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::LoadItemTemplates()
+void FillItemDamageFields(float* minDamage, float* maxDamage, float* dps, uint32 itemLevel, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32 delay, float statScalingFactor, uint32 inventoryType, uint32 flags2)
{
- uint32 oldMSTime = getMSTime();
-
- // 0 1 2 3 4 5 6 7 8 9 10 11 12
- QueryResult result = WorldDatabase.Query("SELECT entry, class, subclass, SoundOverrideSubclass, name, displayid, Quality, Flags, FlagsExtra, BuyCount, BuyPrice, SellPrice, InventoryType, "
- // 13 14 15 16 17 18 19 20
- "AllowableClass, AllowableRace, ItemLevel, RequiredLevel, RequiredSkill, RequiredSkillRank, requiredspell, requiredhonorrank, "
- // 21 22 23 24 25 26 27 28
- "RequiredCityRank, RequiredReputationFaction, RequiredReputationRank, maxcount, stackable, ContainerSlots, StatsCount, stat_type1, "
- // 29 30 31 32 33 34 35 36 37 38
- "stat_value1, stat_type2, stat_value2, stat_type3, stat_value3, stat_type4, stat_value4, stat_type5, stat_value5, stat_type6, "
- // 39 40 41 42 43 44 45 46 47
- "stat_value6, stat_type7, stat_value7, stat_type8, stat_value8, stat_type9, stat_value9, stat_type10, stat_value10, "
- // 48 49 50 51 52 53 54 55 56 57 58
- "ScalingStatDistribution, ScalingStatValue, dmg_min1, dmg_max1, dmg_type1, dmg_min2, dmg_max2, dmg_type2, armor, holy_res, fire_res, "
- // 59 60 61 62 63 64 65 66 67 68
- "nature_res, frost_res, shadow_res, arcane_res, delay, ammo_type, RangedModRange, spellid_1, spelltrigger_1, spellcharges_1, "
- // 69 70 71 72 73 74 75
- "spellppmRate_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, spellid_2, spelltrigger_2, spellcharges_2, "
- // 76 77 78 79 80 81 82
- "spellppmRate_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, spellid_3, spelltrigger_3, spellcharges_3, "
- // 83 84 85 86 87 88 89
- "spellppmRate_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, spellid_4, spelltrigger_4, spellcharges_4, "
- // 90 91 92 93 94 95 96
- "spellppmRate_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, spellid_5, spelltrigger_5, spellcharges_5, "
- // 97 98 99 100 101 102 103 104 105
- "spellppmRate_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, bonding, description, PageText, LanguageID, PageMaterial, "
- // 106 107 108 109 110 111 112 113 114 115 116 117
- "startquest, lockid, Material, sheath, RandomProperty, RandomSuffix, block, itemset, MaxDurability, area, Map, BagFamily, "
- // 118 119 120 121 122 123 124 125
- "TotemCategory, socketColor_1, socketContent_1, socketColor_2, socketContent_2, socketColor_3, socketContent_3, socketBonus, "
- // 126 127 128 129 130 131 132 133
- "GemProperties, RequiredDisenchantSkill, ArmorDamageModifier, duration, ItemLimitCategory, HolidayId, ScriptName, DisenchantID, "
- // 134 135 136
- "FoodType, minMoneyLoot, maxMoneyLoot, flagsCustom FROM item_template");
-
- if (!result)
- {
- TC_LOG_INFO("server.loading", ">> Loaded 0 item templates. DB table `item_template` is empty.");
+ *minDamage = *maxDamage = *dps = 0.0f;
+ if (itemClass != ITEM_CLASS_WEAPON || quality > ITEM_QUALITY_ARTIFACT)
return;
- }
- _itemTemplateStore.rehash(result->GetRowCount());
- uint32 count = 0;
- bool enforceDBCAttributes = sWorld->getBoolConfig(CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES);
+ DBCStorage<ItemDamageEntry>* store = NULL;
+ // get the right store here
+ if (inventoryType > 0xD + 13)
+ return;
- do
+ switch (inventoryType)
{
- Field* fields = result->Fetch();
-
- uint32 entry = fields[0].GetUInt32();
-
- ItemTemplate& itemTemplate = _itemTemplateStore[entry];
-
- itemTemplate.ItemId = entry;
- itemTemplate.Class = uint32(fields[1].GetUInt8());
- itemTemplate.SubClass = uint32(fields[2].GetUInt8());
- itemTemplate.SoundOverrideSubclass = int32(fields[3].GetInt8());
- itemTemplate.Name1 = fields[4].GetString();
- itemTemplate.DisplayInfoID = fields[5].GetUInt32();
- itemTemplate.Quality = uint32(fields[6].GetUInt8());
- itemTemplate.Flags = fields[7].GetUInt32();
- itemTemplate.Flags2 = fields[8].GetUInt32();
- itemTemplate.BuyCount = uint32(fields[9].GetUInt8());
- itemTemplate.BuyPrice = int32(fields[10].GetInt64());
- itemTemplate.SellPrice = fields[11].GetUInt32();
- itemTemplate.InventoryType = uint32(fields[12].GetUInt8());
- itemTemplate.AllowableClass = fields[13].GetInt32();
- itemTemplate.AllowableRace = fields[14].GetInt32();
- itemTemplate.ItemLevel = uint32(fields[15].GetUInt16());
- itemTemplate.RequiredLevel = uint32(fields[16].GetUInt8());
- itemTemplate.RequiredSkill = uint32(fields[17].GetUInt16());
- itemTemplate.RequiredSkillRank = uint32(fields[18].GetUInt16());
- itemTemplate.RequiredSpell = fields[19].GetUInt32();
- itemTemplate.RequiredHonorRank = fields[20].GetUInt32();
- itemTemplate.RequiredCityRank = fields[21].GetUInt32();
- itemTemplate.RequiredReputationFaction = uint32(fields[22].GetUInt16());
- itemTemplate.RequiredReputationRank = uint32(fields[23].GetUInt16());
- itemTemplate.MaxCount = fields[24].GetInt32();
- itemTemplate.Stackable = fields[25].GetInt32();
- itemTemplate.ContainerSlots = uint32(fields[26].GetUInt8());
- itemTemplate.StatsCount = uint32(fields[27].GetUInt8());
-
- for (uint8 i = 0; i < itemTemplate.StatsCount; ++i)
- {
- itemTemplate.ItemStat[i].ItemStatType = uint32(fields[28 + i*2].GetUInt8());
- itemTemplate.ItemStat[i].ItemStatValue = int32(fields[29 + i*2].GetInt16());
- }
-
- itemTemplate.ScalingStatDistribution = uint32(fields[48].GetUInt16());
- itemTemplate.ScalingStatValue = fields[49].GetInt32();
-
- for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
- {
- itemTemplate.Damage[i].DamageMin = fields[50 + i*3].GetFloat();
- itemTemplate.Damage[i].DamageMax = fields[51 + i*3].GetFloat();
- itemTemplate.Damage[i].DamageType = uint32(fields[52 + i*3].GetUInt8());
- }
-
- itemTemplate.Armor = uint32(fields[56].GetUInt16());
- itemTemplate.HolyRes = uint32(fields[57].GetUInt8());
- itemTemplate.FireRes = uint32(fields[58].GetUInt8());
- itemTemplate.NatureRes = uint32(fields[59].GetUInt8());
- itemTemplate.FrostRes = uint32(fields[60].GetUInt8());
- itemTemplate.ShadowRes = uint32(fields[61].GetUInt8());
- itemTemplate.ArcaneRes = uint32(fields[62].GetUInt8());
- itemTemplate.Delay = uint32(fields[63].GetUInt16());
- itemTemplate.AmmoType = uint32(fields[64].GetUInt8());
- itemTemplate.RangedModRange = fields[65].GetFloat();
-
- for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
- {
- itemTemplate.Spells[i].SpellId = fields[66 + i*7 ].GetInt32();
- itemTemplate.Spells[i].SpellTrigger = uint32(fields[67 + i*7].GetUInt8());
- itemTemplate.Spells[i].SpellCharges = int32(fields[68 + i*7].GetInt16());
- itemTemplate.Spells[i].SpellPPMRate = fields[69 + i*7].GetFloat();
- itemTemplate.Spells[i].SpellCooldown = fields[70 + i*7].GetInt32();
- itemTemplate.Spells[i].SpellCategory = uint32(fields[71 + i*7].GetUInt16());
- itemTemplate.Spells[i].SpellCategoryCooldown = fields[72 + i*7].GetInt32();
- }
-
- itemTemplate.Bonding = uint32(fields[101].GetUInt8());
- itemTemplate.Description = fields[102].GetString();
- itemTemplate.PageText = fields[103].GetUInt32();
- itemTemplate.LanguageID = uint32(fields[104].GetUInt8());
- itemTemplate.PageMaterial = uint32(fields[105].GetUInt8());
- itemTemplate.StartQuest = fields[106].GetUInt32();
- itemTemplate.LockID = fields[107].GetUInt32();
- itemTemplate.Material = int32(fields[108].GetInt8());
- itemTemplate.Sheath = uint32(fields[109].GetUInt8());
- itemTemplate.RandomProperty = fields[110].GetUInt32();
- itemTemplate.RandomSuffix = fields[111].GetInt32();
- itemTemplate.Block = fields[112].GetUInt32();
- itemTemplate.ItemSet = fields[113].GetUInt32();
- itemTemplate.MaxDurability = uint32(fields[114].GetUInt16());
- itemTemplate.Area = fields[115].GetUInt32();
- itemTemplate.Map = uint32(fields[116].GetUInt16());
- itemTemplate.BagFamily = fields[117].GetUInt32();
- itemTemplate.TotemCategory = fields[118].GetUInt32();
-
- for (uint8 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
- {
- itemTemplate.Socket[i].Color = uint32(fields[119 + i*2].GetUInt8());
- itemTemplate.Socket[i].Content = fields[120 + i*2].GetUInt32();
- }
-
- itemTemplate.socketBonus = fields[125].GetUInt32();
- itemTemplate.GemProperties = fields[126].GetUInt32();
- itemTemplate.RequiredDisenchantSkill = uint32(fields[127].GetInt16());
- itemTemplate.ArmorDamageModifier = fields[128].GetFloat();
- itemTemplate.Duration = fields[129].GetUInt32();
- itemTemplate.ItemLimitCategory = uint32(fields[130].GetInt16());
- itemTemplate.HolidayId = fields[131].GetUInt32();
- itemTemplate.ScriptId = sObjectMgr->GetScriptId(fields[132].GetCString());
- itemTemplate.DisenchantID = fields[133].GetUInt32();
- itemTemplate.FoodType = uint32(fields[134].GetUInt8());
- itemTemplate.MinMoneyLoot = fields[135].GetUInt32();
- itemTemplate.MaxMoneyLoot = fields[136].GetUInt32();
- itemTemplate.FlagsCu = fields[137].GetUInt32();
-
- // Checks
-
- ItemEntry const* dbcitem = sItemStore.LookupEntry(entry);
-
- if (dbcitem)
- {
- if (itemTemplate.Class != dbcitem->Class)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not have a correct class %u, must be %u .", entry, itemTemplate.Class, dbcitem->Class);
- if (enforceDBCAttributes)
- itemTemplate.Class = dbcitem->Class;
- }
-
- if (itemTemplate.SoundOverrideSubclass != dbcitem->SoundOverrideSubclass)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not have a correct SoundOverrideSubclass (%i), must be %i .", entry, itemTemplate.SoundOverrideSubclass, dbcitem->SoundOverrideSubclass);
- if (enforceDBCAttributes)
- itemTemplate.SoundOverrideSubclass = dbcitem->SoundOverrideSubclass;
- }
- if (itemTemplate.Material != dbcitem->Material)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not have a correct material (%i), must be %i .", entry, itemTemplate.Material, dbcitem->Material);
- if (enforceDBCAttributes)
- itemTemplate.Material = dbcitem->Material;
- }
- if (itemTemplate.InventoryType != dbcitem->InventoryType)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not have a correct inventory type (%u), must be %u .", entry, itemTemplate.InventoryType, dbcitem->InventoryType);
- if (enforceDBCAttributes)
- itemTemplate.InventoryType = dbcitem->InventoryType;
- }
- if (itemTemplate.DisplayInfoID != dbcitem->DisplayId)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not have a correct display id (%u), must be %u .", entry, itemTemplate.DisplayInfoID, dbcitem->DisplayId);
- if (enforceDBCAttributes)
- itemTemplate.DisplayInfoID = dbcitem->DisplayId;
- }
- if (itemTemplate.Sheath != dbcitem->Sheath)
+ case INVTYPE_AMMO:
+ store = &sItemDamageAmmoStore;
+ break;
+ case INVTYPE_2HWEAPON:
+ if (flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON)
+ store = &sItemDamageTwoHandCasterStore;
+ else
+ store = &sItemDamageTwoHandStore;
+ break;
+ case INVTYPE_RANGED:
+ case INVTYPE_THROWN:
+ case INVTYPE_RANGEDRIGHT:
+ switch (itemSubClass)
{
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not have a correct sheathid (%u), must be %u .", entry, itemTemplate.Sheath, dbcitem->Sheath);
- if (enforceDBCAttributes)
- itemTemplate.Sheath = dbcitem->Sheath;
+ case ITEM_SUBCLASS_WEAPON_WAND:
+ store = &sItemDamageWandStore;
+ break;
+ case ITEM_SUBCLASS_WEAPON_THROWN:
+ store = &sItemDamageThrownStore;
+ break;
+ case ITEM_SUBCLASS_WEAPON_BOW:
+ case ITEM_SUBCLASS_WEAPON_GUN:
+ case ITEM_SUBCLASS_WEAPON_CROSSBOW:
+ store = &sItemDamageRangedStore;
+ break;
+ default:
+ return;
}
+ break;
+ case INVTYPE_WEAPON:
+ case INVTYPE_WEAPONMAINHAND:
+ case INVTYPE_WEAPONOFFHAND:
+ if (flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON)
+ store = &sItemDamageOneHandCasterStore;
+ else
+ store = &sItemDamageOneHandStore;
+ break;
+ default:
+ return;
+ }
- }
- else
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not exist in item.dbc! (not correct id?).", entry);
-
- if (itemTemplate.Class >= MAX_ITEM_CLASS)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong Class value (%u)", entry, itemTemplate.Class);
- itemTemplate.Class = ITEM_CLASS_MISC;
- }
-
- if (itemTemplate.SubClass >= MaxItemSubclassValues[itemTemplate.Class])
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong Subclass value (%u) for class %u", entry, itemTemplate.SubClass, itemTemplate.Class);
- itemTemplate.SubClass = 0;// exist for all item classes
- }
-
- if (itemTemplate.Quality >= MAX_ITEM_QUALITY)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong Quality value (%u)", entry, itemTemplate.Quality);
- itemTemplate.Quality = ITEM_QUALITY_NORMAL;
- }
-
- if (itemTemplate.Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY)
- {
- if (FactionEntry const* faction = sFactionStore.LookupEntry(HORDE))
- if ((itemTemplate.AllowableRace & faction->BaseRepRaceMask[0]) == 0)
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has value (%u) in `AllowableRace` races, not compatible with ITEM_FLAGS_EXTRA_HORDE_ONLY (%u) in Flags field, item cannot be equipped or used by these races.",
- entry, itemTemplate.AllowableRace, ITEM_FLAGS_EXTRA_HORDE_ONLY);
-
- if (itemTemplate.Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY)
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has value (%u) in `Flags2` flags (ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) and ITEM_FLAGS_EXTRA_HORDE_ONLY (%u) in Flags field, this is a wrong combination.",
- entry, ITEM_FLAGS_EXTRA_ALLIANCE_ONLY, ITEM_FLAGS_EXTRA_HORDE_ONLY);
- }
- else if (itemTemplate.Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY)
- {
- if (FactionEntry const* faction = sFactionStore.LookupEntry(ALLIANCE))
- if ((itemTemplate.AllowableRace & faction->BaseRepRaceMask[0]) == 0)
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has value (%u) in `AllowableRace` races, not compatible with ITEM_FLAGS_EXTRA_ALLIANCE_ONLY (%u) in Flags field, item cannot be equipped or used by these races.",
- entry, itemTemplate.AllowableRace, ITEM_FLAGS_EXTRA_ALLIANCE_ONLY);
- }
-
- if (itemTemplate.BuyCount <= 0)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong BuyCount value (%u), set to default(1).", entry, itemTemplate.BuyCount);
- itemTemplate.BuyCount = 1;
- }
-
- if (itemTemplate.InventoryType >= MAX_INVTYPE)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong InventoryType value (%u)", entry, itemTemplate.InventoryType);
- itemTemplate.InventoryType = INVTYPE_NON_EQUIP;
- }
-
- if (itemTemplate.RequiredSkill >= MAX_SKILL_TYPE)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong RequiredSkill value (%u)", entry, itemTemplate.RequiredSkill);
- itemTemplate.RequiredSkill = 0;
- }
-
- {
- // can be used in equip slot, as page read use in inventory, or spell casting at use
- bool req = itemTemplate.InventoryType != INVTYPE_NON_EQUIP || itemTemplate.PageText;
- if (!req)
- for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j)
- {
- if (itemTemplate.Spells[j].SpellId)
- {
- req = true;
- break;
- }
- }
-
- if (req)
- {
- if (!(itemTemplate.AllowableClass & CLASSMASK_ALL_PLAYABLE))
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not have any playable classes (%u) in `AllowableClass` and can't be equipped or used.", entry, itemTemplate.AllowableClass);
+ if (!store)
+ return;
- if (!(itemTemplate.AllowableRace & RACEMASK_ALL_PLAYABLE))
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not have any playable races (%u) in `AllowableRace` and can't be equipped or used.", entry, itemTemplate.AllowableRace);
- }
- }
+ ItemDamageEntry const* damageInfo = store->LookupEntry(itemLevel);
+ if (!damageInfo)
+ return;
- if (itemTemplate.RequiredSpell && !sSpellMgr->GetSpellInfo(itemTemplate.RequiredSpell))
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has a wrong (non-existing) spell in RequiredSpell (%u)", entry, itemTemplate.RequiredSpell);
- itemTemplate.RequiredSpell = 0;
- }
+ *dps = damageInfo->DPS[quality];
+ float avgDamage = *dps * delay * 0.001f;
+ *minDamage = (statScalingFactor * -0.5f + 1.0f) * avgDamage;
+ *maxDamage = floor(float(avgDamage* (statScalingFactor * 0.5f + 1.0f) + 0.5f));
+}
- if (itemTemplate.RequiredReputationRank >= MAX_REPUTATION_RANK)
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong reputation rank in RequiredReputationRank (%u), item can't be used.", entry, itemTemplate.RequiredReputationRank);
+uint32 FillItemArmor(uint32 itemlevel, uint32 itemClass, uint32 itemSubclass, uint32 quality, uint32 inventoryType)
+{
+ if (quality > ITEM_QUALITY_ARTIFACT)
+ return 0;
- if (itemTemplate.RequiredReputationFaction)
- {
- if (!sFactionStore.LookupEntry(itemTemplate.RequiredReputationFaction))
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong (not existing) faction in RequiredReputationFaction (%u)", entry, itemTemplate.RequiredReputationFaction);
- itemTemplate.RequiredReputationFaction = 0;
- }
+ // all items but shields
+ if (itemClass != ITEM_CLASS_ARMOR || itemSubclass != ITEM_SUBCLASS_ARMOR_SHIELD)
+ {
+ ItemArmorQualityEntry const* armorQuality = sItemArmorQualityStore.LookupEntry(itemlevel);
+ ItemArmorTotalEntry const* armorTotal = sItemArmorTotalStore.LookupEntry(itemlevel);
+ if (!armorQuality || !armorTotal)
+ return 0;
- if (itemTemplate.RequiredReputationRank == MIN_REPUTATION_RANK)
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has min. reputation rank in RequiredReputationRank (0) but RequiredReputationFaction > 0, faction setting is useless.", entry);
- }
+ if (inventoryType == INVTYPE_ROBE)
+ inventoryType = INVTYPE_CHEST;
- if (itemTemplate.MaxCount < -1)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has too large negative in maxcount (%i), replace by value (-1) no storing limits.", entry, itemTemplate.MaxCount);
- itemTemplate.MaxCount = -1;
- }
+ ArmorLocationEntry const* location = sArmorLocationStore.LookupEntry(inventoryType);
+ if (!location)
+ return 0;
- if (itemTemplate.Stackable == 0)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong value in stackable (%i), replace by default 1.", entry, itemTemplate.Stackable);
- itemTemplate.Stackable = 1;
- }
- else if (itemTemplate.Stackable < -1)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has too large negative in stackable (%i), replace by value (-1) no stacking limits.", entry, itemTemplate.Stackable);
- itemTemplate.Stackable = -1;
- }
+ if (itemSubclass < ITEM_SUBCLASS_ARMOR_CLOTH || itemSubclass > ITEM_SUBCLASS_ARMOR_PLATE)
+ return 0;
- if (itemTemplate.ContainerSlots > MAX_BAG_SIZE)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has too large value in ContainerSlots (%u), replace by hardcoded limit (%u).", entry, itemTemplate.ContainerSlots, MAX_BAG_SIZE);
- itemTemplate.ContainerSlots = MAX_BAG_SIZE;
- }
+ return uint32(armorQuality->Value[quality] * armorTotal->Value[itemSubclass - 1] * location->Value[itemSubclass - 1] + 0.5f);
+ }
- if (itemTemplate.StatsCount > MAX_ITEM_PROTO_STATS)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has too large value in statscount (%u), replace by hardcoded limit (%u).", entry, itemTemplate.StatsCount, MAX_ITEM_PROTO_STATS);
- itemTemplate.StatsCount = MAX_ITEM_PROTO_STATS;
- }
+ // shields
+ ItemArmorShieldEntry const* shield = sItemArmorShieldStore.LookupEntry(itemlevel);
+ if (!shield)
+ return 0;
- for (uint8 j = 0; j < itemTemplate.StatsCount; ++j)
- {
- // for ItemStatValue != 0
- if (itemTemplate.ItemStat[j].ItemStatValue && itemTemplate.ItemStat[j].ItemStatType >= MAX_ITEM_MOD)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong (non-existing?) stat_type%d (%u)", entry, j+1, itemTemplate.ItemStat[j].ItemStatType);
- itemTemplate.ItemStat[j].ItemStatType = 0;
- }
+ return uint32(shield->Value[quality] + 0.5f);
+}
- switch (itemTemplate.ItemStat[j].ItemStatType)
- {
- case ITEM_MOD_SPELL_HEALING_DONE:
- case ITEM_MOD_SPELL_DAMAGE_DONE:
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has deprecated stat_type%d (%u)", entry, j+1, itemTemplate.ItemStat[j].ItemStatType);
- break;
- default:
- break;
- }
- }
+uint32 FillMaxDurability(uint32 itemClass, uint32 itemSubClass, uint32 inventoryType, uint32 quality, uint32 itemLevel)
+{
+ if (itemClass != ITEM_CLASS_ARMOR && itemClass != ITEM_CLASS_WEAPON)
+ return 0;
- for (uint8 j = 0; j < MAX_ITEM_PROTO_DAMAGES; ++j)
- {
- if (itemTemplate.Damage[j].DamageType >= MAX_SPELL_SCHOOL)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong dmg_type%d (%u)", entry, j+1, itemTemplate.Damage[j].DamageType);
- itemTemplate.Damage[j].DamageType = 0;
- }
- }
+ static float const qualityMultipliers[MAX_ITEM_QUALITY] =
+ {
+ 1.0f, 1.0f, 1.0f, 1.17f, 1.37f, 1.68f, 0.0f, 0.0f
+ };
- // special format
- if ((itemTemplate.Spells[0].SpellId == 483) || (itemTemplate.Spells[0].SpellId == 55884))
- {
- // spell_1
- if (itemTemplate.Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format", entry, 0+1, itemTemplate.Spells[0].SpellTrigger);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[0].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
+ static float const armorMultipliers[MAX_INVTYPE] =
+ {
+ 0.00f, // INVTYPE_NON_EQUIP
+ 0.59f, // INVTYPE_HEAD
+ 0.00f, // INVTYPE_NECK
+ 0.59f, // INVTYPE_SHOULDERS
+ 0.00f, // INVTYPE_BODY
+ 1.00f, // INVTYPE_CHEST
+ 0.35f, // INVTYPE_WAIST
+ 0.75f, // INVTYPE_LEGS
+ 0.49f, // INVTYPE_FEET
+ 0.35f, // INVTYPE_WRISTS
+ 0.35f, // INVTYPE_HANDS
+ 0.00f, // INVTYPE_FINGER
+ 0.00f, // INVTYPE_TRINKET
+ 0.00f, // INVTYPE_WEAPON
+ 1.00f, // INVTYPE_SHIELD
+ 0.00f, // INVTYPE_RANGED
+ 0.00f, // INVTYPE_CLOAK
+ 0.00f, // INVTYPE_2HWEAPON
+ 0.00f, // INVTYPE_BAG
+ 0.00f, // INVTYPE_TABARD
+ 1.00f, // INVTYPE_ROBE
+ 0.00f, // INVTYPE_WEAPONMAINHAND
+ 0.00f, // INVTYPE_WEAPONOFFHAND
+ 0.00f, // INVTYPE_HOLDABLE
+ 0.00f, // INVTYPE_AMMO
+ 0.00f, // INVTYPE_THROWN
+ 0.00f, // INVTYPE_RANGEDRIGHT
+ 0.00f, // INVTYPE_QUIVER
+ 0.00f, // INVTYPE_RELIC
+ };
- // spell_2 have learning spell
- if (itemTemplate.Spells[1].SpellTrigger != ITEM_SPELLTRIGGER_LEARN_SPELL_ID)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format.", entry, 1+1, itemTemplate.Spells[1].SpellTrigger);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- else if (!itemTemplate.Spells[1].SpellId)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not have an expected spell in spellid_%d in special learning format.", entry, 1+1);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- else if (itemTemplate.Spells[1].SpellId != -1)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[1].SpellId);
- if (!spellInfo && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[1].SpellId, NULL))
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%d)", entry, 1+1, itemTemplate.Spells[1].SpellId);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- // allowed only in special format
- else if ((itemTemplate.Spells[1].SpellId == 483) || (itemTemplate.Spells[1].SpellId == 55884))
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has broken spell in spellid_%d (%d)", entry, 1+1, itemTemplate.Spells[1].SpellId);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- }
+ static float const weaponMultipliers[MAX_ITEM_SUBCLASS_WEAPON] =
+ {
+ 0.89f, // ITEM_SUBCLASS_WEAPON_AXE
+ 1.03f, // ITEM_SUBCLASS_WEAPON_AXE2
+ 0.77f, // ITEM_SUBCLASS_WEAPON_BOW
+ 0.77f, // ITEM_SUBCLASS_WEAPON_GUN
+ 0.89f, // ITEM_SUBCLASS_WEAPON_MACE
+ 1.03f, // ITEM_SUBCLASS_WEAPON_MACE2
+ 1.03f, // ITEM_SUBCLASS_WEAPON_POLEARM
+ 0.89f, // ITEM_SUBCLASS_WEAPON_SWORD
+ 1.03f, // ITEM_SUBCLASS_WEAPON_SWORD2
+ 0.00f, // ITEM_SUBCLASS_WEAPON_Obsolete
+ 1.03f, // ITEM_SUBCLASS_WEAPON_STAFF
+ 0.00f, // ITEM_SUBCLASS_WEAPON_EXOTIC
+ 0.00f, // ITEM_SUBCLASS_WEAPON_EXOTIC2
+ 0.64f, // ITEM_SUBCLASS_WEAPON_FIST_WEAPON
+ 0.00f, // ITEM_SUBCLASS_WEAPON_MISCELLANEOUS
+ 0.64f, // ITEM_SUBCLASS_WEAPON_DAGGER
+ 0.64f, // ITEM_SUBCLASS_WEAPON_THROWN
+ 0.00f, // ITEM_SUBCLASS_WEAPON_SPEAR
+ 0.77f, // ITEM_SUBCLASS_WEAPON_CROSSBOW
+ 0.64f, // ITEM_SUBCLASS_WEAPON_WAND
+ 0.64f, // ITEM_SUBCLASS_WEAPON_FISHING_POLE
+ };
- // spell_3*, spell_4*, spell_5* is empty
- for (uint8 j = 2; j < MAX_ITEM_PROTO_SPELLS; ++j)
- {
- if (itemTemplate.Spells[j].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)", entry, j+1, itemTemplate.Spells[j].SpellTrigger);
- itemTemplate.Spells[j].SpellId = 0;
- itemTemplate.Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- else if (itemTemplate.Spells[j].SpellId != 0)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong spell in spellid_%d (%d) for learning special format", entry, j+1, itemTemplate.Spells[j].SpellId);
- itemTemplate.Spells[j].SpellId = 0;
- }
- }
- }
- // normal spell list
- else
- {
- for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j)
- {
- if (itemTemplate.Spells[j].SpellTrigger >= MAX_ITEM_SPELLTRIGGER || itemTemplate.Spells[j].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)", entry, j+1, itemTemplate.Spells[j].SpellTrigger);
- itemTemplate.Spells[j].SpellId = 0;
- itemTemplate.Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
+ float levelPenalty = 1.0f;
+ if (itemLevel <= 28)
+ levelPenalty = 0.966f - float(28u - itemLevel) / 54.0f;
- if (itemTemplate.Spells[j].SpellId && itemTemplate.Spells[j].SpellId != -1)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[j].SpellId);
- if (!spellInfo && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[j].SpellId, NULL))
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%d)", entry, j+1, itemTemplate.Spells[j].SpellId);
- itemTemplate.Spells[j].SpellId = 0;
- }
- // allowed only in special format
- else if ((itemTemplate.Spells[j].SpellId == 483) || (itemTemplate.Spells[j].SpellId == 55884))
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has broken spell in spellid_%d (%d)", entry, j+1, itemTemplate.Spells[j].SpellId);
- itemTemplate.Spells[j].SpellId = 0;
- }
- }
- }
- }
+ if (itemClass == ITEM_CLASS_ARMOR)
+ {
+ if (inventoryType > INVTYPE_ROBE)
+ return 0;
- if (itemTemplate.Bonding >= MAX_BIND_TYPE)
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong Bonding value (%u)", entry, itemTemplate.Bonding);
+ return 5 * uint32(23.0f * qualityMultipliers[quality] * armorMultipliers[inventoryType] * levelPenalty + 0.5f);
+ }
- if (itemTemplate.PageText && !GetPageText(itemTemplate.PageText))
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has non existing first page (Id:%u)", entry, itemTemplate.PageText);
+ return 5 * uint32(17.0f * qualityMultipliers[quality] * weaponMultipliers[itemSubClass] * levelPenalty + 0.5f);
+};
- if (itemTemplate.LockID && !sLockStore.LookupEntry(itemTemplate.LockID))
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong LockID (%u)", entry, itemTemplate.LockID);
+void FillDisenchantFields(uint32* disenchantID, uint32* requiredDisenchantSkill, ItemTemplate const& itemTemplate)
+{
+ *disenchantID = 0;
+ *(int32*)requiredDisenchantSkill = -1;
+ if ((itemTemplate.Flags & (ITEM_PROTO_FLAG_CONJURED | ITEM_PROTO_FLAG_UNK6)) ||
+ itemTemplate.Bonding == BIND_QUEST_ITEM || itemTemplate.Area || itemTemplate.Map ||
+ itemTemplate.Stackable > 1 ||
+ itemTemplate.Quality < ITEM_QUALITY_UNCOMMON || itemTemplate.Quality > ITEM_QUALITY_EPIC ||
+ !(itemTemplate.Class == ITEM_CLASS_ARMOR || itemTemplate.Class == ITEM_CLASS_WEAPON) ||
+ !(Item::GetSpecialPrice(&itemTemplate) || sItemCurrencyCostStore.LookupEntry(itemTemplate.ItemId)))
+ return;
- if (itemTemplate.Sheath >= MAX_SHEATHETYPE)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong Sheath (%u)", entry, itemTemplate.Sheath);
- itemTemplate.Sheath = SHEATHETYPE_NONE;
- }
+ for (uint32 i = 0; i < sItemDisenchantLootStore.GetNumRows(); ++i)
+ {
+ ItemDisenchantLootEntry const* disenchant = sItemDisenchantLootStore.LookupEntry(i);
+ if (!disenchant)
+ continue;
- if (itemTemplate.RandomProperty)
+ if (disenchant->ItemClass == itemTemplate.Class &&
+ disenchant->ItemQuality == itemTemplate.Quality &&
+ disenchant->MinItemLevel <= itemTemplate.ItemLevel &&
+ disenchant->MaxItemLevel >= itemTemplate.ItemLevel)
{
- // To be implemented later
- if (itemTemplate.RandomProperty == -1)
- itemTemplate.RandomProperty = 0;
-
- else if (!sItemRandomPropertiesStore.LookupEntry(GetItemEnchantMod(itemTemplate.RandomProperty)))
+ if (disenchant->Id == 60 || disenchant->Id == 61) // epic item disenchant ilvl range 66-99 (classic)
{
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has unknown (wrong or not listed in `item_enchantment_template`) RandomProperty (%u)", entry, itemTemplate.RandomProperty);
- itemTemplate.RandomProperty = 0;
+ if (itemTemplate.RequiredLevel > 60 || itemTemplate.RequiredSkillRank > 300)
+ continue; // skip to epic item disenchant ilvl range 90-199 (TBC)
}
- }
-
- if (itemTemplate.RandomSuffix && !sItemRandomSuffixStore.LookupEntry(GetItemEnchantMod(itemTemplate.RandomSuffix)))
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong RandomSuffix (%u)", entry, itemTemplate.RandomSuffix);
- itemTemplate.RandomSuffix = 0;
- }
-
- if (itemTemplate.ItemSet && !sItemSetStore.LookupEntry(itemTemplate.ItemSet))
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) have wrong ItemSet (%u)", entry, itemTemplate.ItemSet);
- itemTemplate.ItemSet = 0;
- }
-
- if (itemTemplate.Area && !GetAreaEntryByAreaID(itemTemplate.Area))
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong Area (%u)", entry, itemTemplate.Area);
-
- if (itemTemplate.Map && !sMapStore.LookupEntry(itemTemplate.Map))
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong Map (%u)", entry, itemTemplate.Map);
-
- if (itemTemplate.BagFamily)
- {
- // check bits
- for (uint32 j = 0; j < sizeof(itemTemplate.BagFamily)*8; ++j)
+ else if (disenchant->Id == 66 || disenchant->Id == 67) // epic item disenchant ilvl range 90-199 (TBC)
{
- uint32 mask = 1 << j;
- if ((itemTemplate.BagFamily & mask) == 0)
+ if (itemTemplate.RequiredLevel <= 60 || (itemTemplate.RequiredSkill && itemTemplate.RequiredSkillRank <= 300))
continue;
-
- ItemBagFamilyEntry const* bf = sItemBagFamilyStore.LookupEntry(j+1);
- if (!bf)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has bag family bit set not listed in ItemBagFamily.dbc, remove bit", entry);
- itemTemplate.BagFamily &= ~mask;
- continue;
- }
-
- if (BAG_FAMILY_MASK_CURRENCY_TOKENS & mask)
- {
- CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemTemplate.ItemId);
- if (!ctEntry)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has currency bag family bit set in BagFamily but not listed in CurrencyTypes.dbc, remove bit", entry);
- itemTemplate.BagFamily &= ~mask;
- }
- }
}
- }
-
- if (itemTemplate.TotemCategory && !sTotemCategoryStore.LookupEntry(itemTemplate.TotemCategory))
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong TotemCategory (%u)", entry, itemTemplate.TotemCategory);
- for (uint8 j = 0; j < MAX_ITEM_PROTO_SOCKETS; ++j)
- {
- if (itemTemplate.Socket[j].Color && (itemTemplate.Socket[j].Color & SOCKET_COLOR_ALL) != itemTemplate.Socket[j].Color)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong socketColor_%d (%u)", entry, j+1, itemTemplate.Socket[j].Color);
- itemTemplate.Socket[j].Color = 0;
- }
+ *disenchantID = disenchant->Id;
+ *requiredDisenchantSkill = disenchant->RequiredDisenchantSkill;
+ return;
}
+ }
+}
- if (itemTemplate.GemProperties && !sGemPropertiesStore.LookupEntry(itemTemplate.GemProperties))
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong GemProperties (%u)", entry, itemTemplate.GemProperties);
-
- if (itemTemplate.FoodType >= MAX_PET_DIET)
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong FoodType value (%u)", entry, itemTemplate.FoodType);
- itemTemplate.FoodType = 0;
- }
+void ObjectMgr::LoadItemTemplates()
+{
+ uint32 oldMSTime = getMSTime();
+ uint32 sparseCount = 0;
+ uint32 dbCount = 0;
- if (itemTemplate.ItemLimitCategory && !sItemLimitCategoryStore.LookupEntry(itemTemplate.ItemLimitCategory))
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong LimitCategory value (%u)", entry, itemTemplate.ItemLimitCategory);
- itemTemplate.ItemLimitCategory = 0;
- }
+ for (uint32 itemId = 0; itemId < sItemSparseStore.GetNumRows(); ++itemId)
+ {
+ ItemSparseEntry const* sparse = sItemSparseStore.LookupEntry(itemId);
+ ItemEntry const* db2Data = sItemStore.LookupEntry(itemId);
+ if (!sparse || !db2Data)
+ continue;
- if (itemTemplate.HolidayId && !sHolidaysStore.LookupEntry(itemTemplate.HolidayId))
- {
- TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong HolidayId value (%u)", entry, itemTemplate.HolidayId);
- itemTemplate.HolidayId = 0;
- }
+ ItemTemplate& itemTemplate = _itemTemplateStore[itemId];
+
+ itemTemplate.ItemId = itemId;
+ itemTemplate.Class = db2Data->Class;
+ itemTemplate.SubClass = db2Data->SubClass;
+ itemTemplate.SoundOverrideSubclass = db2Data->SoundOverrideSubclass;
+ itemTemplate.Name1 = sparse->Name->Str[sWorld->GetDefaultDbcLocale()];
+ itemTemplate.DisplayInfoID = db2Data->DisplayId;
+ itemTemplate.Quality = sparse->Quality;
+ itemTemplate.Flags = sparse->Flags;
+ itemTemplate.Flags2 = sparse->Flags2;
+ itemTemplate.Unk430_1 = sparse->Unk430_1;
+ itemTemplate.Unk430_2 = sparse->Unk430_2;
+ itemTemplate.BuyCount = std::max(sparse->BuyCount, 1u);
+ itemTemplate.BuyPrice = sparse->BuyPrice;
+ itemTemplate.SellPrice = sparse->SellPrice;
+ itemTemplate.InventoryType = db2Data->InventoryType;
+ itemTemplate.AllowableClass = sparse->AllowableClass;
+ itemTemplate.AllowableRace = sparse->AllowableRace;
+ itemTemplate.ItemLevel = sparse->ItemLevel;
+ itemTemplate.RequiredLevel = sparse->RequiredLevel;
+ itemTemplate.RequiredSkill = sparse->RequiredSkill;
+ itemTemplate.RequiredSkillRank = sparse->RequiredSkillRank;
+ itemTemplate.RequiredSpell = sparse->RequiredSpell;
+ itemTemplate.RequiredHonorRank = sparse->RequiredHonorRank;
+ itemTemplate.RequiredCityRank = sparse->RequiredCityRank;
+ itemTemplate.RequiredReputationFaction = sparse->RequiredReputationFaction;
+ itemTemplate.RequiredReputationRank = sparse->RequiredReputationRank;
+ itemTemplate.MaxCount = sparse->MaxCount;
+ itemTemplate.Stackable = sparse->Stackable;
+ itemTemplate.ContainerSlots = sparse->ContainerSlots;
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ {
+ itemTemplate.ItemStat[i].ItemStatType = sparse->ItemStatType[i];
+ itemTemplate.ItemStat[i].ItemStatValue = sparse->ItemStatValue[i];
+ itemTemplate.ItemStat[i].ItemStatUnk1 = sparse->ItemStatUnk1[i];
+ itemTemplate.ItemStat[i].ItemStatUnk2 = sparse->ItemStatUnk2[i];
+ }
+
+ itemTemplate.ScalingStatDistribution = sparse->ScalingStatDistribution;
+
+ // cache item damage
+ FillItemDamageFields(&itemTemplate.DamageMin, &itemTemplate.DamageMax, &itemTemplate.DPS, sparse->ItemLevel,
+ db2Data->Class, db2Data->SubClass, sparse->Quality, sparse->Delay, sparse->StatScalingFactor,
+ sparse->InventoryType, sparse->Flags2);
+
+ itemTemplate.DamageType = sparse->DamageType;
+ itemTemplate.Armor = FillItemArmor(sparse->ItemLevel, db2Data->Class, db2Data->SubClass, sparse->Quality, sparse->InventoryType);
+ itemTemplate.Delay = sparse->Delay;
+ itemTemplate.RangedModRange = sparse->RangedModRange;
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
+ {
+ itemTemplate.Spells[i].SpellId = sparse->SpellId[i];
+ itemTemplate.Spells[i].SpellTrigger = sparse->SpellTrigger[i];
+ itemTemplate.Spells[i].SpellCharges = sparse->SpellCharges[i];
+ itemTemplate.Spells[i].SpellCooldown = sparse->SpellCooldown[i];
+ itemTemplate.Spells[i].SpellCategory = sparse->SpellCategory[i];
+ itemTemplate.Spells[i].SpellCategoryCooldown = sparse->SpellCategoryCooldown[i];
+ }
+
+ itemTemplate.SpellPPMRate = 0.0f;
+ itemTemplate.Bonding = sparse->Bonding;
+ itemTemplate.Description = sparse->Description->Str[sWorld->GetDefaultDbcLocale()];
+ itemTemplate.PageText = sparse->PageText;
+ itemTemplate.LanguageID = sparse->LanguageID;
+ itemTemplate.PageMaterial = sparse->PageMaterial;
+ itemTemplate.StartQuest = sparse->StartQuest;
+ itemTemplate.LockID = sparse->LockID;
+ itemTemplate.Material = sparse->Material;
+ itemTemplate.Sheath = sparse->Sheath;
+ itemTemplate.RandomProperty = sparse->RandomProperty;
+ itemTemplate.RandomSuffix = sparse->RandomSuffix;
+ itemTemplate.ItemSet = sparse->ItemSet;
+ itemTemplate.MaxDurability = FillMaxDurability(db2Data->Class, db2Data->SubClass, sparse->InventoryType, sparse->Quality, sparse->ItemLevel);
+ itemTemplate.Area = sparse->Area;
+ itemTemplate.Map = sparse->Map;
+ itemTemplate.BagFamily = sparse->BagFamily;
+ itemTemplate.TotemCategory = sparse->TotemCategory;
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
+ {
+ itemTemplate.Socket[i].Color = sparse->Color[i];
+ itemTemplate.Socket[i].Content = sparse->Content[i];
+ }
+
+ itemTemplate.socketBonus = sparse->SocketBonus;
+ itemTemplate.GemProperties = sparse->GemProperties;
+ FillDisenchantFields(&itemTemplate.DisenchantID, &itemTemplate.RequiredDisenchantSkill, itemTemplate);
+
+ itemTemplate.ArmorDamageModifier = sparse->ArmorDamageModifier;
+ itemTemplate.Duration = sparse->Duration;
+ itemTemplate.ItemLimitCategory = sparse->ItemLimitCategory;
+ itemTemplate.HolidayId = sparse->HolidayId;
+ itemTemplate.StatScalingFactor = sparse->StatScalingFactor;
+ itemTemplate.CurrencySubstitutionId = sparse->CurrencySubstitutionId;
+ itemTemplate.CurrencySubstitutionCount = sparse->CurrencySubstitutionCount;
+ itemTemplate.ScriptId = 0;
+ itemTemplate.FoodType = 0;
+ itemTemplate.MinMoneyLoot = 0;
+ itemTemplate.MaxMoneyLoot = 0;
+ ++sparseCount;
+ }
+
+ // Load missing items from item_template AND overwrite data from Item-sparse.db2 (item_template is supposed to contain Item-sparse.adb data)
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
+ QueryResult result = WorldDatabase.Query("SELECT entry, Class, SubClass, SoundOverrideSubclass, Name, DisplayId, Quality, Flags, FlagsExtra, Unk430_1, Unk430_2, BuyCount, BuyPrice, SellPrice, "
+ // 14 15 16 17 18 19 20 21
+ "InventoryType, AllowableClass, AllowableRace, ItemLevel, RequiredLevel, RequiredSkill, RequiredSkillRank, RequiredSpell, "
+ // 22 23 24 25 26 27 28
+ "RequiredHonorRank, RequiredCityRank, RequiredReputationFaction, RequiredReputationRank, MaxCount, Stackable, ContainerSlots, "
+ // 29 30 31 32 33 34 35 36
+ "stat_type1, stat_value1, stat_unk1_1, stat_unk2_1, stat_type2, stat_value2, stat_unk1_2, stat_unk2_2, "
+ // 37 38 39 40 41 42 43 44
+ "stat_type3, stat_value3, stat_unk1_3, stat_unk2_3, stat_type4, stat_value4, stat_unk1_4, stat_unk2_4, "
+ // 45 46 47 48 49 50 51 52
+ "stat_type5, stat_value5, stat_unk1_5, stat_unk2_5, stat_type6, stat_value6, stat_unk1_6, stat_unk2_6, "
+ // 53 54 55 56 57 58 59 60
+ "stat_type7, stat_value7, stat_unk1_7, stat_unk2_7, stat_type8, stat_value8, stat_unk1_8, stat_unk2_8, "
+ // 61 62 63 64 65 66 67 68
+ "stat_type9, stat_value9, stat_unk1_9, stat_unk2_9, stat_type10, stat_value10, stat_unk1_10, stat_unk2_10, "
+ // 69 70 71 72
+ "ScalingStatDistribution, DamageType, Delay, RangedModRange, "
+ // 73 74 75 76 77 78
+ "spellid_1, spelltrigger_1, spellcharges_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, "
+ // 79 80 81 82 83 84
+ "spellid_2, spelltrigger_2, spellcharges_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, "
+ // 85 86 87 88 89 90
+ "spellid_3, spelltrigger_3, spellcharges_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, "
+ // 91 92 93 94 95 96
+ "spellid_4, spelltrigger_4, spellcharges_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, "
+ // 97 98 99 100 101 102
+ "spellid_5, spelltrigger_5, spellcharges_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, "
+ // 103 104 105 106 107 108 109 110
+ "Bonding, Description, PageText, LanguageID, PageMaterial, StartQuest, LockID, Material, "
+ // 111 112 113 114 115 116 117 118
+ "Sheath, RandomProperty, RandomSuffix, ItemSet, Area, Map, BagFamily, TotemCategory, "
+ // 119 120 121 122 123 124 125
+ "SocketColor_1, SocketContent_1, SocketColor_2, SocketContent_2, SocketColor_3, SocketContent_3, SocketBonus, "
+ // 126 127 128 129 130 131
+ "GemProperties, ArmorDamageModifier, Duration, ItemLimitCategory, HolidayId, StatScalingFactor, "
+ // 132 133
+ "CurrencySubstitutionId, CurrencySubstitutionCount "
+ "FROM item_template");
- if (itemTemplate.FlagsCu & ITEM_FLAGS_CU_DURATION_REAL_TIME && !itemTemplate.Duration)
+ if (result)
+ {
+ do
{
- TC_LOG_ERROR("sql.sql", "Item (Entry %u) has flag ITEM_FLAGS_CU_DURATION_REAL_TIME but it does not have duration limit", entry);
- itemTemplate.FlagsCu &= ~ITEM_FLAGS_CU_DURATION_REAL_TIME;
- }
-
- ++count;
+ Field* fields = result->Fetch();
+ uint32 itemId = fields[0].GetUInt32();
+ if (_itemTemplateStore.find(itemId) != _itemTemplateStore.end())
+ --sparseCount;
+
+ ItemTemplate& itemTemplate = _itemTemplateStore[itemId];
+
+ itemTemplate.ItemId = itemId;
+ itemTemplate.Class = uint32(fields[1].GetUInt8());
+ itemTemplate.SubClass = uint32(fields[2].GetUInt8());
+ itemTemplate.SoundOverrideSubclass = fields[3].GetInt32();
+ itemTemplate.Name1 = fields[4].GetString();
+ itemTemplate.DisplayInfoID = fields[5].GetUInt32();
+ itemTemplate.Quality = uint32(fields[6].GetUInt8());
+ itemTemplate.Flags = fields[7].GetUInt32();
+ itemTemplate.Flags2 = fields[8].GetUInt32();
+ itemTemplate.Unk430_1 = fields[9].GetFloat();
+ itemTemplate.Unk430_2 = fields[10].GetFloat();
+ itemTemplate.BuyCount = uint32(fields[11].GetUInt8());
+ itemTemplate.BuyPrice = int32(fields[12].GetInt64());
+ itemTemplate.SellPrice = fields[13].GetUInt32();
+
+ itemTemplate.InventoryType = uint32(fields[14].GetUInt8());
+ itemTemplate.AllowableClass = fields[15].GetInt32();
+ itemTemplate.AllowableRace = fields[16].GetInt32();
+ itemTemplate.ItemLevel = uint32(fields[17].GetUInt16());
+ itemTemplate.RequiredLevel = uint32(fields[18].GetUInt8());
+ itemTemplate.RequiredSkill = uint32(fields[19].GetUInt16());
+ itemTemplate.RequiredSkillRank = uint32(fields[20].GetUInt16());
+ itemTemplate.RequiredSpell = fields[21].GetUInt32();
+ itemTemplate.RequiredHonorRank = fields[22].GetUInt32();
+ itemTemplate.RequiredCityRank = fields[23].GetUInt32();
+ itemTemplate.RequiredReputationFaction = uint32(fields[24].GetUInt16());
+ itemTemplate.RequiredReputationRank = uint32(fields[25].GetUInt16());
+ itemTemplate.MaxCount = fields[26].GetInt32();
+ itemTemplate.Stackable = fields[27].GetInt32();
+ itemTemplate.ContainerSlots = uint32(fields[28].GetUInt8());
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ {
+ itemTemplate.ItemStat[i].ItemStatType = uint32(fields[29 + i * 4 + 0].GetUInt8());
+ itemTemplate.ItemStat[i].ItemStatValue = int32(fields[29 + i * 4 + 1].GetInt16());
+ itemTemplate.ItemStat[i].ItemStatUnk1 = fields[29 + i * 4 + 2].GetInt32();
+ itemTemplate.ItemStat[i].ItemStatUnk2 = fields[29 + i * 4 + 3].GetInt32();
+ }
+
+ itemTemplate.ScalingStatDistribution = uint32(fields[69].GetUInt16());
+
+ // cache item damage
+ FillItemDamageFields(&itemTemplate.DamageMin, &itemTemplate.DamageMax, &itemTemplate.DPS, itemTemplate.ItemLevel,
+ itemTemplate.Class, itemTemplate.SubClass, itemTemplate.Quality, fields[71].GetUInt16(),
+ fields[131].GetFloat(), itemTemplate.InventoryType, itemTemplate.Flags2);
+
+ itemTemplate.DamageType = fields[70].GetUInt8();
+ itemTemplate.Armor = FillItemArmor(itemTemplate.ItemLevel, itemTemplate.Class,
+ itemTemplate.SubClass, itemTemplate.Quality,
+ itemTemplate.InventoryType);
+
+ itemTemplate.Delay = fields[71].GetUInt16();
+ itemTemplate.RangedModRange = fields[72].GetFloat();
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
+ {
+ itemTemplate.Spells[i].SpellId = fields[73 + 6 * i + 0].GetInt32();
+ itemTemplate.Spells[i].SpellTrigger = uint32(fields[73 + 6 * i + 1].GetUInt8());
+ itemTemplate.Spells[i].SpellCharges = int32(fields[73 + 6 * i + 2].GetInt16());
+ itemTemplate.Spells[i].SpellCooldown = fields[73 + 6 * i + 3].GetInt32();
+ itemTemplate.Spells[i].SpellCategory = uint32(fields[73 + 6 * i + 4].GetUInt16());
+ itemTemplate.Spells[i].SpellCategoryCooldown = fields[73 + 6 * i + 5].GetInt32();
+ }
+
+ itemTemplate.SpellPPMRate = 0.0f;
+ itemTemplate.Bonding = uint32(fields[103].GetUInt8());
+ itemTemplate.Description = fields[104].GetString();
+ itemTemplate.PageText = fields[105].GetUInt32();
+ itemTemplate.LanguageID = uint32(fields[106].GetUInt8());
+ itemTemplate.PageMaterial = uint32(fields[107].GetUInt8());
+ itemTemplate.StartQuest = fields[108].GetUInt32();
+ itemTemplate.LockID = fields[109].GetUInt32();
+ itemTemplate.Material = int32(fields[110].GetInt8());
+ itemTemplate.Sheath = uint32(fields[111].GetUInt8());
+ itemTemplate.RandomProperty = fields[112].GetUInt32();
+ itemTemplate.RandomSuffix = fields[113].GetInt32();
+ itemTemplate.ItemSet = fields[114].GetUInt32();
+ itemTemplate.MaxDurability = FillMaxDurability(itemTemplate.Class, itemTemplate.SubClass,
+ itemTemplate.InventoryType, itemTemplate.Quality, itemTemplate.ItemLevel);
+
+ itemTemplate.Area = fields[115].GetUInt32();
+ itemTemplate.Map = uint32(fields[116].GetUInt16());
+ itemTemplate.BagFamily = fields[117].GetUInt32();
+ itemTemplate.TotemCategory = fields[118].GetUInt32();
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
+ {
+ itemTemplate.Socket[i].Color = uint32(fields[119 + i*2].GetUInt8());
+ itemTemplate.Socket[i].Content = fields[119 + i * 2 + 1].GetUInt32();
+ }
+
+ itemTemplate.socketBonus = fields[125].GetUInt32();
+ itemTemplate.GemProperties = fields[126].GetUInt32();
+ FillDisenchantFields(&itemTemplate.DisenchantID, &itemTemplate.RequiredDisenchantSkill, itemTemplate);
+
+ itemTemplate.ArmorDamageModifier = fields[127].GetFloat();
+ itemTemplate.Duration = fields[128].GetUInt32();
+ itemTemplate.ItemLimitCategory = uint32(fields[129].GetInt16());
+ itemTemplate.HolidayId = fields[130].GetUInt32();
+ itemTemplate.StatScalingFactor = fields[131].GetFloat();
+ itemTemplate.CurrencySubstitutionId = fields[132].GetInt32();
+ itemTemplate.CurrencySubstitutionCount = fields[133].GetInt32();
+ itemTemplate.ScriptId = 0;
+ itemTemplate.FoodType = 0;
+ itemTemplate.MinMoneyLoot = 0;
+ itemTemplate.MaxMoneyLoot = 0;
+ ++dbCount;
+ } while (result->NextRow());
}
- while (result->NextRow());
// Check if item templates for DBC referenced character start outfit are present
std::set<uint32> notFoundOutfit;
@@ -2810,124 +2785,77 @@ void ObjectMgr::LoadItemTemplates()
for (std::set<uint32>::const_iterator itr = notFoundOutfit.begin(); itr != notFoundOutfit.end(); ++itr)
TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not exist in `item_template` but is referenced in `CharStartOutfit.dbc`", *itr);
- TC_LOG_INFO("server.loading", ">> Loaded %u item templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded %u item templates from Item-sparse.db2 and %u from database in %u ms", sparseCount, dbCount, GetMSTimeDiffToNow(oldMSTime));
}
-ItemTemplate const* ObjectMgr::GetItemTemplate(uint32 entry)
-{
- ItemTemplateContainer::const_iterator itr = _itemTemplateStore.find(entry);
- if (itr != _itemTemplateStore.end())
- return &(itr->second);
-
- return NULL;
-}
-
-void ObjectMgr::LoadItemSetNameLocales()
+void ObjectMgr::LoadItemTemplateAddon()
{
uint32 oldMSTime = getMSTime();
+ uint32 count = 0;
- _itemSetNameLocaleStore.clear(); // need for reload case
-
- QueryResult result = WorldDatabase.Query("SELECT `entry`, `name_loc1`, `name_loc2`, `name_loc3`, `name_loc4`, `name_loc5`, `name_loc6`, `name_loc7`, `name_loc8` FROM `locales_item_set_names`");
-
- if (!result)
- return;
-
- do
+ QueryResult result = WorldDatabase.Query("SELECT Id, FlagsCu, FoodType, MinMoneyLoot, MaxMoneyLoot, SpellPPMChance FROM item_template_addon");
+ if (result)
{
- Field* fields = result->Fetch();
-
- uint32 entry = fields[0].GetUInt32();
-
- ItemSetNameLocale& data = _itemSetNameLocaleStore[entry];
-
- for (uint8 i = 1; i < TOTAL_LOCALES; ++i)
- AddLocaleString(fields[i].GetString(), LocaleConstant(i), data.Name);
- } while (result->NextRow());
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 itemId = fields[0].GetUInt32();
+ if (!GetItemTemplate(itemId))
+ {
+ TC_LOG_ERROR("sql.sql", "Item %u specified in `item_template_addon` does not exist, skipped.", itemId);
+ continue;
+ }
- TC_LOG_INFO("server.loading", ">> Loaded " UI64FMTD " Item set name locale strings in %u ms", uint64(_itemSetNameLocaleStore.size()), GetMSTimeDiffToNow(oldMSTime));
+ uint32 minMoneyLoot = fields[3].GetUInt32();
+ uint32 maxMoneyLoot = fields[4].GetUInt32();
+ if (minMoneyLoot > maxMoneyLoot)
+ {
+ TC_LOG_ERROR("sql.sql", "Minimum money loot specified in `item_template_addon` for item %u was greater than maximum amount, swapping.", itemId);
+ std::swap(minMoneyLoot, maxMoneyLoot);
+ }
+ ItemTemplate& itemTemplate = _itemTemplateStore[itemId];
+ itemTemplate.FlagsCu = fields[1].GetUInt32();
+ itemTemplate.FoodType = fields[2].GetUInt8();
+ itemTemplate.MinMoneyLoot = minMoneyLoot;
+ itemTemplate.MaxMoneyLoot = maxMoneyLoot;
+ itemTemplate.SpellPPMRate = fields[5].GetFloat();
+ ++count;
+ } while (result->NextRow());
+ }
+ TC_LOG_INFO("server.loading", ">> Loaded %u item addon templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::LoadItemSetNames()
+void ObjectMgr::LoadItemScriptNames()
{
uint32 oldMSTime = getMSTime();
-
- _itemSetNameStore.clear(); // needed for reload case
-
- std::set<uint32> itemSetItems;
-
- // fill item set member ids
- for (uint32 entryId = 0; entryId < sItemSetStore.GetNumRows(); ++entryId)
- {
- ItemSetEntry const* setEntry = sItemSetStore.LookupEntry(entryId);
- if (!setEntry)
- continue;
-
- for (uint32 i = 0; i < MAX_ITEM_SET_ITEMS; ++i)
- if (setEntry->itemId[i])
- itemSetItems.insert(setEntry->itemId[i]);
- }
-
- // 0 1 2
- QueryResult result = WorldDatabase.Query("SELECT `entry`, `name`, `InventoryType` FROM `item_set_names`");
-
- if (!result)
- {
- TC_LOG_INFO("server.loading", ">> Loaded 0 item set names. DB table `item_set_names` is empty.");
- return;
- }
-
- _itemSetNameStore.rehash(result->GetRowCount());
uint32 count = 0;
- do
- {
- Field* fields = result->Fetch();
-
- uint32 entry = fields[0].GetUInt32();
- if (itemSetItems.find(entry) == itemSetItems.end())
- {
- TC_LOG_ERROR("sql.sql", "Item set name (Entry: %u) not found in ItemSet.dbc, data useless.", entry);
- continue;
- }
-
- ItemSetNameEntry &data = _itemSetNameStore[entry];
- data.name = fields[1].GetString();
-
- uint32 invType = fields[2].GetUInt8();
- if (invType >= MAX_INVTYPE)
- {
- TC_LOG_ERROR("sql.sql", "Item set name (Entry: %u) has wrong InventoryType value (%u)", entry, invType);
- invType = INVTYPE_NON_EQUIP;
- }
-
- data.InventoryType = invType;
- itemSetItems.erase(entry);
- ++count;
- } while (result->NextRow());
-
- if (!itemSetItems.empty())
+ QueryResult result = WorldDatabase.Query("SELECT Id, ScriptName FROM item_script_names");
+ if (result)
{
- ItemTemplate const* pProto;
- for (std::set<uint32>::iterator itr = itemSetItems.begin(); itr != itemSetItems.end(); ++itr)
+ do
{
- uint32 entry = *itr;
- // add data from item_template if available
- pProto = sObjectMgr->GetItemTemplate(entry);
- if (pProto)
+ Field* fields = result->Fetch();
+ uint32 itemId = fields[0].GetUInt32();
+ if (!GetItemTemplate(itemId))
{
- TC_LOG_ERROR("sql.sql", "Item set part (Entry: %u) does not have entry in `item_set_names`, adding data from `item_template`.", entry);
- ItemSetNameEntry &data = _itemSetNameStore[entry];
- data.name = pProto->Name1;
- data.InventoryType = pProto->InventoryType;
- ++count;
+ TC_LOG_ERROR("sql.sql", "Item %u specified in `item_script_names` does not exist, skipped.", itemId);
+ continue;
}
- else
- TC_LOG_ERROR("sql.sql", "Item set part (Entry: %u) does not have entry in `item_set_names`, set will not display properly.", entry);
- }
+
+ _itemTemplateStore[itemId].ScriptId = GetScriptId(fields[1].GetCString());
+ ++count;
+ } while (result->NextRow());
}
- TC_LOG_INFO("server.loading", ">> Loaded %u item set names in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded %u item script names in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+ItemTemplate const* ObjectMgr::GetItemTemplate(uint32 entry)
+{
+ ItemTemplateContainer::const_iterator itr = _itemTemplateStore.find(entry);
+ if (itr != _itemTemplateStore.end())
+ return &(itr->second);
+ return NULL;
}
void ObjectMgr::LoadVehicleTemplateAccessories()
@@ -3459,6 +3387,61 @@ void ObjectMgr::LoadPlayerInfo()
}
}
+ // Load playercreate cast spell
+ TC_LOG_INFO("server.loading", "Loading Player Create Cast Spell Data...");
+ {
+ uint32 oldMSTime = getMSTime();
+
+ QueryResult result = WorldDatabase.PQuery("SELECT raceMask, classMask, spell FROM playercreateinfo_cast_spell");
+
+ if (!result)
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 player create cast spells. DB table `playercreateinfo_cast_spell` is empty.");
+ else
+ {
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 raceMask = fields[0].GetUInt32();
+ uint32 classMask = fields[1].GetUInt32();
+ uint32 spellId = fields[2].GetUInt32();
+
+ if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE))
+ {
+ TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_cast_spell` table, ignoring.", raceMask);
+ continue;
+ }
+
+ if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE))
+ {
+ TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_cast_spell` table, ignoring.", classMask);
+ continue;
+ }
+
+ for (uint32 raceIndex = RACE_HUMAN; raceIndex < MAX_RACES; ++raceIndex)
+ {
+ if (raceMask == 0 || ((1 << (raceIndex - 1)) & raceMask))
+ {
+ for (uint32 classIndex = CLASS_WARRIOR; classIndex < MAX_CLASSES; ++classIndex)
+ {
+ if (classMask == 0 || ((1 << (classIndex - 1)) & classMask))
+ {
+ if (PlayerInfo* info = _playerInfo[raceIndex][classIndex])
+ {
+ info->castSpells.push_back(spellId);
+ ++count;
+ }
+ }
+ }
+ }
+ }
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u player create cast spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ }
+ }
+
// Load playercreate actions
TC_LOG_INFO("server.loading", "Loading Player Create Action Data...");
{
@@ -3504,88 +3487,6 @@ void ObjectMgr::LoadPlayerInfo()
}
}
- // Loading levels data (class only dependent)
- TC_LOG_INFO("server.loading", "Loading Player Create Level HP/Mana Data...");
- {
- uint32 oldMSTime = getMSTime();
-
- // 0 1 2 3
- QueryResult result = WorldDatabase.Query("SELECT class, level, basehp, basemana FROM player_classlevelstats");
-
- if (!result)
- {
- TC_LOG_ERROR("server.loading", ">> Loaded 0 level health/mana definitions. DB table `player_classlevelstats` is empty.");
- exit(1);
- }
-
- uint32 count = 0;
-
- do
- {
- Field* fields = result->Fetch();
-
- uint32 current_class = fields[0].GetUInt8();
- if (current_class >= MAX_CLASSES)
- {
- TC_LOG_ERROR("sql.sql", "Wrong class %u in `player_classlevelstats` table, ignoring.", current_class);
- continue;
- }
-
- uint8 current_level = fields[1].GetUInt8(); // Can't be > than STRONG_MAX_LEVEL (hardcoded level maximum) due to var type
- if (current_level > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
- {
- TC_LOG_INFO("misc", "Unused (> MaxPlayerLevel in worldserver.conf) level %u in `player_classlevelstats` table, ignoring.", current_level);
- ++count; // make result loading percent "expected" correct in case disabled detail mode for example.
- continue;
- }
-
- PlayerClassInfo* info = _playerClassInfo[current_class];
- if (!info)
- {
- info = new PlayerClassInfo();
- info->levelInfo = new PlayerClassLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)];
- _playerClassInfo[current_class] = info;
- }
-
- PlayerClassLevelInfo& levelInfo = info->levelInfo[current_level-1];
-
- levelInfo.basehealth = fields[2].GetUInt16();
- levelInfo.basemana = fields[3].GetUInt16();
-
- ++count;
- }
- while (result->NextRow());
-
- // Fill gaps and check integrity
- for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
- {
- // skip non existed classes
- if (!sChrClassesStore.LookupEntry(class_))
- continue;
-
- PlayerClassInfo* pClassInfo = _playerClassInfo[class_];
-
- // fatal error if no level 1 data
- if (!pClassInfo->levelInfo || pClassInfo->levelInfo[0].basehealth == 0)
- {
- TC_LOG_ERROR("sql.sql", "Class %i Level 1 does not have health/mana data!", class_);
- exit(1);
- }
-
- // fill level gaps
- for (uint8 level = 1; level < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); ++level)
- {
- if (pClassInfo->levelInfo[level].basehealth == 0)
- {
- TC_LOG_ERROR("sql.sql", "Class %i Level %i does not have health/mana data. Using stats data of level %i.", class_, level + 1, level);
- pClassInfo->levelInfo[level] = pClassInfo->levelInfo[level - 1];
- }
- }
- }
-
- TC_LOG_INFO("server.loading", ">> Loaded %u level health/mana definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
- }
-
// Loading levels data (class/race dependent)
TC_LOG_INFO("server.loading", "Loading Player Create Level Stats Data...");
{
@@ -3672,6 +3573,10 @@ void ObjectMgr::LoadPlayerInfo()
if (sWorld->getIntConfig(CONFIG_EXPANSION) < EXPANSION_WRATH_OF_THE_LICH_KING && class_ == CLASS_DEATH_KNIGHT)
continue;
+ // skip expansion races if not playing with expansion
+ if (sWorld->getIntConfig(CONFIG_EXPANSION) < EXPANSION_CATACLYSM && (race == RACE_GOBLIN || race == RACE_WORGEN))
+ continue;
+
// fatal error if no level 1 data
if (!info->levelInfo || info->levelInfo[0].stats[0] == 0)
{
@@ -3752,17 +3657,25 @@ void ObjectMgr::LoadPlayerInfo()
}
}
-void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint8 level, PlayerClassLevelInfo* info) const
+void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint8 level, uint32& baseHP, uint32& baseMana) const
{
if (level < 1 || class_ >= MAX_CLASSES)
return;
- PlayerClassInfo const* pInfo = _playerClassInfo[class_];
-
if (level > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
level = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
- *info = pInfo->levelInfo[level-1];
+ GtOCTBaseHPByClassEntry const* hp = sGtOCTBaseHPByClassStore.LookupEntry((class_-1) * GT_MAX_LEVEL + level-1);
+ GtOCTBaseMPByClassEntry const* mp = sGtOCTBaseMPByClassStore.LookupEntry((class_-1) * GT_MAX_LEVEL + level-1);
+
+ if (!hp || !mp)
+ {
+ TC_LOG_ERROR("misc", "Tried to get non-existant Class-Level combination data for base hp/mp. Class %u Level %u", class_, level);
+ return;
+ }
+
+ baseHP = uint32(hp->ratio);
+ baseMana = uint32(mp->ratio);
}
void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, PlayerLevelInfo* info) const
@@ -3874,30 +3787,34 @@ void ObjectMgr::LoadQuests()
"RequiredFactionId1, RequiredFactionId2, RequiredFactionValue1, RequiredFactionValue2, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, "
// 21 22 23 24 25 26 27 28 29 30 31
"PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestIdChain, RewardXPId, RewardOrRequiredMoney, RewardMoneyMaxLevel, RewardSpell, RewardSpellCast, RewardHonor, RewardHonorMultiplier, "
- // 32 33 34 35 36 37 38 39 40 41 42
- "RewardMailTemplateId, RewardMailDelay, SourceItemId, SourceItemCount, SourceSpellId, Flags, SpecialFlags, RewardTitleId, RequiredPlayerKills, RewardTalents, RewardArenaPoints, "
- // 43 44 45 46 47 48 49 50
- "RewardItemId1, RewardItemId2, RewardItemId3, RewardItemId4, RewardItemCount1, RewardItemCount2, RewardItemCount3, RewardItemCount4, "
- // 51 52 53 54 55 56 57 58 59 60 61 62
+ // 32 33 34 35 36 37 38 39 40 41 42 43
+ "RewardMailTemplateId, RewardMailDelay, SourceItemId, SourceItemCount, SourceSpellId, Flags, SpecialFlags, MinimapTargetMark, RewardTitleId, RequiredPlayerKills, RewardTalents, RewardArenaPoints, "
+ // 44 45 46 47 48 49 50 51 52 53 54 55 56
+ "RewardSkillId, RewardSkillPoints, RewardReputationMask, QuestGiverPortrait, QuestTurnInPortrait, RewardItemId1, RewardItemId2, RewardItemId3, RewardItemId4, RewardItemCount1, RewardItemCount2, RewardItemCount3, RewardItemCount4, "
+ // 57 58 59 60 61 62 63 64 65 66 67 68
"RewardChoiceItemId1, RewardChoiceItemId2, RewardChoiceItemId3, RewardChoiceItemId4, RewardChoiceItemId5, RewardChoiceItemId6, RewardChoiceItemCount1, RewardChoiceItemCount2, RewardChoiceItemCount3, RewardChoiceItemCount4, RewardChoiceItemCount5, RewardChoiceItemCount6, "
- // 63 64 65 66 67 68 69 70 71 72
+ // 69 70 71 72 73 74 75 76 77 78
"RewardFactionId1, RewardFactionId2, RewardFactionId3, RewardFactionId4, RewardFactionId5, RewardFactionValueId1, RewardFactionValueId2, RewardFactionValueId3, RewardFactionValueId4, RewardFactionValueId5, "
- // 73 74 75 76 77
+ // 79 80 81 82 83
"RewardFactionValueIdOverride1, RewardFactionValueIdOverride2, RewardFactionValueIdOverride3, RewardFactionValueIdOverride4, RewardFactionValueIdOverride5, "
- // 78 79 80 81
- "PointMapId, PointX, PointY, PointOption, "
- // 82 83 84 85 86 87 88
- "Title, Objectives, Details, EndText, OfferRewardText, RequestItemsText, CompletedText, "
- // 89 90 91 92 93 94 95 96
+ // 84 85 86 87 88 89 90 91 92 93 94
+ "PointMapId, PointX, PointY, PointOption, Title, Objectives, Details, EndText, CompletedText, OfferRewardText, RequestItemsText, "
+ // 95 96 97 98 99 100 101 102
"RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, "
- // 97 98 99 100 101 102 103 104
+ // 103 104 105 106 107 108 109 110
"RequiredSourceItemId1, RequiredSourceItemId2, RequiredSourceItemId3, RequiredSourceItemId4, RequiredSourceItemCount1, RequiredSourceItemCount2, RequiredSourceItemCount3, RequiredSourceItemCount4, "
- // 105 106 107 108 109 110 111 112 113 114 115 116
+ // 111 112 113 114 115 116 117 118 119 120 121 122
"RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6, RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6, "
- // 117 118 119 120 121 122 123 124 125 126 127 128 129
- "Unknown0, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, "
- // 130 131 132 133 134 135 136 137 138 139
- "EmoteOnIncomplete, EmoteOnComplete, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4"
+ // 123 124 125 126 127 128 129 130 131 132 133 134 135
+ "RequiredSpell, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, RewardCurrencyId1, RewardCurrencyId2, RewardCurrencyId3, RewardCurrencyId4, RewardCurrencyCount1, RewardCurrencyCount2, RewardCurrencyCount3, RewardCurrencyCount4, "
+ // 136 137 138 139 140 141 142 143
+ "RequiredCurrencyId1, RequiredCurrencyId2, RequiredCurrencyId3, RequiredCurrencyId4, RequiredCurrencyCount1, RequiredCurrencyCount2, RequiredCurrencyCount3, RequiredCurrencyCount4, "
+ // 144 145 146 147 148 149
+ "QuestGiverTextWindow, QuestGiverTargetName, QuestTurnTextWindow, QuestTurnTargetName, SoundAccept, SoundTurnIn, "
+ // 150 151 152 153 154 155 156 157 158 159
+ "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, EmoteOnIncomplete, EmoteOnComplete, "
+ // 160 161 162 163 164 165 166 167
+ "OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4"
" FROM quest_template");
if (!result)
{
@@ -3925,7 +3842,7 @@ void ObjectMgr::LoadQuests()
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, iter->first, NULL))
continue;
- Quest * qinfo = iter->second;
+ Quest* qinfo = iter->second;
// additional quest integrity checks (GO, creature_template and item_template must be loaded already)
@@ -3986,6 +3903,12 @@ void ObjectMgr::LoadQuests()
}
}
+ if (qinfo->MinLevel == uint32(-1) || qinfo->MinLevel > DEFAULT_MAX_LEVEL)
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u should be disabled because `MinLevel` = %i", qinfo->GetQuestId(), int32(qinfo->MinLevel));
+ // no changes needed, sending -1 in SMSG_QUEST_QUERY_RESPONSE is valid
+ }
+
// client quest log visual (area case)
if (qinfo->ZoneOrSort > 0)
{
@@ -4029,13 +3952,13 @@ void ObjectMgr::LoadQuests()
}
// RequiredRaces, can be 0/RACEMASK_ALL_PLAYABLE to allow any race
if (qinfo->RequiredRaces)
- {
+ {
if (!(qinfo->RequiredRaces & RACEMASK_ALL_PLAYABLE))
{
TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable races in `RequiredRaces` (%u), value set to 0 (all races).", qinfo->GetQuestId(), qinfo->RequiredRaces);
qinfo->RequiredRaces = 0;
}
- }
+ }
// RequiredSkillId, can be 0
if (qinfo->RequiredSkillId)
{
@@ -4195,7 +4118,7 @@ void ObjectMgr::LoadQuests()
qinfo->RequiredItemCount[j] = 0; // prevent incorrect work of quest
}
}
- else if (qinfo->RequiredItemCount[j]>0)
+ else if (qinfo->RequiredItemCount[j] > 0)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredItemId%d` = 0 but `RequiredItemCount%d` = %u, quest can't be done.",
qinfo->GetQuestId(), j+1, j+1, qinfo->RequiredItemCount[j]);
@@ -4427,26 +4350,149 @@ void ObjectMgr::LoadQuests()
qNextItr->second->prevChainQuests.push_back(qinfo->GetQuestId());
}
+ for (uint8 j = 0; j < QUEST_REWARD_CURRENCY_COUNT; ++j)
+ {
+ if (qinfo->RewardCurrencyId[j])
+ {
+ if (qinfo->RewardCurrencyCount[j] == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardCurrencyId%d` = %u but `RewardCurrencyCount%d` = 0, quest can't be done.",
+ qinfo->GetQuestId(), j+1, qinfo->RewardCurrencyId[j], j+1);
+ // no changes, quest can't be done for this requirement
+ }
+
+ if (!sCurrencyTypesStore.LookupEntry(qinfo->RewardCurrencyId[j]))
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardCurrencyId%d` = %u but currency with entry %u does not exist, quest can't be done.",
+ qinfo->GetQuestId(), j+1, qinfo->RewardCurrencyId[j], qinfo->RewardCurrencyId[j]);
+ qinfo->RewardCurrencyCount[j] = 0; // prevent incorrect work of quest
+ }
+ }
+ else if (qinfo->RewardCurrencyCount[j] > 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardCurrencyId%d` = 0 but `RewardCurrencyCount%d` = %u, quest can't be done.",
+ qinfo->GetQuestId(), j+1, j+1, qinfo->RewardCurrencyCount[j]);
+ qinfo->RewardCurrencyCount[j] = 0; // prevent incorrect work of quest
+ }
+ }
+
+ for (uint8 j = 0; j < QUEST_REQUIRED_CURRENCY_COUNT; ++j)
+ {
+ if (qinfo->RequiredCurrencyId[j])
+ {
+ if (qinfo->RequiredCurrencyCount[j] == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredCurrencyId%d` = %u but `RequiredCurrencyCount%d` = 0, quest can't be done.",
+ qinfo->GetQuestId(), j+1, qinfo->RequiredCurrencyId[j], j+1);
+ // no changes, quest can't be done for this requirement
+ }
+
+ if (!sCurrencyTypesStore.LookupEntry(qinfo->RequiredCurrencyId[j]))
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredCurrencyId%d` = %u but currency with entry %u does not exist, quest can't be done.",
+ qinfo->GetQuestId(), j+1, qinfo->RequiredCurrencyId[j], qinfo->RequiredCurrencyId[j]);
+ qinfo->RequiredCurrencyCount[j] = 0; // prevent incorrect work of quest
+ }
+ }
+ else if (qinfo->RequiredCurrencyCount[j] > 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredCurrencyId%d` = 0 but `RequiredCurrencyCount%d` = %u, quest can't be done.",
+ qinfo->GetQuestId(), j+1, j+1, qinfo->RequiredCurrencyCount[j]);
+ qinfo->RequiredCurrencyCount[j] = 0; // prevent incorrect work of quest
+ }
+ }
+
+ if (qinfo->SoundAccept)
+ {
+ if (!sSoundEntriesStore.LookupEntry(qinfo->SoundAccept))
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `SoundAccept` = %u but sound %u does not exist, set to 0.",
+ qinfo->GetQuestId(), qinfo->SoundAccept, qinfo->SoundAccept);
+ qinfo->SoundAccept = 0; // no sound will be played
+ }
+ }
+
+ if (qinfo->SoundTurnIn)
+ {
+ if (!sSoundEntriesStore.LookupEntry(qinfo->SoundTurnIn))
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `SoundTurnIn` = %u but sound %u does not exist, set to 0.",
+ qinfo->GetQuestId(), qinfo->SoundTurnIn, qinfo->SoundTurnIn);
+ qinfo->SoundTurnIn = 0; // no sound will be played
+ }
+ }
+
+ if (qinfo->RequiredSpell > 0)
+ {
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RequiredSpell);
+
+ if (!spellInfo)
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredSpell` = %u but spell %u does not exist, quest will not require a spell.",
+ qinfo->GetQuestId(), qinfo->RequiredSpell, qinfo->RequiredSpell);
+ qinfo->RequiredSpell = 0; // no spell will be required
+ }
+
+ else if (!SpellMgr::IsSpellValid(spellInfo))
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredSpell` = %u but spell %u is broken, quest will not require a spell.",
+ qinfo->GetQuestId(), qinfo->RequiredSpell, qinfo->RequiredSpell);
+ qinfo->RequiredSpell = 0; // no spell will be required
+ }
+
+ /* Can we require talents?
+ else if (GetTalentSpellCost(qinfo->RewardSpellCast))
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u is talent, quest will not have a spell reward.",
+ qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast);
+ qinfo->RewardSpellCast = 0; // no spell will be casted on player
+ }
+ }*/
+ }
+
+ if (qinfo->RewardSkillId)
+ {
+ if (!sSkillLineStore.LookupEntry(qinfo->RewardSkillId))
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSkillId` = %u but this skill does not exist",
+ qinfo->GetQuestId(), qinfo->RewardSkillId);
+ }
+ if (!qinfo->RewardSkillPoints)
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSkillId` = %u but `RewardSkillPoints` is 0",
+ qinfo->GetQuestId(), qinfo->RewardSkillId);
+ }
+ }
+
+ if (qinfo->RewardSkillPoints)
+ {
+ if (qinfo->RewardSkillPoints > sWorld->GetConfigMaxSkillValue())
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSkillPoints` = %u but max possible skill is %u, quest can't be done.",
+ qinfo->GetQuestId(), qinfo->RewardSkillPoints, sWorld->GetConfigMaxSkillValue());
+ // no changes, quest can't be done for this requirement
+ }
+ if (!qinfo->RewardSkillId)
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSkillPoints` = %u but `RewardSkillId` is 0",
+ qinfo->GetQuestId(), qinfo->RewardSkillPoints);
+ }
+ }
+
// fill additional data stores
if (qinfo->PrevQuestId)
{
if (_questTemplates.find(abs(qinfo->GetPrevQuestId())) == _questTemplates.end())
- {
TC_LOG_ERROR("sql.sql", "Quest %d has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId());
- }
else
- {
qinfo->prevQuests.push_back(qinfo->PrevQuestId);
- }
}
if (qinfo->NextQuestId)
{
QuestMap::iterator qNextItr = _questTemplates.find(abs(qinfo->GetNextQuestId()));
if (qNextItr == _questTemplates.end())
- {
TC_LOG_ERROR("sql.sql", "Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId());
- }
else
{
int32 signedQuestId = qinfo->NextQuestId < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId());
@@ -4502,14 +4548,14 @@ void ObjectMgr::LoadQuestLocales()
_questLocaleStore.clear(); // need for reload case
QueryResult result = WorldDatabase.Query("SELECT Id, "
- "Title_loc1, Details_loc1, Objectives_loc1, OfferRewardText_loc1, RequestItemsText_loc1, EndText_loc1, CompletedText_loc1, ObjectiveText1_loc1, ObjectiveText2_loc1, ObjectiveText3_loc1, ObjectiveText4_loc1, "
- "Title_loc2, Details_loc2, Objectives_loc2, OfferRewardText_loc2, RequestItemsText_loc2, EndText_loc2, CompletedText_loc2, ObjectiveText1_loc2, ObjectiveText2_loc2, ObjectiveText3_loc2, ObjectiveText4_loc2, "
- "Title_loc3, Details_loc3, Objectives_loc3, OfferRewardText_loc3, RequestItemsText_loc3, EndText_loc3, CompletedText_loc3, ObjectiveText1_loc3, ObjectiveText2_loc3, ObjectiveText3_loc3, ObjectiveText4_loc3, "
- "Title_loc4, Details_loc4, Objectives_loc4, OfferRewardText_loc4, RequestItemsText_loc4, EndText_loc4, CompletedText_loc4, ObjectiveText1_loc4, ObjectiveText2_loc4, ObjectiveText3_loc4, ObjectiveText4_loc4, "
- "Title_loc5, Details_loc5, Objectives_loc5, OfferRewardText_loc5, RequestItemsText_loc5, EndText_loc5, CompletedText_loc5, ObjectiveText1_loc5, ObjectiveText2_loc5, ObjectiveText3_loc5, ObjectiveText4_loc5, "
- "Title_loc6, Details_loc6, Objectives_loc6, OfferRewardText_loc6, RequestItemsText_loc6, EndText_loc6, CompletedText_loc6, ObjectiveText1_loc6, ObjectiveText2_loc6, ObjectiveText3_loc6, ObjectiveText4_loc6, "
- "Title_loc7, Details_loc7, Objectives_loc7, OfferRewardText_loc7, RequestItemsText_loc7, EndText_loc7, CompletedText_loc7, ObjectiveText1_loc7, ObjectiveText2_loc7, ObjectiveText3_loc7, ObjectiveText4_loc7, "
- "Title_loc8, Details_loc8, Objectives_loc8, OfferRewardText_loc8, RequestItemsText_loc8, EndText_loc8, CompletedText_loc8, ObjectiveText1_loc8, ObjectiveText2_loc8, ObjectiveText3_loc8, ObjectiveText4_loc8"
+ "Title_loc1, Details_loc1, Objectives_loc1, OfferRewardText_loc1, RequestItemsText_loc1, EndText_loc1, CompletedText_loc1, ObjectiveText1_loc1, ObjectiveText2_loc1, ObjectiveText3_loc1, ObjectiveText4_loc1, QuestGiverTextWindow_loc1, QuestGiverTargetName_loc1, QuestTurnTextWindow_loc1, QuestTurnTargetName_loc1,"
+ "Title_loc2, Details_loc2, Objectives_loc2, OfferRewardText_loc2, RequestItemsText_loc2, EndText_loc2, CompletedText_loc2, ObjectiveText1_loc2, ObjectiveText2_loc2, ObjectiveText3_loc2, ObjectiveText4_loc2, QuestGiverTextWindow_loc2, QuestGiverTargetName_loc2, QuestTurnTextWindow_loc2, QuestTurnTargetName_loc2,"
+ "Title_loc3, Details_loc3, Objectives_loc3, OfferRewardText_loc3, RequestItemsText_loc3, EndText_loc3, CompletedText_loc3, ObjectiveText1_loc3, ObjectiveText2_loc3, ObjectiveText3_loc3, ObjectiveText4_loc3, QuestGiverTextWindow_loc3, QuestGiverTargetName_loc3, QuestTurnTextWindow_loc3, QuestTurnTargetName_loc3,"
+ "Title_loc4, Details_loc4, Objectives_loc4, OfferRewardText_loc4, RequestItemsText_loc4, EndText_loc4, CompletedText_loc4, ObjectiveText1_loc4, ObjectiveText2_loc4, ObjectiveText3_loc4, ObjectiveText4_loc4, QuestGiverTextWindow_loc4, QuestGiverTargetName_loc4, QuestTurnTextWindow_loc4, QuestTurnTargetName_loc4,"
+ "Title_loc5, Details_loc5, Objectives_loc5, OfferRewardText_loc5, RequestItemsText_loc5, EndText_loc5, CompletedText_loc5, ObjectiveText1_loc5, ObjectiveText2_loc5, ObjectiveText3_loc5, ObjectiveText4_loc5, QuestGiverTextWindow_loc5, QuestGiverTargetName_loc5, QuestTurnTextWindow_loc5, QuestTurnTargetName_loc5,"
+ "Title_loc6, Details_loc6, Objectives_loc6, OfferRewardText_loc6, RequestItemsText_loc6, EndText_loc6, CompletedText_loc6, ObjectiveText1_loc6, ObjectiveText2_loc6, ObjectiveText3_loc6, ObjectiveText4_loc6, QuestGiverTextWindow_loc6, QuestGiverTargetName_loc6, QuestTurnTextWindow_loc6, QuestTurnTargetName_loc6,"
+ "Title_loc7, Details_loc7, Objectives_loc7, OfferRewardText_loc7, RequestItemsText_loc7, EndText_loc7, CompletedText_loc7, ObjectiveText1_loc7, ObjectiveText2_loc7, ObjectiveText3_loc7, ObjectiveText4_loc7, QuestGiverTextWindow_loc7, QuestGiverTargetName_loc7, QuestTurnTextWindow_loc7, QuestTurnTargetName_loc7,"
+ "Title_loc8, Details_loc8, Objectives_loc8, OfferRewardText_loc8, RequestItemsText_loc8, EndText_loc8, CompletedText_loc8, ObjectiveText1_loc8, ObjectiveText2_loc8, ObjectiveText3_loc8, ObjectiveText4_loc8, QuestGiverTextWindow_loc8, QuestGiverTargetName_loc8, QuestTurnTextWindow_loc8, QuestTurnTargetName_loc8"
" FROM locales_quest");
if (!result)
@@ -4527,16 +4573,21 @@ void ObjectMgr::LoadQuestLocales()
{
LocaleConstant locale = (LocaleConstant) i;
- AddLocaleString(fields[1 + 11 * (i - 1)].GetString(), locale, data.Title);
- AddLocaleString(fields[1 + 11 * (i - 1) + 1].GetString(), locale, data.Details);
- AddLocaleString(fields[1 + 11 * (i - 1) + 2].GetString(), locale, data.Objectives);
- AddLocaleString(fields[1 + 11 * (i - 1) + 3].GetString(), locale, data.OfferRewardText);
- AddLocaleString(fields[1 + 11 * (i - 1) + 4].GetString(), locale, data.RequestItemsText);
- AddLocaleString(fields[1 + 11 * (i - 1) + 5].GetString(), locale, data.EndText);
- AddLocaleString(fields[1 + 11 * (i - 1) + 6].GetString(), locale, data.CompletedText);
+ AddLocaleString(fields[1 + 15 * (i - 1)].GetString(), locale, data.Title);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 1].GetString(), locale, data.Details);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 2].GetString(), locale, data.Objectives);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 3].GetString(), locale, data.OfferRewardText);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 4].GetString(), locale, data.RequestItemsText);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 5].GetString(), locale, data.EndText);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 6].GetString(), locale, data.CompletedText);
for (uint8 k = 0; k < 4; ++k)
- AddLocaleString(fields[1 + 11 * (i - 1) + 7 + k].GetString(), locale, data.ObjectiveText[k]);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 7 + k].GetString(), locale, data.ObjectiveText[k]);
+
+ AddLocaleString(fields[1 + 15 * (i - 1) + 11].GetString(), locale, data.QuestGiverTextWindow);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 12].GetString(), locale, data.QuestGiverTargetName);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 13].GetString(), locale, data.QuestTurnTextWindow);
+ AddLocaleString(fields[1 + 15 * (i - 1) + 14].GetString(), locale, data.QuestTurnTargetName);
}
} while (result->NextRow());
@@ -4991,7 +5042,7 @@ void ObjectMgr::LoadSpellScriptNames()
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
- TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) does not exist.", scriptName, spellId);
+ TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) does not exist.", scriptName, fields[0].GetInt32());
continue;
}
@@ -5005,7 +5056,6 @@ void ObjectMgr::LoadSpellScriptNames()
TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is not first rank of spell.", scriptName, fields[0].GetInt32());
continue;
}
-
while (spellInfo)
{
_spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, GetScriptId(scriptName)));
@@ -5239,7 +5289,7 @@ void ObjectMgr::LoadInstanceEncounters()
if (lastEncounterDungeon && !sLFGMgr->GetLFGDungeonEntry(lastEncounterDungeon))
{
- TC_LOG_ERROR("sql.sql", "Table `instance_encounters` has an encounter %u (%s) marked as final for invalid dungeon id %u, skipped!", entry, dungeonEncounter->encounterName[0], lastEncounterDungeon);
+ TC_LOG_ERROR("sql.sql", "Table `instance_encounters` has an encounter %u (%s) marked as final for invalid dungeon id %u, skipped!", entry, dungeonEncounter->encounterName, lastEncounterDungeon);
continue;
}
@@ -5248,7 +5298,7 @@ void ObjectMgr::LoadInstanceEncounters()
{
if (itr != dungeonLastBosses.end())
{
- TC_LOG_ERROR("sql.sql", "Table `instance_encounters` specified encounter %u (%s) as last encounter but %u (%s) is already marked as one, skipped!", entry, dungeonEncounter->encounterName[0], itr->second->id, itr->second->encounterName[0]);
+ TC_LOG_ERROR("sql.sql", "Table `instance_encounters` specified encounter %u (%s) as last encounter but %u (%s) is already marked as one, skipped!", entry, dungeonEncounter->encounterName, itr->second->id, itr->second->encounterName);
continue;
}
@@ -5262,7 +5312,7 @@ void ObjectMgr::LoadInstanceEncounters()
CreatureTemplate const* creatureInfo = GetCreatureTemplate(creditEntry);
if (!creatureInfo)
{
- TC_LOG_ERROR("sql.sql", "Table `instance_encounters` has an invalid creature (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName[0]);
+ TC_LOG_ERROR("sql.sql", "Table `instance_encounters` has an invalid creature (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName);
continue;
}
const_cast<CreatureTemplate*>(creatureInfo)->flags_extra |= CREATURE_FLAG_EXTRA_DUNGEON_BOSS;
@@ -5271,17 +5321,32 @@ void ObjectMgr::LoadInstanceEncounters()
case ENCOUNTER_CREDIT_CAST_SPELL:
if (!sSpellMgr->GetSpellInfo(creditEntry))
{
- TC_LOG_ERROR("sql.sql", "Table `instance_encounters` has an invalid spell (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName[0]);
+ TC_LOG_ERROR("sql.sql", "Table `instance_encounters` has an invalid spell (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName);
continue;
}
break;
default:
- TC_LOG_ERROR("sql.sql", "Table `instance_encounters` has an invalid credit type (%u) for encounter %u (%s), skipped!", creditType, entry, dungeonEncounter->encounterName[0]);
+ TC_LOG_ERROR("sql.sql", "Table `instance_encounters` has an invalid credit type (%u) for encounter %u (%s), skipped!", creditType, entry, dungeonEncounter->encounterName);
continue;
}
- DungeonEncounterList& encounters = _dungeonEncounterStore[MAKE_PAIR32(dungeonEncounter->mapId, dungeonEncounter->difficulty)];
- encounters.push_back(new DungeonEncounter(dungeonEncounter, EncounterCreditType(creditType), creditEntry, lastEncounterDungeon));
+ if (dungeonEncounter->difficulty == -1)
+ {
+ for (uint32 i = 0; i < MAX_DIFFICULTY; ++i)
+ {
+ if (GetMapDifficultyData(dungeonEncounter->mapId, Difficulty(i)))
+ {
+ DungeonEncounterList& encounters = _dungeonEncounterStore[MAKE_PAIR32(dungeonEncounter->mapId, i)];
+ encounters.push_back(new DungeonEncounter(dungeonEncounter, EncounterCreditType(creditType), creditEntry, lastEncounterDungeon));
+ }
+ }
+ }
+ else
+ {
+ DungeonEncounterList& encounters = _dungeonEncounterStore[MAKE_PAIR32(dungeonEncounter->mapId, dungeonEncounter->difficulty)];
+ encounters.push_back(new DungeonEncounter(dungeonEncounter, EncounterCreditType(creditType), creditEntry, lastEncounterDungeon));
+ }
+
++count;
} while (result->NextRow());
@@ -5470,7 +5535,7 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
bool has_items = fields[4].GetBool();
m->expire_time = time_t(fields[5].GetUInt32());
m->deliver_time = 0;
- m->COD = fields[6].GetUInt32();
+ m->COD = fields[6].GetUInt64();
m->checked = fields[7].GetUInt8();
m->mailTemplateId = fields[8].GetInt16();
@@ -5686,8 +5751,8 @@ uint32 ObjectMgr::GetNearestTaxiNode(float x, float y, float z, uint32 mapid, ui
if (!node || node->map_id != mapid || (!node->MountCreatureID[team == ALLIANCE ? 1 : 0] && node->MountCreatureID[0] != 32981)) // dk flight
continue;
- uint8 field = (uint8)((i - 1) / 32);
- uint32 submask = 1<<((i-1)%32);
+ uint8 field = (uint8)((i - 1) / 8);
+ uint32 submask = 1 << ((i-1) % 8);
// skip not taxi network nodes
if ((sTaxiNodesMask[field] & submask) == 0)
@@ -6088,7 +6153,7 @@ void ObjectMgr::LoadAreaTriggerTeleports()
uint32 Trigger_ID = fields[0].GetUInt32();
- AreaTrigger at;
+ AreaTriggerStruct at;
at.target_mapId = fields[1].GetUInt16();
at.target_X = fields[2].GetFloat();
@@ -6135,8 +6200,8 @@ void ObjectMgr::LoadAccessRequirements()
_accessRequirementStore.clear(); // need for reload case
}
- // 0 1 2 3 4 5 6 7 8 9 10
- QueryResult result = WorldDatabase.Query("SELECT mapid, difficulty, level_min, level_max, item_level, item, item2, quest_done_A, quest_done_H, completed_achievement, quest_failed_text FROM access_requirement");
+ // 0 1 2 3 4 5 6 7 8 9
+ QueryResult result = WorldDatabase.Query("SELECT mapid, difficulty, level_min, level_max, item, item2, quest_done_A, quest_done_H, completed_achievement, quest_failed_text FROM access_requirement");
if (!result)
{
@@ -6156,17 +6221,15 @@ void ObjectMgr::LoadAccessRequirements()
uint8 difficulty = fields[1].GetUInt8();
uint32 requirement_ID = MAKE_PAIR32(mapid, difficulty);
- AccessRequirement* ar = new AccessRequirement();
-
- ar->levelMin = fields[2].GetUInt8();
- ar->levelMax = fields[3].GetUInt8();
- ar->item_level = fields[4].GetUInt16();
- ar->item = fields[5].GetUInt32();
- ar->item2 = fields[6].GetUInt32();
- ar->quest_A = fields[7].GetUInt32();
- ar->quest_H = fields[8].GetUInt32();
- ar->achievement = fields[9].GetUInt32();
- ar->questFailedText = fields[10].GetString();
+ AccessRequirement* ar = new AccessRequirement();
+ ar->levelMin = fields[2].GetUInt8();
+ ar->levelMax = fields[3].GetUInt8();
+ ar->item = fields[4].GetUInt32();
+ ar->item2 = fields[5].GetUInt32();
+ ar->quest_A = fields[6].GetUInt32();
+ ar->quest_H = fields[7].GetUInt32();
+ ar->achievement = fields[8].GetUInt32();
+ ar->questFailedText = fields[9].GetString();
if (ar->item)
{
@@ -6224,7 +6287,7 @@ void ObjectMgr::LoadAccessRequirements()
/*
* Searches for the areatrigger which teleports players out of the given map with instance_template.parent field support
*/
-AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const
+AreaTriggerStruct const* ObjectMgr::GetGoBackTrigger(uint32 Map) const
{
bool useParentDbValue = false;
uint32 parentId = 0;
@@ -6257,7 +6320,7 @@ AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const
/**
* Searches for the areatrigger which teleports players to the given map
*/
-AreaTrigger const* ObjectMgr::GetMapEntranceTrigger(uint32 Map) const
+AreaTriggerStruct const* ObjectMgr::GetMapEntranceTrigger(uint32 Map) const
{
for (AreaTriggerContainer::const_iterator itr = _areaTriggerStore.begin(); itr != _areaTriggerStore.end(); ++itr)
{
@@ -6326,6 +6389,10 @@ void ObjectMgr::SetHighestGuids()
result = CharacterDatabase.Query("SELECT MAX(guid) FROM groups");
if (result)
sGroupMgr->SetGroupDbStoreSize((*result)[0].GetUInt32()+1);
+
+ result = CharacterDatabase.Query("SELECT MAX(itemId) from character_void_storage");
+ if (result)
+ _voidItemId = (*result)[0].GetUInt64()+1;
}
uint32 ObjectMgr::GenerateAuctionID()
@@ -6397,6 +6464,11 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
ASSERT(_hiCorpseGuid < 0xFFFFFFFE && "Corpse guid overflow!");
return _hiCorpseGuid++;
}
+ case HIGHGUID_AREATRIGGER:
+ {
+ ASSERT(_hiAreaTriggerGuid < 0xFFFFFFFE && "AreaTrigger guid overflow!");
+ return _hiAreaTriggerGuid++;
+ }
case HIGHGUID_DYNAMICOBJECT:
{
ASSERT(_hiDoGuid < 0xFFFFFFFE && "DynamicObject guid overflow!");
@@ -6473,7 +6545,7 @@ inline void CheckGOSpellId(GameObjectTemplate const* goInfo, uint32 dataN, uint3
goInfo->entry, goInfo->type, N, dataN, dataN);
}
-inline void CheckAndFixGOChairHeightId(GameObjectTemplate const* goInfo, uint32 const& dataN, uint32 N)
+inline void CheckAndFixGOChairHeightId(GameObjectTemplate const* goInfo, uint32& dataN, uint32 N)
{
if (dataN <= (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR))
return;
@@ -6482,7 +6554,7 @@ inline void CheckAndFixGOChairHeightId(GameObjectTemplate const* goInfo, uint32
goInfo->entry, goInfo->type, N, dataN, UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
// prevent client and server unexpected work
- const_cast<uint32&>(dataN) = 0;
+ dataN = 0;
}
inline void CheckGONoDamageImmuneId(GameObjectTemplate* goTemplate, uint32 dataN, uint32 N)
@@ -6512,8 +6584,10 @@ void ObjectMgr::LoadGameObjectTemplate()
QueryResult result = WorldDatabase.Query("SELECT entry, type, displayId, name, IconName, castBarCaption, unk1, faction, flags, size, questItem1, questItem2, questItem3, "
// 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
"questItem4, questItem5, questItem6, data0, data1, data2, data3, data4, data5, data6, data7, data8, data9, data10, data11, data12, "
- // 29 30 31 32 33 34 35 36 37 38 39 40 41
- "data13, data14, data15, data16, data17, data18, data19, data20, data21, data22, data23, AIName, ScriptName "
+ // 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
+ "data13, data14, data15, data16, data17, data18, data19, data20, data21, data22, data23, data24, data25, data26, data27, data28, "
+ // 45 46 47 48 49 50
+ "data29, data30, data31, unkInt32, AIName, ScriptName "
"FROM gameobject_template");
if (!result)
@@ -6547,10 +6621,11 @@ void ObjectMgr::LoadGameObjectTemplate()
got.questItems[i] = fields[10 + i].GetUInt32();
for (uint8 i = 0; i < MAX_GAMEOBJECT_DATA; ++i)
- got.raw.data[i] = fields[16 + i].GetInt32(); // data1 and data6 can be -1
+ got.raw.data[i] = fields[16 + i].GetUInt32();
- got.AIName = fields[40].GetString();
- got.ScriptId = GetScriptId(fields[41].GetCString());
+ got.unkInt32 = fields[48].GetInt32();
+ got.AIName = fields[49].GetString();
+ got.ScriptId = GetScriptId(fields[50].GetCString());
// Checks
@@ -6787,7 +6862,7 @@ std::string ObjectMgr::GeneratePetName(uint32 entry)
if (!cinfo)
return std::string();
- char* petname = GetPetName(cinfo->family, sWorld->GetDefaultDbcLocale());
+ char const* petname = GetPetName(cinfo->family, sWorld->GetDefaultDbcLocale());
if (petname)
return std::string(petname);
else
@@ -6802,8 +6877,16 @@ uint32 ObjectMgr::GeneratePetNumber()
return ++_hiPetNumber;
}
+uint64 ObjectMgr::GenerateVoidStorageItemId()
+{
+ return ++_voidItemId;
+}
+
void ObjectMgr::LoadCorpses()
{
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0
+
uint32 oldMSTime = getMSTime();
PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES));
@@ -6818,7 +6901,7 @@ void ObjectMgr::LoadCorpses()
{
Field* fields = result->Fetch();
uint32 guid = fields[16].GetUInt32();
- CorpseType type = CorpseType(fields[13].GetUInt8());
+ CorpseType type = CorpseType(fields[12].GetUInt8());
if (type >= MAX_CORPSE_TYPE)
{
TC_LOG_ERROR("misc", "Corpse (guid: %u) have wrong corpse type (%u), not loading.", guid, type);
@@ -7006,8 +7089,8 @@ void ObjectMgr::LoadReputationSpilloverTemplate()
_repSpilloverTemplateStore.clear(); // for reload case
- uint32 count = 0; // 0 1 2 3 4 5 6 7 8 9 10 11 12
- QueryResult result = WorldDatabase.Query("SELECT faction, faction1, rate_1, rank_1, faction2, rate_2, rank_2, faction3, rate_3, rank_3, faction4, rate_4, rank_4 FROM reputation_spillover_template");
+ uint32 count = 0; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ QueryResult result = WorldDatabase.Query("SELECT faction, faction1, rate_1, rank_1, faction2, rate_2, rank_2, faction3, rate_3, rank_3, faction4, rate_4, rank_4, faction5, rate_5, rank_5 FROM reputation_spillover_template");
if (!result)
{
@@ -7035,6 +7118,9 @@ void ObjectMgr::LoadReputationSpilloverTemplate()
repTemplate.faction[3] = fields[10].GetUInt16();
repTemplate.faction_rate[3] = fields[11].GetFloat();
repTemplate.faction_rank[3] = fields[12].GetUInt8();
+ repTemplate.faction[4] = fields[13].GetUInt16();
+ repTemplate.faction_rate[4] = fields[14].GetFloat();
+ repTemplate.faction_rank[4] = fields[15].GetUInt8();
FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId);
@@ -7100,6 +7186,12 @@ void ObjectMgr::LoadReputationSpilloverTemplate()
TC_LOG_ERROR("sql.sql", "Faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template`", repTemplate.faction[3]);
continue;
}
+ FactionEntry const* factionEntry4 = sFactionStore.LookupEntry(repTemplate.faction[4]);
+ if (repTemplate.faction[4] && !factionEntry4)
+ {
+ TC_LOG_ERROR("sql.sql", "Faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template`", repTemplate.faction[4]);
+ continue;
+ }
_repSpilloverTemplateStore[factionId] = repTemplate;
@@ -8213,7 +8305,7 @@ void ObjectMgr::LoadTrainerSpell()
if (!result)
{
- TC_LOG_ERROR("sql.sql", ">> Loaded 0 Trainers. DB table `npc_trainer` is empty!");
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 Trainers. DB table `npc_trainer` is empty!");
return;
}
@@ -8240,11 +8332,12 @@ void ObjectMgr::LoadTrainerSpell()
TC_LOG_INFO("server.loading", ">> Loaded %d Trainers in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, std::set<uint32> *skip_vendors)
+int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, uint8 type, std::set<uint32> *skip_vendors)
{
// find all items from the reference vendor
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_NPC_VENDOR_REF);
stmt->setUInt32(0, uint32(item));
+ stmt->setUInt8(1, type);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
@@ -8259,19 +8352,20 @@ int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, std::set<uint32> *s
// if item is a negative, its a reference
if (item_id < 0)
- count += LoadReferenceVendor(vendor, -item_id, skip_vendors);
+ count += LoadReferenceVendor(vendor, -item_id, type, skip_vendors);
else
{
- int32 maxcount = fields[1].GetUInt8();
+ int32 maxcount = fields[1].GetUInt32();
uint32 incrtime = fields[2].GetUInt32();
uint32 ExtendedCost = fields[3].GetUInt32();
+ uint8 type = fields[4].GetUInt8();
- if (!IsVendorItemValid(vendor, item_id, maxcount, incrtime, ExtendedCost, NULL, skip_vendors))
+ if (!IsVendorItemValid(vendor, item_id, maxcount, incrtime, ExtendedCost, type, NULL, skip_vendors))
continue;
VendorItemData& vList = _cacheVendorItemStore[vendor];
- vList.AddItem(item_id, maxcount, incrtime, ExtendedCost);
+ vList.AddItem(item_id, maxcount, incrtime, ExtendedCost, type);
++count;
}
} while (result->NextRow());
@@ -8290,11 +8384,11 @@ void ObjectMgr::LoadVendors()
std::set<uint32> skip_vendors;
- QueryResult result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor ORDER BY entry, slot ASC");
+ QueryResult result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost, type FROM npc_vendor ORDER BY entry, slot ASC");
if (!result)
{
- TC_LOG_ERROR("sql.sql", ">> Loaded 0 Vendors. DB table `npc_vendor` is empty!");
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 Vendors. DB table `npc_vendor` is empty!");
return;
}
@@ -8309,19 +8403,20 @@ void ObjectMgr::LoadVendors()
// if item is a negative, its a reference
if (item_id < 0)
- count += LoadReferenceVendor(entry, -item_id, &skip_vendors);
+ count += LoadReferenceVendor(entry, -item_id, 0, &skip_vendors);
else
{
- uint32 maxcount = fields[2].GetUInt8();
+ uint32 maxcount = fields[2].GetUInt32();
uint32 incrtime = fields[3].GetUInt32();
uint32 ExtendedCost = fields[4].GetUInt32();
+ uint8 type = fields[5].GetUInt8();
- if (!IsVendorItemValid(entry, item_id, maxcount, incrtime, ExtendedCost, NULL, &skip_vendors))
+ if (!IsVendorItemValid(entry, item_id, maxcount, incrtime, ExtendedCost, type, NULL, &skip_vendors))
continue;
VendorItemData& vList = _cacheVendorItemStore[entry];
- vList.AddItem(item_id, maxcount, incrtime, ExtendedCost);
+ vList.AddItem(item_id, maxcount, incrtime, ExtendedCost, type);
++count;
}
}
@@ -8450,10 +8545,10 @@ void ObjectMgr::LoadGossipMenuItems()
TC_LOG_INFO("server.loading", ">> Loaded %u gossip_menu_option entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, bool persist /*= true*/)
+void ObjectMgr::AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, uint8 type, bool persist /*= true*/)
{
VendorItemData& vList = _cacheVendorItemStore[entry];
- vList.AddItem(item, maxcount, incrtime, extendedCost);
+ vList.AddItem(item, maxcount, incrtime, extendedCost, type);
if (persist)
{
@@ -8464,18 +8559,19 @@ void ObjectMgr::AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32
stmt->setUInt8(2, maxcount);
stmt->setUInt32(3, incrtime);
stmt->setUInt32(4, extendedCost);
+ stmt->setUInt8(5, type);
WorldDatabase.Execute(stmt);
}
}
-bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, bool persist /*= true*/)
+bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, uint8 type, bool persist /*= true*/)
{
CacheVendorItemContainer::iterator iter = _cacheVendorItemStore.find(entry);
if (iter == _cacheVendorItemStore.end())
return false;
- if (!iter->second.RemoveItem(item))
+ if (!iter->second.RemoveItem(item, type))
return false;
if (persist)
@@ -8484,6 +8580,7 @@ bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, bool persist /*= tru
stmt->setUInt32(0, entry);
stmt->setUInt32(1, item);
+ stmt->setUInt8(2, type);
WorldDatabase.Execute(stmt);
}
@@ -8491,7 +8588,7 @@ bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, bool persist /*= tru
return true;
}
-bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* player, std::set<uint32>* skip_vendors, uint32 ORnpcflag) const
+bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 id, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, uint8 type, Player* player, std::set<uint32>* skip_vendors, uint32 ORnpcflag) const
{
CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(vendor_entry);
if (!cInfo)
@@ -8518,12 +8615,13 @@ bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 max
return false;
}
- if (!sObjectMgr->GetItemTemplate(item_id))
+ if ((type == ITEM_VENDOR_TYPE_ITEM && !sObjectMgr->GetItemTemplate(id)) ||
+ (type == ITEM_VENDOR_TYPE_CURRENCY && !sCurrencyTypesStore.LookupEntry(id)))
{
if (player)
- ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_NOT_FOUND, item_id);
+ ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_NOT_FOUND, id, type);
else
- TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u), ignore", vendor_entry, item_id);
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u, type %u), ignore", vendor_entry, id, type);
return false;
}
@@ -8532,37 +8630,46 @@ bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 max
if (player)
ChatHandler(player->GetSession()).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST, ExtendedCost);
else
- TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore", item_id, ExtendedCost, vendor_entry);
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore", id, ExtendedCost, vendor_entry);
return false;
}
- if (maxcount > 0 && incrtime == 0)
+ if (type == ITEM_VENDOR_TYPE_ITEM) // not applicable to currencies
{
- if (player)
- ChatHandler(player->GetSession()).PSendSysMessage("MaxCount != 0 (%u) but IncrTime == 0", maxcount);
- else
- TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignore", maxcount, item_id, vendor_entry);
- return false;
- }
- else if (maxcount == 0 && incrtime > 0)
- {
- if (player)
- ChatHandler(player->GetSession()).PSendSysMessage("MaxCount == 0 but IncrTime<>= 0");
- else
- TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignore", item_id, vendor_entry);
- return false;
+ if (maxcount > 0 && incrtime == 0)
+ {
+ if (player)
+ ChatHandler(player->GetSession()).PSendSysMessage("MaxCount != 0 (%u) but IncrTime == 0", maxcount);
+ else
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignore", maxcount, id, vendor_entry);
+ return false;
+ }
+ else if (maxcount == 0 && incrtime > 0)
+ {
+ if (player)
+ ChatHandler(player->GetSession()).PSendSysMessage("MaxCount == 0 but IncrTime<>= 0");
+ else
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignore", id, vendor_entry);
+ return false;
+ }
}
VendorItemData const* vItems = GetNpcVendorItemList(vendor_entry);
if (!vItems)
return true; // later checks for non-empty lists
- if (vItems->FindItemCostPair(item_id, ExtendedCost))
+ if (vItems->FindItemCostPair(id, ExtendedCost, type))
{
if (player)
- ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id, ExtendedCost);
+ ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, id, ExtendedCost, type);
else
- TC_LOG_ERROR("sql.sql", "Table `npc_vendor` has duplicate items %u (with extended cost %u) for vendor (Entry: %u), ignoring", item_id, ExtendedCost, vendor_entry);
+ TC_LOG_ERROR("sql.sql", "Table `npc_vendor` has duplicate items %u (with extended cost %u, type %u) for vendor (Entry: %u), ignoring", id, ExtendedCost, type, vendor_entry);
+ return false;
+ }
+
+ if (type == ITEM_VENDOR_TYPE_CURRENCY && maxcount == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` have Item (Entry: %u, type: %u) with missing maxcount for vendor (%u), ignore", id, type, vendor_entry);
return false;
}
@@ -8583,7 +8690,7 @@ void ObjectMgr::LoadScriptNames()
"UNION "
"SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' "
"UNION "
- "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' "
+ "SELECT DISTINCT(ScriptName) FROM item_script_names WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' "
"UNION "
@@ -8840,8 +8947,8 @@ CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unit
void ObjectMgr::LoadCreatureClassLevelStats()
{
uint32 oldMSTime = getMSTime();
-
- QueryResult result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basemana, basearmor, attackpower, rangedattackpower, damage_base, damage_exp1, damage_exp2 FROM creature_classlevelstats");
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
+ QueryResult result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basehp3, basemana, basearmor, attackpower, rangedattackpower, damage_base, damage_exp1, damage_exp2, damage_exp3 FROM creature_classlevelstats");
if (!result)
{
@@ -8864,7 +8971,7 @@ void ObjectMgr::LoadCreatureClassLevelStats()
for (uint8 i = 0; i < MAX_EXPANSIONS; ++i)
{
- stats.BaseHealth[i] = fields[2 + i].GetUInt16();
+ stats.BaseHealth[i] = fields[2 + i].GetUInt32();
if (stats.BaseHealth[i] == 0)
{
@@ -8872,7 +8979,7 @@ void ObjectMgr::LoadCreatureClassLevelStats()
stats.BaseHealth[i] = 1;
}
- stats.BaseDamage[i] = fields[9 + i].GetFloat();
+ stats.BaseDamage[i] = fields[10 + i].GetFloat();
if (stats.BaseDamage[i] < 0.0f)
{
TC_LOG_ERROR("sql.sql", "Creature base stats for class %u, level %u has invalid negative base damage[%u] - set to 0.0", Class, Level, i);
@@ -8880,11 +8987,11 @@ void ObjectMgr::LoadCreatureClassLevelStats()
}
}
- stats.BaseMana = fields[5].GetUInt16();
- stats.BaseArmor = fields[6].GetUInt16();
+ stats.BaseMana = fields[6].GetUInt16();
+ stats.BaseArmor = fields[7].GetUInt16();
- stats.AttackPower = fields[7].GetUInt16();
- stats.RangedAttackPower = fields[8].GetUInt16();
+ stats.AttackPower = fields[8].GetUInt16();
+ stats.RangedAttackPower = fields[9].GetUInt16();
_creatureBaseStatsStore[MAKE_PAIR16(Level, Class)] = stats;
@@ -9045,6 +9152,74 @@ void ObjectMgr::LoadFactionChangeReputations()
TC_LOG_INFO("server.loading", ">> Loaded %u faction change reputation pairs in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+void ObjectMgr::LoadHotfixData()
+{
+ uint32 oldMSTime = getMSTime();
+
+ QueryResult result = WorldDatabase.Query("SELECT entry, type, UNIX_TIMESTAMP(hotfixDate) FROM hotfix_data");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 hotfix info entries. DB table `hotfix_data` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ _hotfixData.reserve(result->GetRowCount());
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ HotfixInfo info;
+ info.Entry = fields[0].GetUInt32();
+ info.Type = fields[1].GetUInt32();
+ info.Timestamp = fields[2].GetUInt64();
+ _hotfixData.push_back(info);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u hotfix info entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ObjectMgr::LoadMissingKeyChains()
+{
+ uint32 oldMSTime = getMSTime();
+
+ QueryResult result = WorldDatabase.Query("SELECT keyId, k1, k2, k3, k4, k5, k6, k7, k8, "
+ "k9, k10, k11, k12, k13, k14, k15, k16, "
+ "k17, k18, k19, k20, k21, k22, k23, k24, "
+ "k25, k26, k27, k28, k29, k30, k31, k32 "
+ "FROM keychain_db2 ORDER BY keyId DESC");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 KeyChain entries. DB table `keychain_db2` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 id = fields[0].GetUInt32();
+
+ KeyChainEntry* kce = sKeyChainStore.CreateEntry(id, true);
+ kce->Id = id;
+ for (uint32 i = 0; i < KEYCHAIN_SIZE; ++i)
+ kce->Key[i] = fields[1 + i].GetUInt8();
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u KeyChain entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
void ObjectMgr::LoadFactionChangeSpells()
{
uint32 oldMSTime = getMSTime();
@@ -9115,6 +9290,89 @@ void ObjectMgr::LoadFactionChangeTitles()
TC_LOG_INFO("server.loading", ">> Loaded %u faction change title pairs in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+void ObjectMgr::LoadPhaseDefinitions()
+{
+ _PhaseDefinitionStore.clear();
+
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2 3
+ QueryResult result = WorldDatabase.Query("SELECT zoneId, entry, phaseId, phaseGroup FROM `phase_definitions` ORDER BY `entry` ASC");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 phasing definitions. DB table `phase_definitions` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ PhaseDefinition PhaseDefinition;
+
+ PhaseDefinition.zoneId = fields[0].GetUInt32();
+ PhaseDefinition.entry = fields[1].GetUInt32();
+ PhaseDefinition.phaseId = fields[2].GetUInt32();
+ PhaseDefinition.phaseGroup = fields[3].GetUInt32();
+
+ if (PhaseDefinition.phaseGroup && PhaseDefinition.phaseId)
+ {
+ TC_LOG_ERROR("sql.sql", "Phase definition for zone %u (Entry: %u) has phaseGroup and phaseId set, phaseGroup set to 0", PhaseDefinition.zoneId, PhaseDefinition.entry);
+ PhaseDefinition.phaseGroup = 0;
+ }
+ _PhaseDefinitionStore[PhaseDefinition.zoneId].push_back(PhaseDefinition);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u phasing definitions in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ObjectMgr::LoadPhaseInfo()
+{
+ _PhaseInfoStore.clear();
+
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT id, worldmapareaswap, terrainswapmap FROM `phase_info`");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 phase infos. DB table `phase_info` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+
+ PhaseInfo phaseInfo;
+ phaseInfo.phaseId = fields[0].GetUInt32();
+
+ PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseInfo.phaseId);
+ if (!phase)
+ {
+ TC_LOG_ERROR("sql.sql", "Phase %u defined in `phase_info` does not exists, skipped.", phaseInfo.phaseId);
+ continue;
+ }
+
+ phaseInfo.worldMapAreaSwap = fields[1].GetUInt32();
+ phaseInfo.terrainSwapMap = fields[2].GetUInt32();
+
+ _PhaseInfoStore[phaseInfo.phaseId] = phaseInfo;
+
+ ++count;
+ }
+ while (result->NextRow());
+ TC_LOG_INFO("server.loading", ">> Loaded %u phase infos in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry)
{
GameObjectTemplateContainer::const_iterator itr = _gameObjectTemplateStore.find(entry);
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 738b99778f8..45671f016c8 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -41,11 +41,10 @@
#include <limits>
#include "ConditionMgr.h"
#include <functional>
+#include "DB2Stores.h"
class Item;
struct AccessRequirement;
-struct PlayerClassInfo;
-struct PlayerClassLevelInfo;
struct PlayerInfo;
struct PlayerLevelInfo;
@@ -130,6 +129,34 @@ typedef std::map<uint32, PageText> PageTextContainer;
// Benchmarked: Faster than std::map (insert/find)
typedef std::unordered_map<uint16, InstanceTemplate> InstanceTemplateContainer;
+// Phasing (visibility)
+enum PhasingFlags
+{
+ PHASE_FLAG_OVERWRITE_EXISTING = 0x01, // don't stack with existing phases, overwrites existing phases
+ PHASE_FLAG_NO_MORE_PHASES = 0x02, // stop calculating phases after this phase was applied (no more phases will be applied)
+ PHASE_FLAG_NEGATE_PHASE = 0x04 // negate instead to add the phasemask
+};
+
+struct PhaseInfo
+{
+ uint32 phaseId;
+ uint32 worldMapAreaSwap;
+ uint32 terrainSwapMap;
+};
+
+typedef std::unordered_map<uint32, PhaseInfo> PhaseInfoContainer;
+
+struct PhaseDefinition
+{
+ uint32 zoneId;
+ uint32 entry;
+ uint32 phaseId;
+ uint32 phaseGroup;
+};
+
+typedef std::list<PhaseDefinition> PhaseDefinitionContainer;
+typedef std::unordered_map<uint32 /*zoneId*/, PhaseDefinitionContainer> PhaseDefinitionStore;
+
struct GameTele
{
float position_x;
@@ -400,7 +427,7 @@ struct SpellClickInfo
typedef std::multimap<uint32, SpellClickInfo> SpellClickInfoContainer;
typedef std::pair<SpellClickInfoContainer::const_iterator, SpellClickInfoContainer::const_iterator> SpellClickInfoMapBounds;
-struct AreaTrigger
+struct AreaTriggerStruct
{
uint32 target_mapId;
float target_X;
@@ -484,7 +511,6 @@ typedef std::map<TempSummonGroupKey, std::vector<TempSummonData> > TempSummonDat
typedef std::unordered_map<uint32, CreatureLocale> CreatureLocaleContainer;
typedef std::unordered_map<uint32, GameObjectLocale> GameObjectLocaleContainer;
typedef std::unordered_map<uint32, ItemLocale> ItemLocaleContainer;
-typedef std::unordered_map<uint32, ItemSetNameLocale> ItemSetNameLocaleContainer;
typedef std::unordered_map<uint32, QuestLocale> QuestLocaleContainer;
typedef std::unordered_map<uint32, NpcTextLocale> NpcTextLocaleContainer;
typedef std::unordered_map<uint32, PageTextLocale> PageTextLocaleContainer;
@@ -627,6 +653,7 @@ struct GraveYardData
};
typedef std::multimap<uint32, GraveYardData> GraveYardContainer;
+typedef std::unordered_map<uint32 /* graveyard Id */, float /* orientation */> GraveyardOrientationContainer;
typedef std::pair<GraveYardContainer::const_iterator, GraveYardContainer::const_iterator> GraveYardMapBounds;
typedef std::pair<GraveYardContainer::iterator, GraveYardContainer::iterator> GraveYardMapBoundsNonConst;
@@ -681,6 +708,15 @@ struct DungeonEncounter
typedef std::list<DungeonEncounter const*> DungeonEncounterList;
typedef std::unordered_map<uint32, DungeonEncounterList> DungeonEncounterContainer;
+struct HotfixInfo
+{
+ uint32 Type;
+ uint32 Timestamp;
+ uint32 Entry;
+};
+
+typedef std::vector<HotfixInfo> HotfixData;
+
class PlayerDumpReader;
class ObjectMgr
@@ -702,7 +738,7 @@ class ObjectMgr
typedef std::unordered_map<uint32, Quest*> QuestMap;
- typedef std::unordered_map<uint32, AreaTrigger> AreaTriggerContainer;
+ typedef std::unordered_map<uint32, AreaTriggerStruct> AreaTriggerContainer;
typedef std::unordered_map<uint32, uint32> AreaTriggerScriptContainer;
@@ -722,7 +758,7 @@ class ObjectMgr
GameObjectTemplate const* GetGameObjectTemplate(uint32 entry);
GameObjectTemplateContainer const* GetGameObjectTemplates() const { return &_gameObjectTemplateStore; }
- int LoadReferenceVendor(int32 vendor, int32 item_id, std::set<uint32> *skip_vendors);
+ int LoadReferenceVendor(int32 vendor, int32 item, uint8 type, std::set<uint32> *skip_vendors);
void LoadGameObjectTemplate();
void AddGameobjectInfo(GameObjectTemplate* goinfo);
@@ -739,25 +775,11 @@ class ObjectMgr
ItemTemplate const* GetItemTemplate(uint32 entry);
ItemTemplateContainer const* GetItemTemplateStore() const { return &_itemTemplateStore; }
- ItemSetNameEntry const* GetItemSetNameEntry(uint32 itemId)
- {
- ItemSetNameContainer::iterator itr = _itemSetNameStore.find(itemId);
- if (itr != _itemSetNameStore.end())
- return &itr->second;
- return NULL;
- }
-
InstanceTemplate const* GetInstanceTemplate(uint32 mapId);
PetLevelInfo const* GetPetLevelInfo(uint32 creature_id, uint8 level) const;
- PlayerClassInfo const* GetPlayerClassInfo(uint32 class_) const
- {
- if (class_ >= MAX_CLASSES)
- return NULL;
- return _playerClassInfo[class_];
- }
- void GetPlayerClassLevelInfo(uint32 class_, uint8 level, PlayerClassLevelInfo* info) const;
+ void GetPlayerClassLevelInfo(uint32 class_, uint8 level, uint32& baseHP, uint32& baseMana) const;
PlayerInfo const* GetPlayerInfo(uint32 race, uint32 class_) const;
@@ -822,7 +844,7 @@ class ObjectMgr
void LoadGraveyardZones();
GraveYardData const* FindGraveYardData(uint32 id, uint32 zone);
- AreaTrigger const* GetAreaTrigger(uint32 trigger) const
+ AreaTriggerStruct const* GetAreaTrigger(uint32 trigger) const
{
AreaTriggerContainer::const_iterator itr = _areaTriggerStore.find(trigger);
if (itr != _areaTriggerStore.end())
@@ -838,8 +860,8 @@ class ObjectMgr
return NULL;
}
- AreaTrigger const* GetGoBackTrigger(uint32 Map) const;
- AreaTrigger const* GetMapEntranceTrigger(uint32 Map) const;
+ AreaTriggerStruct const* GetGoBackTrigger(uint32 Map) const;
+ AreaTriggerStruct const* GetMapEntranceTrigger(uint32 Map) const;
uint32 GetAreaTriggerScriptId(uint32 trigger_id);
SpellScriptsBounds GetSpellScriptsBounds(uint32 spellId);
@@ -959,6 +981,7 @@ class ObjectMgr
void LoadDbScriptStrings();
void LoadCreatureClassLevelStats();
void LoadCreatureLocales();
+ void LoadGraveyardOrientations();
void LoadCreatureTemplates();
void LoadCreatureTemplateAddons();
void CheckCreatureTemplate(CreatureTemplate const* cInfo);
@@ -972,9 +995,9 @@ class ObjectMgr
void LoadGameObjectLocales();
void LoadGameobjects();
void LoadItemTemplates();
+ void LoadItemTemplateAddon();
+ void LoadItemScriptNames();
void LoadItemLocales();
- void LoadItemSetNames();
- void LoadItemSetNameLocales();
void LoadQuestLocales();
void LoadNpcTextLocales();
void LoadPageTextLocales();
@@ -1024,6 +1047,9 @@ class ObjectMgr
void LoadTrainerSpell();
void AddSpellToTrainer(uint32 entry, uint32 spell, uint32 spellCost, uint32 reqSkill, uint32 reqSkillValue, uint32 reqLevel);
+ void LoadPhaseDefinitions();
+ void LoadPhaseInfo();
+
std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint8 level);
uint32 GetXPForLevel(uint8 level) const;
@@ -1044,6 +1070,7 @@ class ObjectMgr
uint64 GenerateEquipmentSetGuid();
uint32 GenerateMailID();
uint32 GeneratePetNumber();
+ uint64 GenerateVoidStorageItemId();
typedef std::multimap<int32, uint32> ExclusiveQuestGroups;
typedef std::pair<ExclusiveQuestGroups::const_iterator, ExclusiveQuestGroups::const_iterator> ExclusiveQuestGroupsBounds;
@@ -1131,12 +1158,6 @@ class ObjectMgr
if (itr == _itemLocaleStore.end()) return NULL;
return &itr->second;
}
- ItemSetNameLocale const* GetItemSetNameLocale(uint32 entry) const
- {
- ItemSetNameLocaleContainer::const_iterator itr = _itemSetNameLocaleStore.find(entry);
- if (itr == _itemSetNameLocaleStore.end())return NULL;
- return &itr->second;
- }
QuestLocale const* GetQuestLocale(uint32 entry) const
{
QuestLocaleContainer::const_iterator itr = _questLocaleStore.find(entry);
@@ -1240,9 +1261,19 @@ class ObjectMgr
return &iter->second;
}
- void AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, bool persist = true); // for event
- bool RemoveVendorItem(uint32 entry, uint32 item, bool persist = true); // for event
- bool IsVendorItemValid(uint32 vendor_entry, uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* player = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0) const;
+
+ float const* GetGraveyardOrientation(uint32 id) const
+ {
+ GraveyardOrientationContainer::const_iterator iter = _graveyardOrientations.find(id);
+ if (iter != _graveyardOrientations.end())
+ return &iter->second;
+
+ return NULL;
+ }
+
+ void AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, uint8 type, bool persist = true); // for event
+ bool RemoveVendorItem(uint32 entry, uint32 item, uint8 type, bool persist = true); // for event
+ bool IsVendorItemValid(uint32 vendor_entry, uint32 id, int32 maxcount, uint32 ptime, uint32 ExtendedCost, uint8 type, Player* player = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0) const;
void LoadScriptNames();
ScriptNameContainer &GetScriptNames() { return _scriptNamesStore; }
@@ -1273,6 +1304,8 @@ class ObjectMgr
return _gossipMenuItemsStore.equal_range(uiMenuId);
}
+ PhaseInfo const* GetPhaseInfo(uint32 phase) { return _PhaseInfoStore.find(phase) != _PhaseInfoStore.end() ? &_PhaseInfoStore[phase] : nullptr; }
+
// for wintergrasp only
GraveYardContainer GraveYardStore;
@@ -1299,6 +1332,21 @@ class ObjectMgr
bool IsTransportMap(uint32 mapId) const { return _transportMaps.count(mapId) != 0; }
+ void LoadHotfixData();
+ HotfixData const& GetHotfixData() const { return _hotfixData; }
+ time_t GetHotfixDate(uint32 entry, uint32 type) const
+ {
+ time_t ret = 0;
+ for (HotfixData::const_iterator itr = _hotfixData.begin(); itr != _hotfixData.end(); ++itr)
+ if (itr->Entry == entry && itr->Type == type)
+ if (time_t(itr->Timestamp) > ret)
+ ret = time_t(itr->Timestamp);
+
+ return ret ? ret : time(NULL);
+ }
+
+ void LoadMissingKeyChains();
+
private:
// first free id for selected id type
uint32 _auctionId;
@@ -1306,6 +1354,7 @@ class ObjectMgr
uint32 _itemTextId;
uint32 _mailId;
uint32 _hiPetNumber;
+ uint64 _voidItemId;
// first free low guid for selected guid type
uint32 _hiCharGuid;
@@ -1316,6 +1365,7 @@ class ObjectMgr
uint32 _hiGoGuid;
uint32 _hiDoGuid;
uint32 _hiCorpseGuid;
+ uint32 _hiAreaTriggerGuid;
uint32 _hiMoTransGuid;
QuestMap _questTemplates;
@@ -1369,6 +1419,9 @@ class ObjectMgr
PageTextContainer _pageTextStore;
InstanceTemplateContainer _instanceTemplateStore;
+ PhaseDefinitionStore _PhaseDefinitionStore;
+ PhaseInfoContainer _PhaseInfoStore;
+
private:
void LoadScripts(ScriptsType type);
void CheckScripts(ScriptsType type, std::set<int32>& ids);
@@ -1383,8 +1436,6 @@ class ObjectMgr
// PetLevelInfoContainer[creature_id][level]
PetLevelInfoContainer _petInfoStore; // [creature_id][level]
- PlayerClassInfo* _playerClassInfo[MAX_CLASSES];
-
void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const;
PlayerInfo* _playerInfo[MAX_RACES][MAX_CLASSES];
@@ -1402,9 +1453,6 @@ class ObjectMgr
HalfNameContainer _petHalfName0;
HalfNameContainer _petHalfName1;
- typedef std::unordered_map<uint32, ItemSetNameEntry> ItemSetNameContainer;
- ItemSetNameContainer _itemSetNameStore;
-
MapObjectGuids _mapObjectGuidsStore;
CreatureDataContainer _creatureDataStore;
CreatureTemplateContainer _creatureTemplateStore;
@@ -1423,7 +1471,6 @@ class ObjectMgr
BroadcastTextContainer _broadcastTextStore;
ItemTemplateContainer _itemTemplateStore;
ItemLocaleContainer _itemLocaleStore;
- ItemSetNameLocaleContainer _itemSetNameLocaleStore;
QuestLocaleContainer _questLocaleStore;
NpcTextLocaleContainer _npcTextLocaleStore;
PageTextLocaleContainer _pageTextLocaleStore;
@@ -1434,6 +1481,8 @@ class ObjectMgr
CacheVendorItemContainer _cacheVendorItemStore;
CacheTrainerSpellContainer _cacheTrainerSpellStore;
+ GraveyardOrientationContainer _graveyardOrientations;
+
std::set<uint32> _difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate
std::set<uint32> _hasDifficultyEntries[MAX_DIFFICULTY - 1]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate
@@ -1445,6 +1494,7 @@ class ObjectMgr
GO_TO_CREATURE // GO is dependant on creature
};
+ HotfixData _hotfixData;
std::set<uint32> _transportMaps; // Helper container storing map ids that are for transports only, loaded from gameobject_template
};
diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h
index 013d0ef5794..9ed8549e9a1 100644
--- a/src/server/game/Grids/GridDefines.h
+++ b/src/server/game/Grids/GridDefines.h
@@ -30,6 +30,7 @@ class DynamicObject;
class GameObject;
class Pet;
class Player;
+class AreaTrigger;
#define MAX_NUMBER_OF_CELLS 8
@@ -57,13 +58,14 @@ class Player;
// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case)
typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes;
-typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
+typedef TYPELIST_5(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/, AreaTrigger) AllGridObjectTypes;
typedef GridRefManager<Corpse> CorpseMapType;
typedef GridRefManager<Creature> CreatureMapType;
typedef GridRefManager<DynamicObject> DynamicObjectMapType;
typedef GridRefManager<GameObject> GameObjectMapType;
typedef GridRefManager<Player> PlayerMapType;
+typedef GridRefManager<AreaTrigger> AreaTriggerMapType;
enum GridMapTypeMask
{
@@ -72,7 +74,8 @@ enum GridMapTypeMask
GRID_MAP_TYPE_MASK_DYNAMICOBJECT = 0x04,
GRID_MAP_TYPE_MASK_GAMEOBJECT = 0x08,
GRID_MAP_TYPE_MASK_PLAYER = 0x10,
- GRID_MAP_TYPE_MASK_ALL = 0x1F
+ GRID_MAP_TYPE_MASK_AREATRIGGER = 0x20,
+ GRID_MAP_TYPE_MASK_ALL = 0x3F
};
typedef Grid<Player, AllWorldObjectTypes, AllGridObjectTypes> GridType;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
index 270d598d53a..8040728133f 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -263,7 +263,7 @@ void MessageDistDeliverer::Visit(PlayerMapType &m)
for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Player* target = iter->GetSource();
- if (!target->InSamePhase(i_phaseMask))
+ if (!target->IsInPhase(i_source))
continue;
if (target->GetExactDist2dSq(i_source) > i_distSq)
@@ -288,7 +288,7 @@ void MessageDistDeliverer::Visit(CreatureMapType &m)
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Creature* target = iter->GetSource();
- if (!target->InSamePhase(i_phaseMask))
+ if (!target->IsInPhase(i_source))
continue;
if (target->GetExactDist2dSq(i_source) > i_distSq)
@@ -310,7 +310,7 @@ void MessageDistDeliverer::Visit(DynamicObjectMapType &m)
for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
DynamicObject* target = iter->GetSource();
- if (!target->InSamePhase(i_phaseMask))
+ if (!target->IsInPhase(i_source))
continue;
if (target->GetExactDist2dSq(i_source) > i_distSq)
@@ -378,3 +378,5 @@ bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Creature* u)
template void ObjectUpdater::Visit<Creature>(CreatureMapType&);
template void ObjectUpdater::Visit<GameObject>(GameObjectMapType&);
template void ObjectUpdater::Visit<DynamicObject>(DynamicObjectMapType&);
+template void ObjectUpdater::Visit<AreaTrigger>(AreaTriggerMapType &);
+
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index e9ba95f8fb6..d4b75b026f6 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -25,6 +25,7 @@
#include "Corpse.h"
#include "Object.h"
+#include "AreaTrigger.h"
#include "DynamicObject.h"
#include "GameObject.h"
#include "Player.h"
@@ -45,7 +46,7 @@ namespace Trinity
std::set<Unit*> i_visibleNow;
Player::ClientGUIDs vis_guids;
- VisibleNotifier(Player &player) : i_player(player), vis_guids(player.m_clientGUIDs) { }
+ VisibleNotifier(Player &player) : i_player(player), i_data(player.GetMapId()), vis_guids(player.m_clientGUIDs) { }
template<class T> void Visit(GridRefManager<T> &m);
void SendToSelf(void);
};
@@ -118,18 +119,18 @@ namespace Trinity
void Visit(GameObjectMapType &m) { updateObjects<GameObject>(m); }
void Visit(DynamicObjectMapType &m) { updateObjects<DynamicObject>(m); }
void Visit(CorpseMapType &m) { updateObjects<Corpse>(m); }
+ void Visit(AreaTriggerMapType &m) { updateObjects<AreaTrigger>(m); }
};
struct MessageDistDeliverer
{
WorldObject* i_source;
WorldPacket* i_message;
- uint32 i_phaseMask;
float i_distSq;
uint32 team;
Player const* skipped_receiver;
MessageDistDeliverer(WorldObject* src, WorldPacket* msg, float dist, bool own_team_only = false, Player const* skipped = NULL)
- : i_source(src), i_message(msg), i_phaseMask(src->GetPhaseMask()), i_distSq(dist * dist)
+ : i_source(src), i_message(msg), i_distSq(dist * dist)
, team(0)
, skipped_receiver(skipped)
{
@@ -173,19 +174,20 @@ namespace Trinity
template<class Check>
struct WorldObjectSearcher
{
- uint32 i_mapTypeMask;
- uint32 i_phaseMask;
- WorldObject* &i_object;
+ WorldObject const* _searcher;
+ WorldObject*& i_object;
Check &i_check;
+ uint32 i_mapTypeMask;
WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
- : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) { }
+ : _searcher(searcher), i_object(result), i_check(check), i_mapTypeMask(mapTypeMask) { }
void Visit(GameObjectMapType &m);
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
void Visit(CorpseMapType &m);
void Visit(DynamicObjectMapType &m);
+ void Visit(AreaTriggerMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) { }
};
@@ -193,19 +195,20 @@ namespace Trinity
template<class Check>
struct WorldObjectLastSearcher
{
- uint32 i_mapTypeMask;
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
WorldObject* &i_object;
Check &i_check;
+ uint32 i_mapTypeMask;
WorldObjectLastSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
- : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) { }
+ : _searcher(searcher), i_object(result), i_check(check), i_mapTypeMask(mapTypeMask) { }
void Visit(GameObjectMapType &m);
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
void Visit(CorpseMapType &m);
void Visit(DynamicObjectMapType &m);
+ void Visit(AreaTriggerMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) { }
};
@@ -214,18 +217,19 @@ namespace Trinity
struct WorldObjectListSearcher
{
uint32 i_mapTypeMask;
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
std::list<WorldObject*> &i_objects;
Check& i_check;
WorldObjectListSearcher(WorldObject const* searcher, std::list<WorldObject*> &objects, Check & check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
- : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) { }
+ : i_mapTypeMask(mapTypeMask), _searcher(searcher), i_objects(objects), i_check(check) { }
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
void Visit(CorpseMapType &m);
void Visit(GameObjectMapType &m);
void Visit(DynamicObjectMapType &m);
+ void Visit(AreaTriggerMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) { }
};
@@ -234,18 +238,18 @@ namespace Trinity
struct WorldObjectWorker
{
uint32 i_mapTypeMask;
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
Do const& i_do;
WorldObjectWorker(WorldObject const* searcher, Do const& _do, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
- : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_do(_do) { }
+ : i_mapTypeMask(mapTypeMask), _searcher(searcher), i_do(_do) { }
void Visit(GameObjectMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
return;
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
i_do(itr->GetSource());
}
@@ -254,7 +258,7 @@ namespace Trinity
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
return;
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
i_do(itr->GetSource());
}
void Visit(CreatureMapType &m)
@@ -262,7 +266,7 @@ namespace Trinity
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
return;
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
i_do(itr->GetSource());
}
@@ -271,7 +275,7 @@ namespace Trinity
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
return;
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
i_do(itr->GetSource());
}
@@ -280,7 +284,16 @@ namespace Trinity
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
return;
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
+ i_do(itr->GetSource());
+ }
+
+ void Visit(AreaTriggerMapType &m)
+ {
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
+ return;
+ for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ if (itr->GetSource()->IsInPhase(_searcher))
i_do(itr->GetSource());
}
@@ -292,12 +305,12 @@ namespace Trinity
template<class Check>
struct GameObjectSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
GameObject* &i_object;
Check &i_check;
GameObjectSearcher(WorldObject const* searcher, GameObject* & result, Check& check)
- : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) { }
+ : _searcher(searcher), i_object(result), i_check(check) { }
void Visit(GameObjectMapType &m);
@@ -308,12 +321,12 @@ namespace Trinity
template<class Check>
struct GameObjectLastSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
GameObject* &i_object;
Check& i_check;
GameObjectLastSearcher(WorldObject const* searcher, GameObject* & result, Check& check)
- : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) { }
+ : _searcher(searcher), i_object(result), i_check(check) { }
void Visit(GameObjectMapType &m);
@@ -323,12 +336,12 @@ namespace Trinity
template<class Check>
struct GameObjectListSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
std::list<GameObject*> &i_objects;
Check& i_check;
GameObjectListSearcher(WorldObject const* searcher, std::list<GameObject*> &objects, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) { }
+ : _searcher(searcher), i_objects(objects), i_check(check) { }
void Visit(GameObjectMapType &m);
@@ -339,12 +352,12 @@ namespace Trinity
struct GameObjectWorker
{
GameObjectWorker(WorldObject const* searcher, Functor& func)
- : _func(func), _phaseMask(searcher->GetPhaseMask()) { }
+ : _func(func), _searcher(searcher) { }
void Visit(GameObjectMapType& m)
{
for (GameObjectMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
_func(itr->GetSource());
}
@@ -352,7 +365,7 @@ namespace Trinity
private:
Functor& _func;
- uint32 _phaseMask;
+ WorldObject const* _searcher;
};
// Unit searchers
@@ -361,12 +374,12 @@ namespace Trinity
template<class Check>
struct UnitSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
Unit* &i_object;
Check & i_check;
UnitSearcher(WorldObject const* searcher, Unit* & result, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) { }
+ : _searcher(searcher), i_object(result), i_check(check) { }
void Visit(CreatureMapType &m);
void Visit(PlayerMapType &m);
@@ -378,12 +391,12 @@ namespace Trinity
template<class Check>
struct UnitLastSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
Unit* &i_object;
Check & i_check;
UnitLastSearcher(WorldObject const* searcher, Unit* & result, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) { }
+ : _searcher(searcher), i_object(result), i_check(check) { }
void Visit(CreatureMapType &m);
void Visit(PlayerMapType &m);
@@ -395,12 +408,12 @@ namespace Trinity
template<class Check>
struct UnitListSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
std::list<Unit*> &i_objects;
Check& i_check;
UnitListSearcher(WorldObject const* searcher, std::list<Unit*> &objects, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) { }
+ : _searcher(searcher), i_objects(objects), i_check(check) { }
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
@@ -413,12 +426,12 @@ namespace Trinity
template<class Check>
struct CreatureSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
Creature* &i_object;
Check & i_check;
CreatureSearcher(WorldObject const* searcher, Creature* & result, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) { }
+ : _searcher(searcher), i_object(result), i_check(check) { }
void Visit(CreatureMapType &m);
@@ -429,12 +442,12 @@ namespace Trinity
template<class Check>
struct CreatureLastSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
Creature* &i_object;
Check & i_check;
CreatureLastSearcher(WorldObject const* searcher, Creature* & result, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) { }
+ : _searcher(searcher), i_object(result), i_check(check) { }
void Visit(CreatureMapType &m);
@@ -444,12 +457,12 @@ namespace Trinity
template<class Check>
struct CreatureListSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
std::list<Creature*> &i_objects;
Check& i_check;
CreatureListSearcher(WorldObject const* searcher, std::list<Creature*> &objects, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) { }
+ : _searcher(searcher), i_objects(objects), i_check(check) { }
void Visit(CreatureMapType &m);
@@ -459,16 +472,16 @@ namespace Trinity
template<class Do>
struct CreatureWorker
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
Do& i_do;
CreatureWorker(WorldObject const* searcher, Do& _do)
- : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) { }
+ : _searcher(searcher), i_do(_do) { }
void Visit(CreatureMapType &m)
{
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
i_do(itr->GetSource());
}
@@ -480,12 +493,12 @@ namespace Trinity
template<class Check>
struct PlayerSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
Player* &i_object;
Check & i_check;
PlayerSearcher(WorldObject const* searcher, Player* & result, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) { }
+ : _searcher(searcher), i_object(result), i_check(check) { }
void Visit(PlayerMapType &m);
@@ -495,12 +508,12 @@ namespace Trinity
template<class Check>
struct PlayerListSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
std::list<Player*> &i_objects;
Check& i_check;
PlayerListSearcher(WorldObject const* searcher, std::list<Player*> &objects, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) { }
+ : _searcher(searcher), i_objects(objects), i_check(check) { }
void Visit(PlayerMapType &m);
@@ -510,11 +523,11 @@ namespace Trinity
template<class Check>
struct PlayerLastSearcher
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
Player* &i_object;
Check& i_check;
- PlayerLastSearcher(WorldObject const* searcher, Player*& result, Check& check) : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check)
+ PlayerLastSearcher(WorldObject const* searcher, Player*& result, Check& check) : _searcher(searcher), i_object(result), i_check(check)
{
}
@@ -526,16 +539,16 @@ namespace Trinity
template<class Do>
struct PlayerWorker
{
- uint32 i_phaseMask;
+ WorldObject const* _searcher;
Do& i_do;
PlayerWorker(WorldObject const* searcher, Do& _do)
- : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) { }
+ : _searcher(searcher), i_do(_do) { }
void Visit(PlayerMapType &m)
{
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
i_do(itr->GetSource());
}
@@ -555,7 +568,7 @@ namespace Trinity
void Visit(PlayerMapType &m)
{
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_searcher) && itr->GetSource()->IsWithinDist(i_searcher, i_dist))
+ if (itr->GetSource()->IsInPhase(i_searcher) && itr->GetSource()->IsWithinDist(i_searcher, i_dist))
i_do(itr->GetSource());
}
@@ -1330,7 +1343,7 @@ namespace Trinity
AllWorldObjectsInRange(const WorldObject* object, float maxRange) : m_pObject(object), m_fRange(maxRange) { }
bool operator() (WorldObject* go)
{
- return m_pObject->IsWithinDist(go, m_fRange, false) && m_pObject->InSamePhase(go);
+ return m_pObject->IsWithinDist(go, m_fRange, false) && m_pObject->IsInPhase(go);
}
private:
const WorldObject* m_pObject;
@@ -1364,6 +1377,25 @@ namespace Trinity
uint64 _GUID;
};
+ class HeightDifferenceCheck
+ {
+ public:
+ HeightDifferenceCheck(WorldObject* go, float diff, bool reverse)
+ : _baseObject(go), _difference(diff), _reverse(reverse)
+ {
+ }
+
+ bool operator()(WorldObject* unit) const
+ {
+ return (unit->GetPositionZ() - _baseObject->GetPositionZ() > _difference) != _reverse;
+ }
+
+ private:
+ WorldObject* _baseObject;
+ float _difference;
+ bool _reverse;
+ };
+
class UnitAuraCheck
{
public:
diff --git a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
index 77b49fdfc8b..e73f18abf90 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
@@ -54,7 +54,7 @@ void Trinity::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m)
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -77,7 +77,7 @@ void Trinity::WorldObjectSearcher<Check>::Visit(PlayerMapType &m)
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -100,7 +100,7 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CreatureMapType &m)
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -123,7 +123,7 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CorpseMapType &m)
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -146,7 +146,7 @@ void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m)
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -157,6 +157,28 @@ void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m)
}
}
+template<class Check>
+void Trinity::WorldObjectSearcher<Check>::Visit(AreaTriggerMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
+ return;
+
+ // already found
+ if (i_object)
+ return;
+
+ for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->GetSource()->IsInPhase(_searcher))
+ continue;
+
+ if (i_check(itr->GetSource()))
+ {
+ i_object = itr->GetSource();
+ return;
+ }
+ }
+}
template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(GameObjectMapType &m)
@@ -166,7 +188,7 @@ void Trinity::WorldObjectLastSearcher<Check>::Visit(GameObjectMapType &m)
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -182,7 +204,7 @@ void Trinity::WorldObjectLastSearcher<Check>::Visit(PlayerMapType &m)
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -198,7 +220,7 @@ void Trinity::WorldObjectLastSearcher<Check>::Visit(CreatureMapType &m)
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -214,7 +236,7 @@ void Trinity::WorldObjectLastSearcher<Check>::Visit(CorpseMapType &m)
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -230,7 +252,23 @@ void Trinity::WorldObjectLastSearcher<Check>::Visit(DynamicObjectMapType &m)
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
+ continue;
+
+ if (i_check(itr->GetSource()))
+ i_object = itr->GetSource();
+ }
+}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(AreaTriggerMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
+ return;
+
+ for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -293,6 +331,17 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(DynamicObjectMapType &m)
i_objects.push_back(itr->GetSource());
}
+template<class Check>
+void Trinity::WorldObjectListSearcher<Check>::Visit(AreaTriggerMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_AREATRIGGER))
+ return;
+
+ for (AreaTriggerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ if (i_check(itr->GetSource()))
+ i_objects.push_back(itr->GetSource());
+}
+
// Gameobject searchers
template<class Check>
@@ -304,7 +353,7 @@ void Trinity::GameObjectSearcher<Check>::Visit(GameObjectMapType &m)
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -320,7 +369,7 @@ void Trinity::GameObjectLastSearcher<Check>::Visit(GameObjectMapType &m)
{
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -332,7 +381,7 @@ template<class Check>
void Trinity::GameObjectListSearcher<Check>::Visit(GameObjectMapType &m)
{
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
if (i_check(itr->GetSource()))
i_objects.push_back(itr->GetSource());
}
@@ -348,7 +397,7 @@ void Trinity::UnitSearcher<Check>::Visit(CreatureMapType &m)
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -368,7 +417,7 @@ void Trinity::UnitSearcher<Check>::Visit(PlayerMapType &m)
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -384,7 +433,7 @@ void Trinity::UnitLastSearcher<Check>::Visit(CreatureMapType &m)
{
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -397,7 +446,7 @@ void Trinity::UnitLastSearcher<Check>::Visit(PlayerMapType &m)
{
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -409,7 +458,7 @@ template<class Check>
void Trinity::UnitListSearcher<Check>::Visit(PlayerMapType &m)
{
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
if (i_check(itr->GetSource()))
i_objects.push_back(itr->GetSource());
}
@@ -418,7 +467,7 @@ template<class Check>
void Trinity::UnitListSearcher<Check>::Visit(CreatureMapType &m)
{
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
if (i_check(itr->GetSource()))
i_objects.push_back(itr->GetSource());
}
@@ -434,7 +483,7 @@ void Trinity::CreatureSearcher<Check>::Visit(CreatureMapType &m)
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -450,7 +499,7 @@ void Trinity::CreatureLastSearcher<Check>::Visit(CreatureMapType &m)
{
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -462,7 +511,7 @@ template<class Check>
void Trinity::CreatureListSearcher<Check>::Visit(CreatureMapType &m)
{
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
if (i_check(itr->GetSource()))
i_objects.push_back(itr->GetSource());
}
@@ -471,7 +520,7 @@ template<class Check>
void Trinity::PlayerListSearcher<Check>::Visit(PlayerMapType &m)
{
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->GetSource()->InSamePhase(i_phaseMask))
+ if (itr->GetSource()->IsInPhase(_searcher))
if (i_check(itr->GetSource()))
i_objects.push_back(itr->GetSource());
}
@@ -485,7 +534,7 @@ void Trinity::PlayerSearcher<Check>::Visit(PlayerMapType &m)
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -501,7 +550,7 @@ void Trinity::PlayerLastSearcher<Check>::Visit(PlayerMapType& m)
{
for (PlayerMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
{
- if (!itr->GetSource()->InSamePhase(i_phaseMask))
+ if (!itr->GetSource()->IsInPhase(_searcher))
continue;
if (i_check(itr->GetSource()))
@@ -526,7 +575,7 @@ void Trinity::LocalizedPacketDo<Builder>::operator()(Player* p)
i_builder(*data, loc_idx);
- ASSERT(data->GetOpcode() != MSG_NULL_ACTION);
+ ASSERT(data->GetOpcode() != NULL_OPCODE);
i_data_cache[cache_idx] = data;
}
diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp
index 51a1f2215f8..ab7a0e20512 100644
--- a/src/server/game/Grids/ObjectGridLoader.cpp
+++ b/src/server/game/Grids/ObjectGridLoader.cpp
@@ -24,6 +24,7 @@
#include "GameObject.h"
#include "DynamicObject.h"
#include "Corpse.h"
+#include "AreaTrigger.h"
#include "World.h"
#include "CellImpl.h"
#include "CreatureAI.h"
@@ -258,7 +259,9 @@ template void ObjectGridUnloader::Visit(CreatureMapType &);
template void ObjectGridUnloader::Visit(GameObjectMapType &);
template void ObjectGridUnloader::Visit(DynamicObjectMapType &);
template void ObjectGridUnloader::Visit(CorpseMapType &);
+template void ObjectGridUnloader::Visit(AreaTriggerMapType &);
template void ObjectGridCleaner::Visit(CreatureMapType &);
template void ObjectGridCleaner::Visit<GameObject>(GameObjectMapType &);
template void ObjectGridCleaner::Visit<DynamicObject>(DynamicObjectMapType &);
template void ObjectGridCleaner::Visit<Corpse>(CorpseMapType &);
+template void ObjectGridCleaner::Visit<AreaTrigger>(AreaTriggerMapType &);
diff --git a/src/server/game/Grids/ObjectGridLoader.h b/src/server/game/Grids/ObjectGridLoader.h
index 2ddc51848a8..1f351c6a0ba 100644
--- a/src/server/game/Grids/ObjectGridLoader.h
+++ b/src/server/game/Grids/ObjectGridLoader.h
@@ -40,6 +40,7 @@ class ObjectGridLoader
void Visit(CreatureMapType &m);
void Visit(CorpseMapType &) const { }
void Visit(DynamicObjectMapType&) const { }
+ void Visit(AreaTriggerMapType &) const { }
void LoadN(void);
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 2e7633091f3..e6f0b0f459a 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -267,6 +267,37 @@ void Group::ConvertToRaid()
player->UpdateForQuestWorldObjects();
}
+void Group::ConvertToGroup()
+{
+ if (m_memberSlots.size() > 5)
+ return; // What message error should we send?
+
+ m_groupType = GroupType(GROUPTYPE_NORMAL);
+
+ if (m_subGroupsCounts)
+ {
+ delete[] m_subGroupsCounts;
+ m_subGroupsCounts = NULL;
+ }
+
+ if (!isBGGroup() && !isBFGroup())
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_TYPE);
+
+ stmt->setUInt8(0, uint8(m_groupType));
+ stmt->setUInt32(1, m_dbStoreId);
+
+ CharacterDatabase.Execute(stmt);
+ }
+
+ 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 = ObjectAccessor::FindPlayer(citr->guid))
+ player->UpdateForQuestWorldObjects();
+}
+
bool Group::AddInvite(Player* player)
{
if (!player || player->GetGroupInvite())
@@ -437,7 +468,7 @@ bool Group::AddMember(Player* player)
// Broadcast new player group member fields to rest of the group
player->SetFieldNotifyFlag(UF_FLAG_PARTY_MEMBER);
- UpdateData groupData;
+ UpdateData groupData(player->GetMapId());
WorldPacket groupDataPacket;
// Broadcast group members' fields to player
@@ -457,7 +488,7 @@ bool Group::AddMember(Player* player)
if (member->HaveAtClient(player))
{
- UpdateData newData;
+ UpdateData newData(player->GetMapId());
WorldPacket newDataPacket;
player->BuildValuesUpdateBlockForPlayer(&newData, member);
if (newData.HasData())
@@ -785,6 +816,7 @@ void Group::SendLootStartRoll(uint32 countDown, uint32 mapid, const Roll &r)
data << uint32(r.itemCount); // items in stack
data << uint32(countDown); // the countdown time to choose "need" or "greed"
data << uint8(r.rollVoteMask); // roll type mask
+ data << uint8(r.totalPlayersRolling); // maybe the number of players rolling for it???
for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr != r.playerVote.end(); ++itr)
{
@@ -815,6 +847,7 @@ void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p,
if (!canNeed)
voteMask &= ~ROLL_FLAG_TYPE_NEED;
data << uint8(voteMask); // roll type mask
+ data << uint8(r.totalPlayersRolling); // maybe the number of players rolling for it???
p->GetSession()->SendPacket(&data);
}
@@ -828,7 +861,7 @@ void Group::SendLootRoll(uint64 sourceGuid, uint64 targetGuid, uint8 rollNumber,
data << uint32(roll.itemid); // the itemEntryId for the item that shall be rolled for
data << uint32(roll.itemRandomSuffix); // randomSuffix
data << uint32(roll.itemRandomPropId); // Item random property ID
- data << uint8(rollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number
+ data << uint32(rollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number
data << uint8(rollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll
data << uint8(0); // 1: "You automatically passed on: %s because you cannot loot that item." - Possibly used in need befor greed
@@ -852,7 +885,7 @@ void Group::SendLootRollWon(uint64 sourceGuid, uint64 targetGuid, uint8 rollNumb
data << uint32(roll.itemRandomSuffix); // randomSuffix
data << uint32(roll.itemRandomPropId); // Item random property
data << uint64(targetGuid); // guid of the player who won.
- data << uint8(rollNumber); // rollnumber realted to SMSG_LOOT_ROLL
+ data << uint32(rollNumber); // rollnumber realted to SMSG_LOOT_ROLL
data << uint8(rollType); // rollType related to SMSG_LOOT_ROLL
for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr)
@@ -1516,6 +1549,7 @@ void Group::SendUpdateToPlayer(uint64 playerGUID, MemberSlot* slot)
{
data << uint8(sLFGMgr->GetState(m_guid) == lfg::LFG_STATE_FINISHED_DUNGEON ? 2 : 0); // FIXME - Dungeon save status? 2 = done
data << uint32(sLFGMgr->GetDungeon(m_guid));
+ data << uint8(0); // 4.x new
}
data << uint64(m_guid);
@@ -1553,7 +1587,6 @@ void Group::SendUpdateToPlayer(uint64 playerGUID, MemberSlot* slot)
data << uint8(m_lootThreshold); // loot threshold
data << uint8(m_dungeonDifficulty); // Dungeon Difficulty
data << uint8(m_raidDifficulty); // Raid Difficulty
- data << uint8(m_raidDifficulty >= RAID_DIFFICULTY_10MAN_HEROIC); // 3.3 Dynamic Raid Difficulty - 0 normal/1 heroic
}
player->GetSession()->SendPacket(&data);
@@ -1576,6 +1609,21 @@ void Group::UpdatePlayerOutOfRange(Player* player)
}
}
+void Group::BroadcastAddonMessagePacket(WorldPacket* packet, const std::string& prefix, bool ignorePlayersInBGRaid, int group, uint64 ignore)
+{
+ for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ Player* player = itr->GetSource();
+ if (!player || (ignore != 0 && player->GetGUID() == ignore) || (ignorePlayersInBGRaid && player->GetGroup() != this))
+ continue;
+
+ if (WorldSession* session = player->GetSession())
+ if (session && (group == -1 || itr->getSubGroup() == group))
+ if (session->IsAddonRegistered(prefix))
+ session->SendPacket(packet);
+ }
+}
+
void Group::BroadcastPacket(WorldPacket* packet, bool ignorePlayersInBGRaid, int group, uint64 ignore)
{
for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
@@ -1784,7 +1832,7 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const*
BattlemasterListEntry const* bgEntry = sBattlemasterListStore.LookupEntry(bgOrTemplate->GetTypeID());
if (!bgEntry)
- return ERR_GROUP_JOIN_BATTLEGROUND_FAIL; // shouldn't happen
+ return ERR_BATTLEGROUND_JOIN_FAILED; // shouldn't happen
// check for min / max count
uint32 memberscount = GetMembersCount();
@@ -1849,7 +1897,7 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const*
if (bgOrTemplate->isArena() && memberscount != MinPlayerCount)
return ERR_ARENA_TEAM_PARTY_SIZE;
- return GroupJoinBattlegroundResult(bgOrTemplate->GetTypeID());
+ return ERR_BATTLEGROUND_NONE;
}
//===================================================
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index f0061a70621..2929c05cace 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -94,34 +94,38 @@ enum GroupType
enum GroupUpdateFlags
{
GROUP_UPDATE_FLAG_NONE = 0x00000000, // nothing
- GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16, flags
- 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 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, // 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 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
+ GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16 (GroupMemberStatusFlag)
+ GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint32 (HP)
+ GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint32 (HP)
+ GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000008, // uint8 (PowerType)
+ GROUP_UPDATE_FLAG_CUR_POWER = 0x00000010, // int16 (power value)
+ GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // int16 (power value)
+ GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16 (level value)
+ GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16 (zone id)
+ GROUP_UPDATE_FLAG_UNK100 = 0x00000100, // int16 (unk)
+ GROUP_UPDATE_FLAG_POSITION = 0x00000200, // uint16 (x), uint16 (y), uint16 (z)
+ GROUP_UPDATE_FLAG_AURAS = 0x00000400, // uint8 (unk), uint64 (mask), uint32 (count), for each bit set: uint32 (spell id) + uint16 (AuraFlags) (if has flags Scalable -> 3x int32 (bps))
+ GROUP_UPDATE_FLAG_PET_GUID = 0x00000800, // uint64 (pet guid)
+ GROUP_UPDATE_FLAG_PET_NAME = 0x00001000, // cstring (name, NULL terminated string)
+ GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00002000, // uint16 (model id)
+ GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00004000, // uint32 (HP)
+ GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00008000, // uint32 (HP)
+ GROUP_UPDATE_FLAG_PET_POWER_TYPE = 0x00010000, // uint8 (PowerType)
+ GROUP_UPDATE_FLAG_PET_CUR_POWER = 0x00020000, // uint16 (power value)
+ GROUP_UPDATE_FLAG_PET_MAX_POWER = 0x00040000, // uint16 (power value)
+ GROUP_UPDATE_FLAG_PET_AURAS = 0x00080000, // [see GROUP_UPDATE_FLAG_AURAS]
+ GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00100000, // int32 (vehicle seat id)
+ GROUP_UPDATE_FLAG_PHASE = 0x00200000, // int32 (unk), uint32 (phase count), for (count) uint16(phaseId)
+
+ GROUP_UPDATE_PET = GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID |
+ GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_POWER_TYPE |
+ GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER | GROUP_UPDATE_FLAG_PET_AURAS, // all pet flags
+ GROUP_UPDATE_FULL = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP |
+ GROUP_UPDATE_FLAG_POWER_TYPE | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER |
+ GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION |
+ GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_PET | GROUP_UPDATE_FLAG_PHASE // all known flags, except UNK100 and VEHICLE_SEAT
};
-#define GROUP_UPDATE_FLAGS_COUNT 20
- // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
-static const uint8 GroupUpdateLength[GROUP_UPDATE_FLAGS_COUNT] = { 0, 2, 2, 2, 1, 2, 2, 2, 2, 4, 8, 8, 1, 2, 2, 2, 1, 2, 2, 8};
-
class Roll : public LootValidatorRef
{
public:
@@ -242,6 +246,7 @@ class Group
void ConvertToLFG();
void ConvertToRaid();
+ void ConvertToGroup();
void SetBattlegroundGroup(Battleground* bg);
void SetBattlefieldGroup(Battlefield* bf);
@@ -270,6 +275,7 @@ class Group
void UpdatePlayerOutOfRange(Player* player);
// ignore: GUID of player that will be ignored
void BroadcastPacket(WorldPacket* packet, bool ignorePlayersInBGRaid, int group = -1, uint64 ignore = 0);
+ void BroadcastAddonMessagePacket(WorldPacket* packet, const std::string& prefix, bool ignorePlayersInBGRaid, int group = -1, uint64 ignore = 0);
void BroadcastReadyCheck(WorldPacket* packet);
void OfflineReadyCheck();
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 57e9a84d611..9e86039e4af 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -22,6 +22,7 @@
#include "Config.h"
#include "DatabaseEnv.h"
#include "Guild.h"
+#include "GuildFinderMgr.h"
#include "GuildMgr.h"
#include "Language.h"
#include "Log.h"
@@ -73,7 +74,7 @@ std::string _GetGuildEventString(GuildEvents event)
case GE_BANK_MONEY_SET:
return "Bank money set";
case GE_BANK_TAB_AND_MONEY_UPDATED:
- return "Bank and money updated";
+ return "Bank money changed";
case GE_BANK_TEXT_CHANGED:
return "Bank tab text changed";
default:
@@ -98,7 +99,10 @@ inline uint32 _GetGuildBankTabPrice(uint8 tabId)
void Guild::SendCommandResult(WorldSession* session, GuildCommandType type, GuildCommandError errCode, std::string const& param)
{
- WorldPacket data(SMSG_GUILD_COMMAND_RESULT, 8 + param.size() + 1);
+ // Note: SMSG_GUILD_COMMAND_RESULT and SMSG_GUILD_COMMAND_RESULT_2 do exactly the same in the client, they just have different structures.
+ // There's no particular reason why we use SMSG_GUILD_COMMAND_RESULT_2, this one is processed inmediately as it is read from the client.
+ // SMSG_GUILD_COMMAND_RESULT is a JAM opcode
+ WorldPacket data(SMSG_GUILD_COMMAND_RESULT_2, 8 + param.size() + 1);
data << uint32(type);
data << param;
data << uint32(errCode);
@@ -153,9 +157,13 @@ inline void Guild::LogHolder::AddEvent(SQLTransaction& trans, LogEntry* entry)
// Writes information about all events into packet.
inline void Guild::LogHolder::WritePacket(WorldPacket& data) const
{
- data << uint8(m_log.size());
+ ByteBuffer buffer;
+ data.WriteBits(m_log.size(), 23);
for (GuildLog::const_iterator itr = m_log.begin(); itr != m_log.end(); ++itr)
- (*itr)->WritePacket(data);
+ (*itr)->WritePacket(data, buffer);
+
+ data.FlushBits();
+ data.append(buffer);
}
inline uint32 Guild::LogHolder::GetNextGUID()
@@ -189,20 +197,56 @@ void Guild::EventLogEntry::SaveToDB(SQLTransaction& trans) const
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
-void Guild::EventLogEntry::WritePacket(WorldPacket& data) const
+void Guild::EventLogEntry::WritePacket(WorldPacket& data, ByteBuffer& content) const
{
- // Event type
- data << uint8(m_eventType);
- // Player 1
- data << uint64(MAKE_NEW_GUID(m_playerGuid1, 0, HIGHGUID_PLAYER));
- // Player 2 not for left/join guild events
- if (m_eventType != GUILD_EVENT_LOG_JOIN_GUILD && m_eventType != GUILD_EVENT_LOG_LEAVE_GUILD)
- data << uint64(MAKE_NEW_GUID(m_playerGuid2, 0, HIGHGUID_PLAYER));
- // New Rank - only for promote/demote guild events
- if (m_eventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || m_eventType == GUILD_EVENT_LOG_DEMOTE_PLAYER)
- data << uint8(m_newRank);
+ ObjectGuid guid1 = MAKE_NEW_GUID(m_playerGuid1, 0, HIGHGUID_PLAYER);
+ ObjectGuid guid2 = MAKE_NEW_GUID(m_playerGuid2, 0, HIGHGUID_PLAYER);
+
+ data.WriteBit(guid1[2]);
+ data.WriteBit(guid1[4]);
+ data.WriteBit(guid2[7]);
+ data.WriteBit(guid2[6]);
+ data.WriteBit(guid1[3]);
+ data.WriteBit(guid2[3]);
+ data.WriteBit(guid2[5]);
+ data.WriteBit(guid1[7]);
+ data.WriteBit(guid1[5]);
+ data.WriteBit(guid1[0]);
+ data.WriteBit(guid2[4]);
+ data.WriteBit(guid2[2]);
+ data.WriteBit(guid2[0]);
+ data.WriteBit(guid2[1]);
+ data.WriteBit(guid1[1]);
+ data.WriteBit(guid1[6]);
+
+ content.WriteByteSeq(guid2[3]);
+ content.WriteByteSeq(guid2[2]);
+ content.WriteByteSeq(guid2[5]);
+
+ // New Rank
+ content << uint8(m_newRank);
+
+ content.WriteByteSeq(guid2[4]);
+ content.WriteByteSeq(guid1[0]);
+ content.WriteByteSeq(guid1[4]);
+
// Event timestamp
- data << uint32(::time(NULL) - m_timestamp);
+ content << uint32(::time(NULL) - m_timestamp);
+
+ content.WriteByteSeq(guid1[7]);
+ content.WriteByteSeq(guid1[3]);
+ content.WriteByteSeq(guid2[0]);
+ content.WriteByteSeq(guid2[6]);
+ content.WriteByteSeq(guid2[7]);
+ content.WriteByteSeq(guid1[5]);
+
+ // Event type
+ content << uint8(m_eventType);
+
+ content.WriteByteSeq(guid2[1]);
+ content.WriteByteSeq(guid1[2]);
+ content.WriteByteSeq(guid1[6]);
+ content.WriteByteSeq(guid1[1]);
}
// BankEventLogEntry
@@ -230,29 +274,101 @@ void Guild::BankEventLogEntry::SaveToDB(SQLTransaction& trans) const
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
-void Guild::BankEventLogEntry::WritePacket(WorldPacket& data) const
+void Guild::BankEventLogEntry::WritePacket(WorldPacket& data, ByteBuffer& content) const
{
- data << uint8(m_eventType);
- data << uint64(MAKE_NEW_GUID(m_playerGuid, 0, HIGHGUID_PLAYER));
+ ObjectGuid logGuid = MAKE_NEW_GUID(m_playerGuid, 0, HIGHGUID_PLAYER);
- switch (m_eventType)
- {
- case GUILD_BANK_LOG_DEPOSIT_ITEM:
- case GUILD_BANK_LOG_WITHDRAW_ITEM:
- data << uint32(m_itemOrMoney);
- data << uint32(m_itemStackCount);
- break;
- case GUILD_BANK_LOG_MOVE_ITEM:
- case GUILD_BANK_LOG_MOVE_ITEM2:
- data << uint32(m_itemOrMoney);
- data << uint32(m_itemStackCount);
- data << uint8(m_destTabId);
- break;
- default:
- data << uint32(m_itemOrMoney);
- }
+ bool hasItem = m_eventType == GUILD_BANK_LOG_DEPOSIT_ITEM || m_eventType == GUILD_BANK_LOG_WITHDRAW_ITEM ||
+ m_eventType == GUILD_BANK_LOG_MOVE_ITEM || m_eventType == GUILD_BANK_LOG_MOVE_ITEM2;
+
+ bool itemMoved = (m_eventType == GUILD_BANK_LOG_MOVE_ITEM || m_eventType == GUILD_BANK_LOG_MOVE_ITEM2);
+
+ bool hasStack = (hasItem && m_itemStackCount > 1) || itemMoved;
- data << uint32(time(NULL) - m_timestamp);
+ data.WriteBit(IsMoneyEvent());
+ data.WriteBit(logGuid[4]);
+ data.WriteBit(logGuid[1]);
+ data.WriteBit(hasItem);
+ data.WriteBit(hasStack);
+ data.WriteBit(logGuid[2]);
+ data.WriteBit(logGuid[5]);
+ data.WriteBit(logGuid[3]);
+ data.WriteBit(logGuid[6]);
+ data.WriteBit(logGuid[0]);
+ data.WriteBit(itemMoved);
+ data.WriteBit(logGuid[7]);
+
+ content.WriteByteSeq(logGuid[6]);
+ content.WriteByteSeq(logGuid[1]);
+ content.WriteByteSeq(logGuid[5]);
+ if (hasStack)
+ content << uint32(m_itemStackCount);
+
+ content << uint8(m_eventType);
+ content.WriteByteSeq(logGuid[2]);
+ content.WriteByteSeq(logGuid[4]);
+ content.WriteByteSeq(logGuid[0]);
+ content.WriteByteSeq(logGuid[7]);
+ content.WriteByteSeq(logGuid[3]);
+ if (hasItem)
+ content << uint32(m_itemOrMoney);
+
+ content << uint32(time(NULL) - m_timestamp);
+
+ if (IsMoneyEvent())
+ content << uint64(m_itemOrMoney);
+
+ if (itemMoved)
+ content << uint8(m_destTabId);
+}
+
+void Guild::NewsLogEntry::SaveToDB(SQLTransaction& trans) const
+{
+ uint8 index = 0;
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_NEWS);
+ stmt->setUInt32( index, m_guildId);
+ stmt->setUInt32(++index, GetGUID());
+ stmt->setUInt8 (++index, GetType());
+ stmt->setUInt32(++index, GetPlayerGuid());
+ stmt->setUInt32(++index, GetFlags());
+ stmt->setUInt32(++index, GetValue());
+ stmt->setUInt64(++index, GetTimestamp());
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+}
+
+void Guild::NewsLogEntry::WritePacket(WorldPacket& data, ByteBuffer& /*content*/) const
+{
+ data.WriteBits(0, 26); // Not yet implemented used for guild achievements
+ ObjectGuid guid = GetPlayerGuid();
+
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(guid[5]);
+
+ data << uint32(GetFlags()); // 1 sticky
+ data << uint32(GetValue());
+ data << uint32(0); // always 0
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+
+ data << uint32(GetGUID());
+ data << uint32(GetType());
+ data.AppendPackedTime(GetTimestamp());
}
// RankInfo
@@ -302,20 +418,6 @@ void Guild::RankInfo::CreateMissingTabsIfNeeded(uint8 tabs, SQLTransaction& tran
}
}
-void Guild::RankInfo::WritePacket(WorldPacket& data) const
-{
- data << uint32(m_rights);
- if (m_bankMoneyPerDay == GUILD_WITHDRAW_MONEY_UNLIMITED)
- data << uint32(GUILD_WITHDRAW_MONEY_UNLIMITED);
- else
- data << uint32(m_bankMoneyPerDay);
- for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
- {
- data << uint32(m_bankTabRightsAndSlots[i].GetRights());
- data << uint32(m_bankTabRightsAndSlots[i].GetSlots());
- }
-}
-
void Guild::RankInfo::SetName(std::string const& name)
{
if (m_name == name)
@@ -444,64 +546,6 @@ void Guild::BankTab::Delete(SQLTransaction& trans, bool removeItemsFromDB)
}
}
-inline void Guild::BankTab::WritePacket(WorldPacket& data) const
-{
- uint8 count = 0;
-
- size_t pos = data.wpos();
- data << uint8(0);
-
- for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId)
- if (WriteSlotPacket(data, slotId))
- ++count;
-
- data.put<uint8>(pos, count);
-}
-
-// Writes information about contents of specified slot into packet.
-bool Guild::BankTab::WriteSlotPacket(WorldPacket& data, uint8 slotId, bool ignoreEmpty /* = true */) const
-{
- Item* pItem = GetItem(slotId);
- uint32 itemEntry = pItem ? pItem->GetEntry() : 0;
-
- if (!itemEntry && ignoreEmpty)
- return false;
-
- data << uint8(slotId);
- data << uint32(itemEntry);
- if (itemEntry)
- {
- data << uint32(0); // 3.3.0 (0x00018020, 0x00018000)
-
-
- if (uint32 random = pItem->GetItemRandomPropertyId())
- {
- data << uint32(random); // Random item property id
- data << uint32(pItem->GetItemSuffixFactor()); // SuffixFactor
- }
- else
- data << uint32(0);
-
- data << uint32(pItem->GetCount()); // ITEM_FIELD_STACK_COUNT
- data << uint32(0);
- data << uint8(abs(pItem->GetSpellCharges())); // Spell charges
-
- uint8 enchCount = 0;
- size_t enchCountPos = data.wpos();
-
- data << uint8(enchCount); // Number of enchantments
- for (uint32 i = PERM_ENCHANTMENT_SLOT; i < MAX_ENCHANTMENT_SLOT; ++i)
- if (uint32 enchId = pItem->GetEnchantmentId(EnchantmentSlot(i)))
- {
- data << uint8(i);
- data << uint32(enchId);
- ++enchCount;
- }
- data.put<uint8>(enchCountPos, enchCount);
- }
- return true;
-}
-
void Guild::BankTab::SetInfo(std::string const& name, std::string const& icon)
{
if (m_name == name && m_icon == icon)
@@ -567,19 +611,20 @@ bool Guild::BankTab::SetItem(SQLTransaction& trans, uint8 slotId, Item* item)
void Guild::BankTab::SendText(Guild const* guild, WorldSession* session) const
{
- WorldPacket data(MSG_QUERY_GUILD_BANK_TEXT, 1 + m_text.size() + 1);
- data << uint8(m_tabId);
- data << m_text;
+ WorldPacket data(SMSG_GUILD_BANK_QUERY_TEXT_RESULT, 1 + m_text.size() + 1);
+ data.WriteBits(m_text.length(), 14);
+ data << uint32(m_tabId);
+ data.WriteString(m_text);
if (session)
{
- TC_LOG_DEBUG("guild", "MSG_QUERY_GUILD_BANK_TEXT [%s]: Tabid: %u, Text: %s"
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_BANK_QUERY_TEXT_RESULT [%s]: Tabid: %u, Text: %s"
, session->GetPlayerInfo().c_str(), m_tabId, m_text.c_str());
session->SendPacket(&data);
}
else
{
- TC_LOG_DEBUG("guild", "MSG_QUERY_GUILD_BANK_TEXT [Broadcast]: Tabid: %u, Text: %s", m_tabId, m_text.c_str());
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_BANK_QUERY_TEXT_RESULT [Broadcast]: Tabid: %u, Text: %s", m_tabId, m_text.c_str());
guild->BroadcastPacket(&data);
}
}
@@ -592,15 +637,17 @@ void Guild::Member::SetStats(Player* player)
m_class = player->getClass();
m_zoneId = player->GetZoneId();
m_accountId = player->GetSession()->GetAccountId();
+ m_achievementPoints = player->GetAchievementPoints();
}
-void Guild::Member::SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId)
+void Guild::Member::SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId, uint32 reputation)
{
m_name = name;
m_level = level;
m_class = _class;
m_zoneId = zoneId;
m_accountId = accountId;
+ m_totalReputation = reputation;
}
void Guild::Member::SetPublicNote(std::string const& publicNote)
@@ -665,12 +712,16 @@ bool Guild::Member::LoadFromDB(Field* fields)
for (uint8 i = 0; i <= GUILD_BANK_MAX_TABS; ++i)
m_bankWithdraw[i] = fields[5 + i].GetUInt32();
- SetStats(fields[12].GetString(),
- fields[13].GetUInt8(), // characters.level
- fields[14].GetUInt8(), // characters.class
- fields[15].GetUInt16(), // characters.zone
- fields[16].GetUInt32()); // characters.account
- m_logoutTime = fields[17].GetUInt32(); // characters.logout_time
+ SetStats(fields[14].GetString(),
+ fields[15].GetUInt8(), // characters.level
+ fields[16].GetUInt8(), // characters.class
+ fields[17].GetUInt16(), // characters.zone
+ fields[18].GetUInt32(), // characters.account
+ 0);
+ m_logoutTime = fields[19].GetUInt32(); // characters.logout_time
+ m_totalActivity = 0;
+ m_weekActivity = 0;
+ m_weekReputation = 0;
if (!CheckStats())
return false;
@@ -701,28 +752,6 @@ bool Guild::Member::CheckStats() const
return true;
}
-void Guild::Member::WritePacket(WorldPacket& data, bool sendOfficerNote) const
-{
- data << uint64(m_guid)
- << uint8(m_flags)
- << m_name
- << uint32(m_rankId)
- << uint8(m_level)
- << uint8(m_class)
- << uint8(0)
- << uint32(m_zoneId);
-
- if (!m_flags)
- data << float(float(::time(NULL) - m_logoutTime) / DAY);
-
- data << m_publicNote;
-
- if (sendOfficerNote)
- data << m_officerNote;
- else
- data << "";
-}
-
// Decreases amount of money/slots left for today.
// If (tabId == GUILD_BANK_MAX_TABS) decrease money amount.
// Otherwise decrease remaining items amount for specified tab.
@@ -741,10 +770,16 @@ void Guild::Member::UpdateBankWithdrawValue(SQLTransaction& trans, uint8 tabId,
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
-void Guild::Member::ResetValues()
+void Guild::Member::ResetValues(bool weekly /* = false*/)
{
for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId)
m_bankWithdraw[tabId] = 0;
+
+ if (weekly)
+ {
+ m_weekActivity = 0;
+ m_weekReputation = 0;
+ }
}
// Get amount of money/slots left for today.
@@ -851,13 +886,13 @@ bool Guild::PlayerMoveItemData::InitItem()
// Anti-WPE protection. Do not move non-empty bags to bank.
if (m_pItem->IsNotEmptyBag())
{
- m_pPlayer->SendEquipError(EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS, m_pItem);
+ m_pPlayer->SendEquipError(EQUIP_ERR_DESTROY_NONEMPTY_BAG, m_pItem);
m_pItem = NULL;
}
// Bound items cannot be put into bank.
else if (!m_pItem->CanBeTraded())
{
- m_pPlayer->SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, m_pItem);
+ m_pPlayer->SendEquipError(EQUIP_ERR_CANT_SWAP, m_pItem);
m_pItem = NULL;
}
}
@@ -1082,11 +1117,11 @@ InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap)
uint32 count = pItem->GetCount();
// Soulbound items cannot be moved
if (pItem->IsSoulBound())
- return EQUIP_ERR_CANT_DROP_SOULBOUND;
+ return EQUIP_ERR_DROP_BOUND_ITEM;
// Make sure destination bank tab exists
if (m_container >= m_pGuild->_GetPurchasedTabsSize())
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ return EQUIP_ERR_WRONG_BAG_TYPE;
// Slot explicitely specified. Check it.
if (m_slotId != NULL_SLOT)
@@ -1097,7 +1132,7 @@ InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap)
pItemDest = NULL;
if (!_ReserveSpace(m_slotId, pItem, pItemDest, count))
- return EQUIP_ERR_ITEM_CANT_STACK;
+ return EQUIP_ERR_CANT_STACK;
if (count == 0)
return EQUIP_ERR_OK;
@@ -1127,7 +1162,12 @@ Guild::Guild():
m_createdDate(0),
m_accountsNumber(0),
m_bankMoney(0),
- m_eventLog(NULL)
+ m_eventLog(NULL),
+ m_newsLog(NULL),
+ m_achievementMgr(this),
+ _level(1),
+ _experience(0),
+ _todayExperience(0)
{
memset(&m_bankEventLog, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(LogHolder*));
}
@@ -1140,6 +1180,8 @@ Guild::~Guild()
// Cleanup
delete m_eventLog;
m_eventLog = NULL;
+ delete m_newsLog;
+ m_newsLog = NULL;
for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId)
{
@@ -1172,6 +1214,9 @@ bool Guild::Create(Player* pLeader, std::string const& name)
m_motd = "No message set.";
m_bankMoney = 0;
m_createdDate = ::time(NULL);
+ _level = 1;
+ _experience = 0;
+ _todayExperience = 0;
_CreateLogHolders();
TC_LOG_DEBUG("guild", "GUILD: creating guild [%s] for leader %s (%u)",
@@ -1204,7 +1249,10 @@ bool Guild::Create(Player* pLeader, std::string const& name)
bool ret = AddMember(m_leaderGuid, GR_GUILDMASTER); // Add guildmaster
if (ret)
+ {
+ _BroadcastEvent(GE_FOUNDER, 0);
sScriptMgr->OnGuildCreate(this, pLeader, name);
+ }
return ret;
}
@@ -1257,9 +1305,28 @@ void Guild::Disband()
trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans);
+
+ sGuildFinderMgr->DeleteGuild(m_id);
+
sGuildMgr->RemoveGuild(m_id);
}
+void Guild::SaveToDB()
+{
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_EXPERIENCE);
+ stmt->setUInt32(0, GetLevel());
+ stmt->setUInt64(1, GetExperience());
+ stmt->setUInt64(2, GetTodayExperience());
+ stmt->setUInt32(3, GetId());
+ trans->Append(stmt);
+
+ m_achievementMgr.SaveToDB(trans);
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
void Guild::UpdateMemberData(Player* player, uint8 dataid, uint32 value)
{
if (Member* member = GetMember(player->GetGUID()))
@@ -1267,7 +1334,10 @@ void Guild::UpdateMemberData(Player* player, uint8 dataid, uint32 value)
switch (dataid)
{
case GUILD_MEMBER_DATA_ZONEID:
- member->SetZoneID(value);
+ member->SetZoneId(value);
+ break;
+ case GUILD_MEMBER_DATA_ACHIEVEMENT_POINTS:
+ member->SetAchievementPoints(value);
break;
case GUILD_MEMBER_DATA_LEVEL:
member->SetLevel(value);
@@ -1300,23 +1370,113 @@ bool Guild::SetName(std::string const& name)
stmt->setString(0, m_name);
stmt->setUInt32(1, GetId());
CharacterDatabase.Execute(stmt);
+
+ ObjectGuid guid = GetGUID();
+ WorldPacket data(SMSG_GUILD_RENAMED, 24 + 8 + 1);
+ data.WriteBit(guid[5]);
+ data.WriteBits(name.length(), 8);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[2]);
+
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteString(name);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[5]);
+
+ BroadcastPacket(&data);
return true;
}
void Guild::HandleRoster(WorldSession* session)
{
+ ByteBuffer memberData(100);
// Guess size
- WorldPacket data(SMSG_GUILD_ROSTER, (4 + m_motd.length() + 1 + m_info.length() + 1 + 4 + _GetRanksSize() * (4 + 4 + GUILD_BANK_MAX_TABS * (4 + 4)) + m_members.size() * 50));
- data << uint32(m_members.size());
- data << m_motd;
- data << m_info;
-
- data << uint32(_GetRanksSize());
- for (Ranks::const_iterator ritr = m_ranks.begin(); ritr != m_ranks.end(); ++ritr)
- ritr->WritePacket(data);
+ WorldPacket data(SMSG_GUILD_ROSTER, 100);
+ data.WriteBits(m_motd.length(), 11);
+ data.WriteBits(m_members.size(), 18);
for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
- itr->second->WritePacket(data, _HasRankRight(session->GetPlayer(), GR_RIGHT_VIEWOFFNOTE));
+ {
+ Member* member = itr->second;
+ size_t pubNoteLength = member->GetPublicNote().length();
+ size_t offNoteLength = member->GetOfficerNote().length();
+
+ ObjectGuid guid = member->GetGUID();
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(0); // Has Authenticator
+ data.WriteBit(0); // Can Scroll of Ressurect
+ data.WriteBits(pubNoteLength, 8);
+ data.WriteBits(offNoteLength, 8);
+ data.WriteBit(guid[0]);
+ data.WriteBits(member->GetName().length(), 7);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[7]);
+
+ memberData << uint8(member->GetClass());
+ memberData << uint32(member->GetTotalReputation());
+ memberData.WriteByteSeq(guid[0]);
+ memberData << uint64(member->GetWeekActivity());
+ memberData << uint32(member->GetRankId());
+ memberData << uint32(member->GetAchievementPoints());
+
+ // for (2 professions)
+ memberData << uint32(0) << uint32(0) << uint32(0);
+ memberData << uint32(0) << uint32(0) << uint32(0);
+
+ memberData.WriteByteSeq(guid[2]);
+ memberData << uint8(member->GetFlags());
+ memberData << uint32(member->GetZoneId());
+ memberData << uint64(member->GetTotalActivity());
+ memberData.WriteByteSeq(guid[7]);
+ memberData << uint32(sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP) - member->GetWeekReputation());
+
+ if (pubNoteLength)
+ memberData.WriteString(member->GetPublicNote());
+
+ memberData.WriteByteSeq(guid[3]);
+ memberData << uint8(member->GetLevel());
+ memberData << int32(0); // unk
+ memberData.WriteByteSeq(guid[5]);
+ memberData.WriteByteSeq(guid[4]);
+ memberData << uint8(0); // unk
+ memberData.WriteByteSeq(guid[1]);
+ memberData << float(member->IsOnline() ? 0.0f : float(::time(NULL) - member->GetLogoutTime()) / DAY);
+
+ if (offNoteLength)
+ memberData.WriteString(member->GetOfficerNote());
+
+ memberData.WriteByteSeq(guid[6]);
+ memberData.WriteString(member->GetName());
+ }
+
+ size_t infoLength = m_info.length();
+ data.WriteBits(infoLength, 12);
+
+ data.FlushBits();
+ data.append(memberData);
+
+ if (infoLength)
+ data.WriteString(m_info);
+
+ data.WriteString(m_motd);
+ data << uint32(m_accountsNumber);
+ data << uint32(sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP));
+ data.AppendPackedTime(m_createdDate);
+ data << uint32(0);
TC_LOG_DEBUG("guild", "SMSG_GUILD_ROSTER [%s]", session->GetPlayerInfo().c_str());
session->SendPacket(&data);
@@ -1325,7 +1485,8 @@ void Guild::HandleRoster(WorldSession* session)
void Guild::HandleQuery(WorldSession* session)
{
WorldPacket data(SMSG_GUILD_QUERY_RESPONSE, 8 * 32 + 200); // Guess size
- data << uint32(m_id);
+
+ data << uint64(GetGUID());
data << m_name;
// Rank name
@@ -1337,6 +1498,24 @@ void Guild::HandleQuery(WorldSession* session)
data << uint8(0); // Empty string
}
+ // Rank order of creation
+ for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i)
+ {
+ if (i < _GetRanksSize())
+ data << uint32(i);
+ else
+ data << uint32(0);
+ }
+
+ // Rank order of "importance" (sorting by rights)
+ for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i)
+ {
+ if (i < _GetRanksSize())
+ data << uint32(m_ranks[i].GetId());
+ else
+ data << uint32(0);
+ }
+
m_emblemInfo.WritePacket(data);
data << uint32(_GetRanksSize()); // Number of ranks used
@@ -1344,6 +1523,44 @@ void Guild::HandleQuery(WorldSession* session)
TC_LOG_DEBUG("guild", "SMSG_GUILD_QUERY_RESPONSE [%s]", session->GetPlayerInfo().c_str());
}
+void Guild::SendGuildRankInfo(WorldSession* session) const
+{
+ ByteBuffer rankData(100);
+ WorldPacket data(SMSG_GUILD_RANK, 100);
+
+ data.WriteBits(_GetRanksSize(), 18);
+
+ for (uint8 i = 0; i < _GetRanksSize(); i++)
+ {
+ RankInfo const* rankInfo = GetRankInfo(i);
+ if (!rankInfo)
+ continue;
+
+ data.WriteBits(rankInfo->GetName().length(), 7);
+
+ rankData << uint32(rankInfo->GetId());
+
+ for (uint8 j = 0; j < GUILD_BANK_MAX_TABS; ++j)
+ {
+ rankData << uint32(rankInfo->GetBankTabSlotsPerDay(j));
+ rankData << uint32(rankInfo->GetBankTabRights(j));
+ }
+
+ rankData << uint32(rankInfo->GetBankMoneyPerDay());
+ rankData << uint32(rankInfo->GetRights());
+
+ if (rankInfo->GetName().length())
+ rankData.WriteString(rankInfo->GetName());
+
+ rankData << uint32(i);
+ }
+
+ data.FlushBits();
+ data.append(rankData);
+ session->SendPacket(&data);
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_RANK [%s]", session->GetPlayerInfo().c_str());
+}
+
void Guild::HandleSetMOTD(WorldSession* session, std::string const& motd)
{
if (m_motd == motd)
@@ -1391,11 +1608,11 @@ void Guild::HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo)
Player* player = session->GetPlayer();
if (!_IsLeader(player))
SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTGUILDMASTER); // "Only guild leaders can create emblems."
- else if (!player->HasEnoughMoney(EMBLEM_PRICE))
+ else if (!player->HasEnoughMoney(uint64(EMBLEM_PRICE)))
SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTENOUGHMONEY); // "You can't afford to do that."
else
{
- player->ModifyMoney(-int32(EMBLEM_PRICE));
+ player->ModifyMoney(-int64(EMBLEM_PRICE));
m_emblemInfo = emblemInfo;
m_emblemInfo.SaveToDB(m_id);
@@ -1406,20 +1623,20 @@ void Guild::HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo)
}
}
-void Guild::HandleSetLeader(WorldSession* session, std::string const& name)
+void Guild::HandleSetNewGuildMaster(WorldSession* session, std::string const& name)
{
Player* player = session->GetPlayer();
- // Only leader can assign new leader
+ // Only the guild master can throne a new guild master
if (!_IsLeader(player))
SendCommandResult(session, GUILD_COMMAND_CHANGE_LEADER, ERR_GUILD_PERMISSIONS);
- // Old leader must be a member of guild
- else if (Member* pOldLeader = GetMember(player->GetGUID()))
+ // Old GM must be a guild member
+ else if (Member* oldGuildMaster = GetMember(player->GetGUID()))
{
- // New leader must be a member of guild
- if (Member* pNewLeader = GetMember(name))
+ // Same for the new one
+ if (Member* newGuildMaster = GetMember(name))
{
- _SetLeaderGUID(pNewLeader);
- pOldLeader->ChangeRank(GR_OFFICER);
+ _SetLeaderGUID(newGuildMaster);
+ oldGuildMaster->ChangeRank(GR_INITIATE);
_BroadcastEvent(GE_LEADER_CHANGED, 0, player->GetName().c_str(), name.c_str());
}
}
@@ -1442,19 +1659,19 @@ void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string
_BroadcastEvent(GE_BANK_TAB_UPDATED, 0, aux, name.c_str(), icon.c_str());
}
-void Guild::HandleSetMemberNote(WorldSession* session, std::string const& name, std::string const& note, bool isPublic)
+void Guild::HandleSetMemberNote(WorldSession* session, std::string const& note, uint64 guid, bool isPublic)
{
// Player must have rights to set public/officer note
if (!_HasRankRight(session->GetPlayer(), isPublic ? GR_RIGHT_EPNOTE : GR_RIGHT_EOFFNOTE))
SendCommandResult(session, GUILD_COMMAND_PUBLIC_NOTE, ERR_GUILD_PERMISSIONS);
- else if (Member* member = GetMember(name))
+ else if (Member* member = GetMember(guid))
{
if (isPublic)
member->SetPublicNote(note);
else
member->SetOfficerNote(note);
- HandleRoster(session);
+ HandleRoster(session); // FIXME - We should send SMSG_GUILD_MEMBER_UPDATE_NOTE
}
}
@@ -1476,7 +1693,7 @@ void Guild::HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string c
char aux[2];
sprintf(aux, "%u", rankId);
- _BroadcastEvent(GE_RANK_UPDATED, 0, aux, name.c_str());
+ _BroadcastEvent(GE_RANK_UPDATED, 0, aux);
}
}
@@ -1496,14 +1713,19 @@ void Guild::HandleBuyBankTab(WorldSession* session, uint8 tabId)
if (tabId != _GetPurchasedTabsSize())
return;
- uint32 tabCost = _GetGuildBankTabPrice(tabId) * GOLD;
- if (!tabCost)
- return;
+ // Do not get money for bank tabs that the GM bought, we had to buy them already.
+ // This is just a speedup check, GetGuildBankTabPrice will return 0.
+ if (tabId < GUILD_BANK_MAX_TABS - 2) // 7th tab is actually the 6th
+ {
+ uint32 tabCost = _GetGuildBankTabPrice(tabId) * GOLD;
+ if (!tabCost)
+ return;
- if (!player->HasEnoughMoney(tabCost)) // Should not happen, this is checked by client
- return;
+ if (!player->HasEnoughMoney(uint64(tabCost))) // Should not happen, this is checked by client
+ return;
- player->ModifyMoney(-int32(tabCost));
+ player->ModifyMoney(-int64(tabCost));
+ }
_CreateNewBankTab();
_BroadcastEvent(GE_BANK_TAB_PURCHASED, 0);
@@ -1529,12 +1751,14 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_NOT_ALLIED, name);
return;
}
+
// Invited player cannot be in another guild
- if (pInvitee->GetGuildId())
+ /*if (pInvitee->GetGuildId())
{
SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_ALREADY_IN_GUILD_S, name);
return;
- }
+ }*/
+
// Invited player cannot be invited
if (pInvitee->GetGuildIdInvited())
{
@@ -1555,9 +1779,65 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
pInvitee->SetGuildIdInvited(m_id);
_LogEvent(GUILD_EVENT_LOG_INVITE_PLAYER, player->GetGUIDLow(), pInvitee->GetGUIDLow());
- WorldPacket data(SMSG_GUILD_INVITE, 8 + 10); // Guess size
- data << player->GetName();
- data << m_name;
+ WorldPacket data(SMSG_GUILD_INVITE, 100);
+ data << uint32(GetLevel());
+ data << uint32(m_emblemInfo.GetBorderStyle());
+ data << uint32(m_emblemInfo.GetBorderColor());
+ data << uint32(m_emblemInfo.GetStyle());
+ data << uint32(m_emblemInfo.GetBackgroundColor());
+ data << uint32(m_emblemInfo.GetColor());
+
+ ObjectGuid oldGuildGuid = MAKE_NEW_GUID(pInvitee->GetGuildId(), 0, pInvitee->GetGuildId() ? uint32(HIGHGUID_GUILD) : 0);
+ ObjectGuid newGuildGuid = GetGUID();
+
+ data.WriteBit(newGuildGuid[3]);
+ data.WriteBit(newGuildGuid[2]);
+ data.WriteBits(pInvitee->GetGuildName().length(), 8);
+ data.WriteBit(newGuildGuid[1]);
+ data.WriteBit(oldGuildGuid[6]);
+ data.WriteBit(oldGuildGuid[4]);
+ data.WriteBit(oldGuildGuid[1]);
+ data.WriteBit(oldGuildGuid[5]);
+ data.WriteBit(oldGuildGuid[7]);
+ data.WriteBit(oldGuildGuid[2]);
+ data.WriteBit(newGuildGuid[7]);
+ data.WriteBit(newGuildGuid[0]);
+ data.WriteBit(newGuildGuid[6]);
+ data.WriteBits(m_name.length(), 8);
+ data.WriteBit(oldGuildGuid[3]);
+ data.WriteBit(oldGuildGuid[0]);
+ data.WriteBit(newGuildGuid[5]);
+ data.WriteBits(player->GetName().size(), 7);
+ data.WriteBit(newGuildGuid[4]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(newGuildGuid[1]);
+ data.WriteByteSeq(oldGuildGuid[3]);
+ data.WriteByteSeq(newGuildGuid[6]);
+ data.WriteByteSeq(oldGuildGuid[2]);
+ data.WriteByteSeq(oldGuildGuid[1]);
+ data.WriteByteSeq(newGuildGuid[0]);
+
+ if (!pInvitee->GetGuildName().empty())
+ data.WriteString(pInvitee->GetGuildName());
+
+ data.WriteByteSeq(newGuildGuid[7]);
+ data.WriteByteSeq(newGuildGuid[2]);
+
+ data.WriteString(player->GetName());
+
+ data.WriteByteSeq(oldGuildGuid[7]);
+ data.WriteByteSeq(oldGuildGuid[6]);
+ data.WriteByteSeq(oldGuildGuid[5]);
+ data.WriteByteSeq(oldGuildGuid[0]);
+ data.WriteByteSeq(newGuildGuid[4]);
+
+ data.WriteString(m_name);
+
+ data.WriteByteSeq(newGuildGuid[5]);
+ data.WriteByteSeq(newGuildGuid[3]);
+ data.WriteByteSeq(oldGuildGuid[4]);
pInvitee->GetSession()->SendPacket(&data);
TC_LOG_DEBUG("guild", "SMSG_GUILD_INVITE [%s]", pInvitee->GetName().c_str());
}
@@ -1583,6 +1863,8 @@ void Guild::HandleLeaveMember(WorldSession* session)
if (m_members.size() > 1)
// Leader cannot leave if he is not the last member
SendCommandResult(session, GUILD_COMMAND_QUIT, ERR_GUILD_LEADER_LEAVE);
+ else if (GetLevel() >= sWorld->getIntConfig(CONFIG_GUILD_UNDELETABLE_LEVEL))
+ SendCommandResult(session, GUILD_COMMAND_QUIT, ERR_GUILD_UNDELETABLE_DUE_TO_LEVEL);
else
{
// Guild is disbanded if leader leaves.
@@ -1606,14 +1888,17 @@ void Guild::HandleLeaveMember(WorldSession* session)
delete this;
}
-void Guild::HandleRemoveMember(WorldSession* session, std::string const& name)
+void Guild::HandleRemoveMember(WorldSession* session, uint64 guid)
{
Player* player = session->GetPlayer();
+
// Player must have rights to remove members
if (!_HasRankRight(player, GR_RIGHT_REMOVE))
SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_PERMISSIONS);
- else if (Member* member = GetMember(name))
+ else if (Member* member = GetMember(guid))
{
+ std::string name = member->GetName();
+
// Guild masters cannot be removed
if (member->IsRank(GR_GUILDMASTER))
SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_LEADER_LEAVE);
@@ -1625,17 +1910,17 @@ void Guild::HandleRemoveMember(WorldSession* session, std::string const& name)
SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_RANK_TOO_HIGH_S, name);
else
{
- uint64 guid = member->GetGUID();
// After call to DeleteMember pointer to member becomes invalid
DeleteMember(guid, false, true);
_LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUIDLow(), GUID_LOPART(guid));
_BroadcastEvent(GE_REMOVED, 0, name.c_str(), player->GetName().c_str());
+ SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_COMMAND_SUCCESS, name);
}
}
}
}
-void Guild::HandleUpdateMemberRank(WorldSession* session, std::string const& name, bool demote)
+void Guild::HandleUpdateMemberRank(WorldSession* session, uint64 guid, bool demote)
{
Player* player = session->GetPlayer();
GuildCommandType type = demote ? GUILD_COMMAND_DEMOTE : GUILD_COMMAND_PROMOTE;
@@ -1643,8 +1928,9 @@ void Guild::HandleUpdateMemberRank(WorldSession* session, std::string const& nam
if (!_HasRankRight(player, demote ? GR_RIGHT_DEMOTE : GR_RIGHT_PROMOTE))
SendCommandResult(session, type, ERR_GUILD_PERMISSIONS);
// Promoted player must be a member of guild
- else if (Member* member = GetMember(name))
+ else if (Member* member = GetMember(guid))
{
+ std::string name = member->GetName();
// Player cannot promote himself
if (member->IsSamePlayer(player->GetGUID()))
{
@@ -1687,6 +1973,36 @@ void Guild::HandleUpdateMemberRank(WorldSession* session, std::string const& nam
}
}
+void Guild::HandleSetMemberRank(WorldSession* session, uint64 targetGuid, uint64 setterGuid, uint32 rank)
+{
+ Player* player = session->GetPlayer();
+ Member* member = GetMember(targetGuid);
+ GuildRankRights rights = GR_RIGHT_PROMOTE;
+ GuildCommandType type = GUILD_COMMAND_PROMOTE;
+
+ if (rank > member->GetRankId())
+ {
+ rights = GR_RIGHT_DEMOTE;
+ type = GUILD_COMMAND_DEMOTE;
+ }
+
+ // Promoted player must be a member of guild
+ if (!_HasRankRight(player, rights))
+ {
+ SendCommandResult(session, type, ERR_GUILD_PERMISSIONS);
+ return;
+ }
+
+ // Player cannot promote himself
+ if (member->IsSamePlayer(player->GetGUID()))
+ {
+ SendCommandResult(session, type, ERR_GUILD_NAME_INVALID);
+ return;
+ }
+
+ SendGuildRanksUpdate(setterGuid, targetGuid, rank);
+}
+
void Guild::HandleAddNewRank(WorldSession* session, std::string const& name)
{
uint8 size = _GetRanksSize();
@@ -1696,16 +2012,7 @@ void Guild::HandleAddNewRank(WorldSession* session, std::string const& name)
// Only leader can add new rank
if (_IsLeader(session->GetPlayer()))
if (_CreateRank(name, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK))
- {
- char aux[2];
- sprintf(aux, "%u", size);
- _BroadcastEvent(GE_RANK_UPDATED, 0, aux, name.c_str());
- }
-}
-
-void Guild::HandleRemoveLowestRank(WorldSession* session)
-{
- HandleRemoveRank(session, _GetLowestRankId());
+ _BroadcastEvent(GE_RANK_CREATED, 0);
}
void Guild::HandleRemoveRank(WorldSession* session, uint8 rankId)
@@ -1720,17 +2027,17 @@ void Guild::HandleRemoveRank(WorldSession* session, uint8 rankId)
stmt->setUInt8(1, rankId);
CharacterDatabase.Execute(stmt);
// Delete rank
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_LOWEST_RANK);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_RANK);
stmt->setUInt32(0, m_id);
stmt->setUInt8(1, rankId);
CharacterDatabase.Execute(stmt);
- m_ranks.pop_back();
+ m_ranks.erase(m_ranks.begin() + rankId);
- _BroadcastEvent(GE_RANK_DELETED, 0);
+ _BroadcastEvent(GE_RANK_DELETED, rankId);
}
-void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount)
+void Guild::HandleMemberDepositMoney(WorldSession* session, uint64 amount, bool cashFlow /*=false*/)
{
Player* player = session->GetPlayer();
@@ -1739,11 +2046,13 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount)
SQLTransaction trans = CharacterDatabase.BeginTransaction();
_ModifyBankMoney(trans, amount, true);
+ if (!cashFlow)
+ {
+ player->ModifyMoney(-int64(amount));
+ player->SaveGoldToDB(trans);
+ }
- player->ModifyMoney(-int32(amount));
- player->SaveGoldToDB(trans);
- _LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), player->GetGUIDLow(), amount);
-
+ _LogBankEvent(trans, cashFlow ? GUILD_BANK_LOG_CASH_FLOW_DEPOSIT : GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), player->GetGUIDLow(), amount);
CharacterDatabase.CommitTransaction(trans);
std::string aux = ByteArrayToHexStr(reinterpret_cast<uint8*>(&m_bankMoney), 8, true);
@@ -1752,15 +2061,15 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount)
if (player->GetSession()->HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
sLog->outCommand(player->GetSession()->GetAccountId(),
- "GM %s (Account: %u) deposit money (Amount: %u) to guild bank (Guild ID %u)",
+ "GM %s (Account: %u) deposit money (Amount: " UI64FMTD ") to guild bank (Guild ID %u)",
player->GetName().c_str(), player->GetSession()->GetAccountId(), amount, m_id);
}
}
-bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair)
+bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint64 amount, bool repair)
{
- //clamp amount to MAX_MONEY_AMOUNT, Players can't hold more than that anyway
- amount = std::min(amount, MAX_MONEY_AMOUNT);
+ // clamp amount to MAX_MONEY_AMOUNT, Players can't hold more than that anyway
+ amount = std::min(amount, uint64(MAX_MONEY_AMOUNT));
if (m_bankMoney < amount) // Not enough money in bank
return false;
@@ -1771,7 +2080,7 @@ bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool
if (!member)
return false;
- if (uint32(_GetMemberRemainingMoney(member)) < amount) // Check if we have enough slot/money today
+ if (uint64(_GetMemberRemainingMoney(member)) < amount) // Check if we have enough slot/money today
return false;
// Call script after validation and before money transfer.
@@ -1811,6 +2120,8 @@ void Guild::HandleMemberLogout(WorldSession* session)
member->ResetFlags();
}
_BroadcastEvent(GE_SIGNED_OFF, player->GetGUID(), player->GetName().c_str());
+
+ SaveToDB();
}
void Guild::HandleDisband(WorldSession* session)
@@ -1824,50 +2135,104 @@ void Guild::HandleDisband(WorldSession* session)
}
}
-// Send data to client
-void Guild::SendInfo(WorldSession* session) const
+void Guild::HandleGuildPartyRequest(WorldSession* session)
{
- WorldPacket data(SMSG_GUILD_INFO, m_name.size() + 4 + 4 + 4);
- data << m_name;
- data.AppendPackedTime(m_createdDate); // 3.x (prev. year + month + day)
- data << uint32(m_members.size()); // Number of members
- data << m_accountsNumber; // Number of accounts
+ Player* player = session->GetPlayer();
+ Group* group = player->GetGroup();
+
+ // Make sure player is a member of the guild and that he is in a group.
+ if (!IsMember(player->GetGUID()) || !group)
+ return;
+
+ WorldPacket data(SMSG_GUILD_PARTY_STATE_RESPONSE, 13);
+ data.WriteBit(player->GetMap()->GetOwnerGuildId(player->GetTeam()) == GetId()); // Is guild group
+ data.FlushBits();
+ data << float(0.f); // Guild XP multiplier
+ data << uint32(0); // Current guild members
+ data << uint32(0); // Needed guild members
session->SendPacket(&data);
- TC_LOG_DEBUG("guild", "SMSG_GUILD_INFO [%s]", session->GetPlayerInfo().c_str());
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_PARTY_STATE_RESPONSE [%s]", session->GetPlayerInfo().c_str());
}
void Guild::SendEventLog(WorldSession* session) const
{
- WorldPacket data(MSG_GUILD_EVENT_LOG_QUERY, 1 + m_eventLog->GetSize() * (1 + 8 + 4));
+ WorldPacket data(SMSG_GUILD_EVENT_LOG_QUERY_RESULT, 1 + m_eventLog->GetSize() * (1 + 8 + 4));
m_eventLog->WritePacket(data);
session->SendPacket(&data);
- TC_LOG_DEBUG("guild", "MSG_GUILD_EVENT_LOG_QUERY [%s]", session->GetPlayerInfo().c_str());
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_EVENT_LOG_QUERY_RESULT [%s]", session->GetPlayerInfo().c_str());
}
-void Guild::SendBankLog(WorldSession* session, uint8 tabId) const
+void Guild::SendNewsUpdate(WorldSession* session)
{
- // GUILD_BANK_MAX_TABS send by client for money log
- if (tabId < _GetPurchasedTabsSize() || tabId == GUILD_BANK_MAX_TABS)
+ uint32 size = m_newsLog->GetSize();
+ GuildLog* logs = m_newsLog->GetGuildLog();
+
+ if (!logs)
+ return;
+
+ WorldPacket data(SMSG_GUILD_NEWS_UPDATE, (21 + size * (26 + 8)) / 8 + (8 + 6 * 4) * size);
+ data.WriteBits(size, 21);
+
+ for (GuildLog::const_iterator itr = logs->begin(); itr != logs->end(); ++itr)
{
- const LogHolder* pLog = m_bankEventLog[tabId];
- WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, pLog->GetSize() * (4 * 4 + 1) + 1 + 1);
- data << uint8(tabId);
- pLog->WritePacket(data);
- session->SendPacket(&data);
- TC_LOG_DEBUG("guild", "MSG_GUILD_BANK_LOG_QUERY [%s]", session->GetPlayerInfo().c_str());
+ data.WriteBits(0, 26); // Not yet implemented used for guild achievements
+ ObjectGuid guid = ((NewsLogEntry*)(*itr))->GetPlayerGuid();
+
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[2]);
}
-}
-void Guild::SendBankTabData(WorldSession* session, uint8 tabId) const
-{
- if (tabId < _GetPurchasedTabsSize())
- _SendBankContent(session, tabId);
+ data.FlushBits();
+
+ for (GuildLog::const_iterator itr = logs->begin(); itr != logs->end(); ++itr)
+ {
+ NewsLogEntry* news = (NewsLogEntry*)(*itr);
+ ObjectGuid guid = news->GetPlayerGuid();
+ data.WriteByteSeq(guid[5]);
+
+ data << uint32(news->GetFlags()); // 1 sticky
+ data << uint32(news->GetValue());
+ data << uint32(0);
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[6]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+
+ data << uint32(news->GetGUID());
+ data << uint32(news->GetType());
+ data.AppendPackedTime(news->GetTimestamp());
+ }
+
+ session->SendPacket(&data);
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_NEWS_UPDATE [%s]", session->GetPlayerInfo().c_str());
}
-void Guild::SendBankTabsInfo(WorldSession* session, bool sendAllSlots /*= false*/) const
+void Guild::SendBankLog(WorldSession* session, uint8 tabId) const
{
- _SendBankList(session, 0, sendAllSlots);
+ // GUILD_BANK_MAX_TABS send by client for money log
+ if (tabId < _GetPurchasedTabsSize() || tabId == GUILD_BANK_MAX_TABS)
+ {
+ LogHolder const* log = m_bankEventLog[tabId];
+ WorldPacket data(SMSG_GUILD_BANK_LOG_QUERY_RESULT, log->GetSize() * (4 * 4 + 1) + 1 + 1);
+ data.WriteBit(GetLevel() >= 5 && tabId == GUILD_BANK_MAX_TABS); // has Cash Flow perk
+ log->WritePacket(data);
+ data << uint32(tabId);
+ //if (tabId == GUILD_BANK_MAX_TABS && hasCashFlow)
+ // data << uint64(cashFlowContribution);
+ session->SendPacket(&data);
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_BANK_LOG_QUERY_RESULT [%s] TabId: %u", session->GetPlayerInfo().c_str(), tabId);
+ }
}
void Guild::SendBankTabText(WorldSession* session, uint8 tabId) const
@@ -1884,11 +2249,12 @@ void Guild::SendPermissions(WorldSession* session) const
uint8 rankId = member->GetRankId();
- WorldPacket data(MSG_GUILD_PERMISSIONS, 4 * 15 + 1);
+ WorldPacket data(SMSG_GUILD_PERMISSIONS_QUERY_RESULTS, 4 * 15 + 1);
data << uint32(rankId);
+ data << uint32(_GetPurchasedTabsSize());
data << uint32(_GetRankRights(rankId));
data << uint32(_GetMemberRemainingMoney(member));
- data << uint8(_GetPurchasedTabsSize());
+ data.WriteBits(GUILD_BANK_MAX_TABS, 23);
for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId)
{
data << uint32(_GetRankBankTabRights(rankId, tabId));
@@ -1896,7 +2262,7 @@ void Guild::SendPermissions(WorldSession* session) const
}
session->SendPacket(&data);
- TC_LOG_DEBUG("guild", "MSG_GUILD_PERMISSIONS [%s] Rank: %u", session->GetPlayerInfo().c_str(), rankId);
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_PERMISSIONS_QUERY_RESULTS [%s] Rank: %u", session->GetPlayerInfo().c_str(), rankId);
}
void Guild::SendMoneyInfo(WorldSession* session) const
@@ -1906,14 +2272,30 @@ void Guild::SendMoneyInfo(WorldSession* session) const
return;
int32 amount = _GetMemberRemainingMoney(member);
- WorldPacket data(MSG_GUILD_BANK_MONEY_WITHDRAWN, 4);
- data << int32(amount);
+ WorldPacket data(SMSG_GUILD_BANK_MONEY_WITHDRAWN, 8);
+ data << int64(amount);
session->SendPacket(&data);
- TC_LOG_DEBUG("guild", "MSG_GUILD_BANK_MONEY_WITHDRAWN [%s] Money: %u", session->GetPlayerInfo().c_str(), amount);
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_BANK_MONEY_WITHDRAWN [%s] Money: %u", session->GetPlayerInfo().c_str(), amount);
}
void Guild::SendLoginInfo(WorldSession* session)
{
+ Player* player = session->GetPlayer();
+ Member* member = GetMember(player->GetGUID());
+ if (!member)
+ return;
+
+ /*
+ Login sequence:
+ SMSG_GUILD_EVENT - GE_MOTD
+ SMSG_GUILD_RANK
+ SMSG_GUILD_EVENT - GE_SIGNED_ON
+ -- learn perks
+ SMSG_GUILD_REPUTATION_WEEKLY_CAP
+ SMSG_GUILD_ACHIEVEMENT_DATA
+ SMSG_GUILD_MEMBER_DAILY_RESET // bank withdrawal reset
+ */
+
WorldPacket data(SMSG_GUILD_EVENT, 1 + 1 + m_motd.size() + 1);
data << uint8(GE_MOTD);
data << uint8(1);
@@ -1922,18 +2304,34 @@ void Guild::SendLoginInfo(WorldSession* session)
TC_LOG_DEBUG("guild", "SMSG_GUILD_EVENT [%s] MOTD", session->GetPlayerInfo().c_str());
- SendBankTabsInfo(session);
+ SendGuildRankInfo(session);
+ _BroadcastEvent(GE_SIGNED_ON, player->GetGUID(), player->GetName().c_str());
- Player* player = session->GetPlayer();
+ // Send to self separately, player is not in world yet and is not found by _BroadcastEvent
+ data.Initialize(SMSG_GUILD_EVENT, 1 + 1 + player->GetName().size() + 8);
+ data << uint8(GE_SIGNED_ON);
+ data << uint8(1);
+ data << player->GetName();
+ data << uint64(player->GetGUID());
+ session->SendPacket(&data);
- HandleRoster(session);
- _BroadcastEvent(GE_SIGNED_ON, player->GetGUID(), player->GetName().c_str());
+ data.Initialize(SMSG_GUILD_MEMBER_DAILY_RESET, 0); // tells the client to request bank withdrawal limit
+ session->SendPacket(&data);
- if (Member* member = GetMember(player->GetGUID()))
- {
- member->SetStats(player);
- member->AddFlag(GUILDMEMBER_STATUS_ONLINE);
- }
+ if (!sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED))
+ return;
+
+ for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i)
+ if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i))
+ if (entry->Level <= GetLevel())
+ player->LearnSpell(entry->SpellId, true);
+
+ SendGuildReputationWeeklyCap(session, member->GetWeekReputation());
+
+ m_achievementMgr.SendAllAchievementData(player);
+
+ member->SetStats(player);
+ member->AddFlag(GUILDMEMBER_STATUS_ONLINE);
}
// Loading methods
@@ -1947,8 +2345,11 @@ bool Guild::LoadFromDB(Field* fields)
m_motd = fields[9].GetString();
m_createdDate = time_t(fields[10].GetUInt32());
m_bankMoney = fields[11].GetUInt64();
+ _level = fields[12].GetUInt32();
+ _experience = fields[13].GetUInt64();
+ _todayExperience = fields[14].GetUInt64();
- uint8 purchasedTabs = uint8(fields[12].GetUInt64());
+ uint8 purchasedTabs = uint8(fields[15].GetUInt64());
if (purchasedTabs > GUILD_BANK_MAX_TABS)
purchasedTabs = GUILD_BANK_MAX_TABS;
@@ -2048,6 +2449,21 @@ bool Guild::LoadBankEventLogFromDB(Field* fields)
return true;
}
+void Guild::LoadGuildNewsLogFromDB(Field* fields)
+{
+ if (!m_newsLog->CanInsert())
+ return;
+
+ m_newsLog->LoadEvent(new NewsLogEntry(
+ m_id, // guild id
+ fields[1].GetUInt32(), // guid
+ fields[6].GetUInt32(), // timestamp //64 bits?
+ GuildNews(fields[2].GetUInt8()), // type
+ fields[3].GetUInt32(), // player guid
+ fields[4].GetUInt32(), // Flags
+ fields[5].GetUInt32())); // value
+}
+
void Guild::LoadBankTabFromDB(Field* fields)
{
uint8 tabId = fields[1].GetUInt8();
@@ -2076,7 +2492,7 @@ bool Guild::Validate()
// GUILD RANKS represent a sequence starting from 0 = GUILD_MASTER (ALL PRIVILEGES) to max 9 (lowest privileges).
// The lower rank id is considered higher rank - so promotion does rank-- and demotion does rank++
// Between ranks in sequence cannot be gaps - so 0, 1, 2, 4 is impossible
- // Min ranks count is 5 and max is 10.
+ // Min ranks count is 2 and max is 10.
bool broken_ranks = false;
uint8 ranks = _GetRanksSize();
if (ranks < GUILD_RANKS_MIN_COUNT || ranks > GUILD_RANKS_MAX_COUNT)
@@ -2156,6 +2572,21 @@ void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, std::strin
}
}
+void Guild::BroadcastAddonToGuild(WorldSession* session, bool officerOnly, std::string const& msg, std::string const& prefix) const
+{
+ if (session && session->GetPlayer() && _HasRankRight(session->GetPlayer(), officerOnly ? GR_RIGHT_OFFCHATSPEAK : GR_RIGHT_GCHATSPEAK))
+ {
+ WorldPacket data;
+ ChatHandler::BuildChatPacket(data, officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, LANG_ADDON, session->GetPlayer(), NULL, msg, 0, "", DEFAULT_LOCALE, prefix);
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (Player* player = itr->second->FindPlayer())
+ if (player->GetSession() && _HasRankRight(player, officerOnly ? GR_RIGHT_OFFCHATLISTEN : GR_RIGHT_GCHATLISTEN) &&
+ !player->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow()) &&
+ player->GetSession()->IsAddonRegistered(prefix))
+ player->GetSession()->SendPacket(&data);
+ }
+}
+
void Guild::BroadcastPacketToRank(WorldPacket* packet, uint8 rankId) const
{
for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
@@ -2235,7 +2666,7 @@ bool Guild::AddMember(uint64 guid, uint8 rankId)
player->SetInGuild(m_id);
player->SetGuildIdInvited(0);
player->SetRank(rankId);
- member->SetStats(player);
+ player->SetGuildLevel(GetLevel());
SendLoginInfo(player->GetSession());
name = player->GetName();
}
@@ -2256,10 +2687,12 @@ bool Guild::AddMember(uint64 guid, uint8 rankId)
fields[1].GetUInt8(),
fields[2].GetUInt8(),
fields[3].GetUInt16(),
- fields[4].GetUInt32());
+ fields[4].GetUInt32(),
+ 0);
ok = member->CheckStats();
}
+
if (!ok)
{
delete member;
@@ -2274,6 +2707,7 @@ bool Guild::AddMember(uint64 guid, uint8 rankId)
_UpdateAccountsNumber();
_LogEvent(GUILD_EVENT_LOG_JOIN_GUILD, lowguid);
_BroadcastEvent(GE_JOINED, guid, name.c_str());
+ sGuildFinderMgr->RemoveAllMembershipRequestsFromPlayer(lowguid);
// Call scripts if member was succesfully added (and stored to database)
sScriptMgr->OnGuildAddMember(this, player, rankId);
@@ -2333,6 +2767,12 @@ void Guild::DeleteMember(uint64 guid, bool isDisbanding, bool isKicked, bool can
{
player->SetInGuild(0);
player->SetRank(0);
+ player->SetGuildLevel(0);
+
+ for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i)
+ if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i))
+ if (entry->Level <= GetLevel())
+ player->RemoveSpell(entry->SpellId, false, false);
}
_DeleteMemberFromDB(lowguid);
@@ -2351,6 +2791,12 @@ bool Guild::ChangeMemberRank(uint64 guid, uint8 newRank)
return false;
}
+bool Guild::IsMember(uint64 guid) const
+{
+ Members::const_iterator itr = m_members.find(GUID_LOPART(guid));
+ return itr != m_members.end();
+}
+
// Bank (items move)
void Guild::SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount)
{
@@ -2393,6 +2839,7 @@ void Guild::SetBankTabText(uint8 tabId, std::string const& text)
void Guild::_CreateLogHolders()
{
m_eventLog = new LogHolder(sWorld->getIntConfig(CONFIG_GUILD_EVENT_LOG_COUNT));
+ m_newsLog = new LogHolder(sWorld->getIntConfig(CONFIG_GUILD_NEWS_LOG_COUNT));
for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId)
m_bankEventLog[tabId] = new LogHolder(sWorld->getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT));
}
@@ -2783,20 +3230,6 @@ bool Guild::_DoItemsMove(MoveItemData* pSrc, MoveItemData* pDest, bool sendError
return true;
}
-void Guild::_SendBankContent(WorldSession* session, uint8 tabId) const
-{
- uint64 guid = session->GetPlayer()->GetGUID();
- if (!_MemberHasTabRights(guid, tabId, GUILD_BANK_RIGHT_VIEW_TAB))
- return;
-
- _SendBankList(session, tabId, true);
-}
-
-void Guild::_SendBankMoneyUpdate(WorldSession* session) const
-{
- _SendBankList(session);
-}
-
void Guild::_SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) const
{
ASSERT(pSrc->IsBank() || pDest->IsBank());
@@ -2831,7 +3264,68 @@ void Guild::_SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) cons
void Guild::_SendBankContentUpdate(uint8 tabId, SlotIds slots) const
{
- _SendBankList(NULL, tabId, false, &slots);
+ if (BankTab const* tab = GetBankTab(tabId))
+ {
+ ByteBuffer tabData;
+ WorldPacket data(SMSG_GUILD_BANK_LIST, 1200);
+ data.WriteBit(0);
+ data.WriteBits(slots.size(), 20); // Item count
+ data.WriteBits(0, 22); // Tab count
+
+ for (SlotIds::const_iterator itr = slots.begin(); itr != slots.end(); ++itr)
+ {
+ data.WriteBit(0);
+
+ Item const* tabItem = tab->GetItem(*itr);
+ uint32 enchantCount = 0;
+ if (tabItem)
+ {
+ for (uint32 enchSlot = 0; enchSlot < MAX_ENCHANTMENT_SLOT; ++enchSlot)
+ {
+ if (uint32 enchantId = tabItem->GetEnchantmentId(EnchantmentSlot(enchSlot)))
+ {
+ tabData << uint32(enchantId);
+ tabData << uint32(enchSlot);
+ ++enchantCount;
+ }
+ }
+ }
+
+ data.WriteBits(enchantCount, 23); // enchantment count
+
+ tabData << uint32(0);
+ tabData << uint32(0);
+ tabData << uint32(0);
+ tabData << uint32(tabItem ? tabItem->GetCount() : 0); // ITEM_FIELD_STACK_COUNT
+ tabData << uint32(*itr);
+ tabData << uint32(0);
+ tabData << uint32(tabItem ? tabItem->GetEntry() : 0);
+ tabData << uint32(tabItem ? tabItem->GetItemRandomPropertyId() : 0);
+ tabData << uint32(tabItem ? abs(tabItem->GetSpellCharges()) : 0); // Spell charges
+ tabData << uint32(tabItem ? tabItem->GetItemSuffixFactor() : 0); // SuffixFactor
+ }
+
+ data.FlushBits();
+
+ data << uint64(m_bankMoney);
+ if (!tabData.empty())
+ data.append(tabData);
+
+ data << uint32(tabId);
+
+ size_t rempos = data.wpos();
+ data << uint32(0); // Item withdraw amount, will be filled later
+
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (_MemberHasTabRights(itr->second->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB))
+ if (Player* player = itr->second->FindPlayer())
+ {
+ data.put<uint32>(rempos, uint32(_GetMemberRemainingSlots(itr->second, tabId)));
+ player->GetSession()->SendPacket(&data);
+ }
+
+ TC_LOG_DEBUG("guild", "WORLD: Sent (SMSG_GUILD_BANK_LIST)");
+ }
}
void Guild::_BroadcastEvent(GuildEvents guildEvent, uint64 guid, const char* param1, const char* param2, const char* param3) const
@@ -2858,69 +3352,293 @@ void Guild::_BroadcastEvent(GuildEvents guildEvent, uint64 guid, const char* par
TC_LOG_DEBUG("guild", "SMSG_GUILD_EVENT [Broadcast] Event: %s (%u)", _GetGuildEventString(guildEvent).c_str(), guildEvent);
}
-void Guild::_SendBankList(WorldSession* session /* = NULL*/, uint8 tabId /*= 0*/, bool sendAllSlots /*= false*/, SlotIds *slots /*= NULL*/) const
+void Guild::SendBankList(WorldSession* session, uint8 tabId, bool withContent, bool withTabInfo) const
{
+ Member const* member = GetMember(session->GetPlayer()->GetGUID());
+ if (!member) // Shouldn't happen, just in case
+ return;
+
+ ByteBuffer tabData;
WorldPacket data(SMSG_GUILD_BANK_LIST, 500);
- data << uint64(m_bankMoney);
- data << uint8(tabId);
- size_t rempos = data.wpos();
- data << uint32(0);
- data << uint8(sendAllSlots);
+ data.WriteBit(0);
+ uint32 itemCount = 0;
+ if (withContent && _MemberHasTabRights(session->GetPlayer()->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB))
+ if (BankTab const* tab = GetBankTab(tabId))
+ for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId)
+ if (tab->GetItem(slotId))
+ ++itemCount;
+
+ data.WriteBits(itemCount, 20);
+ data.WriteBits(withTabInfo ? _GetPurchasedTabsSize() : 0, 22);
+ if (withContent && _MemberHasTabRights(session->GetPlayer()->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB))
+ {
+ if (BankTab const* tab = GetBankTab(tabId))
+ {
+ for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId)
+ {
+ if (Item* tabItem = tab->GetItem(slotId))
+ {
+ data.WriteBit(0);
+
+ uint32 enchants = 0;
+ for (uint32 ench = 0; ench < MAX_ENCHANTMENT_SLOT; ++ench)
+ {
+ if (uint32 enchantId = tabItem->GetEnchantmentId(EnchantmentSlot(ench)))
+ {
+ tabData << uint32(enchantId);
+ tabData << uint32(ench);
+ ++enchants;
+ }
+ }
+
+ data.WriteBits(enchants, 23);
+
+ tabData << uint32(0);
+ tabData << uint32(0);
+ tabData << uint32(0);
+ tabData << uint32(tabItem->GetCount()); // ITEM_FIELD_STACK_COUNT
+ tabData << uint32(slotId);
+ tabData << uint32(0);
+ tabData << uint32(tabItem->GetEntry());
+ tabData << uint32(tabItem->GetItemRandomPropertyId());
+ tabData << uint32(abs(tabItem->GetSpellCharges())); // Spell charges
+ tabData << uint32(tabItem->GetItemSuffixFactor()); // SuffixFactor
+ }
+ }
+ }
+ }
- if (sendAllSlots && !tabId)
+ if (withTabInfo)
{
- data << uint8(_GetPurchasedTabsSize()); // Number of tabs
for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i)
- m_bankTabs[i]->WriteInfoPacket(data);
+ {
+ data.WriteBits(m_bankTabs[i]->GetIcon().length(), 9);
+ data.WriteBits(m_bankTabs[i]->GetName().length(), 7);
+ }
}
- BankTab const* tab = GetBankTab(tabId);
- if (!tab)
- data << uint8(0);
- else if (sendAllSlots)
- tab->WritePacket(data);
- else if (slots && !slots->empty())
+ data.FlushBits();
+
+ if (withTabInfo)
{
- data << uint8(slots->size());
- for (SlotIds::const_iterator itr = slots->begin(); itr != slots->end(); ++itr)
- tab->WriteSlotPacket(data, *itr, false);
+ for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i)
+ {
+ data.WriteString(m_bankTabs[i]->GetIcon());
+ data << uint32(i);
+ data.WriteString(m_bankTabs[i]->GetName());
+ }
}
- else
- data << uint8(0);
- if (session)
+ data << uint64(m_bankMoney);
+ if (!tabData.empty())
+ data.append(tabData);
+
+ data << uint32(tabId);
+ data << uint32(_GetMemberRemainingSlots(member, tabId));
+
+ session->SendPacket(&data);
+
+ TC_LOG_DEBUG("guild", "WORLD: Sent (SMSG_GUILD_BANK_LIST)");
+}
+
+void Guild::SendGuildRanksUpdate(uint64 setterGuid, uint64 targetGuid, uint32 rank)
+{
+ ObjectGuid tarGuid = targetGuid;
+ ObjectGuid setGuid = setterGuid;
+
+ Member* member = GetMember(targetGuid);
+ ASSERT(member);
+
+ WorldPacket data(SMSG_GUILD_RANKS_UPDATE, 100);
+ data.WriteBit(setGuid[7]);
+ data.WriteBit(setGuid[2]);
+ data.WriteBit(tarGuid[2]);
+ data.WriteBit(setGuid[1]);
+ data.WriteBit(tarGuid[1]);
+ data.WriteBit(tarGuid[7]);
+ data.WriteBit(tarGuid[0]);
+ data.WriteBit(tarGuid[5]);
+ data.WriteBit(tarGuid[4]);
+ data.WriteBit(rank < member->GetRankId()); // 1 == higher, 0 = lower?
+ data.WriteBit(setGuid[5]);
+ data.WriteBit(setGuid[0]);
+ data.WriteBit(tarGuid[6]);
+ data.WriteBit(setGuid[3]);
+ data.WriteBit(setGuid[6]);
+ data.WriteBit(tarGuid[3]);
+ data.WriteBit(setGuid[4]);
+
+ data.FlushBits();
+
+ data << uint32(rank);
+ data.WriteByteSeq(setGuid[3]);
+ data.WriteByteSeq(tarGuid[7]);
+ data.WriteByteSeq(setGuid[6]);
+ data.WriteByteSeq(setGuid[2]);
+ data.WriteByteSeq(tarGuid[5]);
+ data.WriteByteSeq(tarGuid[0]);
+ data.WriteByteSeq(setGuid[7]);
+ data.WriteByteSeq(setGuid[5]);
+ data.WriteByteSeq(tarGuid[2]);
+ data.WriteByteSeq(tarGuid[1]);
+ data.WriteByteSeq(setGuid[0]);
+ data.WriteByteSeq(setGuid[4]);
+ data.WriteByteSeq(setGuid[1]);
+ data.WriteByteSeq(tarGuid[3]);
+ data.WriteByteSeq(tarGuid[6]);
+ data.WriteByteSeq(tarGuid[4]);
+ BroadcastPacket(&data);
+
+ member->ChangeRank(rank);
+
+ TC_LOG_DEBUG("network", "SMSG_GUILD_RANKS_UPDATE [Broadcast] Target: %u, Issuer: %u, RankId: %u",
+ GUID_LOPART(targetGuid), GUID_LOPART(setterGuid), rank);
+}
+
+void Guild::GiveXP(uint32 xp, Player* source)
+{
+ if (!sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED))
+ return;
+
+ /// @todo: Award reputation and count activity for player
+
+ if (GetLevel() >= sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL))
+ xp = 0; // SMSG_GUILD_XP_GAIN is always sent, even for no gains
+
+ if (GetLevel() < GUILD_EXPERIENCE_UNCAPPED_LEVEL)
+ xp = std::min(xp, sWorld->getIntConfig(CONFIG_GUILD_DAILY_XP_CAP) - uint32(_todayExperience));
+
+ WorldPacket data(SMSG_GUILD_XP_GAIN, 8);
+ data << uint64(xp);
+ source->GetSession()->SendPacket(&data);
+
+ _experience += xp;
+ _todayExperience += xp;
+
+ if (!xp)
+ return;
+
+ uint32 oldLevel = GetLevel();
+
+ // Ding, mon!
+ while (GetExperience() >= sGuildMgr->GetXPForGuildLevel(GetLevel()) && GetLevel() < sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL))
{
- int32 numSlots = 0;
- if (Member const* member = GetMember(session->GetPlayer()->GetGUID()))
- numSlots = _GetMemberRemainingSlots(member, tabId);
- data.put<uint32>(rempos, numSlots);
- session->SendPacket(&data);
- TC_LOG_DEBUG("guild", "SMSG_GUILD_BANK_LIST [%s]: TabId: %u, FullSlots: %u, slots: %d",
- session->GetPlayerInfo().c_str(), tabId, sendAllSlots, numSlots);
+ _experience -= sGuildMgr->GetXPForGuildLevel(GetLevel());
+ ++_level;
+
+ // Find all guild perks to learn
+ std::vector<uint32> perksToLearn;
+ for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i)
+ if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i))
+ if (entry->Level > oldLevel && entry->Level <= GetLevel())
+ perksToLearn.push_back(entry->SpellId);
+
+ // Notify all online players that guild level changed and learn perks
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ {
+ if (Player* player = itr->second->FindPlayer())
+ {
+ player->SetGuildLevel(GetLevel());
+ for (size_t i = 0; i < perksToLearn.size(); ++i)
+ player->LearnSpell(perksToLearn[i], true);
+ }
+ }
+
+ AddGuildNews(GUILD_NEWS_LEVEL_UP, 0, 0, _level);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL, GetLevel(), 0, 0, NULL, source);
+
+ ++oldLevel;
}
- else /// @todo - Probably this is just sent to session + those that have sent CMSG_GUILD_BANKER_ACTIVATE
+}
+
+void Guild::SendGuildXP(WorldSession* session /* = NULL */) const
+{
+ //Member const* member = GetMember(session->GetGuidLow());
+
+ WorldPacket data(SMSG_GUILD_XP, 40);
+ data << uint64(/*member ? member->GetTotalActivity() :*/ 0);
+ data << uint64(sGuildMgr->GetXPForGuildLevel(GetLevel()) - GetExperience()); // XP missing for next level
+ data << uint64(GetTodayExperience());
+ data << uint64(/*member ? member->GetWeeklyActivity() :*/ 0);
+ data << uint64(GetExperience());
+ session->SendPacket(&data);
+}
+
+void Guild::SendGuildReputationWeeklyCap(WorldSession* session, uint32 reputation) const
+{
+ uint32 cap = sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP) - reputation;
+ WorldPacket data(SMSG_GUILD_REPUTATION_WEEKLY_CAP, 4);
+ data << uint32(cap);
+ session->SendPacket(&data);
+ TC_LOG_DEBUG("guild", "SMSG_GUILD_REPUTATION_WEEKLY_CAP [%s]: Left: %u",
+ session->GetPlayerInfo().c_str(), cap);
+}
+
+void Guild::ResetTimes(bool weekly)
+{
+ _todayExperience = 0;
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
{
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ itr->second->ResetValues(weekly);
+ if (Player* player = itr->second->FindPlayer())
{
- if (!_MemberHasTabRights(itr->second->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB))
- continue;
- Player* player = itr->second->FindPlayer();
- if (!player)
- continue;
-
- uint32 numSlots = _GetMemberRemainingSlots(itr->second, tabId);
- data.put<uint32>(rempos, numSlots);
+ //SendGuildXP(player->GetSession());
+ WorldPacket data(SMSG_GUILD_MEMBER_DAILY_RESET, 0); // tells the client to request bank withdrawal limit
player->GetSession()->SendPacket(&data);
- TC_LOG_DEBUG("guild", "SMSG_GUILD_BANK_LIST [%s]: TabId: %u, FullSlots: %u, slots: %u"
- , player->GetName().c_str(), tabId, sendAllSlots, numSlots);
}
}
}
-void Guild::ResetTimes()
+void Guild::AddGuildNews(uint8 type, uint64 guid, uint32 flags, uint32 value)
{
- for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
- itr->second->ResetValues();
+ uint32 lowGuid = GUID_LOPART(guid);
+ NewsLogEntry* news = new NewsLogEntry(m_id, m_newsLog->GetNextGUID(), GuildNews(type), lowGuid, flags, value);
- _BroadcastEvent(GE_BANK_TAB_AND_MONEY_UPDATED, 0);
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ m_newsLog->AddEvent(trans, news);
+ CharacterDatabase.CommitTransaction(trans);
+
+ WorldPacket data(SMSG_GUILD_NEWS_UPDATE, 7 + 32);
+ data.WriteBits(1, 21); // size, we are only sending 1 news here
+ ByteBuffer buffer;
+ news->WritePacket(data, buffer);
+
+ BroadcastPacket(&data);
+}
+
+bool Guild::HasAchieved(uint32 achievementId) const
+{
+ return m_achievementMgr.HasAchieved(achievementId);
+}
+
+void Guild::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit* unit, Player* player)
+{
+ m_achievementMgr.UpdateAchievementCriteria(type, miscValue1, miscValue2, miscValue3, unit, player);
+}
+
+void Guild::HandleNewsSetSticky(WorldSession* session, uint32 newsId, bool sticky)
+{
+ GuildLog* logs = m_newsLog->GetGuildLog();
+ GuildLog::iterator itr = logs->begin();
+ while (itr != logs->end() && (*itr)->GetGUID() != newsId)
+ ++itr;
+
+ if (itr == logs->end())
+ {
+ TC_LOG_DEBUG("guild", "HandleNewsSetSticky: [%s] requested unknown newsId %u - Sticky: %u",
+ session->GetPlayerInfo().c_str(), newsId, sticky);
+ return;
+ }
+
+ NewsLogEntry* news = (NewsLogEntry*)(*itr);
+ news->SetSticky(sticky);
+
+ TC_LOG_DEBUG("guild", "HandleNewsSetSticky: [%s] chenged newsId %u sticky to %u",
+ session->GetPlayerInfo().c_str(), newsId, sticky);
+
+ WorldPacket data(SMSG_GUILD_NEWS_UPDATE, 7 + 32);
+ data.WriteBits(1, 21);
+ ByteBuffer buffer;
+ news->WritePacket(data, buffer);
+ session->SendPacket(&data);
}
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index ea0b2e44c53..d62907ddde5 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -19,31 +19,35 @@
#ifndef TRINITYCORE_GUILD_H
#define TRINITYCORE_GUILD_H
+#include "AchievementMgr.h"
#include "World.h"
#include "Item.h"
#include "WorldPacket.h"
#include "ObjectMgr.h"
#include "Player.h"
+#include "DBCStore.h"
class Item;
enum GuildMisc
{
- GUILD_BANK_MAX_TABS = 6, // send by client for money log also
+ GUILD_BANK_MAX_TABS = 8, // send by client for money log also
GUILD_BANK_MAX_SLOTS = 98,
GUILD_BANK_MONEY_LOGS_TAB = 100, // used for money log in DB
- GUILD_RANKS_MIN_COUNT = 5,
+ GUILD_RANKS_MIN_COUNT = 2,
GUILD_RANKS_MAX_COUNT = 10,
GUILD_RANK_NONE = 0xFF,
GUILD_WITHDRAW_MONEY_UNLIMITED = 0xFFFFFFFF,
GUILD_WITHDRAW_SLOT_UNLIMITED = 0xFFFFFFFF,
GUILD_EVENT_LOG_GUID_UNDEFINED = 0xFFFFFFFF,
+ GUILD_EXPERIENCE_UNCAPPED_LEVEL = 20, ///> Hardcoded in client, starting from this level, guild daily experience gain is unlimited.
TAB_UNDEFINED = 0xFF,
};
enum GuildMemberData
{
GUILD_MEMBER_DATA_ZONEID,
+ GUILD_MEMBER_DATA_ACHIEVEMENT_POINTS,
GUILD_MEMBER_DATA_LEVEL,
};
@@ -79,7 +83,7 @@ enum GuildRankRights
GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair
GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold
GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk
- GR_RIGHT_ALL = 0x001DF1FF
+ GR_RIGHT_ALL = 0x00DDFFBF
};
enum GuildCommandType
@@ -128,37 +132,53 @@ enum GuildCommandError
ERR_GUILD_NOT_ENOUGH_MONEY = 26,
ERR_GUILD_BANK_FULL = 28,
ERR_GUILD_ITEM_NOT_FOUND = 29,
+ ERR_GUILD_TOO_MUCH_MONEY = 31,
+ ERR_GUILD_BANK_WRONG_TAB = 32,
+ ERR_RANK_REQUIRES_AUTHENTICATOR = 34,
+ ERR_GUILD_BANK_VOUCHER_FAILED = 35,
+ ERR_GUILD_TRIAL_ACCOUNT = 36,
+ ERR_GUILD_UNDELETABLE_DUE_TO_LEVEL = 37,
+ ERR_GUILD_MOVE_STARTING = 38,
+ ERR_GUILD_REP_TOO_LOW = 39
};
enum GuildEvents
{
- GE_PROMOTION = 0,
- GE_DEMOTION = 1,
- GE_MOTD = 2,
- GE_JOINED = 3,
- GE_LEFT = 4,
- GE_REMOVED = 5,
- GE_LEADER_IS = 6,
- GE_LEADER_CHANGED = 7,
- GE_DISBANDED = 8,
- GE_TABARDCHANGE = 9,
- GE_RANK_UPDATED = 10,
- GE_RANK_DELETED = 11,
- GE_SIGNED_ON = 12,
- GE_SIGNED_OFF = 13,
- GE_GUILDBANKBAGSLOTS_CHANGED = 14, /// TODO: Sent when items are moved in gbank - all players with bank open will send tab query
- GE_BANK_TAB_PURCHASED = 15,
- GE_BANK_TAB_UPDATED = 16,
- GE_BANK_MONEY_SET = 17,
- GE_BANK_TAB_AND_MONEY_UPDATED = 18,
- GE_BANK_TEXT_CHANGED = 19,
+ GE_PROMOTION = 1,
+ GE_DEMOTION = 2,
+ GE_MOTD = 3,
+ GE_JOINED = 4,
+ GE_LEFT = 5,
+ GE_REMOVED = 6,
+ GE_LEADER_IS = 7,
+ GE_LEADER_CHANGED = 8,
+ GE_DISBANDED = 9,
+ GE_TABARDCHANGE = 10,
+ GE_RANK_UPDATED = 11,
+ GE_RANK_CREATED = 12,
+ GE_RANK_DELETED = 13,
+ GE_RANK_ORDER_CHANGED = 14,
+ GE_FOUNDER = 15,
+ GE_SIGNED_ON = 16,
+ GE_SIGNED_OFF = 17,
+ GE_GUILDBANKBAGSLOTS_CHANGED = 18,
+ GE_BANK_TAB_PURCHASED = 19,
+ GE_BANK_TAB_UPDATED = 20,
+ GE_BANK_MONEY_SET = 21,
+ GE_BANK_TAB_AND_MONEY_UPDATED = 22,
+ GE_BANK_TEXT_CHANGED = 23,
+ // 24 - error 795
+ GE_SIGNED_ON_MOBILE = 25,
+ GE_SIGNED_Off_MOBILE = 26,
};
enum PetitionTurns
{
PETITION_TURN_OK = 0,
PETITION_TURN_ALREADY_IN_GUILD = 2,
- PETITION_TURN_NEED_MORE_SIGNATURES = 4
+ PETITION_TURN_NEED_MORE_SIGNATURES = 4,
+ PETITION_TURN_GUILD_PERMISSIONS = 11,
+ PETITION_TURN_GUILD_NAME_INVALID = 12
};
enum PetitionSigns
@@ -167,7 +187,10 @@ enum PetitionSigns
PETITION_SIGN_ALREADY_SIGNED = 1,
PETITION_SIGN_ALREADY_IN_GUILD = 2,
PETITION_SIGN_CANT_SIGN_OWN = 3,
- PETITION_SIGN_NOT_SERVER = 4
+ PETITION_SIGN_NOT_SERVER = 4,
+ PETITION_SIGN_FULL = 5,
+ PETITION_SIGN_ALREADY_SIGNED_OTHER = 6,
+ PETITION_SIGN_RESTRICTED_ACCOUNT = 7
};
enum GuildBankRights
@@ -190,7 +213,8 @@ enum GuildBankEventLogTypes
GUILD_BANK_LOG_REPAIR_MONEY = 6,
GUILD_BANK_LOG_MOVE_ITEM2 = 7,
GUILD_BANK_LOG_UNK1 = 8,
- GUILD_BANK_LOG_BUY_SLOT = 9
+ GUILD_BANK_LOG_BUY_SLOT = 9,
+ GUILD_BANK_LOG_CASH_FLOW_DEPOSIT = 10
};
enum GuildEventLogTypes
@@ -222,6 +246,28 @@ enum GuildMemberFlags
GUILDMEMBER_STATUS_MOBILE = 0x0008, // remote chat from mobile app
};
+enum GuildNews
+{
+ GUILD_NEWS_GUILD_ACHIEVEMENT = 0,
+ GUILD_NEWS_PLAYER_ACHIEVEMENT = 1,
+ GUILD_NEWS_DUNGEON_ENCOUNTER = 2, // @todo Implement
+ GUILD_NEWS_ITEM_LOOTED = 3,
+ GUILD_NEWS_ITEM_CRAFTED = 4,
+ GUILD_NEWS_ITEM_PURCHASED = 5,
+ GUILD_NEWS_LEVEL_UP = 6,
+};
+
+struct GuildReward
+{
+ uint32 Entry;
+ int32 Racemask;
+ uint64 Price;
+ uint32 AchievementId;
+ uint8 Standing;
+};
+
+uint32 const MinNewsItemLevel[MAX_CONTENT] = { 61, 90, 200, 353 };
+
// Emblem info
class EmblemInfo
{
@@ -295,19 +341,27 @@ private:
m_flags(GUILDMEMBER_STATUS_NONE),
m_logoutTime(::time(NULL)),
m_accountId(0),
- m_rankId(rankId)
+ m_rankId(rankId),
+ m_achievementPoints(0),
+ m_totalActivity(0),
+ m_weekActivity(0),
+ m_totalReputation(0),
+ m_weekReputation(0)
{
memset(m_bankWithdraw, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(int32));
}
void SetStats(Player* player);
- void SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId);
+ void SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId, uint32 reputation);
bool CheckStats() const;
void SetPublicNote(std::string const& publicNote);
void SetOfficerNote(std::string const& officerNote);
- void SetZoneID(uint32 id) { m_zoneId = id; }
+ void SetZoneId(uint32 id) { m_zoneId = id; }
+ void SetAchievementPoints(uint32 val) { m_achievementPoints = val; }
void SetLevel(uint8 var) { m_level = var; }
+ void AddReputation(uint32& reputation);
+ void AddActivity(uint64 activity);
void AddFlag(uint8 var) { m_flags |= var; }
void RemFlag(uint8 var) { m_flags &= ~var; }
@@ -315,7 +369,6 @@ private:
bool LoadFromDB(Field* fields);
void SaveToDB(SQLTransaction& trans) const;
- void WritePacket(WorldPacket& data, bool sendOfficerNote) const;
uint64 GetGUID() const { return m_guid; }
std::string const& GetName() const { return m_name; }
@@ -328,6 +381,12 @@ private:
uint8 GetLevel() const { return m_level; }
uint8 GetFlags() const { return m_flags; }
uint32 GetZoneId() const { return m_zoneId; }
+ uint32 GetAchievementPoints() const { return m_achievementPoints; }
+ uint64 GetTotalActivity() const { return m_totalActivity; }
+ uint64 GetWeekActivity() const { return m_weekActivity; }
+ uint32 GetTotalReputation() const { return m_totalReputation; }
+ uint32 GetWeekReputation() const { return m_weekReputation; }
+
bool IsOnline() { return (m_flags & GUILDMEMBER_STATUS_ONLINE); }
void ChangeRank(uint8 newRank);
@@ -339,7 +398,7 @@ private:
void UpdateBankWithdrawValue(SQLTransaction& trans, uint8 tabId, uint32 amount);
int32 GetBankWithdrawValue(uint8 tabId) const;
- void ResetValues();
+ void ResetValues(bool weekly = false);
inline Player* FindPlayer() const { return ObjectAccessor::FindPlayer(m_guid); }
@@ -360,6 +419,11 @@ private:
std::string m_officerNote;
int32 m_bankWithdraw[GUILD_BANK_MAX_TABS + 1];
+ uint32 m_achievementPoints;
+ uint64 m_totalActivity;
+ uint64 m_weekActivity;
+ uint32 m_totalReputation;
+ uint32 m_weekReputation;
};
// Base class for event entries
@@ -374,7 +438,7 @@ private:
uint64 GetTimestamp() const { return m_timestamp; }
virtual void SaveToDB(SQLTransaction& trans) const = 0;
- virtual void WritePacket(WorldPacket& data) const = 0;
+ virtual void WritePacket(WorldPacket& data, ByteBuffer& content) const = 0;
protected:
uint32 m_guildId;
@@ -395,7 +459,7 @@ private:
~EventLogEntry() { }
void SaveToDB(SQLTransaction& trans) const;
- void WritePacket(WorldPacket& data) const;
+ void WritePacket(WorldPacket& data, ByteBuffer& content) const;
private:
GuildEventLogTypes m_eventType;
@@ -413,31 +477,71 @@ private:
return
eventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
eventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
- eventType == GUILD_BANK_LOG_REPAIR_MONEY;
+ eventType == GUILD_BANK_LOG_REPAIR_MONEY ||
+ eventType == GUILD_BANK_LOG_CASH_FLOW_DEPOSIT;
}
- BankEventLogEntry(uint32 guildId, uint32 guid, GuildBankEventLogTypes eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
+ bool IsMoneyEvent() const
+ {
+ return IsMoneyEvent(m_eventType);
+ }
+
+ BankEventLogEntry(uint32 guildId, uint32 guid, GuildBankEventLogTypes eventType, uint8 tabId, uint32 playerGuid, uint64 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
LogEntry(guildId, guid), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
- BankEventLogEntry(uint32 guildId, uint32 guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
+ BankEventLogEntry(uint32 guildId, uint32 guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, uint32 playerGuid, uint64 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
~BankEventLogEntry() { }
void SaveToDB(SQLTransaction& trans) const;
- void WritePacket(WorldPacket& data) const;
+ void WritePacket(WorldPacket& data, ByteBuffer& content) const;
private:
GuildBankEventLogTypes m_eventType;
uint8 m_bankTabId;
uint32 m_playerGuid;
- uint32 m_itemOrMoney;
+ uint64 m_itemOrMoney;
uint16 m_itemStackCount;
uint8 m_destTabId;
};
+ // News log entry
+ class NewsLogEntry : public LogEntry
+ {
+ public:
+ NewsLogEntry(uint32 guildId, uint32 guid, GuildNews type, uint32 playerGuid, uint32 flags, uint32 value) :
+ LogEntry(guildId, guid), m_type(type), m_playerGuid(playerGuid), m_flags(flags), m_value(value) { }
+
+ NewsLogEntry(uint32 guildId, uint32 guid, time_t timestamp, GuildNews type, uint32 playerGuid, uint32 flags, uint32 value) :
+ LogEntry(guildId, guid, timestamp), m_type(type), m_playerGuid(playerGuid), m_flags(flags), m_value(value) { }
+
+ ~NewsLogEntry() { }
+
+ GuildNews GetType() const { return m_type; }
+ uint64 GetPlayerGuid() const { return m_playerGuid ? MAKE_NEW_GUID(m_playerGuid, 0, HIGHGUID_PLAYER) : 0; }
+ uint32 GetValue() const { return m_value; }
+ uint32 GetFlags() const { return m_flags; }
+ void SetSticky(bool sticky)
+ {
+ if (sticky)
+ m_flags |= 1;
+ else
+ m_flags &= ~1;
+ }
+
+ void SaveToDB(SQLTransaction& trans) const;
+ void WritePacket(WorldPacket& data, ByteBuffer& content) const;
+
+ private:
+ GuildNews m_type;
+ uint32 m_playerGuid;
+ uint32 m_flags;
+ uint32 m_value;
+ };
+
// Class encapsulating work with events collection
typedef std::list<LogEntry*> GuildLog;
@@ -457,6 +561,7 @@ private:
// Writes information about all events to packet
void WritePacket(WorldPacket& data) const;
uint32 GetNextGUID();
+ GuildLog* GetGuildLog() { return &m_log; } // Hack needed for news as WritePacket can't be used
private:
GuildLog m_log;
@@ -476,7 +581,6 @@ private:
void LoadFromDB(Field* fields);
void SaveToDB(SQLTransaction& trans) const;
- void WritePacket(WorldPacket& data) const;
uint8 GetId() const { return m_rankId; }
@@ -505,7 +609,6 @@ private:
private:
uint32 m_guildId;
-
uint8 m_rankId;
std::string m_name;
uint32 m_rights;
@@ -535,10 +638,14 @@ private:
void SetInfo(std::string const& name, std::string const& icon);
void SetText(std::string const& text);
- void SendText(const Guild* guild, WorldSession* session) const;
+ void SendText(Guild const* guild, WorldSession* session) const;
+
+ std::string const& GetName() const { return m_name; }
+ std::string const& GetIcon() const { return m_icon; }
+ std::string const& GetText() const { return m_text; }
inline Item* GetItem(uint8 slotId) const { return slotId < GUILD_BANK_MAX_SLOTS ? m_items[slotId] : NULL; }
- bool SetItem(SQLTransaction& trans, uint8 slotId, Item* pItem);
+ bool SetItem(SQLTransaction& trans, uint8 slotId, Item* item);
private:
uint32 m_guildId;
@@ -651,8 +758,11 @@ public:
bool Create(Player* pLeader, std::string const& name);
void Disband();
+ void SaveToDB();
+
// Getters
uint32 GetId() const { return m_id; }
+ uint64 GetGUID() const { return MAKE_NEW_GUID(m_id, 0, HIGHGUID_GUILD); }
uint64 GetLeaderGUID() const { return m_leaderGuid; }
std::string const& GetName() const { return m_name; }
std::string const& GetMOTD() const { return m_motd; }
@@ -666,40 +776,44 @@ public:
void HandleSetMOTD(WorldSession* session, std::string const& motd);
void HandleSetInfo(WorldSession* session, std::string const& info);
void HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo);
- void HandleSetLeader(WorldSession* session, std::string const& name);
+ void HandleSetNewGuildMaster(WorldSession* session, std::string const& name);
void HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string const& name, std::string const& icon);
- void HandleSetMemberNote(WorldSession* session, std::string const& name, std::string const& note, bool officer);
- void HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, const GuildBankRightsAndSlotsVec& rightsAndSlots);
+ void HandleSetMemberNote(WorldSession* session, std::string const& note, uint64 guid, bool isPublic);
+ void HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec const& rightsAndSlots);
void HandleBuyBankTab(WorldSession* session, uint8 tabId);
void HandleInviteMember(WorldSession* session, std::string const& name);
void HandleAcceptMember(WorldSession* session);
void HandleLeaveMember(WorldSession* session);
- void HandleRemoveMember(WorldSession* session, std::string const& name);
- void HandleUpdateMemberRank(WorldSession* session, std::string const& name, bool demote);
+ void HandleRemoveMember(WorldSession* session, uint64 guid);
+ void HandleUpdateMemberRank(WorldSession* session, uint64 guid, bool demote);
+ void HandleSetMemberRank(WorldSession* session, uint64 guid, uint64 setterGuid, uint32 rank);
void HandleAddNewRank(WorldSession* session, std::string const& name);
void HandleRemoveRank(WorldSession* session, uint8 rankId);
- void HandleRemoveLowestRank(WorldSession* session);
- void HandleMemberDepositMoney(WorldSession* session, uint32 amount);
- bool HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair = false);
+ void HandleMemberDepositMoney(WorldSession* session, uint64 amount, bool cashFlow = false);
+ bool HandleMemberWithdrawMoney(WorldSession* session, uint64 amount, bool repair = false);
void HandleMemberLogout(WorldSession* session);
void HandleDisband(WorldSession* session);
+ void HandleGuildPartyRequest(WorldSession* session);
+ void HandleNewsSetSticky(WorldSession* session, uint32 newsId, bool sticky);
void UpdateMemberData(Player* player, uint8 dataid, uint32 value);
void OnPlayerStatusChange(Player* player, uint32 flag, bool state);
// Send info to client
- void SendInfo(WorldSession* session) const;
+ void SendGuildRankInfo(WorldSession* session) const;
void SendEventLog(WorldSession* session) const;
void SendBankLog(WorldSession* session, uint8 tabId) const;
- void SendBankTabsInfo(WorldSession* session, bool showTabs = false) const;
- void SendBankTabData(WorldSession* session, uint8 tabId) const;
+ void SendBankList(WorldSession* session, uint8 tabId, bool withContent, bool withTabInfo) const;
+ void SendGuildXP(WorldSession* session = NULL) const;
void SendBankTabText(WorldSession* session, uint8 tabId) const;
void SendPermissions(WorldSession* session) const;
void SendMoneyInfo(WorldSession* session) const;
void SendLoginInfo(WorldSession* session);
+ void SendNewsUpdate(WorldSession* session);
// Load from DB
bool LoadFromDB(Field* fields);
+ void LoadGuildNewsLogFromDB(Field* fields);
void LoadRankFromDB(Field* fields);
bool LoadMemberFromDB(Field* fields);
bool LoadEventLogFromDB(Field* fields);
@@ -711,6 +825,7 @@ public:
// Broadcasts
void BroadcastToGuild(WorldSession* session, bool officerOnly, std::string const& msg, uint32 language = LANG_UNIVERSAL) const;
+ void BroadcastAddonToGuild(WorldSession* session, bool officerOnly, std::string const& msg, std::string const& prefix) const;
void BroadcastPacketToRank(WorldPacket* packet, uint8 rankId) const;
void BroadcastPacket(WorldPacket* packet) const;
@@ -730,6 +845,8 @@ public:
bool AddMember(uint64 guid, uint8 rankId = GUILD_RANK_NONE);
void DeleteMember(uint64 guid, bool isDisbanding = false, bool isKicked = false, bool canDeleteGuild = false);
bool ChangeMemberRank(uint64 guid, uint8 newRank);
+ bool IsMember(uint64 guid) const;
+ uint32 GetMembersCount() { return m_members.size(); }
// Bank
void SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount);
@@ -738,7 +855,22 @@ public:
// Bank tabs
void SetBankTabText(uint8 tabId, std::string const& text);
- void ResetTimes();
+ AchievementMgr<Guild>& GetAchievementMgr() { return m_achievementMgr; }
+ AchievementMgr<Guild> const& GetAchievementMgr() const { return m_achievementMgr; }
+
+ // Guild leveling
+ uint8 GetLevel() const { return _level; }
+ void GiveXP(uint32 xp, Player* source);
+ uint64 GetExperience() const { return _experience; }
+ uint64 GetTodayExperience() const { return _todayExperience; }
+
+ void AddGuildNews(uint8 type, uint64 guid, uint32 flags, uint32 value);
+
+ EmblemInfo const& GetEmblemInfo() const { return m_emblemInfo; }
+ void ResetTimes(bool weekly);
+
+ bool HasAchieved(uint32 achievementId) const;
+ void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit* unit, Player* player);
protected:
uint32 m_id;
@@ -759,12 +891,18 @@ protected:
// These are actually ordered lists. The first element is the oldest entry.
LogHolder* m_eventLog;
LogHolder* m_bankEventLog[GUILD_BANK_MAX_TABS + 1];
+ LogHolder* m_newsLog;
+ AchievementMgr<Guild> m_achievementMgr;
+
+ uint8 _level;
+ uint64 _experience;
+ uint64 _todayExperience;
private:
inline uint8 _GetRanksSize() const { return uint8(m_ranks.size()); }
inline const RankInfo* GetRankInfo(uint8 rankId) const { return rankId < _GetRanksSize() ? &m_ranks[rankId] : NULL; }
inline RankInfo* GetRankInfo(uint8 rankId) { return rankId < _GetRanksSize() ? &m_ranks[rankId] : NULL; }
- inline bool _HasRankRight(Player* player, uint32 right) const
+ inline bool _HasRankRight(Player const* player, uint32 right) const
{
if (player)
if (Member const* member = GetMember(player->GetGUID()))
@@ -842,11 +980,10 @@ private:
void _MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAmount);
bool _DoItemsMove(MoveItemData* pSrc, MoveItemData* pDest, bool sendError, uint32 splitedAmount = 0);
- void _SendBankContent(WorldSession* session, uint8 tabId) const;
- void _SendBankMoneyUpdate(WorldSession* session) const;
void _SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) const;
void _SendBankContentUpdate(uint8 tabId, SlotIds slots) const;
- void _SendBankList(WorldSession* session = NULL, uint8 tabId = 0, bool sendFullSlots = false, SlotIds *slots = NULL) const;
+ void SendGuildReputationWeeklyCap(WorldSession* session, uint32 reputation) const;
+ void SendGuildRanksUpdate(uint64 setterGuid, uint64 targetGuid, uint32 rank);
void _BroadcastEvent(GuildEvents guildEvent, uint64 guid, const char* param1 = NULL, const char* param2 = NULL, const char* param3 = NULL) const;
};
diff --git a/src/server/game/Guilds/GuildFinderMgr.cpp b/src/server/game/Guilds/GuildFinderMgr.cpp
new file mode 100644
index 00000000000..024f4f4bd38
--- /dev/null
+++ b/src/server/game/Guilds/GuildFinderMgr.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "GuildFinderMgr.h"
+#include "GuildMgr.h"
+#include "World.h"
+
+GuildFinderMgr::GuildFinderMgr()
+{
+}
+
+GuildFinderMgr::~GuildFinderMgr()
+{
+}
+
+void GuildFinderMgr::LoadFromDB()
+{
+ LoadGuildSettings();
+ LoadMembershipRequests();
+}
+
+void GuildFinderMgr::LoadGuildSettings()
+{
+ TC_LOG_INFO("server.loading", "Loading guild finder guild-related settings...");
+ // 0 1 2 3 4 5 6 7
+ QueryResult result = CharacterDatabase.Query("SELECT gfgs.guildId, gfgs.availability, gfgs.classRoles, gfgs.interests, gfgs.level, gfgs.listed, gfgs.comment, c.race "
+ "FROM guild_finder_guild_settings gfgs "
+ "LEFT JOIN guild_member gm ON gm.guildid=gfgs.guildId "
+ "LEFT JOIN characters c ON c.guid = gm.guid LIMIT 1");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 guild finder guild-related settings. Table `guild_finder_guild_settings` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ uint32 oldMSTime = getMSTime();
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+ uint8 availability = fields[1].GetUInt8();
+ uint8 classRoles = fields[2].GetUInt8();
+ uint8 interests = fields[3].GetUInt8();
+ uint8 level = fields[4].GetUInt8();
+ bool listed = (fields[5].GetUInt8() != 0);
+ std::string comment = fields[6].GetString();
+
+ TeamId guildTeam = TEAM_ALLIANCE;
+ if (ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(fields[7].GetUInt8()))
+ if (raceEntry->TeamID == 1)
+ guildTeam = TEAM_HORDE;
+
+ LFGuildSettings settings(listed, guildTeam, guildId, classRoles, availability, interests, level, comment);
+ _guildSettings[guildId] = settings;
+
+ ++count;
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u guild finder guild-related settings in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void GuildFinderMgr::LoadMembershipRequests()
+{
+ TC_LOG_INFO("server.loading", "Loading guild finder membership requests...");
+ // 0 1 2 3 4 5 6
+ QueryResult result = CharacterDatabase.Query("SELECT guildId, playerGuid, availability, classRole, interests, comment, submitTime "
+ "FROM guild_finder_applicant");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 guild finder membership requests. Table `guild_finder_applicant` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ uint32 oldMSTime = getMSTime();
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+ uint32 playerId = fields[1].GetUInt32();
+ uint8 availability = fields[2].GetUInt8();
+ uint8 classRoles = fields[3].GetUInt8();
+ uint8 interests = fields[4].GetUInt8();
+ std::string comment = fields[5].GetString();
+ uint32 submitTime = fields[6].GetUInt32();
+
+ MembershipRequest request(playerId, guildId, availability, classRoles, interests, comment, time_t(submitTime));
+
+ _membershipRequests[guildId].push_back(request);
+
+ ++count;
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u guild finder membership requests in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void GuildFinderMgr::AddMembershipRequest(uint32 guildGuid, MembershipRequest const& request)
+{
+ _membershipRequests[guildGuid].push_back(request);
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GUILD_FINDER_APPLICANT);
+ stmt->setUInt32(0, request.GetGuildId());
+ stmt->setUInt32(1, request.GetPlayerGUID());
+ stmt->setUInt8(2, request.GetAvailability());
+ stmt->setUInt8(3, request.GetClassRoles());
+ stmt->setUInt8(4, request.GetInterests());
+ stmt->setString(5, request.GetComment());
+ stmt->setUInt32(6, request.GetSubmitTime());
+ trans->Append(stmt);
+ CharacterDatabase.CommitTransaction(trans);
+
+ // Notify the applicant his submittion has been added
+ if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(request.GetPlayerGUID(), 0, HIGHGUID_PLAYER)))
+ SendMembershipRequestListUpdate(*player);
+
+ // Notify the guild master and officers the list changed
+ if (Guild* guild = sGuildMgr->GetGuildById(guildGuid))
+ SendApplicantListUpdate(*guild);
+}
+
+void GuildFinderMgr::RemoveAllMembershipRequestsFromPlayer(uint32 playerId)
+{
+ for (MembershipRequestStore::iterator itr = _membershipRequests.begin(); itr != _membershipRequests.end(); ++itr)
+ {
+ std::vector<MembershipRequest>::iterator itr2 = itr->second.begin();
+ for (; itr2 != itr->second.end(); ++itr2)
+ if (itr2->GetPlayerGUID() == playerId)
+ break;
+
+ if (itr2 == itr->second.end())
+ continue;
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT);
+ stmt->setUInt32(0, itr2->GetGuildId());
+ stmt->setUInt32(1, itr2->GetPlayerGUID());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+ itr->second.erase(itr2);
+
+ // Notify the guild master and officers the list changed
+ if (Guild* guild = sGuildMgr->GetGuildById(itr->first))
+ SendApplicantListUpdate(*guild);
+ }
+}
+
+void GuildFinderMgr::RemoveMembershipRequest(uint32 playerId, uint32 guildId)
+{
+ std::vector<MembershipRequest>::iterator itr = _membershipRequests[guildId].begin();
+ for (; itr != _membershipRequests[guildId].end(); ++itr)
+ if (itr->GetPlayerGUID() == playerId)
+ break;
+
+ if (itr == _membershipRequests[guildId].end())
+ return;
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT);
+ stmt->setUInt32(0, itr->GetGuildId());
+ stmt->setUInt32(1, itr->GetPlayerGUID());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+
+ _membershipRequests[guildId].erase(itr);
+
+ // Notify the applicant his submittion has been removed
+ if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(playerId, 0, HIGHGUID_PLAYER)))
+ SendMembershipRequestListUpdate(*player);
+
+ // Notify the guild master and officers the list changed
+ if (Guild* guild = sGuildMgr->GetGuildById(guildId))
+ SendApplicantListUpdate(*guild);
+}
+
+std::list<MembershipRequest> GuildFinderMgr::GetAllMembershipRequestsForPlayer(uint32 playerGuid)
+{
+ std::list<MembershipRequest> resultSet;
+ for (MembershipRequestStore::const_iterator itr = _membershipRequests.begin(); itr != _membershipRequests.end(); ++itr)
+ {
+ std::vector<MembershipRequest> const& guildReqs = itr->second;
+ for (std::vector<MembershipRequest>::const_iterator itr2 = guildReqs.begin(); itr2 != guildReqs.end(); ++itr2)
+ {
+ if (itr2->GetPlayerGUID() == playerGuid)
+ {
+ resultSet.push_back(*itr2);
+ break;
+ }
+ }
+ }
+ return resultSet;
+}
+
+uint8 GuildFinderMgr::CountRequestsFromPlayer(uint32 playerId)
+{
+ uint8 result = 0;
+ for (MembershipRequestStore::const_iterator itr = _membershipRequests.begin(); itr != _membershipRequests.end(); ++itr)
+ {
+ for (std::vector<MembershipRequest>::const_iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2)
+ {
+ if (itr2->GetPlayerGUID() != playerId)
+ continue;
+ ++result;
+ break;
+ }
+ }
+ return result;
+}
+
+LFGuildStore GuildFinderMgr::GetGuildsMatchingSetting(LFGuildPlayer& settings, TeamId faction)
+{
+ LFGuildStore resultSet;
+ for (LFGuildStore::const_iterator itr = _guildSettings.begin(); itr != _guildSettings.end(); ++itr)
+ {
+ LFGuildSettings const& guildSettings = itr->second;
+
+ if (guildSettings.GetTeam() != faction)
+ continue;
+
+ if (!(guildSettings.GetAvailability() & settings.GetAvailability()))
+ continue;
+
+ if (!(guildSettings.GetClassRoles() & settings.GetClassRoles()))
+ continue;
+
+ if (!(guildSettings.GetInterests() & settings.GetInterests()))
+ continue;
+
+ if (!(guildSettings.GetLevel() & settings.GetLevel()))
+ continue;
+
+ resultSet.insert(std::make_pair(itr->first, guildSettings));
+ }
+
+ return resultSet;
+}
+
+bool GuildFinderMgr::HasRequest(uint32 playerId, uint32 guildId)
+{
+ for (std::vector<MembershipRequest>::const_iterator itr = _membershipRequests[guildId].begin(); itr != _membershipRequests[guildId].end(); ++itr)
+ if (itr->GetPlayerGUID() == playerId)
+ return true;
+ return false;
+}
+
+void GuildFinderMgr::SetGuildSettings(uint32 guildGuid, LFGuildSettings const& settings)
+{
+ _guildSettings[guildGuid] = settings;
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GUILD_FINDER_GUILD_SETTINGS);
+ stmt->setUInt32(0, settings.GetGUID());
+ stmt->setUInt8(1, settings.GetAvailability());
+ stmt->setUInt8(2, settings.GetClassRoles());
+ stmt->setUInt8(3, settings.GetInterests());
+ stmt->setUInt8(4, settings.GetLevel());
+ stmt->setUInt8(5, settings.IsListed());
+ stmt->setString(6, settings.GetComment());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+void GuildFinderMgr::DeleteGuild(uint32 guildId)
+{
+ std::vector<MembershipRequest>::iterator itr = _membershipRequests[guildId].begin();
+ while (itr != _membershipRequests[guildId].end())
+ {
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ uint32 applicant = itr->GetPlayerGUID();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT);
+ stmt->setUInt32(0, itr->GetGuildId());
+ stmt->setUInt32(1, applicant);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_GUILD_SETTINGS);
+ stmt->setUInt32(0, itr->GetGuildId());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+
+ // Notify the applicant his submition has been removed
+ if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(applicant, 0, HIGHGUID_PLAYER)))
+ SendMembershipRequestListUpdate(*player);
+
+ ++itr;
+ }
+
+ _membershipRequests.erase(guildId);
+ _guildSettings.erase(guildId);
+
+ // Notify the guild master the list changed (even if he's not a GM any more, not sure if needed)
+ if (Guild* guild = sGuildMgr->GetGuildById(guildId))
+ SendApplicantListUpdate(*guild);
+}
+
+void GuildFinderMgr::SendApplicantListUpdate(Guild& guild)
+{
+ WorldPacket data(SMSG_LF_GUILD_APPLICANT_LIST_UPDATED, 0);
+ if (Player* player = ObjectAccessor::FindPlayer(guild.GetLeaderGUID()))
+ player->SendDirectMessage(&data);
+ guild.BroadcastPacketToRank(&data, GR_OFFICER);
+}
+
+void GuildFinderMgr::SendMembershipRequestListUpdate(Player& player)
+{
+ WorldPacket data(SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED, 0);
+ player.SendDirectMessage(&data);
+}
diff --git a/src/server/game/Guilds/GuildFinderMgr.h b/src/server/game/Guilds/GuildFinderMgr.h
new file mode 100644
index 00000000000..9fc62d43935
--- /dev/null
+++ b/src/server/game/Guilds/GuildFinderMgr.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TRINITY_GUILDFINDER_H
+#define __TRINITY_GUILDFINDER_H
+
+#include "Common.h"
+#include "World.h"
+#include "GuildMgr.h"
+
+enum GuildFinderOptionsInterest
+{
+ INTEREST_QUESTING = 0x01,
+ INTEREST_DUNGEONS = 0x02,
+ INTEREST_RAIDS = 0x04,
+ INTEREST_PVP = 0x08,
+ INTEREST_ROLE_PLAYING = 0x10,
+ ALL_INTERESTS = INTEREST_QUESTING | INTEREST_DUNGEONS | INTEREST_RAIDS | INTEREST_PVP | INTEREST_ROLE_PLAYING
+};
+
+enum GuildFinderOptionsAvailability
+{
+ AVAILABILITY_WEEKDAYS = 0x1,
+ AVAILABILITY_WEEKENDS = 0x2,
+ AVAILABILITY_ALWAYS = AVAILABILITY_WEEKDAYS | AVAILABILITY_WEEKENDS
+};
+
+enum GuildFinderOptionsRoles
+{
+ GUILDFINDER_ROLE_TANK = 0x1,
+ GUILDFINDER_ROLE_HEALER = 0x2,
+ GUILDFINDER_ROLE_DPS = 0x4,
+ GUILDFINDER_ALL_ROLES = GUILDFINDER_ROLE_TANK | GUILDFINDER_ROLE_HEALER | GUILDFINDER_ROLE_DPS
+};
+
+enum GuildFinderOptionsLevel
+{
+ ANY_FINDER_LEVEL = 0x1,
+ MAX_FINDER_LEVEL = 0x2,
+ ALL_GUILDFINDER_LEVELS = ANY_FINDER_LEVEL | MAX_FINDER_LEVEL
+};
+
+/// Holds all required informations about a membership request
+struct MembershipRequest
+{
+ public:
+ MembershipRequest(MembershipRequest const& settings) : _comment(settings.GetComment())
+ {
+ _availability = settings.GetAvailability();
+ _classRoles = settings.GetClassRoles();
+ _interests = settings.GetInterests();
+ _guildId = settings.GetGuildId();
+ _playerGUID = settings.GetPlayerGUID();
+ _time = settings.GetSubmitTime();
+ }
+
+ MembershipRequest(uint32 playerGUID, uint32 guildId, uint32 availability, uint32 classRoles, uint32 interests, std::string& comment, time_t submitTime) :
+ _comment(comment), _guildId(guildId), _playerGUID(playerGUID), _availability(availability),
+ _classRoles(classRoles), _interests(interests), _time(submitTime) {}
+
+ MembershipRequest() : _guildId(0), _playerGUID(0), _availability(0), _classRoles(0),
+ _interests(0), _time(time(NULL)) {}
+
+ uint32 GetGuildId() const { return _guildId; }
+ uint32 GetPlayerGUID() const { return _playerGUID; }
+ uint8 GetAvailability() const { return _availability; }
+ uint8 GetClassRoles() const { return _classRoles; }
+ uint8 GetInterests() const { return _interests; }
+ uint8 GetClass() const { return sWorld->GetCharacterNameData(GetPlayerGUID())->m_class; }
+ uint8 GetLevel() const { return sWorld->GetCharacterNameData(GetPlayerGUID())->m_level; }
+ time_t GetSubmitTime() const { return _time; }
+ time_t GetExpiryTime() const { return time_t(_time + 30 * 24 * 3600); } // Adding 30 days
+ std::string const& GetComment() const { return _comment; }
+ std::string const& GetName() const { return sWorld->GetCharacterNameData(GetPlayerGUID())->m_name; }
+ private:
+ std::string _comment;
+
+ uint32 _guildId;
+ uint32 _playerGUID;
+
+ uint8 _availability;
+ uint8 _classRoles;
+ uint8 _interests;
+
+ time_t _time;
+};
+
+/// Holds all informations about a player's finder settings. _NOT_ stored in database.
+struct LFGuildPlayer
+{
+ public:
+ LFGuildPlayer()
+ {
+ _guid = 0;
+ _roles = 0;
+ _availability = 0;
+ _interests = 0;
+ _level = 0;
+ }
+
+ LFGuildPlayer(uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level)
+ {
+ _guid = guid;
+ _roles = role;
+ _availability = availability;
+ _interests = interests;
+ _level = level;
+ }
+
+ LFGuildPlayer(uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level, std::string& comment) : _comment(comment)
+ {
+ _guid = guid;
+ _roles = role;
+ _availability = availability;
+ _interests = interests;
+ _level = level;
+ }
+
+ LFGuildPlayer(LFGuildPlayer const& settings) : _comment(settings.GetComment())
+ {
+ _guid = settings.GetGUID();
+ _roles = settings.GetClassRoles();
+ _availability = settings.GetAvailability();
+ _interests = settings.GetInterests();
+ _level = settings.GetLevel();
+ }
+
+ uint32 GetGUID() const { return _guid; }
+ uint8 GetClassRoles() const { return _roles; }
+ uint8 GetAvailability() const { return _availability; }
+ uint8 GetInterests() const { return _interests; }
+ uint8 GetLevel() const { return _level; }
+ std::string const& GetComment() const { return _comment; }
+
+ private:
+ std::string _comment;
+ uint32 _guid;
+ uint8 _roles;
+ uint8 _availability;
+ uint8 _interests;
+ uint8 _level;
+};
+
+/// Holds settings for a guild in the finder system. Saved to database.
+struct LFGuildSettings : public LFGuildPlayer
+{
+ public:
+ LFGuildSettings() : LFGuildPlayer(), _listed(false), _team(TEAM_ALLIANCE) {}
+
+ LFGuildSettings(bool listed, TeamId team) : LFGuildPlayer(), _listed(listed), _team(team) {}
+
+ LFGuildSettings(bool listed, TeamId team, uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level) :
+ LFGuildPlayer(guid, role, availability, interests, level), _listed(listed), _team(team) {}
+
+ LFGuildSettings(bool listed, TeamId team, uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level, std::string& comment) :
+ LFGuildPlayer(guid, role, availability, interests, level, comment), _listed(listed), _team(team) {}
+
+ LFGuildSettings(LFGuildSettings const& settings) :
+ LFGuildPlayer(settings), _listed(settings.IsListed()), _team(settings.GetTeam()) {}
+
+
+ bool IsListed() const { return _listed; }
+ void SetListed(bool state) { _listed = state; }
+
+ TeamId GetTeam() const { return _team; }
+ private:
+ bool _listed;
+ TeamId _team;
+};
+
+typedef std::map<uint32 /* guildGuid */, LFGuildSettings> LFGuildStore;
+typedef std::map<uint32 /* guildGuid */, std::vector<MembershipRequest> > MembershipRequestStore;
+
+class GuildFinderMgr
+{
+ private:
+ GuildFinderMgr();
+ ~GuildFinderMgr();
+
+ LFGuildStore _guildSettings;
+
+ MembershipRequestStore _membershipRequests;
+
+ void LoadGuildSettings();
+ void LoadMembershipRequests();
+
+ public:
+ void LoadFromDB();
+
+ /**
+ * @brief Stores guild settings and begins an asynchronous database insert
+ * @param guildGuid The guild's database guid.
+ * @param LFGuildSettings The guild's settings storage.
+ */
+ void SetGuildSettings(uint32 guildGuid, LFGuildSettings const& settings);
+
+ /**
+ * @brief Returns settings for a guild.
+ * @param guildGuid The guild's database guid.
+ */
+ LFGuildSettings GetGuildSettings(uint32 guildGuid) { return _guildSettings[guildGuid]; }
+
+ /**
+ * @brief Files a membership request to a guild
+ * @param guildGuid The guild's database GUID.
+ * @param MembershipRequest An object storing all data related to the request.
+ */
+ void AddMembershipRequest(uint32 guildGuid, MembershipRequest const& request);
+
+ /**
+ * @brief Removes all membership request from a player.
+ * @param playerId The player's database guid whose application shall be deleted.
+ */
+ void RemoveAllMembershipRequestsFromPlayer(uint32 playerId);
+
+ /**
+ * @brief Removes a membership request to a guild.
+ * @param playerId The player's database guid whose application shall be deleted.
+ * @param guildId The guild's database guid
+ */
+ void RemoveMembershipRequest(uint32 playerId, uint32 guildId);
+
+ /// Wipes everything related to a guild. Used when that guild is disbanded
+ void DeleteGuild(uint32 guildId);
+
+ /**
+ * @brief Returns a set of membership requests for a guild
+ * @param guildGuid The guild's database guid.
+ */
+ std::vector<MembershipRequest> GetAllMembershipRequestsForGuild(uint32 guildGuid) { return _membershipRequests[guildGuid]; }
+
+ /**
+ * @brief Returns a list of membership requests for a player.
+ * @param playerGuid The player's database guid.
+ */
+ std::list<MembershipRequest> GetAllMembershipRequestsForPlayer(uint32 playerGuid);
+
+ /**
+ * @brief Returns a store of guilds matching the settings provided, using bitmask operators.
+ * @param settings The player's finder settings
+ * @param teamId The player's faction (TEAM_ALLIANCE or TEAM_HORDE)
+ */
+ LFGuildStore GetGuildsMatchingSetting(LFGuildPlayer& settings, TeamId faction);
+
+ /// Provided a player DB guid and a guild DB guid, determines if a pending request is filed with these keys.
+ bool HasRequest(uint32 playerId, uint32 guildId);
+
+ /// Counts the amount of pending membership requests, given the player's db guid.
+ uint8 CountRequestsFromPlayer(uint32 playerId);
+
+ void SendApplicantListUpdate(Guild& guild);
+ void SendMembershipRequestListUpdate(Player& player);
+
+ static GuildFinderMgr* instance()
+ {
+ static GuildFinderMgr instance;
+ return &instance;
+ }
+};
+
+#define sGuildFinderMgr GuildFinderMgr::instance()
+
+#endif // __TRINITY_GUILDFINDER_H
diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp
index b9cb7d6dce9..bdb0b7dce52 100644
--- a/src/server/game/Guilds/GuildMgr.cpp
+++ b/src/server/game/Guilds/GuildMgr.cpp
@@ -37,6 +37,12 @@ void GuildMgr::RemoveGuild(uint32 guildId)
GuildStore.erase(guildId);
}
+void GuildMgr::SaveGuilds()
+{
+ for (GuildContainer::iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
+ itr->second->SaveToDB();
+}
+
uint32 GuildMgr::GenerateGuildId()
{
if (NextGuildId >= 0xFFFFFFFE)
@@ -57,6 +63,17 @@ Guild* GuildMgr::GetGuildById(uint32 guildId) const
return NULL;
}
+Guild* GuildMgr::GetGuildByGuid(uint64 guid) const
+{
+ // Full guids are only used when receiving/sending data to client
+ // everywhere else guild id is used
+ if (IS_GUILD_GUID(guid))
+ if (uint32 guildId = GUID_LOPART(guid))
+ return GetGuildById(guildId);
+
+ return NULL;
+}
+
Guild* GuildMgr::GetGuildByName(const std::string& guildName) const
{
std::string search = guildName;
@@ -88,6 +105,13 @@ Guild* GuildMgr::GetGuildByLeader(uint64 guid) const
return NULL;
}
+uint32 GuildMgr::GetXPForGuildLevel(uint8 level) const
+{
+ if (level < GuildXPperLevel.size())
+ return GuildXPperLevel[level];
+ return 0;
+}
+
void GuildMgr::LoadGuilds()
{
// 1. Load all guilds
@@ -97,8 +121,8 @@ void GuildMgr::LoadGuilds()
// 0 1 2 3 4 5 6
QueryResult result = CharacterDatabase.Query("SELECT g.guildid, g.name, g.leaderguid, g.EmblemStyle, g.EmblemColor, g.BorderStyle, g.BorderColor, "
- // 7 8 9 10 11 12
- "g.BackgroundColor, g.info, g.motd, g.createdate, g.BankMoney, COUNT(gbt.guildid) "
+ // 7 8 9 10 11 12 13 14 15
+ "g.BackgroundColor, g.info, g.motd, g.createdate, g.BankMoney, g.level, g.experience, g.todayExperience, COUNT(gbt.guildid) "
"FROM guild g LEFT JOIN guild_bank_tab gbt ON g.guildid = gbt.guildid GROUP BY g.guildid ORDER BY g.guildid ASC");
if (!result)
@@ -173,13 +197,13 @@ void GuildMgr::LoadGuilds()
CharacterDatabase.DirectExecute("DELETE gm FROM guild_member gm LEFT JOIN guild g ON gm.guildId = g.guildId WHERE g.guildId IS NULL");
CharacterDatabase.DirectExecute("DELETE gm FROM guild_member_withdraw gm LEFT JOIN guild_member g ON gm.guid = g.guid WHERE g.guid IS NULL");
- // 0 1 2 3 4 5 6 7 8 9 10
- QueryResult result = CharacterDatabase.Query("SELECT guildid, gm.guid, rank, pnote, offnote, w.tab0, w.tab1, w.tab2, w.tab3, w.tab4, w.tab5, "
- // 11 12 13 14 15 16 17
- "w.money, c.name, c.level, c.class, c.zone, c.account, c.logout_time "
+ // 0 1 2 3 4 5 6 7 8 9 10
+ QueryResult result = CharacterDatabase.Query("SELECT gm.guildid, gm.guid, rank, pnote, offnote, w.tab0, w.tab1, w.tab2, w.tab3, w.tab4, w.tab5, "
+ // 11 12 13 14 15 16 17 18 19
+ "w.tab6, w.tab7, w.money, c.name, c.level, c.class, c.zone, c.account, c.logout_time "
"FROM guild_member gm "
"LEFT JOIN guild_member_withdraw w ON gm.guid = w.guid "
- "LEFT JOIN characters c ON c.guid = gm.guid ORDER BY guildid ASC");
+ "LEFT JOIN characters c ON c.guid = gm.guid ORDER BY gm.guildid ASC");
if (!result)
TC_LOG_INFO("server.loading", ">> Loaded 0 guild members. DB table `guild_member` is empty.");
@@ -304,7 +328,39 @@ void GuildMgr::LoadGuilds()
}
}
- // 7. Load all guild bank tabs
+ // 7. Load all news event logs
+ TC_LOG_INFO("server.loading", "Loading Guild News...");
+ {
+ uint32 oldMSTime = getMSTime();
+
+ CharacterDatabase.DirectPExecute("DELETE FROM guild_newslog WHERE LogGuid > %u", sWorld->getIntConfig(CONFIG_GUILD_NEWS_LOG_COUNT));
+
+ // 0 1 2 3 4 5 6
+ QueryResult result = CharacterDatabase.Query("SELECT guildid, LogGuid, EventType, PlayerGuid, Flags, Value, Timestamp FROM guild_newslog ORDER BY TimeStamp DESC, LogGuid DESC");
+
+ if (!result)
+ TC_LOG_INFO("server.loading", ">> Loaded 0 guild event logs. DB table `guild_newslog` is empty.");
+ else
+ {
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+
+ if (Guild* guild = GetGuildById(guildId))
+ guild->LoadGuildNewsLogFromDB(fields);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u guild new logs in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ }
+ }
+
+
+ // 8. Load all guild bank tabs
TC_LOG_INFO("server.loading", "Loading guild bank tabs...");
{
uint32 oldMSTime = getMSTime();
@@ -338,7 +394,7 @@ void GuildMgr::LoadGuilds()
}
}
- // 8. Fill all guild bank tabs
+ // 9. Fill all guild bank tabs
TC_LOG_INFO("guild", "Filling bank tabs with items...");
{
uint32 oldMSTime = getMSTime();
@@ -374,8 +430,25 @@ void GuildMgr::LoadGuilds()
}
}
- // 9. Validate loaded guild data
- TC_LOG_INFO("guild", "Validating data of loaded guilds...");
+ // 10. Load guild achievements
+ {
+ PreparedQueryResult achievementResult;
+ PreparedQueryResult criteriaResult;
+ for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_ACHIEVEMENT);
+ stmt->setUInt32(0, itr->first);
+ achievementResult = CharacterDatabase.Query(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt32(0, itr->first);
+ criteriaResult = CharacterDatabase.Query(stmt);
+
+ itr->second->GetAchievementMgr().LoadFromDB(achievementResult, criteriaResult);
+ }
+ }
+
+ // 11. Validate loaded guild data
+ TC_LOG_INFO("misc", "Validating data of loaded guilds...");
{
uint32 oldMSTime = getMSTime();
@@ -391,11 +464,112 @@ void GuildMgr::LoadGuilds()
}
}
-void GuildMgr::ResetTimes()
+void GuildMgr::LoadGuildXpForLevel()
{
+ uint32 oldMSTime = getMSTime();
+
+ GuildXPperLevel.resize(sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL));
+ for (uint8 level = 0; level < sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL); ++level)
+ GuildXPperLevel[level] = 0;
+
+ // 0 1
+ QueryResult result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM guild_xp_for_level");
+
+ if (!result)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 xp for guild level definitions. DB table `guild_xp_for_level` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 level = fields[0].GetUInt8();
+ uint32 requiredXP = fields[1].GetUInt32();
+
+ if (level >= sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL))
+ {
+ TC_LOG_INFO("misc", "Unused (> Guild.MaxLevel in worldserver.conf) level %u in `guild_xp_for_level` table, ignoring.", uint32(level));
+ continue;
+ }
+
+ GuildXPperLevel[level] = requiredXP;
+ ++count;
+
+ } while (result->NextRow());
+
+ // fill level gaps
+ for (uint8 level = 1; level < sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL); ++level)
+ {
+ if (!GuildXPperLevel[level])
+ {
+ TC_LOG_ERROR("sql.sql", "Level %i does not have XP for guild level data. Using data of level [%i] + 1660000.", level+1, level);
+ GuildXPperLevel[level] = GuildXPperLevel[level - 1] + 1660000;
+ }
+ }
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u xp for guild level definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void GuildMgr::LoadGuildRewards()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT entry, standing, racemask, price, achievement FROM guild_rewards");
+
+ if (!result)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 guild reward definitions. DB table `guild_rewards` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ GuildReward reward;
+ Field* fields = result->Fetch();
+ reward.Entry = fields[0].GetUInt32();
+ reward.Standing = fields[1].GetUInt8();
+ reward.Racemask = fields[2].GetInt32();
+ reward.Price = fields[3].GetUInt64();
+ reward.AchievementId = fields[4].GetUInt32();
+
+ if (!sObjectMgr->GetItemTemplate(reward.Entry))
+ {
+ TC_LOG_ERROR("server.loading", "Guild rewards constains not existing item entry %u", reward.Entry);
+ continue;
+ }
+
+ if (reward.AchievementId != 0 && (!sAchievementMgr->GetAchievement(reward.AchievementId)))
+ {
+ TC_LOG_ERROR("server.loading", "Guild rewards constains not existing achievement entry %u", reward.AchievementId);
+ continue;
+ }
+
+ if (reward.Standing >= MAX_REPUTATION_RANK)
+ {
+ TC_LOG_ERROR("server.loading", "Guild rewards contains wrong reputation standing %u, max is %u", uint32(reward.Standing), MAX_REPUTATION_RANK - 1);
+ continue;
+ }
+
+ GuildRewards.push_back(reward);
+ ++count;
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u guild reward definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void GuildMgr::ResetTimes(bool week)
+{
+ CharacterDatabase.Execute(CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RESET_TODAY_EXPERIENCE));
+ CharacterDatabase.Execute(CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_MEMBER_WITHDRAW));
+
for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
if (Guild* guild = itr->second)
- guild->ResetTimes();
-
- CharacterDatabase.DirectExecute("TRUNCATE guild_member_withdraw");
-} \ No newline at end of file
+ guild->ResetTimes(week);
+}
diff --git a/src/server/game/Guilds/GuildMgr.h b/src/server/game/Guilds/GuildMgr.h
index 4aa418b7e73..5df59f7e8ea 100644
--- a/src/server/game/Guilds/GuildMgr.h
+++ b/src/server/game/Guilds/GuildMgr.h
@@ -35,21 +35,34 @@ public:
Guild* GetGuildByLeader(uint64 guid) const;
Guild* GetGuildById(uint32 guildId) const;
+ Guild* GetGuildByGuid(uint64 guid) const;
Guild* GetGuildByName(std::string const& guildName) const;
std::string GetGuildNameById(uint32 guildId) const;
+ void LoadGuildXpForLevel();
+ void LoadGuildRewards();
+
void LoadGuilds();
void AddGuild(Guild* guild);
void RemoveGuild(uint32 guildId);
+ void SaveGuilds();
+
+ void ResetReputationCaps();
+
uint32 GenerateGuildId();
void SetNextGuildId(uint32 Id) { NextGuildId = Id; }
- void ResetTimes();
+ uint32 GetXPForGuildLevel(uint8 level) const;
+ std::vector<GuildReward> const& GetGuildRewards() const { return GuildRewards; }
+
+ void ResetTimes(bool week);
protected:
typedef std::unordered_map<uint32, Guild*> GuildContainer;
uint32 NextGuildId;
GuildContainer GuildStore;
+ std::vector<uint64> GuildXPperLevel;
+ std::vector<GuildReward> GuildRewards;
};
#define sGuildMgr GuildMgr::instance()
diff --git a/src/server/game/Handlers/ArenaTeamHandler.cpp b/src/server/game/Handlers/ArenaTeamHandler.cpp
index 3bb3edac500..b2db2fff6c2 100644
--- a/src/server/game/Handlers/ArenaTeamHandler.cpp
+++ b/src/server/game/Handlers/ArenaTeamHandler.cpp
@@ -83,6 +83,54 @@ void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket& recvData)
arenaTeam->Roster(this);
}
+void WorldSession::HandleArenaTeamCreateOpcode(WorldPacket & recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_ARENA_TEAM_CREATE");
+
+ uint32 slot, icon, iconcolor, border, bordercolor, background;
+ std::string name;
+
+ recvData >> slot;
+ recvData >> iconcolor;
+ recvData >> bordercolor;
+ recvData >> border;
+ recvData >> background;
+ recvData >> icon;
+ name = recvData.ReadString(recvData.ReadBits(8));
+
+ uint8 type = ArenaTeam::GetTypeBySlot(slot);
+
+ if (_player->GetArenaTeamId(slot))
+ {
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
+ return;
+ }
+
+ if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
+ {
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
+ return;
+ }
+
+ if (sArenaTeamMgr->GetArenaTeamByName(name))
+ {
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
+ return;
+ }
+
+ ArenaTeam* arenaTeam = new ArenaTeam;
+ if (!arenaTeam->Create(GUID_LOPART(_player->GetGUID()), type, name, background, icon, iconcolor, border, bordercolor))
+ {
+ TC_LOG_ERROR("bg.arena", "Arena team create failed.");
+ delete arenaTeam;
+ return;
+ }
+
+ sArenaTeamMgr->AddArenaTeam(arenaTeam);
+
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_CREATED);
+}
+
void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "CMSG_ARENA_TEAM_INVITE");
@@ -121,6 +169,12 @@ void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket& recvData)
return;
}
+ if (arenaTeam->GetCaptain() != _player->GetGUID())
+ {
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
+ return;
+ }
+
if (GetPlayer()->GetArenaTeamId(arenaTeam->GetSlot()) != arenaTeamId)
{
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
@@ -363,20 +417,25 @@ void WorldSession::HandleArenaTeamLeaderOpcode(WorldPacket& recvData)
void WorldSession::SendArenaTeamCommandResult(uint32 teamAction, const std::string& team, const std::string& player, uint32 errorId)
{
- WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+team.length()+1+player.length()+1+4);
+ WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 2 + team.length() + player.length() + 4 + 4);
+
+ data.WriteBits(player.length(), 7);
+ data.WriteBits(team.length(), 8);
+ data.FlushBits();
+
+ data.WriteString(player);
data << uint32(teamAction);
- data << team;
- data << player;
data << uint32(errorId);
+ data.WriteString(team);
SendPacket(&data);
}
void WorldSession::SendNotInArenaTeamPacket(uint8 type)
{
- WorldPacket data(SMSG_ARENA_ERROR, 4+1); // 886 - You are not in a %uv%u arena team
- uint32 unk = 0;
- data << uint32(unk); // unk(0)
- if (!unk)
+ WorldPacket data(SMSG_ARENA_ERROR, 4+1);
+ uint32 error = 0;
+ data << uint32(error); // 0 = ERR_ARENA_NO_TEAM_II, 1 = ERR_ARENA_EXPIRED_CAIS, 2 = ERR_LFG_CANT_USE_BATTLEGROUND
+ if (!error)
data << uint8(type); // team type (2=2v2, 3=3v3, 5=5v5), can be used for custom types...
SendPacket(&data);
}
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index 86fa0429cce..12bc18298b7 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -71,14 +71,29 @@ void WorldSession::SendAuctionHello(uint64 guid, Creature* unit)
}
//call this method when player bids, creates, or deletes auction
-void WorldSession::SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError)
+void WorldSession::SendAuctionCommandResult(AuctionEntry* auction, uint32 action, uint32 errorCode, uint32 bidError)
{
- WorldPacket data(SMSG_AUCTION_COMMAND_RESULT, 16);
- data << auctionId;
- data << Action;
- data << ErrorCode;
- if (!ErrorCode && Action)
- data << bidError; //when bid, then send 0, once...
+ WorldPacket data(SMSG_AUCTION_COMMAND_RESULT);
+ data << uint32(auction ? auction->Id : 0);
+ data << uint32(action);
+ data << uint32(errorCode);
+
+ switch (errorCode)
+ {
+ case ERR_AUCTION_OK:
+ if (action == AUCTION_PLACE_BID)
+ data << uint64(auction->bid ? auction->GetAuctionOutBid() : 0);
+ break;
+ case ERR_AUCTION_INVENTORY:
+ data << uint32(bidError);
+ break;
+ case ERR_AUCTION_HIGHER_BID:
+ data << uint64(auction->bidder);
+ data << uint64(auction->bid);
+ data << uint64(auction->bid ? auction->GetAuctionOutBid() : 0);
+ break;
+ }
+
SendPacket(&data);
}
@@ -89,32 +104,41 @@ void WorldSession::SendAuctionBidderNotification(uint32 location, uint32 auction
data << uint32(location);
data << uint32(auctionId);
data << uint64(bidder);
- data << uint32(bidSum);
- data << uint32(diff);
+ data << uint64(bidSum);
+ data << uint64(diff);
data << uint32(itemEntry);
data << uint32(0);
SendPacket(&data);
}
-//this void causes on client to display: "Your auction sold"
+// this void causes on client to display: "Your auction sold"
void WorldSession::SendAuctionOwnerNotification(AuctionEntry* auction)
{
- WorldPacket data(SMSG_AUCTION_OWNER_NOTIFICATION, (8*4));
+ WorldPacket data(SMSG_AUCTION_OWNER_NOTIFICATION, 40);
data << uint32(auction->Id);
- data << uint32(auction->bid);
- data << uint32(0); //unk
- data << uint64(0); //unk (bidder guid?)
+ data << uint64(auction->bid);
+ data << uint64(0); //unk
+ data << uint64(0); //unk
data << uint32(auction->itemEntry);
- data << uint32(0); //unk
- data << float(0); //unk (time?)
+ data << uint32(0); //unk
+ data << float(0); //unk
+ SendPacket(&data);
+}
+
+void WorldSession::SendAuctionRemovedNotification(uint32 auctionId, uint32 itemEntry, int32 randomPropertyId)
+{
+ WorldPacket data(SMSG_AUCTION_REMOVED_NOTIFICATION, (4+4+4));
+ data << uint32(auctionId);
+ data << uint32(itemEntry);
+ data << uint32(randomPropertyId);
SendPacket(&data);
}
//this void creates new auction and adds auction to some auctionhouse
void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
{
- uint64 auctioneer;
- uint32 itemsCount, etime, bid, buyout;
+ uint64 auctioneer, bid, buyout;
+ uint32 itemsCount, etime;
recvData >> auctioneer;
recvData >> itemsCount;
@@ -125,7 +149,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (itemsCount > MAX_AUCTION_ITEMS)
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
recvData.rfinish();
return;
}
@@ -152,7 +176,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (bid > MAX_MONEY_AMOUNT || buyout > MAX_MONEY_AMOUNT)
{
TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Player %s (GUID %u) attempted to sell item with higher price than max gold amount.", _player->GetName().c_str(), _player->GetGUIDLow());
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
return;
}
@@ -197,7 +221,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (!item)
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_ITEM_NOT_FOUND);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_ITEM_NOT_FOUND);
return;
}
@@ -208,7 +232,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) ||
item->GetCount() < count[i] || itemEntry != item->GetTemplate()->ItemId)
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
return;
}
@@ -218,7 +242,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (!finalCount)
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
return;
}
@@ -241,7 +265,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (item->GetMaxStackCount() < finalCount)
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
return;
}
}
@@ -252,9 +276,9 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction());
uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, item, finalCount);
- if (!_player->HasEnoughMoney(deposit))
+ if (!_player->HasEnoughMoney((uint64)deposit))
{
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_NOT_ENOUGHT_MONEY);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_NOT_ENOUGHT_MONEY);
return;
}
@@ -287,7 +311,10 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
AH->deposit = deposit;
AH->auctionHouseEntry = auctionHouseEntry;
- TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName().c_str(), _player->GetGUIDLow(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUIDLow(), AH->auctioneer, item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
+ TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) "
+ "to auctioneer %u with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u",
+ _player->GetName().c_str(), _player->GetGUIDLow(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUIDLow(),
+ AH->auctioneer, item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
sAuctionMgr->AddAItem(item);
auctionHouse->AddAuction(AH);
@@ -300,7 +327,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
_player->SaveInventoryAndGoldToDB(trans);
CharacterDatabase.CommitTransaction(trans);
- SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
+ SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
}
@@ -310,7 +337,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
if (!newItem)
{
TC_LOG_ERROR("network", "CMSG_AUCTION_SELL_ITEM: Could not create clone of item %u", item->GetEntry());
- SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
delete AH;
return;
}
@@ -334,7 +361,10 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
AH->deposit = deposit;
AH->auctionHouseEntry = auctionHouseEntry;
- TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName().c_str(), _player->GetGUIDLow(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetGUIDLow(), AH->auctioneer, newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
+ TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to "
+ "auctioneer %u with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u",
+ _player->GetName().c_str(), _player->GetGUIDLow(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(),
+ newItem->GetGUIDLow(), AH->auctioneer, newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
sAuctionMgr->AddAItem(newItem);
auctionHouse->AddAuction(AH);
@@ -372,7 +402,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
_player->SaveInventoryAndGoldToDB(trans);
CharacterDatabase.CommitTransaction(trans);
- SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
+ SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
}
@@ -380,19 +410,20 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
_player->ModifyMoney(-int32(deposit));
}
-//this function is called when client bids or buys out auction
+// this function is called when client bids or buys out auction
void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_PLACE_BID");
uint64 auctioneer;
uint32 auctionId;
- uint32 price;
+ uint64 price;
recvData >> auctioneer;
- recvData >> auctionId >> price;
+ recvData >> auctionId;
+ recvData >> price;
if (!auctionId || !price)
- return; //check for cheaters
+ return; // check for cheaters
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER);
if (!creature)
@@ -413,18 +444,18 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
if (!auction || auction->owner == player->GetGUIDLow())
{
//you cannot bid your own auction:
- SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN);
+ SendAuctionCommandResult(NULL, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN);
return;
}
// impossible have online own another character (use this for speedup check in case online owner)
- Player* auction_owner = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER));
+ /*Player* auction_owner = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER));
if (!auction_owner && sObjectMgr->GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == player->GetSession()->GetAccountId())
{
//you cannot bid your another character auction:
- SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN);
+ SendAuctionCommandResult(NULL, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN);
return;
- }
+ }*/
// cheating
if (price <= auction->bid || price < auction->startbid)
@@ -434,14 +465,15 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
if ((price < auction->buyout || auction->buyout == 0) &&
price < auction->bid + auction->GetAuctionOutBid())
{
- //auction has already higher bid, client tests it!
+ // client already test it but just in case ...
+ SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_HIGHER_BID);
return;
}
if (!player->HasEnoughMoney(price))
{
- //you don't have enought money!, client tests!
- //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???);
+ // client already test it but just in case ...
+ SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_NOT_ENOUGHT_MONEY);
return;
}
@@ -452,16 +484,16 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
if (auction->bidder > 0)
{
if (auction->bidder == player->GetGUIDLow())
- player->ModifyMoney(-int32(price - auction->bid));
+ player->ModifyMoney(-int64(price - auction->bid));
else
{
// mail to last bidder and return money
sAuctionMgr->SendAuctionOutbiddedMail(auction, price, GetPlayer(), trans);
- player->ModifyMoney(-int32(price));
+ player->ModifyMoney(-int64(price));
}
}
else
- player->ModifyMoney(-int32(price));
+ player->ModifyMoney(-int64(price));
auction->bidder = player->GetGUIDLow();
auction->bid = price;
@@ -473,16 +505,16 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
stmt->setUInt32(2, auction->Id);
trans->Append(stmt);
- SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK, 0);
+ SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_OK);
}
else
{
//buyout:
if (player->GetGUIDLow() == auction->bidder)
- player->ModifyMoney(-int32(auction->buyout - auction->bid));
+ player->ModifyMoney(-int64(auction->buyout - auction->bid));
else
{
- player->ModifyMoney(-int32(auction->buyout));
+ player->ModifyMoney(-int64(auction->buyout));
if (auction->bidder) //buyout for bidded auction ..
sAuctionMgr->SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans);
}
@@ -495,7 +527,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
sAuctionMgr->SendAuctionSuccessfulMail(auction, trans);
sAuctionMgr->SendAuctionWonMail(auction, trans);
- SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK);
+ SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_OK);
auction->DeleteFromDB(trans);
@@ -516,7 +548,6 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData)
uint32 auctionId;
recvData >> auctioneer;
recvData >> auctionId;
- //TC_LOG_DEBUG("Cancel AUCTION AuctionID: %u", auctionId);
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER);
if (!creature)
@@ -543,11 +574,10 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData)
if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid
{
uint32 auctionCut = auction->GetAuctionCut();
- if (!player->HasEnoughMoney(auctionCut)) //player doesn't have enough money, maybe message needed
+ if (!player->HasEnoughMoney((uint64)auctionCut)) //player doesn't have enough money, maybe message needed
return;
- //some auctionBidderNotification would be needed, but don't know that parts..
- sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans);
- player->ModifyMoney(-int32(auctionCut));
+ sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans, pItem);
+ player->ModifyMoney(-int64(auctionCut));
}
// item will deleted or added to received mail list
@@ -557,21 +587,21 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData)
}
else
{
- TC_LOG_ERROR("network", "Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->itemGUIDLow);
- SendAuctionCommandResult(0, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR);
+ TC_LOG_ERROR("network", "Auction id: %u got non existing item (item guid : %u)!", auction->Id, auction->itemGUIDLow);
+ SendAuctionCommandResult(NULL, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR);
return;
}
}
else
{
- SendAuctionCommandResult(0, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR);
+ SendAuctionCommandResult(NULL, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR);
//this code isn't possible ... maybe there should be assert
- TC_LOG_ERROR("network", "CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", player->GetGUIDLow(), auctionId);
+ TC_LOG_ERROR("network", "CHEATER: %u tried to cancel auction (id: %u) of another player or auction is NULL", player->GetGUIDLow(), auctionId);
return;
}
//inform player, that auction is removed
- SendAuctionCommandResult(auction->Id, AUCTION_CANCEL, ERR_AUCTION_OK);
+ SendAuctionCommandResult(auction, AUCTION_CANCEL, ERR_AUCTION_OK);
// Now remove the auction
@@ -618,7 +648,7 @@ void WorldSession::HandleAuctionListBidderItems(WorldPacket& recvData)
WorldPacket data(SMSG_AUCTION_BIDDER_LIST_RESULT, (4+4+4));
Player* player = GetPlayer();
- data << (uint32) 0; //add 0 as count
+ data << uint32(0); //add 0 as count
uint32 count = 0;
uint32 totalcount = 0;
while (outbiddedCount > 0) //add all data, which client requires
@@ -637,7 +667,7 @@ void WorldSession::HandleAuctionListBidderItems(WorldPacket& recvData)
auctionHouse->BuildListBidderItems(data, player, count, totalcount);
data.put<uint32>(0, count); // add count to placeholder
data << totalcount;
- data << (uint32)300; //unk 2.3.0
+ data << uint32(300); //unk 2.3.0
SendPacket(&data);
}
@@ -666,15 +696,15 @@ void WorldSession::HandleAuctionListOwnerItems(WorldPacket& recvData)
AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction());
WorldPacket data(SMSG_AUCTION_OWNER_LIST_RESULT, (4+4+4));
- data << (uint32) 0; // amount place holder
+ data << uint32(0); // amount place holder
uint32 count = 0;
uint32 totalcount = 0;
auctionHouse->BuildListOwnerItems(data, _player, count, totalcount);
data.put<uint32>(0, count);
- data << (uint32) totalcount;
- data << (uint32) 0;
+ data << uint32(totalcount);
+ data << uint32(0);
SendPacket(&data);
}
@@ -697,15 +727,11 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
recvData >> quality >> usable;
recvData.read_skip<uint8>(); // unk
+ recvData.read_skip<uint8>(); // unk
// this block looks like it uses some lame byte packing or similar...
- uint8 unkCnt;
- recvData >> unkCnt;
- for (uint8 i = 0; i < unkCnt; i++)
- {
- recvData.read_skip<uint8>();
+ for (uint8 i = 0; i < 15; i++)
recvData.read_skip<uint8>();
- }
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_AUCTIONEER);
if (!creature)
@@ -720,13 +746,13 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction());
- //TC_LOG_DEBUG("Auctionhouse search (GUID: %u TypeId: %u)",, list from: %u, searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u",
+ //TC_LOG_DEBUG("misc", "Auctionhouse search (GUID: %u TypeId: %u)",, list from: %u, searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u",
// GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid)), listfrom, searchedname.c_str(), levelmin, levelmax, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, usable);
WorldPacket data(SMSG_AUCTION_LIST_RESULT, (4+4+4));
uint32 count = 0;
uint32 totalcount = 0;
- data << (uint32) 0;
+ data << uint32(0);
// converting string that we try to find to lower case
std::wstring wsearchedname;
@@ -741,8 +767,8 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
count, totalcount);
data.put<uint32>(0, count);
- data << (uint32) totalcount;
- data << (uint32) 300; // unk 2.3.0 const?
+ data << uint32(totalcount);
+ data << uint32(300); //unk 2.3.0
SendPacket(&data);
}
@@ -760,7 +786,7 @@ void WorldSession::HandleAuctionListPendingSales(WorldPacket& recvData)
{
data << ""; // string
data << ""; // string
- data << uint32(0);
+ data << uint64(0);
data << uint32(0);
data << float(0);
}*/
diff --git a/src/server/game/Handlers/AuthHandler.cpp b/src/server/game/Handlers/AuthHandler.cpp
index 70b0d541e6c..5fafeea9991 100644
--- a/src/server/game/Handlers/AuthHandler.cpp
+++ b/src/server/game/Handlers/AuthHandler.cpp
@@ -19,20 +19,28 @@
#include "WorldSession.h"
#include "WorldPacket.h"
-void WorldSession::SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos)
+void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos)
{
- WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1 + (shortForm ? 0 : (4 + 1)));
- packet << uint8(code);
+ WorldPacket packet(SMSG_AUTH_RESPONSE, 1 /*bits*/ + 4 + 1 + 4 + 1 + 4 + 1 + 1 + (queued ? 4 : 0));
+ packet.WriteBit(queued);
+ if (queued)
+ packet.WriteBit(0);
+
+ packet.WriteBit(1); // has account info
+
+ packet.FlushBits();
+
+ // account info
packet << uint32(0); // BillingTimeRemaining
- packet << uint8(0); // BillingPlanFlags
+ packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, 3 - CATA; must be set in database manually for each account
+ packet << uint32(0);
+ packet << uint8(Expansion()); // Unknown, these two show the same
packet << uint32(0); // BillingTimeRested
- packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, must be set in database manually for each account
+ packet << uint8(0); // BillingPlanFlags
- if (!shortForm)
- {
+ packet << uint8(code);
+ if (queued)
packet << uint32(queuePos); // Queue position
- packet << uint8(0); // Realm has a free character migration - bool
- }
SendPacket(&packet);
}
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
index 95e4dd3b5e0..faae8ef3ba0 100644
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
@@ -66,23 +66,41 @@ void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket& recvData)
void WorldSession::SendBattleGroundList(uint64 guid, BattlegroundTypeId bgTypeId)
{
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundListPacket(&data, guid, _player, bgTypeId, 0);
+ sBattlegroundMgr->BuildBattlegroundListPacket(&data, guid, _player, bgTypeId);
SendPacket(&data);
}
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{
- uint64 guid;
uint32 bgTypeId_;
uint32 instanceId;
- uint8 joinAsGroup;
+ uint8 asGroup;
bool isPremade = false;
Group* grp = NULL;
-
- recvData >> guid; // battlemaster guid
- recvData >> bgTypeId_; // battleground type id (DBC id)
- recvData >> instanceId; // instance id, 0 if First Available selected
- recvData >> joinAsGroup; // join as group
+ ObjectGuid guid;
+
+ recvData >> instanceId; // Instance Id
+ guid[2] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ asGroup = recvData.ReadBit(); // As Group
+ guid[4] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[5]);
+ recvData.ReadByteSeq(guid[1]);
+
+ //extract from guid
+ bgTypeId_ = GUID_LOPART(guid);
if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
{
@@ -95,10 +113,9 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED);
return;
}
-
BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_);
- TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid)));
+ //TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID:"UI64FMTD" TypeId:%u)", guid, bgTypeId_);
// can do this, since it's battleground, not arena
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, 0);
@@ -123,16 +140,15 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (!bracketEntry)
return;
- GroupJoinBattlegroundResult err;
+ GroupJoinBattlegroundResult err = ERR_BATTLEGROUND_NONE;
// check queue conditions
- if (!joinAsGroup)
+ if (!asGroup)
{
if (GetPlayer()->isUsingLfg())
{
- // player is using dungeon finder or raid finder
WorldPacket data;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_LFG_CANT_USE_BATTLEGROUND);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_LFG_CANT_USE_BATTLEGROUND);
GetPlayer()->GetSession()->SendPacket(&data);
return;
}
@@ -141,7 +157,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (!_player->CanJoinToBattleground(bg))
{
WorldPacket data;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
_player->GetSession()->SendPacket(&data);
return;
}
@@ -150,7 +166,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{
// player is already in random queue
WorldPacket data;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_RANDOM_BG);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_IN_RANDOM_BG);
_player->GetSession()->SendPacket(&data);
return;
}
@@ -159,7 +175,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{
// player is already in queue, can't start random queue
WorldPacket data;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_NON_RANDOM_BG);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_IN_NON_RANDOM_BG);
_player->GetSession()->SendPacket(&data);
return;
}
@@ -173,33 +189,37 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (!_player->HasFreeBattlegroundQueueId())
{
WorldPacket data;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_TOO_MANY_QUEUES);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, ERR_BATTLEGROUND_TOO_MANY_QUEUES);
_player->GetSession()->SendPacket(&data);
return;
}
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
-
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
+
uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
- // already checked if queueSlot is valid, now just get it
uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
- WorldPacket data;
- // send status packet (in queue)
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType, 0);
+ // add joined time data
+ _player->AddBattlegroundQueueJoinTime(bgTypeId, ginfo->JoinTime);
+
+ WorldPacket data; // send status packet (in queue)
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, _player, queueSlot, STATUS_WAIT_QUEUE, avgTime, ginfo->JoinTime, ginfo->ArenaType);
SendPacket(&data);
+
TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",
bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName().c_str());
}
else
{
grp = _player->GetGroup();
- // no group found, error
+
if (!grp)
return;
+
if (grp->GetLeaderGUID() != _player->GetGUID())
return;
+
err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0);
isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam());
@@ -207,7 +227,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
GroupQueueInfo* ginfo = NULL;
uint32 avgTime = 0;
- if (err > 0)
+ if (!err)
{
TC_LOG_DEBUG("bg.battleground", "Battleground: the following players are joining as group:");
ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
@@ -220,11 +240,10 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (!member)
continue; // this should never happen
- WorldPacket data;
-
- if (err <= 0)
+ if (err)
{
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
+ WorldPacket data;
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, err);
member->GetSession()->SendPacket(&data);
continue;
}
@@ -232,65 +251,107 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
// add to queue
uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
- // send status packet (in queue)
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType, 0);
- member->GetSession()->SendPacket(&data);
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
+ // add joined time data
+ member->AddBattlegroundQueueJoinTime(bgTypeId, ginfo->JoinTime);
+
+ WorldPacket data; // send status packet (in queue)
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, member, queueSlot, STATUS_WAIT_QUEUE, avgTime, ginfo->JoinTime, ginfo->ArenaType);
member->GetSession()->SendPacket(&data);
TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",
bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName().c_str());
}
TC_LOG_DEBUG("bg.battleground", "Battleground: group end");
}
+
sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
}
void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket& /*recvData*/)
{
- TC_LOG_DEBUG("network", "WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message");
+ TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_BATTLEGROUND_PLAYER_POSITIONS Message");
Battleground* bg = _player->GetBattleground();
if (!bg) // can't be received if player not in battleground
return;
- uint32 flagCarrierCount = 0;
- Player* allianceFlagCarrier = NULL;
- Player* hordeFlagCarrier = NULL;
+ uint32 acount = 0;
+ uint32 hcount = 0;
+ Player* aplr = NULL;
+ Player* hplr = NULL;
if (uint64 guid = bg->GetFlagPickerGUID(TEAM_ALLIANCE))
{
- allianceFlagCarrier = ObjectAccessor::FindPlayer(guid);
- if (allianceFlagCarrier)
- ++flagCarrierCount;
+ aplr = ObjectAccessor::FindPlayer(guid);
+ if (aplr)
+ ++acount;
}
if (uint64 guid = bg->GetFlagPickerGUID(TEAM_HORDE))
{
- hordeFlagCarrier = ObjectAccessor::FindPlayer(guid);
- if (hordeFlagCarrier)
- ++flagCarrierCount;
+ hplr = ObjectAccessor::FindPlayer(guid);
+ if (hplr)
+ ++hcount;
}
- WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, 4 + 4 + 16 * flagCarrierCount);
- // Used to send several player positions (found used in AV)
- data << 0; // CGBattlefieldInfo__m_numPlayerPositions
- /*
- for (CGBattlefieldInfo__m_numPlayerPositions)
- data << guid << posx << posy;
- */
- data << flagCarrierCount;
- if (allianceFlagCarrier)
+ ObjectGuid aguid = aplr ? aplr->GetGUID() : 0;
+ ObjectGuid hguid = hplr ? hplr->GetGUID() : 0;
+
+ WorldPacket data(SMSG_BATTLEFIELD_PLAYER_POSITIONS);
+
+ data.WriteBits(acount, 22);
+ for (uint8 i = 0; i < acount; i++)
+ {
+ data.WriteBit(aguid[3]);
+ data.WriteBit(aguid[5]);
+ data.WriteBit(aguid[1]);
+ data.WriteBit(aguid[6]);
+ data.WriteBit(aguid[7]);
+ data.WriteBit(aguid[0]);
+ data.WriteBit(aguid[2]);
+ data.WriteBit(aguid[4]);
+ }
+
+ data.WriteBits(hcount, 22);
+ for (uint8 i = 0; i < hcount; i++)
+ {
+ data.WriteBit(hguid[6]);
+ data.WriteBit(hguid[5]);
+ data.WriteBit(hguid[4]);
+ data.WriteBit(hguid[7]);
+ data.WriteBit(hguid[2]);
+ data.WriteBit(hguid[1]);
+ data.WriteBit(hguid[0]);
+ data.WriteBit(hguid[3]);
+ }
+
+ data.FlushBits();
+
+ for (uint8 i = 0; i < hcount; i++)
{
- data << uint64(allianceFlagCarrier->GetGUID());
- data << float(allianceFlagCarrier->GetPositionX());
- data << float(allianceFlagCarrier->GetPositionY());
+ data.WriteByteSeq(hguid[2]);
+ data.WriteByteSeq(hguid[1]);
+ data << float(hplr->GetPositionY());
+ data.WriteByteSeq(hguid[5]);
+ data.WriteByteSeq(hguid[4]);
+ data.WriteByteSeq(hguid[7]);
+ data.WriteByteSeq(hguid[0]);
+ data.WriteByteSeq(hguid[6]);
+ data.WriteByteSeq(hguid[3]);
+ data << float(hplr->GetPositionX());
}
- if (hordeFlagCarrier)
+ for (uint8 i = 0; i < acount; i++)
{
- data << uint64(hordeFlagCarrier->GetGUID());
- data << float(hordeFlagCarrier->GetPositionX());
- data << float(hordeFlagCarrier->GetPositionY());
+ data.WriteByteSeq(aguid[6]);
+ data << float(aplr->GetPositionX());
+ data.WriteByteSeq(aguid[5]);
+ data.WriteByteSeq(aguid[3]);
+ data << float(aplr->GetPositionY());
+ data.WriteByteSeq(aguid[1]);
+ data.WriteByteSeq(aguid[7]);
+ data.WriteByteSeq(aguid[0]);
+ data.WriteByteSeq(aguid[2]);
+ data.WriteByteSeq(aguid[4]);
}
SendPacket(&data);
@@ -298,7 +359,7 @@ void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket& /*recvDa
void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recvData*/)
{
- TC_LOG_DEBUG("network", "WORLD: Recvd MSG_PVP_LOG_DATA Message");
+ TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_PVP_LOG_DATA Message");
Battleground* bg = _player->GetBattleground();
if (!bg)
@@ -312,22 +373,16 @@ void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recvData*/)
bg->BuildPvPLogDataPacket(data);
SendPacket(&data);
- TC_LOG_DEBUG("network", "WORLD: Sent MSG_PVP_LOG_DATA Message");
+ TC_LOG_DEBUG("network", "WORLD: Sent SMSG_PVP_LOG_DATA Message");
}
-void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recvData)
+void WorldSession::HandleBattlefieldListOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_BATTLEFIELD_LIST Message");
uint32 bgTypeId;
recvData >> bgTypeId; // id from DBC
- uint8 fromWhere;
- recvData >> fromWhere; // 0 - battlemaster (lua: ShowBattlefieldList), 1 - UI (lua: RequestBattlegroundInstanceInfo)
-
- uint8 canGainXP;
- recvData >> canGainXP; // players with locked xp have their own bg queue on retail
-
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
if (!bl)
{
@@ -336,60 +391,87 @@ void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recvData)
}
WorldPacket data;
- sBattlegroundMgr->BuildBattlegroundListPacket(&data, 0, _player, BattlegroundTypeId(bgTypeId), fromWhere);
+ sBattlegroundMgr->BuildBattlegroundListPacket(&data, 0, _player, BattlegroundTypeId(bgTypeId));
SendPacket(&data);
}
void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
{
- uint8 type; // arenatype if arena
- uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1
- uint32 bgTypeId_; // type id from dbc
- uint16 unk; // 0x1F90 constant?
- uint8 action; // enter battle 0x1, leave queue 0x0
+ TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
+
+ uint32 time;
+ uint32 queueSlot;
+ uint32 unk;
+ uint8 action; // enter battle 0x1, leave queue 0x0
+ ObjectGuid guid;
+
+ recvData >> time;
+ recvData >> queueSlot;
+ recvData >> unk;
+
+ guid[0] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[2] = recvData.ReadBit();
+
+ action = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[5]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[4]);
- recvData >> type >> unk2 >> bgTypeId_ >> unk >> action;
- if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
+ if (!_player->InBattlegroundQueue())
{
- TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Invalid BgType!",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+ TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Player not in queue!",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action);
return;
}
- if (!_player->InBattlegroundQueue())
+ BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(queueSlot);
+ if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE)
{
- TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player not in queue!",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+ TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Invalid queueSlot!",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action);
return;
}
- //get GroupQueueInfo from BattlegroundQueue
- BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_);
- BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, type);
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
+
//we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattlegroundQueue::RemovePlayer() function
GroupQueueInfo ginfo;
if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
{
- TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player not in queue (No player Group Info)!",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+ TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Player not in queue (No player Group Info)!",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action);
return;
}
// if action == 1, then instanceId is required
if (!ginfo.IsInvitedToBGInstanceGUID && action == 1)
{
- TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player is not invited to any bg!",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+ TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Player is not invited to any bg!",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action);
return;
}
- Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
+ BattlegroundTypeId bgTypeId = BattlegroundMgr::BGTemplateId(bgQueueTypeId);
+ // BGTemplateId returns BATTLEGROUND_AA when it is arena queue.
+ // Do instance id search as there is no AA bg instances.
+ Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId == BATTLEGROUND_AA ? BATTLEGROUND_TYPE_NONE : bgTypeId);
if (!bg)
{
if (action)
{
- TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Cant find BG with id %u!",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action, ginfo.IsInvitedToBGInstanceGUID);
+ TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Cant find BG with id %u!",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action, ginfo.IsInvitedToBGInstanceGUID);
return;
}
@@ -401,8 +483,11 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
}
}
- TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u.",
- GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+ TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u.",
+ GetPlayerInfo().c_str(), queueSlot, unk, time, action);
+
+ // get real bg type
+ bgTypeId = bg->GetTypeID();
// expected bracket entry
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel());
@@ -417,7 +502,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
{
//send bg command result to show nice message
WorldPacket data2;
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data2, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
+ sBattlegroundMgr->BuildStatusFailedPacket(&data2, bg, _player, 0, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
_player->GetSession()->SendPacket(&data2);
action = 0;
TC_LOG_DEBUG("bg.battleground", "Player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName().c_str(), _player->GetGUIDLow());
@@ -425,12 +510,12 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
//if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
if (_player->getLevel() > bg->GetMaxLevel())
{
- TC_LOG_ERROR("network", "Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
+ TC_LOG_DEBUG("network", "Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
_player->GetName().c_str(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID());
action = 0;
}
}
- uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
+
WorldPacket data;
if (action)
{
@@ -453,7 +538,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
_player->CleanupAfterTaxiFlight();
}
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), ginfo.Team);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, _player, queueSlot, STATUS_IN_PROGRESS, _player->GetBattlegroundQueueJoinTime(bgTypeId), bg->GetElapsedTime(), bg->GetArenaType());
_player->GetSession()->SendPacket(&data);
// remove battleground queue status from BGmgr
@@ -476,9 +561,6 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
}
else // leave queue
{
- if (bg->isArena() && bg->GetStatus() > STATUS_WAIT_QUEUE)
- return;
-
// if player leaves rated arena match before match start, it is counted as he played but he lost
if (ginfo.IsRated && ginfo.IsInvitedToBGInstanceGUID)
{
@@ -490,25 +572,22 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
at->SaveToDB();
}
}
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, _player, queueSlot, STATUS_NONE, _player->GetBattlegroundQueueJoinTime(bgTypeId), 0, 0);
+ SendPacket(&data);
+
_player->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, 0);
bgQueue.RemovePlayer(_player->GetGUID(), true);
// player left queue, we should update it - do not update Arena Queue
if (!ginfo.ArenaType)
sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
- SendPacket(&data);
+
TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId);
}
}
-void WorldSession::HandleBattlefieldLeaveOpcode(WorldPacket& recvData)
+void WorldSession::HandleBattlefieldLeaveOpcode(WorldPacket& /*recvData*/)
{
- TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message");
-
- recvData.read_skip<uint8>(); // unk1
- recvData.read_skip<uint8>(); // unk2
- recvData.read_skip<uint32>(); // BattlegroundTypeId
- recvData.read_skip<uint16>(); // unk3
+ TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_BATTLEFIELD_LEAVE Message");
// not allow leave battleground in combat
if (_player->IsInCombat())
@@ -522,7 +601,7 @@ void WorldSession::HandleBattlefieldLeaveOpcode(WorldPacket& recvData)
void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/)
{
// empty opcode
- TC_LOG_DEBUG("network", "WORLD: Battleground status");
+ TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_BATTLEFIELD_STATUS Message");
WorldPacket data;
// we must update all queues here
@@ -541,13 +620,14 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/)
//so i must use bg pointer to get that information
if (bg && bg->GetArenaType() == arenaType)
{
- // this line is checked, i only don't know if GetStartTime is changing itself after bg end!
+ // this line is checked, i only don't know if GetElapsedTime() is changing itself after bg end!
// send status in Battleground
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType, _player->GetBGTeam());
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, GetPlayer(), i, STATUS_IN_PROGRESS, _player->GetBattlegroundQueueJoinTime(bgTypeId), bg->GetElapsedTime(), arenaType);
SendPacket(&data);
continue;
}
}
+
//we are sending update to player about queue - he can be invited there!
//get GroupQueueInfo for queue status
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
@@ -559,9 +639,9 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/)
bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
if (!bg)
continue;
- uint32 remainingTime = getMSTimeDiff(getMSTime(), ginfo.RemoveInviteTime);
+
// send status invited to Battleground
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0, arenaType, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, GetPlayer(), i, STATUS_WAIT_JOIN, getMSTimeDiff(getMSTime(), ginfo.RemoveInviteTime), _player->GetBattlegroundQueueJoinTime(bgTypeId), arenaType);
SendPacket(&data);
}
else
@@ -577,7 +657,7 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/)
uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, bracketEntry->GetBracketId());
// send status in Battleground Queue
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(ginfo.JoinTime, getMSTime()), arenaType, 0);
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, GetPlayer(), i, STATUS_WAIT_QUEUE, avgTime, _player->GetBattlegroundQueueJoinTime(bgTypeId), arenaType);
SendPacket(&data);
}
}
@@ -587,44 +667,18 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
- uint64 guid; // arena Battlemaster guid
uint8 arenaslot; // 2v2, 3v3 or 5v5
- uint8 asGroup; // asGroup
- uint8 isRated; // isRated
- Group* grp = NULL;
- recvData >> guid >> arenaslot >> asGroup >> isRated;
+ recvData >> arenaslot;
// ignore if we already in BG or BG queue
if (_player->InBattleground())
return;
- Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
- if (!unit)
- return;
-
- if (!unit->IsBattleMaster()) // it's not battle master
- return;
-
- uint8 arenatype = 0;
uint32 arenaRating = 0;
uint32 matchmakerRating = 0;
- switch (arenaslot)
- {
- case 0:
- arenatype = ARENA_TYPE_2v2;
- break;
- case 1:
- arenatype = ARENA_TYPE_3v3;
- break;
- case 2:
- arenatype = ARENA_TYPE_5v5;
- break;
- default:
- TC_LOG_ERROR("network", "Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot);
- return;
- }
+ uint8 arenatype = ArenaTeam::GetTypeBySlot(arenaslot);
//check existance
Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA);
@@ -646,108 +700,73 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
if (!bracketEntry)
return;
- GroupJoinBattlegroundResult err = ERR_GROUP_JOIN_BATTLEGROUND_FAIL;
+ GroupJoinBattlegroundResult err = ERR_BATTLEGROUND_NONE;
- if (!asGroup)
- {
- // check if already in queue
- if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
- //player is already in this queue
- return;
- // check if has free queue slots
- if (!_player->HasFreeBattlegroundQueueId())
- return;
- }
- else
+ Group* grp = _player->GetGroup();
+ // no group found, error
+ if (!grp)
+ return;
+ if (grp->GetLeaderGUID() != _player->GetGUID())
+ return;
+
+ uint32 ateamId = _player->GetArenaTeamId(arenaslot);
+ // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
+ ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId);
+ if (!at)
{
- grp = _player->GetGroup();
- // no group found, error
- if (!grp)
- return;
- if (grp->GetLeaderGUID() != _player->GetGUID())
- return;
- err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, arenatype, arenatype, isRated != 0, arenaslot);
+ _player->GetSession()->SendNotInArenaTeamPacket(arenatype);
+ return;
}
- uint32 ateamId = 0;
+ // get the team rating for queueing
+ arenaRating = at->GetRating();
+ matchmakerRating = at->GetAverageMMR(grp);
+ // the arenateam id must match for everyone in the group
+
+ if (arenaRating <= 0)
+ arenaRating = 1;
+
+ BattlegroundQueue &bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
- if (isRated)
+ uint32 avgTime = 0;
+ GroupQueueInfo* ginfo = NULL;
+
+ err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, arenatype, arenatype, true, arenaslot);
+ if (!err)
{
- ateamId = _player->GetArenaTeamId(arenaslot);
- // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
- ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId);
- if (!at)
- {
- _player->GetSession()->SendNotInArenaTeamPacket(arenatype);
- return;
- }
- // get the team rating for queueing
- arenaRating = at->GetRating();
- matchmakerRating = at->GetAverageMMR(grp);
- // the arenateam id must match for everyone in the group
+ TC_LOG_DEBUG("bg.battleground", "Battleground: arena team id %u, leader %s queued with matchmaker rating %u for type %u", _player->GetArenaTeamId(arenaslot), _player->GetName().c_str(), matchmakerRating, arenatype);
- if (arenaRating <= 0)
- arenaRating = 1;
+ ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, true, false, arenaRating, matchmakerRating, ateamId);
+ avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
}
- BattlegroundQueue &bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
- if (asGroup)
+ for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
- uint32 avgTime = 0;
+ Player* member = itr->GetSource();
+ if (!member)
+ continue;
- if (err > 0)
+ if (err)
{
- TC_LOG_DEBUG("bg.battleground", "Battleground: arena join as group start");
- if (isRated)
- {
- TC_LOG_DEBUG("bg.battleground", "Battleground: arena team id %u, leader %s queued with matchmaker rating %u for type %u", _player->GetArenaTeamId(arenaslot), _player->GetName().c_str(), matchmakerRating, arenatype);
- bg->SetRated(true);
- }
- else
- bg->SetRated(false);
-
- GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated != 0, false, arenaRating, matchmakerRating, ateamId);
- avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
+ WorldPacket data;
+ sBattlegroundMgr->BuildStatusFailedPacket(&data, bg, _player, 0, err);
+ member->GetSession()->SendPacket(&data);
+ continue;
}
- for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
- {
- Player* member = itr->GetSource();
- if (!member)
- continue;
-
- WorldPacket data;
+ // add to queue
+ uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
- if (err <= 0)
- {
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
- member->GetSession()->SendPacket(&data);
- continue;
- }
+ // add joined time data
+ member->AddBattlegroundQueueJoinTime(bgTypeId, ginfo->JoinTime);
- // add to queue
- uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
+ WorldPacket data; // send status packet (in queue)
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, member, queueSlot, STATUS_WAIT_QUEUE, avgTime, ginfo->JoinTime, arenatype);
+ member->GetSession()->SendPacket(&data);
- // send status packet (in queue)
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype, 0);
- member->GetSession()->SendPacket(&data);
- sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
- member->GetSession()->SendPacket(&data);
- TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName().c_str());
- }
+ TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName().c_str());
}
- else
- {
- GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, arenatype, isRated != 0, false, arenaRating, matchmakerRating, ateamId);
- uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
- uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
- WorldPacket data;
- // send status packet (in queue)
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype, 0);
- SendPacket(&data);
- TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName().c_str());
- }
sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
}
@@ -767,3 +786,78 @@ void WorldSession::HandleReportPvPAFK(WorldPacket& recvData)
reportedPlayer->ReportedAfkBy(_player);
}
+
+void WorldSession::HandleRequestRatedBgInfo(WorldPacket & recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_REQUEST_RATED_BG_INFO");
+
+ uint8 unk;
+ recvData >> unk;
+
+ TC_LOG_DEBUG("bg.battleground", "WorldSession::HandleRequestRatedBgInfo: unk = %u", unk);
+
+ /// @Todo: perfome research in this case
+ /// The unk fields are related to arenas
+ WorldPacket data(SMSG_RATED_BG_STATS, 72);
+ data << uint32(0); // BgWeeklyWins20vs20
+ data << uint32(0); // BgWeeklyPlayed20vs20
+ data << uint32(0); // BgWeeklyPlayed15vs15
+ data << uint32(0);
+ data << uint32(0); // BgWeeklyWins10vs10
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0); // BgWeeklyWins15vs15
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0); // BgWeeklyPlayed10vs10
+ data << uint32(0);
+ data << uint32(0);
+
+ SendPacket(&data);
+}
+
+void WorldSession::HandleRequestPvpOptions(WorldPacket& /*recvData*/)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_REQUEST_PVP_OPTIONS_ENABLED");
+
+ /// @Todo: perfome research in this case
+ WorldPacket data(SMSG_PVP_OPTIONS_ENABLED, 1);
+ data.WriteBit(1);
+ data.WriteBit(1); // WargamesEnabled
+ data.WriteBit(1);
+ data.WriteBit(1); // RatedBGsEnabled
+ data.WriteBit(1); // RatedArenasEnabled
+
+ data.FlushBits();
+
+ SendPacket(&data);
+}
+
+void WorldSession::HandleRequestPvpReward(WorldPacket& /*recvData*/)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_REQUEST_PVP_REWARDS");
+
+ _player->SendPvpRewards();
+}
+
+void WorldSession::HandleRequestRatedBgStats(WorldPacket& /*recvData*/)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_REQUEST_RATED_BG_STATS");
+
+ WorldPacket data(SMSG_BATTLEFIELD_RATED_INFO, 29);
+ data << uint32(0); // Reward
+ data << uint8(3); // unk
+ data << uint32(0); // unk
+ data << uint32(0); // unk
+ data << _player->GetCurrencyWeekCap(CURRENCY_TYPE_CONQUEST_META_RBG, true);
+ data << uint32(0); // unk
+ data << uint32(0); // unk
+ data << _player->GetCurrency(CURRENCY_TYPE_CONQUEST_POINTS, true);
+
+ SendPacket(&data);
+}
diff --git a/src/server/game/Handlers/BattlefieldHandler.cpp b/src/server/game/Handlers/BattlefieldHandler.cpp
index b0580681f91..632cf83cd8f 100644
--- a/src/server/game/Handlers/BattlefieldHandler.cpp
+++ b/src/server/game/Handlers/BattlefieldHandler.cpp
@@ -21,96 +21,223 @@
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
+#include "Object.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
/**
- * @fn void WorldSession::SendBfInvitePlayerToWar(uint32 battleId, uint32 zoneId, uint32 acceptTime)
+ * @fn void WorldSession::SendBfInvitePlayerToWar(uint64 guid, uint32 zoneId, uint32 acceptTime)
*
* @brief This send to player windows for invite player to join the war.
*
- * @param battleId The BattleId of Bf
+ * @param guid The guid of Bf
* @param zoneId The zone where the battle is (4197 for wg)
* @param acceptTime Time in second that the player have for accept
*/
-void WorldSession::SendBfInvitePlayerToWar(uint32 battleId, uint32 zoneId, uint32 acceptTime)
+void WorldSession::SendBfInvitePlayerToWar(uint64 guid, uint32 zoneId, uint32 acceptTime)
{
- WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, 12);
- data << uint32(battleId);
- data << uint32(zoneId);
- data << uint32(time(NULL) + acceptTime);
+ ObjectGuid guidBytes = guid;
+
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, 16);
+
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(guidBytes[7]);
+ data.WriteBit(guidBytes[2]);
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(guidBytes[4]);
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[0]);
+
+ data.WriteByteSeq(guidBytes[6]);
+ data << uint32(zoneId); // Zone Id
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[3]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[0]);
+ data << uint32(time(NULL) + acceptTime); // Invite lasts until
+ data.WriteByteSeq(guidBytes[7]);
+ data.WriteByteSeq(guidBytes[5]);
SendPacket(&data);
}
/**
- * @fn void WorldSession::SendBfInvitePlayerToQueue(uint32 battleId)
+ * @fn void WorldSession::SendBfInvitePlayerToQueue(uint64 guid)
*
* @brief This send invitation to player to join the queue.
*
- * @param battleId The BattleId of Bf
+ * @param guid The guid of Bf
*/
-void WorldSession::SendBfInvitePlayerToQueue(uint32 battleId)
+void WorldSession::SendBfInvitePlayerToQueue(uint64 guid)
{
+ ObjectGuid guidBytes = guid;
+
WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_INVITE, 5);
- data << uint32(battleId);
- data << uint8(1); // warmup ? used ?
+
+ data.WriteBit(1); // unk
+ data.WriteBit(0); // Has Warmup
+ data.WriteBit(1); // unk
+ data.WriteBit(guidBytes[0]);
+ data.WriteBit(1); // unk
+ data.WriteBit(guidBytes[2]);
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(1); // unk
+ data.WriteBit(0); // unk
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[4]);
+ data.WriteBit(1); // unk
+ data.WriteBit(guidBytes[7]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[3]);
+ data.WriteByteSeq(guidBytes[6]);
+ data << uint8(1); // Warmup
+ data.WriteByteSeq(guidBytes[5]);
+ data.WriteByteSeq(guidBytes[0]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[7]);
SendPacket(&data);
}
/**
- * @fn void WorldSession::SendBfQueueInviteResponse(uint32 battleId, uint32 zoneId, bool canQueue, bool full)
+ * @fn void WorldSession::SendBfQueueInviteResponse(uint64 guid, uint32 zoneId, bool canQueue, bool full)
*
* @brief This send packet for inform player that he join queue.
*
- * @param battleId The BattleId of Bf
+ * @param guid The guid of Bf
* @param zoneId The zone where the battle is (4197 for wg)
* @param canQueue if able to queue
* @param full on log in is full
*/
-void WorldSession::SendBfQueueInviteResponse(uint32 battleId, uint32 zoneId, bool canQueue, bool full)
+void WorldSession::SendBfQueueInviteResponse(uint64 guid, uint32 zoneId, bool canQueue, bool full)
{
- WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, 11);
- data << uint32(battleId);
+ const bool hasSecondGuid = false;
+ const bool warmup = true;
+ ObjectGuid guidBytes = guid;
+
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, 16);
+
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[7]);
+ data.WriteBit(full); // Logging In, VERIFYME
+ data.WriteBit(guidBytes[0]);
+ data.WriteBit(!hasSecondGuid);
+ data.WriteBit(guidBytes[4]);
+
+ // if (hasSecondGuid) 7 3 0 4 2 6 1 5
+
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(guidBytes[2]);
+
+ // if (hasSecondGuid) 2 5 3 0 4 6 1 7
+
+ data.FlushBits();
+
+ data << uint8(canQueue); // Accepted
+
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[3]);
+ data.WriteByteSeq(guidBytes[6]);
+ data.WriteByteSeq(guidBytes[7]);
+ data.WriteByteSeq(guidBytes[0]);
+
+ data << uint8(warmup);
+
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[5]);
+
data << uint32(zoneId);
- data << uint8(canQueue ? 1 : 0); // Accepted // 0 you cannot queue wg // 1 you are queued
- data << uint8(full ? 0 : 1); // Logging In // 0 wg full // 1 queue for upcoming
- data << uint8(1); // Warmup
+
SendPacket(&data);
}
/**
- * @fn void WorldSession::SendBfEntered(uint32 battleId)
+ * @fn void WorldSession::SendBfEntered(uint64 guid)
*
* @brief This is call when player accept to join war.
*
- * @param battleId The BattleId of Bf
+ * @param guid The guid of Bf
*/
-void WorldSession::SendBfEntered(uint32 battleId)
+void WorldSession::SendBfEntered(uint64 guid)
{
- WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTERED, 7);
- data << uint32(battleId);
- data << uint8(1); // unk
- data << uint8(1); // unk
- data << uint8(_player->isAFK() ? 1 : 0); // Clear AFK
+ uint8 isAFK = _player->isAFK() ? 1 : 0;
+ ObjectGuid guidBytes = guid;
+
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTERED, 11);
+
+ data.WriteBit(0); // unk
+ data.WriteBit(isAFK); // Clear AFK
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[4]);
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[0]);
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(0); // unk
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(guidBytes[7]);
+ data.WriteBit(guidBytes[2]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(guidBytes[5]);
+ data.WriteByteSeq(guidBytes[3]);
+ data.WriteByteSeq(guidBytes[0]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[7]);
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[6]);
+
SendPacket(&data);
}
/**
- * @fn void WorldSession::SendBfLeaveMessage(uint32 battleId, BFLeaveReason reason)
+ * @fn void WorldSession::SendBfLeaveMessage(uint64 guid, BFLeaveReason reason)
*
* @brief This is call when player leave battlefield zone.
*
- * @param battleId The BattleId of Bf
+ * @param guid The guid of Bf
* @param reason Reason why player left battlefield
*/
-void WorldSession::SendBfLeaveMessage(uint32 battleId, BFLeaveReason reason /*= BF_LEAVE_REASON_EXITED*/)
+void WorldSession::SendBfLeaveMessage(uint64 guid, BFLeaveReason reason /*= BF_LEAVE_REASON_EXITED*/)
{
- WorldPacket data(SMSG_BATTLEFIELD_MGR_EJECTED, 7);
- data << uint32(battleId);
- data << uint8(reason); // byte Reason
- data << uint8(2); // byte BattleStatus
- data << uint8(0); // bool Relocated
+ ObjectGuid guidBytes = guid;
+
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_EJECTED, 11);
+
+ data.WriteBit(guidBytes[2]);
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[0]);
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(0); // Relocated
+ data.WriteBit(guidBytes[7]);
+ data.WriteBit(guidBytes[4]);
+
+ data.FlushBits();
+
+ data << uint8(2); // BattleStatus
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[7]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[3]);
+ data << uint8(reason); // Reason
+ data.WriteByteSeq(guidBytes[6]);
+ data.WriteByteSeq(guidBytes[0]);
+ data.WriteByteSeq(guidBytes[5]);
+
SendPacket(&data);
}
@@ -121,14 +248,31 @@ void WorldSession::SendBfLeaveMessage(uint32 battleId, BFLeaveReason reason /*=
*/
void WorldSession::HandleBfQueueInviteResponse(WorldPacket& recvData)
{
- uint32 battleId;
uint8 accepted;
+ ObjectGuid guid;
+
+ guid[2] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ accepted = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
- recvData >> battleId >> accepted;
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[5]);
- TC_LOG_DEBUG("misc", "HandleBfQueueInviteResponse: BattleID:%u Accepted:%u", battleId, accepted);
+ TC_LOG_ERROR("misc", "HandleQueueInviteResponse: GUID: " UI64FMTD ", accepted: %u", uint64(guid), accepted);
- Battlefield* bf = sBattlefieldMgr->GetBattlefieldByBattleId(battleId);
+ Battlefield* bf = sBattlefieldMgr->GetBattlefieldByGUID(guid);
if (!bf)
return;
@@ -143,14 +287,31 @@ void WorldSession::HandleBfQueueInviteResponse(WorldPacket& recvData)
*/
void WorldSession::HandleBfEntryInviteResponse(WorldPacket& recvData)
{
- uint32 battleId;
uint8 accepted;
+ ObjectGuid guid;
- recvData >> battleId >> accepted;
+ guid[6] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ accepted = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[2] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
- TC_LOG_DEBUG("misc", "HandleBfEntryInviteResponse: battleId: %u, accepted: %u", battleId, accepted);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[5]);
- Battlefield* bf = sBattlefieldMgr->GetBattlefieldByBattleId(battleId);
+ TC_LOG_ERROR("misc", "HandleBattlefieldInviteResponse: GUID: " UI64FMTD ", accepted: %u", uint64(guid), accepted);
+
+ Battlefield* bf = sBattlefieldMgr->GetBattlefieldByGUID(guid);
if (!bf)
return;
@@ -173,13 +334,29 @@ void WorldSession::HandleBfEntryInviteResponse(WorldPacket& recvData)
*/
void WorldSession::HandleBfExitRequest(WorldPacket& recvData)
{
- uint32 battleId;
+ ObjectGuid guid;
+
+ guid[2] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
- recvData >> battleId;
+ recvData.ReadByteSeq(guid[5]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[6]);
- TC_LOG_DEBUG("misc", "HandleBfExitRequest: battleId: %u ", battleId);
+ TC_LOG_ERROR("misc", "HandleBfExitRequest: GUID: " UI64FMTD, uint64(guid));
- Battlefield* bf = sBattlefieldMgr->GetBattlefieldByBattleId(battleId);
+ Battlefield* bf = sBattlefieldMgr->GetBattlefieldByGUID(guid);
if (!bf)
return;
diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp
index dd654fb3ad0..a7de4491a85 100644
--- a/src/server/game/Handlers/CalendarHandler.cpp
+++ b/src/server/game/Handlers/CalendarHandler.cpp
@@ -90,6 +90,10 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/)
data.AppendPackedTime(calendarEvent->GetEventTime());
data << uint32(calendarEvent->GetFlags());
data << int32(calendarEvent->GetDungeonId());
+
+ Guild* guild = sGuildMgr->GetGuildById(calendarEvent->GetGuildId());
+ data << uint64(guild ? guild->GetGUID() : 0);
+
data.appendPackGUID(calendarEvent->GetCreatorGUID());
}
@@ -671,10 +675,11 @@ void WorldSession::HandleCalendarComplain(WorldPacket& recvData)
uint64 guid = _player->GetGUID();
uint64 eventId;
uint64 complainGUID;
+ uint64 inviteId;
- recvData >> eventId >> complainGUID;
+ recvData >> complainGUID >> eventId >> inviteId;
TC_LOG_DEBUG("network", "CMSG_CALENDAR_COMPLAIN [" UI64FMTD "] EventId ["
- UI64FMTD "] guid [" UI64FMTD "]", guid, eventId, complainGUID);
+ UI64FMTD "] guid [" UI64FMTD "] InviteId [" UI64FMTD "]", guid, eventId, complainGUID, inviteId);
// what to do with complains?
}
diff --git a/src/server/game/Handlers/ChannelHandler.cpp b/src/server/game/Handlers/ChannelHandler.cpp
index c95eadc7d90..0ab5a8ab811 100644
--- a/src/server/game/Handlers/ChannelHandler.cpp
+++ b/src/server/game/Handlers/ChannelHandler.cpp
@@ -19,14 +19,21 @@
#include "ObjectMgr.h" // for normalizePlayerName
#include "ChannelMgr.h"
#include "Player.h"
+#include "WorldSession.h"
void WorldSession::HandleJoinChannel(WorldPacket& recvPacket)
{
uint32 channelId;
- uint8 unknown1, unknown2;
+ uint32 channelLength, passLength;
std::string channelName, password;
- recvPacket >> channelId >> unknown1 >> unknown2 >> channelName >> password;
+ recvPacket >> channelId;
+ uint8 unknown1 = recvPacket.ReadBit(); // unknowns
+ uint8 unknown2 = recvPacket.ReadBit();
+ channelLength = recvPacket.ReadBits(8);
+ passLength = recvPacket.ReadBits(8);
+ channelName = recvPacket.ReadString(channelLength);
+ password = recvPacket.ReadString(passLength);
TC_LOG_DEBUG("chat.system", "CMSG_JOIN_CHANNEL %s Channel: %u, unk1: %u, unk2: %u, channel: %s, password: %s",
GetPlayerInfo().c_str(), channelId, unknown1, unknown2, channelName.c_str(), password.c_str());
@@ -57,7 +64,9 @@ void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket)
{
uint32 unk;
std::string channelName;
- recvPacket >> unk >> channelName;
+ recvPacket >> unk; // channel id?
+ uint32 length = recvPacket.ReadBits(8);
+ channelName = recvPacket.ReadString(length);
TC_LOG_DEBUG("chat.system", "CMSG_LEAVE_CHANNEL %s Channel: %s, unk1: %u",
GetPlayerInfo().c_str(), channelName.c_str(), unk);
@@ -75,8 +84,8 @@ void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket)
void WorldSession::HandleChannelList(WorldPacket& recvPacket)
{
- std::string channelName;
- recvPacket >> channelName;
+ uint32 length = recvPacket.ReadBits(8);
+ std::string channelName = recvPacket.ReadString(length);
TC_LOG_DEBUG("chat.system", "%s %s Channel: %s",
recvPacket.GetOpcode() == CMSG_CHANNEL_DISPLAY_LIST ? "CMSG_CHANNEL_DISPLAY_LIST" : "CMSG_CHANNEL_LIST",
@@ -89,8 +98,11 @@ void WorldSession::HandleChannelList(WorldPacket& recvPacket)
void WorldSession::HandleChannelPassword(WorldPacket& recvPacket)
{
- std::string channelName, password;
- recvPacket >> channelName >> password;
+ uint32 nameLength = recvPacket.ReadBits(8);
+ uint32 passLength = recvPacket.ReadBits(7);
+
+ std::string channelName = recvPacket.ReadString(nameLength);
+ std::string password = recvPacket.ReadString(passLength);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_PASSWORD %s Channel: %s, Password: %s",
GetPlayerInfo().c_str(), channelName.c_str(), password.c_str());
@@ -102,8 +114,11 @@ void WorldSession::HandleChannelPassword(WorldPacket& recvPacket)
void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 channelLength = recvPacket.ReadBits(8);
+ uint32 nameLength = recvPacket.ReadBits(7);
+
+ std::string targetName = recvPacket.ReadString(nameLength);
+ std::string channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_SET_OWNER %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -118,8 +133,8 @@ void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket)
void WorldSession::HandleChannelOwner(WorldPacket& recvPacket)
{
- std::string channelName;
- recvPacket >> channelName;
+ uint32 length = recvPacket.ReadBits(8);
+ std::string channelName = recvPacket.ReadString(length);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_OWNER %s Channel: %s",
GetPlayerInfo().c_str(), channelName.c_str());
@@ -131,8 +146,11 @@ void WorldSession::HandleChannelOwner(WorldPacket& recvPacket)
void WorldSession::HandleChannelModerator(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 channelLength = recvPacket.ReadBits(8);
+ uint32 nameLength = recvPacket.ReadBits(7);
+
+ std::string targetName = recvPacket.ReadString(nameLength);
+ std::string channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_MODERATOR %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -147,8 +165,11 @@ void WorldSession::HandleChannelModerator(WorldPacket& recvPacket)
void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 nameLength = recvPacket.ReadBits(7);
+ uint32 channelLength = recvPacket.ReadBits(8);
+
+ std::string channelName = recvPacket.ReadString(channelLength);
+ std::string targetName = recvPacket.ReadString(nameLength);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_UNMODERATOR %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -163,8 +184,11 @@ void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket)
void WorldSession::HandleChannelMute(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 channelLength = recvPacket.ReadBits(8);
+ uint32 nameLength = recvPacket.ReadBits(7);
+
+ std::string channelName = recvPacket.ReadString(channelLength);
+ std::string targetName = recvPacket.ReadString(nameLength);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_MUTE %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -179,8 +203,11 @@ void WorldSession::HandleChannelMute(WorldPacket& recvPacket)
void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 nameLength = recvPacket.ReadBits(8);
+ uint32 channelLength = recvPacket.ReadBits(7);
+
+ std::string targetName = recvPacket.ReadString(nameLength);
+ std::string channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_UNMUTE %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -195,8 +222,11 @@ void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket)
void WorldSession::HandleChannelInvite(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 nameLength = recvPacket.ReadBits(7);
+ uint32 channelLength = recvPacket.ReadBits(8);
+
+ std::string targetName = recvPacket.ReadString(nameLength);
+ std::string channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_INVITE %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -211,8 +241,11 @@ void WorldSession::HandleChannelInvite(WorldPacket& recvPacket)
void WorldSession::HandleChannelKick(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 channelLength = recvPacket.ReadBits(8);
+ uint32 nameLength = recvPacket.ReadBits(7);
+
+ std::string channelName = recvPacket.ReadString(channelLength);
+ std::string targetName = recvPacket.ReadString(nameLength);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_KICK %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -227,8 +260,14 @@ void WorldSession::HandleChannelKick(WorldPacket& recvPacket)
void WorldSession::HandleChannelBan(WorldPacket& recvPacket)
{
+ uint32 channelLength, nameLength;
std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+
+ channelLength = recvPacket.ReadBits(8);
+ nameLength = recvPacket.ReadBits(7);
+
+ targetName = recvPacket.ReadString(nameLength);
+ channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_BAN %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -243,8 +282,11 @@ void WorldSession::HandleChannelBan(WorldPacket& recvPacket)
void WorldSession::HandleChannelUnban(WorldPacket& recvPacket)
{
- std::string channelName, targetName;
- recvPacket >> channelName >> targetName;
+ uint32 channelLength = recvPacket.ReadBits(7);
+ uint32 nameLength = recvPacket.ReadBits(8);
+
+ std::string targetName = recvPacket.ReadString(nameLength);
+ std::string channelName = recvPacket.ReadString(channelLength);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_UNBAN %s Channel: %s, Target: %s",
GetPlayerInfo().c_str(), channelName.c_str(), targetName.c_str());
@@ -259,8 +301,8 @@ void WorldSession::HandleChannelUnban(WorldPacket& recvPacket)
void WorldSession::HandleChannelAnnouncements(WorldPacket& recvPacket)
{
- std::string channelName;
- recvPacket >> channelName;
+ uint32 length = recvPacket.ReadBits(8);
+ std::string channelName = recvPacket.ReadString(length);
TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_ANNOUNCEMENTS %s Channel: %s",
GetPlayerInfo().c_str(), channelName.c_str());
@@ -300,7 +342,7 @@ void WorldSession::HandleGetChannelMemberCount(WorldPacket &recvPacket)
}
}
-void WorldSession::HandleSetChannelWatch(WorldPacket &recvPacket)
+void WorldSession::HandleSetChannelWatch(WorldPacket& recvPacket)
{
std::string channelName;
recvPacket >> channelName;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 4d52eab61d6..422e5ce206b 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -26,6 +26,7 @@
#include "DatabaseEnv.h"
#include "Group.h"
#include "Guild.h"
+#include "GuildFinderMgr.h"
#include "GuildMgr.h"
#include "Language.h"
#include "LFGMgr.h"
@@ -47,7 +48,6 @@
#include "WorldPacket.h"
#include "WorldSession.h"
-
class LoginQueryHolder : public SQLQueryHolder
{
private:
@@ -116,6 +116,10 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_INVENTORY, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_VOID_STORAGE);
+ stmt->setUInt32(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE, stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS);
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_ACTIONS, stmt);
@@ -168,6 +172,10 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUF_PROFILES);
+ stmt->setUInt32(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES, stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_BGDATA);
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_BG_DATA, stmt);
@@ -204,39 +212,56 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt32(0, m_accountId);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PLAYER_CURRENCY);
+ stmt->setUInt32(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CURRENCY, stmt);
+
return res;
}
void WorldSession::HandleCharEnum(PreparedQueryResult result)
{
- WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
+ uint32 charCount = 0;
+ ByteBuffer bitBuffer;
+ ByteBuffer dataBuffer;
- uint8 num = 0;
-
- data << num;
-
- _legitCharacters.clear();
+ bitBuffer.WriteBits(0, 23);
+ bitBuffer.WriteBit(1);
if (result)
{
+ _legitCharacters.clear();
+
+ charCount = uint32(result->GetRowCount());
+ bitBuffer.reserve(24 * charCount / 8);
+ dataBuffer.reserve(charCount * 381);
+
+ bitBuffer.WriteBits(charCount, 17);
+
do
{
- uint32 guidlow = (*result)[0].GetUInt32();
- TC_LOG_INFO("network", "Loading char guid %u from account %u.", guidlow, GetAccountId());
- if (Player::BuildEnumData(result, &data))
- {
- // Do not allow banned characters to log in
- if (!(*result)[20].GetUInt32())
- _legitCharacters.insert(guidlow);
+ uint32 guidLow = (*result)[0].GetUInt32();
- if (!sWorld->HasCharacterNameData(guidlow)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
- sWorld->AddCharacterNameData(guidlow, (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8());
- ++num;
- }
- }
- while (result->NextRow());
+ TC_LOG_INFO("network", "Loading char guid %u from account %u.", guidLow, GetAccountId());
+
+ Player::BuildEnumData(result, &dataBuffer, &bitBuffer);
+
+ // Do not allow banned characters to log in
+ if (!(*result)[20].GetUInt32())
+ _legitCharacters.insert(guidLow);
+
+ if (!sWorld->HasCharacterNameData(guidLow)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
+ sWorld->AddCharacterNameData(guidLow, (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8());
+ } while (result->NextRow());
+
+ bitBuffer.FlushBits();
}
+ else
+ bitBuffer.WriteBits(0, 17);
- data.put<uint8>(0, num);
+ WorldPacket data(SMSG_CHAR_ENUM, 7 + bitBuffer.size() + dataBuffer.size());
+ data.append(bitBuffer);
+ if (charCount)
+ data.append(dataBuffer);
SendPacket(&data);
}
@@ -762,6 +787,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
sLog->outCharDump(dump.c_str(), accountId, GUID_LOPART(guid), name.c_str());
}
+ sGuildFinderMgr->RemoveAllMembershipRequestsFromPlayer(guid);
sCalendarMgr->RemoveAllPlayerEventsAndInvites(guid);
Player::DeleteFromDB(guid, accountId);
@@ -780,11 +806,28 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
}
m_playerLoading = true;
- uint64 playerGuid = 0;
+ ObjectGuid playerGuid;
TC_LOG_DEBUG("network", "WORLD: Recvd Player Logon Message");
-
- recvData >> playerGuid;
+ playerGuid[2] = recvData.ReadBit();
+ playerGuid[3] = recvData.ReadBit();
+ playerGuid[0] = recvData.ReadBit();
+ playerGuid[6] = recvData.ReadBit();
+ playerGuid[4] = recvData.ReadBit();
+ playerGuid[5] = recvData.ReadBit();
+ playerGuid[1] = recvData.ReadBit();
+ playerGuid[7] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(playerGuid[2]);
+ recvData.ReadByteSeq(playerGuid[7]);
+ recvData.ReadByteSeq(playerGuid[0]);
+ recvData.ReadByteSeq(playerGuid[3]);
+ recvData.ReadByteSeq(playerGuid[5]);
+ recvData.ReadByteSeq(playerGuid[6]);
+ recvData.ReadByteSeq(playerGuid[1]);
+ recvData.ReadByteSeq(playerGuid[4]);
+
+ TC_LOG_DEBUG("network", "Character (Guid: %u) logging in", GUID_LOPART(playerGuid));
if (!IsLegitCharacterForAccount(GUID_LOPART(playerGuid)))
{
@@ -804,6 +847,17 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
_charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder);
}
+void WorldSession::HandleLoadScreenOpcode(WorldPacket& recvPacket)
+{
+ TC_LOG_INFO("misc", "WORLD: Recvd CMSG_LOAD_SCREEN");
+ uint32 mapID;
+
+ recvPacket >> mapID;
+ recvPacket.ReadBit();
+
+ // TODO: Do something with this packet
+}
+
void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
{
uint64 playerGuid = holder->GetGuid();
@@ -838,9 +892,34 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
LoadAccountData(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ACCOUNT_DATA), PER_CHARACTER_CACHE_MASK);
SendAccountDataTimes(PER_CHARACTER_CACHE_MASK);
- data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0
+ bool featureBit4 = true;
+ data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 7); // checked in 4.2.2
data << uint8(2); // unknown value
- data << uint8(0); // enable(1)/disable(0) voice chat interface in client
+ data << uint32(1);
+ data << uint32(1);
+ data << uint32(2);
+ data << uint32(0);
+ data.WriteBit(1);
+ data.WriteBit(1);
+ data.WriteBit(0);
+ data.WriteBit(featureBit4);
+ data.WriteBit(0);
+ data.WriteBit(0);
+ data.FlushBits();
+ if (featureBit4)
+ {
+ data << uint32(1);
+ data << uint32(0);
+ data << uint32(10);
+ data << uint32(60);
+ }
+
+ //if (featureBit5)
+ //{
+ // data << uint32(0);
+ // data << uint32(0);
+ // data << uint32(0);
+ //}
SendPacket(&data);
// Send MOTD
@@ -887,28 +966,30 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
Field* fields = resultGuild->Fetch();
pCurrChar->SetInGuild(fields[0].GetUInt32());
pCurrChar->SetRank(fields[1].GetUInt8());
+ if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId()))
+ pCurrChar->SetGuildLevel(guild->GetLevel());
}
else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership
{
pCurrChar->SetInGuild(0);
pCurrChar->SetRank(0);
+ pCurrChar->SetGuildLevel(0);
}
- if (pCurrChar->GetGuildId() != 0)
+ data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4);
+ data << uint64(0);
+ SendPacket(&data);
+
+ data.Initialize(SMSG_HOTFIX_INFO);
+ HotfixData const& hotfix = sObjectMgr->GetHotfixData();
+ data.WriteBits(hotfix.size(), 22);
+ data.FlushBits();
+ for (uint32 i = 0; i < hotfix.size(); ++i)
{
- if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId()))
- guild->SendLoginInfo(this);
- else
- {
- // remove wrong guild data
- TC_LOG_ERROR("network", "Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName().c_str(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId());
- pCurrChar->SetInGuild(0);
- }
+ data << uint32(hotfix[i].Type);
+ data << uint32(hotfix[i].Timestamp);
+ data << uint32(hotfix[i].Entry);
}
-
- data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4);
- data << uint32(0);
- data << uint32(0);
SendPacket(&data);
pCurrChar->SendInitialPacketsBeforeAddToMap();
@@ -933,7 +1014,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
if (!pCurrChar->GetMap()->AddPlayerToMap(pCurrChar) || !pCurrChar->CheckInstanceLoginValid())
{
- AreaTrigger const* at = sObjectMgr->GetGoBackTrigger(pCurrChar->GetMapId());
+ AreaTriggerStruct const* at = sObjectMgr->GetGoBackTrigger(pCurrChar->GetMapId());
if (at)
pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation());
else
@@ -943,18 +1024,26 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
sObjectAccessor->AddObject(pCurrChar);
//TC_LOG_DEBUG("Player %s added to Map.", pCurrChar->GetName().c_str());
+ if (pCurrChar->GetGuildId() != 0)
+ {
+ if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId()))
+ guild->SendLoginInfo(this);
+ else
+ {
+ // remove wrong guild data
+ TC_LOG_ERROR("misc", "Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName().c_str(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId());
+ pCurrChar->SetInGuild(0);
+ }
+ }
+
pCurrChar->SendInitialPacketsAfterAddToMap();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ONLINE);
-
stmt->setUInt32(0, pCurrChar->GetGUIDLow());
-
CharacterDatabase.Execute(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_ONLINE);
-
stmt->setUInt32(0, GetAccountId());
-
LoginDatabase.Execute(stmt);
pCurrChar->SetInGameTime(getMSTime());
@@ -977,11 +1066,13 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
if (pCurrChar->m_deathState != ALIVE)
{
// not blizz like, we must correctly save and load player instead...
- if (pCurrChar->getRace() == RACE_NIGHTELF)
+ if (pCurrChar->getRace() == RACE_NIGHTELF && !pCurrChar->HasAura(20584))
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->SetMovement(MOVE_WATER_WALK);
+ if (!pCurrChar->HasAura(8326))
+ pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?)
+
+ pCurrChar->SetWaterWalking(true);
}
pCurrChar->ContinueTaxiFlight();
@@ -1016,8 +1107,14 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
bool firstLogin = pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST);
if (firstLogin)
+ {
pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST);
+ PlayerInfo const* info = sObjectMgr->GetPlayerInfo(pCurrChar->getRace(), pCurrChar->getClass());
+ for (uint32 spellId : info->castSpells)
+ pCurrChar->CastSpell(pCurrChar, spellId, true);
+ }
+
// show time before shutdown if shutdown planned.
if (sWorld->IsShuttingDown())
sWorld->ShutdownMsg(true, pCurrChar);
@@ -1081,13 +1178,13 @@ void WorldSession::HandleTutorialFlag(WorldPacket& recvData)
SetTutorialInt(index, flag);
}
-void WorldSession::HandleTutorialClear(WorldPacket & /*recvData*/)
+void WorldSession::HandleTutorialClear(WorldPacket& /*recvData*/)
{
for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i)
SetTutorialInt(i, 0xFFFFFFFF);
}
-void WorldSession::HandleTutorialReset(WorldPacket & /*recvData*/)
+void WorldSession::HandleTutorialReset(WorldPacket& /*recvData*/)
{
for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i)
SetTutorialInt(i, 0x00000000);
@@ -1233,7 +1330,6 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recvData)
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
- data << uint64(guid);
SendPacket(&data);
return;
}
@@ -1243,7 +1339,6 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recvData)
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
- data << uint64(guid);
SendPacket(&data);
return;
}
@@ -1252,7 +1347,6 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recvData)
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
- data << uint64(guid);
SendPacket(&data);
return;
}
@@ -1266,7 +1360,6 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recvData)
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
- data << uint64(guid);
SendPacket(&data);
return;
}
@@ -1278,7 +1371,6 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recvData)
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
- data << uint64(guid);
SendPacket(&data);
return;
}
@@ -1288,7 +1380,6 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recvData)
{
WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8);
data << uint32(1);
- data << uint64(guid);
SendPacket(&data);
return;
}
@@ -1361,8 +1452,8 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData)
// 0 - ok
// 1, 3 - not enough money
- // 2 - you have to seat on barber chair
- if (!_player->HasEnoughMoney(cost))
+ // 2 - you have to sit on barber chair
+ if (!_player->HasEnoughMoney((uint64)cost))
{
WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4);
data << uint32(1); // no money
@@ -1376,7 +1467,7 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData)
SendPacket(&data);
}
- _player->ModifyMoney(-int32(cost)); // it isn't free
+ _player->ModifyMoney(-int64(cost)); // it isn't free
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, cost);
_player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id));
@@ -1401,7 +1492,7 @@ void WorldSession::HandleRemoveGlyph(WorldPacket& recvData)
return;
}
- if (uint32 glyph = _player->GetGlyph(slot))
+ if (uint32 glyph = _player->GetGlyph(_player->GetActiveSpec(), slot))
{
if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
@@ -1433,7 +1524,6 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
recvData >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AT_LOGIN);
-
stmt->setUInt32(0, GUID_LOPART(guid));
// TODO: Make async with callback
PreparedQueryResult result = CharacterDatabase.Query(stmt);
@@ -1537,7 +1627,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
SendPacket(&data);
}
-void WorldSession::HandleEquipmentSetSave(WorldPacket &recvData)
+void WorldSession::HandleEquipmentSetSave(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "CMSG_EQUIPMENT_SET_SAVE");
@@ -1599,7 +1689,7 @@ void WorldSession::HandleEquipmentSetDelete(WorldPacket &recvData)
_player->DeleteEquipmentSet(setGuid);
}
-void WorldSession::HandleEquipmentSetUse(WorldPacket &recvData)
+void WorldSession::HandleEquipmentSetUse(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "CMSG_EQUIPMENT_SET_USE");
@@ -1807,6 +1897,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
case RACE_UNDEAD_PLAYER:
case RACE_TROLL:
case RACE_BLOODELF:
+ case RACE_GOBLIN:
team = TEAM_HORDE;
break;
default:
@@ -1851,6 +1942,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
case RACE_NIGHTELF:
stmt->setUInt16(1, 113);
break;
+ case RACE_WORGEN:
+ stmt->setUInt16(1, 791);
+ break;
case RACE_UNDEAD_PLAYER:
stmt->setUInt16(1, 673);
break;
@@ -1863,6 +1957,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
case RACE_BLOODELF:
stmt->setUInt16(1, 137);
break;
+ case RACE_GOBLIN:
+ stmt->setUInt16(1, 792);
+ break;
}
trans->Append(stmt);
@@ -2203,3 +2300,88 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
data << uint8(race);
SendPacket(&data);
}
+
+void WorldSession::HandleRandomizeCharNameOpcode(WorldPacket& recvData)
+{
+ uint8 gender, race;
+
+ recvData >> race;
+ recvData >> gender;
+
+ if (!Player::IsValidRace(race))
+ {
+ TC_LOG_ERROR("misc", "Invalid race (%u) sent by accountId: %u", race, GetAccountId());
+ return;
+ }
+
+ if (!Player::IsValidGender(gender))
+ {
+ TC_LOG_ERROR("misc", "Invalid gender (%u) sent by accountId: %u", gender, GetAccountId());
+ return;
+ }
+
+ std::string const* name = GetRandomCharacterName(race, gender);
+ WorldPacket data(SMSG_RANDOMIZE_CHAR_NAME, 10);
+ data.WriteBit(0); // unk
+ data.WriteBits(name->size(), 7);
+ data.WriteString(*name);
+ SendPacket(&data);
+}
+
+void WorldSession::HandleReorderCharacters(WorldPacket& recvData)
+{
+ uint32 charactersCount = recvData.ReadBits(10);
+
+ std::vector<ObjectGuid> guids(charactersCount);
+ uint8 position;
+
+ for (uint8 i = 0; i < charactersCount; ++i)
+ {
+ guids[i][1] = recvData.ReadBit();
+ guids[i][4] = recvData.ReadBit();
+ guids[i][5] = recvData.ReadBit();
+ guids[i][3] = recvData.ReadBit();
+ guids[i][0] = recvData.ReadBit();
+ guids[i][7] = recvData.ReadBit();
+ guids[i][6] = recvData.ReadBit();
+ guids[i][2] = recvData.ReadBit();
+ }
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ for (uint8 i = 0; i < charactersCount; ++i)
+ {
+ recvData.ReadByteSeq(guids[i][6]);
+ recvData.ReadByteSeq(guids[i][5]);
+ recvData.ReadByteSeq(guids[i][1]);
+ recvData.ReadByteSeq(guids[i][4]);
+ recvData.ReadByteSeq(guids[i][0]);
+ recvData.ReadByteSeq(guids[i][3]);
+
+ recvData >> position;
+
+ recvData.ReadByteSeq(guids[i][2]);
+ recvData.ReadByteSeq(guids[i][7]);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_LIST_SLOT);
+ stmt->setUInt8(0, position);
+ stmt->setUInt32(1, GUID_LOPART(guids[i]));
+ trans->Append(stmt);
+ }
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+void WorldSession::HandleOpeningCinematic(WorldPacket& /*recvData*/)
+{
+ // Only players that has not yet gained any experience can use this
+ if (_player->GetUInt32Value(PLAYER_XP))
+ return;
+
+ if (ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(_player->getClass()))
+ {
+ if (classEntry->CinematicSequence)
+ _player->SendCinematicStart(classEntry->CinematicSequence);
+ else if (ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(_player->getRace()))
+ _player->SendCinematicStart(raceEntry->CinematicSequence);
+ }
+}
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index eccf7a6fd38..422d0d9c7d2 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -42,133 +42,185 @@
void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
{
- uint32 type;
+ uint32 type = 0;
uint32 lang;
- recvData >> type;
- recvData >> lang;
-
- if (type >= MAX_CHAT_MSG_TYPE)
+ switch (recvData.GetOpcode())
{
- TC_LOG_ERROR("network", "CHAT: Wrong message type received: %u", type);
- recvData.rfinish();
- return;
+ case CMSG_MESSAGECHAT_SAY:
+ type = CHAT_MSG_SAY;
+ break;
+ case CMSG_MESSAGECHAT_YELL:
+ type = CHAT_MSG_YELL;
+ break;
+ case CMSG_MESSAGECHAT_CHANNEL:
+ type = CHAT_MSG_CHANNEL;
+ break;
+ case CMSG_MESSAGECHAT_WHISPER:
+ type = CHAT_MSG_WHISPER;
+ break;
+ case CMSG_MESSAGECHAT_GUILD:
+ type = CHAT_MSG_GUILD;
+ break;
+ case CMSG_MESSAGECHAT_OFFICER:
+ type = CHAT_MSG_OFFICER;
+ break;
+ case CMSG_MESSAGECHAT_AFK:
+ type = CHAT_MSG_AFK;
+ break;
+ case CMSG_MESSAGECHAT_DND:
+ type = CHAT_MSG_DND;
+ break;
+ case CMSG_MESSAGECHAT_EMOTE:
+ type = CHAT_MSG_EMOTE;
+ break;
+ case CMSG_MESSAGECHAT_PARTY:
+ type = CHAT_MSG_PARTY;
+ break;
+ case CMSG_MESSAGECHAT_RAID:
+ type = CHAT_MSG_RAID;
+ break;
+ case CMSG_MESSAGECHAT_BATTLEGROUND:
+ type = CHAT_MSG_BATTLEGROUND;
+ break;
+ case CMSG_MESSAGECHAT_RAID_WARNING:
+ type = CHAT_MSG_RAID_WARNING;
+ break;
+ default:
+ TC_LOG_ERROR("network", "HandleMessagechatOpcode : Unknown chat opcode (%u)", recvData.GetOpcode());
+ recvData.hexlike();
+ return;
}
- if (lang == LANG_UNIVERSAL && type != CHAT_MSG_AFK && type != CHAT_MSG_DND)
+ if (type >= MAX_CHAT_MSG_TYPE)
{
- TC_LOG_ERROR("network", "CMSG_MESSAGECHAT: Possible hacking-attempt: %s tried to send a message in universal language", GetPlayerInfo().c_str());
- SendNotification(LANG_UNKNOWN_LANGUAGE);
+ TC_LOG_ERROR("network", "CHAT: Wrong message type received: %u", type);
recvData.rfinish();
return;
}
Player* sender = GetPlayer();
- //TC_LOG_DEBUG("CHAT: packet received. type %u, lang %u", type, lang);
+ //TC_LOG_DEBUG("misc", "CHAT: packet received. type %u, lang %u", type, lang);
- // prevent talking at unknown language (cheating)
- LanguageDesc const* langDesc = GetLanguageDescByID(lang);
- if (!langDesc)
+ // no language sent with emote packet.
+ if (type != CHAT_MSG_EMOTE && type != CHAT_MSG_AFK && type != CHAT_MSG_DND)
{
- SendNotification(LANG_UNKNOWN_LANGUAGE);
- recvData.rfinish();
- return;
- }
+ recvData >> lang;
- if (langDesc->skill_id != 0 && !sender->HasSkill(langDesc->skill_id))
- {
- // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language)
- Unit::AuraEffectList const& langAuras = sender->GetAuraEffectsByType(SPELL_AURA_COMPREHEND_LANGUAGE);
- bool foundAura = false;
- for (Unit::AuraEffectList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i)
+ if (lang == LANG_UNIVERSAL)
{
- if ((*i)->GetMiscValue() == int32(lang))
- {
- foundAura = true;
- break;
- }
+ TC_LOG_ERROR("network", "CMSG_MESSAGECHAT: Possible hacking-attempt: %s tried to send a message in universal language", GetPlayerInfo().c_str());
+ SendNotification(LANG_UNKNOWN_LANGUAGE);
+ recvData.rfinish();
+ return;
}
- if (!foundAura)
+
+ // prevent talking at unknown language (cheating)
+ LanguageDesc const* langDesc = GetLanguageDescByID(lang);
+ if (!langDesc)
{
- SendNotification(LANG_NOT_LEARNED_LANGUAGE);
+ SendNotification(LANG_UNKNOWN_LANGUAGE);
recvData.rfinish();
return;
}
- }
- if (lang == LANG_ADDON)
- {
- // LANG_ADDON is only valid for the following message types
- switch (type)
+ if (langDesc->skill_id != 0 && !sender->HasSkill(langDesc->skill_id))
{
- case CHAT_MSG_PARTY:
- case CHAT_MSG_RAID:
- case CHAT_MSG_GUILD:
- case CHAT_MSG_BATTLEGROUND:
- case CHAT_MSG_WHISPER:
- // check if addon messages are disabled
- if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL))
+ // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language)
+ Unit::AuraEffectList const& langAuras = sender->GetAuraEffectsByType(SPELL_AURA_COMPREHEND_LANGUAGE);
+ bool foundAura = false;
+ for (Unit::AuraEffectList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i)
+ {
+ if ((*i)->GetMiscValue() == int32(lang))
{
- recvData.rfinish();
- return;
+ foundAura = true;
+ break;
}
- break;
- default:
- TC_LOG_ERROR("network", "Player %s (GUID: %u) sent a chatmessage with an invalid language/message type combination",
- GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
-
+ }
+ if (!foundAura)
+ {
+ SendNotification(LANG_NOT_LEARNED_LANGUAGE);
recvData.rfinish();
return;
+ }
}
- }
- // LANG_ADDON should not be changed nor be affected by flood control
- else
- {
- // send in universal language if player in .gmon mode (ignore spell effects)
- if (sender->IsGameMaster())
- lang = LANG_UNIVERSAL;
+
+ if (lang == LANG_ADDON)
+ {
+ // LANG_ADDON is only valid for the following message types
+ switch (type)
+ {
+ case CHAT_MSG_PARTY:
+ case CHAT_MSG_RAID:
+ case CHAT_MSG_GUILD:
+ case CHAT_MSG_BATTLEGROUND:
+ case CHAT_MSG_WHISPER:
+ // check if addon messages are disabled
+ if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL))
+ {
+ recvData.rfinish();
+ return;
+ }
+ break;
+ default:
+ TC_LOG_ERROR("network", "Player %s (GUID: %u) sent a chatmessage with an invalid language/message type combination",
+ GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
+
+ recvData.rfinish();
+ return;
+ }
+ }
+ // LANG_ADDON should not be changed nor be affected by flood control
else
{
- Unit::AuraEffectList const& ModLangAuras = sender->GetAuraEffectsByType(SPELL_AURA_MOD_LANGUAGE);
- if (!ModLangAuras.empty())
- lang = ModLangAuras.front()->GetMiscValue();
- else if (HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT))
+ // send in universal language if player in .gm on mode (ignore spell effects)
+ if (sender->IsGameMaster())
lang = LANG_UNIVERSAL;
else
{
- switch (type)
+ // send in universal language in two side iteration allowed mode
+ if (HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT))
+ lang = LANG_UNIVERSAL;
+ else
{
- case CHAT_MSG_PARTY:
- case CHAT_MSG_PARTY_LEADER:
- case CHAT_MSG_RAID:
- case CHAT_MSG_RAID_LEADER:
- case CHAT_MSG_RAID_WARNING:
- // allow two side chat at group channel if two side group allowed
- if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
- lang = LANG_UNIVERSAL;
- break;
- case CHAT_MSG_GUILD:
- case CHAT_MSG_OFFICER:
- // allow two side chat at guild channel if two side guild allowed
- if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD))
- lang = LANG_UNIVERSAL;
- break;
+ switch (type)
+ {
+ case CHAT_MSG_PARTY:
+ case CHAT_MSG_PARTY_LEADER:
+ case CHAT_MSG_RAID:
+ case CHAT_MSG_RAID_LEADER:
+ case CHAT_MSG_RAID_WARNING:
+ // allow two side chat at group channel if two side group allowed
+ if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
+ lang = LANG_UNIVERSAL;
+ break;
+ case CHAT_MSG_GUILD:
+ case CHAT_MSG_OFFICER:
+ // allow two side chat at guild channel if two side guild allowed
+ if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD))
+ lang = LANG_UNIVERSAL;
+ break;
+ }
}
+
+ // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used)
+ Unit::AuraEffectList const& ModLangAuras = sender->GetAuraEffectsByType(SPELL_AURA_MOD_LANGUAGE);
+ if (!ModLangAuras.empty())
+ lang = ModLangAuras.front()->GetMiscValue();
}
- }
- if (!sender->CanSpeak())
- {
- std::string timeStr = secsToTimeString(m_muteTime - time(NULL));
- SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str());
- recvData.rfinish(); // Prevent warnings
- return;
+ if (!sender->CanSpeak())
+ {
+ std::string timeStr = secsToTimeString(m_muteTime - time(NULL));
+ SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str());
+ recvData.rfinish(); // Prevent warnings
+ return;
+ }
}
-
- if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND)
- sender->UpdateSpeakTime();
}
+ else
+ lang = LANG_UNIVERSAL;
if (sender->HasAura(1852) && type != CHAT_MSG_WHISPER)
{
@@ -177,6 +229,8 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return;
}
+ uint32 textLength = 0;
+ uint32 receiverLength = 0;
std::string to, channel, msg;
bool ignoreChecks = false;
switch (type)
@@ -185,27 +239,30 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
case CHAT_MSG_EMOTE:
case CHAT_MSG_YELL:
case CHAT_MSG_PARTY:
- case CHAT_MSG_PARTY_LEADER:
case CHAT_MSG_GUILD:
case CHAT_MSG_OFFICER:
case CHAT_MSG_RAID:
- case CHAT_MSG_RAID_LEADER:
case CHAT_MSG_RAID_WARNING:
case CHAT_MSG_BATTLEGROUND:
- case CHAT_MSG_BATTLEGROUND_LEADER:
- recvData >> msg;
+ textLength = recvData.ReadBits(9);
+ msg = recvData.ReadString(textLength);
break;
case CHAT_MSG_WHISPER:
- recvData >> to;
- recvData >> msg;
+ receiverLength = recvData.ReadBits(10);
+ textLength = recvData.ReadBits(9);
+ to = recvData.ReadString(receiverLength);
+ msg = recvData.ReadString(textLength);
break;
case CHAT_MSG_CHANNEL:
- recvData >> channel;
- recvData >> msg;
+ receiverLength = recvData.ReadBits(10);
+ textLength = recvData.ReadBits(9);
+ msg = recvData.ReadString(textLength);
+ channel = recvData.ReadString(receiverLength);
break;
case CHAT_MSG_AFK:
case CHAT_MSG_DND:
- recvData >> msg;
+ textLength = recvData.ReadBits(9);
+ msg = recvData.ReadString(textLength);
ignoreChecks = true;
break;
}
@@ -259,7 +316,8 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
sender->TextEmote(msg);
else if (type == CHAT_MSG_YELL)
sender->Yell(msg, lang);
- } break;
+ break;
+ }
case CHAT_MSG_WHISPER:
{
if (!normalizePlayerName(to))
@@ -299,7 +357,8 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
sender->AddWhisperWhiteList(receiver->GetGUID());
GetPlayer()->Whisper(msg, lang, receiver->GetGUID());
- } break;
+ break;
+ }
case CHAT_MSG_PARTY:
case CHAT_MSG_PARTY_LEADER:
{
@@ -312,15 +371,16 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return;
}
- if (type == CHAT_MSG_PARTY_LEADER && !group->IsLeader(sender->GetGUID()))
- return;
+ if (group->IsLeader(GetPlayer()->GetGUID()))
+ type = CHAT_MSG_PARTY_LEADER;
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPacket data;
ChatHandler::BuildChatPacket(data, ChatMsg(type), Language(lang), sender, NULL, msg);
group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetGUID()));
- } break;
+ break;
+ }
case CHAT_MSG_GUILD:
{
if (GetPlayer()->GetGuildId())
@@ -332,7 +392,8 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
guild->BroadcastToGuild(this, false, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
}
}
- } break;
+ break;
+ }
case CHAT_MSG_OFFICER:
{
if (GetPlayer()->GetGuildId())
@@ -344,8 +405,10 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
guild->BroadcastToGuild(this, true, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
}
}
- } break;
+ break;
+ }
case CHAT_MSG_RAID:
+ case CHAT_MSG_RAID_LEADER:
{
// if player is in battleground, he cannot say to battleground members by /ra
Group* group = GetPlayer()->GetOriginalGroup();
@@ -356,29 +419,16 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return;
}
- sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
-
- WorldPacket data;
- ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID, Language(lang), sender, NULL, msg);
- group->BroadcastPacket(&data, false);
- } break;
- case CHAT_MSG_RAID_LEADER:
- {
- // if player is in battleground, he cannot say to battleground members by /ra
- Group* group = GetPlayer()->GetOriginalGroup();
- if (!group)
- {
- group = GetPlayer()->GetGroup();
- if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(sender->GetGUID()))
- return;
- }
+ if (group->IsLeader(GetPlayer()->GetGUID()))
+ type = CHAT_MSG_RAID_LEADER;
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPacket data;
- ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID_LEADER, Language(lang), sender, NULL, msg);
+ ChatHandler::BuildChatPacket(data, ChatMsg(type), Language(lang), sender, NULL, msg);
group->BroadcastPacket(&data, false);
- } break;
+ break;
+ }
case CHAT_MSG_RAID_WARNING:
{
Group* group = GetPlayer()->GetGroup();
@@ -391,33 +441,26 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
//in battleground, raid warning is sent only to players in battleground - code is ok
ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID_WARNING, Language(lang), sender, NULL, msg);
group->BroadcastPacket(&data, false);
- } break;
+ break;
+ }
case CHAT_MSG_BATTLEGROUND:
- {
- //battleground raid is always in Player->GetGroup(), never in GetOriginalGroup()
- Group* group = GetPlayer()->GetGroup();
- if (!group || !group->isBGGroup())
- return;
-
- sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
-
- WorldPacket data;
- ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND, Language(lang), sender, NULL, msg);
- group->BroadcastPacket(&data, false);
- } break;
case CHAT_MSG_BATTLEGROUND_LEADER:
{
// battleground raid is always in Player->GetGroup(), never in GetOriginalGroup()
Group* group = GetPlayer()->GetGroup();
- if (!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID()))
+ if (!group || !group->isBGGroup())
return;
+ if (group->IsLeader(GetPlayer()->GetGUID()))
+ type = CHAT_MSG_BATTLEGROUND_LEADER;
+
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPacket data;
- ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND_LEADER, Language(lang), sender, NULL, msg);;
+ ChatHandler::BuildChatPacket(data, ChatMsg(type), Language(lang), sender, NULL, msg);
group->BroadcastPacket(&data, false);
- } break;
+ break;
+ }
case CHAT_MSG_CHANNEL:
{
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHAT_CHANNEL_REQ))
@@ -437,17 +480,18 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
chn->Say(sender->GetGUID(), msg.c_str(), lang);
}
}
- } break;
+ break;
+ }
case CHAT_MSG_AFK:
{
if (!sender->IsInCombat())
{
- if (sender->isAFK()) // Already AFK
+ if (sender ->isAFK()) // Already AFK
{
if (msg.empty())
- sender->ToggleAFK(); // Remove AFK
+ sender->ToggleAFK(); // Remove AFK
else
- sender->autoReplyMsg = msg; // Update message
+ sender->autoReplyMsg = msg; // Update message
}
else // New AFK mode
{
@@ -465,12 +509,12 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
}
case CHAT_MSG_DND:
{
- if (sender->isDND()) // Already DND
+ if (sender->isDND()) // Already DND
{
if (msg.empty())
- sender->ToggleDND(); // Remove DND
+ sender->ToggleDND(); // Remove DND
else
- sender->autoReplyMsg = msg; // Update message
+ sender->autoReplyMsg = msg; // Update message
}
else // New DND mode
{
@@ -491,6 +535,140 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
}
}
+void WorldSession::HandleAddonMessagechatOpcode(WorldPacket& recvData)
+{
+ Player* sender = GetPlayer();
+ ChatMsg type;
+
+ switch (recvData.GetOpcode())
+ {
+ case CMSG_MESSAGECHAT_ADDON_BATTLEGROUND:
+ type = CHAT_MSG_BATTLEGROUND;
+ break;
+ case CMSG_MESSAGECHAT_ADDON_GUILD:
+ type = CHAT_MSG_GUILD;
+ break;
+ case CMSG_MESSAGECHAT_ADDON_OFFICER:
+ type = CHAT_MSG_OFFICER;
+ break;
+ case CMSG_MESSAGECHAT_ADDON_PARTY:
+ type = CHAT_MSG_PARTY;
+ break;
+ case CMSG_MESSAGECHAT_ADDON_RAID:
+ type = CHAT_MSG_RAID;
+ break;
+ case CMSG_MESSAGECHAT_ADDON_WHISPER:
+ type = CHAT_MSG_WHISPER;
+ break;
+ default:
+ TC_LOG_ERROR("network", "HandleAddonMessagechatOpcode: Unknown addon chat opcode (%u)", recvData.GetOpcode());
+ recvData.hexlike();
+ return;
+ }
+
+ std::string message;
+ std::string prefix;
+ std::string targetName;
+
+ switch (type)
+ {
+ case CHAT_MSG_WHISPER:
+ {
+ uint32 msgLen = recvData.ReadBits(9);
+ uint32 prefixLen = recvData.ReadBits(5);
+ uint32 targetLen = recvData.ReadBits(10);
+ message = recvData.ReadString(msgLen);
+ prefix = recvData.ReadString(prefixLen);
+ targetName = recvData.ReadString(targetLen);
+ break;
+ }
+ case CHAT_MSG_PARTY:
+ case CHAT_MSG_RAID:
+ case CHAT_MSG_OFFICER:
+ {
+ uint32 prefixLen = recvData.ReadBits(5);
+ uint32 msgLen = recvData.ReadBits(9);
+ prefix = recvData.ReadString(prefixLen);
+ message = recvData.ReadString(msgLen);
+ break;
+ }
+ case CHAT_MSG_GUILD:
+ case CHAT_MSG_BATTLEGROUND:
+ {
+ uint32 msgLen = recvData.ReadBits(9);
+ uint32 prefixLen = recvData.ReadBits(5);
+ message = recvData.ReadString(msgLen);
+ prefix = recvData.ReadString(prefixLen);
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (prefix.empty() || prefix.length() > 16)
+ return;
+
+ // Disabled addon channel?
+ if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL))
+ {
+ recvData.rfinish();
+ return;
+ }
+
+ switch (type)
+ {
+ case CHAT_MSG_BATTLEGROUND:
+ {
+ Group* group = sender->GetGroup();
+ if (!group || !group->isBGGroup())
+ return;
+
+ WorldPacket data;
+ ChatHandler::BuildChatPacket(data, type, LANG_ADDON, sender, NULL, message, 0U, "", DEFAULT_LOCALE, prefix);
+ group->BroadcastAddonMessagePacket(&data, prefix, false);
+ break;
+ }
+ case CHAT_MSG_GUILD:
+ case CHAT_MSG_OFFICER:
+ {
+ if (sender->GetGuildId())
+ if (Guild* guild = sGuildMgr->GetGuildById(sender->GetGuildId()))
+ guild->BroadcastAddonToGuild(this, type == CHAT_MSG_OFFICER, message, prefix);
+ break;
+ }
+ case CHAT_MSG_WHISPER:
+ {
+ if (!normalizePlayerName(targetName))
+ break;
+ Player* receiver = sObjectAccessor->FindPlayerByName(targetName);
+ if (!receiver)
+ break;
+
+ sender->WhisperAddon(message, prefix, receiver);
+ break;
+ }
+ // Messages sent to "RAID" while in a party will get delivered to "PARTY"
+ case CHAT_MSG_PARTY:
+ case CHAT_MSG_RAID:
+ {
+
+ Group* group = sender->GetGroup();
+ if (!group || group->isBGGroup())
+ break;
+
+ WorldPacket data;
+ ChatHandler::BuildChatPacket(data, type, LANG_ADDON, sender, NULL, message, 0U, "", DEFAULT_LOCALE, prefix);
+ group->BroadcastAddonMessagePacket(&data, prefix, true, -1, group->GetMemberGroup(sender->GetGUID()));
+ break;
+ }
+ default:
+ {
+ TC_LOG_ERROR("misc", "HandleAddonMessagechatOpcode: unknown addon message type %u", type);
+ break;
+ }
+ }
+}
+
void WorldSession::HandleEmoteOpcode(WorldPacket& recvData)
{
if (!GetPlayer()->IsAlive() || GetPlayer()->HasUnitState(UNIT_STATE_DIED))
@@ -589,7 +767,7 @@ void WorldSession::HandleTextEmoteOpcode(WorldPacket& recvData)
TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder> >, WorldTypeMapContainer> message(emote_worker);
cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
- GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);
+ GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, 0, unit);
//Send scripted event call
if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI())
@@ -598,14 +776,30 @@ void WorldSession::HandleTextEmoteOpcode(WorldPacket& recvData)
void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recvData)
{
- uint64 iguid;
+ ObjectGuid guid;
uint8 unk;
//TC_LOG_DEBUG("network", "WORLD: Received CMSG_CHAT_IGNORED");
- recvData >> iguid;
recvData >> unk; // probably related to spam reporting
-
- Player* player = ObjectAccessor::FindPlayer(iguid);
+ guid[5] = recvData.ReadBit();
+ guid[2] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[5]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[2]);
+
+ Player* player = ObjectAccessor::FindPlayer(guid);
if (!player || !player->GetSession())
return;
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index 5b35da297c9..d74aebaaa1f 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -32,6 +32,7 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
+#include "SpellAuraEffects.h"
class Aura;
@@ -48,11 +49,12 @@ class Aura;
void WorldSession::SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res, uint32 val /* = 0 */)
{
- WorldPacket data(SMSG_PARTY_COMMAND_RESULT, 4 + member.size() + 1 + 4 + 4);
+ WorldPacket data(SMSG_PARTY_COMMAND_RESULT, 4 + member.size() + 1 + 4 + 4 + 8);
data << uint32(operation);
data << member;
data << uint32(res);
data << uint32(val); // LFD cooldown related (used with ERR_PARTY_LFG_BOOT_COOLDOWN_S and ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S)
+ data << uint64(0); // player who caused error (in some cases).
SendPacket(&data);
}
@@ -61,59 +63,91 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_INVITE");
- std::string membername;
- recvData >> membername;
- recvData.read_skip<uint32>();
+ ObjectGuid crossRealmGuid; // unused
+
+ recvData.read_skip<uint32>(); // Non-zero in cross realm invites
+ recvData.read_skip<uint32>(); // Always 0
+
+ crossRealmGuid[2] = recvData.ReadBit();
+ crossRealmGuid[7] = recvData.ReadBit();
+
+ uint8 realmLen = recvData.ReadBits(9);
+
+ crossRealmGuid[3] = recvData.ReadBit();
+
+ uint8 nameLen = recvData.ReadBits(10);
+
+ crossRealmGuid[5] = recvData.ReadBit();
+ crossRealmGuid[4] = recvData.ReadBit();
+ crossRealmGuid[6] = recvData.ReadBit();
+ crossRealmGuid[0] = recvData.ReadBit();
+ crossRealmGuid[1] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(crossRealmGuid[4]);
+ recvData.ReadByteSeq(crossRealmGuid[7]);
+ recvData.ReadByteSeq(crossRealmGuid[6]);
+
+ std::string memberName, realmName;
+ memberName = recvData.ReadString(nameLen);
+ realmName = recvData.ReadString(realmLen); // unused
+
+ recvData.ReadByteSeq(crossRealmGuid[1]);
+ recvData.ReadByteSeq(crossRealmGuid[0]);
+ recvData.ReadByteSeq(crossRealmGuid[5]);
+ recvData.ReadByteSeq(crossRealmGuid[3]);
+ recvData.ReadByteSeq(crossRealmGuid[2]);
// attempt add selected player
// cheating
- if (!normalizePlayerName(membername))
+ if (!normalizePlayerName(memberName))
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
return;
}
- Player* player = sObjectAccessor->FindPlayerByName(membername);
+ Player* player = sObjectAccessor->FindPlayerByName(memberName);
// no player
if (!player)
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
return;
}
// restrict invite to GMs
if (!sWorld->getBoolConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->IsGameMaster() && player->IsGameMaster())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
return;
}
// can't group with
if (!GetPlayer()->IsGameMaster() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_PLAYER_WRONG_FACTION);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PLAYER_WRONG_FACTION);
return;
}
if (GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_TARGET_NOT_IN_INSTANCE_S);
return;
}
// just ignore us
if (player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S);
return;
}
if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S);
return;
}
+ ObjectGuid invitedGuid = player->GetGUID();
+
Group* group = GetPlayer()->GetGroup();
if (group && group->isBGGroup())
group = GetPlayer()->GetOriginalGroup();
@@ -124,17 +158,63 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
// player already in another group or invited
if (group2 || player->GetGroupInvite())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_ALREADY_IN_GROUP_S);
if (group2)
{
// tell the player that they were invited but it failed as they were already in a group
- WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size
- data << uint8(0); // invited/already in group flag
- data << GetPlayer()->GetName(); // max len 48
- data << uint32(0); // unk
- data << uint8(0); // count
- data << uint32(0); // unk
+ WorldPacket data(SMSG_GROUP_INVITE, 45);
+
+ data.WriteBit(0);
+
+ data.WriteBit(invitedGuid[0]);
+ data.WriteBit(invitedGuid[3]);
+ data.WriteBit(invitedGuid[2]);
+
+ data.WriteBit(0); // Inverse already in group
+
+ data.WriteBit(invitedGuid[6]);
+ data.WriteBit(invitedGuid[5]);
+
+ data.WriteBits(0, 9); // Realm name
+
+ data.WriteBit(invitedGuid[4]);
+
+ data.WriteBits(GetPlayer()->GetName().size(), 7); // Inviter name length
+
+ data.WriteBits(0, 24); // Count 2
+
+ data.WriteBit(0);
+
+ data.WriteBit(invitedGuid[1]);
+ data.WriteBit(invitedGuid[7]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(invitedGuid[1]);
+ data.WriteByteSeq(invitedGuid[4]);
+
+ data << int32(getMSTime());
+ data << int32(0);
+ data << int32(0);
+
+ data.WriteByteSeq(invitedGuid[6]);
+ data.WriteByteSeq(invitedGuid[0]);
+ data.WriteByteSeq(invitedGuid[2]);
+ data.WriteByteSeq(invitedGuid[3]);
+
+ // for count2 { int32(0) }
+
+ data.WriteByteSeq(invitedGuid[5]);
+
+ // data.append(realm name);
+
+ data.WriteByteSeq(invitedGuid[7]);
+
+ data.WriteString(GetPlayer()->GetName()); // inviter name
+
+ data << int32(0);
+
player->GetSession()->SendPacket(&data);
}
@@ -185,90 +265,138 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
}
// ok, we do it
- WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size
- data << uint8(1); // invited/already in group flag
- data << GetPlayer()->GetName(); // max len 48
- data << uint32(0); // unk
- data << uint8(0); // count
- data << uint32(0); // unk
+ WorldPacket data(SMSG_GROUP_INVITE, 45);
+
+ data.WriteBit(0);
+
+ data.WriteBit(invitedGuid[0]);
+ data.WriteBit(invitedGuid[3]);
+ data.WriteBit(invitedGuid[2]);
+
+ data.WriteBit(1); // Inverse already in group
+
+ data.WriteBit(invitedGuid[6]);
+ data.WriteBit(invitedGuid[5]);
+
+ data.WriteBits(0, 9); // Realm name
+
+ data.WriteBit(invitedGuid[4]);
+
+ data.WriteBits(GetPlayer()->GetName().size(), 7); // Inviter name length
+
+ data.WriteBits(0, 24); // Count 2
+
+ data.WriteBit(0);
+
+ data.WriteBit(invitedGuid[1]);
+ data.WriteBit(invitedGuid[7]);
+
+ data.FlushBits();
+
+ data.WriteByteSeq(invitedGuid[1]);
+ data.WriteByteSeq(invitedGuid[4]);
+
+ data << int32(getMSTime());
+ data << int32(0);
+ data << int32(0);
+
+ data.WriteByteSeq(invitedGuid[6]);
+ data.WriteByteSeq(invitedGuid[0]);
+ data.WriteByteSeq(invitedGuid[2]);
+ data.WriteByteSeq(invitedGuid[3]);
+
+ // for count2 { int32(0) }
+
+ data.WriteByteSeq(invitedGuid[5]);
+
+ // data.append(realm name);
+
+ data.WriteByteSeq(invitedGuid[7]);
+
+ data.WriteString(GetPlayer()->GetName());
+
+ data << int32(0);
+
player->GetSession()->SendPacket(&data);
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PARTY_RESULT_OK);
}
-void WorldSession::HandleGroupAcceptOpcode(WorldPacket& recvData)
+void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData)
{
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_ACCEPT");
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_INVITE_RESPONSE");
- recvData.read_skip<uint32>();
- Group* group = GetPlayer()->GetGroupInvite();
+ recvData.ReadBit(); // unk always 0
+ bool accept = recvData.ReadBit();
- if (!group)
- return;
+ // Never actually received?
+ /*if (accept)
+ recvData.read_skip<uint32>(); // unk*/
- // Remove player from invitees in any case
- group->RemoveInvite(GetPlayer());
+ Group* group = GetPlayer()->GetGroupInvite();
- if (group->GetLeaderGUID() == GetPlayer()->GetGUID())
- {
- TC_LOG_ERROR("network", "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
+ if (!group)
return;
- }
- // Group is full
- if (group->IsFull())
+ if (accept)
{
- SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL);
- return;
- }
+ // Remove player from invitees in any case
+ group->RemoveInvite(GetPlayer());
- Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
-
- // Forming a new group, create it
- if (!group->IsCreated())
- {
- // This can happen if the leader is zoning. To be removed once delayed actions for zoning are implemented
- if (!leader)
+ if (group->GetLeaderGUID() == GetPlayer()->GetGUID())
{
- group->RemoveAllInvites();
+ TC_LOG_ERROR("network", "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
return;
}
- // If we're about to create a group there really should be a leader present
- ASSERT(leader);
- group->RemoveInvite(leader);
- group->Create(leader);
- sGroupMgr->AddGroup(group);
- }
+ // Group is full
+ if (group->IsFull())
+ {
+ SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL);
+ return;
+ }
- // Everything is fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
- if (!group->AddMember(GetPlayer()))
- return;
+ Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
- group->BroadcastGroupUpdate();
-}
+ // Forming a new group, create it
+ if (!group->IsCreated())
+ {
+ // This can happen if the leader is zoning. To be removed once delayed actions for zoning are implemented
+ if (!leader)
+ {
+ group->RemoveAllInvites();
+ return;
+ }
-void WorldSession::HandleGroupDeclineOpcode(WorldPacket & /*recvData*/)
-{
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_DECLINE");
+ // If we're about to create a group there really should be a leader present
+ ASSERT(leader);
+ group->RemoveInvite(leader);
+ group->Create(leader);
+ sGroupMgr->AddGroup(group);
+ }
- Group* group = GetPlayer()->GetGroupInvite();
- if (!group)
- return;
+ // Everything is fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
+ if (!group->AddMember(GetPlayer()))
+ return;
- // Remember leader if online (group pointer will be invalid if group gets disbanded)
- Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
+ group->BroadcastGroupUpdate();
+ }
+ else
+ {
+ // Remember leader if online (group pointer will be invalid if group gets disbanded)
+ Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
- // uninvite, group can be deleted
- GetPlayer()->UninviteFromGroup();
+ // uninvite, group can be deleted
+ GetPlayer()->UninviteFromGroup();
- if (!leader || !leader->GetSession())
- return;
+ if (!leader || !leader->GetSession())
+ return;
- // report
- WorldPacket data(SMSG_GROUP_DECLINE, GetPlayer()->GetName().length());
- data << GetPlayer()->GetName();
- leader->GetSession()->SendPacket(&data);
+ // report
+ WorldPacket data(SMSG_GROUP_DECLINE, GetPlayer()->GetName().size());
+ data << GetPlayer()->GetName();
+ leader->GetSession()->SendPacket(&data);
+ }
}
void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket& recvData)
@@ -386,7 +514,81 @@ void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData)
group->SendUpdate();
}
-void WorldSession::HandleGroupDisbandOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleGroupSetRolesOpcode(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_SET_ROLES");
+
+ uint32 newRole;
+ ObjectGuid guid1; // Assigner GUID
+ ObjectGuid guid2; // Target GUID
+
+ guid1 = GetPlayer()->GetGUID();
+
+ recvData >> newRole;
+
+ guid2[2] = recvData.ReadBit();
+ guid2[6] = recvData.ReadBit();
+ guid2[3] = recvData.ReadBit();
+ guid2[7] = recvData.ReadBit();
+ guid2[5] = recvData.ReadBit();
+ guid2[1] = recvData.ReadBit();
+ guid2[0] = recvData.ReadBit();
+ guid2[4] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid2[6]);
+ recvData.ReadByteSeq(guid2[4]);
+ recvData.ReadByteSeq(guid2[1]);
+ recvData.ReadByteSeq(guid2[3]);
+ recvData.ReadByteSeq(guid2[0]);
+ recvData.ReadByteSeq(guid2[5]);
+ recvData.ReadByteSeq(guid2[2]);
+ recvData.ReadByteSeq(guid2[7]);
+
+ WorldPacket data(SMSG_GROUP_SET_ROLE, 24);
+
+ data.WriteBit(guid1[1]);
+ data.WriteBit(guid2[0]);
+ data.WriteBit(guid2[2]);
+ data.WriteBit(guid2[4]);
+ data.WriteBit(guid2[7]);
+ data.WriteBit(guid2[3]);
+ data.WriteBit(guid1[7]);
+ data.WriteBit(guid2[5]);
+ data.WriteBit(guid1[5]);
+ data.WriteBit(guid1[4]);
+ data.WriteBit(guid1[3]);
+ data.WriteBit(guid2[6]);
+ data.WriteBit(guid1[2]);
+ data.WriteBit(guid1[6]);
+ data.WriteBit(guid2[1]);
+ data.WriteBit(guid1[0]);
+
+ data.WriteByteSeq(guid1[7]);
+ data.WriteByteSeq(guid2[3]);
+ data.WriteByteSeq(guid1[6]);
+ data.WriteByteSeq(guid2[4]);
+ data.WriteByteSeq(guid2[0]);
+ data << uint32(newRole); // New Role
+ data.WriteByteSeq(guid2[6]);
+ data.WriteByteSeq(guid2[2]);
+ data.WriteByteSeq(guid1[0]);
+ data.WriteByteSeq(guid1[4]);
+ data.WriteByteSeq(guid2[1]);
+ data.WriteByteSeq(guid1[3]);
+ data.WriteByteSeq(guid1[5]);
+ data.WriteByteSeq(guid1[2]);
+ data.WriteByteSeq(guid2[5]);
+ data.WriteByteSeq(guid2[7]);
+ data.WriteByteSeq(guid1[1]);
+ data << uint32(0); // Old Role
+
+ if (GetPlayer()->GetGroup())
+ GetPlayer()->GetGroup()->BroadcastPacket(&data, false);
+ else
+ SendPacket(&data);
+}
+
+void WorldSession::HandleGroupDisbandOpcode(WorldPacket& /*recvData*/)
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_DISBAND");
@@ -480,7 +682,7 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recvData)
recvData >> x;
recvData >> y;
- //TC_LOG_DEBUG("Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y);
+ //TC_LOG_DEBUG("misc", "Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y);
/** error handling **/
/********************/
@@ -509,7 +711,7 @@ void WorldSession::HandleRandomRollOpcode(WorldPacket& recvData)
// everything's fine, do it
roll = urand(minimum, maximum);
- //TC_LOG_DEBUG("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll);
+ //TC_LOG_DEBUG("misc", "ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll);
WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8);
data << uint32(minimum);
@@ -530,7 +732,7 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
if (!group)
return;
- uint8 x;
+ uint8 x;
recvData >> x;
/** error handling **/
@@ -538,9 +740,7 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
// everything's fine, do it
if (x == 0xFF) // target icon request
- {
group->SendTargetIconList(this);
- }
else // target icon update
{
if (group->isRaidGroup() && !group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
@@ -561,7 +761,7 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
}
}
-void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_RAID_CONVERT");
@@ -572,14 +772,22 @@ void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recvData*/)
if (_player->InBattleground())
return;
- /** error handling **/
+ // error handling
if (!group->IsLeader(GetPlayer()->GetGUID()) || group->GetMembersCount() < 2)
return;
- /********************/
// everything's fine, do it (is it 0 (PARTY_OP_INVITE) correct code)
SendPartyResult(PARTY_OP_INVITE, "", ERR_PARTY_RESULT_OK);
- group->ConvertToRaid();
+
+ // New 4.x: it is now possible to convert a raid to a group if member count is 5 or less
+
+ bool toRaid;
+ recvData >> toRaid;
+
+ if (toRaid)
+ group->ConvertToRaid();
+ else
+ group->ConvertToGroup();
}
void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
@@ -608,10 +816,9 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
Player* movedPlayer = sObjectAccessor->FindPlayerByName(name);
uint64 guid;
+
if (movedPlayer)
- {
guid = movedPlayer->GetGUID();
- }
else
{
CharacterDatabase.EscapeString(name);
@@ -621,6 +828,16 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
group->ChangeMembersGroup(guid, groupNr);
}
+void WorldSession::HandleGroupSwapSubGroupOpcode(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_SWAP_SUB_GROUP");
+ std::string unk1;
+ std::string unk2;
+
+ recvData >> unk1;
+ recvData >> unk2;
+}
+
void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_ASSISTANT_LEADER");
@@ -709,7 +926,7 @@ void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket& recvData)
}
}
-void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket& /*recvData*/)
{
//Group* group = GetPlayer()->GetGroup();
//if (!group)
@@ -728,18 +945,15 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
if (mask == GROUP_UPDATE_FLAG_NONE)
return;
+ std::set<uint32> const& phases = player->GetPhases();
+
if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also
mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER);
if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets
mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER);
- uint32 byteCount = 0;
- for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i)
- if (mask & (1 << i))
- byteCount += GroupUpdateLength[i];
-
- data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount);
+ data->Initialize(SMSG_PARTY_MEMBER_STATS, 80); // average value
data->append(player->GetPackGUID());
*data << uint32(mask);
@@ -791,23 +1005,47 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
if (mask & GROUP_UPDATE_FLAG_ZONE)
*data << uint16(player->GetZoneId());
+ if (mask & GROUP_UPDATE_FLAG_UNK100)
+ *data << uint16(0);
+
if (mask & GROUP_UPDATE_FLAG_POSITION)
{
*data << uint16(player->GetPositionX());
*data << uint16(player->GetPositionY());
+ *data << uint16(player->GetPositionZ());
}
if (mask & GROUP_UPDATE_FLAG_AURAS)
{
+ *data << uint8(0);
uint64 auramask = player->GetAuraUpdateMaskForRaid();
*data << uint64(auramask);
+ *data << uint32(MAX_AURAS); // count
for (uint32 i = 0; i < MAX_AURAS; ++i)
{
if (auramask & (uint64(1) << i))
{
AuraApplication const* aurApp = player->GetVisibleAura(i);
- *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0);
- *data << uint8(1);
+ if (!aurApp)
+ {
+ *data << uint32(0);
+ *data << uint16(0);
+ continue;
+ }
+
+ *data << uint32(aurApp->GetBase()->GetId());
+ *data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ *data << int32(eff->GetAmount());
+ else
+ *data << int32(0);
+ }
+ }
}
}
}
@@ -816,9 +1054,9 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
if (mask & GROUP_UPDATE_FLAG_PET_GUID)
{
if (pet)
- *data << (uint64) pet->GetGUID();
+ *data << uint64(pet->GetGUID());
else
- *data << (uint64) 0;
+ *data << uint64(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_NAME)
@@ -881,20 +1119,43 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
{
if (pet)
{
+ *data << uint8(0);
uint64 auramask = pet->GetAuraUpdateMaskForRaid();
*data << uint64(auramask);
+ *data << uint32(MAX_AURAS); // count
for (uint32 i = 0; i < MAX_AURAS; ++i)
{
if (auramask & (uint64(1) << i))
{
AuraApplication const* aurApp = pet->GetVisibleAura(i);
- *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0);
- *data << uint8(aurApp ? aurApp->GetFlags() : 0);
+ if (!aurApp)
+ {
+ *data << uint32(0);
+ *data << uint16(0);
+ continue;
+ }
+
+ *data << uint32(aurApp->GetBase()->GetId());
+ *data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ *data << int32(eff->GetAmount());
+ else
+ *data << int32(0);
+ }
+ }
}
}
}
else
+ {
+ *data << uint8(0);
*data << uint64(0);
+ }
}
if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
@@ -903,22 +1164,31 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
*data << uint32(veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.transport.seat]);
else
*data << uint32(0);
+
+ }
+
+ if (mask & GROUP_UPDATE_FLAG_PHASE)
+ {
+ *data << uint32(phases.empty() ? 8 : 0);
+ *data << uint32(phases.size());
+ for (std::set<uint32>::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
+ *data << uint16(*itr);
}
}
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
-void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
+void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS");
- uint64 Guid;
- recvData >> Guid;
+ uint64 guid;
+ recvData >> guid;
- Player* player = HashMapHolder<Player>::Find(Guid);
+ Player* player = HashMapHolder<Player>::Find(guid);
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.appendPackGUID(guid);
data << uint32(GROUP_UPDATE_FLAG_STATUS);
data << uint16(MEMBER_STATUS_OFFLINE);
SendPacket(&data);
@@ -927,6 +1197,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
Pet* pet = player->GetPet();
Powers powerType = player->getPowerType();
+ std::set<uint32> const& phases = player->GetPhases();
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
@@ -947,6 +1218,9 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
if (player->GetVehicle())
updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT;
+ if (!phases.empty())
+ updateFlags |= GROUP_UPDATE_FLAG_PHASE;
+
uint16 playerStatus = MEMBER_STATUS_ONLINE;
if (player->IsPvP())
playerStatus |= MEMBER_STATUS_PVP;
@@ -981,21 +1255,38 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE
data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION
data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION
+ data << uint16(player->GetPositionZ()); // GROUP_UPDATE_FLAG_POSITION
- uint64 auraMask = 0;
+ // GROUP_UPDATE_FLAG_AURAS
+ data << uint8(1);
+ uint64 auramask = 0;
size_t maskPos = data.wpos();
- data << uint64(auraMask); // placeholder
+ data << uint64(auramask); // placeholder
+ data << uint32(MAX_AURAS); // count
+
for (uint8 i = 0; i < MAX_AURAS; ++i)
{
if (AuraApplication const* aurApp = player->GetVisibleAura(i))
{
- auraMask |= uint64(1) << i;
+ auramask |= (uint64(1) << i);
+
data << uint32(aurApp->GetBase()->GetId());
- data << uint8(aurApp->GetFlags());
+ data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ data << int32(eff->GetAmount());
+ else
+ data << int32(0);
+ }
+ }
}
}
- data.put<uint64>(maskPos, auraMask); // GROUP_UPDATE_FLAG_AURAS
+ data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS
if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID)
data << uint64(pet->GetGUID());
@@ -1018,18 +1309,33 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_POWER)
data << uint16(pet->GetMaxPower(pet->getPowerType()));
+ // GROUP_UPDATE_FLAG_PET_AURAS
uint64 petAuraMask = 0;
+ data << uint8(1);
maskPos = data.wpos();
data << uint64(petAuraMask); // placeholder
+ data << uint32(MAX_AURAS); // count
if (pet)
{
for (uint8 i = 0; i < MAX_AURAS; ++i)
{
if (AuraApplication const* aurApp = pet->GetVisibleAura(i))
{
- petAuraMask |= uint64(1) << i;
+ petAuraMask |= (uint64(1) << i);
+
data << uint32(aurApp->GetBase()->GetId());
- data << uint8(aurApp->GetFlags());
+ data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ data << int32(eff->GetAmount());
+ else
+ data << int32(0);
+ }
+ }
}
}
}
@@ -1039,31 +1345,34 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
data << uint32(player->GetVehicle()->GetVehicleInfo()->m_seatID[player->m_movementInfo.transport.seat]);
+ if (updateFlags & GROUP_UPDATE_FLAG_PHASE)
+ {
+ data << uint32(phases.empty() ? 8 : 0);
+ data << uint32(phases.size());
+ for (std::set<uint32>::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
+ data << uint16(*itr);
+ }
+
SendPacket(&data);
}
-/*!*/void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket& /*recvData*/)
{
// every time the player checks the character screen
_player->SendRaidInfo();
}
-/*void WorldSession::HandleGroupCancelOpcode(WorldPacket& recvData)
-{
- TC_LOG_DEBUG("WORLD: got CMSG_GROUP_CANCEL.");
-}*/
-
void WorldSession::HandleOptOutOfLootOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_OPT_OUT_OF_LOOT");
- uint32 passOnLoot;
+ bool passOnLoot;
recvData >> passOnLoot; // 1 always pass, 0 do not pass
// ignore if player not loaded
if (!GetPlayer()) // needed because STATUS_AUTHED
{
- if (passOnLoot != 0)
+ if (passOnLoot)
TC_LOG_ERROR("network", "CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!");
return;
}
diff --git a/src/server/game/Handlers/GuildFinderHandler.cpp b/src/server/game/Handlers/GuildFinderHandler.cpp
new file mode 100644
index 00000000000..14175b44d9f
--- /dev/null
+++ b/src/server/game/Handlers/GuildFinderHandler.cpp
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "WorldSession.h"
+#include "WorldPacket.h"
+#include "Object.h"
+#include "SharedDefines.h"
+#include "GuildFinderMgr.h"
+#include "GuildMgr.h"
+
+void WorldSession::HandleGuildFinderAddRecruit(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_ADD_RECRUIT");
+
+ if (sGuildFinderMgr->GetAllMembershipRequestsForPlayer(GetPlayer()->GetGUIDLow()).size() == 10)
+ return;
+
+ uint32 classRoles = 0;
+ uint32 availability = 0;
+ uint32 guildInterests = 0;
+
+ recvPacket >> classRoles >> guildInterests >> availability;
+
+ ObjectGuid guid;
+ guid[3] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ uint16 commentLength = recvPacket.ReadBits(11);
+ guid[5] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ uint8 nameLength = recvPacket.ReadBits(7);
+ guid[2] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[5]);
+ std::string comment = recvPacket.ReadString(commentLength);
+ std::string playerName = recvPacket.ReadString(nameLength);
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[0]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[3]);
+
+ uint32 guildLowGuid = GUID_LOPART(uint64(guid));
+
+ if (!IS_GUILD_GUID(guid))
+ return;
+ if (!(classRoles & GUILDFINDER_ALL_ROLES) || classRoles > GUILDFINDER_ALL_ROLES)
+ return;
+ if (!(availability & AVAILABILITY_ALWAYS) || availability > AVAILABILITY_ALWAYS)
+ return;
+ if (!(guildInterests & ALL_INTERESTS) || guildInterests > ALL_INTERESTS)
+ return;
+
+ MembershipRequest request = MembershipRequest(GetPlayer()->GetGUIDLow(), guildLowGuid, availability, classRoles, guildInterests, comment, time(NULL));
+ sGuildFinderMgr->AddMembershipRequest(guildLowGuid, request);
+}
+
+void WorldSession::HandleGuildFinderBrowse(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_BROWSE");
+ uint32 classRoles = 0;
+ uint32 availability = 0;
+ uint32 guildInterests = 0;
+ uint32 playerLevel = 0; // Raw player level (1-85), do they use MAX_FINDER_LEVEL when on level 85 ?
+
+ recvPacket >> classRoles >> availability >> guildInterests >> playerLevel;
+
+ if (!(classRoles & GUILDFINDER_ALL_ROLES) || classRoles > GUILDFINDER_ALL_ROLES)
+ return;
+ if (!(availability & AVAILABILITY_ALWAYS) || availability > AVAILABILITY_ALWAYS)
+ return;
+ if (!(guildInterests & ALL_INTERESTS) || guildInterests > ALL_INTERESTS)
+ return;
+ if (playerLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || playerLevel < 1)
+ return;
+
+ Player* player = GetPlayer();
+
+ LFGuildPlayer settings(player->GetGUIDLow(), classRoles, availability, guildInterests, ANY_FINDER_LEVEL);
+ LFGuildStore guildList = sGuildFinderMgr->GetGuildsMatchingSetting(settings, player->GetTeamId());
+ uint32 guildCount = guildList.size();
+
+ if (guildCount == 0)
+ {
+ WorldPacket packet(SMSG_LF_GUILD_BROWSE_UPDATED, 0);
+ player->SendDirectMessage(&packet);
+ return;
+ }
+
+ ByteBuffer bufferData(65 * guildCount);
+ WorldPacket data(SMSG_LF_GUILD_BROWSE_UPDATED, 3 + guildCount * 65); // Estimated size
+ data.WriteBits(guildCount, 19);
+
+ for (LFGuildStore::const_iterator itr = guildList.begin(); itr != guildList.end(); ++itr)
+ {
+ LFGuildSettings guildSettings = itr->second;
+ Guild* guild = sGuildMgr->GetGuildById(itr->first);
+
+ ObjectGuid guildGUID = ObjectGuid(guild->GetGUID());
+
+ data.WriteBit(guildGUID[7]);
+ data.WriteBit(guildGUID[5]);
+ data.WriteBits(guild->GetName().size(), 8);
+ data.WriteBit(guildGUID[0]);
+ data.WriteBits(guildSettings.GetComment().size(), 11);
+ data.WriteBit(guildGUID[4]);
+ data.WriteBit(guildGUID[1]);
+ data.WriteBit(guildGUID[2]);
+ data.WriteBit(guildGUID[6]);
+ data.WriteBit(guildGUID[3]);
+
+ bufferData << uint32(guild->GetEmblemInfo().GetColor());
+ bufferData << uint32(guild->GetEmblemInfo().GetBorderStyle()); // Guessed
+ bufferData << uint32(guild->GetEmblemInfo().GetStyle());
+
+ bufferData.WriteString(guildSettings.GetComment());
+
+ bufferData << uint8(0); // Unk
+
+ bufferData.WriteByteSeq(guildGUID[5]);
+
+ bufferData << uint32(guildSettings.GetInterests());
+
+ bufferData.WriteByteSeq(guildGUID[6]);
+ bufferData.WriteByteSeq(guildGUID[4]);
+
+ bufferData << uint32(guild->GetLevel());
+
+ bufferData.WriteString(guild->GetName());
+
+ bufferData << uint32(guild->GetAchievementMgr().GetAchievementPoints());
+
+ bufferData.WriteByteSeq(guildGUID[7]);
+
+ bufferData << uint8(sGuildFinderMgr->HasRequest(player->GetGUIDLow(), guild->GetGUID())); // Request pending
+
+ bufferData.WriteByteSeq(guildGUID[2]);
+ bufferData.WriteByteSeq(guildGUID[0]);
+
+ bufferData << uint32(guildSettings.GetAvailability());
+
+ bufferData.WriteByteSeq(guildGUID[1]);
+
+ bufferData << uint32(guild->GetEmblemInfo().GetBackgroundColor());
+ bufferData << uint32(0); // Unk Int 2 (+ 128) // Always 0 or 1
+ bufferData << uint32(guild->GetEmblemInfo().GetBorderColor());
+ bufferData << uint32(guildSettings.GetClassRoles());
+
+ bufferData.WriteByteSeq(guildGUID[3]);
+ bufferData << uint32(guild->GetMembersCount());
+ }
+
+ data.FlushBits();
+ data.append(bufferData);
+
+ player->SendDirectMessage(&data);
+}
+
+void WorldSession::HandleGuildFinderDeclineRecruit(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_DECLINE_RECRUIT");
+
+ ObjectGuid playerGuid;
+
+ playerGuid[1] = recvPacket.ReadBit();
+ playerGuid[4] = recvPacket.ReadBit();
+ playerGuid[5] = recvPacket.ReadBit();
+ playerGuid[2] = recvPacket.ReadBit();
+ playerGuid[6] = recvPacket.ReadBit();
+ playerGuid[7] = recvPacket.ReadBit();
+ playerGuid[0] = recvPacket.ReadBit();
+ playerGuid[3] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(playerGuid[5]);
+ recvPacket.ReadByteSeq(playerGuid[7]);
+ recvPacket.ReadByteSeq(playerGuid[2]);
+ recvPacket.ReadByteSeq(playerGuid[3]);
+ recvPacket.ReadByteSeq(playerGuid[4]);
+ recvPacket.ReadByteSeq(playerGuid[1]);
+ recvPacket.ReadByteSeq(playerGuid[0]);
+ recvPacket.ReadByteSeq(playerGuid[6]);
+
+ if (!IS_PLAYER_GUID(playerGuid))
+ return;
+
+ sGuildFinderMgr->RemoveMembershipRequest(GUID_LOPART(playerGuid), GetPlayer()->GetGuildId());
+}
+
+void WorldSession::HandleGuildFinderGetApplications(WorldPacket& /*recvPacket*/)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_GET_APPLICATIONS"); // Empty opcode
+
+ std::list<MembershipRequest> applicatedGuilds = sGuildFinderMgr->GetAllMembershipRequestsForPlayer(GetPlayer()->GetGUIDLow());
+ uint32 applicationsCount = applicatedGuilds.size();
+ WorldPacket data(SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED, 7 + 54 * applicationsCount);
+ data.WriteBits(applicationsCount, 20);
+
+ if (applicationsCount > 0)
+ {
+ ByteBuffer bufferData(54 * applicationsCount);
+ for (std::list<MembershipRequest>::const_iterator itr = applicatedGuilds.begin(); itr != applicatedGuilds.end(); ++itr)
+ {
+ Guild* guild = sGuildMgr->GetGuildById(itr->GetGuildId());
+ LFGuildSettings guildSettings = sGuildFinderMgr->GetGuildSettings(itr->GetGuildId());
+ MembershipRequest request = *itr;
+
+ ObjectGuid guildGuid = ObjectGuid(guild->GetGUID());
+
+ data.WriteBit(guildGuid[1]);
+ data.WriteBit(guildGuid[0]);
+ data.WriteBit(guildGuid[5]);
+ data.WriteBits(request.GetComment().size(), 11);
+ data.WriteBit(guildGuid[3]);
+ data.WriteBit(guildGuid[7]);
+ data.WriteBit(guildGuid[4]);
+ data.WriteBit(guildGuid[6]);
+ data.WriteBit(guildGuid[2]);
+ data.WriteBits(guild->GetName().size(), 8);
+
+ bufferData.WriteByteSeq(guildGuid[2]);
+ bufferData.WriteString(request.GetComment());
+ bufferData.WriteByteSeq(guildGuid[5]);
+ bufferData.WriteString(guild->GetName());
+
+ bufferData << uint32(guildSettings.GetAvailability());
+ bufferData << uint32(request.GetExpiryTime() - time(NULL)); // Time left to application expiry (seconds)
+
+ bufferData.WriteByteSeq(guildGuid[0]);
+ bufferData.WriteByteSeq(guildGuid[6]);
+ bufferData.WriteByteSeq(guildGuid[3]);
+ bufferData.WriteByteSeq(guildGuid[7]);
+
+ bufferData << uint32(guildSettings.GetClassRoles());
+
+ bufferData.WriteByteSeq(guildGuid[4]);
+ bufferData.WriteByteSeq(guildGuid[1]);
+
+ bufferData << uint32(time(NULL) - request.GetSubmitTime()); // Time since application (seconds)
+ bufferData << uint32(guildSettings.GetInterests());
+ }
+
+ data.FlushBits();
+ data.append(bufferData);
+ }
+ data << uint32(10 - sGuildFinderMgr->CountRequestsFromPlayer(GetPlayer()->GetGUIDLow())); // Applications count left
+
+ GetPlayer()->SendDirectMessage(&data);
+}
+
+// Lists all recruits for a guild - Misses times
+void WorldSession::HandleGuildFinderGetRecruits(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_GET_RECRUITS");
+
+ uint32 unkTime = 0;
+ recvPacket >> unkTime;
+
+ Player* player = GetPlayer();
+ if (!player->GetGuildId())
+ return;
+
+ std::vector<MembershipRequest> recruitsList = sGuildFinderMgr->GetAllMembershipRequestsForGuild(player->GetGuildId());
+ uint32 recruitCount = recruitsList.size();
+
+ ByteBuffer dataBuffer(53 * recruitCount);
+ WorldPacket data(SMSG_LF_GUILD_RECRUIT_LIST_UPDATED, 7 + 26 * recruitCount + 53 * recruitCount);
+ data.WriteBits(recruitCount, 20);
+
+ for (std::vector<MembershipRequest>::const_iterator itr = recruitsList.begin(); itr != recruitsList.end(); ++itr)
+ {
+ MembershipRequest request = *itr;
+ ObjectGuid playerGuid(MAKE_NEW_GUID(request.GetPlayerGUID(), 0, HIGHGUID_PLAYER));
+
+ data.WriteBits(request.GetComment().size(), 11);
+ data.WriteBit(playerGuid[2]);
+ data.WriteBit(playerGuid[4]);
+ data.WriteBit(playerGuid[3]);
+ data.WriteBit(playerGuid[7]);
+ data.WriteBit(playerGuid[0]);
+ data.WriteBits(request.GetName().size(), 7);
+ data.WriteBit(playerGuid[5]);
+ data.WriteBit(playerGuid[1]);
+ data.WriteBit(playerGuid[6]);
+
+ dataBuffer.WriteByteSeq(playerGuid[4]);
+
+ dataBuffer << int32(time(NULL) <= request.GetExpiryTime());
+
+ dataBuffer.WriteByteSeq(playerGuid[3]);
+ dataBuffer.WriteByteSeq(playerGuid[0]);
+ dataBuffer.WriteByteSeq(playerGuid[1]);
+
+ dataBuffer << int32(request.GetLevel());
+
+ dataBuffer.WriteByteSeq(playerGuid[6]);
+ dataBuffer.WriteByteSeq(playerGuid[7]);
+ dataBuffer.WriteByteSeq(playerGuid[2]);
+
+ dataBuffer << int32(time(NULL) - request.GetSubmitTime()); // Time in seconds since application submitted.
+ dataBuffer << int32(request.GetAvailability());
+ dataBuffer << int32(request.GetClassRoles());
+ dataBuffer << int32(request.GetInterests());
+ dataBuffer << int32(request.GetExpiryTime() - time(NULL)); // TIme in seconds until application expires.
+
+ dataBuffer.WriteString(request.GetName());
+ dataBuffer.WriteString(request.GetComment());
+
+ dataBuffer << int32(request.GetClass());
+
+ dataBuffer.WriteByteSeq(playerGuid[5]);
+ }
+
+ data.FlushBits();
+ data.append(dataBuffer);
+ data << uint32(time(NULL)); // Unk time
+
+ player->SendDirectMessage(&data);
+}
+
+void WorldSession::HandleGuildFinderPostRequest(WorldPacket& /*recvPacket*/)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_POST_REQUEST"); // Empty opcode
+
+ Player* player = GetPlayer();
+
+ if (!player->GetGuildId()) // Player must be in guild
+ return;
+
+ bool isGuildMaster = true;
+ if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
+ if (guild->GetLeaderGUID() != player->GetGUID())
+ isGuildMaster = false;
+
+ LFGuildSettings settings = sGuildFinderMgr->GetGuildSettings(player->GetGuildId());
+
+ WorldPacket data(SMSG_LF_GUILD_POST_UPDATED, 35);
+ data.WriteBit(isGuildMaster); // Guessed
+
+ if (isGuildMaster)
+ {
+ data.WriteBit(settings.IsListed());
+ data.WriteBits(settings.GetComment().size(), 11);
+ data << uint32(settings.GetLevel());
+ data.WriteString(settings.GetComment());
+ data << uint32(0); // Unk Int32
+ data << uint32(settings.GetAvailability());
+ data << uint32(settings.GetClassRoles());
+ data << uint32(settings.GetInterests());
+ }
+ else
+ data.FlushBits();
+ player->SendDirectMessage(&data);
+}
+
+void WorldSession::HandleGuildFinderRemoveRecruit(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_REMOVE_RECRUIT");
+
+ ObjectGuid guildGuid;
+
+ guildGuid[0] = recvPacket.ReadBit();
+ guildGuid[4] = recvPacket.ReadBit();
+ guildGuid[3] = recvPacket.ReadBit();
+ guildGuid[5] = recvPacket.ReadBit();
+ guildGuid[7] = recvPacket.ReadBit();
+ guildGuid[6] = recvPacket.ReadBit();
+ guildGuid[2] = recvPacket.ReadBit();
+ guildGuid[1] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guildGuid[4]);
+ recvPacket.ReadByteSeq(guildGuid[0]);
+ recvPacket.ReadByteSeq(guildGuid[3]);
+ recvPacket.ReadByteSeq(guildGuid[6]);
+ recvPacket.ReadByteSeq(guildGuid[5]);
+ recvPacket.ReadByteSeq(guildGuid[1]);
+ recvPacket.ReadByteSeq(guildGuid[2]);
+ recvPacket.ReadByteSeq(guildGuid[7]);
+
+ if (!IS_GUILD_GUID(guildGuid))
+ return;
+
+ sGuildFinderMgr->RemoveMembershipRequest(GetPlayer()->GetGUIDLow(), GUID_LOPART(guildGuid));
+}
+
+// Sent any time a guild master sets an option in the interface and when listing / unlisting his guild
+void WorldSession::HandleGuildFinderSetGuildPost(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_SET_GUILD_POST");
+
+ uint32 classRoles = 0;
+ uint32 availability = 0;
+ uint32 guildInterests = 0;
+ uint32 level = 0;
+
+ recvPacket >> level >> availability >> guildInterests >> classRoles;
+ // Level sent is zero if untouched, force to any (from interface). Idk why
+ if (!level)
+ level = ANY_FINDER_LEVEL;
+
+ uint16 length = recvPacket.ReadBits(11);
+ bool listed = recvPacket.ReadBit();
+ std::string comment = recvPacket.ReadString(length);
+
+ if (!(classRoles & GUILDFINDER_ALL_ROLES) || classRoles > GUILDFINDER_ALL_ROLES)
+ return;
+ if (!(availability & AVAILABILITY_ALWAYS) || availability > AVAILABILITY_ALWAYS)
+ return;
+ if (!(guildInterests & ALL_INTERESTS) || guildInterests > ALL_INTERESTS)
+ return;
+ if (!(level & ALL_GUILDFINDER_LEVELS) || level > ALL_GUILDFINDER_LEVELS)
+ return;
+
+ Player* player = GetPlayer();
+
+ if (!player->GetGuildId()) // Player must be in guild
+ return;
+
+ if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId())) // Player must be guild master
+ if (guild->GetLeaderGUID() != player->GetGUID())
+ return;
+
+ LFGuildSettings settings(listed, player->GetTeamId(), player->GetGuildId(), classRoles, availability, guildInterests, level, comment);
+ sGuildFinderMgr->SetGuildSettings(player->GetGuildId(), settings);
+}
diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp
index b652192bfd7..a6e63d196c2 100644
--- a/src/server/game/Handlers/GuildHandler.cpp
+++ b/src/server/game/Handlers/GuildHandler.cpp
@@ -30,29 +30,21 @@
void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket)
{
- uint32 guildId;
- recvPacket >> guildId;
+ uint64 guildGuid, playerGuid;
+ recvPacket >> guildGuid >> playerGuid;
- TC_LOG_DEBUG("guild", "CMSG_GUILD_QUERY [%s]: Guild: %u", GetPlayerInfo().c_str(), guildId);
- if (!guildId)
- return;
-
- if (Guild* guild = sGuildMgr->GetGuildById(guildId))
- guild->HandleQuery(this);
-}
-
-void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket)
-{
- std::string name;
- recvPacket >> name;
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_QUERY [%s]: Guild: %u Target: %u",
+ GetPlayerInfo().c_str(), GUID_LOPART(guildGuid), GUID_LOPART(playerGuid));
- TC_LOG_ERROR("guild", "CMSG_GUILD_CREATE: Possible hacking-attempt: %s tried to create a guild [Name: %s] using cheats", GetPlayerInfo().c_str(), name.c_str());
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
+ if (guild->IsMember(playerGuid))
+ guild->HandleQuery(this);
}
void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket)
{
- std::string invitedName;
- recvPacket >> invitedName;
+ uint32 nameLength = recvPacket.ReadBits(7);
+ std::string invitedName = recvPacket.ReadString(nameLength);
TC_LOG_DEBUG("guild", "CMSG_GUILD_INVITE [%s]: Invited: %s", GetPlayerInfo().c_str(), invitedName.c_str());
if (normalizePlayerName(invitedName))
@@ -62,19 +54,35 @@ void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket)
void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket)
{
- std::string playerName;
- recvPacket >> playerName;
+ ObjectGuid playerGuid;
- TC_LOG_DEBUG("guild", "CMSG_GUILD_REMOVE [%s]: Target: %s", GetPlayerInfo().c_str(), playerName.c_str());
+ playerGuid[6] = recvPacket.ReadBit();
+ playerGuid[5] = recvPacket.ReadBit();
+ playerGuid[4] = recvPacket.ReadBit();
+ playerGuid[0] = recvPacket.ReadBit();
+ playerGuid[1] = recvPacket.ReadBit();
+ playerGuid[3] = recvPacket.ReadBit();
+ playerGuid[7] = recvPacket.ReadBit();
+ playerGuid[2] = recvPacket.ReadBit();
- if (normalizePlayerName(playerName))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleRemoveMember(this, playerName);
+ recvPacket.ReadByteSeq(playerGuid[2]);
+ recvPacket.ReadByteSeq(playerGuid[6]);
+ recvPacket.ReadByteSeq(playerGuid[5]);
+ recvPacket.ReadByteSeq(playerGuid[7]);
+ recvPacket.ReadByteSeq(playerGuid[1]);
+ recvPacket.ReadByteSeq(playerGuid[4]);
+ recvPacket.ReadByteSeq(playerGuid[3]);
+ recvPacket.ReadByteSeq(playerGuid[0]);
+
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_REMOVE [%s]: Target: %u", GetPlayerInfo().c_str(), GUID_LOPART(playerGuid));
+
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleRemoveMember(this, playerGuid);
}
void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/)
{
- TC_LOG_DEBUG("guild", "CMSG_GUILD_ACCEPT [%s]", GetPlayer()->GetName().c_str());
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_ACCEPT [%s]", GetPlayerInfo().c_str());
if (!GetPlayer()->GetGuildId())
if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildIdInvited()))
@@ -89,17 +97,10 @@ void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/)
GetPlayer()->SetInGuild(0);
}
-void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/)
-{
- TC_LOG_DEBUG("guild", "CMSG_GUILD_INFO [%s]", GetPlayerInfo().c_str());
-
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->SendInfo(this);
-}
-
-void WorldSession::HandleGuildRosterOpcode(WorldPacket& /*recvPacket*/)
+void WorldSession::HandleGuildRosterOpcode(WorldPacket& recvPacket)
{
TC_LOG_DEBUG("guild", "CMSG_GUILD_ROSTER [%s]", GetPlayerInfo().c_str());
+ recvPacket.rfinish();
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleRoster(this);
@@ -109,26 +110,107 @@ void WorldSession::HandleGuildRosterOpcode(WorldPacket& /*recvPacket*/)
void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket)
{
- std::string playerName;
- recvPacket >> playerName;
+ ObjectGuid targetGuid;
- TC_LOG_DEBUG("guild", "CMSG_GUILD_PROMOTE [%s]: Target: %s", GetPlayerInfo().c_str(), playerName.c_str());
+ targetGuid[7] = recvPacket.ReadBit();
+ targetGuid[2] = recvPacket.ReadBit();
+ targetGuid[5] = recvPacket.ReadBit();
+ targetGuid[6] = recvPacket.ReadBit();
+ targetGuid[1] = recvPacket.ReadBit();
+ targetGuid[0] = recvPacket.ReadBit();
+ targetGuid[3] = recvPacket.ReadBit();
+ targetGuid[4] = recvPacket.ReadBit();
- if (normalizePlayerName(playerName))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleUpdateMemberRank(this, playerName, false);
+ recvPacket.ReadByteSeq(targetGuid[0]);
+ recvPacket.ReadByteSeq(targetGuid[5]);
+ recvPacket.ReadByteSeq(targetGuid[2]);
+ recvPacket.ReadByteSeq(targetGuid[3]);
+ recvPacket.ReadByteSeq(targetGuid[6]);
+ recvPacket.ReadByteSeq(targetGuid[4]);
+ recvPacket.ReadByteSeq(targetGuid[1]);
+ recvPacket.ReadByteSeq(targetGuid[7]);
+
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_PROMOTE [%s]: Target: %u", GetPlayerInfo().c_str(), GUID_LOPART(targetGuid));
+
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleUpdateMemberRank(this, targetGuid, false);
}
void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket)
{
- std::string playerName;
- recvPacket >> playerName;
+ ObjectGuid targetGuid;
- TC_LOG_DEBUG("guild", "CMSG_GUILD_DEMOTE [%s]: Target: %s", GetPlayerInfo().c_str(), playerName.c_str());
+ targetGuid[7] = recvPacket.ReadBit();
+ targetGuid[1] = recvPacket.ReadBit();
+ targetGuid[5] = recvPacket.ReadBit();
+ targetGuid[6] = recvPacket.ReadBit();
+ targetGuid[2] = recvPacket.ReadBit();
+ targetGuid[3] = recvPacket.ReadBit();
+ targetGuid[0] = recvPacket.ReadBit();
+ targetGuid[4] = recvPacket.ReadBit();
- if (normalizePlayerName(playerName))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleUpdateMemberRank(this, playerName, true);
+ recvPacket.ReadByteSeq(targetGuid[1]);
+ recvPacket.ReadByteSeq(targetGuid[2]);
+ recvPacket.ReadByteSeq(targetGuid[7]);
+ recvPacket.ReadByteSeq(targetGuid[5]);
+ recvPacket.ReadByteSeq(targetGuid[6]);
+ recvPacket.ReadByteSeq(targetGuid[0]);
+ recvPacket.ReadByteSeq(targetGuid[4]);
+ recvPacket.ReadByteSeq(targetGuid[3]);
+
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_DEMOTE [%s]: Target: %u", GetPlayerInfo().c_str(), GUID_LOPART(targetGuid));
+
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleUpdateMemberRank(this, targetGuid, true);
+}
+
+void WorldSession::HandleGuildAssignRankOpcode(WorldPacket& recvPacket)
+{
+ ObjectGuid targetGuid;
+ ObjectGuid setterGuid;
+
+ uint32 rankId;
+ recvPacket >> rankId;
+
+ targetGuid[1] = recvPacket.ReadBit();
+ targetGuid[7] = recvPacket.ReadBit();
+ setterGuid[4] = recvPacket.ReadBit();
+ setterGuid[2] = recvPacket.ReadBit();
+ targetGuid[4] = recvPacket.ReadBit();
+ targetGuid[5] = recvPacket.ReadBit();
+ targetGuid[6] = recvPacket.ReadBit();
+ setterGuid[1] = recvPacket.ReadBit();
+ setterGuid[7] = recvPacket.ReadBit();
+ targetGuid[2] = recvPacket.ReadBit();
+ targetGuid[3] = recvPacket.ReadBit();
+ targetGuid[0] = recvPacket.ReadBit();
+ setterGuid[6] = recvPacket.ReadBit();
+ setterGuid[3] = recvPacket.ReadBit();
+ setterGuid[0] = recvPacket.ReadBit();
+ setterGuid[5] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(targetGuid[0]);
+ recvPacket.ReadByteSeq(setterGuid[1]);
+ recvPacket.ReadByteSeq(setterGuid[3]);
+ recvPacket.ReadByteSeq(setterGuid[5]);
+ recvPacket.ReadByteSeq(targetGuid[7]);
+ recvPacket.ReadByteSeq(targetGuid[3]);
+ recvPacket.ReadByteSeq(setterGuid[0]);
+ recvPacket.ReadByteSeq(targetGuid[1]);
+ recvPacket.ReadByteSeq(setterGuid[6]);
+ recvPacket.ReadByteSeq(targetGuid[2]);
+ recvPacket.ReadByteSeq(targetGuid[5]);
+ recvPacket.ReadByteSeq(targetGuid[4]);
+ recvPacket.ReadByteSeq(setterGuid[2]);
+ recvPacket.ReadByteSeq(setterGuid[4]);
+ recvPacket.ReadByteSeq(targetGuid[6]);
+ recvPacket.ReadByteSeq(setterGuid[7]);
+
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_ASSIGN_MEMBER_RANK [%s]: Target: %u Rank: %u, Issuer: %u",
+ GetPlayerInfo().c_str(), GUID_LOPART(targetGuid), rankId, GUID_LOPART(setterGuid));
+
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleSetMemberRank(this, targetGuid, setterGuid, rankId);
}
void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/)
@@ -147,100 +229,85 @@ void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/)
guild->HandleDisband(this);
}
-void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket)
-{
- std::string name;
- recvPacket >> name;
-
- TC_LOG_DEBUG("guild", "CMSG_GUILD_LEADER [%s]: Target: %s", GetPlayerInfo().c_str(), name.c_str());
-
- if (normalizePlayerName(name))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleSetLeader(this, name);
-}
-
void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket)
{
- std::string motd;
- recvPacket >> motd;
-
+ uint32 motdLength = recvPacket.ReadBits(11);
+ std::string motd = recvPacket.ReadString(motdLength);
TC_LOG_DEBUG("guild", "CMSG_GUILD_MOTD [%s]: MOTD: %s", GetPlayerInfo().c_str(), motd.c_str());
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleSetMOTD(this, motd);
}
-void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket)
+void WorldSession::HandleGuildSetNoteOpcode(WorldPacket& recvPacket)
{
- std::string playerName;
- std::string note;
- recvPacket >> playerName >> note;
+ ObjectGuid playerGuid;
- TC_LOG_DEBUG("guild", "CMSG_GUILD_SET_PUBLIC_NOTE [%s]: Target: %s, Note: %s",
- GetPlayerInfo().c_str(), playerName.c_str(), note.c_str());
-
- if (normalizePlayerName(playerName))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleSetMemberNote(this, playerName, note, true);
-}
+ playerGuid[1] = recvPacket.ReadBit();
+ playerGuid[4] = recvPacket.ReadBit();
+ playerGuid[5] = recvPacket.ReadBit();
+ playerGuid[3] = recvPacket.ReadBit();
+ playerGuid[0] = recvPacket.ReadBit();
+ playerGuid[7] = recvPacket.ReadBit();
+ bool ispublic = recvPacket.ReadBit(); // 0 == Officer, 1 == Public
+ playerGuid[6] = recvPacket.ReadBit();
+ uint32 noteLength = recvPacket.ReadBits(8);
+ playerGuid[2] = recvPacket.ReadBit();
-void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket)
-{
- std::string playerName;
- std::string note;
- recvPacket >> playerName >> note;
+ recvPacket.ReadByteSeq(playerGuid[4]);
+ recvPacket.ReadByteSeq(playerGuid[5]);
+ recvPacket.ReadByteSeq(playerGuid[0]);
+ recvPacket.ReadByteSeq(playerGuid[3]);
+ recvPacket.ReadByteSeq(playerGuid[1]);
+ recvPacket.ReadByteSeq(playerGuid[6]);
+ recvPacket.ReadByteSeq(playerGuid[7]);
+ std::string note = recvPacket.ReadString(noteLength);
+ recvPacket.ReadByteSeq(playerGuid[2]);
- TC_LOG_DEBUG("guild", "CMSG_GUILD_SET_OFFICER_NOTE [%s]: Target: %s, Note: %s",
- GetPlayerInfo().c_str(), playerName.c_str(), note.c_str());
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_SET_NOTE [%s]: Target: %u, Note: %s, Public: %u",
+ GetPlayerInfo().c_str(), GUID_LOPART(playerGuid), note.c_str(), ispublic);
- if (normalizePlayerName(playerName))
- if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleSetMemberNote(this, playerName, note, false);
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleSetMemberNote(this, note, playerGuid, ispublic);
}
-void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket)
+void WorldSession::HandleGuildQueryRanksOpcode(WorldPacket& recvPacket)
{
- uint32 rankId;
- recvPacket >> rankId;
-
- uint32 rights;
- recvPacket >> rights;
-
- std::string rankName;
- recvPacket >> rankName;
-
- uint32 money;
- recvPacket >> money;
-
- TC_LOG_DEBUG("guild", "CMSG_GUILD_RANK [%s]: Rank: %s (%u)", GetPlayerInfo().c_str(), rankName.c_str(), rankId);
+ ObjectGuid guildGuid;
- Guild* guild = GetPlayer()->GetGuild();
- if (!guild)
- {
- recvPacket.rpos(recvPacket.wpos());
- return;
- }
-
- GuildBankRightsAndSlotsVec rightsAndSlots(GUILD_BANK_MAX_TABS);
-
- for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId)
- {
- uint32 bankRights;
- uint32 slots;
+ guildGuid[2] = recvPacket.ReadBit();
+ guildGuid[3] = recvPacket.ReadBit();
+ guildGuid[0] = recvPacket.ReadBit();
+ guildGuid[6] = recvPacket.ReadBit();
+ guildGuid[4] = recvPacket.ReadBit();
+ guildGuid[7] = recvPacket.ReadBit();
+ guildGuid[5] = recvPacket.ReadBit();
+ guildGuid[1] = recvPacket.ReadBit();
- recvPacket >> bankRights;
- recvPacket >> slots;
+ recvPacket.ReadByteSeq(guildGuid[3]);
+ recvPacket.ReadByteSeq(guildGuid[4]);
+ recvPacket.ReadByteSeq(guildGuid[5]);
+ recvPacket.ReadByteSeq(guildGuid[7]);
+ recvPacket.ReadByteSeq(guildGuid[1]);
+ recvPacket.ReadByteSeq(guildGuid[0]);
+ recvPacket.ReadByteSeq(guildGuid[6]);
+ recvPacket.ReadByteSeq(guildGuid[2]);
- rightsAndSlots[tabId] = GuildBankRightsAndSlots(tabId, bankRights, slots);
- }
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_QUERY_RANKS [%s]: Guild: %u",
+ GetPlayerInfo().c_str(), GUID_LOPART(guildGuid));
- guild->HandleSetRankInfo(this, rankId, rankName, rights, money, rightsAndSlots);
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
+ if (guild->IsMember(_player->GetGUID()))
+ guild->SendGuildRankInfo(this);
}
void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket)
{
- std::string rankName;
- recvPacket >> rankName;
+ uint32 rankId;
+ recvPacket >> rankId;
+
+ uint32 length = recvPacket.ReadBits(7);
+ std::string rankName = recvPacket.ReadString(length);
TC_LOG_DEBUG("guild", "CMSG_GUILD_ADD_RANK [%s]: Rank: %s", GetPlayerInfo().c_str(), rankName.c_str());
@@ -248,18 +315,21 @@ void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket)
guild->HandleAddNewRank(this, rankName);
}
-void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/)
+void WorldSession::HandleGuildDelRankOpcode(WorldPacket& recvPacket)
{
- TC_LOG_DEBUG("guild", "CMSG_GUILD_DEL_RANK [%s]", GetPlayerInfo().c_str());
+ uint32 rankId;
+ recvPacket >> rankId;
+
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_DEL_RANK [%s]: Rank: %u", GetPlayerInfo().c_str(), rankId);
if (Guild* guild = GetPlayer()->GetGuild())
- guild->HandleRemoveLowestRank(this);
+ guild->HandleRemoveRank(this, rankId);
}
void WorldSession::HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket)
{
- std::string info;
- recvPacket >> info;
+ uint32 length = recvPacket.ReadBits(12);
+ std::string info = recvPacket.ReadString(length);
TC_LOG_DEBUG("guild", "CMSG_GUILD_INFO_TEXT [%s]: %s", GetPlayerInfo().c_str(), info.c_str());
@@ -304,32 +374,36 @@ void WorldSession::HandleGuildEventLogQueryOpcode(WorldPacket& /* recvPacket */)
guild->SendEventLog(this);
}
-void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPacket & /* recvData */)
+void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPacket& /* recvPacket */)
{
- TC_LOG_DEBUG("guild", "MSG_GUILD_BANK_MONEY_WITHDRAWN [%s]", GetPlayerInfo().c_str());
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_MONEY_WITHDRAWN [%s]", GetPlayerInfo().c_str());
if (Guild* guild = GetPlayer()->GetGuild())
guild->SendMoneyInfo(this);
}
-void WorldSession::HandleGuildPermissions(WorldPacket& /* recvData */)
+void WorldSession::HandleGuildPermissions(WorldPacket& /* recvPacket */)
{
- TC_LOG_DEBUG("guild", "MSG_GUILD_PERMISSIONS [%s]", GetPlayerInfo().c_str());
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_PERMISSIONS [%s]", GetPlayerInfo().c_str());
if (Guild* guild = GetPlayer()->GetGuild())
guild->SendPermissions(this);
}
// Called when clicking on Guild bank gameobject
-void WorldSession::HandleGuildBankerActivate(WorldPacket& recvData)
+void WorldSession::HandleGuildBankerActivate(WorldPacket& recvPacket)
{
uint64 guid;
bool sendAllSlots;
- recvData >> guid >> sendAllSlots;
+ recvPacket >> guid >> sendAllSlots;
TC_LOG_DEBUG("guild", "CMSG_GUILD_BANKER_ACTIVATE [%s]: Go: [" UI64FMTD "] AllSlots: %u"
, GetPlayerInfo().c_str(), guid, sendAllSlots);
+ GameObject const* const go = GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK);
+ if (!go)
+ return;
+
Guild* const guild = GetPlayer()->GetGuild();
if (!guild)
{
@@ -337,33 +411,33 @@ void WorldSession::HandleGuildBankerActivate(WorldPacket& recvData)
return;
}
- guild->SendBankTabsInfo(this, sendAllSlots);
+ guild->SendBankList(this, 0, true, true);
}
// Called when opening guild bank tab only (first one)
-void WorldSession::HandleGuildBankQueryTab(WorldPacket& recvData)
+void WorldSession::HandleGuildBankQueryTab(WorldPacket& recvPacket)
{
uint64 guid;
uint8 tabId;
- bool full;
+ bool sendAllSlots;
- recvData >> guid >> tabId >> full;
+ recvPacket >> guid >> tabId >> sendAllSlots;
- TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_QUERY_TAB [%s]: Go: [" UI64FMTD "], TabId: %u, ShowTabs: %u"
- , GetPlayerInfo().c_str(), guid, tabId, full);
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_QUERY_TAB [%s]: Go: [" UI64FMTD "], TabId: %u, AllSlots: %u"
+ , GetPlayerInfo().c_str(), guid, tabId, sendAllSlots);
if (GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
if (Guild* guild = GetPlayer()->GetGuild())
- guild->SendBankTabData(this, tabId);
+ guild->SendBankList(this, tabId, true, false);
}
-void WorldSession::HandleGuildBankDepositMoney(WorldPacket& recvData)
+void WorldSession::HandleGuildBankDepositMoney(WorldPacket& recvPacket)
{
uint64 guid;
- uint32 money;
- recvData >> guid >> money;
+ uint64 money;
+ recvPacket >> guid >> money;
- TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_DEPOSIT_MONEY [%s]: Go: [" UI64FMTD "], money: %u",
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_DEPOSIT_MONEY [%s]: Go: [" UI64FMTD "], money: " UI64FMTD,
GetPlayerInfo().c_str(), guid, money);
if (GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
@@ -372,13 +446,13 @@ void WorldSession::HandleGuildBankDepositMoney(WorldPacket& recvData)
guild->HandleMemberDepositMoney(this, money);
}
-void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket& recvData)
+void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket& recvPacket)
{
uint64 guid;
- uint32 money;
- recvData >> guid >> money;
+ uint64 money;
+ recvPacket >> guid >> money;
- TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_WITHDRAW_MONEY [%s]: Go: [" UI64FMTD "], money: %u",
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_WITHDRAW_MONEY [%s]: Go: [" UI64FMTD "], money: " UI64FMTD,
GetPlayerInfo().c_str(), guid, money);
if (money && GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
@@ -386,28 +460,28 @@ void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket& recvData)
guild->HandleMemberWithdrawMoney(this, money);
}
-void WorldSession::HandleGuildBankSwapItems(WorldPacket& recvData)
+void WorldSession::HandleGuildBankSwapItems(WorldPacket& recvPacket)
{
TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_SWAP_ITEMS [%s]", GetPlayerInfo().c_str());
uint64 GoGuid;
- recvData >> GoGuid;
+ recvPacket >> GoGuid;
if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
{
- recvData.rfinish(); // Prevent additional spam at rejected packet
+ recvPacket.rfinish(); // Prevent additional spam at rejected packet
return;
}
Guild* guild = GetPlayer()->GetGuild();
if (!guild)
{
- recvData.rfinish(); // Prevent additional spam at rejected packet
+ recvPacket.rfinish(); // Prevent additional spam at rejected packet
return;
}
uint8 bankToBank;
- recvData >> bankToBank;
+ recvPacket >> bankToBank;
uint8 tabId;
uint8 slotId;
@@ -417,18 +491,19 @@ void WorldSession::HandleGuildBankSwapItems(WorldPacket& recvData)
if (bankToBank)
{
uint8 destTabId;
- recvData >> destTabId;
+ recvPacket >> destTabId;
uint8 destSlotId;
- recvData >> destSlotId;
- recvData.read_skip<uint32>(); // Always 0
+ recvPacket >> destSlotId;
- recvData >> tabId;
- recvData >> slotId;
- recvData >> itemEntry;
- recvData.read_skip<uint8>(); // Always 0
+ uint32 destItemEntry;
+ recvPacket >> destItemEntry;
- recvData >> splitedAmount;
+ recvPacket >> tabId;
+ recvPacket >> slotId;
+ recvPacket >> itemEntry;
+ recvPacket.read_skip<uint8>(); // Always 0
+ recvPacket >> splitedAmount;
guild->SwapItems(GetPlayer(), tabId, slotId, destTabId, destSlotId, splitedAmount);
}
@@ -438,97 +513,313 @@ void WorldSession::HandleGuildBankSwapItems(WorldPacket& recvData)
uint8 playerSlotId = NULL_SLOT;
uint8 toChar = 1;
- recvData >> tabId;
- recvData >> slotId;
- recvData >> itemEntry;
+ recvPacket >> tabId;
+ recvPacket >> slotId;
+ recvPacket >> itemEntry;
uint8 autoStore;
- recvData >> autoStore;
+ recvPacket >> autoStore;
if (autoStore)
{
- recvData.read_skip<uint32>(); // autoStoreCount
- recvData.read_skip<uint8>(); // ToChar (?), always and expected to be 1 (autostore only triggered in Bank -> Char)
- recvData.read_skip<uint32>(); // Always 0
+ recvPacket.read_skip<uint32>(); // autoStoreCount
+ recvPacket.read_skip<uint8>(); // ToChar (?), always and expected to be 1 (autostore only triggered in Bank -> Char)
+ recvPacket.read_skip<uint32>(); // Always 0
}
else
{
- recvData >> playerBag;
- recvData >> playerSlotId;
- recvData >> toChar;
- recvData >> splitedAmount;
+ recvPacket >> playerBag;
+ recvPacket >> playerSlotId;
+ recvPacket >> toChar;
+ recvPacket >> splitedAmount;
}
// Player <-> Bank
// Allow to work with inventory only
if (!Player::IsInventoryPos(playerBag, playerSlotId) && !(playerBag == NULL_BAG && playerSlotId == NULL_SLOT))
- GetPlayer()->SendEquipError(EQUIP_ERR_NONE, NULL);
+ GetPlayer()->SendEquipError(EQUIP_ERR_INTERNAL_BAG_ERROR, NULL);
else
guild->SwapItemsWithInventory(GetPlayer(), toChar != 0, tabId, slotId, playerBag, playerSlotId, splitedAmount);
}
}
-void WorldSession::HandleGuildBankBuyTab(WorldPacket& recvData)
+void WorldSession::HandleGuildBankBuyTab(WorldPacket& recvPacket)
{
uint64 guid;
- uint8 tabId;
+ recvPacket >> guid;
- recvData >> guid >> tabId;
+ uint8 tabId;
+ recvPacket >> tabId;
TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_BUY_TAB [%s]: Go: [" UI64FMTD "], TabId: %u", GetPlayerInfo().c_str(), guid, tabId);
-
- if (GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
+ if (!guid || GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleBuyBankTab(this, tabId);
}
-void WorldSession::HandleGuildBankUpdateTab(WorldPacket& recvData)
+void WorldSession::HandleGuildBankUpdateTab(WorldPacket& recvPacket)
{
uint64 guid;
uint8 tabId;
std::string name, icon;
- recvData >> guid >> tabId >> name >> icon;
+ recvPacket >> guid >> tabId >> name >> icon;
TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_UPDATE_TAB [%s]: Go: [" UI64FMTD "], TabId: %u, Name: %s, Icon: %s"
, GetPlayerInfo().c_str(), guid, tabId, name.c_str(), icon.c_str());
-
if (!name.empty() && !icon.empty())
if (GetPlayer()->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_GUILD_BANK))
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleSetBankTabInfo(this, tabId, name, icon);
}
-void WorldSession::HandleGuildBankLogQuery(WorldPacket& recvData)
+void WorldSession::HandleGuildBankLogQuery(WorldPacket& recvPacket)
{
- uint8 tabId;
- recvData >> tabId;
+ uint32 tabId;
+ recvPacket >> tabId;
- TC_LOG_DEBUG("guild", "MSG_GUILD_BANK_LOG_QUERY [%s]: TabId: %u", GetPlayerInfo().c_str(), tabId);
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_LOG_QUERY [%s]: TabId: %u", GetPlayerInfo().c_str(), tabId);
if (Guild* guild = GetPlayer()->GetGuild())
guild->SendBankLog(this, tabId);
}
-void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recvData)
+void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recvPacket)
{
uint8 tabId;
- recvData >> tabId;
+ recvPacket >> tabId;
- TC_LOG_DEBUG("guild", "MSG_QUERY_GUILD_BANK_TEXT [%s]: TabId: %u", GetPlayerInfo().c_str(), tabId);
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_QUERY_TEXT [%s]: TabId: %u", GetPlayerInfo().c_str(), tabId);
if (Guild* guild = GetPlayer()->GetGuild())
guild->SendBankTabText(this, tabId);
}
-void WorldSession::HandleSetGuildBankTabText(WorldPacket &recvData)
+void WorldSession::HandleSetGuildBankTabText(WorldPacket& recvPacket)
{
- uint8 tabId;
- std::string text;
- recvData >> tabId >> text;
+ uint32 tabId;
+ recvPacket >> tabId;
+
+ uint32 textLen = recvPacket.ReadBits(14);
+ std::string text = recvPacket.ReadString(textLen);
TC_LOG_DEBUG("guild", "CMSG_SET_GUILD_BANK_TEXT [%s]: TabId: %u, Text: %s", GetPlayerInfo().c_str(), tabId, text.c_str());
if (Guild* guild = GetPlayer()->GetGuild())
guild->SetBankTabText(tabId, text);
}
+
+void WorldSession::HandleGuildQueryXPOpcode(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUERY_GUILD_XP");
+
+ ObjectGuid guildGuid;
+
+ guildGuid[2] = recvPacket.ReadBit();
+ guildGuid[1] = recvPacket.ReadBit();
+ guildGuid[0] = recvPacket.ReadBit();
+ guildGuid[5] = recvPacket.ReadBit();
+ guildGuid[4] = recvPacket.ReadBit();
+ guildGuid[7] = recvPacket.ReadBit();
+ guildGuid[6] = recvPacket.ReadBit();
+ guildGuid[3] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guildGuid[7]);
+ recvPacket.ReadByteSeq(guildGuid[2]);
+ recvPacket.ReadByteSeq(guildGuid[3]);
+ recvPacket.ReadByteSeq(guildGuid[6]);
+ recvPacket.ReadByteSeq(guildGuid[1]);
+ recvPacket.ReadByteSeq(guildGuid[5]);
+ recvPacket.ReadByteSeq(guildGuid[0]);
+ recvPacket.ReadByteSeq(guildGuid[4]);
+
+ TC_LOG_DEBUG("guild", "CMSG_QUERY_GUILD_XP [%s]: Guild: %u", GetPlayerInfo().c_str(), GUID_LOPART(guildGuid));
+
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
+ if (guild->IsMember(_player->GetGUID()))
+ guild->SendGuildXP(this);
+}
+
+void WorldSession::HandleGuildSetRankPermissionsOpcode(WorldPacket& recvPacket)
+{
+ Guild* guild = GetPlayer()->GetGuild();
+ if (!guild)
+ {
+ recvPacket.rfinish();
+ return;
+ }
+
+ uint32 oldRankId;
+ uint32 newRankId;
+ uint32 oldRights;
+ uint32 newRights;
+ uint32 moneyPerDay;
+
+ recvPacket >> oldRankId;
+ recvPacket >> oldRights;
+ recvPacket >> newRights;
+
+ GuildBankRightsAndSlotsVec rightsAndSlots(GUILD_BANK_MAX_TABS);
+ for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId)
+ {
+ uint32 bankRights;
+ uint32 slots;
+
+ recvPacket >> bankRights;
+ recvPacket >> slots;
+
+ rightsAndSlots[tabId] = GuildBankRightsAndSlots(tabId, uint8(bankRights), slots);
+ }
+
+ recvPacket >> moneyPerDay;
+ recvPacket >> newRankId;
+ uint32 nameLength = recvPacket.ReadBits(7);
+ std::string rankName = recvPacket.ReadString(nameLength);
+
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_SET_RANK_PERMISSIONS [%s]: Rank: %s (%u)", GetPlayerInfo().c_str(), rankName.c_str(), newRankId);
+
+ guild->HandleSetRankInfo(this, newRankId, rankName, newRights, moneyPerDay, rightsAndSlots);
+}
+
+void WorldSession::HandleGuildRequestPartyState(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_GUILD_REQUEST_PARTY_STATE");
+
+ ObjectGuid guildGuid;
+
+ guildGuid[0] = recvPacket.ReadBit();
+ guildGuid[6] = recvPacket.ReadBit();
+ guildGuid[7] = recvPacket.ReadBit();
+ guildGuid[3] = recvPacket.ReadBit();
+ guildGuid[5] = recvPacket.ReadBit();
+ guildGuid[1] = recvPacket.ReadBit();
+ guildGuid[2] = recvPacket.ReadBit();
+ guildGuid[4] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guildGuid[6]);
+ recvPacket.ReadByteSeq(guildGuid[3]);
+ recvPacket.ReadByteSeq(guildGuid[2]);
+ recvPacket.ReadByteSeq(guildGuid[1]);
+ recvPacket.ReadByteSeq(guildGuid[5]);
+ recvPacket.ReadByteSeq(guildGuid[0]);
+ recvPacket.ReadByteSeq(guildGuid[7]);
+ recvPacket.ReadByteSeq(guildGuid[4]);
+
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
+ guild->HandleGuildPartyRequest(this);
+}
+
+void WorldSession::HandleGuildRequestMaxDailyXP(WorldPacket& recvPacket)
+{
+ ObjectGuid guid;
+ guid[0] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[0]);
+
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guid))
+ {
+ if (guild->IsMember(_player->GetGUID()))
+ {
+ WorldPacket data(SMSG_GUILD_MAX_DAILY_XP, 8);
+ data << uint64(sWorld->getIntConfig(CONFIG_GUILD_DAILY_XP_CAP));
+ SendPacket(&data);
+ }
+ }
+}
+
+void WorldSession::HandleAutoDeclineGuildInvites(WorldPacket& recvPacket)
+{
+ uint8 enable;
+ recvPacket >> enable;
+
+ GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_AUTO_DECLINE_GUILD, enable != 0);
+}
+
+void WorldSession::HandleGuildRewardsQueryOpcode(WorldPacket& recvPacket)
+{
+ recvPacket.read_skip<uint32>(); // Unk
+
+ if (sGuildMgr->GetGuildById(_player->GetGuildId()))
+ {
+ std::vector<GuildReward> const& rewards = sGuildMgr->GetGuildRewards();
+
+ WorldPacket data(SMSG_GUILD_REWARDS_LIST, 3 + rewards.size() * (4 + 4 + 4 + 8 + 4 + 4));
+ data.WriteBits(rewards.size(), 21);
+ data.FlushBits();
+
+ for (uint32 i = 0; i < rewards.size(); i++)
+ {
+ data << uint32(rewards[i].Standing);
+ data << int32(rewards[i].Racemask);
+ data << uint32(rewards[i].Entry);
+ data << uint64(rewards[i].Price);
+ data << uint32(0); // Unused
+ data << uint32(rewards[i].AchievementId);
+ }
+ data << uint32(time(NULL));
+ SendPacket(&data);
+ }
+}
+
+void WorldSession::HandleGuildQueryNewsOpcode(WorldPacket& recvPacket)
+{
+ recvPacket.read_skip<uint32>();
+ TC_LOG_DEBUG("guild", "CMSG_GUILD_QUERY_NEWS [%s]", GetPlayerInfo().c_str());
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->SendNewsUpdate(this);
+}
+
+void WorldSession::HandleGuildNewsUpdateStickyOpcode(WorldPacket& recvPacket)
+{
+ uint32 newsId;
+ bool sticky;
+ ObjectGuid guid;
+
+ recvPacket >> newsId;
+
+ guid[2] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ sticky = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[0]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[4]);
+
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleNewsSetSticky(this, newsId, sticky);
+}
+
+void WorldSession::HandleGuildSetGuildMaster(WorldPacket& recvPacket)
+{
+ uint8 nameLength = recvPacket.ReadBits(7);
+ // This is related to guild master inactivity.
+ /*bool isDethrone = */recvPacket.ReadBit();
+ std::string playerName = recvPacket.ReadString(nameLength);
+ if (Guild* guild = GetPlayer()->GetGuild())
+ guild->HandleSetNewGuildMaster(this, playerName);
+}
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index 60966ace011..97a535cd38b 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -27,6 +27,8 @@
#include "UpdateData.h"
#include "ObjectAccessor.h"
#include "SpellInfo.h"
+#include "DB2Stores.h"
+#include <vector>
void WorldSession::HandleSplitItemOpcode(WorldPacket& recvData)
{
@@ -54,7 +56,7 @@ void WorldSession::HandleSplitItemOpcode(WorldPacket& recvData)
if (!_player->IsValidPos(dstbag, dstslot, false)) // can be autostore pos
{
- _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL);
+ _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
return;
}
@@ -81,7 +83,7 @@ void WorldSession::HandleSwapInvItemOpcode(WorldPacket& recvData)
if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0, dstslot, true))
{
- _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL);
+ _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
return;
}
@@ -145,7 +147,7 @@ void WorldSession::HandleSwapItem(WorldPacket& recvData)
if (!_player->IsValidPos(dstbag, dstslot, true))
{
- _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL);
+ _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
return;
}
@@ -260,7 +262,7 @@ void WorldSession::HandleAutoEquipItemOpcode(WorldPacket& recvData)
void WorldSession::HandleDestroyItemOpcode(WorldPacket& recvData)
{
- //TC_LOG_DEBUG("network", "WORLD: CMSG_DESTROYITEM");
+ //TC_LOG_DEBUG("network", "WORLD: CMSG_DESTROY_ITEM");
uint8 bag, slot, count, data1, data2, data3;
recvData >> bag >> slot >> count >> data1 >> data2 >> data3;
@@ -288,7 +290,7 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket& recvData)
if (pItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_INDESTRUCTIBLE)
{
- _player->SendEquipError(EQUIP_ERR_CANT_DROP_SOULBOUND, NULL, NULL);
+ _player->SendEquipError(EQUIP_ERR_DROP_BOUND_ITEM, NULL, NULL);
return;
}
@@ -301,174 +303,11 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket& recvData)
_player->DestroyItem(bag, slot, true);
}
-// Only _static_ data send in this packet !!!
-void WorldSession::HandleItemQuerySingleOpcode(WorldPacket& recvData)
-{
- //TC_LOG_DEBUG("network", "WORLD: CMSG_ITEM_QUERY_SINGLE");
- uint32 item;
- recvData >> item;
-
- TC_LOG_INFO("network", "STORAGE: Item Query = %u", item);
-
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item);
- if (pProto)
- {
- std::string Name = pProto->Name1;
- std::string Description = pProto->Description;
-
- int loc_idx = GetSessionDbLocaleIndex();
- if (loc_idx >= 0)
- {
- if (ItemLocale const* il = sObjectMgr->GetItemLocale(pProto->ItemId))
- {
- ObjectMgr::GetLocaleString(il->Name, loc_idx, Name);
- ObjectMgr::GetLocaleString(il->Description, loc_idx, Description);
- }
- }
- // guess size
- WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600);
- data << pProto->ItemId;
- data << pProto->Class;
- data << pProto->SubClass;
- data << pProto->SoundOverrideSubclass;
- 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);
- data << uint8(0x00); //pProto->Name4; // blizz not send name there, just uint8(0x00);
- data << pProto->DisplayInfoID;
- data << pProto->Quality;
- data << pProto->Flags;
- data << pProto->Flags2;
- data << pProto->BuyPrice;
- data << pProto->SellPrice;
- data << pProto->InventoryType;
- data << pProto->AllowableClass;
- data << pProto->AllowableRace;
- data << pProto->ItemLevel;
- data << pProto->RequiredLevel;
- data << pProto->RequiredSkill;
- data << pProto->RequiredSkillRank;
- data << pProto->RequiredSpell;
- data << pProto->RequiredHonorRank;
- data << pProto->RequiredCityRank;
- data << pProto->RequiredReputationFaction;
- data << pProto->RequiredReputationRank;
- data << int32(pProto->MaxCount);
- data << int32(pProto->Stackable);
- data << pProto->ContainerSlots;
- data << pProto->StatsCount; // item stats count
- for (uint32 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 < MAX_ITEM_PROTO_DAMAGES; ++i)
- {
- data << pProto->Damage[i].DamageMin;
- data << pProto->Damage[i].DamageMax;
- data << pProto->Damage[i].DamageType;
- }
-
- // resistances (7)
- data << pProto->Armor;
- data << pProto->HolyRes;
- data << pProto->FireRes;
- data << pProto->NatureRes;
- data << pProto->FrostRes;
- data << pProto->ShadowRes;
- data << pProto->ArcaneRes;
-
- data << pProto->Delay;
- data << pProto->AmmoType;
- data << pProto->RangedModRange;
-
- for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
- {
- // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown
- // use `item_template` or if not set then only use spell cooldowns
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(pProto->Spells[s].SpellId);
- if (spell)
- {
- bool db_data = pProto->Spells[s].SpellCooldown >= 0 || pProto->Spells[s].SpellCategoryCooldown >= 0;
-
- data << pProto->Spells[s].SpellId;
- data << pProto->Spells[s].SpellTrigger;
- data << uint32(-abs(pProto->Spells[s].SpellCharges));
-
- if (db_data)
- {
- data << uint32(pProto->Spells[s].SpellCooldown);
- data << uint32(pProto->Spells[s].SpellCategory);
- data << uint32(pProto->Spells[s].SpellCategoryCooldown);
- }
- else
- {
- data << uint32(spell->RecoveryTime);
- data << uint32(spell->GetCategory());
- data << uint32(spell->CategoryRecoveryTime);
- }
- }
- else
- {
- data << uint32(0);
- data << uint32(0);
- data << uint32(0);
- data << uint32(-1);
- data << uint32(0);
- data << uint32(-1);
- }
- }
- data << pProto->Bonding;
- data << Description;
- data << pProto->PageText;
- data << pProto->LanguageID;
- data << pProto->PageMaterial;
- data << pProto->StartQuest;
- data << pProto->LockID;
- data << int32(pProto->Material);
- data << pProto->Sheath;
- data << pProto->RandomProperty;
- data << pProto->RandomSuffix;
- data << pProto->Block;
- data << pProto->ItemSet;
- data << pProto->MaxDurability;
- data << pProto->Area;
- data << pProto->Map; // Added in 1.12.x & 2.0.1 client branch
- data << pProto->BagFamily;
- data << pProto->TotemCategory;
- for (int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s)
- {
- data << pProto->Socket[s].Color;
- data << pProto->Socket[s].Content;
- }
- data << pProto->socketBonus;
- data << pProto->GemProperties;
- data << pProto->RequiredDisenchantSkill;
- data << pProto->ArmorDamageModifier;
- data << pProto->Duration; // added in 2.4.2.8209, duration (seconds)
- data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory
- data << pProto->HolidayId; // Holiday.dbc?
- SendPacket(&data);
- }
- else
- {
- TC_LOG_DEBUG("network", "WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", item);
- WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 4);
- data << uint32(item | 0x80000000);
- SendPacket(&data);
- }
-}
-
void WorldSession::HandleReadItem(WorldPacket& recvData)
{
- //TC_LOG_DEBUG("network", "WORLD: CMSG_READ_ITEM");
-
uint8 bag, slot;
recvData >> bag >> slot;
- //TC_LOG_INFO("network", "STORAGE: Read bag = %u, slot = %u", bag, slot);
Item* pItem = _player->GetItemByPos(bag, slot);
if (pItem && pItem->GetTemplate()->PageText)
@@ -478,7 +317,7 @@ void WorldSession::HandleReadItem(WorldPacket& recvData)
InventoryResult msg = _player->CanUseItem(pItem);
if (msg == EQUIP_ERR_OK)
{
- data.Initialize (SMSG_READ_ITEM_OK, 8);
+ data.Initialize(SMSG_READ_ITEM_OK, 8);
TC_LOG_INFO("network", "STORAGE: Item page sent");
}
else
@@ -509,7 +348,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
if (!creature)
{
TC_LOG_DEBUG("network", "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid)));
- _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid);
return;
}
@@ -523,21 +362,21 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
// prevent sell not owner item
if (_player->GetGUID() != pItem->GetOwnerGUID())
{
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
// prevent sell non empty bag by drag-and-drop at vendor's item list
if (pItem->IsNotEmptyBag())
{
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
// prevent sell currently looted item
if (_player->GetLootGUID() == pItem->GetGUID())
{
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
@@ -555,7 +394,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
// prevent sell more items that exist in stack (possible only not from client)
if (count > pItem->GetCount())
{
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
}
@@ -571,7 +410,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
if (!pNewItem)
{
TC_LOG_ERROR("network", "WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count);
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
@@ -598,11 +437,11 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money);
}
else
- _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid);
return;
}
}
- _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, creature, itemguid, 0);
+ _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, creature, itemguid);
return;
}
@@ -618,7 +457,7 @@ void WorldSession::HandleBuybackItem(WorldPacket& recvData)
if (!creature)
{
TC_LOG_DEBUG("network", "WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid)));
- _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
+ _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0);
return;
}
@@ -630,7 +469,7 @@ void WorldSession::HandleBuybackItem(WorldPacket& recvData)
if (pItem)
{
uint32 price = _player->GetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + slot - BUYBACK_SLOT_START);
- if (!_player->HasEnoughMoney(price))
+ if (!_player->HasEnoughMoney(uint64(price)))
{
_player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, pItem->GetEntry(), 0);
return;
@@ -670,24 +509,15 @@ void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket& recvData)
return; // cheating
uint8 bag = NULL_BAG; // init for case invalid bagGUID
-
+ Item* bagItem = NULL;
// find bag slot by bag guid
if (bagguid == _player->GetGUID())
bag = INVENTORY_SLOT_BAG_0;
else
- {
- for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
- {
- if (Bag* pBag = _player->GetBagByPos(i))
- {
- if (bagguid == pBag->GetGUID())
- {
- bag = i;
- break;
- }
- }
- }
- }
+ bagItem = _player->GetItemByGuid(bagguid);
+
+ if (bagItem && bagItem->IsBag())
+ bag = bagItem->GetSlot();
// bag not found, cheating?
if (bag == NULL_BAG)
@@ -699,11 +529,12 @@ void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket& recvData)
void WorldSession::HandleBuyItemOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_BUY_ITEM");
- uint64 vendorguid;
+ uint64 vendorguid, bagGuid;
uint32 item, slot, count;
- uint8 unk1;
+ uint8 itemType; // 1 = item, 2 = currency
+ uint8 bagSlot;
- recvData >> vendorguid >> item >> slot >> count >> unk1;
+ recvData >> vendorguid >> itemType >> item >> slot >> count >> bagGuid >> bagSlot;
// client expects count starting at 1, and we send vendorslot+1 to client already
if (slot > 0)
@@ -711,7 +542,22 @@ void WorldSession::HandleBuyItemOpcode(WorldPacket& recvData)
else
return; // cheating
- GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, NULL_BAG, NULL_SLOT);
+ if (itemType == ITEM_VENDOR_TYPE_ITEM)
+ {
+ Item* bagItem = _player->GetItemByGuid(bagGuid);
+
+ uint8 bag = NULL_BAG;
+ if (bagItem && bagItem->IsBag())
+ bag = bagItem->GetSlot();
+ else if (bagGuid == GetPlayer()->GetGUID()) // The client sends the player guid when trying to store an item in the default backpack
+ bag = INVENTORY_SLOT_BAG_0;
+
+ GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, bag, bagSlot);
+ }
+ else if (itemType == ITEM_VENDOR_TYPE_CURRENCY)
+ GetPlayer()->BuyCurrencyFromVendorSlot(vendorguid, slot, item, count);
+ else
+ TC_LOG_DEBUG("network", "WORLD: received wrong itemType (%u) in HandleBuyItemOpcode", itemType);
}
void WorldSession::HandleListInventoryOpcode(WorldPacket& recvData)
@@ -736,7 +582,7 @@ void WorldSession::SendListInventory(uint64 vendorGuid)
if (!vendor)
{
TC_LOG_DEBUG("network", "WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorGuid)));
- _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
+ _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0);
return;
}
@@ -748,79 +594,155 @@ void WorldSession::SendListInventory(uint64 vendorGuid)
if (vendor->HasUnitState(UNIT_STATE_MOVING))
vendor->StopMoving();
- VendorItemData const* items = vendor->GetVendorItems();
- if (!items)
- {
- WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + 1);
- data << uint64(vendorGuid);
- data << uint8(0); // count == 0, next will be error code
- data << uint8(0); // "Vendor has no inventory"
- SendPacket(&data);
- return;
- }
-
- uint8 itemCount = items->GetItemCount();
- uint8 count = 0;
+ VendorItemData const* vendorItems = vendor->GetVendorItems();
+ uint32 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0;
- WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + itemCount * 8 * 4);
- data << uint64(vendorGuid);
+ //if (rawItemCount > 300),
+ // rawItemCount = 300; // client cap but uint8 max value is 255
- size_t countPos = data.wpos();
- data << uint8(count);
+ ByteBuffer itemsData(32 * rawItemCount);
+ std::vector<bool> enablers;
+ enablers.reserve(2 * rawItemCount);
- float discountMod = _player->GetReputationPriceDiscount(vendor);
-
- for (uint8 slot = 0; slot < itemCount; ++slot)
+ const float discountMod = _player->GetReputationPriceDiscount(vendor);
+ uint8 count = 0;
+ for (uint32 slot = 0; slot < rawItemCount; ++slot)
{
- if (VendorItem const* item = items->GetItem(slot))
+ VendorItem const* vendorItem = vendorItems->GetItem(slot);
+ if (!vendorItem)
+ continue;
+
+ if (vendorItem->Type == ITEM_VENDOR_TYPE_ITEM)
{
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(item->item))
+ ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(vendorItem->item);
+ if (!itemTemplate)
+ continue;
+
+ uint32 leftInStock = !vendorItem->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(vendorItem);
+ if (!_player->IsGameMaster()) // ignore conditions if GM on
{
- if (!(itemTemplate->AllowableClass & _player->getClassMask()) && itemTemplate->Bonding == BIND_WHEN_PICKED_UP && !_player->IsGameMaster())
+ // Respect allowed class
+ if (!(itemTemplate->AllowableClass & _player->getClassMask()) && itemTemplate->Bonding == BIND_WHEN_PICKED_UP)
continue;
- // Only display items in vendor lists for the team the
- // player is on. If GM on, display all items.
- if (!_player->IsGameMaster() && ((itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) || (itemTemplate->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE)))
+
+ // Only display items in vendor lists for the team the player is on
+ if ((itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) ||
+ (itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE))
continue;
// Items sold out are not displayed in list
- uint32 leftInStock = !item->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(item);
- if (!_player->IsGameMaster() && !leftInStock)
+ if (leftInStock == 0)
continue;
+ }
- ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(vendor->GetEntry(), item->item);
- if (!sConditionMgr->IsObjectMeetToConditions(_player, vendor, conditions))
- {
- TC_LOG_DEBUG("condition", "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), item->item);
- continue;
- }
+ ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(vendor->GetEntry(), vendorItem->item);
+ if (!sConditionMgr->IsObjectMeetToConditions(_player, vendor, conditions))
+ {
+ TC_LOG_DEBUG("condition", "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), vendorItem->item);
+ continue;
+ }
- // reputation discount
- int32 price = item->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0;
+ int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0;
- data << uint32(slot + 1); // client expects counting to start at 1
- data << uint32(item->item);
- data << uint32(itemTemplate->DisplayInfoID);
- data << int32(leftInStock);
- data << uint32(price);
- data << uint32(itemTemplate->MaxDurability);
- data << uint32(itemTemplate->BuyCount);
- data << uint32(item->ExtendedCost);
+ if (int32 priceMod = _player->GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES))
+ price -= CalculatePct(price, priceMod);
- if (++count >= MAX_VENDOR_ITEMS)
- break;
+ itemsData << uint32(slot + 1); // client expects counting to start at 1
+ itemsData << uint32(itemTemplate->MaxDurability);
+
+ if (vendorItem->ExtendedCost)
+ {
+ enablers.push_back(0);
+ itemsData << uint32(vendorItem->ExtendedCost);
}
+ else
+ enablers.push_back(1);
+
+ enablers.push_back(1); // item is unlocked
+
+ itemsData << uint32(vendorItem->item);
+ itemsData << uint32(vendorItem->Type); // 1 is items, 2 is currency
+ itemsData << uint32(price);
+ itemsData << uint32(itemTemplate->DisplayInfoID);
+ // if (!unk "enabler") data << uint32(something);
+ itemsData << int32(leftInStock);
+ itemsData << uint32(itemTemplate->BuyCount);
+
+ if (++count >= MAX_VENDOR_ITEMS)
+ break;
}
- }
+ else if (vendorItem->Type == ITEM_VENDOR_TYPE_CURRENCY)
+ {
+ CurrencyTypesEntry const* currencyTemplate = sCurrencyTypesStore.LookupEntry(vendorItem->item);
+ if (!currencyTemplate)
+ continue;
- if (count == 0)
- {
- data << uint8(0);
- SendPacket(&data);
- return;
+ if (!vendorItem->ExtendedCost)
+ continue; // there's no price defined for currencies, only extendedcost is used
+
+ itemsData << uint32(slot + 1); // client expects counting to start at 1
+ itemsData << uint32(0); // max durability
+
+ enablers.push_back(0);
+ itemsData << uint32(vendorItem->ExtendedCost);
+
+ enablers.push_back(1); // item is unlocked
+
+ itemsData << uint32(vendorItem->item);
+ itemsData << uint32(vendorItem->Type); // 1 is items, 2 is currency
+ itemsData << uint32(0); // price, only seen currency types that have Extended cost
+ itemsData << uint32(0); // displayId
+ // if (!unk "enabler") data << uint32(something);
+ itemsData << int32(-1);
+ itemsData << uint32(vendorItem->maxcount);
+
+ if (++count >= MAX_VENDOR_ITEMS)
+ break;
+ }
+ // else error
}
- data.put<uint8>(countPos, count);
+ ObjectGuid guid = vendorGuid;
+
+ WorldPacket data(SMSG_LIST_INVENTORY, 12 + itemsData.size());
+
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[0]);
+
+ data.WriteBits(count, 21); // item count
+
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[7]);
+
+ for (std::vector<bool>::const_iterator itr = enablers.begin(); itr != enablers.end(); ++itr)
+ data.WriteBit(*itr);
+
+ data.WriteBit(guid[4]);
+
+ data.FlushBits();
+ data.append(itemsData);
+
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[6]);
+
+ // It doesn't matter what value is used here (PROBABLY its full vendor size)
+ // What matters is that if count of items we can see is 0 and this field is 1
+ // then client will open the vendor list, otherwise it won't
+ if (rawItemCount)
+ data << uint8(rawItemCount);
+ else
+ data << uint8(vendor->IsArmorer());
+
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[7]);
+
SendPacket(&data);
}
@@ -838,7 +760,7 @@ void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket& recvData)
if (!_player->IsValidPos(dstbag, NULL_SLOT, false)) // can be autostore pos
{
- _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL);
+ _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
return;
}
@@ -867,7 +789,7 @@ void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket& recvData)
if (dest.size() == 1 && dest[0].pos == src)
{
// just remove grey item state
- _player->SendEquipError(EQUIP_ERR_NONE, pItem, NULL);
+ _player->SendEquipError(EQUIP_ERR_INTERNAL_BAG_ERROR, pItem, NULL);
return;
}
@@ -882,8 +804,11 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket)
uint64 guid;
recvPacket >> guid;
+ WorldPacket data(SMSG_BUY_BANK_SLOT_RESULT, 4);
if (!CanUseBank(guid))
{
+ data << uint32(ERR_BANKSLOT_NOTBANKER);
+ SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
return;
}
@@ -897,8 +822,6 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket)
BankBagSlotPricesEntry const* slotEntry = sBankBagSlotPricesStore.LookupEntry(slot);
- WorldPacket data(SMSG_BUY_BANK_SLOT_RESULT, 4);
-
if (!slotEntry)
{
data << uint32(ERR_BANKSLOT_FAILED_TOO_MANY);
@@ -908,7 +831,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket)
uint32 price = slotEntry->price;
- if (!_player->HasEnoughMoney(price))
+ if (!_player->HasEnoughMoney(uint64(price)))
{
data << uint32(ERR_BANKSLOT_INSUFFICIENT_FUNDS);
SendPacket(&data);
@@ -916,7 +839,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket)
}
_player->SetBankBagSlotCount(slot);
- _player->ModifyMoney(-int32(price));
+ _player->ModifyMoney(-int64(price));
data << uint32(ERR_BANKSLOT_OK);
SendPacket(&data);
@@ -952,7 +875,7 @@ void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket)
if (dest.size() == 1 && dest[0].pos == pItem->GetPos())
{
- _player->SendEquipError(EQUIP_ERR_NONE, pItem, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_SWAP, pItem, NULL);
return;
}
@@ -1008,36 +931,9 @@ void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket)
}
}
-void WorldSession::HandleSetAmmoOpcode(WorldPacket& recvData)
-{
- if (!_player->IsAlive())
- {
- _player->SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL);
- return;
- }
-
- TC_LOG_DEBUG("network", "WORLD: CMSG_SET_AMMO");
- uint32 item;
-
- recvData >> item;
-
- if (item)
- {
- if (!_player->GetItemCount(item))
- {
- _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
- return;
- }
-
- _player->SetAmmo(item);
- }
- else
- _player->RemoveAmmo();
-}
-
void WorldSession::SendEnchantmentLog(uint64 target, uint64 caster, uint32 itemId, uint32 enchantId)
{
- WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4)); // last check 2.0.10
+ WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4));
data.appendPackGUID(target);
data.appendPackGUID(caster);
data << uint32(itemId);
@@ -1056,30 +952,6 @@ void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,
SendPacket(&data);
}
-void WorldSession::HandleItemNameQueryOpcode(WorldPacket& recvData)
-{
- uint32 itemid;
- recvData >> itemid;
- recvData.read_skip<uint64>(); // guid
-
- TC_LOG_DEBUG("network", "WORLD: CMSG_ITEM_NAME_QUERY %u", itemid);
- ItemSetNameEntry const* pName = sObjectMgr->GetItemSetNameEntry(itemid);
- if (pName)
- {
- std::string Name = pName->name;
- int loc_idx = GetSessionDbLocaleIndex();
- if (loc_idx >= 0)
- if (ItemSetNameLocale const* isnl = sObjectMgr->GetItemSetNameLocale(itemid))
- ObjectMgr::GetLocaleString(isnl->Name, loc_idx, Name);
-
- WorldPacket data(SMSG_ITEM_NAME_QUERY_RESPONSE, (4+Name.size()+1+4));
- data << uint32(itemid);
- data << Name;
- data << uint32(pName->InventoryType);
- SendPacket(&data);
- }
-}
-
void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "Received opcode CMSG_WRAP_ITEM");
@@ -1114,44 +986,44 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData)
if (item == gift) // not possable with pacjket from real client
{
- _player->SendEquipError(EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_WRAPPED, item, NULL);
return;
}
if (item->IsEquipped())
{
- _player->SendEquipError(EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_EQUIPPED, item, NULL);
return;
}
if (item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR)) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
{
- _player->SendEquipError(EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_WRAPPED, item, NULL);
return;
}
if (item->IsBag())
{
- _player->SendEquipError(EQUIP_ERR_BAGS_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_BAGS, item, NULL);
return;
}
if (item->IsSoulBound())
{
- _player->SendEquipError(EQUIP_ERR_BOUND_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_BOUND, item, NULL);
return;
}
if (item->GetMaxStackCount() != 1)
{
- _player->SendEquipError(EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_STACKABLE, item, NULL);
return;
}
// maybe not correct check (it is better than nothing)
- if (item->GetTemplate()->MaxCount>0)
+ if (item->GetTemplate()->MaxCount > 0)
{
- _player->SendEquipError(EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED, item, NULL);
+ _player->SendEquipError(EQUIP_ERR_CANT_WRAP_UNIQUE, item, NULL);
return;
}
@@ -1257,6 +1129,14 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData)
// tried to put meta gem in normal socket
if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META)
return;
+
+ // tried to put normal gem in cogwheel socket
+ if (itemProto->Socket[i].Color == SOCKET_COLOR_COGWHEEL && GemProps[i]->color != SOCKET_COLOR_COGWHEEL)
+ return;
+
+ // tried to put cogwheel gem in normal socket
+ if (itemProto->Socket[i].Color != SOCKET_COLOR_COGWHEEL && GemProps[i]->color == SOCKET_COLOR_COGWHEEL)
+ return;
}
uint32 GemEnchants[MAX_GEM_SOCKETS];
@@ -1365,7 +1245,10 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData)
{
itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i], 0, 0, _player->GetGUID());
if (Item* guidItem = _player->GetItemByGuid(gem_guids[i]))
- _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true);
+ {
+ uint32 gemCount = 1;
+ _player->DestroyItemCount(guidItem, gemCount, true);
+ }
}
}
@@ -1393,15 +1276,15 @@ void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT");
- uint32 eslot;
+ uint32 slot;
- recvData >> eslot;
+ recvData >> slot;
// apply only to equipped item
- if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, eslot))
+ if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, slot))
return;
- Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, eslot);
+ Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
if (!item)
return;
@@ -1462,7 +1345,7 @@ void WorldSession::HandleItemTextQuery(WorldPacket& recvData )
TC_LOG_DEBUG("network", "CMSG_ITEM_TEXT_QUERY item guid: %u", GUID_LOPART(itemGuid));
- WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, (4+10)); // guess size
+ WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, 14); // guess size
if (Item* item = _player->GetItemByGuid(itemGuid))
{
@@ -1478,6 +1361,289 @@ void WorldSession::HandleItemTextQuery(WorldPacket& recvData )
SendPacket(&data);
}
+void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_TRANSMOGRIFY_ITEMS");
+ Player* player = GetPlayer();
+
+ // Read data
+ uint32 count = recvData.ReadBits(22);
+
+ if (count >= EQUIPMENT_SLOT_END)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) sent a wrong count (%u) when transmogrifying items.", player->GetGUIDLow(), player->GetName().c_str(), count);
+ recvData.rfinish();
+ return;
+ }
+
+ std::vector<ObjectGuid> itemGuids(count, ObjectGuid(0));
+ std::vector<uint32> newEntries(count, 0);
+ std::vector<uint32> slots(count, 0);
+
+ for (uint8 i = 0; i < count; ++i)
+ {
+ itemGuids[i][0] = recvData.ReadBit();
+ itemGuids[i][5] = recvData.ReadBit();
+ itemGuids[i][6] = recvData.ReadBit();
+ itemGuids[i][2] = recvData.ReadBit();
+ itemGuids[i][3] = recvData.ReadBit();
+ itemGuids[i][7] = recvData.ReadBit();
+ itemGuids[i][4] = recvData.ReadBit();
+ itemGuids[i][1] = recvData.ReadBit();
+ }
+
+ ObjectGuid npcGuid;
+ npcGuid[7] = recvData.ReadBit();
+ npcGuid[3] = recvData.ReadBit();
+ npcGuid[5] = recvData.ReadBit();
+ npcGuid[6] = recvData.ReadBit();
+ npcGuid[1] = recvData.ReadBit();
+ npcGuid[4] = recvData.ReadBit();
+ npcGuid[0] = recvData.ReadBit();
+ npcGuid[2] = recvData.ReadBit();
+
+ recvData.FlushBits();
+
+ for (uint32 i = 0; i < count; ++i)
+ {
+ recvData >> newEntries[i];
+
+ recvData.ReadByteSeq(itemGuids[i][1]);
+ recvData.ReadByteSeq(itemGuids[i][5]);
+ recvData.ReadByteSeq(itemGuids[i][0]);
+ recvData.ReadByteSeq(itemGuids[i][4]);
+ recvData.ReadByteSeq(itemGuids[i][6]);
+ recvData.ReadByteSeq(itemGuids[i][7]);
+ recvData.ReadByteSeq(itemGuids[i][3]);
+ recvData.ReadByteSeq(itemGuids[i][2]);
+
+ recvData >> slots[i];
+ }
+
+ recvData.ReadByteSeq(npcGuid[7]);
+ recvData.ReadByteSeq(npcGuid[2]);
+ recvData.ReadByteSeq(npcGuid[5]);
+ recvData.ReadByteSeq(npcGuid[4]);
+ recvData.ReadByteSeq(npcGuid[3]);
+ recvData.ReadByteSeq(npcGuid[1]);
+ recvData.ReadByteSeq(npcGuid[6]);
+ recvData.ReadByteSeq(npcGuid[0]);
+
+ // Validate
+
+ if (!player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_TRANSMOGRIFIER))
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
+ return;
+ }
+
+ int32 cost = 0;
+ for (uint8 i = 0; i < count; ++i)
+ {
+ // slot of the transmogrified item
+ if (slots[i] >= EQUIPMENT_SLOT_END)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify an item (lowguid: %u) with a wrong slot (%u) when transmogrifying items.", player->GetGUIDLow(), player->GetName().c_str(), GUID_LOPART(itemGuids[i]), slots[i]);
+ return;
+ }
+
+ // entry of the transmogrifier item, if it's not 0
+ if (newEntries[i])
+ {
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(newEntries[i]);
+ if (!proto)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify to an invalid item (entry: %u).", player->GetGUIDLow(), player->GetName().c_str(), newEntries[i]);
+ return;
+ }
+ }
+
+ Item* itemTransmogrifier = NULL;
+ // guid of the transmogrifier item, if it's not 0
+ if (itemGuids[i])
+ {
+ itemTransmogrifier = player->GetItemByGuid(itemGuids[i]);
+ if (!itemTransmogrifier)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify with an invalid item (lowguid: %u).", player->GetGUIDLow(), player->GetName().c_str(), GUID_LOPART(itemGuids[i]));
+ return;
+ }
+ }
+
+ // transmogrified item
+ Item* itemTransmogrified = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slots[i]);
+ if (!itemTransmogrified)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify an invalid item in a valid slot (slot: %u).", player->GetGUIDLow(), player->GetName().c_str(), slots[i]);
+ return;
+ }
+
+ // uint16 tempDest;
+ //// has to be able to equip item transmogrified item
+ //if (!player->CanEquipItem(slots[i], tempDest, itemTransmogrified, true, true))
+ //{
+ // TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) can't equip the item to be transmogrified (slot: %u, entry: %u).", player->GetGUIDLow(), player->GetName().c_str(), slots[i], itemTransmogrified->GetEntry());
+ // return;
+ //}
+ //
+ //// has to be able to equip item transmogrifier item
+ //if (!player->CanEquipItem(slots[i], tempDest, itemTransmogrifier, true, true))
+ //{
+ // TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) can't equip the transmogrifier item (slot: %u, entry: %u).", player->GetGUIDLow(), player->GetName().c_str(), slots[i], itemTransmogrifier->GetEntry());
+ // return;
+ //}
+
+ if (!newEntries[i]) // reset look
+ {
+ itemTransmogrified->ClearEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT);
+ player->SetVisibleItemSlot(slots[i], itemTransmogrified);
+ }
+ else
+ {
+ if (itemTransmogrifier->GetEntry() != newEntries[i])
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify with an invalid entry (entry: %u) for item (lowguid: %u).", player->GetGUIDLow(), player->GetName().c_str(), newEntries[i], GUID_LOPART(itemGuids[i]));
+ return;
+ }
+
+ if (!Item::CanTransmogrifyItemWithItem(itemTransmogrified, itemTransmogrifier))
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) failed CanTransmogrifyItemWithItem (%u with %u).", player->GetGUIDLow(), player->GetName().c_str(), itemTransmogrified->GetEntry(), itemTransmogrifier->GetEntry());
+ return;
+ }
+
+ // All okay, proceed
+ itemTransmogrified->SetEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT, newEntries[i], 0, 0);
+ player->SetVisibleItemSlot(slots[i], itemTransmogrified);
+
+ itemTransmogrified->UpdatePlayedTime(player);
+
+ itemTransmogrified->SetOwnerGUID(player->GetGUID());
+ itemTransmogrified->SetNotRefundable(player);
+ itemTransmogrified->ClearSoulboundTradeable(player);
+
+ if (itemTransmogrifier->GetTemplate()->Bonding == BIND_WHEN_EQUIPED || itemTransmogrifier->GetTemplate()->Bonding == BIND_WHEN_USE)
+ itemTransmogrifier->SetBinding(true);
+
+ itemTransmogrifier->SetOwnerGUID(player->GetGUID());
+ itemTransmogrifier->SetNotRefundable(player);
+ itemTransmogrifier->ClearSoulboundTradeable(player);
+
+ cost += itemTransmogrified->GetSpecialPrice();
+ }
+ }
+
+ // trusting the client, if it got here it has to have enough money
+ // ... unless client was modified
+ if (cost) // 0 cost if reverting look
+ player->ModifyMoney(-cost);
+}
+
+void WorldSession::SendReforgeResult(bool success)
+{
+ WorldPacket data(SMSG_REFORGE_RESULT, 1);
+ data.WriteBit(success);
+ data.FlushBits();
+ SendPacket(&data);
+}
+
+void WorldSession::HandleReforgeItemOpcode(WorldPacket& recvData)
+{
+ uint32 slot, reforgeEntry;
+ ObjectGuid guid;
+ uint32 bag;
+ Player* player = GetPlayer();
+
+ recvData >> reforgeEntry >> slot >> bag;
+
+ guid[2] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[5]);
+
+ if (!player->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_REFORGER))
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleReforgeItemOpcode - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(guid));
+ SendReforgeResult(false);
+ return;
+ }
+
+ Item* item = player->GetItemByPos(bag, slot);
+
+ if (!item)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to reforge an invalid/non-existant item.", player->GetGUIDLow(), player->GetName().c_str());
+ SendReforgeResult(false);
+ return;
+ }
+
+ if (!reforgeEntry)
+ {
+ if (!item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT))
+ {
+ TC_LOG_ERROR("network", "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to remove reforge from non-reforged item (Entry: %u)", player->GetGUIDLow(), player->GetName().c_str(), item->GetEntry());
+ SendReforgeResult(false);
+ return;
+ }
+
+ // Reset the item
+ if (item->IsEquipped())
+ player->ApplyReforgeEnchantment(item, false);
+ item->ClearEnchantment(REFORGE_ENCHANTMENT_SLOT);
+ SendReforgeResult(true);
+ return;
+ }
+
+ if (item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT))
+ {
+ TC_LOG_ERROR("network", "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to reforge an already reforged item (Entry: %u)", player->GetGUIDLow(), player->GetName().c_str(), item->GetEntry());
+ SendReforgeResult(false);
+ return;
+ }
+
+ ItemReforgeEntry const* stats = sItemReforgeStore.LookupEntry(reforgeEntry);
+ if (!stats)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to reforge an item with invalid reforge entry (%u).", player->GetGUIDLow(), player->GetName().c_str(), reforgeEntry);
+ SendReforgeResult(false);
+ return;
+ }
+
+ if (!item->GetReforgableStat(ItemModType(stats->SourceStat)) || item->GetReforgableStat(ItemModType(stats->FinalStat))) // Cheating, you cant reforge to a stat that the item already has, nor reforge from a stat that the item does not have
+ {
+ SendReforgeResult(false);
+ return;
+ }
+
+ if (!player->HasEnoughMoney(uint64(item->GetSpecialPrice()))) // cheating
+ {
+ SendReforgeResult(false);
+ return;
+ }
+
+ player->ModifyMoney(-int64(item->GetSpecialPrice()));
+
+ item->SetEnchantment(REFORGE_ENCHANTMENT_SLOT, reforgeEntry, 0, 0);
+
+ SendReforgeResult(true);
+
+ if (item->IsEquipped())
+ player->ApplyReforgeEnchantment(item, true);
+}
+
bool WorldSession::CanUseBank(uint64 bankerGUID) const
{
// bankerGUID parameter is optional, set to 0 by default.
@@ -1494,4 +1660,4 @@ bool WorldSession::CanUseBank(uint64 bankerGUID) const
}
return true;
-} \ No newline at end of file
+}
diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp
index a984c033872..c67d0bbf895 100644
--- a/src/server/game/Handlers/LFGHandler.cpp
+++ b/src/server/game/Handlers/LFGHandler.cpp
@@ -28,8 +28,13 @@ void BuildPlayerLockDungeonBlock(WorldPacket& data, lfg::LfgLockMap const& lock)
data << uint32(lock.size()); // Size of lock dungeons
for (lfg::LfgLockMap::const_iterator it = lock.begin(); it != lock.end(); ++it)
{
- data << uint32(it->first); // Dungeon entry (id + type)
- data << uint32(it->second); // Lock status
+ TC_LOG_TRACE("lfg", "BuildPlayerLockDungeonBlock:: DungeonID: %u Lock status: %u Required itemLevel: %u Current itemLevel: %f",
+ (it->first & 0x00FFFFFF), it->second.lockStatus, it->second.requiredItemLevel, it->second.currentItemLevel);
+
+ data << uint32(it->first); // Dungeon entry (id + type)
+ data << uint32(it->second.lockStatus); // Lock status
+ data << uint32(it->second.requiredItemLevel); // Required itemLevel
+ data << uint32(it->second.currentItemLevel); // Current itemLevel
}
}
@@ -43,6 +48,40 @@ void BuildPartyLockDungeonBlock(WorldPacket& data, lfg::LfgLockPartyMap const& l
}
}
+void BuildQuestReward(WorldPacket& data, Quest const* quest, Player* player)
+{
+ uint8 rewCount = quest->GetRewItemsCount() + quest->GetRewCurrencyCount();
+
+ data << uint32(quest->GetRewOrReqMoney());
+ data << uint32(quest->XPValue(player));
+ data << uint8(rewCount);
+ if (rewCount)
+ {
+ for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ {
+ if (uint32 currencyId = quest->RewardCurrencyId[i])
+ {
+ data << uint32(currencyId);
+ data << uint32(0);
+ data << uint32(quest->RewardCurrencyCount[i]);
+ data << uint8(1); // Is currency
+ }
+ }
+
+ for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ {
+ if (uint32 itemId = quest->RewardItemId[i])
+ {
+ ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId);
+ data << uint32(itemId);
+ data << uint32(item ? item->DisplayInfoID : 0);
+ data << uint32(quest->RewardItemIdCount[i]);
+ data << uint8(0); // Is currency
+ }
+ }
+ }
+}
+
void WorldSession::HandleLfgJoinOpcode(WorldPacket& recvData)
{
if (!sLFGMgr->isOptionEnabled(lfg::LFG_OPTION_ENABLE_DUNGEON_FINDER | lfg::LFG_OPTION_ENABLE_RAID_BROWSER) ||
@@ -53,12 +92,15 @@ void WorldSession::HandleLfgJoinOpcode(WorldPacket& recvData)
return;
}
- uint8 numDungeons;
uint32 roles;
recvData >> roles;
- recvData.read_skip<uint16>(); // uint8 (always 0) - uint8 (always 0)
- recvData >> numDungeons;
+ for (int32 i = 0; i < 3; ++i)
+ recvData.read_skip<uint32>();
+
+ uint32 commentLen = recvData.ReadBits(9);
+ uint32 numDungeons = recvData.ReadBits(24);
+
if (!numDungeons)
{
TC_LOG_DEBUG("lfg", "CMSG_LFG_JOIN %s no dungeons selected", GetPlayerInfo().c_str());
@@ -66,48 +108,113 @@ void WorldSession::HandleLfgJoinOpcode(WorldPacket& recvData)
return;
}
+ std::string comment = recvData.ReadString(commentLen);
+
lfg::LfgDungeonSet newDungeons;
- for (int8 i = 0; i < numDungeons; ++i)
+ for (uint32 i = 0; i < numDungeons; ++i)
{
uint32 dungeon;
recvData >> dungeon;
newDungeons.insert((dungeon & 0x00FFFFFF)); // remove the type from the dungeon entry
}
- recvData.read_skip<uint32>(); // for 0..uint8 (always 3) { uint8 (always 0) }
-
- std::string comment;
- recvData >> comment;
TC_LOG_DEBUG("lfg", "CMSG_LFG_JOIN %s roles: %u, Dungeons: %u, Comment: %s",
GetPlayerInfo().c_str(), roles, uint8(newDungeons.size()), comment.c_str());
sLFGMgr->JoinLfg(GetPlayer(), uint8(roles), newDungeons, comment);
}
-void WorldSession::HandleLfgLeaveOpcode(WorldPacket& /*recvData*/)
+void WorldSession::HandleLfgLeaveOpcode(WorldPacket& recvData)
{
+ ObjectGuid leaveGuid;
Group* group = GetPlayer()->GetGroup();
uint64 guid = GetPlayer()->GetGUID();
uint64 gguid = group ? group->GetGUID() : guid;
- TC_LOG_DEBUG("lfg", "CMSG_LFG_LEAVE %s in group: %u",
- GetPlayerInfo().c_str(), group ? 1 : 0);
+ recvData.read_skip<uint32>(); // Always 8
+ recvData.read_skip<uint32>(); // Join date
+ recvData.read_skip<uint32>(); // Always 3
+ recvData.read_skip<uint32>(); // Queue Id
+
+ leaveGuid[4] = recvData.ReadBit();
+ leaveGuid[5] = recvData.ReadBit();
+ leaveGuid[0] = recvData.ReadBit();
+ leaveGuid[6] = recvData.ReadBit();
+ leaveGuid[2] = recvData.ReadBit();
+ leaveGuid[7] = recvData.ReadBit();
+ leaveGuid[1] = recvData.ReadBit();
+ leaveGuid[3] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(leaveGuid[7]);
+ recvData.ReadByteSeq(leaveGuid[4]);
+ recvData.ReadByteSeq(leaveGuid[3]);
+ recvData.ReadByteSeq(leaveGuid[2]);
+ recvData.ReadByteSeq(leaveGuid[6]);
+ recvData.ReadByteSeq(leaveGuid[0]);
+ recvData.ReadByteSeq(leaveGuid[1]);
+ recvData.ReadByteSeq(leaveGuid[5]);
+
+ TC_LOG_DEBUG("lfg", "CMSG_LFG_LEAVE %s in group: %u sent guid " UI64FMTD ".",
+ GetPlayerInfo().c_str(), group ? 1 : 0, uint64(leaveGuid));
// Check cheating - only leader can leave the queue
- if (!group || group->GetLeaderGUID() == GetPlayer()->GetGUID())
+ if (!group || group->GetLeaderGUID() == guid)
sLFGMgr->LeaveLfg(gguid);
}
void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recvData)
{
- uint32 lfgGroupID; // Internal lfgGroupID
- bool accept; // Accept to join?
- recvData >> lfgGroupID;
- recvData >> accept;
+ uint32 proposalID; // Proposal ID
+ bool accept;
+
+ ObjectGuid guid1;
+ ObjectGuid guid2;
+
+ recvData >> proposalID;
+ recvData.read_skip<uint32>();
+ recvData.read_skip<uint32>();
+ recvData.read_skip<uint32>();
+
+ guid2[4] = recvData.ReadBit();
+ guid2[5] = recvData.ReadBit();
+ guid2[0] = recvData.ReadBit();
+ guid2[6] = recvData.ReadBit();
+ guid2[2] = recvData.ReadBit();
+ guid2[7] = recvData.ReadBit();
+ guid2[1] = recvData.ReadBit();
+ guid2[3] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid2[7]);
+ recvData.ReadByteSeq(guid2[4]);
+ recvData.ReadByteSeq(guid2[3]);
+ recvData.ReadByteSeq(guid2[2]);
+ recvData.ReadByteSeq(guid2[6]);
+ recvData.ReadByteSeq(guid2[0]);
+ recvData.ReadByteSeq(guid2[1]);
+ recvData.ReadByteSeq(guid2[5]);
+
+ guid1[7] = recvData.ReadBit();
+ accept = recvData.ReadBit();
+ guid1[1] = recvData.ReadBit();
+ guid1[3] = recvData.ReadBit();
+ guid1[0] = recvData.ReadBit();
+ guid1[5] = recvData.ReadBit();
+ guid1[4] = recvData.ReadBit();
+ guid1[6] = recvData.ReadBit();
+ guid1[2] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid1[7]);
+ recvData.ReadByteSeq(guid1[1]);
+ recvData.ReadByteSeq(guid1[5]);
+ recvData.ReadByteSeq(guid1[6]);
+ recvData.ReadByteSeq(guid1[3]);
+ recvData.ReadByteSeq(guid1[4]);
+ recvData.ReadByteSeq(guid1[0]);
+ recvData.ReadByteSeq(guid1[2]);
TC_LOG_DEBUG("lfg", "CMSG_LFG_PROPOSAL_RESULT %s proposal: %u accept: %u",
- GetPlayerInfo().c_str(), lfgGroupID, accept ? 1 : 0);
- sLFGMgr->UpdateProposal(lfgGroupID, GetPlayer()->GetGUID(), accept);
+ GetPlayerInfo().c_str(), proposalID, accept ? 1 : 0);
+ sLFGMgr->UpdateProposal(proposalID, GetPlayer()->GetGUID(), accept);
}
void WorldSession::HandleLfgSetRolesOpcode(WorldPacket& recvData)
@@ -160,11 +267,20 @@ void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recvData)
sLFGMgr->TeleportPlayer(GetPlayer(), out, true);
}
-void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recvData*/)
+void WorldSession::HandleLfgGetLockInfoOpcode(WorldPacket& recvData)
+{
+ bool forPlayer = recvData.ReadBit();
+ TC_LOG_DEBUG("lfg", "CMSG_LFG_LOCK_INFO_REQUEST %s for %s", GetPlayerInfo().c_str(), (forPlayer ? "player" : "party"));
+
+ if (forPlayer)
+ SendLfgPlayerLockInfo();
+ else
+ SendLfgPartyLockInfo();
+}
+
+void WorldSession::SendLfgPlayerLockInfo()
{
uint64 guid = GetPlayer()->GetGUID();
- TC_LOG_DEBUG("lfg", "CMSG_LFG_PLAYER_LOCK_INFO_REQUEST %s",
- GetPlayerInfo().c_str());
// Get Random dungeons that can be done at a certain level and expansion
uint8 level = GetPlayer()->getLevel();
@@ -197,45 +313,46 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recvData*
}
}
- if (quest)
+ data << uint8(done);
+ data << uint32(0); // currencyQuantity
+ data << uint32(0); // some sort of overall cap/weekly cap
+ data << uint32(0); // currencyID
+ data << uint32(0); // tier1Quantity
+ data << uint32(0); // tier1Limit
+ data << uint32(0); // overallQuantity
+ data << uint32(0); // overallLimit
+ data << uint32(0); // periodPurseQuantity
+ data << uint32(0); // periodPurseLimit
+ data << uint32(0); // purseQuantity
+ data << uint32(0); // purseLimit
+ data << uint32(0); // some sort of reward for completion
+ data << uint32(0); // completedEncounters
+ data << uint8(0); // Call to Arms eligible
+
+ for (uint32 i = 0; i < 3; ++i)
{
- data << uint8(done);
- data << uint32(quest->GetRewOrReqMoney());
- data << uint32(quest->XPValue(GetPlayer()));
- data << uint32(0);
- data << uint32(0);
- data << uint8(quest->GetRewItemsCount());
- if (quest->GetRewItemsCount())
- {
- for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
- if (uint32 itemId = quest->RewardItemId[i])
- {
- ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId);
- data << uint32(itemId);
- data << uint32(item ? item->DisplayInfoID : 0);
- data << uint32(quest->RewardItemIdCount[i]);
- }
- }
+ data << uint32(0); // Call to Arms Role
+ //if (role)
+ // BuildQuestReward(data, ctaRoleQuest, GetPlayer());
}
+
+ if (quest)
+ BuildQuestReward(data, quest, GetPlayer());
else
{
- data << uint8(0);
- data << uint32(0);
- data << uint32(0);
- data << uint32(0);
- data << uint32(0);
- data << uint8(0);
+ data << uint32(0); // Money
+ data << uint32(0); // XP
+ data << uint8(0); // Reward count
}
}
+
BuildPlayerLockDungeonBlock(data, lock);
SendPacket(&data);
}
-void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recvData*/)
+void WorldSession::SendLfgPartyLockInfo()
{
uint64 guid = GetPlayer()->GetGUID();
- TC_LOG_DEBUG("lfg", "CMSG_LFG_PARTY_LOCK_INFO_REQUEST %s", GetPlayerInfo().c_str());
-
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
@@ -257,7 +374,7 @@ void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recvData*
uint32 size = 0;
for (lfg::LfgLockPartyMap::const_iterator it = lockMap.begin(); it != lockMap.end(); ++it)
- size += 8 + 4 + uint32(it->second.size()) * (4 + 4);
+ size += 8 + 4 + uint32(it->second.size()) * (4 + 4 + 4 + 4);
TC_LOG_DEBUG("lfg", "SMSG_LFG_PARTY_INFO %s", GetPlayerInfo().c_str());
WorldPacket data(SMSG_LFG_PARTY_INFO, 1 + size);
@@ -287,71 +404,45 @@ void WorldSession::HandleLfgGetStatus(WorldPacket& /*recvData*/)
{
TC_LOG_DEBUG("lfg", "CMSG_LFG_GET_STATUS %s", GetPlayerInfo().c_str());
+ if (!GetPlayer()->isUsingLfg())
+ return;
+
uint64 guid = GetPlayer()->GetGUID();
lfg::LfgUpdateData updateData = sLFGMgr->GetLfgStatus(guid);
if (GetPlayer()->GetGroup())
{
- SendLfgUpdateParty(updateData);
+ SendLfgUpdateStatus(updateData, true);
updateData.dungeons.clear();
- SendLfgUpdatePlayer(updateData);
+ SendLfgUpdateStatus(updateData, false);
}
else
{
- SendLfgUpdatePlayer(updateData);
+ SendLfgUpdateStatus(updateData, false);
updateData.dungeons.clear();
- SendLfgUpdateParty(updateData);
+ SendLfgUpdateStatus(updateData, true);
}
}
-void WorldSession::SendLfgUpdatePlayer(lfg::LfgUpdateData const& updateData)
-{
- bool queued = false;
- uint8 size = uint8(updateData.dungeons.size());
-
- switch (updateData.updateType)
- {
- case lfg::LFG_UPDATETYPE_JOIN_QUEUE:
- case lfg::LFG_UPDATETYPE_ADDED_TO_QUEUE:
- queued = true;
- break;
- case lfg::LFG_UPDATETYPE_UPDATE_STATUS:
- queued = updateData.state == lfg::LFG_STATE_QUEUED;
- break;
- default:
- break;
- }
-
- TC_LOG_DEBUG("lfg", "SMSG_LFG_UPDATE_PLAYER %s updatetype: %u",
- GetPlayerInfo().c_str(), updateData.updateType);
- WorldPacket data(SMSG_LFG_UPDATE_PLAYER, 1 + 1 + (size > 0 ? 1 : 0) * (1 + 1 + 1 + 1 + size * 4 + updateData.comment.length()));
- data << uint8(updateData.updateType); // Lfg Update type
- data << uint8(size > 0); // Extra info
- if (size)
- {
- data << uint8(queued); // Join the queue
- data << uint8(0); // unk - Always 0
- data << uint8(0); // unk - Always 0
-
- data << uint8(size);
- for (lfg::LfgDungeonSet::const_iterator it = updateData.dungeons.begin(); it != updateData.dungeons.end(); ++it)
- data << uint32(*it);
- data << updateData.comment;
- }
- SendPacket(&data);
-}
-
-void WorldSession::SendLfgUpdateParty(const lfg::LfgUpdateData& updateData)
+void WorldSession::SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, bool party)
{
bool join = false;
bool queued = false;
uint8 size = uint8(updateData.dungeons.size());
+ ObjectGuid guid = _player->GetGUID();
+ time_t joinTime = sLFGMgr->GetQueueJoinTime(_player->GetGUID());
+ uint32 queueId = sLFGMgr->GetQueueId(_player->GetGUID());
switch (updateData.updateType)
{
+ case lfg::LFG_UPDATETYPE_JOIN_QUEUE_INITIAL: // Joined queue outside the dungeon
+ join = true;
+ break;
+ case lfg::LFG_UPDATETYPE_JOIN_QUEUE:
case lfg::LFG_UPDATETYPE_ADDED_TO_QUEUE: // Rolecheck Success
+ join = true;
queued = true;
- // no break on purpose
+ break;
case lfg::LFG_UPDATETYPE_PROPOSAL_BEGIN:
join = true;
break;
@@ -363,25 +454,44 @@ void WorldSession::SendLfgUpdateParty(const lfg::LfgUpdateData& updateData)
break;
}
- TC_LOG_DEBUG("lfg", "SMSG_LFG_UPDATE_PARTY %s updatetype: %u",
- GetPlayerInfo().c_str(), updateData.updateType);
- WorldPacket data(SMSG_LFG_UPDATE_PARTY, 1 + 1 + (size > 0 ? 1 : 0) * (1 + 1 + 1 + 1 + 1 + size * 4 + updateData.comment.length()));
+ TC_LOG_DEBUG("lfg", "SMSG_LFG_UPDATE_STATUS %s updatetype: %u, party %s",
+ GetPlayerInfo().c_str(), updateData.updateType, party ? "true" : "false");
+
+ WorldPacket data(SMSG_LFG_UPDATE_STATUS, 1 + 8 + 3 + 2 + 1 + updateData.comment.length() + 4 + 4 + 1 + 1 + 1 + 4 + size);
+ data.WriteBit(guid[1]);
+ data.WriteBit(party);
+ data.WriteBits(size, 24);
+ data.WriteBit(guid[6]);
+ data.WriteBit(size > 0); // Extra info
+ data.WriteBits(updateData.comment.length(), 9);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(join); // LFG Join
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(queued); // Join the queue
+
data << uint8(updateData.updateType); // Lfg Update type
- data << uint8(size > 0); // Extra info
- if (size)
- {
- data << uint8(join); // LFG Join
- data << uint8(queued); // Join the queue
+ data.WriteString(updateData.comment);
+ data << uint32(queueId); // Queue Id
+ data << uint32(joinTime); // Join date
+ data.WriteByteSeq(guid[6]);
+ for (uint8 i = 0; i < 3; ++i)
data << uint8(0); // unk - Always 0
- data << uint8(0); // unk - Always 0
- for (uint8 i = 0; i < 3; ++i)
- data << uint8(0); // unk - Always 0
- data << uint8(size);
- for (lfg::LfgDungeonSet::const_iterator it = updateData.dungeons.begin(); it != updateData.dungeons.end(); ++it)
- data << uint32(*it);
- data << updateData.comment;
- }
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[0]);
+ data << uint32(3);
+ data.WriteByteSeq(guid[7]);
+ for (lfg::LfgDungeonSet::const_iterator it = updateData.dungeons.begin(); it != updateData.dungeons.end(); ++it)
+ data << uint32(*it);
+
SendPacket(&data);
}
@@ -421,10 +531,10 @@ void WorldSession::SendLfgRoleCheckUpdate(lfg::LfgRoleCheck const& roleCheck)
// Leader info MUST be sent 1st :S
uint64 guid = roleCheck.leader;
uint8 roles = roleCheck.roles.find(guid)->second;
+ Player* player = ObjectAccessor::FindPlayer(guid);
data << uint64(guid); // Guid
data << uint8(roles > 0); // Ready
data << uint32(roles); // Roles
- Player* player = ObjectAccessor::FindPlayer(guid);
data << uint8(player ? player->getLevel() : 0); // Level
for (lfg::LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it)
@@ -434,10 +544,10 @@ void WorldSession::SendLfgRoleCheckUpdate(lfg::LfgRoleCheck const& roleCheck)
guid = it->first;
roles = it->second;
+ player = ObjectAccessor::FindPlayer(guid);
data << uint64(guid); // Guid
data << uint8(roles > 0); // Ready
data << uint32(roles); // Roles
- player = ObjectAccessor::FindPlayer(guid);
data << uint8(player ? player->getLevel() : 0);// Level
}
}
@@ -447,17 +557,76 @@ void WorldSession::SendLfgRoleCheckUpdate(lfg::LfgRoleCheck const& roleCheck)
void WorldSession::SendLfgJoinResult(lfg::LfgJoinResultData const& joinData)
{
uint32 size = 0;
+ ObjectGuid guid = GetPlayer()->GetGUID();
+ uint32 queueId = sLFGMgr->GetQueueId(_player->GetGUID());
for (lfg::LfgLockPartyMap::const_iterator it = joinData.lockmap.begin(); it != joinData.lockmap.end(); ++it)
- size += 8 + 4 + uint32(it->second.size()) * (4 + 4);
+ size += 8 + 4 + uint32(it->second.size()) * (4 + 4 + 4 + 4);
TC_LOG_DEBUG("lfg", "SMSG_LFG_JOIN_RESULT %s checkResult: %u checkValue: %u",
GetPlayerInfo().c_str(), joinData.result, joinData.state);
WorldPacket data(SMSG_LFG_JOIN_RESULT, 4 + 4 + size);
- data << uint32(joinData.result); // Check Result
- data << uint32(joinData.state); // Check Value
- if (!joinData.lockmap.empty())
- BuildPartyLockDungeonBlock(data, joinData.lockmap);
+ data << uint32(3);
+ data << uint8(joinData.result); // Check Result
+ data << uint32(queueId); // Queue Id
+ data << uint8(joinData.state); // Check Value
+ data << uint32(time(NULL)); // Join date
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[0]);
+ data.WriteBits(joinData.lockmap.size(), 24);
+ for (lfg::LfgLockPartyMap::const_iterator it = joinData.lockmap.begin(); it != joinData.lockmap.end(); ++it)
+ {
+ ObjectGuid playerGuid = it->first;
+ data.WriteBit(playerGuid[7]);
+ data.WriteBit(playerGuid[5]);
+ data.WriteBit(playerGuid[3]);
+ data.WriteBit(playerGuid[6]);
+ data.WriteBit(playerGuid[0]);
+ data.WriteBit(playerGuid[2]);
+ data.WriteBit(playerGuid[4]);
+ data.WriteBit(playerGuid[1]);
+ data.WriteBits(it->second.size(), 22);
+ }
+
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[6]);
+ for (lfg::LfgLockPartyMap::const_iterator it = joinData.lockmap.begin(); it != joinData.lockmap.end(); ++it)
+ {
+ ObjectGuid playerGuid = it->first;
+ for (lfg::LfgLockMap::const_iterator itr = it->second.begin(); itr != it->second.end(); ++itr)
+ {
+ TC_LOG_TRACE("lfg", "SendLfgJoinResult:: PlayerGUID: " UI64FMTD " DungeonID: %u Lock status: %u Required itemLevel: %u Current itemLevel: %f",
+ uint64(playerGuid), (itr->first & 0x00FFFFFF), itr->second.lockStatus, itr->second.requiredItemLevel, itr->second.currentItemLevel);
+
+ data << uint32(itr->second.lockStatus); // Lock status
+ data << uint32(itr->second.currentItemLevel); // Current itemLevel
+ data << uint32(itr->second.requiredItemLevel); // Required itemLevel
+ data << uint32(itr->first); // Dungeon entry (id + type)
+ }
+
+ data.WriteByteSeq(playerGuid[2]);
+ data.WriteByteSeq(playerGuid[5]);
+ data.WriteByteSeq(playerGuid[1]);
+ data.WriteByteSeq(playerGuid[0]);
+ data.WriteByteSeq(playerGuid[4]);
+ data.WriteByteSeq(playerGuid[3]);
+ data.WriteByteSeq(playerGuid[6]);
+ data.WriteByteSeq(playerGuid[7]);
+ }
+
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[0]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[6]);
+
SendPacket(&data);
}
@@ -470,17 +639,39 @@ void WorldSession::SendLfgQueueStatus(lfg::LfgQueueStatusData const& queueData)
queueData.waitTimeTank, queueData.waitTimeHealer, queueData.waitTimeDps,
queueData.queuedTime, queueData.tanks, queueData.healers, queueData.dps);
- WorldPacket data(SMSG_LFG_QUEUE_STATUS, 4 + 4 + 4 + 4 + 4 +4 + 1 + 1 + 1 + 4);
- data << uint32(queueData.dungeonId); // Dungeon
- data << int32(queueData.waitTimeAvg); // Average Wait time
- data << int32(queueData.waitTime); // Wait Time
- data << int32(queueData.waitTimeTank); // Wait Tanks
- data << int32(queueData.waitTimeHealer); // Wait Healers
- data << int32(queueData.waitTimeDps); // Wait Dps
+ ObjectGuid guid = _player->GetGUID();
+ WorldPacket data(SMSG_LFG_QUEUE_STATUS, 4 + 4 + 4 + 4 + 4 + 4 + 1 + 1 + 1 + 4 + 4 + 4 + 4 + 8);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[7]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[4]);
+
+ data.WriteByteSeq(guid[0]);
data << uint8(queueData.tanks); // Tanks needed
+ data << int32(queueData.waitTimeTank); // Wait Tanks
data << uint8(queueData.healers); // Healers needed
+ data << int32(queueData.waitTimeHealer); // Wait Healers
data << uint8(queueData.dps); // Dps needed
+ data << int32(queueData.waitTimeDps); // Wait Dps
+ data.WriteByteSeq(guid[4]);
+ data.WriteByteSeq(guid[6]);
+ data << int32(queueData.waitTime); // Wait Time
+ data << uint32(queueData.joinTime); // Join time
+ data << uint32(queueData.dungeonId); // Dungeon
data << uint32(queueData.queuedTime); // Player wait time in queue
+ data.WriteByteSeq(guid[5]);
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[3]);
+ data << uint32(queueData.queueId); // Queue Id
+ data.WriteByteSeq(guid[1]);
+ data.WriteByteSeq(guid[2]);
+ data << int32(queueData.waitTimeAvg); // Average Wait time
+ data << uint32(3);
+
SendPacket(&data);
}
@@ -492,29 +683,12 @@ void WorldSession::SendLfgPlayerReward(lfg::LfgPlayerRewardData const& rewardDat
TC_LOG_DEBUG("lfg", "SMSG_LFG_PLAYER_REWARD %s rdungeonEntry: %u, sdungeonEntry: %u, done: %u",
GetPlayerInfo().c_str(), rewardData.rdungeonEntry, rewardData.sdungeonEntry, rewardData.done);
- uint8 itemNum = rewardData.quest->GetRewItemsCount();
+ uint8 itemNum = rewardData.quest->GetRewItemsCount() + rewardData.quest->GetRewCurrencyCount();
WorldPacket data(SMSG_LFG_PLAYER_REWARD, 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 + 1 + itemNum * (4 + 4 + 4));
- data << uint32(rewardData.rdungeonEntry); // Random Dungeon Finished
- data << uint32(rewardData.sdungeonEntry); // Dungeon Finished
- data << uint8(rewardData.done);
- data << uint32(1);
- data << uint32(rewardData.quest->GetRewOrReqMoney());
- data << uint32(rewardData.quest->XPValue(GetPlayer()));
- data << uint32(0);
- data << uint32(0);
- data << uint8(itemNum);
- if (itemNum)
- {
- for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
- if (uint32 itemId = rewardData.quest->RewardItemId[i])
- {
- ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId);
- data << uint32(itemId);
- data << uint32(item ? item->DisplayInfoID : 0);
- data << uint32(rewardData.quest->RewardItemIdCount[i]);
- }
- }
+ data << uint32(rewardData.rdungeonEntry); // Random Dungeon Finished
+ data << uint32(rewardData.sdungeonEntry); // Dungeon Finished
+ BuildQuestReward(data, rewardData.quest, GetPlayer());
SendPacket(&data);
}
@@ -540,16 +714,17 @@ void WorldSession::SendLfgBootProposalUpdate(lfg::LfgPlayerBoot const& boot)
GetPlayerInfo().c_str(), uint8(boot.inProgress), uint8(playerVote != lfg::LFG_ANSWER_PENDING),
uint8(playerVote == lfg::LFG_ANSWER_AGREE), GUID_LOPART(boot.victim), votesNum, agreeNum,
secsleft, lfg::LFG_GROUP_KICK_VOTES_NEEDED, boot.reason.c_str());
- WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + boot.reason.length());
- data << uint8(boot.inProgress); // Vote in progress
- data << uint8(playerVote != lfg::LFG_ANSWER_PENDING); // Did Vote
- data << uint8(playerVote == lfg::LFG_ANSWER_AGREE); // Agree
- data << uint64(boot.victim); // Victim GUID
- data << uint32(votesNum); // Total Votes
- data << uint32(agreeNum); // Agree Count
- data << uint32(secsleft); // Time Left
- data << uint32(lfg::LFG_GROUP_KICK_VOTES_NEEDED); // Needed Votes
- data << boot.reason.c_str(); // Kick reason
+ WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + boot.reason.length());
+ data << uint8(boot.inProgress); // Vote in progress
+ data << uint8(agreeNum >= lfg::LFG_GROUP_KICK_VOTES_NEEDED); // Did succeed
+ data << uint8(playerVote != lfg::LFG_ANSWER_PENDING); // Did Vote
+ data << uint8(playerVote == lfg::LFG_ANSWER_AGREE); // Agree
+ data << uint64(boot.victim); // Victim GUID
+ data << uint32(votesNum); // Total Votes
+ data << uint32(agreeNum); // Agree Count
+ data << uint32(secsleft); // Time Left
+ data << uint32(lfg::LFG_GROUP_KICK_VOTES_NEEDED); // Needed Votes
+ data << boot.reason.c_str(); // Kick reason
SendPacket(&data);
}
@@ -559,6 +734,8 @@ void WorldSession::SendLfgUpdateProposal(lfg::LfgProposal const& proposal)
uint64 gguid = proposal.players.find(guid)->second.group;
bool silent = !proposal.isNew && gguid == proposal.group;
uint32 dungeonEntry = proposal.dungeonId;
+ uint32 queueId = sLFGMgr->GetQueueId(_player->GetGUID());
+ time_t joinTime = sLFGMgr->GetQueueJoinTime(_player->GetGUID());
TC_LOG_DEBUG("lfg", "SMSG_LFG_PROPOSAL_UPDATE %s state: %u",
GetPlayerInfo().c_str(), proposal.state);
@@ -574,31 +751,81 @@ void WorldSession::SendLfgUpdateProposal(lfg::LfgProposal const& proposal)
dungeonEntry = sLFGMgr->GetLFGDungeonEntry(dungeonEntry);
WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + proposal.players.size() * (4 + 1 + 1 + 1 + 1 +1));
+ data << uint32(joinTime);
+ data << uint32(proposal.encounters); // Encounters done
+ data << uint32(queueId); // Queue Id
+ data << uint32(3); // Always 3
data << uint32(dungeonEntry); // Dungeon
- data << uint8(proposal.state); // Proposal state
- data << uint32(proposal.id); // Proposal ID
- data << uint32(proposal.encounters); // encounters done
- data << uint8(silent); // Show proposal window
- data << uint8(proposal.players.size()); // Group size
+ data << uint32(proposal.id); // Proposal Id
+ data << uint8(proposal.state); // State
+
+ ObjectGuid guid1 = guid;
+ ObjectGuid guid2 = gguid;
+
+ data.WriteBit(guid2[4]);
+ data.WriteBit(guid1[3]);
+ data.WriteBit(guid1[7]);
+ data.WriteBit(guid1[0]);
+ data.WriteBit(guid2[1]);
+ data.WriteBit(silent);
+ data.WriteBit(guid1[4]);
+ data.WriteBit(guid1[5]);
+ data.WriteBit(guid2[3]);
+ data.WriteBits(proposal.players.size(), 23);
+ data.WriteBit(guid2[7]);
for (lfg::LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
{
lfg::LfgProposalPlayer const& player = it->second;
- data << uint32(player.role); // Role
- data << uint8(it->first == guid); // Self player
- if (!player.group) // Player not it a group
+
+ if (!player.group)
{
- data << uint8(0); // Not in dungeon
- data << uint8(0); // Not same group
+ data.WriteBit(0);
+ data.WriteBit(0);
}
else
{
- data << uint8(player.group == proposal.group); // In dungeon (silent)
- data << uint8(player.group == gguid); // Same Group than player
+ data.WriteBit(player.group == proposal.group); // Is group in dungeon
+ data.WriteBit(player.group == gguid); // Same group as the player
}
- data << uint8(player.accept != lfg::LFG_ANSWER_PENDING);// Answered
- data << uint8(player.accept == lfg::LFG_ANSWER_AGREE); // Accepted
+
+ data.WriteBit(player.accept == lfg::LFG_ANSWER_AGREE);
+ data.WriteBit(player.accept != lfg::LFG_ANSWER_PENDING);
+ data.WriteBit(it->first == guid);
}
+
+ data.WriteBit(guid2[5]);
+ data.WriteBit(guid1[6]);
+ data.WriteBit(guid2[2]);
+ data.WriteBit(guid2[6]);
+ data.WriteBit(guid1[2]);
+ data.WriteBit(guid1[1]);
+ data.WriteBit(guid2[0]);
+
+ data.WriteByteSeq(guid1[5]);
+ data.WriteByteSeq(guid2[3]);
+ data.WriteByteSeq(guid2[6]);
+ data.WriteByteSeq(guid1[6]);
+ data.WriteByteSeq(guid1[0]);
+ data.WriteByteSeq(guid2[5]);
+ data.WriteByteSeq(guid1[1]);
+
+ for (lfg::LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
+ {
+ lfg::LfgProposalPlayer const& player = it->second;
+ data << uint32(player.role);
+ }
+
+ data.WriteByteSeq(guid2[7]);
+ data.WriteByteSeq(guid1[4]);
+ data.WriteByteSeq(guid2[0]);
+ data.WriteByteSeq(guid2[1]);
+ data.WriteByteSeq(guid1[2]);
+ data.WriteByteSeq(guid1[7]);
+ data.WriteByteSeq(guid2[2]);
+ data.WriteByteSeq(guid1[3]);
+ data.WriteByteSeq(guid2[4]);
+
SendPacket(&data);
}
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index b9c6f349ac3..7c3d9e99eee 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -22,6 +22,7 @@
#include "Creature.h"
#include "GameObject.h"
#include "Group.h"
+#include "GuildMgr.h"
#include "LootMgr.h"
#include "ObjectAccessor.h"
#include "Object.h"
@@ -186,6 +187,10 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
(*i)->ModifyMoney(goldPerPlayer);
(*i)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer);
+ if (Guild* guild = sGuildMgr->GetGuildById((*i)->GetGuildId()))
+ if (uint32 guildGold = CalculatePct(goldPerPlayer, (*i)->GetTotalAuraModifier(SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT)))
+ guild->HandleMemberDepositMoney(this, guildGold, true);
+
WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1);
data << uint32(goldPerPlayer);
data << uint8(playersNear.size() <= 1); // Controls the text displayed in chat. 0 is "Your share is..." and 1 is "You loot..."
@@ -197,6 +202,10 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
player->ModifyMoney(loot->gold);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold);
+ if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
+ if (uint32 guildGold = CalculatePct(loot->gold, player->GetTotalAuraModifier(SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT)))
+ guild->HandleMemberDepositMoney(this, guildGold, true);
+
WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1);
data << uint32(loot->gold);
data << uint8(1); // "You loot..."
@@ -447,7 +456,7 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData)
ItemPosCountVec dest;
InventoryResult msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count);
if (item.follow_loot_rules && !item.AllowedForPlayer(target))
- msg = EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+ msg = EQUIP_ERR_CANT_EQUIP_EVER;
if (msg != EQUIP_ERR_OK)
{
target->SendEquipError(msg, NULL, NULL, item.itemid);
@@ -463,7 +472,7 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData)
Item* newitem = target->StoreNewItem(dest, item.itemid, true, item.randomPropertyId, looters);
target->SendNewItem(newitem, uint32(item.count), false, false, true);
target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count);
- target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, loot->loot_type, item.count);
+ target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, item.itemid, item.count, loot->loot_type);
target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item.itemid, item.count);
// mark as looted
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index 1270f4e6419..1359032080b 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -28,6 +28,8 @@
#include "DBCStores.h"
#include "Item.h"
#include "AccountMgr.h"
+#include "BattlenetAccountMgr.h"
+#include "GuildMgr.h"
bool WorldSession::CanOpenMailBox(uint64 guid)
{
@@ -57,15 +59,20 @@ bool WorldSession::CanOpenMailBox(uint64 guid)
void WorldSession::HandleSendMail(WorldPacket& recvData)
{
- uint64 mailbox, unk3;
+ ObjectGuid mailbox;
+ uint64 money, COD;
std::string receiverName, subject, body;
- uint32 unk1, unk2, money, COD;
- uint8 unk4;
- uint8 items_count;
- recvData >> mailbox >> receiverName >> subject >> body
- >> unk1 // stationery?
- >> unk2 // 0x00000000
- >> items_count; // attached items count
+ uint32 bodyLength, subjectLength, receiverLength;
+ uint32 unk1, unk2;
+
+ recvData >> unk1;
+ recvData >> unk2; // Stationery?
+
+ recvData >> COD >> money; // money and cod
+ bodyLength = recvData.ReadBits(12);
+ subjectLength = recvData.ReadBits(9);
+
+ uint8 items_count = recvData.ReadBits(5); // attached items count
if (items_count > MAX_MAIL_ITEMS) // client limit
{
@@ -74,17 +81,60 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
return;
}
- uint64 itemGUIDs[MAX_MAIL_ITEMS];
+ mailbox[0] = recvData.ReadBit();
+
+ ObjectGuid itemGUIDs[MAX_MAIL_ITEMS];
for (uint8 i = 0; i < items_count; ++i)
{
- recvData.read_skip<uint8>(); // item slot in mail, not used
- recvData >> itemGUIDs[i];
+ itemGUIDs[i][2] = recvData.ReadBit();
+ itemGUIDs[i][6] = recvData.ReadBit();
+ itemGUIDs[i][3] = recvData.ReadBit();
+ itemGUIDs[i][7] = recvData.ReadBit();
+ itemGUIDs[i][1] = recvData.ReadBit();
+ itemGUIDs[i][0] = recvData.ReadBit();
+ itemGUIDs[i][4] = recvData.ReadBit();
+ itemGUIDs[i][5] = recvData.ReadBit();
}
- recvData >> money >> COD; // money and cod
- recvData >> unk3; // const 0
- recvData >> unk4; // const 0
+ mailbox[3] = recvData.ReadBit();
+ mailbox[4] = recvData.ReadBit();
+ receiverLength = recvData.ReadBits(7);
+ mailbox[2] = recvData.ReadBit();
+ mailbox[6] = recvData.ReadBit();
+ mailbox[1] = recvData.ReadBit();
+ mailbox[7] = recvData.ReadBit();
+ mailbox[5] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(mailbox[4]);
+
+ for (uint8 i = 0; i < items_count; ++i)
+ {
+ recvData.ReadByteSeq(itemGUIDs[i][6]);
+ recvData.ReadByteSeq(itemGUIDs[i][1]);
+ recvData.ReadByteSeq(itemGUIDs[i][7]);
+ recvData.ReadByteSeq(itemGUIDs[i][2]);
+ recvData.read_skip<uint8>(); // item slot in mail, not used
+ recvData.ReadByteSeq(itemGUIDs[i][3]);
+ recvData.ReadByteSeq(itemGUIDs[i][0]);
+ recvData.ReadByteSeq(itemGUIDs[i][4]);
+ recvData.ReadByteSeq(itemGUIDs[i][5]);
+ }
+
+ recvData.ReadByteSeq(mailbox[7]);
+ recvData.ReadByteSeq(mailbox[3]);
+ recvData.ReadByteSeq(mailbox[6]);
+ recvData.ReadByteSeq(mailbox[5]);
+
+ subject = recvData.ReadString(subjectLength);
+ receiverName = recvData.ReadString(receiverLength);
+
+ recvData.ReadByteSeq(mailbox[2]);
+ recvData.ReadByteSeq(mailbox[0]);
+
+ body = recvData.ReadString(bodyLength);
+
+ recvData.ReadByteSeq(mailbox[1]);
// packet read complete, now do check
@@ -109,7 +159,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (!receiverGuid)
{
TC_LOG_INFO("network", "Player %u is sending mail to %s (GUID: not existed!) with subject %s "
- "and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u",
+ "and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
player->GetGUIDLow(), receiverName.c_str(), subject.c_str(), body.c_str(),
items_count, money, COD, unk1, unk2);
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND);
@@ -117,7 +167,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
}
TC_LOG_INFO("network", "Player %u is sending mail to %s (GUID: %u) with subject %s and body %s "
- "includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u",
+ "includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
player->GetGUIDLow(), receiverName.c_str(), GUID_LOPART(receiverGuid), subject.c_str(),
body.c_str(), items_count, money, COD, unk1, unk2);
@@ -129,7 +179,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client
- uint32 reqmoney = cost + money;
+ uint64 reqmoney = cost + money;
// Check for overflow
if (reqmoney < money)
@@ -150,6 +200,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
uint8 mailsCount = 0; //do not allow to send to one player more than 100 mails
uint8 receiverLevel = 0;
uint32 receiverAccountId = 0;
+ uint32 receiverBnetAccountId = 0;
if (receiver)
{
@@ -157,6 +208,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
mailsCount = receiver->GetMailSize();
receiverLevel = receiver->getLevel();
receiverAccountId = receiver->GetSession()->GetAccountId();
+ receiverBnetAccountId = receiver->GetSession()->GetBattlenetAccountId();
}
else
{
@@ -183,6 +235,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
}
receiverAccountId = sObjectMgr->GetPlayerAccountIdByGUID(receiverGuid);
+ receiverBnetAccountId = Battlenet::AccountMgr::GetIdByGameAccount(receiverAccountId);
}
// do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255..
@@ -246,8 +299,11 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != receiverAccountId)
{
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS);
- return;
+ if (!item->IsBattlenetAccountBound() || !player->GetSession()->GetBattlenetAccountId() || player->GetSession()->GetBattlenetAccountId() != receiverBnetAccountId)
+ {
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_NOT_SAME_ACCOUNT);
+ return;
+ }
}
if (item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION))
@@ -264,7 +320,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (item->IsNotEmptyBag())
{
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS);
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_DESTROY_NONEMPTY_BAG);
return;
}
@@ -273,7 +329,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
player->SendMailResult(0, MAIL_SEND, MAIL_OK);
- player->ModifyMoney(-int32(reqmoney));
+ player->ModifyMoney(-int64(reqmoney));
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost);
bool needItemDelay = false;
@@ -314,7 +370,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (log && money > 0)
{
- sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail money: %u to player: %s (GUID: %u) (Account: %u)",
+ sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail money: " UI64FMTD " to player: %s (GUID: %u) (Account: %u)",
GetPlayerName().c_str(), GetGuidLow(), GetAccountId(), money, receiverName.c_str(), GUID_LOPART(receiverGuid), receiverAccountId);
}
}
@@ -322,6 +378,11 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
// If theres is an item, there is a one hour delivery delay if sent to another account's character.
uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0;
+ // Mail sent between guild members arrives instantly if they have the guild perk "Guild Mail"
+ if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
+ if (guild->GetLevel() >= 17 && guild->IsMember(receiverGuid))
+ deliver_delay = 0;
+
// don't ask for COD if there are no items
if (items_count == 0)
COD = 0;
@@ -406,8 +467,7 @@ void WorldSession::HandleMailReturnToSender(WorldPacket& recvData)
player->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, MAIL_ERR_INTERNAL_ERROR);
return;
}
- //we can return mail now
- //so firstly delete the old one
+ //we can return mail now, so firstly delete the old one
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_BY_ID);
@@ -431,14 +491,8 @@ void WorldSession::HandleMailReturnToSender(WorldPacket& recvData)
{
for (MailItemInfoVec::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2)
{
- Item* item = player->GetMItem(itr2->item_guid);
- if (item)
+ if (Item* const item = player->GetMItem(itr2->item_guid))
draft.AddItem(item);
- else
- {
- //WTF?
- }
-
player->RemoveMItem(itr2->item_guid);
}
}
@@ -481,7 +535,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
}
// prevent cheating with skip client money check
- if (!player->HasEnoughMoney(m->COD))
+ if (!player->HasEnoughMoney(uint64(m->COD)))
{
player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_NOT_ENOUGH_MONEY);
return;
@@ -520,7 +574,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
if (!sObjectMgr->GetPlayerNameByGUID(sender_guid, sender_name))
sender_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN);
}
- sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receiver mail item: %s (Entry: %u Count: %u) and send COD money: %u to player: %s (Account: %u)",
+ sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receiver mail item: %s (Entry: %u Count: %u) and send COD money: " UI64FMTD " to player: %s (Account: %u)",
GetPlayerName().c_str(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId);
}
else if (!receiver)
@@ -558,9 +612,12 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
void WorldSession::HandleMailTakeMoney(WorldPacket& recvData)
{
uint64 mailbox;
+ uint64 money;
uint32 mailId;
+
recvData >> mailbox;
recvData >> mailId;
+ recvData >> money;
if (!CanOpenMailBox(mailbox))
return;
@@ -568,7 +625,8 @@ void WorldSession::HandleMailTakeMoney(WorldPacket& recvData)
Player* player = _player;
Mail* m = player->GetMail(mailId);
- if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL))
+ if ((!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) ||
+ (money > 0 && m->money != money))
{
player->SendMailResult(mailId, MAIL_MONEY_TAKEN, MAIL_ERR_INTERNAL_ERROR);
return;
@@ -614,7 +672,7 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData)
uint32 mailsCount = 0; // real send to client mails amount
uint32 realCount = 0; // real mails amount
- WorldPacket data(SMSG_MAIL_LIST_RESULT, (200)); // guess size
+ WorldPacket data(SMSG_MAIL_LIST_RESULT, 200); // guess size
data << uint32(0); // real mail's count
data << uint8(0); // mail's count
time_t cur_time = time(NULL);
@@ -655,14 +713,14 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData)
case MAIL_GAMEOBJECT:
case MAIL_AUCTION:
case MAIL_CALENDAR:
- data << uint32((*itr)->sender); // creature/gameobject entry, auction id, calendar event id?
+ data << uint32((*itr)->sender); // creature/gameobject entry, auction id, calendar event id?
break;
}
- data << uint32((*itr)->COD); // COD
- data << uint32(0); // package (Package.dbc)
+ data << uint64((*itr)->COD); // COD
+ data << uint32(0); // Package.dbc ID ?
data << uint32((*itr)->stationery); // stationery (Stationery.dbc)
- data << uint32((*itr)->money); // Gold
+ data << uint64((*itr)->money); // Gold
data << uint32((*itr)->checked); // flags
data << float(float((*itr)->expire_time-time(NULL))/DAY); // Time
data << uint32((*itr)->mailTemplateId); // mail template (MailTemplate.dbc)
@@ -685,6 +743,7 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData)
data << uint32((item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0));
data << uint32((item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0));
}
+
// can be negative
data << int32((item ? item->GetItemRandomPropertyId() : 0));
// unk
@@ -751,7 +810,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
return;
}
- bodyItem->SetText(mailTemplateEntry->content[GetSessionDbcLocale()]);
+ bodyItem->SetText(mailTemplateEntry->content);
}
else
bodyItem->SetText(m->body);
@@ -780,7 +839,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
}
/// @todo Fix me! ... this void has probably bad condition, but good data are sent
-void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recvData*/)
+void WorldSession::HandleQueryNextMailTime(WorldPacket& /*recvData*/)
{
WorldPacket data(MSG_QUERY_NEXT_MAIL_TIME, 8);
@@ -832,3 +891,10 @@ void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recvData*/)
SendPacket(&data);
}
+
+void WorldSession::SendShowMailBox(uint64 guid)
+{
+ WorldPacket data(SMSG_SHOW_MAILBOX, 8);
+ data << guid;
+ SendPacket(&data);
+}
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index baa20f76a40..c9891de3c16 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -55,6 +55,7 @@
#include "BattlegroundMgr.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
+#include "DB2Stores.h"
void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData)
{
@@ -388,7 +389,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/)
uint32 reason = 0;
if (GetPlayer()->IsInCombat() && !canLogoutInCombat)
reason = 1;
- else if (GetPlayer()->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR))
+ else if (GetPlayer()->IsFalling())
reason = 3; // is jumping or falling
else if (GetPlayer()->duel || GetPlayer()->HasAura(9454)) // is dueling or frozen by GM via freeze command
reason = 2; // FIXME - Need the correct value
@@ -404,7 +405,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/)
return;
}
- //instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in worldserver.conf
+ // instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in worldserver.conf
if (instantLogout)
{
LogoutPlayer(true);
@@ -415,11 +416,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/)
if (GetPlayer()->CanFreeMove())
{
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()->SetRooted(true);
GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
}
@@ -448,10 +445,7 @@ void WorldSession::HandleLogoutCancelOpcode(WorldPacket& /*recvData*/)
if (GetPlayer()->CanFreeMove())
{
//!we can move again
- data.Initialize(SMSG_FORCE_MOVE_UNROOT, 8); // guess size
- data.append(GetPlayer()->GetPackGUID());
- data << uint32(0);
- SendPacket(&data);
+ GetPlayer()->SetRooted(false);
//! Stand Up
GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND);
@@ -507,6 +501,13 @@ void WorldSession::HandleZoneUpdateOpcode(WorldPacket& recvData)
//GetPlayer()->SendInitWorldStates(true, newZone);
}
+void WorldSession::HandleReturnToGraveyard(WorldPacket& /*recvPacket*/)
+{
+ if (GetPlayer()->IsAlive() || !GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
+ return;
+ GetPlayer()->RepopAtGraveyard();
+}
+
void WorldSession::HandleSetSelectionOpcode(WorldPacket& recvData)
{
uint64 guid;
@@ -526,9 +527,8 @@ void WorldSession::HandleStandStateChangeOpcode(WorldPacket& recvData)
void WorldSession::HandleContactListOpcode(WorldPacket& recvData)
{
- uint32 unk;
- recvData >> unk;
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_CONTACT_LIST - Unk: %d", unk);
+ recvData.read_skip<uint32>(); // always 1
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_CONTACT_LIST");
_player->GetSocial()->SendSocialList(_player);
}
@@ -713,9 +713,11 @@ void WorldSession::HandleBugOpcode(WorldPacket& recvData)
uint32 suggestion, contentlen, typelen;
std::string content, type;
- recvData >> suggestion >> contentlen >> content;
+ recvData >> suggestion >> contentlen;
+ content = recvData.ReadString(contentlen);
- recvData >> typelen >> type;
+ recvData >> typelen;
+ type = recvData.ReadString(typelen);
if (suggestion == 0)
TC_LOG_DEBUG("network", "WORLD: Received CMSG_BUG [Bug Report]");
@@ -784,11 +786,11 @@ void WorldSession::HandleResurrectResponseOpcode(WorldPacket& recvData)
if (status == 0)
{
- GetPlayer()->clearResurrectRequestData(); // reject
+ GetPlayer()->ClearResurrectRequestData(); // reject
return;
}
- if (!GetPlayer()->isResurrectRequestedBy(guid))
+ if (!GetPlayer()->IsResurrectRequestedBy(guid))
return;
GetPlayer()->ResurrectUsingRequestData();
@@ -922,7 +924,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData)
if (pvp->HandleAreaTrigger(_player, triggerId))
return;
- AreaTrigger const* at = sObjectMgr->GetAreaTrigger(triggerId);
+ AreaTriggerStruct const* at = sObjectMgr->GetAreaTrigger(triggerId);
if (!at)
return;
@@ -1034,6 +1036,13 @@ void WorldSession::HandleRequestAccountData(WorldPacket& recvData)
SendPacket(&data);
}
+int32 WorldSession::HandleEnableNagleAlgorithm()
+{
+ // Instructs the server we wish to receive few amounts of large packets (SMSG_MULTIPLE_PACKETS?)
+ // instead of large amount of small packets
+ return 0;
+}
+
void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recvData)
{
uint8 button;
@@ -1059,12 +1068,32 @@ void WorldSession::HandleNextCinematicCamera(WorldPacket& /*recvData*/)
void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData)
{
- /* WorldSession::Update(getMSTime());*/
TC_LOG_DEBUG("network", "WORLD: Received CMSG_MOVE_TIME_SKIPPED");
- uint64 guid;
- recvData.readPackGUID(guid);
- recvData.read_skip<uint32>();
+ ObjectGuid guid;
+ uint32 time;
+ recvData >> time;
+
+ guid[5] = recvData.ReadBit();
+ guid[1] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[2] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[3]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[5]);
+
+ //TODO!
+
/*
uint64 guid;
uint32 time_skipped;
@@ -1185,10 +1214,9 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recvData)
if (GetPlayer()->IsValidAttackTarget(player))
return;
- uint32 talent_points = 0x47;
- uint32 guid_size = player->GetPackGUID().wpos();
- WorldPacket data(SMSG_INSPECT_TALENT, guid_size+4+talent_points);
- data.append(player->GetPackGUID());
+ uint32 talent_points = 41;
+ WorldPacket data(SMSG_INSPECT_TALENT, 8 + 4 + 1 + 1 + talent_points + 8 + 4 + 8 + 4);
+ data << player->GetGUID();
if (sWorld->getBoolConfig(CONFIG_TALENTS_INSPECTING) || _player->IsGameMaster())
player->BuildPlayerTalentsInfoData(&data);
@@ -1200,19 +1228,40 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recvData)
}
player->BuildEnchantmentsInfoData(&data);
+ if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
+ {
+ data << uint64(guild->GetGUID());
+ data << uint32(guild->GetLevel());
+ data << uint64(guild->GetExperience());
+ data << uint32(guild->GetMembersCount());
+ }
SendPacket(&data);
}
void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recvData)
{
- uint64 guid;
- recvData >> guid;
-
+ ObjectGuid guid;
+ guid[1] = recvData.ReadBit();
+ guid[5] = recvData.ReadBit();
+ guid[7] = recvData.ReadBit();
+ guid[3] = recvData.ReadBit();
+ guid[2] = recvData.ReadBit();
+ guid[4] = recvData.ReadBit();
+ guid[0] = recvData.ReadBit();
+ guid[6] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(guid[4]);
+ recvData.ReadByteSeq(guid[7]);
+ recvData.ReadByteSeq(guid[0]);
+ recvData.ReadByteSeq(guid[5]);
+ recvData.ReadByteSeq(guid[1]);
+ recvData.ReadByteSeq(guid[6]);
+ recvData.ReadByteSeq(guid[2]);
+ recvData.ReadByteSeq(guid[3]);
Player* player = ObjectAccessor::FindPlayer(guid);
-
if (!player)
{
- TC_LOG_DEBUG("network", "MSG_INSPECT_HONOR_STATS: No player found from GUID: " UI64FMTD, guid);
+ TC_LOG_DEBUG("network", "CMSG_INSPECT_HONOR_STATS: No player found from GUID: " UI64FMTD, (uint64)guid);
return;
}
@@ -1222,13 +1271,28 @@ void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recvData)
if (GetPlayer()->IsValidAttackTarget(player))
return;
- WorldPacket data(MSG_INSPECT_HONOR_STATS, 8+1+4*4);
- data << uint64(player->GetGUID());
- data << uint8(player->GetHonorPoints());
- data << uint32(player->GetUInt32Value(PLAYER_FIELD_KILLS));
- data << uint32(player->GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION));
- data << uint32(player->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION));
+ ObjectGuid playerGuid = player->GetGUID();
+ WorldPacket data(SMSG_INSPECT_HONOR_STATS, 8+1+4+4);
+ data.WriteBit(playerGuid[4]);
+ data.WriteBit(playerGuid[3]);
+ data.WriteBit(playerGuid[6]);
+ data.WriteBit(playerGuid[2]);
+ data.WriteBit(playerGuid[5]);
+ data.WriteBit(playerGuid[0]);
+ data.WriteBit(playerGuid[7]);
+ data.WriteBit(playerGuid[1]);
+ data << uint8(0); // rank
+ data << uint16(player->GetUInt16Value(PLAYER_FIELD_KILLS, 1)); // yesterday kills
+ data << uint16(player->GetUInt16Value(PLAYER_FIELD_KILLS, 0)); // today kills
+ data.WriteByteSeq(playerGuid[2]);
+ data.WriteByteSeq(playerGuid[0]);
+ data.WriteByteSeq(playerGuid[6]);
+ data.WriteByteSeq(playerGuid[3]);
+ data.WriteByteSeq(playerGuid[4]);
+ data.WriteByteSeq(playerGuid[1]);
+ data.WriteByteSeq(playerGuid[5]);
data << uint32(player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS));
+ data.WriteByteSeq(playerGuid[7]);
SendPacket(&data);
}
@@ -1360,8 +1424,9 @@ void WorldSession::HandleComplainOpcode(WorldPacket& recvData)
// if it's mail spam - ALL mails from this spammer automatically removed by client
// Complaint Received message
- WorldPacket data(SMSG_COMPLAIN_RESULT, 1);
- data << uint8(0);
+ WorldPacket data(SMSG_COMPLAIN_RESULT, 2);
+ data << uint8(0); // value 1 resets CGChat::m_complaintsSystemStatus in client. (unused?)
+ data << uint8(0); // value 0xC generates a "CalendarError" in client.
SendPacket(&data);
TC_LOG_DEBUG("network", "REPORT SPAM: type %u, guid %u, unk1 %u, unk2 %u, unk3 %u, unk4 %u, message %s", spam_type, GUID_LOPART(spammer_guid), unk1, unk2, unk3, unk4, description.c_str());
@@ -1437,8 +1502,8 @@ void WorldSession::HandleTimeSyncResp(WorldPacket& recvData)
uint32 counter, clientTicks;
recvData >> counter >> clientTicks;
- if (counter != _player->m_timeSyncCounter - 1)
- TC_LOG_DEBUG("network", "Wrong time sync counter from player %s (cheater?)", _player->GetName().c_str());
+ if (counter != _player->m_timeSyncQueue.front())
+ TC_LOG_ERROR("network", "Wrong time sync counter from player %s (cheater?)", _player->GetName().c_str());
TC_LOG_DEBUG("network", "Time sync received: counter %u, client ticks %u, time since last sync %u", counter, clientTicks, clientTicks - _player->m_timeSyncClient);
@@ -1448,6 +1513,7 @@ void WorldSession::HandleTimeSyncResp(WorldPacket& recvData)
TC_LOG_DEBUG("network", "Our ticks: %u, diff %u, latency %u", ourTicks, ourTicks - clientTicks, GetLatency());
_player->m_timeSyncClient = clientTicks;
+ _player->m_timeSyncQueue.pop();
}
void WorldSession::HandleResetInstancesOpcode(WorldPacket& /*recvData*/)
@@ -1604,16 +1670,8 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData)
// fly mode on/off
TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK");
- uint64 guid; // guid - unused
- recvData.readPackGUID(guid);
-
- recvData.read_skip<uint32>(); // unk
-
MovementInfo movementInfo;
- movementInfo.guid = guid;
- ReadMovementInfo(recvData, &movementInfo);
-
- recvData.read_skip<float>(); // unk2
+ _player->ReadMovementInfo(recvData, &movementInfo);
_player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags();
}
@@ -1657,6 +1715,15 @@ void WorldSession::HandleQueryInspectAchievements(WorldPacket& recvData)
player->SendRespondInspectAchievements(_player);
}
+void WorldSession::HandleGuildAchievementProgressQuery(WorldPacket& recvData)
+{
+ uint32 achievementId;
+ recvData >> achievementId;
+
+ if (Guild* guild = sGuildMgr->GetGuildById(_player->GetGuildId()))
+ guild->GetAchievementMgr().SendAchievementInfo(_player, achievementId);
+}
+
void WorldSession::HandleWorldStateUITimerUpdate(WorldPacket& /*recvData*/)
{
// empty opcode
@@ -1675,12 +1742,54 @@ void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recvData*/)
SendAccountDataTimes(GLOBAL_CACHE_MASK);
}
-void WorldSession::SendSetPhaseShift(uint32 PhaseShift)
+void WorldSession::SendSetPhaseShift(std::set<uint32> const& phaseIds, std::set<uint32> const& terrainswaps, std::set<uint32> const& worldMapAreaSwaps)
{
- WorldPacket data(SMSG_SET_PHASE_SHIFT, 4);
- data << uint32(PhaseShift);
+ ObjectGuid guid = _player->GetGUID();
+
+ WorldPacket data(SMSG_SET_PHASE_SHIFT, 1 + 8 + 4 + 4 + 4 + 4 + 2 * phaseIds.size() + 4 + terrainswaps.size() * 2);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[7]);
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[4]);
+
+ data << uint32(worldMapAreaSwaps.size());
+ for (auto mapSwap : worldMapAreaSwaps)
+ data << uint16(mapSwap); // WorldMapArea.dbc id (controls map display)
+
+ data.WriteByteSeq(guid[1]);
+
+ data << uint32(phaseIds.size() ? 0 : 8); // flags (not phasemask)
+
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[6]);
+
+ data << uint32(0); // Inactive terrain swaps
+ //for (uint8 i = 0; i < inactiveSwapsCount; ++i)
+ // data << uint16(0);
+
+ data << uint32(phaseIds.size()) * 2; // Phase.dbc ids
+ for (std::set<uint32>::const_iterator itr = phaseIds.begin(); itr != phaseIds.end(); ++itr)
+ data << uint16(*itr);
+
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+
+ data << uint32(terrainswaps.size()) * 2; // Active terrain swaps
+ for (std::set<uint32>::const_iterator itr = terrainswaps.begin(); itr != terrainswaps.end(); ++itr)
+ data << uint16(*itr);
+
+ data.WriteByteSeq(guid[5]);
+
SendPacket(&data);
}
+
// Battlefield and Battleground
void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPacket& recvData)
{
@@ -1768,6 +1877,74 @@ void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket)
_player->SetPendingBind(0, 0);
}
+void WorldSession::HandleRequestHotfix(WorldPacket& recvPacket)
+{
+ uint32 type, count;
+ recvPacket >> type;
+
+ DB2StorageBase const* store = GetDB2Storage(type);
+ if (!store)
+ {
+ TC_LOG_ERROR("network", "CMSG_REQUEST_HOTFIX: Received unknown hotfix type: %u", type);
+ recvPacket.rfinish();
+ return;
+ }
+
+ count = recvPacket.ReadBits(23);
+
+ ObjectGuid* guids = new ObjectGuid[count];
+ for (uint32 i = 0; i < count; ++i)
+ {
+ guids[i][0] = recvPacket.ReadBit();
+ guids[i][4] = recvPacket.ReadBit();
+ guids[i][7] = recvPacket.ReadBit();
+ guids[i][2] = recvPacket.ReadBit();
+ guids[i][5] = recvPacket.ReadBit();
+ guids[i][3] = recvPacket.ReadBit();
+ guids[i][6] = recvPacket.ReadBit();
+ guids[i][1] = recvPacket.ReadBit();
+ }
+
+ uint32 entry;
+ for (uint32 i = 0; i < count; ++i)
+ {
+ recvPacket.ReadByteSeq(guids[i][5]);
+ recvPacket.ReadByteSeq(guids[i][6]);
+ recvPacket.ReadByteSeq(guids[i][7]);
+ recvPacket.ReadByteSeq(guids[i][0]);
+ recvPacket.ReadByteSeq(guids[i][1]);
+ recvPacket.ReadByteSeq(guids[i][3]);
+ recvPacket.ReadByteSeq(guids[i][4]);
+ recvPacket >> entry;
+ recvPacket.ReadByteSeq(guids[i][2]);
+
+ if (!store->HasRecord(entry))
+ {
+ WorldPacket data(SMSG_DB_REPLY, 4 * 4);
+ data << -int32(entry);
+ data << uint32(store->GetHash());
+ data << uint32(time(NULL));
+ data << uint32(0);
+ SendPacket(&data);
+ continue;
+ }
+
+ WorldPacket data(SMSG_DB_REPLY);
+ data << int32(entry);
+ data << uint32(store->GetHash());
+ data << uint32(sObjectMgr->GetHotfixDate(entry, store->GetHash()));
+
+ size_t sizePos = data.wpos();
+ data << uint32(0); // size of next block
+ store->WriteRecord(entry, uint32(GetSessionDbcLocale()), data);
+ data.put<uint32>(sizePos, data.wpos() - sizePos - 4);
+
+ SendPacket(&data);
+ }
+
+ delete[] guids;
+}
+
void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket)
{
TC_LOG_DEBUG("network", "WORLD: CMSG_UPDATE_MISSILE_TRAJECTORY");
@@ -1807,7 +1984,179 @@ void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket)
{
uint32 opcode;
recvPacket >> opcode;
- recvPacket.SetOpcode(opcode);
+ recvPacket.SetOpcode(MSG_MOVE_STOP); // always set to MSG_MOVE_STOP in client SetOpcode
HandleMovementOpcodes(recvPacket);
}
}
+
+void WorldSession::HandleViolenceLevel(WorldPacket& recvPacket)
+{
+ uint8 violenceLevel;
+ recvPacket >> violenceLevel;
+
+ // do something?
+}
+
+void WorldSession::HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket)
+{
+ ObjectGuid guid;
+ guid[6] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[0]);
+ recvPacket.ReadByteSeq(guid[5]);
+
+ WorldObject* obj = ObjectAccessor::GetWorldObject(*GetPlayer(), guid);
+ TC_LOG_ERROR("network", "Object update failed for object " UI64FMTD " (%s) for player %s (%u)", uint64(guid), obj ? obj->GetName().c_str() : "object-not-found", GetPlayerName().c_str(), GetGuidLow());
+
+ // If create object failed for current player then client will be stuck on loading screen
+ if (_player->GetGUID() == guid)
+ {
+ LogoutPlayer(true);
+ return;
+ }
+
+ // Pretend we've never seen this object
+ _player->m_clientGUIDs.erase(guid);
+}
+
+void WorldSession::HandleSaveCUFProfiles(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_SAVE_CUF_PROFILES");
+
+ uint8 count = (uint8)recvPacket.ReadBits(20);
+
+ if (count > MAX_CUF_PROFILES)
+ {
+ TC_LOG_ERROR("entities.player", "HandleSaveCUFProfiles - %s tried to save more than %i CUF profiles. Hacking attempt?", GetPlayerName().c_str(), MAX_CUF_PROFILES);
+ recvPacket.rfinish();
+ return;
+ }
+
+ CUFProfile* profiles[MAX_CUF_PROFILES];
+ uint8 strlens[MAX_CUF_PROFILES];
+
+ for (uint8 i = 0; i < count; ++i)
+ {
+ profiles[i] = new CUFProfile;
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_SPEC_2 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_10_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_UNK_157 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_HEAL_PREDICTION , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_SPEC_1 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_PVP , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_POWER_BAR , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_15_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_40_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_PETS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_5_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS, recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_2_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_UNK_156 , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_NON_BOSS_DEBUFFS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_MAIN_TANK_AND_ASSIST , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_AGGRO_HIGHLIGHT , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_3_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_BORDER , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_USE_CLASS_COLORS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_UNK_145 , recvPacket.ReadBit());
+ strlens[i] = (uint8)recvPacket.ReadBits(8);
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_PVE , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_DISPLAY_HORIZONTAL_GROUPS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_25_PLAYERS , recvPacket.ReadBit());
+ profiles[i]->BoolOptions.set(CUF_KEEP_GROUPS_TOGETHER , recvPacket.ReadBit());
+ }
+
+ for (uint8 i = 0; i < count; ++i)
+ {
+ recvPacket >> profiles[i]->Unk146;
+ profiles[i]->ProfileName = recvPacket.ReadString(strlens[i]);
+ recvPacket >> profiles[i]->Unk152;
+ recvPacket >> profiles[i]->FrameHeight;
+ recvPacket >> profiles[i]->FrameWidth;
+ recvPacket >> profiles[i]->Unk150;
+ recvPacket >> profiles[i]->HealthText;
+ recvPacket >> profiles[i]->Unk147;
+ recvPacket >> profiles[i]->SortBy;
+ recvPacket >> profiles[i]->Unk154;
+ recvPacket >> profiles[i]->Unk148;
+
+ GetPlayer()->SaveCUFProfile(i, profiles[i]);
+ }
+
+ for (uint8 i = count; i < MAX_CUF_PROFILES; ++i)
+ GetPlayer()->SaveCUFProfile(i, NULL);
+}
+
+void WorldSession::SendLoadCUFProfiles()
+{
+ Player* player = GetPlayer();
+
+ uint8 count = player->GetCUFProfilesCount();
+
+ ByteBuffer byteBuffer(25 * count);
+ WorldPacket data(SMSG_LOAD_CUF_PROFILES, 5 * count + 25 * count);
+
+ data.WriteBits(count, 20);
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
+ {
+ CUFProfile* profile = player->GetCUFProfile(i);
+ if (!profile)
+ continue;
+
+ data.WriteBit(profile->BoolOptions[CUF_UNK_157]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_10_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_5_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_25_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_HEAL_PREDICTION]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_PVE]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_HORIZONTAL_GROUPS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_40_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_3_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_AGGRO_HIGHLIGHT]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_BORDER]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_2_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_NON_BOSS_DEBUFFS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_MAIN_TANK_AND_ASSIST]);
+ data.WriteBit(profile->BoolOptions[CUF_UNK_156]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_SPEC_2]);
+ data.WriteBit(profile->BoolOptions[CUF_USE_CLASS_COLORS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_POWER_BAR]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_SPEC_1]);
+ data.WriteBits(profile->ProfileName.size(), 8);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS]);
+ data.WriteBit(profile->BoolOptions[CUF_KEEP_GROUPS_TOGETHER]);
+ data.WriteBit(profile->BoolOptions[CUF_UNK_145]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_15_PLAYERS]);
+ data.WriteBit(profile->BoolOptions[CUF_DISPLAY_PETS]);
+ data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_PVP]);
+
+ byteBuffer << uint16(profile->Unk154);
+ byteBuffer << uint16(profile->FrameHeight);
+ byteBuffer << uint16(profile->Unk152);
+ byteBuffer << uint8(profile->Unk147);
+ byteBuffer << uint16(profile->Unk150);
+ byteBuffer << uint8(profile->Unk146);
+ byteBuffer << uint8(profile->HealthText);
+ byteBuffer << uint8(profile->SortBy);
+ byteBuffer << uint16(profile->FrameWidth);
+ byteBuffer << uint8(profile->Unk148);
+ byteBuffer.WriteString(profile->ProfileName);
+ }
+
+ data.FlushBits();
+ data.append(byteBuffer);
+ SendPacket(&data);
+}
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 6fedc481a14..dabe40e427e 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -30,6 +30,7 @@
#include "WaypointMovementGenerator.h"
#include "InstanceSaveMgr.h"
#include "ObjectMgr.h"
+#include "MovementStructures.h"
#include "Vehicle.h"
#define MOVEMENT_PACKET_TIME_DELAY 0
@@ -195,16 +196,33 @@ void WorldSession::HandleMoveWorldportAckOpcode()
GetPlayer()->ProcessDelayedOperations();
}
-void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData)
+void WorldSession::HandleMoveTeleportAck(WorldPacket& recvPacket)
{
TC_LOG_DEBUG("network", "MSG_MOVE_TELEPORT_ACK");
- uint64 guid;
-
- recvData.readPackGUID(guid);
+ ObjectGuid guid;
uint32 flags, time;
- recvData >> flags >> time;
- TC_LOG_DEBUG("network", "Guid " UI64FMTD, guid);
+ recvPacket >> flags >> time;
+
+ guid[5] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[0]);
+
+ TC_LOG_DEBUG("network", "Guid " UI64FMTD, uint64(guid));
TC_LOG_DEBUG("network", "Flags %u, time %u", flags, time/IN_MILLISECONDS);
Player* plMover = _player->m_mover->ToPlayer();
@@ -246,9 +264,9 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData)
GetPlayer()->ProcessDelayedOperations();
}
-void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
+void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket)
{
- uint16 opcode = recvData.GetOpcode();
+ uint16 opcode = recvPacket.GetOpcode();
Unit* mover = _player->m_mover;
@@ -259,46 +277,41 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
if (plrMover && plrMover->IsBeingTeleported())
{
- recvData.rfinish(); // prevent warnings spam
+ recvPacket.rfinish(); // prevent warnings spam
return;
}
/* extract packet */
- uint64 guid;
-
- recvData.readPackGUID(guid);
-
MovementInfo movementInfo;
- movementInfo.guid = guid;
- ReadMovementInfo(recvData, &movementInfo);
-
- recvData.rfinish(); // prevent warnings spam
+ GetPlayer()->ReadMovementInfo(recvPacket, &movementInfo);
// prevent tampered movement data
- if (guid != mover->GetGUID())
+ if (movementInfo.guid != mover->GetGUID())
+ {
+ TC_LOG_ERROR("network", "HandleMovementOpcodes: guid error");
return;
-
+ }
if (!movementInfo.pos.IsPositionValid())
{
- recvData.rfinish(); // prevent warnings spam
+ TC_LOG_ERROR("network", "HandleMovementOpcodes: Invalid Position");
return;
}
/* handle special cases */
- if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
+ if (movementInfo.transport.guid)
{
// transports size limited
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
if (movementInfo.transport.pos.GetPositionX() > 50 || movementInfo.transport.pos.GetPositionY() > 50 || movementInfo.transport.pos.GetPositionZ() > 50)
{
- recvData.rfinish(); // prevent warnings spam
+ recvPacket.rfinish(); // prevent warnings spam
return;
}
if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(),
movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation()))
{
- recvData.rfinish(); // prevent warnings spam
+ recvPacket.rfinish(); // prevent warnings spam
return;
}
@@ -316,7 +329,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
transport->AddPassenger(plrMover);
else
- movementInfo.transport.Reset();
+ movementInfo.ResetTransport();
}
}
@@ -324,14 +337,11 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
{
GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid);
if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
- movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
+ movementInfo.transport.guid = 0;
}
}
else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
- {
- plrMover->GetTransport()->RemovePassenger(plrMover);
- movementInfo.transport.Reset();
- }
+ plrMover->m_transport->RemovePassenger(plrMover);
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight())
@@ -349,13 +359,9 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
m_clientTimeDelay = mstime - movementInfo.time;
/* process position-change */
- WorldPacket data(opcode, recvData.size());
movementInfo.time = movementInfo.time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY;
movementInfo.guid = mover->GetGUID();
- WriteMovementInfo(&data, &movementInfo);
- mover->SendMessageToSet(&data, _player);
-
mover->m_movementInfo = movementInfo;
// Some vehicles allow the passenger to turn by himself
@@ -377,6 +383,10 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
mover->UpdatePosition(movementInfo.pos);
+ WorldPacket data(SMSG_PLAYER_MOVE, recvPacket.size());
+ mover->WriteMovementInfo(data);
+ mover->SendMessageToSet(&data, _player);
+
if (plrMover) // nothing is charmed, or player charmed
{
if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING)))
@@ -384,7 +394,9 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
- if (movementInfo.pos.GetPositionZ() < -500.0f)
+ AreaTableEntry const* zone = GetAreaEntryByAreaID(plrMover->GetAreaId());
+ float depth = zone ? zone->MaxDepth : -500.0f;
+ if (movementInfo.pos.GetPositionZ() < depth)
{
if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
{
@@ -408,62 +420,62 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData)
{
uint32 opcode = recvData.GetOpcode();
- TC_LOG_DEBUG("network", "WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
/* extract packet */
- uint64 guid;
- uint32 unk1;
- float newspeed;
-
- recvData.readPackGUID(guid);
+ MovementInfo movementInfo;
+ static MovementStatusElements const speedElement = MSEExtraFloat;
+ Movement::ExtraMovementStatusElement extras(&speedElement);
+ GetPlayer()->ReadMovementInfo(recvData, &movementInfo, &extras);
// now can skip not our packet
- if (_player->GetGUID() != guid)
+ if (_player->GetGUID() != movementInfo.guid)
{
recvData.rfinish(); // prevent warnings spam
return;
}
- // continue parse packet
-
- recvData >> unk1; // counter or moveEvent
-
- MovementInfo movementInfo;
- movementInfo.guid = guid;
- ReadMovementInfo(recvData, &movementInfo);
-
- recvData >> newspeed;
+ float newspeed = extras.Data.floatData;
/*----------------*/
// client ACK send one packet for mounted/run case and need skip all except last from its
// in other cases anti-cheat check can be fail in false case
UnitMoveType move_type;
- UnitMoveType force_move_type;
- static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" };
+ static char const* const move_type_name[MAX_MOVE_TYPE] =
+ {
+ "Walk",
+ "Run",
+ "RunBack",
+ "Swim",
+ "SwimBack",
+ "TurnRate",
+ "Flight",
+ "FlightBack",
+ "PitchRate"
+ };
switch (opcode)
{
- case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break;
- case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break;
- case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break;
- case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break;
- case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break;
- case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break;
- case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break;
- case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break;
- case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break;
+ case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; break;
+ case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; break;
+ case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; break;
+ case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; break;
+ case CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; break;
+ case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; break;
+ case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; break;
+ case CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; break;
+ case CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; break;
default:
TC_LOG_ERROR("network", "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode);
return;
}
// skip all forced speed changes except last and unexpected
- // in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both.
- if (_player->m_forced_speed_changes[force_move_type] > 0)
+ // in run/mounted case used one ACK and it must be skipped. m_forced_speed_changes[MOVE_RUN] store both.
+ if (_player->m_forced_speed_changes[move_type] > 0)
{
- --_player->m_forced_speed_changes[force_move_type];
- if (_player->m_forced_speed_changes[force_move_type] > 0)
+ --_player->m_forced_speed_changes[move_type];
+ if (_player->m_forced_speed_changes[move_type] > 0)
return;
}
@@ -484,17 +496,34 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData)
}
}
-void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recvData)
+void WorldSession::HandleSetActiveMoverOpcode(WorldPacket& recvPacket)
{
TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_SET_ACTIVE_MOVER");
- uint64 guid;
- recvData >> guid;
+ ObjectGuid guid;
+
+ guid[7] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[0] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[0]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[7]);
if (GetPlayer()->IsInWorld())
{
if (_player->m_mover->GetGUID() != guid)
- TC_LOG_DEBUG("network", "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " (%s - Entry: %u) and should be " UI64FMTD, guid, GetLogNameForGuid(guid), GUID_ENPART(guid), _player->m_mover->GetGUID());
+ TC_LOG_DEBUG("network", "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " (%s - Entry: %u) and should be " UI64FMTD, uint64(guid), GetLogNameForGuid(guid), GUID_ENPART(guid), _player->m_mover->GetGUID());
}
}
@@ -502,14 +531,8 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recvData)
{
TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER");
- uint64 old_mover_guid;
- recvData.readPackGUID(old_mover_guid);
-
MovementInfo mi;
- ReadMovementInfo(recvData, &mi);
-
- mi.guid = old_mover_guid;
-
+ GetPlayer()->ReadMovementInfo(recvData, &mi);
_player->m_movementInfo = mi;
}
@@ -525,29 +548,16 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "CMSG_MOVE_KNOCK_BACK_ACK");
- uint64 guid;
- recvData.readPackGUID(guid);
+ MovementInfo movementInfo;
+ GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
- if (_player->m_mover->GetGUID() != guid)
+ if (_player->m_mover->GetGUID() != movementInfo.guid)
return;
- recvData.read_skip<uint32>(); // unk
-
- MovementInfo movementInfo;
- ReadMovementInfo(recvData, &movementInfo);
-
_player->m_movementInfo = movementInfo;
- WorldPacket data(MSG_MOVE_KNOCK_BACK, 66);
- data.appendPackGUID(guid);
- _player->BuildMovementPacket(&data);
-
- // knockback specific info
- data << movementInfo.jump.sinAngle;
- data << movementInfo.jump.cosAngle;
- data << movementInfo.jump.xyspeed;
- data << movementInfo.jump.zspeed;
-
+ WorldPacket data(SMSG_MOVE_UPDATE_KNOCK_BACK, 66);
+ _player->WriteMovementInfo(data);
_player->SendMessageToSet(&data, false);
}
@@ -561,7 +571,7 @@ void WorldSession::HandleMoveHoverAck(WorldPacket& recvData)
recvData.read_skip<uint32>(); // unk
MovementInfo movementInfo;
- ReadMovementInfo(recvData, &movementInfo);
+ GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
recvData.read_skip<uint32>(); // unk2
}
@@ -576,7 +586,7 @@ void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recvData)
recvData.read_skip<uint32>(); // unk
MovementInfo movementInfo;
- ReadMovementInfo(recvData, &movementInfo);
+ GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
recvData.read_skip<uint32>(); // unk2
}
@@ -586,10 +596,20 @@ void WorldSession::HandleSummonResponseOpcode(WorldPacket& recvData)
if (!_player->IsAlive() || _player->IsInCombat())
return;
- uint64 summoner_guid;
+ uint64 summonerGuid;
bool agree;
- recvData >> summoner_guid;
+ recvData >> summonerGuid;
recvData >> agree;
_player->SummonIfPossible(agree);
}
+
+void WorldSession::HandleSetCollisionHeightAck(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "CMSG_MOVE_SET_COLLISION_HEIGHT_ACK");
+
+ static MovementStatusElements const heightElement = MSEExtraFloat;
+ Movement::ExtraMovementStatusElement extra(&heightElement);
+ MovementInfo movementInfo;
+ GetPlayer()->ReadMovementInfo(recvPacket, &movementInfo, &extra);
+}
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index 1311cda1ef9..02651a1af09 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -41,11 +41,12 @@
enum StableResultCode
{
STABLE_ERR_MONEY = 0x01, // "you don't have enough money"
- STABLE_ERR_STABLE = 0x06, // currently used in most fail cases
+ STABLE_ERR_INVALID_SLOT = 0x03, // "That slot is locked"
STABLE_SUCCESS_STABLE = 0x08, // stable success
STABLE_SUCCESS_UNSTABLE = 0x09, // unstable/swap success
STABLE_SUCCESS_BUY_SLOT = 0x0A, // buy slot success
- STABLE_ERR_EXOTIC = 0x0C // "you are unable to control exotic creatures"
+ STABLE_ERR_EXOTIC = 0x0B, // "you are unable to control exotic creatures"
+ STABLE_ERR_STABLE = 0x0C, // "Internal pet error"
};
void WorldSession::HandleTabardVendorActivateOpcode(WorldPacket& recvData)
@@ -104,13 +105,6 @@ void WorldSession::SendShowBank(uint64 guid)
SendPacket(&data);
}
-void WorldSession::SendShowMailBox(uint64 guid)
-{
- WorldPacket data(SMSG_SHOW_MAILBOX, 8);
- data << guid;
- SendPacket(&data);
-}
-
void WorldSession::HandleTrainerListOpcode(WorldPacket& recvData)
{
uint64 guid;
@@ -159,6 +153,7 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
WorldPacket data(SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1);
data << guid;
data << uint32(trainer_spells->trainerType);
+ data << uint32(1); // different value for each trainer, also found in CMSG_TRAINER_BUY_SPELL
size_t count_pos = data.wpos();
data << uint32(trainer_spells->spellList.size());
@@ -196,9 +191,6 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state);
data << uint32(floor(tSpell->spellCost * fDiscountMod));
- data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0);
- // primary prof. learn confirmation dialog
- data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state
data << uint8(tSpell->reqLevel);
data << uint32(tSpell->reqSkill);
data << uint32(tSpell->reqSkillValue);
@@ -213,7 +205,7 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
data << uint32(prevSpellId);
++maxReq;
}
- if (maxReq == 3)
+ if (maxReq == 2)
break;
SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(tSpell->learnedSpell[i]);
for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2)
@@ -221,15 +213,19 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
data << uint32(itr2->second);
++maxReq;
}
- if (maxReq == 3)
+ if (maxReq == 2)
break;
}
- while (maxReq < 3)
+ while (maxReq < 2)
{
data << uint32(0);
++maxReq;
}
+ data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0);
+ // primary prof. learn confirmation dialog
+ data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state
+
++count;
}
@@ -242,9 +238,10 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData)
{
uint64 guid;
- uint32 spellId = 0;
+ uint32 spellId;
+ uint32 trainerId;
- recvData >> guid >> spellId;
+ recvData >> guid >> trainerId >> spellId;
TC_LOG_DEBUG("network", "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u", uint32(GUID_LOPART(guid)), spellId);
Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER);
@@ -261,28 +258,40 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData)
// check present spell in trainer spell list
TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
if (!trainer_spells)
+ {
+ SendTrainerBuyFailed(guid, spellId, 0);
return;
+ }
// not found, cheat?
TrainerSpell const* trainer_spell = trainer_spells->Find(spellId);
if (!trainer_spell)
+ {
+ SendTrainerBuyFailed(guid, spellId, 0);
return;
+ }
// can't be learn, cheat? Or double learn with lags...
if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
+ {
+ SendTrainerBuyFailed(guid, spellId, 0);
return;
+ }
// apply reputation discount
uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit)));
// check money requirement
- if (!_player->HasEnoughMoney(nSpellCost))
+ if (!_player->HasEnoughMoney(uint64(nSpellCost)))
+ {
+ SendTrainerBuyFailed(guid, spellId, 1);
return;
+ }
- _player->ModifyMoney(-int32(nSpellCost));
+ _player->ModifyMoney(-int64(nSpellCost));
- unit->SendPlaySpellVisual(179); // 53 SpellCastDirected
- unit->SendPlaySpellImpact(_player->GetGUID(), 362); // 113 EmoteSalute
+ unit->SendPlaySpellVisualKit(179, 0); // 53 SpellCastDirected
+ _player->SendPlaySpellVisualKit(362, 1); // 113 EmoteSalute
// learn explicitly or cast explicitly
if (trainer_spell->IsCastable())
@@ -292,7 +301,16 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData)
WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12);
data << uint64(guid);
- data << uint32(spellId); // should be same as in packet from client
+ data << uint32(spellId);
+ SendPacket(&data);
+}
+
+void WorldSession::SendTrainerBuyFailed(uint64 guid, uint32 spellId, uint32 reason)
+{
+ WorldPacket data(SMSG_TRAINER_BUY_FAILED, 16);
+ data << uint64(guid);
+ data << uint32(spellId); // should be same as in packet from client
+ data << uint32(reason); // 1 == "Not enough money for trainer service." 0 == "Trainer service %d unavailable."
SendPacket(&data);
}
@@ -320,9 +338,7 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket& recvData)
// GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
if (unit->IsArmorer() || unit->IsCivilian() || unit->IsQuestGiver() || unit->IsServiceProvider() || unit->IsGuard())
- {
unit->StopMoving();
- }
// If spiritguide, no need for gossip menu, just put player into resurrect queue
if (unit->IsSpiritGuide())
@@ -472,7 +488,7 @@ void WorldSession::SendBindPoint(Creature* npc)
// send spell for homebinding (3286)
npc->CastSpell(_player, bindspell, true);
- WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, (8+4));
+ WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12);
data << uint64(npc->GetGUID());
data << uint32(bindspell);
SendPacket(&data);
@@ -536,6 +552,7 @@ void WorldSession::SendStablePetCallback(PreparedQueryResult result, uint64 guid
// not let move dead pet in slot
if (pet && pet->IsAlive() && pet->getPetType() == HUNTER_PET)
{
+ data << uint32(num); // 4.x unknown, some kind of order?
data << uint32(pet->GetCharmInfo()->GetPetNumber());
data << uint32(pet->GetEntry());
data << uint32(pet->getLevel());
@@ -550,6 +567,7 @@ void WorldSession::SendStablePetCallback(PreparedQueryResult result, uint64 guid
{
Field* fields = result->Fetch();
+ data << uint32(num);
data << uint32(fields[1].GetUInt32()); // petnumber
data << uint32(fields[2].GetUInt32()); // creature entry
data << uint32(fields[3].GetUInt16()); // level
@@ -638,14 +656,13 @@ void WorldSession::HandleStablePetCallback(PreparedQueryResult result)
while (result->NextRow());
}
- WorldPacket data(SMSG_STABLE_RESULT, 1);
if (freeSlot > 0 && freeSlot <= GetPlayer()->m_stableSlots)
{
_player->RemovePet(_player->GetPet(), PetSaveMode(freeSlot));
SendStableResult(STABLE_SUCCESS_STABLE);
}
else
- SendStableResult(STABLE_ERR_STABLE);
+ SendStableResult(STABLE_ERR_INVALID_SLOT);
}
void WorldSession::HandleUnstablePet(WorldPacket& recvData)
@@ -748,7 +765,7 @@ void WorldSession::HandleBuyStableSlot(WorldPacket& recvData)
if (GetPlayer()->m_stableSlots < MAX_PET_STABLES)
{
- StableSlotPricesEntry const* SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
+ /*StableSlotPricesEntry const* SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
if (_player->HasEnoughMoney(SlotPrice->Price))
{
++GetPlayer()->m_stableSlots;
@@ -756,7 +773,7 @@ void WorldSession::HandleBuyStableSlot(WorldPacket& recvData)
SendStableResult(STABLE_SUCCESS_BUY_SLOT);
}
else
- SendStableResult(STABLE_ERR_MONEY);
+ SendStableResult(STABLE_ERR_MONEY);*/
}
else
SendStableResult(STABLE_ERR_STABLE);
@@ -827,13 +844,15 @@ void WorldSession::HandleStableSwapPetCallback(PreparedQueryResult result, uint3
}
CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petEntry);
- if (!creatureInfo || !creatureInfo->IsTameable(_player->CanTameExoticPets()))
+ if (!creatureInfo || !creatureInfo->IsTameable(true))
{
- // if problem in exotic pet
- if (creatureInfo && creatureInfo->IsTameable(true))
- SendStableResult(STABLE_ERR_EXOTIC);
- else
- SendStableResult(STABLE_ERR_STABLE);
+ SendStableResult(STABLE_ERR_STABLE);
+ return;
+ }
+
+ if (!creatureInfo->IsTameable(_player->CanTameExoticPets()))
+ {
+ SendStableResult(STABLE_ERR_EXOTIC);
return;
}
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 9346e982bd2..f3dc24a8c01 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -61,9 +61,14 @@ void WorldSession::HandlePetAction(WorldPacket& recvData)
uint64 guid1;
uint32 data;
uint64 guid2;
+ float x, y, z;
recvData >> guid1; //pet guid
recvData >> data;
recvData >> guid2; //tag guid
+ // Position
+ recvData >> x;
+ recvData >> y;
+ recvData >> z;
uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data);
uint8 flag = UNIT_ACTION_BUTTON_TYPE(data); //delete = 0x07 CastSpell = C1
@@ -98,7 +103,7 @@ void WorldSession::HandlePetAction(WorldPacket& recvData)
return;
if (GetPlayer()->m_Controlled.size() == 1)
- HandlePetActionHelper(pet, guid1, spellid, flag, guid2);
+ HandlePetActionHelper(pet, guid1, spellid, flag, guid2, x, y, z);
else
{
//If a pet is dismissed, m_Controlled will change
@@ -107,7 +112,7 @@ void WorldSession::HandlePetAction(WorldPacket& recvData)
if ((*itr)->GetEntry() == pet->GetEntry() && (*itr)->IsAlive())
controlled.push_back(*itr);
for (std::vector<Unit*>::iterator itr = controlled.begin(); itr != controlled.end(); ++itr)
- HandlePetActionHelper(*itr, guid1, spellid, flag, guid2);
+ HandlePetActionHelper(*itr, guid1, spellid, flag, guid2, x, y, z);
}
}
@@ -139,7 +144,7 @@ void WorldSession::HandlePetStopAttack(WorldPacket &recvData)
pet->AttackStop();
}
-void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid, uint16 flag, uint64 guid2)
+void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid, uint16 flag, uint64 guid2, float x, float y, float z)
{
CharmInfo* charmInfo = pet->GetCharmInfo();
if (!charmInfo)
@@ -261,6 +266,18 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid
}
}
break;
+ case COMMAND_MOVE_TO:
+ pet->StopMoving();
+ pet->GetMotionMaster()->Clear(false);
+ pet->GetMotionMaster()->MovePoint(0, x, y, z);
+ charmInfo->SetCommandState(COMMAND_MOVE_TO);
+
+ charmInfo->SetIsCommandAttack(false);
+ charmInfo->SetIsAtStay(true);
+ charmInfo->SetIsFollowing(false);
+ charmInfo->SetIsReturning(false);
+ charmInfo->SaveStayPosition();
+ break;
default:
TC_LOG_ERROR("network", "WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid);
}
@@ -680,15 +697,7 @@ void WorldSession::HandlePetAbandon(WorldPacket& recvData)
if (pet)
{
if (pet->IsPet())
- {
- if (pet->GetGUID() == _player->GetPetGUID())
- {
- uint32 feelty = pet->GetPower(POWER_HAPPINESS);
- pet->SetPower(POWER_HAPPINESS, feelty > 50000 ? (feelty-50000) : 0);
- }
-
_player->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED);
- }
else if (pet->GetGUID() == _player->GetCharmGUID())
_player->StopCastingCharm();
}
@@ -833,14 +842,11 @@ void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, Dec
WorldPacket data(SMSG_PET_NAME_INVALID, 4 + name.size() + 1 + 1);
data << uint32(error);
data << name;
+ data << uint8(declinedName ? 1 : 0);
if (declinedName)
- {
- data << uint8(1);
for (uint32 i = 0; i < MAX_DECLINED_NAME_CASES; ++i)
data << declinedName->name[i];
- }
- else
- data << uint8(0);
+
SendPacket(&data);
}
@@ -868,8 +874,8 @@ void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket& recvData)
uint32 talentId, talentRank;
- // Client has max 24 talents, rounded up : 30
- uint32 const MaxTalentsCount = 30;
+ // Client has max 19 talents, rounded up : 25
+ uint32 const MaxTalentsCount = 25;
for (uint32 i = 0; i < talentsCount && i < MaxTalentsCount; ++i)
{
diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp
index d02b8986e08..8eb699a978f 100644
--- a/src/server/game/Handlers/PetitionsHandler.cpp
+++ b/src/server/game/Handlers/PetitionsHandler.cpp
@@ -182,7 +182,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
return;
}
- if (!_player->HasEnoughMoney(cost))
+ if (!_player->HasEnoughMoney(uint64(cost)))
{ //player hasn't got enough money
_player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, charterid, 0);
return;
@@ -382,7 +382,7 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
void WorldSession::HandlePetitionRenameOpcode(WorldPacket& recvData)
{
- TC_LOG_DEBUG("network", "Received opcode MSG_PETITION_RENAME"); // ok
+ TC_LOG_DEBUG("network", "Received opcode MSG_PETITION_RENAME");
uint64 petitionGuid;
uint32 type;
@@ -550,14 +550,10 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData)
WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
data << uint64(petitionGuid);
data << uint64(_player->GetGUID());
- data << (uint32)PETITION_SIGN_ALREADY_SIGNED;
+ data << uint32(PETITION_SIGN_ALREADY_SIGNED);
// close at signer side
SendPacket(&data);
-
- // update for owner if online
- if (Player* owner = ObjectAccessor::FindPlayer(ownerGuid))
- owner->GetSession()->SendPacket(&data);
return;
}
@@ -779,7 +775,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData)
if (_player->GetGuildId())
{
data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
- data << (uint32)PETITION_TURN_ALREADY_IN_GUILD;
+ data << uint32(PETITION_TURN_ALREADY_IN_GUILD);
_player->GetSession()->SendPacket(&data);
return;
}
diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp
index dbcfb1c4970..fb160c2bc41 100644
--- a/src/server/game/Handlers/QueryHandler.cpp
+++ b/src/server/game/Handlers/QueryHandler.cpp
@@ -96,57 +96,75 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData)
uint64 guid;
recvData >> guid;
- CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(entry);
- if (ci)
+ CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(entry);
+ if (creatureInfo)
{
+ std::string Name, FemaleName, SubName;
+ Name = creatureInfo->Name;
+ FemaleName = creatureInfo->FemaleName;
+ SubName = creatureInfo->SubName;
- std::string Name, SubName;
- Name = ci->Name;
- SubName = ci->SubName;
-
- int loc_idx = GetSessionDbLocaleIndex();
- if (loc_idx >= 0)
+ LocaleConstant locale = GetSessionDbLocaleIndex();
+ if (locale >= 0)
{
- if (CreatureLocale const* cl = sObjectMgr->GetCreatureLocale(entry))
+ if (CreatureLocale const* creatureLocale = sObjectMgr->GetCreatureLocale(entry))
{
- ObjectMgr::GetLocaleString(cl->Name, loc_idx, Name);
- ObjectMgr::GetLocaleString(cl->SubName, loc_idx, SubName);
+ ObjectMgr::GetLocaleString(creatureLocale->Name, locale, Name);
+ ObjectMgr::GetLocaleString(creatureLocale->FemaleName, locale, FemaleName);
+ ObjectMgr::GetLocaleString(creatureLocale->SubName, locale, SubName);
}
}
- TC_LOG_DEBUG("network", "WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry);
- // guess size
- WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100);
- data << uint32(entry); // creature entry
- data << Name;
- data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
- data << SubName;
- data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0
- data << uint32(ci->type_flags); // flags
- data << uint32(ci->type); // CreatureType.dbc
- data << uint32(ci->family); // CreatureFamily.dbc
- data << uint32(ci->rank); // Creature Rank (elite, boss, etc)
- data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit
- data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit
- data << uint32(ci->Modelid1); // Modelid1
- data << uint32(ci->Modelid2); // Modelid2
- data << uint32(ci->Modelid3); // Modelid3
- data << uint32(ci->Modelid4); // Modelid4
- data << float(ci->ModHealth); // dmg/hp modifier
- data << float(ci->ModMana); // dmg/mana modifier
- data << uint8(ci->RacialLeader);
- for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
- data << uint32(ci->questItems[i]); // itemId[6], quest drop
- data << uint32(ci->movementId); // CreatureMovementInfo.dbc
+
+ TC_LOG_DEBUG("network", "WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", creatureInfo->Name.c_str(), entry);
+
+ WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100); // guess size
+ data << uint32(entry); // creature entry
+ data << Name; // Name
+
+ for (uint8 i = 0; i < 3; i++)
+ data << uint8(0); // name2, ..., name3
+
+ data << FemaleName; // FemaleName
+
+ for (uint8 i = 0; i < 3; i++)
+ data << uint8(0); // name5, ..., name8
+
+ data << SubName; // SubName
+ data << creatureInfo->IconName; // "Directions" for guard, string for Icons 2.3.0
+ data << uint32(creatureInfo->type_flags); // flags
+ data << uint32(creatureInfo->type_flags2); // unknown meaning
+ data << uint32(creatureInfo->type); // CreatureType.dbc
+ data << uint32(creatureInfo->family); // CreatureFamily.dbc
+ data << uint32(creatureInfo->rank); // Creature Rank (elite, boss, etc)
+ data << uint32(creatureInfo->KillCredit[0]); // new in 3.1, kill credit
+ data << uint32(creatureInfo->KillCredit[1]); // new in 3.1, kill credit
+ data << uint32(creatureInfo->Modelid1); // Modelid1
+ data << uint32(creatureInfo->Modelid2); // Modelid2
+ data << uint32(creatureInfo->Modelid3); // Modelid3
+ data << uint32(creatureInfo->Modelid4); // Modelid4
+ data << float(creatureInfo->ModHealth); // dmg/hp modifier
+ data << float(creatureInfo->ModMana); // dmg/mana modifier
+ data << uint8(creatureInfo->RacialLeader); // RacialLeader
+
+ for (uint8 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
+ data << uint32(creatureInfo->questItems[i]); // itemId[6], quest drop
+
+ data << uint32(creatureInfo->movementId); // CreatureMovementInfo.dbc
+ data << uint32(creatureInfo->expansionUnknown); // unknown meaning
+
SendPacket(&data);
+
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE");
}
else
{
TC_LOG_DEBUG("network", "WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! (GUID: %u, ENTRY: %u)",
GUID_LOPART(guid), entry);
+
WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 4);
data << uint32(entry | 0x80000000);
SendPacket(&data);
+
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE");
}
}
@@ -192,7 +210,8 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket& recvData)
data.append(info->raw.data, MAX_GAMEOBJECT_DATA);
data << float(info->size); // go size
for (uint32 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
- data << uint32(info->questItems[i]); // itemId[6], quest drop
+ data << uint32(info->questItems[i]); // itemId[6], quest drop
+ data << int32(info->unkInt32); // 4.x, unknown
SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
}
@@ -207,7 +226,7 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket& recvData)
}
}
-void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleCorpseQueryOpcode(WorldPacket& /*recvData*/)
{
TC_LOG_DEBUG("network", "WORLD: Received MSG_CORPSE_QUERY");
@@ -389,8 +408,8 @@ void WorldSession::HandleCorpseMapPositionQuery(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Recv CMSG_CORPSE_MAP_POSITION_QUERY");
- uint32 unk;
- recvData >> unk;
+ uint32 transportGuidLow;
+ recvData >> transportGuidLow;
WorldPacket data(SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE, 4+4+4+4);
data << float(0);
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index d4dc7a9ab0d..a01cfa6d5e7 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -65,8 +65,8 @@ void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recvData)
break;
}
- // inform client about status of quest
- _player->PlayerTalkClass->SendQuestGiverStatus(uint8(questStatus), guid);
+ //inform client about status of quest
+ _player->PlayerTalkClass->SendQuestGiverStatus(questStatus, guid);
}
void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket& recvData)
@@ -267,36 +267,48 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData)
TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_CHOOSE_REWARD npc = %u, quest = %u, reward = %u", uint32(GUID_LOPART(guid)), questId, reward);
- Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT);
- if (!object || !object->hasInvolvedQuest(questId))
+ Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
+ if (!quest)
return;
- // some kind of WPE protection
- if (!_player->CanInteractWithQuestGiver(object))
- return;
+ Object* object = _player;
- if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
+ if (!quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
{
- if ((!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) ||
- (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE && !quest->IsAutoComplete()))
- {
- TC_LOG_ERROR("network", "Error in QUEST_STATUS_COMPLETE: player %s (guid %u) tried to complete quest %u, but is not allowed to do so (possible packet-hacking or high latency)",
- _player->GetName().c_str(), _player->GetGUIDLow(), questId);
+ object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
+ if (!object || !object->hasInvolvedQuest(questId))
return;
- }
- if (_player->CanRewardQuest(quest, reward, true))
- {
- _player->RewardQuest(quest, reward, object);
- switch (object->GetTypeId())
+ // some kind of WPE protection
+ if (!_player->CanInteractWithQuestGiver(object))
+ return;
+ }
+
+ if ((!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) ||
+ (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE && !quest->IsAutoComplete()))
+ {
+ TC_LOG_ERROR("network", "Error in QUEST_STATUS_COMPLETE: player %s (guid %u) tried to complete quest %u, but is not allowed to do so (possible packet-hacking or high latency)",
+ _player->GetName().c_str(), _player->GetGUIDLow(), questId);
+ return;
+ }
+
+ if (_player->CanRewardQuest(quest, reward, true))
+ {
+ _player->RewardQuest(quest, reward, object);
+
+ switch (object->GetTypeId())
+ {
+ case TYPEID_UNIT:
+ case TYPEID_PLAYER:
{
- case TYPEID_UNIT:
+ //For AutoSubmition was added plr case there as it almost same exclute AI script cases.
+ Creature* creatureQGiver = object->ToCreature();
+ if (!creatureQGiver || !(sScriptMgr->OnQuestReward(_player, creatureQGiver, quest, reward)))
{
- Creature* questgiver = object->ToCreature();
- if (!sScriptMgr->OnQuestReward(_player, questgiver, quest, reward))
+ // Send next quest
+ if (Quest const* nextQuest = _player->GetNextQuest(guid, quest))
{
- // Send next quest
- if (Quest const* nextQuest = _player->GetNextQuest(guid, quest))
+ if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true))
{
if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true))
_player->AddQuestAndCheckCompletion(nextQuest, object);
@@ -304,17 +316,23 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData)
_player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true);
}
- questgiver->AI()->sQuestReward(_player, quest, reward);
+ _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true);
}
- break;
+
+ if (creatureQGiver)
+ creatureQGiver->AI()->sQuestReward(_player, quest, reward);
}
- case TYPEID_GAMEOBJECT:
+ break;
+ }
+ case TYPEID_GAMEOBJECT:
+ {
+ GameObject* questGiver = object->ToGameObject();
+ if (!sScriptMgr->OnQuestReward(_player, questGiver, quest, reward))
{
- GameObject* questGiver = object->ToGameObject();
- if (!sScriptMgr->OnQuestReward(_player, questGiver, quest, reward))
+ // Send next quest
+ if (Quest const* nextQuest = _player->GetNextQuest(guid, quest))
{
- // Send next quest
- if (Quest const* nextQuest = _player->GetNextQuest(guid, quest))
+ if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true))
{
if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true))
_player->AddQuestAndCheckCompletion(nextQuest, object);
@@ -322,17 +340,19 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData)
_player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true);
}
- questGiver->AI()->QuestReward(_player, quest, reward);
+ _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true);
}
- break;
+
+ questGiver->AI()->QuestReward(_player, quest, reward);
}
- default:
- break;
+ break;
}
+ default:
+ break;
}
- else
- _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true);
}
+ else
+ _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true);
}
void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPacket& recvData)
@@ -425,7 +445,7 @@ void WorldSession::HandleQuestConfirmAccept(WorldPacket& recvData)
uint32 questId;
recvData >> questId;
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT quest = %u", questId);
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT questId = %u", questId);
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
{
@@ -449,28 +469,48 @@ void WorldSession::HandleQuestConfirmAccept(WorldPacket& recvData)
void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData)
{
uint32 questId;
- uint64 guid;
-
- recvData >> guid >> questId;
+ uint64 guid; // NPC / GameObject guid for normal quest completion. Player guid for self-completed quests
+ bool autoCompleteMode; // 0 - standart complete quest mode with npc, 1 - auto-complete mode
+ recvData >> guid >> questId >> autoCompleteMode;
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, quest = %u", uint32(GUID_LOPART(guid)), questId);
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, questId = %u self-complete: %u", uint32(GUID_LOPART(guid)), questId, autoCompleteMode ? 1 : 0);
Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
if (!quest)
return;
- Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT);
- if (!object || !object->hasInvolvedQuest(questId))
+ if (autoCompleteMode && !quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
return;
- // some kind of WPE protection
- if (!_player->CanInteractWithQuestGiver(object))
+ Object* object = nullptr;
+ if (autoCompleteMode)
+ object = _player;
+ else
+ object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT);
+
+ if (!object)
return;
+ if (autoCompleteMode == 0)
+ {
+ if (!object->hasInvolvedQuest(questId))
+ return;
+
+ // some kind of WPE protection
+ if (!_player->CanInteractWithQuestGiver(object))
+ return;
+ }
+ else
+ {
+ // Do not allow completing quests on other players.
+ if (guid != _player->GetGUID())
+ return;
+ }
+
if (!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE)
{
TC_LOG_ERROR("network", "Possible hacking attempt: Player %s [guid: %u] tried to complete quest [entry: %u] without being in possession of the quest!",
- _player->GetName().c_str(), _player->GetGUIDLow(), questId);
+ _player->GetName().c_str(), _player->GetGUIDLow(), questId);
return;
}
@@ -563,7 +603,7 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket)
if (quest->IsAutoAccept() && receiver->CanAddQuest(quest, true) && receiver->CanTakeQuest(quest, true))
receiver->AddQuestAndCheckCompletion(quest, sender);
- if ((quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) || quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
+ if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
receiver->PlayerTalkClass->SendQuestGiverRequestItems(quest, sender->GetGUID(), receiver->CanCompleteRepeatableQuest(quest), true);
else
{
@@ -602,7 +642,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
uint32 count = 0;
- WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4);
+ WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4 + 8 + 4);
data << uint32(count); // placeholder
for (Player::ClientGUIDs::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr)
@@ -621,7 +661,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
questStatus = _player->GetQuestDialogStatus(questgiver);
data << uint64(questgiver->GetGUID());
- data << uint8(questStatus);
+ data << uint32(questStatus);
++count;
}
else if (IS_GAMEOBJECT_GUID(*itr))
@@ -633,7 +673,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
questStatus = _player->GetQuestDialogStatus(questgiver);
data << uint64(questgiver->GetGUID());
- data << uint8(questStatus);
+ data << uint32(questStatus);
++count;
}
}
@@ -642,7 +682,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
SendPacket(&data);
}
-void WorldSession::HandleQueryQuestsCompleted(WorldPacket & /*recvData*/)
+void WorldSession::HandleQueryQuestsCompleted(WorldPacket& /*recvData*/)
{
size_t rew_count = _player->GetRewardedQuestCount();
diff --git a/src/server/game/Handlers/ReferAFriendHandler.cpp b/src/server/game/Handlers/ReferAFriendHandler.cpp
index 3b348b6e214..2efc9df5d94 100644
--- a/src/server/game/Handlers/ReferAFriendHandler.cpp
+++ b/src/server/game/Handlers/ReferAFriendHandler.cpp
@@ -48,7 +48,8 @@ void WorldSession::HandleGrantLevel(WorldPacket& recvData)
else if (target->GetGroup() != _player->GetGroup())
error = ERR_REFER_A_FRIEND_NOT_IN_GROUP;
- if (error) {
+ if (error)
+ {
WorldPacket data(SMSG_REFER_A_FRIEND_FAILURE, 24);
data << uint32(error);
if (error == ERR_REFER_A_FRIEND_NOT_IN_GROUP)
diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp
index 92c7c60bca0..8e10fc94ea6 100644
--- a/src/server/game/Handlers/SkillHandler.cpp
+++ b/src/server/game/Handlers/SkillHandler.cpp
@@ -29,30 +29,50 @@
void WorldSession::HandleLearnTalentOpcode(WorldPacket& recvData)
{
- uint32 talent_id, requested_rank;
- recvData >> talent_id >> requested_rank;
+ uint32 talentId, requestedRank;
+ recvData >> talentId >> requestedRank;
- _player->LearnTalent(talent_id, requested_rank);
- _player->SendTalentsInfoData(false);
+ if (_player->LearnTalent(talentId, requestedRank))
+ _player->SendTalentsInfoData(false);
}
void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket)
{
TC_LOG_DEBUG("network", "CMSG_LEARN_PREVIEW_TALENTS");
+ int32 tabPage;
uint32 talentsCount;
+ recvPacket >> tabPage; // talent tree
+
+ // prevent cheating (selecting new tree with points already in another)
+ if (tabPage >= 0) // -1 if player already has specialization
+ {
+ if (TalentTabEntry const* talentTabEntry = sTalentTabStore.LookupEntry(_player->GetPrimaryTalentTree(_player->GetActiveSpec())))
+ {
+ if (talentTabEntry->tabpage != uint32(tabPage))
+ {
+ recvPacket.rfinish();
+ return;
+ }
+ }
+ }
+
recvPacket >> talentsCount;
uint32 talentId, talentRank;
- // Client has max 44 talents for tree for 3 trees, rounded up : 150
- uint32 const MaxTalentsCount = 150;
+ // Client has max 21 talents for tree for 3 trees, rounded up : 70
+ uint32 const MaxTalentsCount = 70;
for (uint32 i = 0; i < talentsCount && i < MaxTalentsCount; ++i)
{
recvPacket >> talentId >> talentRank;
- _player->LearnTalent(talentId, talentRank);
+ if (!_player->LearnTalent(talentId, talentRank))
+ {
+ recvPacket.rfinish();
+ break;
+ }
}
_player->SendTalentsInfoData(false);
@@ -80,7 +100,7 @@ void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recvData)
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- if (!(_player->ResetTalents()))
+ if (!_player->ResetTalents())
{
WorldPacket data(MSG_TALENT_WIPE_CONFIRM, 8+4); //you have not any talent
data << uint64(0);
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index ba30803e8c2..04e64634d88 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -21,6 +21,7 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include "ObjectMgr.h"
+#include "GuildMgr.h"
#include "SpellMgr.h"
#include "Log.h"
#include "Opcodes.h"
@@ -50,9 +51,27 @@ void WorldSession::HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlag
uint8 hasMovementData;
recvPacket >> hasMovementData;
if (hasMovementData)
- {
- recvPacket.SetOpcode(recvPacket.read<uint32>());
HandleMovementOpcodes(recvPacket);
+ }
+ else if (castFlags & 0x8) // Archaeology
+ {
+ uint32 count, entry, usedCount;
+ uint8 type;
+ recvPacket >> count;
+ for (uint32 i = 0; i < count; ++i)
+ {
+ recvPacket >> type;
+ switch (type)
+ {
+ case 2: // Keystones
+ recvPacket >> entry; // Item id
+ recvPacket >> usedCount; // Item count
+ break;
+ case 1: // Fragments
+ recvPacket >> entry; // Currency id
+ recvPacket >> usedCount; // Currency count
+ break;
+ }
}
}
}
@@ -200,7 +219,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
// Verify that the bag is an actual bag or wrapped item that can be used "normally"
if (!(proto->Flags & ITEM_PROTO_FLAG_OPENABLE) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))
{
- pUser->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, NULL);
+ pUser->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, NULL);
TC_LOG_ERROR("network", "Possible hacking attempt: Player %s [guid: %u] tried to open item [guid: %u, entry: %u] which is not openable!",
pUser->GetName().c_str(), pUser->GetGUIDLow(), item->GetGUIDLow(), proto->ItemId);
return;
@@ -310,9 +329,13 @@ void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket)
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
- uint32 spellId;
+ uint32 spellId, glyphIndex;
uint8 castCount, castFlags;
- recvPacket >> castCount >> spellId >> castFlags;
+
+ recvPacket >> castCount;
+ recvPacket >> spellId;
+ recvPacket >> glyphIndex;
+ recvPacket >> castFlags;
TC_LOG_DEBUG("network", "WORLD: got cast spell packet, castCount: %u, spellId: %u, castFlags: %u, data length = %u", castCount, spellId, castFlags, (uint32)recvPacket.size());
@@ -359,6 +382,27 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
return;
}
+ Unit::AuraEffectList swaps = mover->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS);
+ Unit::AuraEffectList const& swaps2 = mover->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2);
+ if (!swaps2.empty())
+ swaps.insert(swaps.end(), swaps2.begin(), swaps2.end());
+
+ if (!swaps.empty())
+ {
+ for (Unit::AuraEffectList::const_iterator itr = swaps.begin(); itr != swaps.end(); ++itr)
+ {
+ if ((*itr)->IsAffectingSpell(spellInfo))
+ {
+ if (SpellInfo const* newInfo = sSpellMgr->GetSpellInfo((*itr)->GetAmount()))
+ {
+ spellInfo = newInfo;
+ spellId = newInfo->Id;
+ }
+ break;
+ }
+ }
+ }
+
// Client is resending autoshot cast opcode when other spell is cast during shoot rotation
// Skip it to prevent "interrupt" message
if (spellInfo->IsAutoRepeatRangedSpell() && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)
@@ -392,6 +436,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE, 0, false);
spell->m_cast_count = castCount; // set count of casts
+ spell->m_glyphIndex = glyphIndex;
spell->prepare(&targets);
}
@@ -506,8 +551,9 @@ void WorldSession::HandleTotemDestroyed(WorldPacket& recvPacket)
return;
uint8 slotId;
-
+ uint64 guid;
recvPacket >> slotId;
+ recvPacket >> guid;
++slotId;
if (slotId >= MAX_TOTEM_SLOT)
@@ -517,12 +563,11 @@ void WorldSession::HandleTotemDestroyed(WorldPacket& recvPacket)
return;
Creature* totem = GetPlayer()->GetMap()->GetCreature(_player->m_SummonSlot[slotId]);
-
- if (totem && totem->IsTotem())
+ if (totem && totem->IsTotem() && totem->GetGUID() == guid)
totem->ToTotem()->UnSummon();
}
-void WorldSession::HandleSelfResOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleSelfResOpcode(WorldPacket& /*recvData*/)
{
TC_LOG_DEBUG("network", "WORLD: CMSG_SELF_RES"); // empty opcode
@@ -562,6 +607,7 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData)
TC_LOG_DEBUG("network", "WORLD: CMSG_GET_MIRRORIMAGE_DATA");
uint64 guid;
recvData >> guid;
+ recvData.read_skip<uint32>(); // DisplayId ?
// Get unit for which data is needed by client
Unit* unit = ObjectAccessor::GetObjectInWorld(guid, (Unit*)NULL);
@@ -586,12 +632,17 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData)
if (creator->GetTypeId() == TYPEID_PLAYER)
{
Player* player = creator->ToPlayer();
+ Guild* guild = NULL;
+
+ if (uint32 guildId = player->GetGuildId())
+ guild = sGuildMgr->GetGuildById(guildId);
+
data << uint8(player->GetByteValue(PLAYER_BYTES, 0)); // skin
data << uint8(player->GetByteValue(PLAYER_BYTES, 1)); // face
data << uint8(player->GetByteValue(PLAYER_BYTES, 2)); // hair
data << uint8(player->GetByteValue(PLAYER_BYTES, 3)); // haircolor
data << uint8(player->GetByteValue(PLAYER_BYTES_2, 0)); // facialhair
- data << uint32(player->GetGuildId()); // unk
+ data << uint64(guild ? guild->GetGUID() : 0);
static EquipmentSlots const itemSlots[] =
{
@@ -680,3 +731,28 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket)
data << float(z);
caster->SendMessageToSet(&data, true);
}
+
+void WorldSession::HandleRequestCategoryCooldowns(WorldPacket& /*recvPacket*/)
+{
+ std::map<uint32, int32> categoryMods;
+ Unit::AuraEffectList const& categoryCooldownAuras = _player->GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN);
+ for (Unit::AuraEffectList::const_iterator itr = categoryCooldownAuras.begin(); itr != categoryCooldownAuras.end(); ++itr)
+ {
+ std::map<uint32, int32>::iterator cItr = categoryMods.find((*itr)->GetMiscValue());
+ if (cItr == categoryMods.end())
+ categoryMods[(*itr)->GetMiscValue()] = (*itr)->GetAmount();
+ else
+ cItr->second += (*itr)->GetAmount();
+ }
+
+ WorldPacket data(SMSG_SPELL_CATEGORY_COOLDOWN, 11);
+ data.WriteBits(categoryMods.size(), 23);
+ data.FlushBits();
+ for (std::map<uint32, int32>::const_iterator itr = categoryMods.begin(); itr != categoryMods.end(); ++itr)
+ {
+ data << uint32(itr->first);
+ data << int32(-itr->second);
+ }
+
+ SendPacket(&data);
+}
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index 34899fc23df..aaa9188b6f4 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -94,12 +94,12 @@ void WorldSession::SendTaxiMenu(Creature* unit)
{
// find current node
uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
-
- if (curloc == 0)
+ if (!curloc)
return;
bool lastTaxiCheaterState = GetPlayer()->isTaxiCheater();
- if (unit->GetEntry() == 29480) GetPlayer()->SetTaxiCheater(true); // Grimwing in Ebon Hold, special case. NOTE: Not perfect, Zul'Aman should not be included according to WoWhead, and I think taxicheat includes it.
+ if (unit->GetEntry() == 29480)
+ GetPlayer()->SetTaxiCheater(true); // Grimwing in Ebon Hold, special case. NOTE: Not perfect, Zul'Aman should not be included according to WoWhead, and I think taxicheat includes it.
TC_LOG_DEBUG("network", "WORLD: CMSG_TAXINODE_STATUS_QUERY %u ", curloc);
@@ -207,13 +207,10 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_MOVE_SPLINE_DONE");
- uint64 guid; // used only for proper packet read
- recvData.readPackGUID(guid);
+ recvData.read_skip<uint32>(); // unk
MovementInfo movementInfo; // used only for proper packet read
- ReadMovementInfo(recvData, &movementInfo);
-
- recvData.read_skip<uint32>(); // unk
+ _player->ReadMovementInfo(recvData, &movementInfo);
// in taxi flight packet received in 2 case:
// 1) end taxi path in far (multi-node) flight
diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp
index a2aa426c096..53cde5e8e5a 100644
--- a/src/server/game/Handlers/TicketHandler.cpp
+++ b/src/server/game/Handlers/TicketHandler.cpp
@@ -44,7 +44,7 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket& recvData)
GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID());
if (ticket && ticket->IsCompleted())
- sTicketMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID());;
+ sTicketMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID());
// Player must not have ticket
if (!ticket || ticket->IsClosed())
@@ -190,7 +190,7 @@ void WorldSession::HandleGMSurveySubmit(WorldPacket& recvData)
std::unordered_set<uint32> surveyIds;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
// sub_survey1, r1, comment1, sub_survey2, r2, comment2, sub_survey3, r3, comment3, sub_survey4, r4, comment4, sub_survey5, r5, comment5, sub_survey6, r6, comment6, sub_survey7, r7, comment7, sub_survey8, r8, comment8, sub_survey9, r9, comment9, sub_survey10, r10, comment10,
- for (uint8 i = 0; i < 10; i++)
+ for (uint8 i = 0; i < 15; i++)
{
uint32 subSurveyId; // ref to i'th GMSurveySurveys.dbc field (all fields in that dbc point to fields in GMSurveyQuestions.dbc)
recvData >> subSurveyId;
diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp
index 884c4a83b15..f6c403acb66 100644
--- a/src/server/game/Handlers/TradeHandler.cpp
+++ b/src/server/game/Handlers/TradeHandler.cpp
@@ -30,38 +30,47 @@
#include "Language.h"
#include "AccountMgr.h"
-void WorldSession::SendTradeStatus(TradeStatus status)
+void WorldSession::SendTradeStatus(TradeStatus status, int8 clearSlot)
{
WorldPacket data;
+ Player* trader = GetPlayer()->GetTrader();
+
+ data.Initialize(SMSG_TRADE_STATUS, 1+4+4);
+ data.WriteBit(trader ? (trader->GetSession()->GetBattlenetAccountId() == GetBattlenetAccountId()) : 0); // IsSameBnetAccount, used for trading heirlooms and other battle.net bound items with your other accounts
+ data.WriteBits(status, 5);
+
switch (status)
{
case TRADE_STATUS_BEGIN_TRADE:
- data.Initialize(SMSG_TRADE_STATUS, 4+8);
- data << uint32(status);
- data << uint64(0);
+ data.WriteBits(0, 8); // Trader Guid
+ data.FlushBits();
break;
case TRADE_STATUS_OPEN_WINDOW:
- data.Initialize(SMSG_TRADE_STATUS, 4+4);
- data << uint32(status);
- data << uint32(0); // added in 2.4.0
+ data.FlushBits();
+ data << uint32(0); // Trade Id
break;
case TRADE_STATUS_CLOSE_WINDOW:
- data.Initialize(SMSG_TRADE_STATUS, 4+4+1+4);
- data << uint32(status);
- data << uint32(0);
- data << uint8(0);
- data << uint32(0);
+ data.WriteBit(0); // Error bool (0 = Target, 1 = Self)
+ data.FlushBits();
+ data << uint32(0); // Error Item (Relevant item to the error)
+ data << uint32(0); // InventoryResult
break;
- case TRADE_STATUS_ONLY_CONJURED:
+ case TRADE_STATUS_ONLY_CONJURED: // Not Implemented
case TRADE_STATUS_NOT_ELIGIBLE:
- data.Initialize(SMSG_TRADE_STATUS, 4+1);
- data << uint32(status);
- data << uint8(0);
+ // Used when trading loot soulbound items with people that are not eligible (TRADE_STATUS_NOT_ELIGIBLE),
+ // and when trying to trade items with players in other realms when in a cross realm BG, you can only trade conjured goods with them (TRADE_STATUS_ONLY_CONJURED)
+ data.FlushBits();
+ data << int8(clearSlot); // Trade slot to clear, -1 = Clear the money amount
break;
+ case TRADE_STATUS_CURRENCY: // Not implemented
+ case TRADE_STATUS_CURRENCY_NOT_TRADABLE: // Not implemented
+ // Blizzard never implemented these, you can only trade currency with the field9 & 1 in CurrencyTypes.DBC, and only two test currencies have that flag
+ data.FlushBits();
+ data << uint32(0); // Trading Currency Id
+ data << uint32(0); // Trading Currency Amount
default:
- data.Initialize(SMSG_TRADE_STATUS, 4);
- data << uint32(status);
+ data.FlushBits();
break;
}
@@ -71,60 +80,117 @@ void WorldSession::SendTradeStatus(TradeStatus status)
void WorldSession::HandleIgnoreTradeOpcode(WorldPacket& /*recvPacket*/)
{
TC_LOG_DEBUG("network", "WORLD: Ignore Trade %u", _player->GetGUIDLow());
- // recvPacket.print_storage();
}
void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/)
{
TC_LOG_DEBUG("network", "WORLD: Busy Trade %u", _player->GetGUIDLow());
- // recvPacket.print_storage();
}
void WorldSession::SendUpdateTrade(bool trader_data /*= true*/)
{
TradeData* view_trade = trader_data ? _player->GetTradeData()->GetTraderData() : _player->GetTradeData();
- WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, 1+4+4+4+4+4+7*(1+4+4+4+4+8+4+4+4+4+8+4+4+4+4+4+4));
- data << uint8(trader_data); // 1 means traders data, 0 means own
- data << uint32(0); // added in 2.4.0, this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?)
+ ByteBuffer itemData(7*2 + 7*4 + 3*4 + 3*4 + 1);
+
+ uint8 count = 0;
+ for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
+ if (view_trade->GetItem(TradeSlots(i)))
+ ++count;
+
+ WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, 4*6 + 8 + 1 + 3 + count * 70);
+ data << uint32(0); // this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?)
+ data << uint32(0); // unk 2
+ data << uint64(view_trade->GetMoney()); // trader gold
+ data << uint32(view_trade->GetSpell()); // spell casted on lowest slot item
data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = next field in most cases
+ data << uint32(0); // unk 5
+ data << uint8(trader_data); // 1 means traders data, 0 means own
data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = prev field in most cases
- data << uint32(view_trade->GetMoney()); // trader gold
- data << uint32(view_trade->GetSpell()); // spell cast on lowest slot item
+ data.WriteBits(count, 22);
for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
{
- data << uint8(i); // trade slot number, if not specified, then end of packet
+ Item* item = view_trade->GetItem(TradeSlots(i));
+ if (!item)
+ continue;
- if (Item* item = view_trade->GetItem(TradeSlots(i)))
- {
- data << uint32(item->GetTemplate()->ItemId); // entry
- data << uint32(item->GetTemplate()->DisplayInfoID);// display id
- data << uint32(item->GetCount()); // stack count
- // wrapped: hide stats but show giftcreator name
- data << uint32(item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED) ? 1 : 0);
- data << uint64(item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR));
- // perm. enchantment and gems
- data << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
- for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
- data << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot)));
- // creator
- data << uint64(item->GetUInt64Value(ITEM_FIELD_CREATOR));
- data << uint32(item->GetSpellCharges()); // charges
- data << uint32(item->GetItemSuffixFactor()); // SuffixFactor
- data << uint32(item->GetItemRandomPropertyId());// random properties id
- data << uint32(item->GetTemplate()->LockID); // lock id
- // max durability
- data << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
- // durability
- data << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
- }
- else
+ ObjectGuid giftCreatorGuid = item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR);
+ ObjectGuid creatorGuid = item->GetUInt64Value(ITEM_FIELD_CREATOR);
+
+ data.WriteBit(giftCreatorGuid[7]);
+ data.WriteBit(giftCreatorGuid[1]);
+ bool notWrapped = data.WriteBit(!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED));
+ data.WriteBit(giftCreatorGuid[3]);
+
+ if (notWrapped)
{
- for (uint8 j = 0; j < 18; ++j)
- data << uint32(0);
+ data.WriteBit(creatorGuid[7]);
+ data.WriteBit(creatorGuid[1]);
+ data.WriteBit(creatorGuid[4]);
+ data.WriteBit(creatorGuid[6]);
+ data.WriteBit(creatorGuid[2]);
+ data.WriteBit(creatorGuid[3]);
+ data.WriteBit(creatorGuid[5]);
+ data.WriteBit(item->GetTemplate()->LockID != 0);
+ data.WriteBit(creatorGuid[0]);
+
+ itemData.WriteByteSeq(creatorGuid[1]);
+
+ itemData << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
+ for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS /*3*/; ++enchant_slot)
+ itemData << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot)));
+ itemData << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
+
+ itemData.WriteByteSeq(creatorGuid[6]);
+ itemData.WriteByteSeq(creatorGuid[2]);
+ itemData.WriteByteSeq(creatorGuid[7]);
+ itemData.WriteByteSeq(creatorGuid[4]);
+
+ itemData << uint32(item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT));
+ itemData << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
+ itemData << uint32(item->GetItemRandomPropertyId());
+
+ itemData.WriteByteSeq(creatorGuid[3]);
+
+ itemData << uint32(0); // unk7
+
+ itemData.WriteByteSeq(creatorGuid[0]);
+
+ itemData << uint32(item->GetSpellCharges());
+ itemData << uint32(item->GetItemSuffixFactor());
+
+ itemData.WriteByteSeq(creatorGuid[5]);
}
+
+ data.WriteBit(giftCreatorGuid[6]);
+ data.WriteBit(giftCreatorGuid[4]);
+ data.WriteBit(giftCreatorGuid[2]);
+ data.WriteBit(giftCreatorGuid[0]);
+ data.WriteBit(giftCreatorGuid[5]);
+
+ itemData.WriteByteSeq(giftCreatorGuid[6]);
+ itemData.WriteByteSeq(giftCreatorGuid[1]);
+ itemData.WriteByteSeq(giftCreatorGuid[7]);
+ itemData.WriteByteSeq(giftCreatorGuid[4]);
+
+ itemData << uint32(item->GetTemplate()->ItemId);
+
+ itemData.WriteByteSeq(giftCreatorGuid[0]);
+
+ itemData << uint32(item->GetCount());
+
+ itemData.WriteByteSeq(giftCreatorGuid[5]);
+
+ itemData << uint8(i);
+
+ itemData.WriteByteSeq(giftCreatorGuid[2]);
+ itemData.WriteByteSeq(giftCreatorGuid[3]);
}
+
+ data.FlushBits();
+ data.append(itemData);
+
SendPacket(&data);
}
@@ -299,14 +365,14 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
return;
}
- if (_player->GetMoney() >= MAX_MONEY_AMOUNT - his_trade->GetMoney())
+ if (_player->GetMoney() >= uint64(MAX_MONEY_AMOUNT) - his_trade->GetMoney())
{
_player->SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
my_trade->SetAccepted(false, true);
return;
}
- if (trader->GetMoney() >= MAX_MONEY_AMOUNT - my_trade->GetMoney())
+ if (trader->GetMoney() >= uint64(MAX_MONEY_AMOUNT) - my_trade->GetMoney())
{
trader->SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
his_trade->SetAccepted(false, true);
@@ -484,7 +550,7 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
{
if (my_trade->GetMoney() > 0)
{
- sLog->outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)",
+ sLog->outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: " UI64FMTD ") to player: %s (Account: %u)",
_player->GetName().c_str(), _player->GetSession()->GetAccountId(),
my_trade->GetMoney(),
trader->GetName().c_str(), trader->GetSession()->GetAccountId());
@@ -492,7 +558,7 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
if (his_trade->GetMoney() > 0)
{
- sLog->outCommand(trader->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)",
+ sLog->outCommand(trader->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: " UI64FMTD ") to player: %s (Account: %u)",
trader->GetName().c_str(), trader->GetSession()->GetAccountId(),
his_trade->GetMoney(),
_player->GetName().c_str(), _player->GetSession()->GetAccountId());
@@ -500,9 +566,9 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
}
// update money
- _player->ModifyMoney(-int32(my_trade->GetMoney()));
+ _player->ModifyMoney(-int64(my_trade->GetMoney()));
_player->ModifyMoney(his_trade->GetMoney());
- trader->ModifyMoney(-int32(his_trade->GetMoney()));
+ trader->ModifyMoney(-int64(his_trade->GetMoney()));
trader->ModifyMoney(my_trade->GetMoney());
if (my_spell)
@@ -562,15 +628,32 @@ void WorldSession::SendCancelTrade()
void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/)
{
- // sended also after LOGOUT COMPLETE
+ // sent also after LOGOUT COMPLETE
if (_player) // needed because STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT
_player->TradeCancel(true);
}
void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
{
- uint64 ID;
- recvPacket >> ID;
+ ObjectGuid guid;
+
+ guid[0] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[0]);
if (GetPlayer()->m_trade)
return;
@@ -605,7 +688,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
return;
}
- Player* pOther = ObjectAccessor::FindPlayer(ID);
+ Player* pOther = ObjectAccessor::FindPlayer(guid);
if (!pOther)
{
@@ -671,15 +754,36 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
_player->m_trade = new TradeData(_player, pOther);
pOther->m_trade = new TradeData(pOther, _player);
- WorldPacket data(SMSG_TRADE_STATUS, 12);
- data << uint32(TRADE_STATUS_BEGIN_TRADE);
- data << uint64(_player->GetGUID());
+ WorldPacket data(SMSG_TRADE_STATUS, 2+7);
+ data.WriteBit(0); // unk bit, usually 0
+ data.WriteBits(TRADE_STATUS_BEGIN_TRADE, 5);
+
+ ObjectGuid playerGuid = _player->GetGUID();
+ // WTB StartBitStream...
+ data.WriteBit(playerGuid[2]);
+ data.WriteBit(playerGuid[4]);
+ data.WriteBit(playerGuid[6]);
+ data.WriteBit(playerGuid[0]);
+ data.WriteBit(playerGuid[1]);
+ data.WriteBit(playerGuid[3]);
+ data.WriteBit(playerGuid[7]);
+ data.WriteBit(playerGuid[5]);
+
+ data.WriteByteSeq(playerGuid[4]);
+ data.WriteByteSeq(playerGuid[1]);
+ data.WriteByteSeq(playerGuid[2]);
+ data.WriteByteSeq(playerGuid[3]);
+ data.WriteByteSeq(playerGuid[0]);
+ data.WriteByteSeq(playerGuid[7]);
+ data.WriteByteSeq(playerGuid[6]);
+ data.WriteByteSeq(playerGuid[5]);
+
pOther->GetSession()->SendPacket(&data);
}
void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket)
{
- uint32 gold;
+ uint64 gold;
recvPacket >> gold;
TradeData* my_trade = _player->GetTradeData();
@@ -696,9 +800,9 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
uint8 bag;
uint8 slot;
+ recvPacket >> slot;
recvPacket >> tradeSlot;
recvPacket >> bag;
- recvPacket >> slot;
TradeData* my_trade = _player->GetTradeData();
if (!my_trade)
@@ -729,6 +833,13 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
return;
}
+ if (item->IsBindedNotWith(GetPlayer()->GetTrader()))
+ {
+ // The item is BOP tradeable but the trader wasn't eligible to get it.
+ SendTradeStatus(TRADE_STATUS_NOT_ELIGIBLE, tradeSlot);
+ return;
+ }
+
my_trade->SetItem(TradeSlots(tradeSlot), item);
}
diff --git a/src/server/game/Handlers/VehicleHandler.cpp b/src/server/game/Handlers/VehicleHandler.cpp
index b3fa240e2d2..e17b33c345b 100644
--- a/src/server/game/Handlers/VehicleHandler.cpp
+++ b/src/server/game/Handlers/VehicleHandler.cpp
@@ -22,6 +22,7 @@
#include "Player.h"
#include "Log.h"
#include "ObjectAccessor.h"
+#include "MovementStructures.h"
void WorldSession::HandleDismissControlledVehicle(WorldPacket &recvData)
{
@@ -35,20 +36,15 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recvData)
return;
}
- uint64 guid;
-
- recvData.readPackGUID(guid);
-
MovementInfo mi;
- mi.guid = guid;
- ReadMovementInfo(recvData, &mi);
+ _player->ReadMovementInfo(recvData, &mi);
_player->m_movementInfo = mi;
_player->ExitVehicle();
}
-void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recvData)
+void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
@@ -78,20 +74,36 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recvData)
break;
case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE:
{
- uint64 guid; // current vehicle guid
- recvData.readPackGUID(guid);
-
+ static MovementStatusElements const accessoryGuid[] =
+ {
+ MSEExtraInt8,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ };
+
+ Movement::ExtraMovementStatusElement extra(accessoryGuid);
MovementInfo movementInfo;
- ReadMovementInfo(recvData, &movementInfo);
+ GetPlayer()->ReadMovementInfo(recvData, &movementInfo, &extra);
vehicle_base->m_movementInfo = movementInfo;
- uint64 accessory; // accessory guid
- recvData.readPackGUID(accessory);
-
- int8 seatId;
- recvData >> seatId;
+ uint64 accessory = extra.Data.guid;
+ int8 seatId = extra.Data.byteData;
- if (vehicle_base->GetGUID() != guid)
+ if (vehicle_base->GetGUID() != movementInfo.guid)
return;
if (!accessory)
@@ -125,7 +137,7 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recvData)
}
}
-void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data)
+void WorldSession::HandleEnterPlayerVehicle(WorldPacket& data)
{
// Read guid
uint64 guid;
@@ -144,7 +156,7 @@ void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data)
}
}
-void WorldSession::HandleEjectPassenger(WorldPacket &data)
+void WorldSession::HandleEjectPassenger(WorldPacket& data)
{
Vehicle* vehicle = _player->GetVehicleKit();
if (!vehicle)
diff --git a/src/server/game/Handlers/VoiceChatHandler.cpp b/src/server/game/Handlers/VoiceChatHandler.cpp
index af2d8e20757..fd5d3adad84 100644
--- a/src/server/game/Handlers/VoiceChatHandler.cpp
+++ b/src/server/game/Handlers/VoiceChatHandler.cpp
@@ -30,10 +30,12 @@ void WorldSession::HandleVoiceSessionEnableOpcode(WorldPacket& recvData)
recvData.read_skip<uint8>();
}
-void WorldSession::HandleChannelVoiceOnOpcode(WorldPacket& /*recvData*/)
+void WorldSession::HandleChannelVoiceOnOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: CMSG_CHANNEL_VOICE_ON");
// Enable Voice button in channel context menu
+ recvData.ReadString(recvData.ReadBits(8));
+ //channel->EnableVoice(recvData.GetOpcode() == CMSG_CHANNEL_VOICE_ON);
}
void WorldSession::HandleSetActiveVoiceChannel(WorldPacket& recvData)
diff --git a/src/server/game/Handlers/VoidStorageHandler.cpp b/src/server/game/Handlers/VoidStorageHandler.cpp
new file mode 100644
index 00000000000..cf117762801
--- /dev/null
+++ b/src/server/game/Handlers/VoidStorageHandler.cpp
@@ -0,0 +1,619 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Common.h"
+#include "WorldPacket.h"
+#include "WorldSession.h"
+#include "World.h"
+#include "ObjectAccessor.h"
+#include "ObjectMgr.h"
+#include "Log.h"
+#include "Opcodes.h"
+#include "Player.h"
+#include <list>
+#include <vector>
+#include <utility>
+
+void WorldSession::SendVoidStorageTransferResult(VoidTransferError result)
+{
+ WorldPacket data(SMSG_VOID_TRANSFER_RESULT, 4);
+ data << uint32(result);
+ SendPacket(&data);
+}
+
+void WorldSession::HandleVoidStorageUnlock(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_VOID_STORAGE_UNLOCK");
+ Player* player = GetPlayer();
+
+ ObjectGuid npcGuid;
+ npcGuid[4] = recvData.ReadBit();
+ npcGuid[5] = recvData.ReadBit();
+ npcGuid[3] = recvData.ReadBit();
+ npcGuid[0] = recvData.ReadBit();
+ npcGuid[2] = recvData.ReadBit();
+ npcGuid[1] = recvData.ReadBit();
+ npcGuid[7] = recvData.ReadBit();
+ npcGuid[6] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(npcGuid[7]);
+ recvData.ReadByteSeq(npcGuid[1]);
+ recvData.ReadByteSeq(npcGuid[2]);
+ recvData.ReadByteSeq(npcGuid[3]);
+ recvData.ReadByteSeq(npcGuid[5]);
+ recvData.ReadByteSeq(npcGuid[0]);
+ recvData.ReadByteSeq(npcGuid[6]);
+ recvData.ReadByteSeq(npcGuid[4]);
+
+ Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER);
+ if (!unit)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageUnlock - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
+ return;
+ }
+
+ if (player->IsVoidStorageUnlocked())
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageUnlock - Player (GUID: %u, name: %s) tried to unlock void storage a 2nd time.", player->GetGUIDLow(), player->GetName().c_str());
+ return;
+ }
+
+ player->ModifyMoney(-int64(VOID_STORAGE_UNLOCK));
+ player->UnlockVoidStorage();
+}
+
+void WorldSession::HandleVoidStorageQuery(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_VOID_STORAGE_QUERY");
+ Player* player = GetPlayer();
+
+ ObjectGuid npcGuid;
+ npcGuid[4] = recvData.ReadBit();
+ npcGuid[0] = recvData.ReadBit();
+ npcGuid[5] = recvData.ReadBit();
+ npcGuid[7] = recvData.ReadBit();
+ npcGuid[6] = recvData.ReadBit();
+ npcGuid[3] = recvData.ReadBit();
+ npcGuid[1] = recvData.ReadBit();
+ npcGuid[2] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(npcGuid[5]);
+ recvData.ReadByteSeq(npcGuid[6]);
+ recvData.ReadByteSeq(npcGuid[3]);
+ recvData.ReadByteSeq(npcGuid[7]);
+ recvData.ReadByteSeq(npcGuid[1]);
+ recvData.ReadByteSeq(npcGuid[0]);
+ recvData.ReadByteSeq(npcGuid[4]);
+ recvData.ReadByteSeq(npcGuid[2]);
+
+ Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER);
+ if (!unit)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageQuery - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
+ return;
+ }
+
+ if (!player->IsVoidStorageUnlocked())
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageQuery - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str());
+ return;
+ }
+
+ uint8 count = 0;
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ if (player->GetVoidStorageItem(i))
+ ++count;
+
+ WorldPacket data(SMSG_VOID_STORAGE_CONTENTS, 2 * count + (14 + 4 + 4 + 4 + 4) * count);
+
+ data.WriteBits(count, 8);
+
+ ByteBuffer itemData((14 + 4 + 4 + 4 + 4) * count);
+
+ for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
+ {
+ VoidStorageItem* item = player->GetVoidStorageItem(i);
+ if (!item)
+ continue;
+
+ ObjectGuid itemId = item->ItemId;
+ ObjectGuid creatorGuid = item->CreatorGuid;
+
+ data.WriteBit(creatorGuid[3]);
+ data.WriteBit(itemId[5]);
+ data.WriteBit(creatorGuid[6]);
+ data.WriteBit(creatorGuid[1]);
+ data.WriteBit(itemId[1]);
+ data.WriteBit(itemId[3]);
+ data.WriteBit(itemId[6]);
+ data.WriteBit(creatorGuid[5]);
+ data.WriteBit(creatorGuid[2]);
+ data.WriteBit(itemId[2]);
+ data.WriteBit(creatorGuid[4]);
+ data.WriteBit(itemId[0]);
+ data.WriteBit(itemId[4]);
+ data.WriteBit(itemId[7]);
+ data.WriteBit(creatorGuid[0]);
+ data.WriteBit(creatorGuid[7]);
+
+ itemData.WriteByteSeq(creatorGuid[3]);
+
+ itemData << uint32(item->ItemSuffixFactor);
+
+ itemData.WriteByteSeq(creatorGuid[4]);
+
+ itemData << uint32(i);
+
+ itemData.WriteByteSeq(itemId[0]);
+ itemData.WriteByteSeq(itemId[6]);
+ itemData.WriteByteSeq(creatorGuid[0]);
+ itemData.WriteByteSeq(creatorGuid[1]);
+
+ itemData << uint32(item->ItemRandomPropertyId);
+
+ itemData.WriteByteSeq(itemId[4]);
+ itemData.WriteByteSeq(itemId[5]);
+ itemData.WriteByteSeq(itemId[2]);
+ itemData.WriteByteSeq(creatorGuid[2]);
+ itemData.WriteByteSeq(creatorGuid[6]);
+ itemData.WriteByteSeq(itemId[1]);
+ itemData.WriteByteSeq(itemId[3]);
+ itemData.WriteByteSeq(creatorGuid[5]);
+ itemData.WriteByteSeq(creatorGuid[7]);
+
+ itemData << uint32(item->ItemEntry);
+
+ itemData.WriteByteSeq(itemId[7]);
+ }
+
+ data.FlushBits();
+ data.append(itemData);
+
+ SendPacket(&data);
+}
+
+void WorldSession::HandleVoidStorageTransfer(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_VOID_STORAGE_TRANSFER");
+ Player* player = GetPlayer();
+
+ // Read everything
+
+ ObjectGuid npcGuid;
+ npcGuid[1] = recvData.ReadBit();
+
+ uint32 countDeposit = recvData.ReadBits(26);
+
+ if (countDeposit > 9)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit more than 9 items (%u).", player->GetGUIDLow(), player->GetName().c_str(), countDeposit);
+ return;
+ }
+
+ std::vector<ObjectGuid> itemGuids(countDeposit);
+ for (uint32 i = 0; i < countDeposit; ++i)
+ {
+ itemGuids[i][4] = recvData.ReadBit();
+ itemGuids[i][6] = recvData.ReadBit();
+ itemGuids[i][7] = recvData.ReadBit();
+ itemGuids[i][0] = recvData.ReadBit();
+ itemGuids[i][1] = recvData.ReadBit();
+ itemGuids[i][5] = recvData.ReadBit();
+ itemGuids[i][3] = recvData.ReadBit();
+ itemGuids[i][2] = recvData.ReadBit();
+ }
+
+ npcGuid[2] = recvData.ReadBit();
+ npcGuid[0] = recvData.ReadBit();
+ npcGuid[3] = recvData.ReadBit();
+ npcGuid[5] = recvData.ReadBit();
+ npcGuid[6] = recvData.ReadBit();
+ npcGuid[4] = recvData.ReadBit();
+
+ uint32 countWithdraw = recvData.ReadBits(26);
+
+ if (countWithdraw > 9)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to withdraw more than 9 items (%u).", player->GetGUIDLow(), player->GetName().c_str(), countWithdraw);
+ return;
+ }
+
+ std::vector<ObjectGuid> itemIds(countWithdraw);
+ for (uint32 i = 0; i < countWithdraw; ++i)
+ {
+ itemIds[i][4] = recvData.ReadBit();
+ itemIds[i][7] = recvData.ReadBit();
+ itemIds[i][1] = recvData.ReadBit();
+ itemIds[i][0] = recvData.ReadBit();
+ itemIds[i][2] = recvData.ReadBit();
+ itemIds[i][3] = recvData.ReadBit();
+ itemIds[i][5] = recvData.ReadBit();
+ itemIds[i][6] = recvData.ReadBit();
+ }
+
+ npcGuid[7] = recvData.ReadBit();
+
+ for (uint32 i = 0; i < countDeposit; ++i)
+ {
+ recvData.ReadByteSeq(itemGuids[i][6]);
+ recvData.ReadByteSeq(itemGuids[i][1]);
+ recvData.ReadByteSeq(itemGuids[i][0]);
+ recvData.ReadByteSeq(itemGuids[i][2]);
+ recvData.ReadByteSeq(itemGuids[i][4]);
+ recvData.ReadByteSeq(itemGuids[i][5]);
+ recvData.ReadByteSeq(itemGuids[i][3]);
+ recvData.ReadByteSeq(itemGuids[i][7]);
+ }
+
+ recvData.ReadByteSeq(npcGuid[5]);
+ recvData.ReadByteSeq(npcGuid[6]);
+
+ for (uint32 i = 0; i < countWithdraw; ++i)
+ {
+ recvData.ReadByteSeq(itemIds[i][3]);
+ recvData.ReadByteSeq(itemIds[i][0]);
+ recvData.ReadByteSeq(itemIds[i][1]);
+ recvData.ReadByteSeq(itemIds[i][6]);
+ recvData.ReadByteSeq(itemIds[i][2]);
+ recvData.ReadByteSeq(itemIds[i][7]);
+ recvData.ReadByteSeq(itemIds[i][5]);
+ recvData.ReadByteSeq(itemIds[i][4]);
+ }
+
+ recvData.ReadByteSeq(npcGuid[1]);
+ recvData.ReadByteSeq(npcGuid[4]);
+ recvData.ReadByteSeq(npcGuid[7]);
+ recvData.ReadByteSeq(npcGuid[3]);
+ recvData.ReadByteSeq(npcGuid[2]);
+ recvData.ReadByteSeq(npcGuid[0]);
+
+ Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER);
+ if (!unit)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
+ return;
+ }
+
+ if (!player->IsVoidStorageUnlocked())
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str());
+ return;
+ }
+
+ if (itemGuids.size() > player->GetNumOfVoidStorageFreeSlots())
+ {
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL);
+ return;
+ }
+
+ uint32 freeBagSlots = 0;
+ if (itemIds.size() != 0)
+ {
+ // make this a Player function
+ for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
+ if (Bag* bag = player->GetBagByPos(i))
+ freeBagSlots += bag->GetFreeSlots();
+ for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
+ if (!player->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
+ ++freeBagSlots;
+ }
+
+ if (itemIds.size() > freeBagSlots)
+ {
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL);
+ return;
+ }
+
+ if (!player->HasEnoughMoney(uint64(itemGuids.size() * VOID_STORAGE_STORE_ITEM)))
+ {
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NOT_ENOUGH_MONEY);
+ return;
+ }
+
+ std::pair<VoidStorageItem, uint8> depositItems[VOID_STORAGE_MAX_DEPOSIT];
+ uint8 depositCount = 0;
+ for (std::vector<ObjectGuid>::iterator itr = itemGuids.begin(); itr != itemGuids.end(); ++itr)
+ {
+ Item* item = player->GetItemByGuid(*itr);
+ if (!item)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit an invalid item (item guid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr));
+ continue;
+ }
+
+ VoidStorageItem itemVS(sObjectMgr->GenerateVoidStorageItemId(), item->GetEntry(), item->GetUInt64Value(ITEM_FIELD_CREATOR), item->GetItemRandomPropertyId(), item->GetItemSuffixFactor());
+
+ uint8 slot = player->AddVoidStorageItem(itemVS);
+
+ depositItems[depositCount++] = std::make_pair(itemVS, slot);
+
+ player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
+ }
+
+ int64 cost = depositCount * VOID_STORAGE_STORE_ITEM;
+
+ player->ModifyMoney(-cost);
+
+ VoidStorageItem withdrawItems[VOID_STORAGE_MAX_WITHDRAW];
+ uint8 withdrawCount = 0;
+ for (std::vector<ObjectGuid>::iterator itr = itemIds.begin(); itr != itemIds.end(); ++itr)
+ {
+ uint8 slot;
+ VoidStorageItem* itemVS = player->GetVoidStorageItem(*itr, slot);
+ if (!itemVS)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) tried to withdraw an invalid item (id: " UI64FMTD ")", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr));
+ continue;
+ }
+
+ ItemPosCountVec dest;
+ InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemVS->ItemEntry, 1);
+ if (msg != EQUIP_ERR_OK)
+ {
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL);
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) couldn't withdraw item id " UI64FMTD " because inventory was full.", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr));
+ return;
+ }
+
+ Item* item = player->StoreNewItem(dest, itemVS->ItemEntry, true, itemVS->ItemRandomPropertyId);
+ item->SetUInt64Value(ITEM_FIELD_CREATOR, uint64(itemVS->CreatorGuid));
+ item->SetBinding(true);
+ player->SendNewItem(item, 1, false, false, false);
+
+ withdrawItems[withdrawCount++] = *itemVS;
+
+ player->DeleteVoidStorageItem(slot);
+ }
+
+ WorldPacket data(SMSG_VOID_STORAGE_TRANSFER_CHANGES, ((5 + 5 + (7 + 7) * depositCount +
+ 7 * withdrawCount) / 8) + 7 * withdrawCount + (7 + 7 + 4 * 4) * depositCount);
+
+ data.WriteBits(depositCount, 5);
+ data.WriteBits(withdrawCount, 5);
+
+ for (uint8 i = 0; i < depositCount; ++i)
+ {
+ ObjectGuid itemId = depositItems[i].first.ItemId;
+ ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid;
+ data.WriteBit(creatorGuid[7]);
+ data.WriteBit(itemId[7]);
+ data.WriteBit(itemId[4]);
+ data.WriteBit(creatorGuid[6]);
+ data.WriteBit(creatorGuid[5]);
+ data.WriteBit(itemId[3]);
+ data.WriteBit(itemId[5]);
+ data.WriteBit(creatorGuid[4]);
+ data.WriteBit(creatorGuid[2]);
+ data.WriteBit(creatorGuid[0]);
+ data.WriteBit(creatorGuid[3]);
+ data.WriteBit(creatorGuid[1]);
+ data.WriteBit(itemId[2]);
+ data.WriteBit(itemId[0]);
+ data.WriteBit(itemId[1]);
+ data.WriteBit(itemId[6]);
+ }
+
+ for (uint8 i = 0; i < withdrawCount; ++i)
+ {
+ ObjectGuid itemId = withdrawItems[i].ItemId;
+ data.WriteBit(itemId[1]);
+ data.WriteBit(itemId[7]);
+ data.WriteBit(itemId[3]);
+ data.WriteBit(itemId[5]);
+ data.WriteBit(itemId[6]);
+ data.WriteBit(itemId[2]);
+ data.WriteBit(itemId[4]);
+ data.WriteBit(itemId[0]);
+ }
+
+ data.FlushBits();
+
+ for (uint8 i = 0; i < withdrawCount; ++i)
+ {
+ ObjectGuid itemId = withdrawItems[i].ItemId;
+ data.WriteByteSeq(itemId[3]);
+ data.WriteByteSeq(itemId[1]);
+ data.WriteByteSeq(itemId[0]);
+ data.WriteByteSeq(itemId[2]);
+ data.WriteByteSeq(itemId[7]);
+ data.WriteByteSeq(itemId[5]);
+ data.WriteByteSeq(itemId[6]);
+ data.WriteByteSeq(itemId[4]);
+ }
+
+ for (uint8 i = 0; i < depositCount; ++i)
+ {
+ ObjectGuid itemId = depositItems[i].first.ItemId;
+ ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid;
+
+ data << uint32(depositItems[i].first.ItemSuffixFactor);
+
+ data.WriteByteSeq(itemId[6]);
+ data.WriteByteSeq(itemId[4]);
+ data.WriteByteSeq(creatorGuid[4]);
+ data.WriteByteSeq(itemId[2]);
+ data.WriteByteSeq(creatorGuid[1]);
+ data.WriteByteSeq(creatorGuid[3]);
+ data.WriteByteSeq(itemId[3]);
+ data.WriteByteSeq(creatorGuid[0]);
+ data.WriteByteSeq(itemId[0]);
+ data.WriteByteSeq(creatorGuid[6]);
+ data.WriteByteSeq(itemId[5]);
+ data.WriteByteSeq(creatorGuid[5]);
+ data.WriteByteSeq(creatorGuid[7]);
+
+ data << uint32(depositItems[i].first.ItemEntry);
+
+ data.WriteByteSeq(itemId[1]);
+
+ data << uint32(depositItems[i].second); // slot
+
+ data.WriteByteSeq(creatorGuid[2]);
+ data.WriteByteSeq(itemId[7]);
+
+ data << uint32(depositItems[i].first.ItemRandomPropertyId);
+ }
+
+ SendPacket(&data);
+
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NO_ERROR);
+}
+
+void WorldSession::HandleVoidSwapItem(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_VOID_SWAP_ITEM");
+
+ Player* player = GetPlayer();
+ uint32 newSlot;
+ ObjectGuid npcGuid;
+ ObjectGuid itemId;
+
+ recvData >> newSlot;
+
+ npcGuid[2] = recvData.ReadBit();
+ npcGuid[4] = recvData.ReadBit();
+ npcGuid[0] = recvData.ReadBit();
+ itemId[2] = recvData.ReadBit();
+ itemId[6] = recvData.ReadBit();
+ itemId[5] = recvData.ReadBit();
+ npcGuid[1] = recvData.ReadBit();
+ npcGuid[7] = recvData.ReadBit();
+ itemId[3] = recvData.ReadBit();
+ itemId[7] = recvData.ReadBit();
+ itemId[0] = recvData.ReadBit();
+ npcGuid[6] = recvData.ReadBit();
+ npcGuid[5] = recvData.ReadBit();
+ npcGuid[3] = recvData.ReadBit();
+ itemId[1] = recvData.ReadBit();
+ itemId[4] = recvData.ReadBit();
+
+ recvData.ReadByteSeq(npcGuid[1]);
+ recvData.ReadByteSeq(itemId[3]);
+ recvData.ReadByteSeq(itemId[2]);
+ recvData.ReadByteSeq(itemId[4]);
+ recvData.ReadByteSeq(npcGuid[3]);
+ recvData.ReadByteSeq(npcGuid[0]);
+ recvData.ReadByteSeq(itemId[6]);
+ recvData.ReadByteSeq(itemId[1]);
+ recvData.ReadByteSeq(npcGuid[5]);
+ recvData.ReadByteSeq(itemId[5]);
+ recvData.ReadByteSeq(npcGuid[6]);
+ recvData.ReadByteSeq(itemId[0]);
+ recvData.ReadByteSeq(npcGuid[2]);
+ recvData.ReadByteSeq(npcGuid[7]);
+ recvData.ReadByteSeq(npcGuid[4]);
+ recvData.ReadByteSeq(itemId[7]);
+
+ Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER);
+ if (!unit)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidSwapItem - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
+ return;
+ }
+
+ if (!player->IsVoidStorageUnlocked())
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidSwapItem - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str());
+ return;
+ }
+
+ uint8 oldSlot;
+ if (!player->GetVoidStorageItem(itemId, oldSlot))
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidSwapItem - Player (GUID: %u, name: %s) requested swapping an invalid item (slot: %u, itemid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName().c_str(), newSlot, uint64(itemId));
+ return;
+ }
+
+ bool usedSrcSlot = player->GetVoidStorageItem(oldSlot) != NULL; // should be always true
+ bool usedDestSlot = player->GetVoidStorageItem(newSlot) != NULL;
+ ObjectGuid itemIdDest;
+ if (usedDestSlot)
+ itemIdDest = player->GetVoidStorageItem(newSlot)->ItemId;
+
+ if (!player->SwapVoidStorageItem(oldSlot, newSlot))
+ {
+ SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1);
+ return;
+ }
+
+ WorldPacket data(SMSG_VOID_ITEM_SWAP_RESPONSE, 1 + (usedSrcSlot + usedDestSlot) * (1 + 7 + 4));
+
+ data.WriteBit(!usedDestSlot);
+ data.WriteBit(!usedSrcSlot);
+
+ if (usedSrcSlot)
+ {
+ data.WriteBit(itemId[5]);
+ data.WriteBit(itemId[2]);
+ data.WriteBit(itemId[1]);
+ data.WriteBit(itemId[4]);
+ data.WriteBit(itemId[0]);
+ data.WriteBit(itemId[6]);
+ data.WriteBit(itemId[7]);
+ data.WriteBit(itemId[3]);
+ }
+
+ data.WriteBit(!usedDestSlot); // unk
+
+ if (usedDestSlot)
+ {
+ data.WriteBit(itemIdDest[7]);
+ data.WriteBit(itemIdDest[3]);
+ data.WriteBit(itemIdDest[4]);
+ data.WriteBit(itemIdDest[0]);
+ data.WriteBit(itemIdDest[5]);
+ data.WriteBit(itemIdDest[1]);
+ data.WriteBit(itemIdDest[2]);
+ data.WriteBit(itemIdDest[6]);
+ }
+
+ data.WriteBit(!usedSrcSlot); // unk
+
+ data.FlushBits();
+
+ if (usedDestSlot)
+ {
+ data.WriteByteSeq(itemIdDest[4]);
+ data.WriteByteSeq(itemIdDest[6]);
+ data.WriteByteSeq(itemIdDest[5]);
+ data.WriteByteSeq(itemIdDest[2]);
+ data.WriteByteSeq(itemIdDest[3]);
+ data.WriteByteSeq(itemIdDest[1]);
+ data.WriteByteSeq(itemIdDest[7]);
+ data.WriteByteSeq(itemIdDest[0]);
+ }
+
+ if (usedSrcSlot)
+ {
+ data.WriteByteSeq(itemId[6]);
+ data.WriteByteSeq(itemId[3]);
+ data.WriteByteSeq(itemId[5]);
+ data.WriteByteSeq(itemId[0]);
+ data.WriteByteSeq(itemId[1]);
+ data.WriteByteSeq(itemId[2]);
+ data.WriteByteSeq(itemId[4]);
+ data.WriteByteSeq(itemId[7]);
+ }
+
+ if (usedDestSlot)
+ data << uint32(oldSlot);
+
+ if (usedSrcSlot)
+ data << uint32(newSlot);
+
+ SendPacket(&data);
+}
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index c46d9002604..e37e6847bdd 100644
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -164,11 +164,7 @@ void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId)
void InstanceSaveManager::UnloadInstanceSave(uint32 InstanceId)
{
if (InstanceSave* save = GetInstanceSave(InstanceId))
- {
save->UnloadIfEmpty();
- if (save->m_toDelete)
- delete save;
- }
}
InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset)
diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h
index 0a2af4b73ee..701776bb57d 100644
--- a/src/server/game/Instances/InstanceSaveMgr.h
+++ b/src/server/game/Instances/InstanceSaveMgr.h
@@ -120,16 +120,16 @@ class InstanceSave
but that would depend on a lot of things that can easily change in future */
Difficulty GetDifficulty() const { return m_difficulty; }
- typedef std::list<Player*> PlayerListType;
- typedef std::list<Group*> GroupListType;
- private:
- bool UnloadIfEmpty();
/* used to flag the InstanceSave as to be deleted, so the caller can delete it */
void SetToDelete(bool toDelete)
{
m_toDelete = toDelete;
}
+ typedef std::list<Player*> PlayerListType;
+ typedef std::list<Group*> GroupListType;
+ private:
+ bool UnloadIfEmpty();
/* the only reason the instSave-object links are kept is because
the object-instSave links need to be broken at reset time */
/// @todo: Check if maybe it's enough to just store the number of players/groups
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index adef21fe7a2..46e1352df3f 100644
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -334,7 +334,7 @@ void InstanceScript::DoUpdateAchievementCriteria(AchievementCriteriaTypes type,
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* player = i->GetSource())
- player->UpdateAchievementCriteria(type, miscValue1, miscValue2, unit);
+ player->UpdateAchievementCriteria(type, miscValue1, miscValue2, 0, unit);
}
// Start timed achievement for all players in instance
@@ -414,6 +414,7 @@ void InstanceScript::SendEncounterUnit(uint32 type, Unit* unit /*= NULL*/, uint8
case ENCOUNTER_FRAME_ADD_TIMER:
case ENCOUNTER_FRAME_ENABLE_OBJECTIVE:
case ENCOUNTER_FRAME_DISABLE_OBJECTIVE:
+ case ENCOUNTER_FRAME_SET_COMBAT_RES_LIMIT:
data << uint8(param1);
break;
case ENCOUNTER_FRAME_UPDATE_OBJECTIVE:
@@ -421,6 +422,8 @@ void InstanceScript::SendEncounterUnit(uint32 type, Unit* unit /*= NULL*/, uint8
data << uint8(param2);
break;
case ENCOUNTER_FRAME_UNK7:
+ case ENCOUNTER_FRAME_ADD_COMBAT_RES_LIMIT:
+ case ENCOUNTER_FRAME_RESET_COMBAT_RES_LIMIT:
default:
break;
}
@@ -445,7 +448,7 @@ void InstanceScript::UpdateEncounterState(EncounterCreditType type, uint32 credi
if (encounter->lastEncounterDungeon)
{
dungeonId = encounter->lastEncounterDungeon;
- TC_LOG_DEBUG("lfg", "UpdateEncounterState: Instance %s (instanceId %u) completed encounter %s. Credit Dungeon: %u", instance->GetMapName(), instance->GetInstanceId(), encounter->dbcEntry->encounterName[0], dungeonId);
+ TC_LOG_DEBUG("lfg", "UpdateEncounterState: Instance %s (instanceId %u) completed encounter %s. Credit Dungeon: %u", instance->GetMapName(), instance->GetInstanceId(), encounter->dbcEntry->encounterName, dungeonId);
break;
}
}
@@ -466,3 +469,11 @@ void InstanceScript::UpdateEncounterState(EncounterCreditType type, uint32 credi
}
}
}
+
+void InstanceScript::UpdatePhasing()
+{
+ Map::PlayerList const& players = instance->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->GetSource())
+ player->UpdatePhasing();
+}
diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index f379572961c..7e9be651e61 100644
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -40,14 +40,17 @@ typedef std::set<uint64> MinionSet;
enum EncounterFrameType
{
- ENCOUNTER_FRAME_ENGAGE = 0,
- ENCOUNTER_FRAME_DISENGAGE = 1,
- ENCOUNTER_FRAME_UPDATE_PRIORITY = 2,
- ENCOUNTER_FRAME_ADD_TIMER = 3,
- ENCOUNTER_FRAME_ENABLE_OBJECTIVE = 4,
- ENCOUNTER_FRAME_UPDATE_OBJECTIVE = 5,
- ENCOUNTER_FRAME_DISABLE_OBJECTIVE = 6,
- ENCOUNTER_FRAME_UNK7 = 7 // Seems to have something to do with sorting the encounter units
+ ENCOUNTER_FRAME_SET_COMBAT_RES_LIMIT = 0,
+ ENCOUNTER_FRAME_RESET_COMBAT_RES_LIMIT = 1,
+ ENCOUNTER_FRAME_ENGAGE = 2,
+ ENCOUNTER_FRAME_DISENGAGE = 3,
+ ENCOUNTER_FRAME_UPDATE_PRIORITY = 4,
+ ENCOUNTER_FRAME_ADD_TIMER = 5,
+ ENCOUNTER_FRAME_ENABLE_OBJECTIVE = 6,
+ ENCOUNTER_FRAME_UPDATE_OBJECTIVE = 7,
+ ENCOUNTER_FRAME_DISABLE_OBJECTIVE = 8,
+ ENCOUNTER_FRAME_UNK7 = 9, // Seems to have something to do with sorting the encounter units
+ ENCOUNTER_FRAME_ADD_COMBAT_RES_LIMIT = 10
};
enum EncounterState
@@ -214,6 +217,9 @@ class InstanceScript : public ZoneScript
virtual void FillInitialWorldStates(WorldPacket& /*data*/) { }
+ // ReCheck PhaseTemplate related conditions
+ void UpdatePhasing();
+
protected:
void SetBossNumber(uint32 number) { bosses.resize(number); }
void LoadDoorData(DoorData const* data);
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index 270af559f0b..60475382d5e 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -864,17 +864,21 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
{
b << uint32(0); // gold
b << uint8(0); // item count
+ b << uint8(0); // currency count
return b;
}
Loot &l = lv.loot;
uint8 itemsShown = 0;
+ uint8 currenciesShown = 0;
b << uint32(l.gold); //gold
size_t count_pos = b.wpos(); // pos of item count byte
b << uint8(0); // item count placeholder
+ size_t currency_count_pos = b.wpos(); // pos of currency count byte
+ b << uint8(0); // currency count placeholder
switch (lv.permission)
{
@@ -1062,8 +1066,9 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
}
}
- //update number of items shown
+ //update number of items and currencies shown
b.put<uint8>(count_pos, itemsShown);
+ b.put<uint8>(currency_count_pos, currenciesShown);
return b;
}
@@ -1545,16 +1550,17 @@ void LoadLootTemplates_Disenchant()
LootIdSet lootIdSet, lootIdSetUsed;
uint32 count = LootTemplates_Disenchant.LoadAndCollectLootIds(lootIdSet);
- ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore();
- for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr)
+ for (uint32 i = 0; i < sItemDisenchantLootStore.GetNumRows(); ++i)
{
- if (uint32 lootid = itr->second.DisenchantID)
- {
- if (lootIdSet.find(lootid) == lootIdSet.end())
- LootTemplates_Disenchant.ReportNotExistedId(lootid);
- else
- lootIdSetUsed.insert(lootid);
- }
+ ItemDisenchantLootEntry const* disenchant = sItemDisenchantLootStore.LookupEntry(i);
+ if (!disenchant)
+ continue;
+
+ uint32 lootid = disenchant->Id;
+ if (lootIdSet.find(lootid) == lootIdSet.end())
+ LootTemplates_Disenchant.ReportNotExistedId(lootid);
+ else
+ lootIdSetUsed.insert(lootid);
}
for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
diff --git a/src/server/game/Mails/Mail.h b/src/server/game/Mails/Mail.h
index e3fc42f3f9e..abae99330c0 100644
--- a/src/server/game/Mails/Mail.h
+++ b/src/server/game/Mails/Mail.h
@@ -126,13 +126,13 @@ class MailDraft
public: // Accessors
uint16 GetMailTemplateId() const { return m_mailTemplateId; }
std::string const& GetSubject() const { return m_subject; }
- uint32 GetMoney() const { return m_money; }
- uint32 GetCOD() const { return m_COD; }
+ uint64 GetMoney() const { return m_money; }
+ uint64 GetCOD() const { return m_COD; }
std::string const& GetBody() const { return m_body; }
public: // modifiers
MailDraft& AddItem(Item* item);
- MailDraft& AddMoney(uint32 money) { m_money = money; return *this; }
+ MailDraft& AddMoney(uint64 money) { m_money = money; return *this; }
MailDraft& AddCOD(uint32 COD) { m_COD = COD; return *this; }
public: // finishers
@@ -150,8 +150,8 @@ class MailDraft
MailItemMap m_items; // Keep the items in a map to avoid duplicate guids (which can happen), store only low part of guid
- uint32 m_money;
- uint32 m_COD;
+ uint64 m_money;
+ uint64 m_COD;
};
struct MailItemInfo
@@ -167,7 +167,7 @@ struct Mail
uint8 messageType;
uint8 stationery;
uint16 mailTemplateId;
- uint32 sender;
+ uint32 sender; // TODO: change to uint64 and store full guids
uint32 receiver;
std::string subject;
std::string body;
@@ -175,8 +175,8 @@ struct Mail
std::vector<uint32> removedItems;
time_t expire_time;
time_t deliver_time;
- uint32 money;
- uint32 COD;
+ uint64 money;
+ uint64 COD;
uint32 checked;
MailState state;
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index b0164b77f1c..75301da32ed 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -575,7 +575,7 @@ bool Map::AddToMap(Transport* obj)
{
if (itr->GetSource()->GetTransport() != obj)
{
- UpdateData data;
+ UpdateData data(GetId());
obj->BuildCreateUpdateBlockForPlayer(&data, itr->GetSource());
WorldPacket packet;
data.BuildPacket(&packet);
@@ -835,13 +835,13 @@ void Map::RemoveFromMap(Transport* obj, bool remove)
Map::PlayerList const& players = GetPlayers();
if (!players.isEmpty())
{
- UpdateData data;
+ UpdateData data(GetId());
obj->BuildOutOfRangeUpdateBlock(&data);
WorldPacket packet;
data.BuildPacket(&packet);
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- if (itr->GetSource()->GetTransport() != obj)
- itr->GetSource()->SendDirectMessage(&packet);
+ if (itr->GetSource()->GetTransport() != obj)
+ itr->GetSource()->SendDirectMessage(&packet);
}
if (_transportsUpdateIter != _transports.end())
@@ -2469,7 +2469,7 @@ bool Map::CheckGridIntegrity(Creature* c, bool moved) const
char const* Map::GetMapName() const
{
- return i_mapEntry ? i_mapEntry->name[sWorld->GetDefaultDbcLocale()] : "UNNAMEDMAP\x0";
+ return i_mapEntry ? i_mapEntry->name : "UNNAMEDMAP\x0";
}
void Map::UpdateObjectVisibility(WorldObject* obj, Cell cell, CellCoord cellpair)
@@ -2498,7 +2498,7 @@ void Map::SendInitSelf(Player* player)
{
TC_LOG_INFO("maps", "Creating player data for himself %u", player->GetGUIDLow());
- UpdateData data;
+ UpdateData data(player->GetMapId());
// attach to player data current transport data
if (Transport* transport = player->GetTransport())
@@ -2523,9 +2523,9 @@ void Map::SendInitSelf(Player* player)
void Map::SendInitTransports(Player* player)
{
// Hack to send out transports
- UpdateData transData;
+ UpdateData transData(player->GetMapId());
for (TransportsContainer::const_iterator i = _transports.begin(); i != _transports.end(); ++i)
- if (*i != player->GetTransport())
+ if (*i != player->GetTransport() && player->IsInPhase(*i))
(*i)->BuildCreateUpdateBlockForPlayer(&transData, player);
WorldPacket packet;
@@ -2536,7 +2536,7 @@ void Map::SendInitTransports(Player* player)
void Map::SendRemoveTransports(Player* player)
{
// Hack to send out transports
- UpdateData transData;
+ UpdateData transData(player->GetMapId());
for (TransportsContainer::const_iterator i = _transports.begin(); i != _transports.end(); ++i)
if (*i != player->GetTransport())
(*i)->BuildOutOfRangeUpdateBlock(&transData);
@@ -2546,6 +2546,26 @@ void Map::SendRemoveTransports(Player* player)
player->GetSession()->SendPacket(&packet);
}
+void Map::SendUpdateTransportVisibility(Player* player, std::set<uint32> const& previousPhases)
+{
+ // Hack to send out transports
+ UpdateData transData(player->GetMapId());
+ for (TransportsContainer::const_iterator i = _transports.begin(); i != _transports.end(); ++i)
+ {
+ if (*i == player->GetTransport())
+ continue;
+
+ if (player->IsInPhase(*i) && !Trinity::Containers::Intersects(previousPhases.begin(), previousPhases.end(), (*i)->GetPhases().begin(), (*i)->GetPhases().end()))
+ (*i)->BuildCreateUpdateBlockForPlayer(&transData, player);
+ else if (!player->IsInPhase(*i))
+ (*i)->BuildOutOfRangeUpdateBlock(&transData);
+ }
+
+ WorldPacket packet;
+ transData.BuildPacket(&packet);
+ player->GetSession()->SendPacket(&packet);
+}
+
inline void Map::setNGrid(NGridType *grid, uint32 x, uint32 y)
{
if (x >= MAX_NUMBER_OF_GRIDS || y >= MAX_NUMBER_OF_GRIDS)
@@ -2647,6 +2667,9 @@ void Map::RemoveAllObjectsInRemoveList()
case TYPEID_DYNAMICOBJECT:
RemoveFromMap(obj->ToDynObject(), true);
break;
+ case TYPEID_AREATRIGGER:
+ RemoveFromMap((AreaTrigger*)obj, true);
+ break;
case TYPEID_GAMEOBJECT:
{
GameObject* go = obj->ToGameObject();
@@ -2794,11 +2817,13 @@ template bool Map::AddToMap(Corpse*);
template bool Map::AddToMap(Creature*);
template bool Map::AddToMap(GameObject*);
template bool Map::AddToMap(DynamicObject*);
+template bool Map::AddToMap(AreaTrigger*);
template void Map::RemoveFromMap(Corpse*, bool);
template void Map::RemoveFromMap(Creature*, bool);
template void Map::RemoveFromMap(GameObject*, bool);
template void Map::RemoveFromMap(DynamicObject*, bool);
+template void Map::RemoveFromMap(AreaTrigger*, bool);
/* ******* Dungeon Instance Maps ******* */
@@ -2968,10 +2993,11 @@ bool InstanceMap::AddPlayerToMap(Player* player)
// players also become permanently bound when they enter
if (groupBind->perm)
{
- WorldPacket data(SMSG_INSTANCE_LOCK_WARNING_QUERY, 9);
+ WorldPacket data(SMSG_INSTANCE_LOCK_WARNING_QUERY, 10);
data << uint32(60000);
data << uint32(i_data ? i_data->GetCompletedEncounterMask() : 0);
data << uint8(0);
+ data << uint8(0); // events it throws: 1 : INSTANCE_LOCK_WARNING 0 : INSTANCE_LOCK_STOP / INSTANCE_LOCK_START
player->GetSession()->SendPacket(&data);
player->SetPendingBind(mapSave->GetInstanceId(), 60000);
}
@@ -3441,6 +3467,7 @@ void Map::SendZoneDynamicInfo(Player* player)
{
WorldPacket data(SMSG_PLAY_MUSIC, 4);
data << uint32(music);
+ data << uint64(player->GetGUID());
player->SendDirectMessage(&data);
}
@@ -3473,13 +3500,15 @@ void Map::SetZoneMusic(uint32 zoneId, uint32 musicId)
Map::PlayerList const& players = GetPlayers();
if (!players.isEmpty())
{
- WorldPacket data(SMSG_PLAY_MUSIC, 4);
- data << uint32(musicId);
-
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource())
if (player->GetZoneId() == zoneId)
+ {
+ WorldPacket data(SMSG_PLAY_MUSIC, 4);
+ data << uint32(musicId);
+ data << uint64(player->GetGUID());
player->SendDirectMessage(&data);
+ }
}
}
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 70198cb20a3..c194f4dccd7 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -474,6 +474,7 @@ class Map : public GridRefManager<NGridType>
bool ContainsGameObjectModel(const GameObjectModel& model) const { return _dynamicTree.contains(model);}
bool getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist);
+ virtual uint32 GetOwnerGuildId(uint32 /*team*/ = TEAM_OTHER) const { return 0; }
/*
RESPAWN TIMES
*/
@@ -507,6 +508,7 @@ class Map : public GridRefManager<NGridType>
void SendInitTransports(Player* player);
void SendRemoveTransports(Player* player);
+ void SendUpdateTransportVisibility(Player* player, std::set<uint32> const& previousPhases);
void SendZoneDynamicInfo(Player* player);
void SetZoneMusic(uint32 zoneId, uint32 musicId);
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index 9c023b86bc9..cc408988428 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -145,7 +145,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
if (player->IsGameMaster())
return true;
- char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()];
+ char const* mapName = entry->name;
Group* group = player->GetGroup();
if (entry->IsRaid())
diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp
index 28869d264c4..ba7d3784157 100644
--- a/src/server/game/Maps/TransportMgr.cpp
+++ b/src/server/game/Maps/TransportMgr.cpp
@@ -348,7 +348,7 @@ void TransportMgr::AddPathNodeToTransport(uint32 transportEntry, uint32 timeSeg,
animNode.Path[timeSeg] = node;
}
-Transport* TransportMgr::CreateTransport(uint32 entry, uint32 guid /*= 0*/, Map* map /*= NULL*/)
+Transport* TransportMgr::CreateTransport(uint32 entry, uint32 guid /*= 0*/, Map* map /*= NULL*/, uint32 phaseid /*= 0*/, uint32 phasegroup /*= 0*/)
{
// instance case, execute GetGameObjectEntry hook
if (map)
@@ -388,6 +388,13 @@ Transport* TransportMgr::CreateTransport(uint32 entry, uint32 guid /*= 0*/, Map*
return NULL;
}
+ if (phaseid)
+ trans->SetInPhase(phaseid, false, true);
+
+ if (phasegroup)
+ for (auto ph : GetPhasesForGroup(phasegroup))
+ trans->SetInPhase(ph, false, true);
+
if (MapEntry const* mapEntry = sMapStore.LookupEntry(mapId))
{
if (mapEntry->Instanceable() != tInfo->inInstance)
@@ -416,7 +423,7 @@ void TransportMgr::SpawnContinentTransports()
uint32 oldMSTime = getMSTime();
- QueryResult result = WorldDatabase.Query("SELECT guid, entry FROM transports");
+ QueryResult result = WorldDatabase.Query("SELECT guid, entry, phaseid, phasegroup FROM transports");
uint32 count = 0;
if (result)
@@ -426,10 +433,12 @@ void TransportMgr::SpawnContinentTransports()
Field* fields = result->Fetch();
uint32 guid = fields[0].GetUInt32();
uint32 entry = fields[1].GetUInt32();
+ uint32 phaseid = fields[2].GetUInt32();
+ uint32 phasegroup = fields[3].GetUInt32();
if (TransportTemplate const* tInfo = GetTransportTemplate(entry))
if (!tInfo->inInstance)
- if (CreateTransport(entry, guid))
+ if (CreateTransport(entry, guid, nullptr, phaseid, phasegroup))
++count;
} while (result->NextRow());
diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h
index 04c372cc526..94a4ba335b1 100644
--- a/src/server/game/Maps/TransportMgr.h
+++ b/src/server/game/Maps/TransportMgr.h
@@ -109,7 +109,7 @@ class TransportMgr
void LoadTransportTemplates();
// Creates a transport using given GameObject template entry
- Transport* CreateTransport(uint32 entry, uint32 guid = 0, Map* map = NULL);
+ Transport* CreateTransport(uint32 entry, uint32 guid = 0, Map* map = nullptr, uint32 phaseid = 0, uint32 phasegroup = 0);
// Spawns all continent transports, used at core startup
void SpawnContinentTransports();
diff --git a/src/server/game/Miscellaneous/Formulas.h b/src/server/game/Miscellaneous/Formulas.h
index 8d0e97dc765..924320ac198 100644
--- a/src/server/game/Miscellaneous/Formulas.h
+++ b/src/server/game/Miscellaneous/Formulas.h
@@ -128,6 +128,9 @@ namespace Trinity
case CONTENT_71_80:
nBaseExp = 580;
break;
+ case CONTENT_81_85:
+ nBaseExp = 1878;
+ break;
default:
TC_LOG_ERROR("misc", "BaseGain: Unsupported content level %u", content);
nBaseExp = 45;
@@ -221,6 +224,26 @@ namespace Trinity
return rate;
}
} // namespace Trinity::XP
+
+ namespace Currency
+ {
+ inline uint32 ConquestRatingCalculator(uint32 rate)
+ {
+ if (rate <= 1500)
+ return 1350; // Default conquest points
+ else if (rate > 3000)
+ rate = 3000;
+
+ // http://www.arenajunkies.com/topic/179536-conquest-point-cap-vs-personal-rating-chart/page__st__60#entry3085246
+ return uint32(1.4326 * ((1511.26 / (1 + 1639.28 / exp(0.00412 * rate))) + 850.15));
+ }
+
+ inline uint32 BgConquestRatingCalculator(uint32 rate)
+ {
+ // WowWiki: Battleground ratings receive a bonus of 22.2% to the cap they generate
+ return uint32((ConquestRatingCalculator(rate) * 1.222f) + 0.5f);
+ }
+ } // namespace Trinity::Currency
} // namespace Trinity
#endif
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 3a680e30217..68a0687dc24 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -205,7 +205,15 @@ enum TrinityStrings
LANG_LIQUID_STATUS = 175,
LANG_INVALID_GAMEOBJECT_TYPE = 176,
LANG_GAMEOBJECT_DAMAGED = 177,
- // Room for more level 1 178-199 not used
+
+ LANG_PHASING_SUCCESS = 178,
+ LANG_PHASING_FAILED = 179,
+ LANG_PHASING_LAST_PHASE = 180,
+ LANG_PHASING_LIST = 181,
+ LANG_PHASING_PHASEMASK = 182,
+ LANG_PHASING_REPORT_STATUS = 183,
+ LANG_PHASING_NO_DEFINITIONS = 184, // Phasing
+ // Room for more level 1 185-199 not used
// level 2 chat
LANG_NO_SELECTION = 200,
@@ -728,12 +736,12 @@ enum TrinityStrings
LANG_DEBUG_ARENA_OFF = 738,
LANG_DEBUG_BG_ON = 739,
LANG_DEBUG_BG_OFF = 740,
- LANG_DIST_ARENA_POINTS_START = 741,
- LANG_DIST_ARENA_POINTS_ONLINE_START = 742,
- LANG_DIST_ARENA_POINTS_ONLINE_END = 743,
- LANG_DIST_ARENA_POINTS_TEAM_START = 744,
- LANG_DIST_ARENA_POINTS_TEAM_END = 745,
- LANG_DIST_ARENA_POINTS_END = 746,
+// LANG_DIST_ARENA_POINTS_START = 741,
+// LANG_DIST_ARENA_POINTS_ONLINE_START = 742,
+// LANG_DIST_ARENA_POINTS_ONLINE_END = 743,
+// LANG_DIST_ARENA_POINTS_TEAM_START = 744,
+// LANG_DIST_ARENA_POINTS_TEAM_END = 745,
+// LANG_DIST_ARENA_POINTS_END = 746,
LANG_BG_DISABLED = 747,
LANG_ARENA_DISABLED = 748,
// = 749, see LANG_PINFO_ACC_OS
@@ -881,7 +889,8 @@ enum TrinityStrings
LANG_CHARACTER_DELETED_LIST_LINE_CHAT = 1026,
LANG_SQLDRIVER_QUERY_LOGGING_ENABLED = 1027,
LANG_SQLDRIVER_QUERY_LOGGING_DISABLED = 1028,
- // Room for more level 4 1029-1099 not used
+ LANG_ACCOUNT_INVALID_BNET_NAME = 1029,
+ // Room for more level 4 1030-1099 not used
// Level 3 (continue)
LANG_ACCOUNT_SETADDON = 1100,
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 7a48e016af0..833e4f7c7bc 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -50,7 +50,8 @@ enum Expansions
EXPANSION_CLASSIC = 0,
EXPANSION_THE_BURNING_CRUSADE = 1,
EXPANSION_WRATH_OF_THE_LICH_KING = 2,
- MAX_EXPANSIONS = 3
+ EXPANSION_CATACLYSM = 3,
+ MAX_EXPANSIONS = 4
};
enum Gender
@@ -72,9 +73,9 @@ enum Races
RACE_TAUREN = 6,
RACE_GNOME = 7,
RACE_TROLL = 8,
- //RACE_GOBLIN = 9,
+ RACE_GOBLIN = 9,
RACE_BLOODELF = 10,
- RACE_DRAENEI = 11
+ RACE_DRAENEI = 11,
//RACE_FEL_ORC = 12,
//RACE_NAGA = 13,
//RACE_BROKEN = 14,
@@ -84,21 +85,23 @@ enum Races
//RACE_FOREST_TROLL = 18,
//RACE_TAUNKA = 19,
//RACE_NORTHREND_SKELETON = 20,
- //RACE_ICE_TROLL = 21
+ //RACE_ICE_TROLL = 21,
+ RACE_WORGEN = 22,
+ //RACE_GILNEAN = 23
};
// max+1 for player race
-#define MAX_RACES 12
+#define MAX_RACES 23
#define RACEMASK_ALL_PLAYABLE \
((1<<(RACE_HUMAN-1)) |(1<<(RACE_ORC-1)) |(1<<(RACE_DWARF-1)) | \
(1<<(RACE_NIGHTELF-1))|(1<<(RACE_UNDEAD_PLAYER-1))|(1<<(RACE_TAUREN-1)) | \
(1<<(RACE_GNOME-1)) |(1<<(RACE_TROLL-1)) |(1<<(RACE_BLOODELF-1))| \
- (1<<(RACE_DRAENEI-1)))
+ (1<<(RACE_DRAENEI-1)) |(1<<(RACE_GOBLIN-1)) |(1<<(RACE_WORGEN-1)))
#define RACEMASK_ALLIANCE \
((1<<(RACE_HUMAN-1)) | (1<<(RACE_DWARF-1)) | (1<<(RACE_NIGHTELF-1)) | \
- (1<<(RACE_GNOME-1)) | (1<<(RACE_DRAENEI-1)))
+ (1<<(RACE_GNOME-1)) | (1<<(RACE_DRAENEI-1)) | (1<<(RACE_WORGEN-1)))
#define RACEMASK_HORDE RACEMASK_ALL_PLAYABLE & ~RACEMASK_ALLIANCE
@@ -158,7 +161,7 @@ enum ReputationRank
#define MIN_REPUTATION_RANK (REP_HATED)
#define MAX_REPUTATION_RANK 8
-#define MAX_SPILLOVER_FACTIONS 4
+#define MAX_SPILLOVER_FACTIONS 5
enum MoneyConstants
{
@@ -184,14 +187,20 @@ enum Powers
POWER_RAGE = 1,
POWER_FOCUS = 2,
POWER_ENERGY = 3,
- POWER_HAPPINESS = 4,
- POWER_RUNE = 5,
+ POWER_UNUSED = 4,
+ POWER_RUNES = 5,
POWER_RUNIC_POWER = 6,
- MAX_POWERS = 7,
- POWER_ALL = 127, // default for class?
+ POWER_SOUL_SHARDS = 7,
+ POWER_ECLIPSE = 8,
+ POWER_HOLY_POWER = 9,
+ POWER_ALTERNATE_POWER = 10, // Used in some quests
+ MAX_POWERS = 11,
+ POWER_ALL = 127, // default for class?
POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value)
};
+#define MAX_POWERS_PER_CLASS 5
+
enum SpellSchools
{
SPELL_SCHOOL_NORMAL = 0,
@@ -436,7 +445,7 @@ enum SpellAttr4
SPELL_ATTR4_UNK13 = 0x00002000, // 13
SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS = 0x00004000, // 14 doesn't break auras by damage from these spells
SPELL_ATTR4_UNK15 = 0x00008000, // 15
- SPELL_ATTR4_NOT_USABLE_IN_ARENA = 0x00010000, // 16
+ SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG = 0x00010000, // 16 Cannot be used in both Arenas or Rated Battlegrounds
SPELL_ATTR4_USABLE_IN_ARENA = 0x00020000, // 17
SPELL_ATTR4_AREA_TARGET_CHAIN = 0x00040000, // 18 (NYI)hits area targets one after another instead of all at once
SPELL_ATTR4_UNK19 = 0x00080000, // 19 proc dalayed, after damage or don't proc on absorb?
@@ -533,7 +542,7 @@ enum SpellAttr7
SPELL_ATTR7_REACTIVATE_AT_RESURRECT = 0x00000004, // 2 Paladin's auras and 65607 only.
SPELL_ATTR7_IS_CHEAT_SPELL = 0x00000008, // 3 Cannot cast if caster doesn't have UnitFlag2 & UNIT_FLAG2_ALLOW_CHEAT_SPELLS
SPELL_ATTR7_UNK4 = 0x00000010, // 4 Only 47883 (Soulstone Resurrection) and test spell.
- SPELL_ATTR7_SUMMON_PLAYER_TOTEM = 0x00000020, // 5 Only Shaman player totems.
+ SPELL_ATTR7_SUMMON_TOTEM = 0x00000020, // 5 Only Shaman totems.
SPELL_ATTR7_NO_PUSHBACK_ON_DAMAGE = 0x00000040, // 6 Does not cause spell pushback on damage
SPELL_ATTR7_UNK7 = 0x00000080, // 7 66218 (Launch) spell.
SPELL_ATTR7_HORDE_ONLY = 0x00000100, // 8 Teleports, mounts and other spells.
@@ -562,11 +571,120 @@ enum SpellAttr7
SPELL_ATTR7_CLIENT_INDICATOR = 0x80000000
};
+enum SpellAttr8
+{
+ SPELL_ATTR8_CANT_MISS = 0x00000001, // 0
+ SPELL_ATTR8_UNK1 = 0x00000002, // 1
+ SPELL_ATTR8_UNK2 = 0x00000004, // 2
+ SPELL_ATTR8_UNK3 = 0x00000008, // 3
+ SPELL_ATTR8_UNK4 = 0x00000010, // 4
+ SPELL_ATTR8_UNK5 = 0x00000020, // 5
+ SPELL_ATTR8_UNK6 = 0x00000040, // 6
+ SPELL_ATTR8_UNK7 = 0x00000080, // 7
+ SPELL_ATTR8_AFFECT_PARTY_AND_RAID = 0x00000100, // 8 Nearly all spells have "all party and raid" in description
+ SPELL_ATTR8_DONT_RESET_PERIODIC_TIMER = 0x00000200, // 9 Periodic auras with this flag keep old periodic timer when refreshing at close to one tick remaining (kind of anti DoT clipping)
+ SPELL_ATTR8_NAME_CHANGED_DURING_TRANSFORM = 0x00000400, // 10 according to wowhead comments, name changes, title remains
+ SPELL_ATTR8_UNK11 = 0x00000800, // 11
+ SPELL_ATTR8_AURA_SEND_AMOUNT = 0x00001000, // 12 Aura must have flag AFLAG_ANY_EFFECT_AMOUNT_SENT to send amount
+ SPELL_ATTR8_UNK13 = 0x00002000, // 13
+ SPELL_ATTR8_UNK14 = 0x00004000, // 14
+ SPELL_ATTR8_WATER_MOUNT = 0x00008000, // 15 only one River Boat used in Thousand Needles
+ SPELL_ATTR8_UNK16 = 0x00010000, // 16
+ SPELL_ATTR8_UNK17 = 0x00020000, // 17
+ SPELL_ATTR8_REMEMBER_SPELLS = 0x00040000, // 18 at some point in time, these auras remember spells and allow to cast them later
+ SPELL_ATTR8_USE_COMBO_POINTS_ON_ANY_TARGET = 0x00080000, // 19 allows to consume combo points from dead targets
+ SPELL_ATTR8_ARMOR_SPECIALIZATION = 0x00100000, // 20
+ SPELL_ATTR8_UNK21 = 0x00200000, // 21
+ SPELL_ATTR8_UNK22 = 0x00400000, // 22
+ SPELL_ATTR8_BATTLE_RESURRECTION = 0x00800000, // 23 Used to limit the Amount of Resurrections in Boss Encounters
+ SPELL_ATTR8_HEALING_SPELL = 0x01000000, // 24
+ SPELL_ATTR8_UNK25 = 0x02000000, // 25
+ SPELL_ATTR8_RAID_MARKER = 0x04000000, // 26 probably spell no need learn to cast
+ SPELL_ATTR8_UNK27 = 0x08000000, // 27
+ SPELL_ATTR8_NOT_IN_BG_OR_ARENA = 0x10000000, // 28 not allow to cast or deactivate currently active effect, not sure about Fast Track
+ SPELL_ATTR8_MASTERY_SPECIALIZATION = 0x20000000, // 29
+ SPELL_ATTR8_UNK30 = 0x40000000, // 30
+ SPELL_ATTR8_ATTACK_IGNORE_IMMUNE_TO_PC_FLAG = 0x80000000 // 31 Do not check UNIT_FLAG_IMMUNE_TO_PC in IsValidAttackTarget
+};
+
+enum SpellAttr9
+{
+ SPELL_ATTR9_UNK0 = 0x00000001, // 0
+ SPELL_ATTR9_UNK1 = 0x00000002, // 1
+ SPELL_ATTR9_RESTRICTED_FLIGHT_AREA = 0x00000004, // 2 Dalaran and Wintergrasp flight area auras have it
+ SPELL_ATTR9_UNK3 = 0x00000008, // 3
+ SPELL_ATTR9_SPECIAL_DELAY_CALCULATION = 0x00000010, // 4
+ SPELL_ATTR9_SUMMON_PLAYER_TOTEM = 0x00000020, // 5
+ SPELL_ATTR9_UNK6 = 0x00000040, // 6
+ SPELL_ATTR9_UNK7 = 0x00000080, // 7
+ SPELL_ATTR9_AIMED_SHOT = 0x00000100, // 8
+ SPELL_ATTR9_NOT_USABLE_IN_ARENA = 0x00000200, // 9 Cannot be used in arenas
+ SPELL_ATTR9_UNK10 = 0x00000400, // 10
+ SPELL_ATTR9_UNK11 = 0x00000800, // 11
+ SPELL_ATTR9_UNK12 = 0x00001000, // 12
+ SPELL_ATTR9_SLAM = 0x00002000, // 13
+ SPELL_ATTR9_USABLE_IN_RATED_BATTLEGROUNDS = 0x00004000, // 14 Can be used in Rated Battlegrounds
+ SPELL_ATTR9_UNK15 = 0x00008000, // 15
+ SPELL_ATTR9_UNK16 = 0x00010000, // 16
+ SPELL_ATTR9_UNK17 = 0x00020000, // 17
+ SPELL_ATTR9_UNK18 = 0x00040000, // 18
+ SPELL_ATTR9_UNK19 = 0x00080000, // 19
+ SPELL_ATTR9_UNK20 = 0x00100000, // 20
+ SPELL_ATTR9_UNK21 = 0x00200000, // 21
+ SPELL_ATTR9_UNK22 = 0x00400000, // 22
+ SPELL_ATTR9_UNK23 = 0x00800000, // 23
+ SPELL_ATTR9_UNK24 = 0x01000000, // 24
+ SPELL_ATTR9_UNK25 = 0x02000000, // 25
+ SPELL_ATTR9_UNK26 = 0x04000000, // 26
+ SPELL_ATTR9_UNK27 = 0x08000000, // 27
+ SPELL_ATTR9_UNK28 = 0x10000000, // 28
+ SPELL_ATTR9_UNK29 = 0x20000000, // 29
+ SPELL_ATTR9_UNK30 = 0x40000000, // 30
+ SPELL_ATTR9_UNK31 = 0x80000000 // 31
+};
+
+enum SpellAttr10
+{
+ SPELL_ATTR10_UNK0 = 0x00000001, // 0
+ SPELL_ATTR10_UNK1 = 0x00000002, // 1
+ SPELL_ATTR10_UNK2 = 0x00000004, // 2
+ SPELL_ATTR10_UNK3 = 0x00000008, // 3
+ SPELL_ATTR10_WATER_SPOUT = 0x00000010, // 4
+ SPELL_ATTR10_UNK5 = 0x00000020, // 5
+ SPELL_ATTR10_UNK6 = 0x00000040, // 6
+ SPELL_ATTR10_TELEPORT_PLAYER = 0x00000080, // 7 4 Teleport Player spells
+ SPELL_ATTR10_UNK8 = 0x00000100, // 8
+ SPELL_ATTR10_UNK9 = 0x00000200, // 9
+ SPELL_ATTR10_UNK10 = 0x00000400, // 10
+ SPELL_ATTR10_HERB_GATHERING_MINING = 0x00000800, // 11 Only Herb Gathering and Mining
+ SPELL_ATTR10_UNK12 = 0x00001000, // 12
+ SPELL_ATTR10_UNK13 = 0x00002000, // 13
+ SPELL_ATTR10_UNK14 = 0x00004000, // 14
+ SPELL_ATTR10_UNK15 = 0x00008000, // 15
+ SPELL_ATTR10_UNK16 = 0x00010000, // 16
+ SPELL_ATTR10_UNK17 = 0x00020000, // 17
+ SPELL_ATTR10_UNK18 = 0x00040000, // 18
+ SPELL_ATTR10_UNK19 = 0x00080000, // 19
+ SPELL_ATTR10_UNK20 = 0x00100000, // 20
+ SPELL_ATTR10_UNK21 = 0x00200000, // 21
+ SPELL_ATTR10_UNK22 = 0x00400000, // 22
+ SPELL_ATTR10_UNK23 = 0x00800000, // 23
+ SPELL_ATTR10_UNK24 = 0x01000000, // 24
+ SPELL_ATTR10_UNK25 = 0x02000000, // 25
+ SPELL_ATTR10_UNK26 = 0x04000000, // 26
+ SPELL_ATTR10_UNK27 = 0x08000000, // 27
+ SPELL_ATTR10_UNK28 = 0x10000000, // 28
+ SPELL_ATTR10_UNK29 = 0x20000000, // 29
+ SPELL_ATTR10_UNK30 = 0x40000000, // 30
+ SPELL_ATTR10_UNK31 = 0x80000000 // 31
+};
+
#define MIN_TALENT_SPEC 0
#define MAX_TALENT_SPEC 1
#define MIN_TALENT_SPECS 1
#define MAX_TALENT_SPECS 2
-#define MAX_GLYPH_SLOT_INDEX 6
+#define MAX_GLYPH_SLOT_INDEX 9
+#define REQ_PRIMARY_TREE_TALENTS 31
// Custom values
enum SpellClickUserTypes
@@ -643,10 +761,12 @@ enum Language
LANG_ZOMBIE = 36,
LANG_GNOMISH_BINARY = 37,
LANG_GOBLIN_BINARY = 38,
+ LANG_WORGEN = 39,
+ LANG_GOBLIN = 40,
LANG_ADDON = 0xFFFFFFFF // used by addons, in 2.4.0 not exist, replaced by messagetype?
};
-#define LANGUAGES_COUNT 19
+#define LANGUAGES_COUNT 21
enum TeamId
{
@@ -672,7 +792,7 @@ enum SpellEffects
SPELL_EFFECT_INSTAKILL = 1,
SPELL_EFFECT_SCHOOL_DAMAGE = 2,
SPELL_EFFECT_DUMMY = 3,
- SPELL_EFFECT_PORTAL_TELEPORT = 4,
+ SPELL_EFFECT_PORTAL_TELEPORT = 4, // Unused (4.3.4)
SPELL_EFFECT_TELEPORT_UNITS = 5,
SPELL_EFFECT_APPLY_AURA = 6,
SPELL_EFFECT_ENVIRONMENTAL_DAMAGE = 7,
@@ -681,9 +801,9 @@ enum SpellEffects
SPELL_EFFECT_HEAL = 10,
SPELL_EFFECT_BIND = 11,
SPELL_EFFECT_PORTAL = 12,
- SPELL_EFFECT_RITUAL_BASE = 13,
- SPELL_EFFECT_RITUAL_SPECIALIZE = 14,
- SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15,
+ SPELL_EFFECT_RITUAL_BASE = 13, // Unused (4.3.4)
+ SPELL_EFFECT_RITUAL_SPECIALIZE = 14, // Unused (4.3.4)
+ SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15, // Unused (4.3.4)
SPELL_EFFECT_QUEST_COMPLETE = 16,
SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL = 17,
SPELL_EFFECT_RESURRECT = 18,
@@ -713,14 +833,14 @@ enum SpellEffects
SPELL_EFFECT_JUMP_DEST = 42,
SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER = 43,
SPELL_EFFECT_SKILL_STEP = 44,
- SPELL_EFFECT_ADD_HONOR = 45,
+ SPELL_EFFECT_PLAY_MOVIE = 45,
SPELL_EFFECT_SPAWN = 46,
SPELL_EFFECT_TRADE_SKILL = 47,
SPELL_EFFECT_STEALTH = 48,
SPELL_EFFECT_DETECT = 49,
SPELL_EFFECT_TRANS_DOOR = 50,
- SPELL_EFFECT_FORCE_CRITICAL_HIT = 51,
- SPELL_EFFECT_GUARANTEE_HIT = 52,
+ SPELL_EFFECT_FORCE_CRITICAL_HIT = 51, // Unused (4.3.4)
+ SPELL_EFFECT_GUARANTEE_HIT = 52, // Unused (4.3.4)
SPELL_EFFECT_ENCHANT_ITEM = 53,
SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY = 54,
SPELL_EFFECT_TAMECREATURE = 55,
@@ -790,7 +910,7 @@ enum SpellEffects
SPELL_EFFECT_APPLY_AREA_AURA_PET = 119,
SPELL_EFFECT_TELEPORT_GRAVEYARD = 120,
SPELL_EFFECT_NORMALIZED_WEAPON_DMG = 121,
- SPELL_EFFECT_122 = 122,
+ SPELL_EFFECT_122 = 122, // Unused (4.3.4)
SPELL_EFFECT_SEND_TAXI = 123,
SPELL_EFFECT_PULL_TOWARDS = 124,
SPELL_EFFECT_MODIFY_THREAT_PERCENT = 125,
@@ -831,203 +951,236 @@ enum SpellEffects
SPELL_EFFECT_160 = 160,
SPELL_EFFECT_TALENT_SPEC_COUNT = 161,
SPELL_EFFECT_TALENT_SPEC_SELECT = 162,
- SPELL_EFFECT_163 = 163,
+ SPELL_EFFECT_163 = 163, // Unused (4.3.4)
SPELL_EFFECT_REMOVE_AURA = 164,
- TOTAL_SPELL_EFFECTS = 165
+ SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT = 165,
+ SPELL_EFFECT_GIVE_CURRENCY = 166,
+ SPELL_EFFECT_167 = 167,
+ SPELL_EFFECT_168 = 168,
+ SPELL_EFFECT_DESTROY_ITEM = 169,
+ SPELL_EFFECT_170 = 170,
+ SPELL_EFFECT_171 = 171, // Summons gamebject
+ SPELL_EFFECT_RESURRECT_WITH_AURA = 172,
+ SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB = 173, // Guild tab unlocked (guild perk)
+ SPELL_EFFECT_174 = 174,
+ SPELL_EFFECT_175 = 175, // Unused (4.3.4)
+ SPELL_EFFECT_176 = 176, // Some kind of sanctuary effect (Vanish)
+ SPELL_EFFECT_177 = 177,
+ SPELL_EFFECT_178 = 178, // Unused (4.3.4)
+ SPELL_EFFECT_CREATE_AREATRIGGER = 179,
+ SPELL_EFFECT_180 = 180, // Unused (4.3.4)
+ SPELL_EFFECT_181 = 181, // Unused (4.3.4)
+ SPELL_EFFECT_182 = 182,
+ TOTAL_SPELL_EFFECTS = 183,
};
enum SpellCastResult
{
- SPELL_FAILED_SUCCESS = 0,
- SPELL_FAILED_AFFECTING_COMBAT = 1,
- SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 2,
- SPELL_FAILED_ALREADY_AT_FULL_MANA = 3,
- SPELL_FAILED_ALREADY_AT_FULL_POWER = 4,
- SPELL_FAILED_ALREADY_BEING_TAMED = 5,
- SPELL_FAILED_ALREADY_HAVE_CHARM = 6,
- SPELL_FAILED_ALREADY_HAVE_SUMMON = 7,
- SPELL_FAILED_ALREADY_OPEN = 8,
- SPELL_FAILED_AURA_BOUNCED = 9,
- SPELL_FAILED_AUTOTRACK_INTERRUPTED = 10,
- SPELL_FAILED_BAD_IMPLICIT_TARGETS = 11,
- SPELL_FAILED_BAD_TARGETS = 12,
- SPELL_FAILED_CANT_BE_CHARMED = 13,
- SPELL_FAILED_CANT_BE_DISENCHANTED = 14,
- SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 15,
- SPELL_FAILED_CANT_BE_MILLED = 16,
- SPELL_FAILED_CANT_BE_PROSPECTED = 17,
- SPELL_FAILED_CANT_CAST_ON_TAPPED = 18,
- SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 19,
- SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 20,
- SPELL_FAILED_CANT_STEALTH = 21,
- SPELL_FAILED_CASTER_AURASTATE = 22,
- SPELL_FAILED_CASTER_DEAD = 23,
- SPELL_FAILED_CHARMED = 24,
- SPELL_FAILED_CHEST_IN_USE = 25,
- SPELL_FAILED_CONFUSED = 26,
- SPELL_FAILED_DONT_REPORT = 27,
- SPELL_FAILED_EQUIPPED_ITEM = 28,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS = 29,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 30,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 31,
- SPELL_FAILED_ERROR = 32,
- SPELL_FAILED_FIZZLE = 33,
- SPELL_FAILED_FLEEING = 34,
- SPELL_FAILED_FOOD_LOWLEVEL = 35,
- SPELL_FAILED_HIGHLEVEL = 36,
- SPELL_FAILED_HUNGER_SATIATED = 37,
- SPELL_FAILED_IMMUNE = 38,
- SPELL_FAILED_INCORRECT_AREA = 39,
- SPELL_FAILED_INTERRUPTED = 40,
- SPELL_FAILED_INTERRUPTED_COMBAT = 41,
- SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 42,
- SPELL_FAILED_ITEM_GONE = 43,
- SPELL_FAILED_ITEM_NOT_FOUND = 44,
- SPELL_FAILED_ITEM_NOT_READY = 45,
- SPELL_FAILED_LEVEL_REQUIREMENT = 46,
- SPELL_FAILED_LINE_OF_SIGHT = 47,
- SPELL_FAILED_LOWLEVEL = 48,
- SPELL_FAILED_LOW_CASTLEVEL = 49,
- SPELL_FAILED_MAINHAND_EMPTY = 50,
- SPELL_FAILED_MOVING = 51,
- SPELL_FAILED_NEED_AMMO = 52,
- SPELL_FAILED_NEED_AMMO_POUCH = 53,
- SPELL_FAILED_NEED_EXOTIC_AMMO = 54,
- SPELL_FAILED_NEED_MORE_ITEMS = 55,
- SPELL_FAILED_NOPATH = 56,
- SPELL_FAILED_NOT_BEHIND = 57,
- SPELL_FAILED_NOT_FISHABLE = 58,
- SPELL_FAILED_NOT_FLYING = 59,
- SPELL_FAILED_NOT_HERE = 60,
- SPELL_FAILED_NOT_INFRONT = 61,
- SPELL_FAILED_NOT_IN_CONTROL = 62,
- SPELL_FAILED_NOT_KNOWN = 63,
- SPELL_FAILED_NOT_MOUNTED = 64,
- SPELL_FAILED_NOT_ON_TAXI = 65,
- SPELL_FAILED_NOT_ON_TRANSPORT = 66,
- SPELL_FAILED_NOT_READY = 67,
- SPELL_FAILED_NOT_SHAPESHIFT = 68,
- SPELL_FAILED_NOT_STANDING = 69,
- SPELL_FAILED_NOT_TRADEABLE = 70,
- SPELL_FAILED_NOT_TRADING = 71,
- SPELL_FAILED_NOT_UNSHEATHED = 72,
- SPELL_FAILED_NOT_WHILE_GHOST = 73,
- SPELL_FAILED_NOT_WHILE_LOOTING = 74,
- SPELL_FAILED_NO_AMMO = 75,
- SPELL_FAILED_NO_CHARGES_REMAIN = 76,
- SPELL_FAILED_NO_CHAMPION = 77,
- SPELL_FAILED_NO_COMBO_POINTS = 78,
- SPELL_FAILED_NO_DUELING = 79,
- SPELL_FAILED_NO_ENDURANCE = 80,
- SPELL_FAILED_NO_FISH = 81,
- SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 82,
- SPELL_FAILED_NO_MOUNTS_ALLOWED = 83,
- SPELL_FAILED_NO_PET = 84,
- SPELL_FAILED_NO_POWER = 85,
- SPELL_FAILED_NOTHING_TO_DISPEL = 86,
- SPELL_FAILED_NOTHING_TO_STEAL = 87,
- SPELL_FAILED_ONLY_ABOVEWATER = 88,
- SPELL_FAILED_ONLY_DAYTIME = 89,
- SPELL_FAILED_ONLY_INDOORS = 90,
- SPELL_FAILED_ONLY_MOUNTED = 91,
- SPELL_FAILED_ONLY_NIGHTTIME = 92,
- SPELL_FAILED_ONLY_OUTDOORS = 93,
- SPELL_FAILED_ONLY_SHAPESHIFT = 94,
- SPELL_FAILED_ONLY_STEALTHED = 95,
- SPELL_FAILED_ONLY_UNDERWATER = 96,
- SPELL_FAILED_OUT_OF_RANGE = 97,
- SPELL_FAILED_PACIFIED = 98,
- SPELL_FAILED_POSSESSED = 99,
- SPELL_FAILED_REAGENTS = 100,
- SPELL_FAILED_REQUIRES_AREA = 101,
- SPELL_FAILED_REQUIRES_SPELL_FOCUS = 102,
- SPELL_FAILED_ROOTED = 103,
- SPELL_FAILED_SILENCED = 104,
- SPELL_FAILED_SPELL_IN_PROGRESS = 105,
- SPELL_FAILED_SPELL_LEARNED = 106,
- SPELL_FAILED_SPELL_UNAVAILABLE = 107,
- SPELL_FAILED_STUNNED = 108,
- SPELL_FAILED_TARGETS_DEAD = 109,
- SPELL_FAILED_TARGET_AFFECTING_COMBAT = 110,
- SPELL_FAILED_TARGET_AURASTATE = 111,
- SPELL_FAILED_TARGET_DUELING = 112,
- SPELL_FAILED_TARGET_ENEMY = 113,
- SPELL_FAILED_TARGET_ENRAGED = 114,
- SPELL_FAILED_TARGET_FRIENDLY = 115,
- SPELL_FAILED_TARGET_IN_COMBAT = 116,
- SPELL_FAILED_TARGET_IS_PLAYER = 117,
- SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 118,
- SPELL_FAILED_TARGET_NOT_DEAD = 119,
- SPELL_FAILED_TARGET_NOT_IN_PARTY = 120,
- SPELL_FAILED_TARGET_NOT_LOOTED = 121,
- SPELL_FAILED_TARGET_NOT_PLAYER = 122,
- SPELL_FAILED_TARGET_NO_POCKETS = 123,
- SPELL_FAILED_TARGET_NO_WEAPONS = 124,
- SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 125,
- SPELL_FAILED_TARGET_UNSKINNABLE = 126,
- SPELL_FAILED_THIRST_SATIATED = 127,
- SPELL_FAILED_TOO_CLOSE = 128,
- SPELL_FAILED_TOO_MANY_OF_ITEM = 129,
- SPELL_FAILED_TOTEM_CATEGORY = 130,
- SPELL_FAILED_TOTEMS = 131,
- SPELL_FAILED_TRY_AGAIN = 132,
- SPELL_FAILED_UNIT_NOT_BEHIND = 133,
- SPELL_FAILED_UNIT_NOT_INFRONT = 134,
- SPELL_FAILED_WRONG_PET_FOOD = 135,
- SPELL_FAILED_NOT_WHILE_FATIGUED = 136,
- SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 137,
- SPELL_FAILED_NOT_WHILE_TRADING = 138,
- SPELL_FAILED_TARGET_NOT_IN_RAID = 139,
- SPELL_FAILED_TARGET_FREEFORALL = 140,
- SPELL_FAILED_NO_EDIBLE_CORPSES = 141,
- SPELL_FAILED_ONLY_BATTLEGROUNDS = 142,
- SPELL_FAILED_TARGET_NOT_GHOST = 143,
- SPELL_FAILED_TRANSFORM_UNUSABLE = 144,
- SPELL_FAILED_WRONG_WEATHER = 145,
- SPELL_FAILED_DAMAGE_IMMUNE = 146,
- SPELL_FAILED_PREVENTED_BY_MECHANIC = 147,
- SPELL_FAILED_PLAY_TIME = 148,
- SPELL_FAILED_REPUTATION = 149,
- SPELL_FAILED_MIN_SKILL = 150,
- SPELL_FAILED_NOT_IN_ARENA = 151,
- SPELL_FAILED_NOT_ON_SHAPESHIFT = 152,
- SPELL_FAILED_NOT_ON_STEALTHED = 153,
- SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 154,
- SPELL_FAILED_NOT_ON_MOUNTED = 155,
- SPELL_FAILED_TOO_SHALLOW = 156,
- SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 157,
- SPELL_FAILED_TARGET_IS_TRIVIAL = 158,
- SPELL_FAILED_BM_OR_INVISGOD = 159,
- SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 160,
- SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 161,
- SPELL_FAILED_NOT_IDLE = 162,
- SPELL_FAILED_NOT_INACTIVE = 163,
- SPELL_FAILED_PARTIAL_PLAYTIME = 164,
- SPELL_FAILED_NO_PLAYTIME = 165,
- SPELL_FAILED_NOT_IN_BATTLEGROUND = 166,
- SPELL_FAILED_NOT_IN_RAID_INSTANCE = 167,
- SPELL_FAILED_ONLY_IN_ARENA = 168,
- SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 169,
- SPELL_FAILED_ON_USE_ENCHANT = 170,
- SPELL_FAILED_NOT_ON_GROUND = 171,
- SPELL_FAILED_CUSTOM_ERROR = 172,
- SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 173,
- SPELL_FAILED_TOO_MANY_SOCKETS = 174,
- SPELL_FAILED_INVALID_GLYPH = 175,
- SPELL_FAILED_UNIQUE_GLYPH = 176,
- SPELL_FAILED_GLYPH_SOCKET_LOCKED = 177,
- SPELL_FAILED_NO_VALID_TARGETS = 178,
- SPELL_FAILED_ITEM_AT_MAX_CHARGES = 179,
- SPELL_FAILED_NOT_IN_BARBERSHOP = 180,
- SPELL_FAILED_FISHING_TOO_LOW = 181,
- SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 182,
- SPELL_FAILED_SUMMON_PENDING = 183,
- SPELL_FAILED_MAX_SOCKETS = 184,
- SPELL_FAILED_PET_CAN_RENAME = 185,
- SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED = 186,
- SPELL_FAILED_UNKNOWN = 187, // actually doesn't exist in client
-
- SPELL_CAST_OK = 255 // custom value, must not be sent to client
+ SPELL_FAILED_SUCCESS = 0,
+ SPELL_FAILED_AFFECTING_COMBAT = 1,
+ SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 2,
+ SPELL_FAILED_ALREADY_AT_FULL_MANA = 3,
+ SPELL_FAILED_ALREADY_AT_FULL_POWER = 4,
+ SPELL_FAILED_ALREADY_BEING_TAMED = 5,
+ SPELL_FAILED_ALREADY_HAVE_CHARM = 6,
+ SPELL_FAILED_ALREADY_HAVE_SUMMON = 7,
+ SPELL_FAILED_ALREADY_HAVE_PET = 8,
+ SPELL_FAILED_ALREADY_OPEN = 9,
+ SPELL_FAILED_AURA_BOUNCED = 10,
+ SPELL_FAILED_AUTOTRACK_INTERRUPTED = 11,
+ SPELL_FAILED_BAD_IMPLICIT_TARGETS = 12,
+ SPELL_FAILED_BAD_TARGETS = 13,
+ SPELL_FAILED_CANT_BE_CHARMED = 14,
+ SPELL_FAILED_CANT_BE_DISENCHANTED = 15,
+ SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 16,
+ SPELL_FAILED_CANT_BE_MILLED = 17,
+ SPELL_FAILED_CANT_BE_PROSPECTED = 18,
+ SPELL_FAILED_CANT_CAST_ON_TAPPED = 19,
+ SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 20,
+ SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 21,
+ SPELL_FAILED_CANT_STEALTH = 22,
+ SPELL_FAILED_CASTER_AURASTATE = 23,
+ SPELL_FAILED_CASTER_DEAD = 24,
+ SPELL_FAILED_CHARMED = 25,
+ SPELL_FAILED_CHEST_IN_USE = 26,
+ SPELL_FAILED_CONFUSED = 27,
+ SPELL_FAILED_DONT_REPORT = 28,
+ SPELL_FAILED_EQUIPPED_ITEM = 29,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS = 30,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 31,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 32,
+ SPELL_FAILED_ERROR = 33,
+ SPELL_FAILED_FALLING = 34,
+ SPELL_FAILED_FIZZLE = 35,
+ SPELL_FAILED_FLEEING = 36,
+ SPELL_FAILED_FOOD_LOWLEVEL = 37,
+ SPELL_FAILED_HIGHLEVEL = 38,
+ SPELL_FAILED_HUNGER_SATIATED = 39,
+ SPELL_FAILED_IMMUNE = 40,
+ SPELL_FAILED_INCORRECT_AREA = 41,
+ SPELL_FAILED_INTERRUPTED = 42,
+ SPELL_FAILED_INTERRUPTED_COMBAT = 43,
+ SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 44,
+ SPELL_FAILED_ITEM_GONE = 45,
+ SPELL_FAILED_ITEM_NOT_FOUND = 46,
+ SPELL_FAILED_ITEM_NOT_READY = 47,
+ SPELL_FAILED_LEVEL_REQUIREMENT = 48,
+ SPELL_FAILED_LINE_OF_SIGHT = 49,
+ SPELL_FAILED_LOWLEVEL = 50,
+ SPELL_FAILED_LOW_CASTLEVEL = 51,
+ SPELL_FAILED_MAINHAND_EMPTY = 52,
+ SPELL_FAILED_MOVING = 53,
+ SPELL_FAILED_NEED_AMMO = 54,
+ SPELL_FAILED_NEED_AMMO_POUCH = 55,
+ SPELL_FAILED_NEED_EXOTIC_AMMO = 56,
+ SPELL_FAILED_NEED_MORE_ITEMS = 57,
+ SPELL_FAILED_NOPATH = 58,
+ SPELL_FAILED_NOT_BEHIND = 59,
+ SPELL_FAILED_NOT_FISHABLE = 60,
+ SPELL_FAILED_NOT_FLYING = 61,
+ SPELL_FAILED_NOT_HERE = 62,
+ SPELL_FAILED_NOT_INFRONT = 63,
+ SPELL_FAILED_NOT_IN_CONTROL = 64,
+ SPELL_FAILED_NOT_KNOWN = 65,
+ SPELL_FAILED_NOT_MOUNTED = 66,
+ SPELL_FAILED_NOT_ON_TAXI = 67,
+ SPELL_FAILED_NOT_ON_TRANSPORT = 68,
+ SPELL_FAILED_NOT_READY = 69,
+ SPELL_FAILED_NOT_SHAPESHIFT = 70,
+ SPELL_FAILED_NOT_STANDING = 71,
+ SPELL_FAILED_NOT_TRADEABLE = 72,
+ SPELL_FAILED_NOT_TRADING = 73,
+ SPELL_FAILED_NOT_UNSHEATHED = 74,
+ SPELL_FAILED_NOT_WHILE_GHOST = 75,
+ SPELL_FAILED_NOT_WHILE_LOOTING = 76,
+ SPELL_FAILED_NO_AMMO = 77,
+ SPELL_FAILED_NO_CHARGES_REMAIN = 78,
+ SPELL_FAILED_NO_CHAMPION = 79,
+ SPELL_FAILED_NO_COMBO_POINTS = 80,
+ SPELL_FAILED_NO_DUELING = 81,
+ SPELL_FAILED_NO_ENDURANCE = 82,
+ SPELL_FAILED_NO_FISH = 83,
+ SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 84,
+ SPELL_FAILED_NO_MOUNTS_ALLOWED = 85,
+ SPELL_FAILED_NO_PET = 86,
+ SPELL_FAILED_NO_POWER = 87,
+ SPELL_FAILED_NOTHING_TO_DISPEL = 88,
+ SPELL_FAILED_NOTHING_TO_STEAL = 89,
+ SPELL_FAILED_ONLY_ABOVEWATER = 90,
+ SPELL_FAILED_ONLY_DAYTIME = 91,
+ SPELL_FAILED_ONLY_INDOORS = 92,
+ SPELL_FAILED_ONLY_MOUNTED = 93,
+ SPELL_FAILED_ONLY_NIGHTTIME = 94,
+ SPELL_FAILED_ONLY_OUTDOORS = 95,
+ SPELL_FAILED_ONLY_SHAPESHIFT = 96,
+ SPELL_FAILED_ONLY_STEALTHED = 97,
+ SPELL_FAILED_ONLY_UNDERWATER = 98,
+ SPELL_FAILED_OUT_OF_RANGE = 99,
+ SPELL_FAILED_PACIFIED = 100,
+ SPELL_FAILED_POSSESSED = 101,
+ SPELL_FAILED_REAGENTS = 102,
+ SPELL_FAILED_REQUIRES_AREA = 103,
+ SPELL_FAILED_REQUIRES_SPELL_FOCUS = 104,
+ SPELL_FAILED_ROOTED = 105,
+ SPELL_FAILED_SILENCED = 106,
+ SPELL_FAILED_SPELL_IN_PROGRESS = 107,
+ SPELL_FAILED_SPELL_LEARNED = 108,
+ SPELL_FAILED_SPELL_UNAVAILABLE = 109,
+ SPELL_FAILED_STUNNED = 110,
+ SPELL_FAILED_TARGETS_DEAD = 111,
+ SPELL_FAILED_TARGET_AFFECTING_COMBAT = 112,
+ SPELL_FAILED_TARGET_AURASTATE = 113,
+ SPELL_FAILED_TARGET_DUELING = 114,
+ SPELL_FAILED_TARGET_ENEMY = 115,
+ SPELL_FAILED_TARGET_ENRAGED = 116,
+ SPELL_FAILED_TARGET_FRIENDLY = 117,
+ SPELL_FAILED_TARGET_IN_COMBAT = 118,
+ SPELL_FAILED_TARGET_IS_PLAYER = 119,
+ SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 120,
+ SPELL_FAILED_TARGET_NOT_DEAD = 121,
+ SPELL_FAILED_TARGET_NOT_IN_PARTY = 122,
+ SPELL_FAILED_TARGET_NOT_LOOTED = 123,
+ SPELL_FAILED_TARGET_NOT_PLAYER = 124,
+ SPELL_FAILED_TARGET_NO_POCKETS = 125,
+ SPELL_FAILED_TARGET_NO_WEAPONS = 126,
+ SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 127,
+ SPELL_FAILED_TARGET_UNSKINNABLE = 128,
+ SPELL_FAILED_THIRST_SATIATED = 129,
+ SPELL_FAILED_TOO_CLOSE = 130,
+ SPELL_FAILED_TOO_MANY_OF_ITEM = 131,
+ SPELL_FAILED_TOTEM_CATEGORY = 132,
+ SPELL_FAILED_TOTEMS = 133,
+ SPELL_FAILED_TRY_AGAIN = 134,
+ SPELL_FAILED_UNIT_NOT_BEHIND = 135,
+ SPELL_FAILED_UNIT_NOT_INFRONT = 136,
+ SPELL_FAILED_VISION_OBSCURED = 137,
+ SPELL_FAILED_WRONG_PET_FOOD = 138,
+ SPELL_FAILED_NOT_WHILE_FATIGUED = 139,
+ SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 140,
+ SPELL_FAILED_NOT_WHILE_TRADING = 141,
+ SPELL_FAILED_TARGET_NOT_IN_RAID = 142,
+ SPELL_FAILED_TARGET_FREEFORALL = 143,
+ SPELL_FAILED_NO_EDIBLE_CORPSES = 144,
+ SPELL_FAILED_ONLY_BATTLEGROUNDS = 145,
+ SPELL_FAILED_TARGET_NOT_GHOST = 146,
+ SPELL_FAILED_TRANSFORM_UNUSABLE = 147,
+ SPELL_FAILED_WRONG_WEATHER = 148,
+ SPELL_FAILED_DAMAGE_IMMUNE = 149,
+ SPELL_FAILED_PREVENTED_BY_MECHANIC = 150,
+ SPELL_FAILED_PLAY_TIME = 151,
+ SPELL_FAILED_REPUTATION = 152,
+ SPELL_FAILED_MIN_SKILL = 153,
+ SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND = 154,
+ SPELL_FAILED_NOT_ON_SHAPESHIFT = 155,
+ SPELL_FAILED_NOT_ON_STEALTHED = 156,
+ SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 157,
+ SPELL_FAILED_NOT_ON_MOUNTED = 158,
+ SPELL_FAILED_TOO_SHALLOW = 159,
+ SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 160,
+ SPELL_FAILED_TARGET_IS_TRIVIAL = 161,
+ SPELL_FAILED_BM_OR_INVISGOD = 162,
+ SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 163,
+ SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 164,
+ SPELL_FAILED_NOT_IDLE = 165,
+ SPELL_FAILED_NOT_INACTIVE = 166,
+ SPELL_FAILED_PARTIAL_PLAYTIME = 167,
+ SPELL_FAILED_NO_PLAYTIME = 168,
+ SPELL_FAILED_NOT_IN_BATTLEGROUND = 169,
+ SPELL_FAILED_NOT_IN_RAID_INSTANCE = 170,
+ SPELL_FAILED_ONLY_IN_ARENA = 171,
+ SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 172,
+ SPELL_FAILED_ON_USE_ENCHANT = 173,
+ SPELL_FAILED_NOT_ON_GROUND = 174,
+ SPELL_FAILED_CUSTOM_ERROR = 175,
+ SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 176,
+ SPELL_FAILED_TOO_MANY_SOCKETS = 177,
+ SPELL_FAILED_INVALID_GLYPH = 178,
+ SPELL_FAILED_UNIQUE_GLYPH = 179,
+ SPELL_FAILED_GLYPH_SOCKET_LOCKED = 180,
+ SPELL_FAILED_NO_VALID_TARGETS = 181,
+ SPELL_FAILED_ITEM_AT_MAX_CHARGES = 182,
+ SPELL_FAILED_NOT_IN_BARBERSHOP = 183,
+ SPELL_FAILED_FISHING_TOO_LOW = 184,
+ SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 185,
+ SPELL_FAILED_SUMMON_PENDING = 186,
+ SPELL_FAILED_MAX_SOCKETS = 187,
+ SPELL_FAILED_PET_CAN_RENAME = 188,
+ SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED = 189,
+ SPELL_FAILED_NO_ACTIONS = 190,
+ SPELL_FAILED_CURRENCY_WEIGHT_MISMATCH = 191,
+ SPELL_FAILED_WEIGHT_NOT_ENOUGH = 192,
+ SPELL_FAILED_WEIGHT_TOO_MUCH = 193,
+ SPELL_FAILED_NO_VACANT_SEAT = 194,
+ SPELL_FAILED_NO_LIQUID = 195,
+ SPELL_FAILED_ONLY_NOT_SWIMMING = 196,
+ SPELL_FAILED_BY_NOT_MOVING = 197,
+ SPELL_FAILED_IN_COMBAT_RES_LIMIT_REACHED = 198,
+ SPELL_FAILED_NOT_IN_ARENA = 199,
+ SPELL_FAILED_TARGET_NOT_GROUNDED = 200,
+ SPELL_FAILED_EXCEEDED_WEEKLY_USAGE = 201,
+ SPELL_FAILED_NOT_IN_LFG_DUNGEON = 202,
+ SPELL_FAILED_UNKNOWN = 254, // custom value, default case
+ SPELL_CAST_OK = 255, // custom value, must not be sent to client
};
enum SpellCustomErrors
@@ -1100,38 +1253,80 @@ enum SpellCustomErrors
SPELL_CUSTOM_ERROR_GM_ONLY = 65, // Only GMs may use that. Your account has been reported for investigation.
SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_58 = 66, // You must reach level 58 to use this portal.
SPELL_CUSTOM_ERROR_AT_HONOR_CAP = 67, // You already have the maximum amount of honor.
- SPELL_CUSTOM_ERROR_68 = 68, // ""
- SPELL_CUSTOM_ERROR_69 = 69, // ""
- SPELL_CUSTOM_ERROR_70 = 70, // ""
- SPELL_CUSTOM_ERROR_71 = 71, // ""
- SPELL_CUSTOM_ERROR_72 = 72, // ""
- SPELL_CUSTOM_ERROR_73 = 73, // ""
- SPELL_CUSTOM_ERROR_74 = 74, // ""
+ SPELL_CUSTOM_ERROR_HAVE_HOT_ROD = 68, // You already have a Hot Rod.
+ SPELL_CUSTOM_ERROR_PARTYGOER_MORE_BUBBLY = 69, // This partygoer wants some more bubbly
+ SPELL_CUSTOM_ERROR_PARTYGOER_NEED_BUCKET = 70, // This partygoer needs a bucket!
+ SPELL_CUSTOM_ERROR_PARTYGOER_WANT_TO_DANCE = 71, // This partygoer wants to dance with you.
+ SPELL_CUSTOM_ERROR_PARTYGOER_WANT_FIREWORKS = 72, // This partygoer wants to see some fireworks.
+ SPELL_CUSTOM_ERROR_PARTYGOER_WANT_APPETIZER = 73, // This partygoer wants some more hors d'oeuvres.
+ SPELL_CUSTOM_ERROR_GOBLIN_BATTERY_DEPLETED = 74, // The Goblin All-In-1-Der Belt's battery is depleted.
SPELL_CUSTOM_ERROR_MUST_HAVE_DEMONIC_CIRCLE = 75, // You must have a demonic circle active.
SPELL_CUSTOM_ERROR_AT_MAX_RAGE = 76, // You already have maximum rage
SPELL_CUSTOM_ERROR_REQUIRES_350_ENGINEERING = 77, // Requires Engineering (350)
SPELL_CUSTOM_ERROR_SOUL_BELONGS_TO_LICH_KING = 78, // Your soul belongs to the Lich King
SPELL_CUSTOM_ERROR_ATTENDANT_HAS_PONY = 79, // Your attendant already has an Argent Pony
- SPELL_CUSTOM_ERROR_80 = 80, // ""
- SPELL_CUSTOM_ERROR_81 = 81, // ""
- SPELL_CUSTOM_ERROR_82 = 82, // ""
+ SPELL_CUSTOM_ERROR_GOBLIN_STARTING_MISSION = 80, // First, Overload the Defective Generator, Activate the Leaky Stove, and Drop a Cigar on the Flammable Bed.
+ SPELL_CUSTOM_ERROR_GASBOT_ALREADY_SENT = 81, // You've already sent in the Gasbot and destroyed headquarters!
+ SPELL_CUSTOM_ERROR_GOBLIN_IS_PARTIED_OUT = 82, // This goblin is all partied out!
SPELL_CUSTOM_ERROR_MUST_HAVE_FIRE_TOTEM = 83, // You must have a Fire Totem active.
SPELL_CUSTOM_ERROR_CANT_TARGET_VAMPIRES = 84, // You may not bite other vampires.
SPELL_CUSTOM_ERROR_PET_ALREADY_AT_YOUR_LEVEL = 85, // Your pet is already at your level.
SPELL_CUSTOM_ERROR_MISSING_ITEM_REQUIREMENS = 86, // You do not meet the level requirements for this item.
SPELL_CUSTOM_ERROR_TOO_MANY_ABOMINATIONS = 87, // There are too many Mutated Abominations.
SPELL_CUSTOM_ERROR_ALL_POTIONS_USED = 88, // The potions have all been depleted by Professor Putricide.
- SPELL_CUSTOM_ERROR_89 = 89, // ""
+ SPELL_CUSTOM_ERROR_DEFEATED_ENOUGH_ALREADY = 89, // You have already defeated enough of them.
SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_65 = 90, // Requires level 65
- SPELL_CUSTOM_ERROR_91 = 91, // ""
- SPELL_CUSTOM_ERROR_92 = 92, // ""
- SPELL_CUSTOM_ERROR_93 = 93, // ""
- SPELL_CUSTOM_ERROR_94 = 94, // ""
- SPELL_CUSTOM_ERROR_95 = 95, // ""
+ SPELL_CUSTOM_ERROR_DESTROYED_KTC_OIL_PLATFORM = 91, // You have already destroyed the KTC Oil Platform.
+ SPELL_CUSTOM_ERROR_LAUNCHED_ENOUGH_CAGES = 92, // You have already launched enough cages.
+ SPELL_CUSTOM_ERROR_REQUIRES_BOOSTER_ROCKETS = 93, // Requires Single-Stage Booster Rockets. Return to Hobart Grapplehammer to get more.
+ SPELL_CUSTOM_ERROR_ENOUGH_WILD_CLUCKERS = 94, // You have already captured enough wild cluckers.
+ SPELL_CUSTOM_ERROR_REQUIRES_CONTROL_FIREWORKS = 95, // Requires Remote Control Fireworks. Return to Hobart Grapplehammer to get more.
SPELL_CUSTOM_ERROR_MAX_NUMBER_OF_RECRUITS = 96, // You already have the max number of recruits.
SPELL_CUSTOM_ERROR_MAX_NUMBER_OF_VOLUNTEERS = 97, // You already have the max number of volunteers.
SPELL_CUSTOM_ERROR_FROSTMOURNE_RENDERED_RESURRECT = 98, // Frostmourne has rendered you unable to resurrect.
- SPELL_CUSTOM_ERROR_CANT_MOUNT_WITH_SHAPESHIFT = 99 // You can't mount while affected by that shapeshift.
+ SPELL_CUSTOM_ERROR_CANT_MOUNT_WITH_SHAPESHIFT = 99, // You can't mount while affected by that shapeshift.
+ SPELL_CUSTOM_ERROR_FAWNS_ALREADY_FOLLOWING = 100, // Three fawns are already following you!
+ SPELL_CUSTOM_ERROR_ALREADY_HAVE_RIVER_BOAT = 101, // You already have a River Boat.
+ SPELL_CUSTOM_ERROR_NO_ACTIVE_ENCHANTMENT = 102, // You have no active enchantment to unleash.
+ SPELL_CUSTOM_ERROR_ENOUGH_HIGHBOURNE_SOULS = 103, // You have bound enough Highborne souls. Return to Arcanist Valdurian.
+ SPELL_CUSTOM_ERROR_ATLEAST_40YD_FROM_OIL_DRILLING = 104, // You must be at least 40 yards away from all other Oil Drilling Rigs.
+ SPELL_CUSTOM_ERROR_ABOVE_ENSLAVED_PEARL_MINER = 106, // You must be above the Enslaved Pearl Miner.
+ SPELL_CUSTOM_ERROR_MUST_TARGET_CORPSE_SPECIAL_1 = 107, // You must target the corpse of a Seabrush Terrapin, Scourgut Remora, or Spinescale Hammerhead.
+ SPELL_CUSTOM_ERROR_SLAGHAMMER_ALREADY_PRISONER = 108, // Ambassador Slaghammer is already your prisoner.
+ SPELL_CUSTOM_ERROR_REQUIRE_ATTUNED_LOCATION_1 = 109, // Requires a location that is attuned with the Naz'jar Battlemaiden.
+ SPELL_CUSTOM_ERROR_NEED_TO_FREE_DRAKE_FIRST = 110, // Free the Drake from the net first!
+ SPELL_CUSTOM_ERROR_DRAGONMAW_ALLIES_ALREADY_FOLLOW = 111, // You already have three Dragonmaw allies following you.
+ SPELL_CUSTOM_ERROR_REQUIRE_OPPOSABLE_THUMBS = 112, // Requires Opposable Thumbs.
+ SPELL_CUSTOM_ERROR_NOT_ENOUGH_HEALTH_2 = 113, // Not enough health
+ SPELL_CUSTOM_ERROR_ENOUGH_FORSAKEN_TROOPERS = 114, // You already have enough Forsaken Troopers.
+ SPELL_CUSTOM_ERROR_CANNOT_JUMP_TO_BOULDER = 115, // You cannot jump to another boulder yet.
+ SPELL_CUSTOM_ERROR_SKILL_TOO_HIGH = 116, // Skill too high.
+ SPELL_CUSTOM_ERROR_ALREADY_6_SURVIVORS_RESCUED = 117, // You have already rescued 6 Survivors.
+ SPELL_CUSTOM_ERROR_MUST_FACE_SHIPS_FROM_BALLOON = 118, // You need to be facing the ships from the rescue balloon.
+ SPELL_CUSTOM_ERROR_CANNOT_SUPERVISE_MORE_CULTISTS = 119, // You cannot supervise more than 5 Arrested Cultists at a time.
+ SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_85 = 120, // You must reach level 85 to use this portal.
+ SPELL_CUSTOM_ERROR_MUST_BE_BELOW_35_HEALTH = 121, // Your target must be below 35% health.
+ SPELL_CUSTOM_ERROR_MUST_SELECT_TALENT_SPECIAL = 122, // You must select a talent specialization first.
+ SPELL_CUSTOM_ERROR_TOO_WISE_AND_POWERFUL = 123, // You are too wise and powerful to gain any benefit from that item.
+ SPELL_CUSTOM_ERROR_TOO_CLOSE_ARGENT_LIGHTWELL = 124, // You are within 10 yards of another Argent Lightwell.
+ SPELL_CUSTOM_ERROR_NOT_WHILE_SHAPESHIFTED = 125, // You can't do that while shapeshifted.
+ SPELL_CUSTOM_ERROR_MANA_GEM_IN_BANK = 126, // You already have a Mana Gem in your bank.
+ SPELL_CUSTOM_ERROR_FLAME_SHOCK_NOT_ACTIVE = 127, // You must have at least one Flame Shock active.
+ SPELL_CUSTOM_ERROR_CANT_TRANSFORM = 128, // You cannot transform right now
+ SPELL_CUSTOM_ERROR_PET_MUST_BE_ATTACKING = 129, // Your pet must be attacking a target.
+ SPELL_CUSTOM_ERROR_GNOMISH_ENGINEERING = 130, // Requires Gnomish Engineering
+ SPELL_CUSTOM_ERROR_GOBLIN_ENGINEERING = 131, // Requires Goblin Engineering
+ SPELL_CUSTOM_ERROR_NO_TARGET = 132, // You have no target.
+ SPELL_CUSTOM_ERROR_PET_OUT_OF_RANGE = 133, // Your Pet is out of range of the target.
+ SPELL_CUSTOM_ERROR_HOLDING_FLAG = 134, // You can't do that while holding the flag.
+ SPELL_CUSTOM_ERROR_TARGET_HOLDING_FLAG = 135, // You can't do that to targets holding the flag.
+ SPELL_CUSTOM_ERROR_PORTAL_NOT_OPEN = 136, // The portal is not yet open. Continue helping the druids at the Sanctuary of Malorne.
+ SPELL_CUSTOM_ERROR_AGGRA_AIR_TOTEM = 137, // You need to be closer to Aggra's Air Totem, in the west.
+ SPELL_CUSTOM_ERROR_AGGRA_WATER_TOTEM = 138, // You need to be closer to Aggra's Water Totem, in the north.
+ SPELL_CUSTOM_ERROR_AGGRA_EARTH_TOTEM = 139, // You need to be closer to Aggra's Earth Totem, in the east.
+ SPELL_CUSTOM_ERROR_AGGRA_FIRE_TOTEM = 140, // You need to be closer to Aggra's Fire Totem, near Thrall.
+ SPELL_CUSTOM_ERROR_TARGET_HAS_STARTDUST_2 = 148, // Target is already affected by Stardust No. 2.
+ SPELL_CUSTOM_ERROR_ELEMENTIUM_GEM_CLUSTERS = 149 // You cannot deconstruct Elementium Gem Clusters while collecting them!
};
enum StealthType
@@ -1156,8 +1351,34 @@ enum InvisibilityType
INVISIBILITY_UNK9 = 9,
INVISIBILITY_UNK10 = 10,
INVISIBILITY_UNK11 = 11,
-
- TOTAL_INVISIBILITY_TYPES = 12
+ INVISIBILITY_UNK12 = 12,
+ INVISIBILITY_TRA13 = 13,
+ INVISIBILITY_UNK14 = 14,
+ INVISIBILITY_UNK15 = 15,
+ INVISIBILITY_UNK16 = 16,
+ INVISIBILITY_UNK17 = 17,
+ INVISIBILITY_UNK18 = 18,
+ INVISIBILITY_UNK19 = 19,
+ INVISIBILITY_UNK20 = 20,
+ INVISIBILITY_UNK21 = 21,
+ INVISIBILITY_UNK22 = 22,
+ INVISIBILITY_TRA23 = 23,
+ INVISIBILITY_UNK24 = 24,
+ INVISIBILITY_UNK25 = 25,
+ INVISIBILITY_UNK26 = 26,
+ INVISIBILITY_UNK27 = 27,
+ INVISIBILITY_UNK28 = 28,
+ INVISIBILITY_UNK29 = 29,
+ INVISIBILITY_UNK30 = 30,
+ INVISIBILITY_UNK31 = 31,
+ INVISIBILITY_UNK32 = 32,
+ INVISIBILITY_UNK33 = 33,
+ INVISIBILITY_UNK34 = 34,
+ INVISIBILITY_UNK35 = 35,
+ INVISIBILITY_UNK36 = 36,
+ INVISIBILITY_UNK37 = 37,
+
+ TOTAL_INVISIBILITY_TYPES = 38
};
enum ServerSideVisibilityType
@@ -1243,14 +1464,15 @@ enum Mechanics
MECHANIC_IMMUNE_SHIELD = 29, // Divine (Blessing) Shield/Protection and Ice Block
MECHANIC_SAPPED = 30,
MECHANIC_ENRAGED = 31,
- MAX_MECHANIC = 32
+ MECHANIC_WOUNDED = 32,
+ MAX_MECHANIC = 33
};
// Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967ca6)
#define IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK (\
(1<<MECHANIC_CHARM)|(1<<MECHANIC_DISORIENTED)|(1<<MECHANIC_FEAR)| \
(1<<MECHANIC_ROOT)|(1<<MECHANIC_SLEEP)|(1<<MECHANIC_SNARE)| \
- (1<<MECHANIC_STUN)|(1<<MECHANIC_FREEZE)|(1<<MECHANIC_KNOCKOUT)| \
+ (1<<MECHANIC_STUN)|(1<<MECHANIC_FREEZE)|(1<<MECHANIC_SILENCE)|(1<<MECHANIC_DISARM)|(1<<MECHANIC_KNOCKOUT)| \
(1<<MECHANIC_POLYMORPH)|(1<<MECHANIC_BANISH)|(1<<MECHANIC_SHACKLE)| \
(1<<MECHANIC_TURN)|(1<<MECHANIC_HORROR)|(1<<MECHANIC_DAZE)| \
(1<<MECHANIC_SAPPED))
@@ -1399,6 +1621,23 @@ enum Targets
TARGET_UNK_DEST_AREA_UNK_107 = 107, // not enough info - only generic spells avalible
TARGET_GAMEOBJECT_CONE = 108,
TARGET_DEST_UNK_110 = 110, // 1 spell
+ TARGET_UNK_111 = 111,
+ TARGET_UNK_112 = 112,
+ TARGET_UNK_113 = 113,
+ TARGET_UNK_114 = 114,
+ TARGET_UNK_115 = 115,
+ TARGET_UNK_116 = 116,
+ TARGET_UNK_117 = 117,
+ TARGET_UNK_118 = 118,
+ TARGET_UNK_119 = 119,
+ TARGET_UNK_120 = 120,
+ TARGET_UNK_121 = 121,
+ TARGET_UNK_122 = 122,
+ TARGET_UNK_123 = 123,
+ TARGET_UNK_124 = 124,
+ TARGET_UNK_125 = 125,
+ TARGET_UNK_126 = 126,
+ TARGET_UNK_127 = 127,
TOTAL_SPELL_TARGETS
};
@@ -1440,7 +1679,8 @@ enum SpellPreventionType
{
SPELL_PREVENTION_TYPE_NONE = 0,
SPELL_PREVENTION_TYPE_SILENCE = 1,
- SPELL_PREVENTION_TYPE_PACIFY = 2
+ SPELL_PREVENTION_TYPE_PACIFY = 2,
+ SPELL_PREVENTION_TYPE_UNK = 3 // Only a few spells have this, but most of the should be interruptable.
};
enum GameobjectTypes
@@ -1484,7 +1724,7 @@ enum GameobjectTypes
};
#define MAX_GAMEOBJECT_TYPE 36 // sending to client this or greater value can crash client.
-#define MAX_GAMEOBJECT_DATA 24 // Max number of uint32 vars in gameobject_template data field
+#define MAX_GAMEOBJECT_DATA 32 // Max number of uint32 vars in gameobject_template data field
enum GameObjectFlags
{
@@ -1770,7 +2010,8 @@ enum TextEmotes
TEXT_EMOTE_LOOK = 449,
TEXT_EMOTE_OBJECT = 450,
TEXT_EMOTE_SWEAT = 451,
- TEXT_EMOTE_YW = 453
+ TEXT_EMOTE_YW = 453,
+ TEXT_EMOTE_READ = 456
};
// Emotes.dbc
@@ -1950,7 +2191,19 @@ enum Emote
EMOTE_STATE_STRANGULATE = 473,
EMOTE_STATE_READY_SPELL_OMNI = 474,
EMOTE_STATE_HOLD_JOUST = 475,
- EMOTE_ONESHOT_CRY_JAINA = 476
+ EMOTE_ONESHOT_CRY_JAINA = 476,
+ EMOTE_ONESHOT_SPECIAL_UNARMED = 477,
+ EMOTE_STATE_DANCE_NOSHEATHE = 478,
+ EMOTE_ONESHOT_SNIFF = 479,
+ EMOTE_ONESHOT_DRAGONSTOMP = 480,
+ EMOTE_ONESHOT_KNOCKDOWN = 482,
+ EMOTE_STATE_READ = 483,
+ EMOTE_ONESHOT_FLYEMOTETALK = 485,
+ EMOTE_STATE_READ_ALLOWMOVEMENT = 492,
+ EMOTE_STATE_READY1H_ALLOW_MOVEMENT = 505,
+ EMOTE_STATE_READY2H_ALLOW_MOVEMENT = 506,
+ EMOTE_ONESHOT_OPEN = 517,
+ EMOTE_STATE_READ_CHRISTMAS = 518
};
// AnimationData.dbc
@@ -2461,7 +2714,161 @@ enum Anim
ANIM_CARRY2H = 502,
ANIM_CARRIED2H = 503,
ANIM_FLY_CARRY2H = 504,
- ANIM_FLY_CARRIED2H = 505
+ ANIM_FLY_CARRIED2H = 505,
+ ANIM_EMOTE_SNIFF = 506,
+ ANIM_EMOTE_FLY_SNIFF = 507,
+ ANIM_ATTACK_FIST1H = 508,
+ ANIM_FLY_ATTACK_FIST1H = 509,
+ ANIM_ATTACK_FIST_1H_OFF = 510,
+ ANIM_FLY_ATTACK_FIST_1H_OFF = 511,
+ ANIM_PARRY_FIST1H = 512,
+ ANIM_FLY_PARRY_FIST1H = 513,
+ ANIM_READY_FIST1H = 514,
+ ANIM_FLY_READY_FIST1H = 515,
+ ANIM_SPECIAL_FIST1H = 516,
+ ANIM_FLY_SPECIAL_FIST1H = 517,
+ ANIM_EMOTE_READ_START = 518,
+ ANIM_FLY_EMOTE_READ_START = 519,
+ ANIM_EMOTE_READ_LOOP = 520,
+ ANIM_FLY_EMOTE_READ_LOOP = 521,
+ ANIM_EMOTE_READ_END = 522,
+ ANIM_FLY_EMOTE_READ_END = 523,
+ ANIM_SWIM_RUN = 524,
+ ANIM_FLY_SWIM_RUN = 525,
+ ANIM_SWIM_WALK = 526,
+ ANIM_FLY_SWIM_WALK = 527,
+ ANIM_SWIM_WALK_BACKWARDS = 528,
+ ANIM_FLY_SWIM_WALK_BACKWARDS = 529,
+ ANIM_SWIM_SPRINT = 530,
+ ANIM_FLY_SWIM_SPRINT = 531,
+ ANIM_MOUNT_SWIM_IDLE = 532,
+ ANIM_FLY_MOUNT_SWIM_IDLE = 533,
+ ANIM_MOUNT_SWIM_BACKWARDS = 534,
+ ANIM_FLY_MOUNT_SWIM_BACKWARDS = 535,
+ ANIM_MOUNT_SWIM_LEFT = 536,
+ ANIM_FLY_MOUNT_SWIM_LEFT = 537,
+ ANIM_MOUNT_SWIM_RIGHT = 538,
+ ANIM_FLY_MOUNT_SWIM_RIGHT = 539,
+ ANIM_MOUNT_SWIM_RUN = 540,
+ ANIM_FLY_MOUNT_SWIM_RUN = 541,
+ ANIM_MOUNT_SWIM_SPRINT = 542,
+ ANIM_FLY_MOUNT_SWIM_SPRINT = 543,
+ ANIM_MOUNT_SWIM_WALK = 544,
+ ANIM_FLY_MOUNT_SWIM_WALK = 545,
+ ANIM_MOUNT_SWIM_WALK_BACKWARDS = 546,
+ ANIM_FLY_MOUNT_SWIM_WALK_BACKWARDS = 547,
+ ANIM_MOUNT_FLIGHT_IDLE = 548,
+ ANIM_FLY_MOUNT_FLIGHT_IDLE = 549,
+ ANIM_MOUNT_FLIGHT_BACKWARDS = 550,
+ ANIM_FLY_MOUNT_FLIGHT_BACKWARDS = 551,
+ ANIM_MOUNT_FLIGHT_LEFT = 552,
+ ANIM_FLY_MOUNT_FLIGHT_LEFT = 553,
+ ANIM_MOUNT_FLIGHT_RIGHT = 554,
+ ANIM_FLY_MOUNT_FLIGHT_RIGHT = 555,
+ ANIM_MOUNT_FLIGHT_RUN = 556,
+ ANIM_FLY_MOUNT_FLIGHT_RUN = 557,
+ ANIM_MOUNT_FLIGHT_SPRINT = 558,
+ ANIM_FLY_MOUNT_FLIGHT_SPRINT = 559,
+ ANIM_MOUNT_FLIGHT_WALK = 560,
+ ANIM_FLY_MOUNT_FLIGHT_WALK = 561,
+ ANIM_MOUNT_FLIGHT_WALK_BACKWARDS = 562,
+ ANIM_FLY_MOUNT_FLIGHT_WALK_BACKWARDS = 563,
+ ANIM_MOUNT_FLIGHT_START = 564,
+ ANIM_FLY_MOUNT_FLIGHT_START = 565,
+ ANIM_MOUNT_SWIM_START = 566,
+ ANIM_FLY_MOUNT_SWIM_START = 567,
+ ANIM_MOUNT_SWIM_LAND = 568,
+ ANIM_FLY_MOUNT_SWIM_LAND = 569,
+ ANIM_MOUNT_SWIM_LAND_RUN = 570,
+ ANIM_FLY_MOUNT_SWIM_LAND_RUN = 571,
+ ANIM_MOUNT_FLIGHT_LAND = 572,
+ ANIM_FLY_MOUNT_FLIGHT_LAND = 573,
+ ANIM_MOUNT_FLIGHT_LAND_RUN = 574,
+ ANIM_FLY_MOUNT_FLIGHT_LAND_RUN = 575,
+ ANIM_READY_BLOW_DART = 576,
+ ANIM_FLY_READY_BLOW_DART = 577,
+ ANIM_LOAD_BLOW_DART = 578,
+ ANIM_FLY_LOAD_BLOW_DART = 579,
+ ANIM_HOLD_BLOW_DART = 580,
+ ANIM_FLY_HOLD_BLOW_DART = 581,
+ ANIM_ATTACK_BLOW_DART = 582,
+ ANIM_FLY_ATTACK_BLOW_DART = 583,
+ ANIM_CARRIAGE_MOUNT = 584,
+ ANIM_FLY_CARRIAGE_MOUNT = 585,
+ ANIM_CARRIAGE_PASSENGER_MOUNT = 586,
+ ANIM_FLY_CARRIAGE_PASSENGER_MOUNT = 587,
+ ANIM_CARRIAGE_MOUNT_ATTACK = 588,
+ ANIM_FLY_CARRIAGE_MOUNT_ATTACK = 589,
+ ANIM_BARTENDER_STAND = 590,
+ ANIM_FLY_BARTENDER_STAND = 591,
+ ANIM_BARTENDER_WALK = 592,
+ ANIM_FLY_BARTENDER_WALK = 593,
+ ANIM_BARTENDER_RUN = 594,
+ ANIM_FLY_BARTENDER_RUN = 595,
+ ANIM_BARTENDER_SHUFFLE_LEFT = 596,
+ ANIM_FLY_BARTENDER_SHUFFLE_LEFT = 597,
+ ANIM_BARTENDER_SHUFFLE_RIGHT = 598,
+ ANIM_FLY_BARTENDER_SHUFFLE_RIGHT = 599,
+ ANIM_BARTENDER_EMOTE_TALK = 600,
+ ANIM_FLY_BARTENDER_EMOTE_TALK = 601,
+ ANIM_BARTENDER_EMOTE_POINT = 602,
+ ANIM_FLY_BARTENDER_EMOTE_POINT = 603,
+ ANIM_BARMAID_STAND = 604,
+ ANIM_FLY_BARMAID_STAND = 605,
+ ANIM_BARMAID_WALK = 606,
+ ANIM_FLY_BARMAID_WALK = 607,
+ ANIM_BARMAID_RUN = 608,
+ ANIM_FLY_BARMAID_RUN = 609,
+ ANIM_BARMAID_SHUFFLE_LEFT = 610,
+ ANIM_FLY_BARMAID_SHUFFLE_LEFT = 611,
+ ANIM_BARMAID_SHUFFLE_RIGHT = 612,
+ ANIM_FLY_BARMAID_SHUFFLE_RIGHT = 613,
+ ANIM_BARMAID_EMOTE_TALK = 614,
+ ANIM_FLY_BARMAID_EMOTE_TALK = 615,
+ ANIM_BARMAID_EMOTE_POINT = 616,
+ ANIM_FLY_BARMAID_EMOTE_POINT = 617,
+ ANIM_MOUNT_SELF_IDLE = 618,
+ ANIM_FLY_MOUNT_SELF_IDLE = 619,
+ ANIM_MOUNT_SELF_WALK = 620,
+ ANIM_FLY_MOUNT_SELF_WALK = 621,
+ ANIM_MOUNT_SELF_RUN = 622,
+ ANIM_FLY_MOUNT_SELF_RUN = 623,
+ ANIM_MOUNT_SELF_SPRINT = 624,
+ ANIM_FLY_MOUNT_SELF_SPRINT = 625,
+ ANIM_MOUNT_SELF_RUN_LEFT = 626,
+ ANIM_FLY_MOUNT_SELF_RUN_LEFT = 627,
+ ANIM_MOUNT_SELF_RUN_RIGHT = 628,
+ ANIM_FLY_MOUNT_SELF_RUN_RIGHT = 629,
+ ANIM_MOUNT_SELF_SHUFFLE_LEFT = 630,
+ ANIM_FLY_MOUNT_SELF_SHUFFLE_LEFT = 631,
+ ANIM_MOUNT_SELF_SHUFFLE_RIGHT = 632,
+ ANIM_FLY_MOUNT_SELF_SHUFFLE_RIGHT = 633,
+ ANIM_MOUNT_SELF_WALK_BACKWARDS = 634,
+ ANIM_FLY_MOUNT_SELF_WALK_BACKWARDS = 635,
+ ANIM_MOUNT_SELF_SPECIAL = 636,
+ ANIM_FLY_MOUNT_SELF_SPECIAL = 637,
+ ANIM_MOUNT_SELF_JUMP = 638,
+ ANIM_FLY_MOUNT_SELF_JUMP = 639,
+ ANIM_MOUNT_SELF_JUMP_START = 640,
+ ANIM_FLY_MOUNT_SELF_JUMP_START = 641,
+ ANIM_MOUNT_SELF_JUMP_END = 642,
+ ANIM_FLY_MOUNT_SELF_JUMP_END = 643,
+ ANIM_MOUNT_SELF_JUMP_LAND_RUN = 644,
+ ANIM_FLY_MOUNT_SELF_JUMP_LAND_RUN = 645,
+ ANIM_MOUNT_SELF_START = 646,
+ ANIM_FLY_MOUNT_SELF_START = 647,
+ ANIM_MOUNT_SELF_FALL = 648,
+ ANIM_FLY_MOUNT_SELF_FALL = 649,
+ ANIM_STORMSTRIKE = 650,
+ ANIM_FLY_STORMSTRIKE = 651,
+ ANIM_READY_JOUST_NO_SHEATHE = 652,
+ ANIM_FLY_READY_JOUST_NO_SHEATHE = 653,
+ ANIM_SLAM = 654,
+ ANIM_FLY_SLAM = 655,
+ ANIM_DEATH_STRIKE = 656,
+ ANIM_FLY_DEATH_STRIKE = 657,
+ ANIM_SWIM_ATTACK_UNARMED = 658,
+ ANIM_FLY_SWIM_ATTACK_UNARMED = 659
};
enum LockKeyType
@@ -2571,7 +2978,18 @@ enum CreatureFamily
CREATURE_FAMILY_RHINO = 43,
CREATURE_FAMILY_WASP = 44,
CREATURE_FAMILY_CORE_HOUND = 45,
- CREATURE_FAMILY_SPIRIT_BEAST = 46
+ CREATURE_FAMILY_SPIRIT_BEAST = 46,
+ CREATURE_FAMILY_WATER_ELEMENTAL = 49,
+ CREATURE_FAMILY_FOX = 50,
+ CREATURE_FAMILY_MONKEY = 51,
+ CREATURE_FAMILY_DOG = 52,
+ CREATURE_FAMILY_BEETLE = 53,
+ CREATURE_FAMILY_SHALE_SPIDER = 55,
+ CREATURE_FAMILY_ZOMBIE = 56,
+ CREATURE_FAMILY_BEETLE_OLD = 57,
+ CREATURE_FAMILY_SILITHID_2 = 59,
+ CREATURE_FAMILY_WASP_2 = 66,
+ CREATURE_FAMILY_HYDRA = 68,
};
enum CreatureTypeFlags
@@ -2610,6 +3028,18 @@ enum CreatureTypeFlags
CREATURE_TYPEFLAGS_UNK31 = 0x80000000
};
+enum CreatureTypeFlags2
+{
+ CREATURE_TYPEFLAGS_2_UNK1 = 0x00000001,
+ CREATURE_TYPEFLAGS_2_UNK2 = 0x00000002,
+ CREATURE_TYPEFLAGS_2_UNK3 = 0x00000004,
+ CREATURE_TYPEFLAGS_2_UNK4 = 0x00000008,
+ CREATURE_TYPEFLAGS_2_UNK5 = 0x00000010,
+ CREATURE_TYPEFLAGS_2_UNK6 = 0x00000020,
+ CREATURE_TYPEFLAGS_2_UNK7 = 0x00000040,
+ CREATURE_TYPEFLAGS_2_UNK8 = 0x00000080
+};
+
enum CreatureEliteType
{
CREATURE_ELITE_NORMAL = 0,
@@ -2650,7 +3080,14 @@ enum HolidayIds
HOLIDAY_DAY_OF_DEAD = 409,
HOLIDAY_CALL_TO_ARMS_IC = 420,
HOLIDAY_LOVE_IS_IN_THE_AIR = 423,
- HOLIDAY_KALU_AK_FISHING_DERBY = 424
+ HOLIDAY_KALU_AK_FISHING_DERBY = 424,
+ HOLIDAY_CALL_TO_ARMS_BFG = 435,
+ HOLIDAY_CALL_TO_ARMS_TP = 436,
+ HOLIDAY_RATED_BG_15_VS_15 = 442,
+ HOLIDAY_RATED_BG_25_VS_25 = 443,
+ HOLIDAY_ANNIVERSARY_7_YEARS = 467,
+ HOLIDAY_DARKMOON_FAIRE_TEROKKAR = 479,
+ HOLIDAY_ANNIVERSARY_8_YEARS = 484
};
// values based at QuestInfo.dbc
@@ -2712,7 +3149,12 @@ enum QuestSort
QUEST_SORT_JEWELCRAFTING = 373,
QUEST_SORT_NOBLEGARDEN = 374,
QUEST_SORT_PILGRIMS_BOUNTY = 375,
- QUEST_SORT_LOVE_IS_IN_THE_AIR = 376
+ QUEST_SORT_LOVE_IS_IN_THE_AIR = 376,
+ QUEST_SORT_ARCHAEOLOGY = 377,
+ QUEST_SORT_CHILDRENS_WEEK = 378,
+ QUEST_SORT_FIRELANDS_INVASION = 379,
+ QUEST_SORT_ZANDALARI = 380,
+ QUEST_SORT_ELEMENTAL_BONDS = 381
};
inline uint8 ClassByQuestSort(int32 QuestSort)
@@ -2858,7 +3300,7 @@ enum SkillType
SKILL_RACIAL_HUMAN = 754,
SKILL_JEWELCRAFTING = 755,
SKILL_RACIAL_BLOODELF = 756,
- SKILL_PET_EVENT_RC = 758,
+ SKILL_PET_EVENT_RC = 758, // SkillCategory = -1
SKILL_LANG_DRAENEI = 759,
SKILL_RACIAL_DRAENEI = 760,
SKILL_PET_FELGUARD = 761,
@@ -2886,10 +3328,34 @@ enum SkillType
SKILL_PET_WASP = 785,
SKILL_PET_EXOTIC_RHINO = 786,
SKILL_PET_EXOTIC_CORE_HOUND = 787,
- SKILL_PET_EXOTIC_SPIRIT_BEAST = 788
+ SKILL_PET_EXOTIC_SPIRIT_BEAST = 788,
+ SKILL_RACIAL_WORGEN = 789,
+ SKILL_RACIAL_GOBLIN = 790,
+ SKILL_LANG_WORGEN = 791,
+ SKILL_LANG_GOBLIN = 792,
+ SKILL_ARCHAEOLOGY = 794,
+ SKILL_GENERAL_HUNTER = 795,
+ SKILL_GENERAL_DEATH_KNIGHT = 796,
+ SKILL_GENERAL_ROGUE = 797,
+ SKILL_GENERAL_DRUID = 798,
+ SKILL_GENERAL_MAGE = 799,
+ SKILL_GENERAL_PALADIN = 800,
+ SKILL_GENERAL_SHAMAN = 801,
+ SKILL_GENERAL_WARLOCK = 802,
+ SKILL_GENERAL_WARRIOR = 803,
+ SKILL_GENERAL_PRIEST = 804,
+ SKILL_PET_WATER_ELEMENTAL = 805,
+ SKILL_PET_FOX = 808,
+ SKILL_ALL_GLYPHS = 810,
+ SKILL_PET_DOG = 811,
+ SKILL_PET_MONKEY = 815,
+ SKILL_PET_SHALE_SPIDER = 817,
+ SKILL_PET_BEETLE = 818,
+ SKILL_ALL_GUILD_PERKS = 821,
+ SKILL_PET_HYDRA = 824
};
-#define MAX_SKILL_TYPE 789
+#define MAX_SKILL_TYPE 825
inline SkillType SkillByLockType(LockType locktype)
{
@@ -2920,12 +3386,14 @@ inline uint32 SkillByQuestSort(int32 QuestSort)
case QUEST_SORT_FIRST_AID: return SKILL_FIRST_AID;
case QUEST_SORT_JEWELCRAFTING: return SKILL_JEWELCRAFTING;
case QUEST_SORT_INSCRIPTION: return SKILL_INSCRIPTION;
+ case QUEST_SORT_ARCHAEOLOGY: return SKILL_ARCHAEOLOGY;
}
return 0;
}
enum SkillCategory
{
+ SKILL_CATEGORY_UNK1 = 0,
SKILL_CATEGORY_ATTRIBUTES = 5,
SKILL_CATEGORY_WEAPON = 6,
SKILL_CATEGORY_CLASS = 7,
@@ -2969,7 +3437,9 @@ enum TotemCategory
TC_BLADED_PICKAXE = 168,
TC_FLINT_AND_TINDER = 169,
TC_RUNED_COBALT_ROD = 189,
- TC_RUNED_TITANIUM_ROD = 190
+ TC_RUNED_TITANIUM_ROD = 190,
+ TC_RUNED_ELEMENTIUM_ROD = 209,
+ TC_HIGH_POWERED_BOLT_GUN = 210,
};
enum UnitDynFlags
@@ -3004,62 +3474,75 @@ enum WeatherType
enum ChatMsg
{
- CHAT_MSG_ADDON = 0xFFFFFFFF, // -1
- CHAT_MSG_SYSTEM = 0x00,
- CHAT_MSG_SAY = 0x01,
- CHAT_MSG_PARTY = 0x02,
- CHAT_MSG_RAID = 0x03,
- CHAT_MSG_GUILD = 0x04,
- CHAT_MSG_OFFICER = 0x05,
- CHAT_MSG_YELL = 0x06,
- CHAT_MSG_WHISPER = 0x07,
- CHAT_MSG_WHISPER_FOREIGN = 0x08,
- CHAT_MSG_WHISPER_INFORM = 0x09,
- CHAT_MSG_EMOTE = 0x0A,
- CHAT_MSG_TEXT_EMOTE = 0x0B,
- CHAT_MSG_MONSTER_SAY = 0x0C,
- CHAT_MSG_MONSTER_PARTY = 0x0D,
- CHAT_MSG_MONSTER_YELL = 0x0E,
- CHAT_MSG_MONSTER_WHISPER = 0x0F,
- CHAT_MSG_MONSTER_EMOTE = 0x10,
- CHAT_MSG_CHANNEL = 0x11,
- CHAT_MSG_CHANNEL_JOIN = 0x12,
- CHAT_MSG_CHANNEL_LEAVE = 0x13,
- CHAT_MSG_CHANNEL_LIST = 0x14,
- CHAT_MSG_CHANNEL_NOTICE = 0x15,
- CHAT_MSG_CHANNEL_NOTICE_USER = 0x16,
- CHAT_MSG_AFK = 0x17,
- CHAT_MSG_DND = 0x18,
- CHAT_MSG_IGNORED = 0x19,
- CHAT_MSG_SKILL = 0x1A,
- CHAT_MSG_LOOT = 0x1B,
- CHAT_MSG_MONEY = 0x1C,
- CHAT_MSG_OPENING = 0x1D,
- CHAT_MSG_TRADESKILLS = 0x1E,
- CHAT_MSG_PET_INFO = 0x1F,
- CHAT_MSG_COMBAT_MISC_INFO = 0x20,
- CHAT_MSG_COMBAT_XP_GAIN = 0x21,
- CHAT_MSG_COMBAT_HONOR_GAIN = 0x22,
- CHAT_MSG_COMBAT_FACTION_CHANGE = 0x23,
- CHAT_MSG_BG_SYSTEM_NEUTRAL = 0x24,
- CHAT_MSG_BG_SYSTEM_ALLIANCE = 0x25,
- CHAT_MSG_BG_SYSTEM_HORDE = 0x26,
- CHAT_MSG_RAID_LEADER = 0x27,
- CHAT_MSG_RAID_WARNING = 0x28,
- CHAT_MSG_RAID_BOSS_EMOTE = 0x29,
- CHAT_MSG_RAID_BOSS_WHISPER = 0x2A,
- CHAT_MSG_FILTERED = 0x2B,
- CHAT_MSG_BATTLEGROUND = 0x2C,
- CHAT_MSG_BATTLEGROUND_LEADER = 0x2D,
- CHAT_MSG_RESTRICTED = 0x2E,
- CHAT_MSG_BATTLENET = 0x2F,
- CHAT_MSG_ACHIEVEMENT = 0x30,
- CHAT_MSG_GUILD_ACHIEVEMENT = 0x31,
- CHAT_MSG_ARENA_POINTS = 0x32,
- CHAT_MSG_PARTY_LEADER = 0x33
-};
-
-#define MAX_CHAT_MSG_TYPE 0x34
+ CHAT_MSG_ADDON = 0xFFFFFFFF, // -1
+ CHAT_MSG_SYSTEM = 0x00,
+ CHAT_MSG_SAY = 0x01,
+ CHAT_MSG_PARTY = 0x02,
+ CHAT_MSG_RAID = 0x03,
+ CHAT_MSG_GUILD = 0x04,
+ CHAT_MSG_OFFICER = 0x05,
+ CHAT_MSG_YELL = 0x06,
+ CHAT_MSG_WHISPER = 0x07,
+ CHAT_MSG_WHISPER_FOREIGN = 0x08,
+ CHAT_MSG_WHISPER_INFORM = 0x09,
+ CHAT_MSG_EMOTE = 0x0A,
+ CHAT_MSG_TEXT_EMOTE = 0x0B,
+ CHAT_MSG_MONSTER_SAY = 0x0C,
+ CHAT_MSG_MONSTER_PARTY = 0x0D,
+ CHAT_MSG_MONSTER_YELL = 0x0E,
+ CHAT_MSG_MONSTER_WHISPER = 0x0F,
+ CHAT_MSG_MONSTER_EMOTE = 0x10,
+ CHAT_MSG_CHANNEL = 0x11,
+ CHAT_MSG_CHANNEL_JOIN = 0x12,
+ CHAT_MSG_CHANNEL_LEAVE = 0x13,
+ CHAT_MSG_CHANNEL_LIST = 0x14,
+ CHAT_MSG_CHANNEL_NOTICE = 0x15,
+ CHAT_MSG_CHANNEL_NOTICE_USER = 0x16,
+ CHAT_MSG_AFK = 0x17,
+ CHAT_MSG_DND = 0x18,
+ CHAT_MSG_IGNORED = 0x19,
+ CHAT_MSG_SKILL = 0x1A,
+ CHAT_MSG_LOOT = 0x1B,
+ CHAT_MSG_MONEY = 0x1C,
+ CHAT_MSG_OPENING = 0x1D,
+ CHAT_MSG_TRADESKILLS = 0x1E,
+ CHAT_MSG_PET_INFO = 0x1F,
+ CHAT_MSG_COMBAT_MISC_INFO = 0x20,
+ CHAT_MSG_COMBAT_XP_GAIN = 0x21,
+ CHAT_MSG_COMBAT_HONOR_GAIN = 0x22,
+ CHAT_MSG_COMBAT_FACTION_CHANGE = 0x23,
+ CHAT_MSG_BG_SYSTEM_NEUTRAL = 0x24,
+ CHAT_MSG_BG_SYSTEM_ALLIANCE = 0x25,
+ CHAT_MSG_BG_SYSTEM_HORDE = 0x26,
+ CHAT_MSG_RAID_LEADER = 0x27,
+ CHAT_MSG_RAID_WARNING = 0x28,
+ CHAT_MSG_RAID_BOSS_EMOTE = 0x29,
+ CHAT_MSG_RAID_BOSS_WHISPER = 0x2A,
+ CHAT_MSG_FILTERED = 0x2B,
+ CHAT_MSG_BATTLEGROUND = 0x2C,
+ CHAT_MSG_BATTLEGROUND_LEADER = 0x2D,
+ CHAT_MSG_RESTRICTED = 0x2E,
+ CHAT_MSG_BATTLENET = 0x2F,
+ CHAT_MSG_ACHIEVEMENT = 0x30,
+ CHAT_MSG_GUILD_ACHIEVEMENT = 0x31,
+ CHAT_MSG_ARENA_POINTS = 0x32,
+ CHAT_MSG_PARTY_LEADER = 0x33,
+ CHAT_MSG_TARGETICONS = 0x34,
+ CHAT_MSG_BN_WHISPER = 0x35,
+ CHAT_MSG_BN_WHISPER_INFORM = 0x36,
+ CHAT_MSG_BN_CONVERSATION = 0x37,
+ CHAT_MSG_BN_CONVERSATION_NOTICE = 0x38,
+ CHAT_MSG_BN_CONVERSATION_LIST = 0x39,
+ CHAT_MSG_BN_INLINE_TOAST_ALERT = 0x3A,
+ CHAT_MSG_BN_INLINE_TOAST_BROADCAST = 0x3B,
+ CHAT_MSG_BN_INLINE_TOAST_BROADCAST_INFORM = 0x3C,
+ CHAT_MSG_BN_INLINE_TOAST_CONVERSATION = 0x3D,
+ CHAT_MSG_BN_WHISPER_PLAYER_OFFLINE = 0x3E,
+ CHAT_MSG_COMBAT_GUILD_XP_GAIN = 0x3F,
+ CHAT_MSG_CURRENCY = 0x40
+};
+
+#define MAX_CHAT_MSG_TYPE 0x41
enum ChatLinkColors
{
@@ -3092,6 +3575,7 @@ enum GuildLogs
{
GUILD_BANKLOG_MAX_RECORDS = 25,
GUILD_EVENTLOG_MAX_RECORDS = 100,
+ GUILD_NEWSLOG_MAX_RECORDS = 250
};
enum AiReaction
@@ -3162,7 +3646,8 @@ enum SummonType
SUMMON_TYPE_VEHICLE = 9,
SUMMON_TYPE_VEHICLE2 = 10, // Oculus and Argent Tournament vehicles (3.3.5a)
SUMMON_TYPE_LIGHTWELL = 11,
- SUMMON_TYPE_JEEVES = 12
+ SUMMON_TYPE_JEEVES = 12,
+ SUMMON_TYPE_UNK13 = 13
};
enum EventId
@@ -3261,36 +3746,38 @@ enum ResponseCodes
CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 73,
CHAR_DELETE_FAILED_GUILD_LEADER = 74,
CHAR_DELETE_FAILED_ARENA_CAPTAIN = 75,
-
- CHAR_LOGIN_IN_PROGRESS = 76,
- CHAR_LOGIN_SUCCESS = 77,
- CHAR_LOGIN_NO_WORLD = 78,
- CHAR_LOGIN_DUPLICATE_CHARACTER = 79,
- CHAR_LOGIN_NO_INSTANCES = 80,
- CHAR_LOGIN_FAILED = 81,
- CHAR_LOGIN_DISABLED = 82,
- CHAR_LOGIN_NO_CHARACTER = 83,
- CHAR_LOGIN_LOCKED_FOR_TRANSFER = 84,
- CHAR_LOGIN_LOCKED_BY_BILLING = 85,
- CHAR_LOGIN_LOCKED_BY_MOBILE_AH = 86,
-
- CHAR_NAME_SUCCESS = 87,
- CHAR_NAME_FAILURE = 88,
- CHAR_NAME_NO_NAME = 89,
- CHAR_NAME_TOO_SHORT = 90,
- CHAR_NAME_TOO_LONG = 91,
- CHAR_NAME_INVALID_CHARACTER = 92,
- CHAR_NAME_MIXED_LANGUAGES = 93,
- CHAR_NAME_PROFANE = 94,
- CHAR_NAME_RESERVED = 95,
- CHAR_NAME_INVALID_APOSTROPHE = 96,
- CHAR_NAME_MULTIPLE_APOSTROPHES = 97,
- CHAR_NAME_THREE_CONSECUTIVE = 98,
- CHAR_NAME_INVALID_SPACE = 99,
- CHAR_NAME_CONSECUTIVE_SPACES = 100,
- CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 101,
- CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 102,
- CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 103
+ CHAR_DELETE_FAILED_HAS_HEIRLOOM_OR_MAIL = 76,
+
+ CHAR_LOGIN_IN_PROGRESS = 77,
+ CHAR_LOGIN_SUCCESS = 78,
+ CHAR_LOGIN_NO_WORLD = 79,
+ CHAR_LOGIN_DUPLICATE_CHARACTER = 80,
+ CHAR_LOGIN_NO_INSTANCES = 81,
+ CHAR_LOGIN_FAILED = 82,
+ CHAR_LOGIN_DISABLED = 83,
+ CHAR_LOGIN_NO_CHARACTER = 84,
+ CHAR_LOGIN_LOCKED_FOR_TRANSFER = 85,
+ CHAR_LOGIN_LOCKED_BY_BILLING = 86,
+ CHAR_LOGIN_LOCKED_BY_MOBILE_AH = 87,
+ CHAR_LOGIN_TEMPORARY_GM_LOCK = 88,
+
+ CHAR_NAME_SUCCESS = 89,
+ CHAR_NAME_FAILURE = 90,
+ CHAR_NAME_NO_NAME = 91,
+ CHAR_NAME_TOO_SHORT = 92,
+ CHAR_NAME_TOO_LONG = 93,
+ CHAR_NAME_INVALID_CHARACTER = 94,
+ CHAR_NAME_MIXED_LANGUAGES = 95,
+ CHAR_NAME_PROFANE = 96,
+ CHAR_NAME_RESERVED = 97,
+ CHAR_NAME_INVALID_APOSTROPHE = 98,
+ CHAR_NAME_MULTIPLE_APOSTROPHES = 99,
+ CHAR_NAME_THREE_CONSECUTIVE = 100,
+ CHAR_NAME_INVALID_SPACE = 101,
+ CHAR_NAME_CONSECUTIVE_SPACES = 102,
+ CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 103,
+ CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 104,
+ CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 105,
};
/// Ban function modes
@@ -3321,23 +3808,31 @@ enum BattlegroundTeamId
// indexes of BattlemasterList.dbc
enum BattlegroundTypeId
{
- BATTLEGROUND_TYPE_NONE = 0, // None
- BATTLEGROUND_AV = 1, // Alterac Valley
- BATTLEGROUND_WS = 2, // Warsong Gulch
- BATTLEGROUND_AB = 3, // Arathi Basin
- BATTLEGROUND_NA = 4, // Nagrand Arena
- BATTLEGROUND_BE = 5, // Blade's Edge Arena
- BATTLEGROUND_AA = 6, // All Arenas
- BATTLEGROUND_EY = 7, // Eye of the Storm
- BATTLEGROUND_RL = 8, // Ruins of Lordaernon
- BATTLEGROUND_SA = 9, // Strand of the Ancients
- BATTLEGROUND_DS = 10, // Dalaran Sewers
- BATTLEGROUND_RV = 11, // Ring of Valor
- BATTLEGROUND_IC = 30, // Isle of Conquest
- BATTLEGROUND_RB = 32 // Random Battleground
+ BATTLEGROUND_TYPE_NONE = 0, // None
+ BATTLEGROUND_AV = 1, // Alterac Valley
+ BATTLEGROUND_WS = 2, // Warsong Gulch
+ BATTLEGROUND_AB = 3, // Arathi Basin
+ BATTLEGROUND_NA = 4, // Nagrand Arena
+ BATTLEGROUND_BE = 5, // Blade's Edge Arena
+ BATTLEGROUND_AA = 6, // All Arenas
+ BATTLEGROUND_EY = 7, // Eye of the Storm
+ BATTLEGROUND_RL = 8, // Ruins of Lordaernon
+ BATTLEGROUND_SA = 9, // Strand of the Ancients
+ BATTLEGROUND_DS = 10, // Dalaran Sewers
+ BATTLEGROUND_RV = 11, // Ring of Valor
+ BATTLEGROUND_IC = 30, // Isle of Conquest
+ BATTLEGROUND_RB = 32, // Random Battleground
+ BATTLEGROUND_RATED_10_VS_10 = 100, // Rated BG 10 vs 10
+ BATTLEGROUND_RATED_15_VS_15 = 101, // Rated BG 15 vs 15
+ BATTLEGROUND_RATED_25_VS_25 = 102, // Rated BG 25 vs 25
+ BATTLEGROUND_TP = 108, // Twin Peaks
+ BATTLEGROUND_BFG = 120, // Battle For Gilneas
+ // 441 = "Icecrown Citadel"
+ // 443 = "The Ruby Sanctum"
+ // 656 = "Rated Eye of the Storm"
};
-#define MAX_BATTLEGROUND_TYPE_ID 33
+#define MAX_BATTLEGROUND_TYPE_ID 121
enum MailResponseType
{
@@ -3386,35 +3881,44 @@ enum SpellFamilyNames
// 14 - unused
SPELLFAMILY_DEATHKNIGHT = 15,
// 16 - unused
- SPELLFAMILY_PET = 17
+ SPELLFAMILY_PET = 17,
+ SPELLFAMILY_UNK3 = 50,
};
enum TradeStatus
{
- TRADE_STATUS_BUSY = 0,
- TRADE_STATUS_BEGIN_TRADE = 1,
- TRADE_STATUS_OPEN_WINDOW = 2,
- TRADE_STATUS_TRADE_CANCELED = 3,
- TRADE_STATUS_TRADE_ACCEPT = 4,
- TRADE_STATUS_BUSY_2 = 5,
- TRADE_STATUS_NO_TARGET = 6,
- TRADE_STATUS_BACK_TO_TRADE = 7,
- TRADE_STATUS_TRADE_COMPLETE = 8,
- // 9?
- TRADE_STATUS_TARGET_TO_FAR = 10,
- TRADE_STATUS_WRONG_FACTION = 11,
- TRADE_STATUS_CLOSE_WINDOW = 12,
- // 13?
- TRADE_STATUS_IGNORE_YOU = 14,
- TRADE_STATUS_YOU_STUNNED = 15,
- TRADE_STATUS_TARGET_STUNNED = 16,
- TRADE_STATUS_YOU_DEAD = 17,
- TRADE_STATUS_TARGET_DEAD = 18,
- TRADE_STATUS_YOU_LOGOUT = 19,
- TRADE_STATUS_TARGET_LOGOUT = 20,
- TRADE_STATUS_TRIAL_ACCOUNT = 21, // Trial accounts can not perform that action
- TRADE_STATUS_ONLY_CONJURED = 22, // You can only trade conjured items... (cross realm BG related).
- TRADE_STATUS_NOT_ELIGIBLE = 23 // Related to trading soulbound loot items
+ TRADE_STATUS_OPEN_WINDOW = 0,
+ // 1 - Related to EVENT_PLAYER_MONEY
+ TRADE_STATUS_NOT_ELIGIBLE = 2, // Related to trading soulbound loot items
+ TRADE_STATUS_YOU_LOGOUT = 3,
+ TRADE_STATUS_IGNORE_YOU = 4,
+ TRADE_STATUS_TARGET_DEAD = 5,
+ TRADE_STATUS_TRADE_ACCEPT = 6,
+ TRADE_STATUS_TARGET_LOGOUT = 7,
+ // 8 - nonexistent
+ TRADE_STATUS_TRADE_COMPLETE = 9,
+ TRADE_STATUS_TRIAL_ACCOUNT = 10, // Trial accounts can not perform that action
+ // 11 - nonexistent
+ TRADE_STATUS_BEGIN_TRADE = 12,
+ TRADE_STATUS_YOU_DEAD = 13,
+ // 14 - nonexistent
+ // 15 - nonexistent
+ TRADE_STATUS_TARGET_TO_FAR = 16,
+ TRADE_STATUS_NO_TARGET = 17,
+ TRADE_STATUS_BUSY_2 = 18,
+ TRADE_STATUS_CURRENCY_NOT_TRADABLE = 19, // new 4.x
+ TRADE_STATUS_WRONG_FACTION = 20,
+ TRADE_STATUS_BUSY = 21,
+ // 22 - equivalent to 335 unk status 9
+ TRADE_STATUS_TRADE_CANCELED = 23,
+ TRADE_STATUS_CURRENCY = 24, // new 4.x
+ TRADE_STATUS_BACK_TO_TRADE = 25,
+ TRADE_STATUS_ONLY_CONJURED = 26, // You can only trade conjured items... (cross realm BG related).
+ TRADE_STATUS_YOU_STUNNED = 27,
+ // 28 - nonexistent
+ TRADE_STATUS_TARGET_STUNNED = 29,
+ // 30 - nonexistent
+ TRADE_STATUS_CLOSE_WINDOW = 31,
};
enum XPColorChar
@@ -3451,6 +3955,12 @@ enum ActivateTaxiReply
ERR_TAXINOTSTANDING = 12
};
+enum ProfessionUI
+{
+ MAX_PRIMARY_PROFESSIONS = 2,
+ MAX_SECONDARY_SKILLS = 5
+};
+
enum DuelCompleteType
{
DUEL_INTERRUPTED = 0,
@@ -3468,32 +3978,44 @@ enum BattlegroundQueueTypeId
BATTLEGROUND_QUEUE_EY = 4,
BATTLEGROUND_QUEUE_SA = 5,
BATTLEGROUND_QUEUE_IC = 6,
- BATTLEGROUND_QUEUE_RB = 7,
- BATTLEGROUND_QUEUE_2v2 = 8,
- BATTLEGROUND_QUEUE_3v3 = 9,
- BATTLEGROUND_QUEUE_5v5 = 10,
+ BATTLEGROUND_QUEUE_TP = 7,
+ BATTLEGROUND_QUEUE_BFG = 8,
+ BATTLEGROUND_QUEUE_RB = 9,
+ BATTLEGROUND_QUEUE_2v2 = 10,
+ BATTLEGROUND_QUEUE_3v3 = 11,
+ BATTLEGROUND_QUEUE_5v5 = 12,
MAX_BATTLEGROUND_QUEUE_TYPES
};
enum GroupJoinBattlegroundResult
{
- // positive values are indexes in BattlemasterList.dbc
- ERR_GROUP_JOIN_BATTLEGROUND_FAIL = 0, // Your group has joined a battleground queue, but you are not eligible (showed for non existing BattlemasterList.dbc indexes)
- ERR_BATTLEGROUND_NONE = -1, // not show anything
- ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS = -2, // You cannot join the battleground yet because you or one of your party members is flagged as a Deserter.
- ERR_ARENA_TEAM_PARTY_SIZE = -3, // Incorrect party size for this arena.
- ERR_BATTLEGROUND_TOO_MANY_QUEUES = -4, // You can only be queued for 2 battles at once
- ERR_BATTLEGROUND_CANNOT_QUEUE_FOR_RATED = -5, // You cannot queue for a rated match while queued for other battles
- ERR_BATTLEDGROUND_QUEUED_FOR_RATED = -6, // You cannot queue for another battle while queued for a rated arena match
- ERR_BATTLEGROUND_TEAM_LEFT_QUEUE = -7, // Your team has left the arena queue
- ERR_BATTLEGROUND_NOT_IN_BATTLEGROUND = -8, // You can't do that in a battleground.
- ERR_BATTLEGROUND_JOIN_XP_GAIN = -9, // wtf, doesn't exist in client...
- ERR_BATTLEGROUND_JOIN_RANGE_INDEX = -10, // Cannot join the queue unless all members of your party are in the same battleground level range.
- ERR_BATTLEGROUND_JOIN_TIMED_OUT = -11, // %s was unavailable to join the queue. (uint64 guid exist in client cache)
- ERR_BATTLEGROUND_JOIN_FAILED = -12, // Join as a group failed (uint64 guid doesn't exist in client cache)
- ERR_LFG_CANT_USE_BATTLEGROUND = -13, // You cannot queue for a battleground or arena while using the dungeon system.
- ERR_IN_RANDOM_BG = -14, // Can't do that while in a Random Battleground queue.
- ERR_IN_NON_RANDOM_BG = -15 // Can't queue for Random Battleground while in another Battleground queue.
+ ERR_BATTLEGROUND_NONE = 0,
+ ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS = 2, // You cannot join the battleground yet because you or one of your party members is flagged as a Deserter.
+ ERR_ARENA_TEAM_PARTY_SIZE = 3, // Incorrect party size for this arena.
+ ERR_BATTLEGROUND_TOO_MANY_QUEUES = 4, // You can only be queued for 2 battles at once
+ ERR_BATTLEGROUND_CANNOT_QUEUE_FOR_RATED = 5, // You cannot queue for a rated match while queued for other battles
+ ERR_BATTLEDGROUND_QUEUED_FOR_RATED = 6, // You cannot queue for another battle while queued for a rated arena match
+ ERR_BATTLEGROUND_TEAM_LEFT_QUEUE = 7, // Your team has left the arena queue
+ ERR_BATTLEGROUND_NOT_IN_BATTLEGROUND = 8, // You can't do that in a battleground.
+ ERR_BATTLEGROUND_JOIN_XP_GAIN = 9, // wtf, doesn't exist in client...
+ ERR_BATTLEGROUND_JOIN_RANGE_INDEX = 10, // Cannot join the queue unless all members of your party are in the same battleground level range.
+ ERR_BATTLEGROUND_JOIN_TIMED_OUT = 11, // %s was unavailable to join the queue. (uint64 guid exist in client cache)
+ //ERR_BATTLEGROUND_JOIN_TIMED_OUT = 12, // same as 11
+ //ERR_BATTLEGROUND_TEAM_LEFT_QUEUE = 13, // same as 7
+ ERR_LFG_CANT_USE_BATTLEGROUND = 14, // You cannot queue for a battleground or arena while using the dungeon system.
+ ERR_IN_RANDOM_BG = 15, // Can't do that while in a Random Battleground queue.
+ ERR_IN_NON_RANDOM_BG = 16, // Can't queue for Random Battleground while in another Battleground queue.
+ ERR_BG_DEVELOPER_ONLY = 17,
+ ERR_BATTLEGROUND_INVITATION_DECLINED = 18,
+ ERR_MEETING_STONE_NOT_FOUND = 19,
+ ERR_WARGAME_REQUEST_FAILURE = 20,
+ ERR_BATTLEFIELD_TEAM_PARTY_SIZE = 22,
+ ERR_NOT_ON_TOURNAMENT_REALM = 23,
+ ERR_BATTLEGROUND_PLAYERS_FROM_DIFFERENT_REALMS = 24,
+ ERR_REMOVE_FROM_PVP_QUEUE_GRANT_LEVEL = 33,
+ ERR_REMOVE_FROM_PVP_QUEUE_FACTION_CHANGE = 34,
+ ERR_BATTLEGROUND_JOIN_FAILED = 35,
+ ERR_BATTLEGROUND_DUPE_QUEUE = 43
};
enum PetNameInvalidReason
@@ -3527,6 +4049,28 @@ enum DungeonStatusFlag
RAID_STATUSFLAG_25MAN_HEROIC = 0x08
};
+#define VOID_STORAGE_UNLOCK 100*GOLD
+#define VOID_STORAGE_STORE_ITEM 25*GOLD
+#define VOID_STORAGE_MAX_DEPOSIT 9
+#define VOID_STORAGE_MAX_WITHDRAW 9
+#define VOID_STORAGE_MAX_SLOT 80
+
+enum VoidTransferError
+{
+ VOID_TRANSFER_ERROR_NO_ERROR = 0,
+ VOID_TRANSFER_ERROR_INTERNAL_ERROR_1 = 1,
+ VOID_TRANSFER_ERROR_INTERNAL_ERROR_2 = 2,
+ VOID_TRANSFER_ERROR_FULL = 3,
+ VOID_TRANSFER_ERROR_INTERNAL_ERROR_3 = 4,
+ VOID_TRANSFER_ERROR_INTERNAL_ERROR_4 = 5,
+ VOID_TRANSFER_ERROR_NOT_ENOUGH_MONEY = 6,
+ VOID_TRANSFER_ERROR_INVENTORY_FULL = 7,
+ VOID_TRANSFER_ERROR_INTERNAL_ERROR_5 = 8,
+ VOID_TRANSFER_ERROR_TRANSFER_UNKNOWN = 9,
+};
+
+#define CURRENCY_PRECISION 100
+
enum PartyResult
{
ERR_PARTY_RESULT_OK = 0,
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 55f745d993b..72bb0e1d56e 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -403,10 +403,7 @@ void MotionMaster::MoveFall(uint32 id /*=0*/)
return;
if (_owner->GetTypeId() == TYPEID_PLAYER)
- {
- _owner->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
- _owner->m_movementInfo.SetFallTime(0);
- }
+ _owner->SetFall(true);
Movement::MoveSplineInit init(_owner);
init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz, false);
diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
index 0a8a9f267dd..2b2b9bec288 100755..100644
--- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
@@ -19,6 +19,7 @@
#include "IdleMovementGenerator.h"
#include "CreatureAI.h"
#include "Creature.h"
+#include <G3D/g3dmath.h>
IdleMovementGenerator si_idleMovement;
@@ -44,25 +45,17 @@ void RotateMovementGenerator::Initialize(Unit* owner)
owner->SetInFront(owner->GetVictim());
owner->AddUnitState(UNIT_STATE_ROTATING);
-
owner->AttackStop();
}
bool RotateMovementGenerator::Update(Unit* owner, uint32 diff)
{
float angle = owner->GetOrientation();
- if (m_direction == ROTATE_DIRECTION_LEFT)
- {
- angle += (float)diff * static_cast<float>(M_PI * 2) / m_maxDuration;
- while (angle >= static_cast<float>(M_PI * 2)) angle -= static_cast<float>(M_PI * 2);
- }
- else
- {
- angle -= (float)diff * static_cast<float>(M_PI * 2) / m_maxDuration;
- while (angle < 0) angle += static_cast<float>(M_PI * 2);
- }
+ angle += (float(diff) * static_cast<float>(M_PI * 2) / m_maxDuration) * (m_direction == ROTATE_DIRECTION_LEFT ? 1.0f : -1.0f);
+ angle = G3D::wrap(angle, 0.0f, float(G3D::twoPi()));
- owner->SetFacingTo(angle);
+ owner->SetOrientation(angle); // UpdateSplinePosition does not set orientation with UNIT_STATE_ROTATING
+ owner->SetFacingTo(angle); // Send spline movement to clients
if (m_duration > diff)
m_duration -= diff;
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index c59762066ae..c59762066ae 100644..100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index 4061998d47a..8cde9876ca1 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -102,7 +102,7 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
if (Stopped())
return true;
- bool transportPath = creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && creature->GetTransGUID();
+ bool transportPath = creature->GetTransport() != NULL;
if (m_isArrivalDone)
{
@@ -210,7 +210,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
else
{
// Set home position at place on waypoint movement.
- if (!creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) || !creature->GetTransGUID())
+ if (!creature->GetTransGUID())
creature->SetHomePosition(creature->GetPosition());
if (creature->IsStopped())
@@ -302,6 +302,9 @@ void FlightPathMovementGenerator::DoReset(Player* player)
}
init.SetFirstPointId(GetCurrentNode());
init.SetFly();
+ init.SetSmooth();
+ init.SetUncompressed();
+ init.SetWalk(true);
init.SetVelocity(PLAYER_FLIGHT_SPEED);
init.Launch();
}
diff --git a/src/server/game/Movement/MovementStructures.cpp b/src/server/game/Movement/MovementStructures.cpp
new file mode 100644
index 00000000000..242b2aeaca7
--- /dev/null
+++ b/src/server/game/Movement/MovementStructures.cpp
@@ -0,0 +1,5451 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "MovementStructures.h"
+#include "Player.h"
+
+MovementStatusElements const PlayerMove[] =
+{
+ MSEHasFallData,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags2,
+ MSEHasSpline,
+ MSEHasTimestamp,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEMovementFlags2,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags,
+ MSEHasOrientation,
+ MSEHasGuidByte2,
+ MSEHasSplineElevation,
+ MSEZeroBit,
+ MSEHasGuidByte4,
+ MSEHasFallDirection,
+ MSEHasGuidByte5,
+ MSEHasTransportData,
+ MSEMovementFlags,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEHasPitch,
+ MSEGuidByte5,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSESplineElevation,
+ MSEGuidByte7,
+ MSEPositionY,
+ MSEGuidByte3,
+ MSETransportTime3,
+ MSETransportGuidByte6,
+ MSETransportSeat,
+ MSETransportGuidByte5,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportOrientation,
+ MSETransportGuidByte2,
+ MSETransportTime2,
+ MSETransportGuidByte0,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte4,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportTime,
+ MSEGuidByte4,
+ MSEPositionX,
+ MSEGuidByte6,
+ MSEPositionZ,
+ MSETimestamp,
+ MSEGuidByte2,
+ MSEPitch,
+ MSEGuidByte0,
+ MSEOrientation,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementFallLand[] =
+{
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasTransportData,
+ MSEHasGuidByte7,
+ MSEHasGuidByte1,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasOrientation,
+ MSEHasGuidByte6,
+ MSEHasTimestamp,
+ MSEZeroBit,
+ MSEHasPitch,
+ MSEHasGuidByte4,
+ MSEHasSpline,
+ MSEHasGuidByte5,
+ MSEHasMovementFlags,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte7,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportPositionY,
+ MSETransportPositionX,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportGuidByte1,
+ MSETransportSeat,
+ MSETransportTime2,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSETransportGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportGuidByte2,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEPitch,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementHeartBeat[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasFallData,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasGuidByte7,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasOrientation,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEZeroBit,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportOrientation,
+ MSETransportGuidByte4,
+ MSETransportPositionY,
+ MSETransportTime,
+ MSETransportPositionX,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportGuidByte7,
+ MSETransportTime3,
+ MSETransportTime2,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportGuidByte6,
+ MSEOrientation,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEPitch,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementJump[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasTimestamp,
+ MSEHasGuidByte5,
+ MSEHasMovementFlags,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte0,
+ MSEHasTransportData,
+ MSEHasGuidByte3,
+ MSEHasPitch,
+ MSEHasGuidByte7,
+ MSEHasFallData,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasGuidByte1,
+ MSEHasSplineElevation,
+ MSEZeroBit,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSETransportGuidByte1,
+ MSETransportGuidByte7,
+ MSETransportPositionX,
+ MSETransportGuidByte4,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportTime2,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportPositionY,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte5,
+ MSEPitch,
+ MSETimestamp,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetFacing[] =
+{
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasGuidByte6,
+ MSEHasTransportData,
+ MSEHasGuidByte4,
+ MSEHasSpline,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasTimestamp,
+ MSEHasPitch,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags,
+ MSEHasGuidByte3,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSETransportGuidByte0,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportTime2,
+ MSETransportGuidByte4,
+ MSETransportPositionZ,
+ MSETransportOrientation,
+ MSETransportGuidByte2,
+ MSETransportTime3,
+ MSETransportGuidByte3,
+ MSETransportSeat,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSESplineElevation,
+ MSEOrientation,
+ MSETimestamp,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetPitch[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasFallData,
+ MSEHasMovementFlags,
+ MSEHasGuidByte1,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasSplineElevation,
+ MSEHasGuidByte6,
+ MSEHasPitch,
+ MSEHasGuidByte4,
+ MSEHasSpline,
+ MSEHasGuidByte2,
+ MSEZeroBit,
+ MSEHasTimestamp,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime2,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSETransportGuidByte4,
+ MSETransportGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportOrientation,
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportTime,
+ MSETransportGuidByte2,
+ MSETransportPositionZ,
+ MSETransportGuidByte0,
+ MSETransportTime2,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportGuidByte7,
+ MSETransportPositionX,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEPitch,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartBackward[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasTransportData,
+ MSEHasGuidByte3,
+ MSEHasGuidByte0,
+ MSEHasGuidByte2,
+ MSEHasTimestamp,
+ MSEHasGuidByte7,
+ MSEHasPitch,
+ MSEZeroBit,
+ MSEHasMovementFlags,
+ MSEHasOrientation,
+ MSEHasSpline,
+ MSEHasMovementFlags2,
+ MSEHasFallData,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSETransportPositionZ,
+ MSETransportGuidByte2,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportGuidByte5,
+ MSETransportPositionY,
+ MSETransportGuidByte1,
+ MSETransportPositionX,
+ MSETransportTime2,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportSeat,
+ MSETransportGuidByte7,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSEPitch,
+ MSETimestamp,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartForward[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEZeroBit,
+ MSEHasMovementFlags,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasOrientation,
+ MSEHasGuidByte6,
+ MSEHasSpline,
+ MSEHasSplineElevation,
+ MSEHasGuidByte4,
+ MSEHasTransportData,
+ MSEHasTimestamp,
+ MSEHasPitch,
+ MSEHasMovementFlags2,
+ MSEHasFallData,
+ MSEMovementFlags,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime3,
+ MSEHasTransportTime2,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEFallVerticalSpeed,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportPositionZ,
+ MSETransportGuidByte1,
+ MSETransportGuidByte4,
+ MSETransportGuidByte7,
+ MSETransportOrientation,
+ MSETransportGuidByte2,
+ MSETransportPositionX,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSETransportTime2,
+ MSESplineElevation,
+ MSEPitch,
+ MSEOrientation,
+ MSETimestamp,
+
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartStrafeLeft[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasSplineElevation,
+ MSEHasGuidByte5,
+ MSEHasPitch,
+ MSEHasGuidByte6,
+ MSEHasTimestamp,
+ MSEHasGuidByte1,
+ MSEZeroBit,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasOrientation,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte7,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasTransportData,
+ MSEHasFallDirection,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSETransportSeat,
+ MSETransportGuidByte2,
+ MSETransportTime2,
+ MSETransportGuidByte3,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportGuidByte7,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte4,
+ MSETransportPositionX,
+ MSETimestamp,
+ MSEOrientation,
+ MSEPitch,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartStrafeRight[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasPitch,
+ MSEHasGuidByte1,
+ MSEHasOrientation,
+ MSEHasGuidByte4,
+ MSEHasSpline,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasFallData,
+ MSEHasSplineElevation,
+ MSEHasTimestamp,
+ MSEHasMovementFlags,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportGuidByte6,
+ MSETransportPositionY,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSETransportGuidByte2,
+ MSETransportSeat,
+ MSETransportPositionX,
+ MSETransportTime3,
+ MSETransportTime,
+ MSETransportGuidByte4,
+ MSETransportGuidByte7,
+ MSETransportTime2,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSEPitch,
+ MSEOrientation,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartTurnLeft[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasOrientation,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasTransportData,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasFallData,
+ MSEMovementFlags2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte6,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSETransportGuidByte0,
+ MSETransportPositionX,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportPositionZ,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportGuidByte2,
+ MSETransportGuidByte6,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportTime3,
+ MSETransportTime2,
+ MSETransportGuidByte5,
+ MSETransportGuidByte7,
+ MSETimestamp,
+ MSEPitch,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartTurnRight[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasMovementFlags,
+ MSEHasSpline,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasGuidByte7,
+ MSEZeroBit,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte1,
+ MSEHasTimestamp,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasSplineElevation,
+ MSEHasPitch,
+ MSEHasFallData,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime3,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSETransportPositionY,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSETransportGuidByte1,
+ MSETransportGuidByte6,
+ MSETransportGuidByte2,
+ MSETransportSeat,
+ MSETransportOrientation,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportPositionZ,
+ MSETransportPositionX,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportTime2,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEPitch,
+ MSEOrientation,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStop[] =
+{
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags,
+ MSEHasGuidByte5,
+ MSEHasFallData,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasTimestamp,
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEZeroBit,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEHasPitch,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte2,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSETransportGuidByte4,
+ MSETransportGuidByte7,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportPositionY,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportGuidByte5,
+ MSETransportGuidByte6,
+ MSETimestamp,
+ MSEOrientation,
+ MSEPitch,
+ MSESplineElevation,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStopStrafe[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasGuidByte7,
+ MSEHasSplineElevation,
+ MSEHasGuidByte3,
+ MSEHasOrientation,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasMovementFlags,
+ MSEHasSpline,
+ MSEHasGuidByte0,
+ MSEZeroBit,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime3,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSETransportSeat,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte4,
+ MSETransportGuidByte5,
+ MSETransportTime,
+ MSETransportOrientation,
+ MSETransportPositionX,
+ MSETransportGuidByte0,
+ MSETransportPositionY,
+ MSETransportTime2,
+ MSETransportGuidByte7,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStopTurn[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEHasFallData,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasPitch,
+ MSEHasTransportData,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasTimestamp,
+ MSEHasMovementFlags2,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSESplineElevation,
+ MSETransportPositionX,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportOrientation,
+ MSETransportTime2,
+ MSETransportTime3,
+ MSETransportGuidByte7,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSETransportPositionY,
+ MSETransportPositionZ,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSEPitch,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartAscend[] =
+{
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte7,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasSplineElevation,
+ MSEHasFallData,
+ MSEHasSpline,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasOrientation,
+ MSEHasGuidByte4,
+ MSEMovementFlags,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportSeat,
+ MSETransportGuidByte2,
+ MSETransportOrientation,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSETransportTime2,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportGuidByte0,
+ MSETransportGuidByte1,
+ MSETransportPositionX,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSEPitch,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartDescend[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEHasGuidByte0,
+ MSEHasPitch,
+ MSEHasFallData,
+ MSEHasGuidByte4,
+ MSEHasOrientation,
+ MSEHasTimestamp,
+ MSEHasMovementFlags2,
+ MSEHasMovementFlags,
+ MSEHasGuidByte6,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasTransportData,
+ MSEHasSpline,
+ MSEHasSplineElevation,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEPitch,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportTime3,
+ MSETransportGuidByte6,
+ MSETransportTime2,
+ MSETransportGuidByte1,
+ MSETransportTime,
+ MSETransportGuidByte4,
+ MSETransportPositionY,
+ MSETransportPositionX,
+ MSETransportGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSEFallTime,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartSwim[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEZeroBit,
+ MSEHasPitch,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasMovementFlags,
+ MSEHasFallData,
+ MSEHasGuidByte5,
+ MSEHasTransportData,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasSpline,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime3,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEPitch,
+ MSETransportTime2,
+ MSETransportGuidByte2,
+ MSETransportPositionY,
+ MSETransportGuidByte3,
+ MSETransportTime,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportTime3,
+ MSETransportGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportPositionZ,
+ MSETransportGuidByte1,
+ MSETransportGuidByte7,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEOrientation,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStopSwim[] =
+{
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasSpline,
+ MSEHasPitch,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags,
+ MSEHasGuidByte4,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasTransportData,
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEHasTimestamp,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasFallData,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSETransportTime3,
+ MSETransportGuidByte4,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSETransportGuidByte1,
+ MSETransportGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSEFallVerticalSpeed,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSETimestamp,
+ MSEPitch,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStopAscend[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasGuidByte7,
+ MSEHasOrientation,
+ MSEHasPitch,
+ MSEHasSpline,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasMovementFlags,
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasTransportData,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+ MSEHasGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSETransportGuidByte2,
+ MSETransportGuidByte6,
+ MSETransportTime2,
+ MSETransportTime3,
+ MSETransportOrientation,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportSeat,
+ MSETransportGuidByte1,
+ MSETransportTime,
+ MSETransportGuidByte0,
+ MSETransportPositionX,
+ MSETransportPositionZ,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEPitch,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStopPitch[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasFallData,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasPitch,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEHasMovementFlags2,
+ MSEHasSplineElevation,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasTimestamp,
+ MSEHasTransportData,
+ MSEHasMovementFlags,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSETimestamp,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSETransportGuidByte1,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSETransportSeat,
+ MSETransportGuidByte7,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartPitchDown[] =
+{
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasMovementFlags,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasPitch,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasTimestamp,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasFallData,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSETransportTime3,
+ MSETransportGuidByte3,
+ MSETransportTime2,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportPositionY,
+ MSETransportGuidByte6,
+ MSETransportGuidByte4,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportPositionX,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSETransportGuidByte2,
+ MSETransportGuidByte7,
+ MSETransportOrientation,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEPitch,
+ MSEOrientation,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementStartPitchUp[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasGuidByte4,
+ MSEHasMovementFlags,
+ MSEHasMovementFlags2,
+ MSEHasSpline,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEZeroBit,
+ MSEHasSplineElevation,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasTransportData,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEMovementFlags2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportOrientation,
+ MSETransportGuidByte7,
+ MSETransportTime2,
+ MSETransportSeat,
+ MSETransportGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportPositionY,
+ MSETransportGuidByte4,
+ MSEFallTime,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEPitch,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveChngTransport[]=
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte2,
+ MSEHasTransportData,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasGuidByte6,
+ MSEHasTimestamp,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasPitch,
+ MSEZeroBit,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasGuidByte1,
+ MSEHasFallData,
+ MSEHasMovementFlags,
+ MSEHasMovementFlags2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSETransportPositionY,
+ MSETransportSeat,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportPositionX,
+ MSETransportTime3,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportTime2,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSEPitch,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSplineDone[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasGuidByte6,
+ MSEHasOrientation,
+ MSEHasFallData,
+ MSEHasTimestamp,
+ MSEHasGuidByte2,
+ MSEHasSplineElevation,
+ MSEHasGuidByte4,
+ MSEHasTransportData,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags,
+ MSEHasGuidByte0,
+ MSEZeroBit,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasPitch,
+ MSEHasSpline,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte7,
+
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte0,
+
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte3,
+
+ MSEFallVerticalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+
+ MSEPitch,
+ MSEOrientation,
+
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportGuidByte7,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSETransportPositionX,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSETransportTime2,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportGuidByte6,
+ MSETransportGuidByte4,
+
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveNotActiveMover[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasMovementFlags2,
+ MSEHasTransportData,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasGuidByte3,
+ MSEZeroBit,
+ MSEHasTimestamp,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasGuidByte5,
+ MSEHasPitch,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasSpline,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasMovementFlags,
+
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte3,
+
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte3,
+
+ MSEFallVerticalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+
+ MSETransportTime3,
+ MSETransportGuidByte1,
+ MSETransportTime2,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSETransportGuidByte4,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportPositionY,
+ MSETransportPositionX,
+ MSETransportGuidByte2,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportTime,
+
+ MSETimestamp,
+ MSESplineElevation,
+ MSEPitch,
+ MSEOrientation,
+
+ MSEEnd,
+};
+
+MovementStatusElements const DismissControlledVehicle[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEHasSplineElevation,
+ MSEHasFallData,
+ MSEHasTransportData,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte2,
+ MSEHasOrientation,
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasPitch,
+ MSEHasTimestamp,
+ MSEHasGuidByte1,
+ MSEZeroBit,
+ MSEHasSpline,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags,
+ MSEHasGuidByte5,
+
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime2,
+
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte0,
+
+ MSETimestamp,
+
+ MSETransportTime3,
+ MSETransportGuidByte4,
+ MSETransportGuidByte7,
+ MSETransportTime2,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportGuidByte0,
+ MSETransportPositionX,
+ MSETransportGuidByte3,
+ MSETransportSeat,
+ MSETransportPositionY,
+ MSETransportOrientation,
+ MSETransportGuidByte1,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+
+ MSEOrientation,
+ MSESplineElevation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveUpdateTeleport[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasOrientation,
+
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasTransportData,
+ MSEHasGuidByte5,
+
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte2,
+
+ MSEZeroBit,
+
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasPitch,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEHasSplineElevation,
+ MSEMovementFlags,
+ MSEHasGuidByte1,
+
+ MSEGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportTime3,
+ MSETransportGuidByte1,
+ MSETransportTime2,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte0,
+ MSETransportGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+ MSETransportSeat,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSETransportPositionX,
+
+ MSEGuidByte6,
+ MSEPitch,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte1,
+
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSETimestamp,
+ MSEGuidByte0,
+
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetRunMode[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasTimestamp,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte1,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasGuidByte7,
+ MSEHasTransportData,
+ MSEZeroBit,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasGuidByte5,
+ MSEHasPitch,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEHasFallData,
+ MSEHasOrientation,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte2,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEPitch,
+ MSETransportTime2,
+ MSETransportGuidByte3,
+ MSETransportPositionX,
+ MSETransportSeat,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportPositionZ,
+ MSETransportGuidByte2,
+ MSETransportGuidByte7,
+ MSETransportOrientation,
+ MSETransportGuidByte4,
+ MSETransportTime,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportPositionY,
+ MSETransportGuidByte6,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetWalkMode[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasGuidByte6,
+ MSEHasSpline,
+ MSEHasTimestamp,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasMovementFlags,
+ MSEHasPitch,
+ MSEHasGuidByte7,
+ MSEHasSplineElevation,
+ MSEHasGuidByte4,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEZeroBit,
+ MSEHasMovementFlags2,
+ MSEHasFallData,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSETransportGuidByte2,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportGuidByte4,
+ MSETransportTime2,
+ MSETransportOrientation,
+ MSETransportPositionX,
+ MSETransportTime3,
+ MSETransportGuidByte7,
+ MSETransportPositionY,
+ MSETransportGuidByte1,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSESplineElevation,
+ MSEPitch,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetCanFly[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasTransportData,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasMovementFlags,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte5,
+ MSEHasTimestamp,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEZeroBit,
+ MSEHasPitch,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportSeat,
+ MSETransportPositionX,
+ MSETransportGuidByte2,
+ MSETransportTime2,
+ MSETransportPositionY,
+ MSETransportGuidByte1,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportGuidByte6,
+ MSETransportTime3,
+ MSESplineElevation,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEPitch,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetCanTransitionBetweenSwimAndFlyAck[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSECounter,
+ MSEPositionX,
+ MSEHasGuidByte3,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasMovementFlags,
+ MSEHasMovementFlags2,
+ MSEHasSplineElevation,
+ MSEHasTimestamp,
+ MSEHasSpline,
+ MSEZeroBit,
+ MSEHasFallData,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasPitch,
+ MSEHasGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte1,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSETransportPositionY,
+ MSETransportPositionZ,
+ MSETransportGuidByte5,
+ MSETransportGuidByte1,
+ MSETransportGuidByte4,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETransportGuidByte0,
+ MSETransportGuidByte2,
+ MSETransportGuidByte7,
+ MSETransportPositionX,
+ MSETransportTime2,
+ MSETransportGuidByte6,
+ MSETransportOrientation,
+ MSETransportTime3,
+ MSEPitch,
+ MSEOrientation,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateSwimSpeed[] =
+{
+ MSEHasMovementFlags,
+ MSEHasGuidByte2,
+ MSEMovementFlags,
+ MSEHasGuidByte3,
+ MSEZeroBit,
+ MSEHasGuidByte7,
+ MSEHasFallDirection,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasOrientation,
+ MSEHasGuidByte1,
+ MSETransportGuidByte2,
+ MSETransportPositionX,
+ MSETransportGuidByte6,
+ MSETransportOrientation,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSETransportPositionY,
+ MSETransportTime,
+ MSETransportGuidByte1,
+ MSETransportGuidByte7,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSEPositionX,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEGuidByte7,
+ MSETimestamp,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEExtraElement,
+ MSEGuidByte4,
+ MSEOrientation,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateRunSpeed[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEExtraElement,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags2,
+ MSEHasPitch,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasTimestamp,
+ MSEHasGuidByte1,
+ MSEMovementFlags2,
+ MSEHasGuidByte3,
+ MSEMovementFlags,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasFallData,
+ MSEHasFallDirection,
+ MSEHasGuidByte4,
+ MSEZeroBit,
+ MSETransportGuidByte4,
+ MSETransportGuidByte5,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSETransportSeat,
+ MSETransportTime2,
+ MSETransportPositionY,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportTime3,
+ MSETransportPositionZ,
+ MSETimestamp,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEPitch,
+ MSEGuidByte6,
+ MSESplineElevation,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEOrientation,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateFlightSpeed[] =
+{
+ MSEPositionY,
+ MSEExtraElement,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasMovementFlags,
+ MSEHasGuidByte4,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEMovementFlags,
+ MSEHasGuidByte2,
+ MSEHasOrientation,
+ MSEHasGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasFallDirection,
+ MSEHasGuidByte0,
+ MSEPitch,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte0,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportGuidByte1,
+ MSETransportSeat,
+ MSETransportPositionX,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSETimestamp,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEOrientation,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateCollisionHeight[] =
+{
+ MSEPositionZ,
+ MSEExtraElement,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasOrientation,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEZeroBit,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags,
+ MSEHasFallDirection,
+ MSEHasGuidByte1,
+ MSEMovementFlags,
+ MSEGuidByte3,
+ MSETransportGuidByte7,
+ MSETransportTime,
+ MSETransportGuidByte4,
+ MSETransportGuidByte5,
+ MSETransportOrientation,
+ MSETransportPositionX,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportPositionY,
+ MSETransportGuidByte2,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSETransportGuidByte1,
+ MSETransportSeat,
+ MSEPitch,
+ MSEGuidByte6,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEGuidByte7,
+ MSEOrientation,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSETimestamp,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementForceRunSpeedChangeAck[] =
+{
+ MSECounter,
+ MSEPositionX,
+ MSEExtraElement,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEHasGuidByte7,
+ MSEHasOrientation,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasSpline,
+ MSEHasTransportData,
+ MSEHasTimestamp,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte6,
+ MSEZeroBit,
+ MSEHasSplineElevation,
+ MSEHasPitch,
+ MSEHasGuidByte5,
+ MSEHasMovementFlags,
+ MSEHasGuidByte3,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSETransportPositionZ,
+ MSETransportGuidByte6,
+ MSETransportGuidByte1,
+ MSETransportPositionY,
+ MSETransportGuidByte0,
+ MSETransportGuidByte5,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportTime,
+ MSETransportGuidByte7,
+ MSETransportOrientation,
+ MSETransportGuidByte3,
+ MSETransportTime3,
+ MSETransportGuidByte2,
+ MSETransportSeat,
+ MSETransportGuidByte4,
+ MSEFallVerticalSpeed,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSESplineElevation,
+ MSEPitch,
+ MSETimestamp,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetCollisionHeightAck[] =
+{
+ MSEExtraElement,
+ MSEPositionX,
+ MSEPositionZ,
+ MSECounter,
+ MSEPositionY,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEZeroBit,
+ MSEZeroBit,
+ MSEHasPitch,
+ MSEHasGuidByte5,
+ MSEZeroBit,
+ MSEHasGuidByte2,
+ MSEHasGuidByte1,
+ MSEHasFallData,
+ MSEHasGuidByte3,
+ MSEHasSpline,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags,
+ MSEHasTransportData,
+ MSEHasTimestamp,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags2,
+ MSEHasOrientation,
+ MSEHasGuidByte0,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSETransportPositionX,
+ MSETransportGuidByte4,
+ MSETransportTime2,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSETransportSeat,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportPositionZ,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementForceFlightSpeedChangeAck[] =
+{
+ MSECounter,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEExtraElement,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEZeroBit,
+ MSEHasMovementFlags,
+ MSEHasSplineElevation,
+ MSEHasGuidByte3,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte7,
+ MSEHasTransportData,
+ MSEHasGuidByte0,
+ MSEHasFallData,
+ MSEHasTimestamp,
+ MSEHasPitch,
+ MSEHasSpline,
+ MSEHasOrientation,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte4,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSETransportTime2,
+ MSETransportOrientation,
+ MSETransportGuidByte1,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportGuidByte2,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportPositionX,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEPitch,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementSetCanFlyAck[] =
+{
+ MSEPositionY,
+ MSECounter,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEHasGuidByte3,
+ MSEHasTimestamp,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasOrientation,
+ MSEHasFallData,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags2,
+ MSEZeroBit,
+ MSEHasGuidByte7,
+ MSEHasSpline,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasMovementFlags,
+ MSEHasTransportData,
+ MSEHasPitch,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSETransportTime2,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportTime3,
+ MSETransportGuidByte7,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportPositionX,
+ MSETransportGuidByte2,
+ MSETransportOrientation,
+ MSETransportSeat,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSEFallTime,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEPitch,
+ MSEOrientation,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementForceSwimSpeedChangeAck[] =
+{
+ MSEPositionX,
+ MSECounter,
+ MSEExtraElement,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEHasGuidByte4,
+ MSEHasOrientation,
+ MSEHasPitch,
+ MSEHasTransportData,
+ MSEHasMovementFlags,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasFallData,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasTimestamp,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSETransportGuidByte0,
+ MSETransportTime3,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportGuidByte7,
+ MSETransportSeat,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportPositionZ,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte2,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSETransportGuidByte1,
+ MSETransportGuidByte4,
+ MSEFallTime,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSEPitch,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementForceWalkSpeedChangeAck[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSEExtraElement,
+ MSEPositionX,
+ MSECounter,
+ MSEHasGuidByte0,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags,
+ MSEHasFallData,
+ MSEHasOrientation,
+ MSEHasSpline,
+ MSEZeroBit,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasSplineElevation,
+ MSEHasTransportData,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasPitch,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEFallVerticalSpeed,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte5,
+ MSETransportPositionX,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportTime3,
+ MSETransportPositionY,
+ MSETransportGuidByte2,
+ MSETransportGuidByte4,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportOrientation,
+ MSETransportSeat,
+ MSETransportGuidByte6,
+ MSETransportTime2,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEOrientation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementForceRunBackSpeedChangeAck[] =
+{
+ MSEExtraElement,
+ MSECounter,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasTimestamp,
+ MSEHasTransportData,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasOrientation,
+ MSEHasFallData,
+ MSEHasMovementFlags2,
+ MSEHasMovementFlags,
+ MSEHasGuidByte7,
+ MSEHasSpline,
+ MSEHasPitch,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEZeroBit,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportGuidByte6,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportGuidByte2,
+ MSETransportPositionY,
+ MSETransportTime3,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportGuidByte3,
+ MSETransportTime,
+ MSETransportTime2,
+ MSETransportGuidByte4,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateRunBackSpeed[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEZeroBit,
+ MSEHasMovementFlags,
+ MSEHasGuidByte5,
+ MSEHasOrientation,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasGuidByte7,
+ MSETransportPositionX,
+ MSETransportGuidByte2,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSETransportPositionZ,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportGuidByte1,
+ MSETransportOrientation,
+ MSEGuidByte4,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSEGuidByte1,
+ MSEOrientation,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEPositionX,
+ MSEPositionY,
+ MSEPitch,
+ MSEGuidByte7,
+ MSEExtraElement,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEPositionZ,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateWalkSpeed[] =
+{
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasMovementFlags,
+ MSEHasGuidByte6,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEHasGuidByte4,
+ MSEPitch,
+ MSETransportGuidByte6,
+ MSETransportGuidByte0,
+ MSETransportGuidByte4,
+ MSETransportGuidByte2,
+ MSETransportPositionX,
+ MSETransportGuidByte7,
+ MSETransportTime,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportGuidByte5,
+ MSETransportOrientation,
+ MSETransportGuidByte1,
+ MSETransportPositionY,
+ MSETransportGuidByte3,
+ MSEFallVerticalSpeed,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSETimestamp,
+ MSEOrientation,
+ MSEPositionY,
+ MSEGuidByte0,
+ MSEPositionZ,
+ MSEPositionX,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEExtraElement,
+ MSEEnd,
+};
+
+MovementStatusElements const ForceMoveRootAck[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSECounter,
+ MSEPositionX,
+ MSEHasGuidByte3,
+ MSEHasTimestamp,
+ MSEHasTransportData,
+ MSEHasPitch,
+ MSEHasGuidByte2,
+ MSEHasOrientation,
+ MSEHasSplineElevation,
+ MSEHasFallData,
+ MSEHasSpline,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags2,
+ MSEHasMovementFlags,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte5,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSETransportGuidByte5,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportPositionZ,
+ MSETransportTime3,
+ MSETransportTime2,
+ MSETransportGuidByte7,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte3,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportPositionY,
+ MSETransportSeat,
+ MSETimestamp,
+ MSEFallVerticalSpeed,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallTime,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const ForceMoveUnrootAck[] =
+{
+ MSECounter,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasGuidByte7,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEZeroBit,
+ MSEHasTimestamp,
+ MSEHasMovementFlags,
+ MSEHasOrientation,
+ MSEHasPitch,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasTransportData,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEHasFallData,
+ MSEHasGuidByte6,
+ MSEHasFallDirection,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportTime3,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportTime2,
+ MSETransportGuidByte4,
+ MSETransportOrientation,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportGuidByte7,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementFallReset[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSEPositionY,
+ MSEHasGuidByte1,
+ MSEHasTimestamp,
+ MSEHasMovementFlags,
+ MSEZeroBit,
+ MSEHasGuidByte6,
+ MSEHasSplineElevation,
+ MSEHasPitch,
+ MSEHasGuidByte3,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags2,
+ MSEHasOrientation,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasSpline,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasFallData,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSETransportPositionX,
+ MSETransportGuidByte7,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportPositionY,
+ MSETransportPositionZ,
+ MSETransportSeat,
+ MSETransportTime2,
+ MSETransportGuidByte6,
+ MSETransportTime3,
+ MSETransportTime,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportGuidByte4,
+ MSETransportGuidByte1,
+ MSEFallVerticalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEOrientation,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementFeatherFallAck[] =
+{
+ MSEPositionZ,
+ MSECounter,
+ MSEPositionY,
+ MSEPositionX,
+ MSEZeroBit,
+ MSEHasGuidByte3,
+ MSEHasSplineElevation,
+ MSEHasGuidByte1,
+ MSEHasPitch,
+ MSEHasGuidByte2,
+ MSEHasSpline,
+ MSEHasTimestamp,
+ MSEHasGuidByte5,
+ MSEHasFallData,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte6,
+ MSEHasMovementFlags,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSETransportTime3,
+ MSETransportOrientation,
+ MSETransportPositionZ,
+ MSETransportGuidByte7,
+ MSETransportGuidByte5,
+ MSETransportGuidByte2,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportGuidByte6,
+ MSETransportTime2,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSETransportGuidByte4,
+ MSETransportGuidByte0,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETimestamp,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEFallVerticalSpeed,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementGravityDisableAck[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSECounter,
+ MSEPositionX,
+ MSEHasGuidByte3,
+ MSEHasTransportData,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasMovementFlags,
+ MSEHasOrientation,
+ MSEHasSpline,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasSplineElevation,
+ MSEHasTimestamp,
+ MSEHasPitch,
+ MSEHasMovementFlags2,
+ MSEZeroBit,
+ MSEHasGuidByte2,
+ MSEHasFallData,
+ MSEHasGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime2,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSETransportPositionZ,
+ MSETransportGuidByte2,
+ MSETransportGuidByte5,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportPositionY,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportGuidByte6,
+ MSETransportGuidByte1,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportTime2,
+ MSETransportPositionX,
+ MSETransportGuidByte7,
+ MSETransportTime3,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSESplineElevation,
+ MSETimestamp,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementGravityEnableAck[] =
+{
+ MSEPositionZ,
+ MSEPositionX,
+ MSECounter,
+ MSEPositionY,
+ MSEHasSplineElevation,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte6,
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEHasGuidByte5,
+ MSEHasSpline,
+ MSEHasGuidByte3,
+ MSEHasTransportData,
+ MSEHasPitch,
+ MSEHasGuidByte1,
+ MSEHasTimestamp,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags,
+ MSEHasFallData,
+ MSEHasGuidByte0,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasFallDirection,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallVerticalSpeed,
+ MSETransportGuidByte1,
+ MSETransportPositionX,
+ MSETransportTime3,
+ MSETransportOrientation,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportGuidByte7,
+ MSETransportGuidByte6,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportPositionZ,
+ MSETransportTime2,
+ MSETransportGuidByte5,
+ MSETransportTime,
+ MSETransportPositionY,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEPitch,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementHoverAck[] =
+{
+ MSECounter,
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasGuidByte4,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasTimestamp,
+ MSEHasSpline,
+ MSEHasMovementFlags,
+ MSEHasGuidByte1,
+ MSEHasPitch,
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEZeroBit,
+ MSEHasFallData,
+ MSEHasMovementFlags2,
+ MSEHasSplineElevation,
+ MSEHasOrientation,
+ MSEHasGuidByte3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime2,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSETimestamp,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEOrientation,
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte7,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportSeat,
+ MSETransportPositionX,
+ MSETransportPositionZ,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte0,
+ MSETransportPositionY,
+ MSETransportGuidByte5,
+ MSETransportTime2,
+ MSETransportGuidByte6,
+ MSESplineElevation,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementKnockBackAck[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSECounter,
+ MSEPositionX,
+ MSEHasGuidByte6,
+ MSEHasOrientation,
+ MSEHasPitch,
+ MSEHasSplineElevation,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasSpline,
+ MSEHasGuidByte7,
+ MSEZeroBit,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+ MSEHasGuidByte0,
+ MSEHasMovementFlags,
+ MSEHasTransportData,
+ MSEHasGuidByte5,
+ MSEHasFallData,
+ MSEMovementFlags,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte7,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSETransportPositionY,
+ MSETransportGuidByte4,
+ MSETransportTime2,
+ MSETransportGuidByte7,
+ MSETransportOrientation,
+ MSETransportGuidByte6,
+ MSETransportTime,
+ MSETransportGuidByte3,
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportGuidByte2,
+ MSETransportPositionZ,
+ MSETransportGuidByte0,
+ MSETransportGuidByte5,
+ MSETransportPositionX,
+ MSETransportSeat,
+ MSEPitch,
+ MSESplineElevation,
+ MSEOrientation,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementWaterWalkAck[] =
+{
+ MSEPositionY,
+ MSEPositionZ,
+ MSECounter,
+ MSEPositionX,
+ MSEHasTimestamp,
+ MSEHasPitch,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasOrientation,
+ MSEHasGuidByte1,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags,
+ MSEHasGuidByte3,
+ MSEHasTransportData,
+ MSEHasGuidByte6,
+ MSEHasFallData,
+ MSEHasGuidByte4,
+ MSEZeroBit,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte4,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEMovementFlags2,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSETransportPositionX,
+ MSETransportGuidByte1,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportGuidByte7,
+ MSETransportPositionY,
+ MSETransportTime2,
+ MSETransportTime,
+ MSETransportGuidByte5,
+ MSETransportSeat,
+ MSETransportPositionZ,
+ MSETransportGuidByte3,
+ MSETransportGuidByte2,
+ MSETransportGuidByte6,
+ MSETransportGuidByte4,
+ MSESplineElevation,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSEFallTime,
+ MSEOrientation,
+ MSETimestamp,
+ MSEPitch,
+ MSEEnd,
+};
+
+MovementStatusElements const MovementUpdateKnockBack[] =
+{
+ MSEZeroBit,
+ MSEHasGuidByte4,
+ MSEHasMovementFlags,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEHasOrientation,
+ MSEOrientation,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallCosAngle,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportGuidByte7,
+ MSETransportSeat,
+ MSETransportGuidByte3,
+ MSETransportGuidByte6,
+ MSETransportPositionZ,
+ MSETransportGuidByte1,
+ MSETransportPositionY,
+ MSETransportPositionX,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte4,
+ MSEPitch,
+ MSEPositionZ,
+ MSETimestamp,
+ MSEPositionX,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEPositionY,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetWalkSpeed[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEExtraElement,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetRunSpeed[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEExtraElement,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetRunBackSpeed[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEGuidByte1,
+ MSEExtraElement,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetSwimSpeed[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEExtraElement,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetSwimBackSpeed[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEExtraElement,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetTurnRate[] =
+{
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEExtraElement,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetFlightSpeed[] =
+{
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEExtraElement,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetFlightBackSpeed[] =
+{
+ MSEHasGuidByte2,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEGuidByte5,
+ MSEExtraElement,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetPitchRate[] =
+{
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEExtraElement,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetWalkSpeed[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEExtraElement,
+ MSEGuidByte2,
+ MSECounter,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetRunSpeed[] =
+{
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSECounter,
+ MSEExtraElement,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetRunBackSpeed[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEGuidByte5,
+ MSECounter,
+ MSEExtraElement,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetSwimSpeed[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEGuidByte0,
+ MSECounter,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEExtraElement,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetSwimBackSpeed[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSECounter,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEExtraElement,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetTurnRate[] =
+{
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEExtraElement,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSECounter,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetFlightSpeed[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEExtraElement,
+ MSECounter,
+ MSEGuidByte2,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetFlightBackSpeed[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEGuidByte3,
+ MSECounter,
+ MSEGuidByte6,
+ MSEExtraElement,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetPitchRate[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEExtraElement,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSECounter,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetCollisionHeight[] =
+{
+ MSEZeroBit,
+ MSEZeroBit,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSECounter,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEExtraElement,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetWalkMode[] =
+{
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetRunMode[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveGravityDisable[] =
+{
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveGravityEnable[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetHover[] =
+{
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveUnsetHover[] =
+{
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveStartSwim[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveStopSwim[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetFlying[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveUnsetFlying[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetWaterWalk[] =
+{
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetLandWalk[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetFeatherFall[] =
+{
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveSetNormalFall[] =
+{
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveRoot[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte2,
+ MSEHasGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte6,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const SplineMoveUnroot[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte3,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetCanFly[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte3,
+ MSECounter,
+ MSEGuidByte2,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveUnsetCanFly[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEHasGuidByte3,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte6,
+ MSECounter,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveSetHover[] =
+{
+ MSEHasGuidByte1,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSECounter,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveUnsetHover[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte0,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSECounter,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveWaterWalk[] =
+{
+ MSEHasGuidByte4,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte5,
+ MSEGuidByte2,
+ MSECounter,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveLandWalk[] =
+{
+ MSEHasGuidByte5,
+ MSEHasGuidByte1,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte0,
+ MSEHasGuidByte7,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEGuidByte4,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte2,
+ MSECounter,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveFeatherFall[] =
+{
+ MSEHasGuidByte3,
+ MSEHasGuidByte1,
+ MSEHasGuidByte7,
+ MSEHasGuidByte0,
+ MSEHasGuidByte4,
+ MSEHasGuidByte2,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEGuidByte5,
+ MSEGuidByte7,
+ MSEGuidByte2,
+ MSECounter,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveNormalFall[] =
+{
+ MSECounter,
+ MSEHasGuidByte3,
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte5,
+ MSEHasGuidByte7,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEHasGuidByte2,
+ MSEGuidByte2,
+ MSEGuidByte7,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte0,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveRoot[] =
+{
+ MSEHasGuidByte2,
+ MSEHasGuidByte7,
+ MSEHasGuidByte6,
+ MSEHasGuidByte0,
+ MSEHasGuidByte5,
+ MSEHasGuidByte4,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEGuidByte1,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSECounter,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte6,
+ MSEEnd,
+};
+
+MovementStatusElements const MoveUnroot[] =
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte3,
+ MSEHasGuidByte7,
+ MSEHasGuidByte5,
+ MSEHasGuidByte2,
+ MSEHasGuidByte4,
+ MSEHasGuidByte6,
+ MSEGuidByte3,
+ MSEGuidByte6,
+ MSEGuidByte1,
+ MSECounter,
+ MSEGuidByte2,
+ MSEGuidByte0,
+ MSEGuidByte7,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEEnd,
+};
+
+MovementStatusElements const ChangeSeatsOnControlledVehicle[] =
+{
+ MSEPositionY,
+ MSEPositionX,
+ MSEPositionZ,
+ MSEExtraElement,
+ MSEHasMovementFlags,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEExtraElement,
+ MSEExtraElement,
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEExtraElement,
+ MSEHasGuidByte7,
+ MSEExtraElement,
+ MSEHasTimestamp,
+ MSEHasSplineElevation,
+ MSEHasGuidByte5,
+ MSEExtraElement,
+ MSEHasMovementFlags2,
+ MSEHasPitch,
+ MSEExtraElement,
+ MSEHasGuidByte0,
+ MSEExtraElement,
+ MSEHasFallData,
+ MSEHasGuidByte1,
+ MSEHasSpline,
+ MSEMovementFlags,
+ MSEExtraElement,
+ MSEHasGuidByte3,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte6,
+ MSEMovementFlags2,
+ MSEHasFallDirection,
+ MSEExtraElement,
+ MSEGuidByte7,
+ MSEGuidByte5,
+ MSEExtraElement,
+ MSEExtraElement,
+ MSEGuidByte6,
+ MSEExtraElement,
+ MSEExtraElement,
+ MSEGuidByte3,
+ MSEExtraElement,
+ MSEGuidByte0,
+ MSEExtraElement,
+ MSEGuidByte4,
+ MSEGuidByte1,
+ MSEExtraElement,
+ MSEGuidByte2,
+ MSEPitch,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSETransportGuidByte2,
+ MSETransportTime2,
+ MSETransportTime3,
+ MSETransportGuidByte0,
+ MSETransportTime,
+ MSETransportSeat,
+ MSETransportPositionX,
+ MSETransportOrientation,
+ MSETransportGuidByte7,
+ MSETransportGuidByte4,
+ MSETransportGuidByte3,
+ MSETransportGuidByte5,
+ MSETransportPositionZ,
+ MSETransportGuidByte1,
+ MSETransportGuidByte6,
+ MSETransportPositionY,
+ MSESplineElevation,
+ MSEOrientation,
+ MSETimestamp,
+ MSEEnd,
+};
+
+MovementStatusElements const CastSpellEmbeddedMovement[] =
+{
+ MSEPositionZ,
+ MSEPositionY,
+ MSEPositionX,
+ MSEHasFallData,
+ MSEHasTimestamp,
+ MSEHasOrientation,
+ MSEZeroBit,
+ MSEHasSpline,
+ MSEHasGuidByte6,
+ MSEHasGuidByte4,
+ MSEHasMovementFlags2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte5,
+ MSEHasSplineElevation,
+ MSEHasPitch,
+ MSEHasGuidByte7,
+ MSEHasTransportData,
+ MSEHasGuidByte2,
+ MSEHasMovementFlags,
+ MSEHasGuidByte1,
+ MSEHasGuidByte0,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportTime2,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportTime3,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte3,
+ MSEMovementFlags2,
+ MSEMovementFlags,
+ MSEHasFallDirection,
+ MSEGuidByte1,
+ MSEGuidByte4,
+ MSEGuidByte7,
+ MSEGuidByte3,
+ MSEGuidByte0,
+ MSEGuidByte2,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSETransportSeat,
+ MSETransportOrientation,
+ MSETransportTime,
+ MSETransportGuidByte6,
+ MSETransportGuidByte5,
+ MSETransportTime3,
+ MSETransportPositionX,
+ MSETransportGuidByte4,
+ MSETransportPositionZ,
+ MSETransportGuidByte2,
+ MSETransportGuidByte0,
+ MSETransportTime2,
+ MSETransportGuidByte1,
+ MSETransportGuidByte3,
+ MSETransportPositionY,
+ MSETransportGuidByte7,
+ MSEOrientation,
+ MSESplineElevation,
+ MSEFallTime,
+ MSEFallHorizontalSpeed,
+ MSEFallSinAngle,
+ MSEFallCosAngle,
+ MSEFallVerticalSpeed,
+ MSETimestamp,
+ MSEPitch,
+ MSEEnd,
+};
+
+void Movement::ExtraMovementStatusElement::ReadNextElement(ByteBuffer& packet)
+{
+ MovementStatusElements const element = _elements[_index++];
+
+ switch (element)
+ {
+ case MSEHasGuidByte0:
+ case MSEHasGuidByte1:
+ case MSEHasGuidByte2:
+ case MSEHasGuidByte3:
+ case MSEHasGuidByte4:
+ case MSEHasGuidByte5:
+ case MSEHasGuidByte6:
+ case MSEHasGuidByte7:
+ Data.guid[element - MSEHasGuidByte0] = packet.ReadBit();
+ break;
+ case MSEGuidByte0:
+ case MSEGuidByte1:
+ case MSEGuidByte2:
+ case MSEGuidByte3:
+ case MSEGuidByte4:
+ case MSEGuidByte5:
+ case MSEGuidByte6:
+ case MSEGuidByte7:
+ packet.ReadByteSeq(Data.guid[element - MSEGuidByte0]);
+ break;
+ case MSEExtraFloat:
+ packet >> Data.floatData;
+ break;
+ case MSEExtraInt8:
+ packet >> Data.byteData;
+ break;
+ default:
+ ASSERT(PrintInvalidSequenceElement(element, __FUNCTION__));
+ break;
+ }
+}
+
+void Movement::ExtraMovementStatusElement::WriteNextElement(ByteBuffer& packet)
+{
+ MovementStatusElements const element = _elements[_index++];
+
+ switch (element)
+ {
+ case MSEHasGuidByte0:
+ case MSEHasGuidByte1:
+ case MSEHasGuidByte2:
+ case MSEHasGuidByte3:
+ case MSEHasGuidByte4:
+ case MSEHasGuidByte5:
+ case MSEHasGuidByte6:
+ case MSEHasGuidByte7:
+ packet.WriteBit(Data.guid[element - MSEHasGuidByte0]);
+ break;
+ case MSEGuidByte0:
+ case MSEGuidByte1:
+ case MSEGuidByte2:
+ case MSEGuidByte3:
+ case MSEGuidByte4:
+ case MSEGuidByte5:
+ case MSEGuidByte6:
+ case MSEGuidByte7:
+ packet.WriteByteSeq(Data.guid[element - MSEGuidByte0]);
+ break;
+ case MSEExtraFloat:
+ packet << Data.floatData;
+ break;
+ case MSEExtraInt8:
+ packet << Data.byteData;
+ break;
+ default:
+ ASSERT(PrintInvalidSequenceElement(element, __FUNCTION__));
+ break;
+ }
+}
+
+bool Movement::PrintInvalidSequenceElement(MovementStatusElements const element, char const* function)
+{
+ TC_LOG_ERROR("entities.unit", "Incorrect sequence element %d detected at %s", element, function);
+ return false;
+}
+
+Movement::PacketSender::PacketSender(Unit* unit, Opcodes serverControl, Opcodes playerControl, Opcodes broadcast /*= SMSG_PLAYER_MOVE*/, ExtraMovementStatusElement* extras /*= NULL*/)
+ : _extraElements(extras), _unit(unit)
+{
+ if (unit->GetTypeId() == TYPEID_PLAYER && unit->ToPlayer()->m_mover->GetTypeId() == TYPEID_PLAYER)
+ {
+ _selfOpcode = playerControl;
+ _broadcast = broadcast;
+ }
+ else
+ {
+ _selfOpcode = NULL_OPCODE;
+ _broadcast = serverControl;
+ }
+}
+
+void Movement::PacketSender::Send() const
+{
+ bool isPlayerMovement = false;
+ if (Player* player = _unit->ToPlayer())
+ {
+ isPlayerMovement = player->m_mover->GetTypeId() == TYPEID_PLAYER;
+ if (isPlayerMovement && _selfOpcode != NULL_OPCODE)
+ {
+ WorldPacket data(_selfOpcode);
+ _unit->WriteMovementInfo(data, _extraElements);
+ player->SendDirectMessage(&data);
+ }
+ }
+
+ if (_broadcast != NULL_OPCODE)
+ {
+ ///! Need to reset current extra element index before writing another packet
+ if (_extraElements)
+ _extraElements->ResetIndex();
+
+ WorldPacket data(_broadcast);
+ _unit->WriteMovementInfo(data, _extraElements);
+ _unit->SendMessageToSet(&data, !isPlayerMovement);
+ }
+}
+
+MovementStatusElements const* GetMovementStatusElementsSequence(Opcodes opcode)
+{
+ switch (opcode)
+ {
+ case MSG_MOVE_FALL_LAND:
+ return MovementFallLand;
+ case MSG_MOVE_HEARTBEAT:
+ return MovementHeartBeat;
+ case MSG_MOVE_JUMP:
+ return MovementJump;
+ case MSG_MOVE_SET_FACING:
+ return MovementSetFacing;
+ case MSG_MOVE_SET_PITCH:
+ return MovementSetPitch;
+ case MSG_MOVE_START_ASCEND:
+ return MovementStartAscend;
+ case MSG_MOVE_START_BACKWARD:
+ return MovementStartBackward;
+ case MSG_MOVE_START_DESCEND:
+ return MovementStartDescend;
+ case MSG_MOVE_START_FORWARD:
+ return MovementStartForward;
+ case MSG_MOVE_START_PITCH_DOWN:
+ return MovementStartPitchDown;
+ case MSG_MOVE_START_PITCH_UP:
+ return MovementStartPitchUp;
+ case MSG_MOVE_START_STRAFE_LEFT:
+ return MovementStartStrafeLeft;
+ case MSG_MOVE_START_STRAFE_RIGHT:
+ return MovementStartStrafeRight;
+ case MSG_MOVE_START_SWIM:
+ return MovementStartSwim;
+ case MSG_MOVE_START_TURN_LEFT:
+ return MovementStartTurnLeft;
+ case MSG_MOVE_START_TURN_RIGHT:
+ return MovementStartTurnRight;
+ case MSG_MOVE_STOP:
+ return MovementStop;
+ case MSG_MOVE_STOP_ASCEND:
+ return MovementStopAscend;
+ case MSG_MOVE_STOP_PITCH:
+ return MovementStopPitch;
+ case MSG_MOVE_STOP_STRAFE:
+ return MovementStopStrafe;
+ case MSG_MOVE_STOP_SWIM:
+ return MovementStopSwim;
+ case MSG_MOVE_STOP_TURN:
+ return MovementStopTurn;
+ case SMSG_PLAYER_MOVE:
+ return PlayerMove;
+ case CMSG_MOVE_CHNG_TRANSPORT:
+ return MoveChngTransport;
+ case CMSG_MOVE_SPLINE_DONE:
+ return MoveSplineDone;
+ case CMSG_MOVE_NOT_ACTIVE_MOVER:
+ return MoveNotActiveMover;
+ case CMSG_DISMISS_CONTROLLED_VEHICLE:
+ return DismissControlledVehicle;
+ case SMSG_MOVE_UPDATE_TELEPORT:
+ return MoveUpdateTeleport;
+ case CMSG_FORCE_MOVE_ROOT_ACK:
+ return ForceMoveRootAck;
+ case CMSG_FORCE_MOVE_UNROOT_ACK:
+ return ForceMoveUnrootAck;
+ case CMSG_MOVE_FALL_RESET:
+ return MovementFallReset;
+ case CMSG_MOVE_FEATHER_FALL_ACK:
+ return MovementFeatherFallAck;
+ case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK:
+ return MovementForceFlightSpeedChangeAck;
+ case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK:
+ return MovementForceRunBackSpeedChangeAck;
+ case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK:
+ return MovementForceRunSpeedChangeAck;
+ case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK:
+ return MovementForceSwimSpeedChangeAck;
+ case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK:
+ return MovementForceWalkSpeedChangeAck;
+ case CMSG_MOVE_GRAVITY_DISABLE_ACK:
+ return MovementGravityDisableAck;
+ case CMSG_MOVE_GRAVITY_ENABLE_ACK:
+ return MovementGravityEnableAck;
+ case CMSG_MOVE_HOVER_ACK:
+ return MovementHoverAck;
+ case CMSG_MOVE_KNOCK_BACK_ACK:
+ return MovementKnockBackAck;
+ case CMSG_MOVE_SET_CAN_FLY:
+ return MovementSetCanFly;
+ case CMSG_MOVE_SET_CAN_FLY_ACK:
+ return MovementSetCanFlyAck;
+ case CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK:
+ return MovementSetCanTransitionBetweenSwimAndFlyAck;
+ case SMSG_MOVE_SET_COLLISION_HEIGHT:
+ return MoveSetCollisionHeight;
+ case CMSG_MOVE_SET_COLLISION_HEIGHT_ACK:
+ return MovementSetCollisionHeightAck;
+ case SMSG_MOVE_UPDATE_COLLISION_HEIGHT:
+ return MovementUpdateCollisionHeight;
+ case CMSG_MOVE_WATER_WALK_ACK:
+ return MovementWaterWalkAck;
+ case MSG_MOVE_SET_RUN_MODE:
+ return MovementSetRunMode;
+ case MSG_MOVE_SET_WALK_MODE:
+ return MovementSetWalkMode;
+ case SMSG_MOVE_UPDATE_FLIGHT_SPEED:
+ return MovementUpdateFlightSpeed;
+ case SMSG_MOVE_UPDATE_RUN_SPEED:
+ return MovementUpdateRunSpeed;
+ case SMSG_MOVE_UPDATE_KNOCK_BACK:
+ return MovementUpdateKnockBack;
+ case SMSG_MOVE_UPDATE_RUN_BACK_SPEED:
+ return MovementUpdateRunBackSpeed;
+ case SMSG_MOVE_UPDATE_SWIM_SPEED:
+ return MovementUpdateSwimSpeed;
+ case SMSG_MOVE_UPDATE_WALK_SPEED:
+ return MovementUpdateWalkSpeed;
+ case SMSG_SPLINE_MOVE_SET_WALK_SPEED:
+ return SplineMoveSetWalkSpeed;
+ case SMSG_SPLINE_MOVE_SET_RUN_SPEED:
+ return SplineMoveSetRunSpeed;
+ case SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED:
+ return SplineMoveSetRunBackSpeed;
+ case SMSG_SPLINE_MOVE_SET_SWIM_SPEED:
+ return SplineMoveSetSwimSpeed;
+ case SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED:
+ return SplineMoveSetSwimBackSpeed;
+ case SMSG_SPLINE_MOVE_SET_TURN_RATE:
+ return SplineMoveSetTurnRate;
+ case SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED:
+ return SplineMoveSetFlightSpeed;
+ case SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED:
+ return SplineMoveSetFlightBackSpeed;
+ case SMSG_SPLINE_MOVE_SET_PITCH_RATE:
+ return SplineMoveSetPitchRate;
+ case SMSG_MOVE_SET_WALK_SPEED:
+ return MoveSetWalkSpeed;
+ case SMSG_MOVE_SET_RUN_SPEED:
+ return MoveSetRunSpeed;
+ case SMSG_MOVE_SET_RUN_BACK_SPEED:
+ return MoveSetRunBackSpeed;
+ case SMSG_MOVE_SET_SWIM_SPEED:
+ return MoveSetSwimSpeed;
+ case SMSG_MOVE_SET_SWIM_BACK_SPEED:
+ return MoveSetSwimBackSpeed;
+ case SMSG_MOVE_SET_TURN_RATE:
+ return MoveSetTurnRate;
+ case SMSG_MOVE_SET_FLIGHT_SPEED:
+ return MoveSetFlightSpeed;
+ case SMSG_MOVE_SET_FLIGHT_BACK_SPEED:
+ return MoveSetFlightBackSpeed;
+ case SMSG_MOVE_SET_PITCH_RATE:
+ return MoveSetPitchRate;
+ case SMSG_SPLINE_MOVE_SET_WALK_MODE:
+ return SplineMoveSetWalkMode;
+ case SMSG_SPLINE_MOVE_SET_RUN_MODE:
+ return SplineMoveSetRunMode;
+ case SMSG_SPLINE_MOVE_GRAVITY_DISABLE:
+ return SplineMoveGravityDisable;
+ case SMSG_SPLINE_MOVE_GRAVITY_ENABLE:
+ return SplineMoveGravityEnable;
+ case SMSG_SPLINE_MOVE_SET_HOVER:
+ return SplineMoveSetHover;
+ case SMSG_SPLINE_MOVE_UNSET_HOVER:
+ return SplineMoveUnsetHover;
+ case SMSG_SPLINE_MOVE_START_SWIM:
+ return SplineMoveStartSwim;
+ case SMSG_SPLINE_MOVE_STOP_SWIM:
+ return SplineMoveStopSwim;
+ case SMSG_SPLINE_MOVE_SET_FLYING:
+ return SplineMoveSetFlying;
+ case SMSG_SPLINE_MOVE_UNSET_FLYING:
+ return SplineMoveUnsetFlying;
+ case SMSG_SPLINE_MOVE_SET_WATER_WALK:
+ return SplineMoveSetWaterWalk;
+ case SMSG_SPLINE_MOVE_SET_LAND_WALK:
+ return SplineMoveSetLandWalk;
+ case SMSG_SPLINE_MOVE_SET_FEATHER_FALL:
+ return SplineMoveSetFeatherFall;
+ case SMSG_SPLINE_MOVE_SET_NORMAL_FALL:
+ return SplineMoveSetNormalFall;
+ case SMSG_SPLINE_MOVE_ROOT:
+ return SplineMoveRoot;
+ case SMSG_SPLINE_MOVE_UNROOT:
+ return SplineMoveUnroot;
+ case SMSG_MOVE_SET_CAN_FLY:
+ return MoveSetCanFly;
+ case SMSG_MOVE_UNSET_CAN_FLY:
+ return MoveUnsetCanFly;
+ case SMSG_MOVE_SET_HOVER:
+ return MoveSetHover;
+ case SMSG_MOVE_UNSET_HOVER:
+ return MoveUnsetHover;
+ case SMSG_MOVE_WATER_WALK:
+ return MoveWaterWalk;
+ case SMSG_MOVE_LAND_WALK:
+ return MoveLandWalk;
+ case SMSG_MOVE_FEATHER_FALL:
+ return MoveFeatherFall;
+ case SMSG_MOVE_NORMAL_FALL:
+ return MoveNormalFall;
+ case SMSG_MOVE_ROOT:
+ return MoveRoot;
+ case SMSG_MOVE_UNROOT:
+ return MoveUnroot;
+ case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE:
+ return ChangeSeatsOnControlledVehicle;
+ case CMSG_CAST_SPELL:
+ case CMSG_PET_CAST_SPELL:
+ case CMSG_USE_ITEM:
+ return CastSpellEmbeddedMovement;
+ default:
+ break;
+ }
+
+ return NULL;
+}
diff --git a/src/server/game/Movement/MovementStructures.h b/src/server/game/Movement/MovementStructures.h
new file mode 100644
index 00000000000..278eaa877fa
--- /dev/null
+++ b/src/server/game/Movement/MovementStructures.h
@@ -0,0 +1,158 @@
+/*
+* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _MOVEMENT_STRUCTURES_H
+#define _MOVEMENT_STRUCTURES_H
+
+#include "Opcodes.h"
+#include "Object.h"
+
+class ByteBuffer;
+class Unit;
+
+enum MovementStatusElements
+{
+ MSEHasGuidByte0,
+ MSEHasGuidByte1,
+ MSEHasGuidByte2,
+ MSEHasGuidByte3,
+ MSEHasGuidByte4,
+ MSEHasGuidByte5,
+ MSEHasGuidByte6,
+ MSEHasGuidByte7,
+ MSEHasMovementFlags,
+ MSEHasMovementFlags2,
+ MSEHasTimestamp,
+ MSEHasOrientation,
+ MSEHasTransportData,
+ MSEHasTransportGuidByte0,
+ MSEHasTransportGuidByte1,
+ MSEHasTransportGuidByte2,
+ MSEHasTransportGuidByte3,
+ MSEHasTransportGuidByte4,
+ MSEHasTransportGuidByte5,
+ MSEHasTransportGuidByte6,
+ MSEHasTransportGuidByte7,
+ MSEHasTransportTime2,
+ MSEHasTransportTime3,
+ MSEHasPitch,
+ MSEHasFallData,
+ MSEHasFallDirection,
+ MSEHasSplineElevation,
+ MSEHasSpline,
+
+ MSEGuidByte0,
+ MSEGuidByte1,
+ MSEGuidByte2,
+ MSEGuidByte3,
+ MSEGuidByte4,
+ MSEGuidByte5,
+ MSEGuidByte6,
+ MSEGuidByte7,
+ MSEMovementFlags,
+ MSEMovementFlags2,
+ MSETimestamp,
+ MSEPositionX,
+ MSEPositionY,
+ MSEPositionZ,
+ MSEOrientation,
+ MSETransportGuidByte0,
+ MSETransportGuidByte1,
+ MSETransportGuidByte2,
+ MSETransportGuidByte3,
+ MSETransportGuidByte4,
+ MSETransportGuidByte5,
+ MSETransportGuidByte6,
+ MSETransportGuidByte7,
+ MSETransportPositionX,
+ MSETransportPositionY,
+ MSETransportPositionZ,
+ MSETransportOrientation,
+ MSETransportSeat,
+ MSETransportTime,
+ MSETransportTime2,
+ MSETransportTime3,
+ MSEPitch,
+ MSEFallTime,
+ MSEFallVerticalSpeed,
+ MSEFallCosAngle,
+ MSEFallSinAngle,
+ MSEFallHorizontalSpeed,
+ MSESplineElevation,
+
+ MSECounter,
+
+ // Special
+ MSEZeroBit, // writes bit value 1 or skips read bit
+ MSEOneBit, // writes bit value 0 or skips read bit
+ MSEEnd, // marks end of parsing
+ MSEExtraElement, // Used to signalize reading into ExtraMovementStatusElement, element sequence inside it is declared as separate array
+ // Allowed internal elements are: GUID markers (not transport), MSEExtraFloat, MSEExtraInt8
+ MSEExtraFloat,
+ MSEExtraInt8,
+};
+
+namespace Movement
+{
+ class PacketSender;
+
+ class ExtraMovementStatusElement
+ {
+ friend class PacketSender;
+
+ public:
+ ExtraMovementStatusElement(MovementStatusElements const* elements) : _elements(elements), _index(0) { }
+
+ void ReadNextElement(ByteBuffer& packet);
+ void WriteNextElement(ByteBuffer& packet);
+
+ struct
+ {
+ ObjectGuid guid;
+ float floatData;
+ int8 byteData;
+ } Data;
+
+ protected:
+ void ResetIndex() { _index = 0; }
+
+ private:
+ MovementStatusElements const* _elements;
+ uint32 _index;
+ };
+
+ class PacketSender
+ {
+ public:
+ PacketSender(Unit* unit, Opcodes serverControl, Opcodes playerControl, Opcodes broadcast = SMSG_PLAYER_MOVE, ExtraMovementStatusElement* extras = NULL);
+
+ void Send() const;
+
+ private:
+ ExtraMovementStatusElement* _extraElements;
+ Unit* _unit;
+ Opcodes _selfOpcode;
+ Opcodes _broadcast;
+ };
+
+ bool PrintInvalidSequenceElement(MovementStatusElements element, char const* function);
+}
+
+MovementStatusElements const* GetMovementStatusElementsSequence(Opcodes opcode);
+
+#endif
diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp
index cbf88b68028..6acee7f7a9c 100644
--- a/src/server/game/Movement/PathGenerator.cpp
+++ b/src/server/game/Movement/PathGenerator.cpp
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify
@@ -75,6 +76,7 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo
// make sure navMesh works - we can run on map w/o mmap
// check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?)
if (!_navMesh || !_navMeshQuery || _sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) ||
+ (_sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING) ||
!HaveTile(start) || !HaveTile(dest))
{
BuildShortcut();
diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp
index 7291c6849c5..6e3d7680637 100644
--- a/src/server/game/Movement/Spline/MoveSpline.cpp
+++ b/src/server/game/Movement/Spline/MoveSpline.cpp
@@ -52,7 +52,7 @@ Location MoveSpline::ComputePosition() const
}
else
{
- if (!splineflags.hasFlag(MoveSplineFlag::OrientationFixed | MoveSplineFlag::Falling))
+ if (!splineflags.hasFlag(MoveSplineFlag::OrientationFixed | MoveSplineFlag::Falling | MoveSplineFlag::Unknown0))
{
Vector3 hermite;
spline.evaluate_derivative(point_Idx, u, hermite);
@@ -216,7 +216,7 @@ bool MoveSplineInitArgs::Validate(Unit* unit) const
// each vertex offset packed into 11 bytes
bool MoveSplineInitArgs::_checkPathBounds() const
{
- if (!(flags & MoveSplineFlag::Mask_CatmullRom) && path.size() > 2)
+ if (!(flags & MoveSplineFlag::Catmullrom) && path.size() > 2)
{
enum{
MAX_OFFSET = (1 << 11) / 2
diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h
index 62fe808b6f5..f9151c53fc2 100644
--- a/src/server/game/Movement/Spline/MoveSplineFlag.h
+++ b/src/server/game/Movement/Spline/MoveSplineFlag.h
@@ -36,42 +36,45 @@ namespace Movement
enum eFlags
{
None = 0x00000000,
- // x00-xFF(first byte) used as animation Ids storage in pair with Animation flag
- Done = 0x00000100,
- Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag
- No_Spline = 0x00000400,
- Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag
- Walkmode = 0x00001000,
- Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation
- OrientationFixed = 0x00004000, // Model orientation fixed
- Final_Point = 0x00008000,
- Final_Target = 0x00010000,
- Final_Angle = 0x00020000,
- Catmullrom = 0x00040000, // Used Catmullrom interpolation mode
- Cyclic = 0x00080000, // Movement by cycled spline
- Enter_Cycle = 0x00100000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done
- Animation = 0x00200000, // Plays animation after some time passed
- Frozen = 0x00400000, // Will never arrive
- TransportEnter = 0x00800000,
- TransportExit = 0x01000000,
- Unknown7 = 0x02000000,
- Unknown8 = 0x04000000,
- OrientationInversed = 0x08000000,
- Unknown10 = 0x10000000,
- Unknown11 = 0x20000000,
- Unknown12 = 0x40000000,
- Unknown13 = 0x80000000,
+ // x00-x07 used as animation Ids storage in pair with Animation flag
+ Unknown0 = 0x00000008, // NOT VERIFIED
+ FallingSlow = 0x00000010,
+ Done = 0x00000020,
+ Falling = 0x00000040, // Affects elevation computation, can't be combined with Parabolic flag
+ No_Spline = 0x00000080,
+ Unknown2 = 0x00000100, // NOT VERIFIED
+ Flying = 0x00000200, // Smooth movement(Catmullrom interpolation mode), flying animation
+ OrientationFixed = 0x00000400, // Model orientation fixed
+ Catmullrom = 0x00000800, // Used Catmullrom interpolation mode
+ Cyclic = 0x00001000, // Movement by cycled spline
+ Enter_Cycle = 0x00002000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done
+ Frozen = 0x00004000, // Will never arrive
+ TransportEnter = 0x00008000,
+ TransportExit = 0x00010000,
+ Unknown3 = 0x00020000, // NOT VERIFIED
+ Unknown4 = 0x00040000, // NOT VERIFIED
+ OrientationInversed = 0x00080000,
+ SmoothGroundPath = 0x00100000,
+ Walkmode = 0x00200000,
+ UncompressedPath = 0x00400000,
+ Unknown6 = 0x00800000, // NOT VERIFIED
+ Animation = 0x01000000, // Plays animation after some time passed
+ Parabolic = 0x02000000, // Affects elevation computation, can't be combined with Falling flag
+ Final_Point = 0x04000000,
+ Final_Target = 0x08000000,
+ Final_Angle = 0x10000000,
+ Unknown7 = 0x20000000, // NOT VERIFIED
+ Unknown8 = 0x40000000, // NOT VERIFIED
+ Unknown9 = 0x80000000, // NOT VERIFIED
// Masks
Mask_Final_Facing = Final_Point | Final_Target | Final_Angle,
// animation ids stored here, see AnimType enum, used with Animation flag
- Mask_Animations = 0xFF,
+ Mask_Animations = 0x7,
// flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably
Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done,
- // CatmullRom interpolation mode used
- Mask_CatmullRom = Flying | Catmullrom,
// Unused, not suported flags
- Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown7|Unknown8|Unknown10|Unknown11|Unknown12|Unknown13
+ Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown0|Unknown2|Unknown3|Unknown4|Unknown6|Unknown7|Unknown8|Unknown9
};
inline uint32& raw() { return (uint32&)*this; }
@@ -83,7 +86,7 @@ namespace Movement
// Constant interface
- bool isSmooth() const { return (raw() & Mask_CatmullRom) != 0; }
+ bool isSmooth() const { return (raw() & Catmullrom) != 0; }
bool isLinear() const { return !isSmooth(); }
bool isFacing() const { return (raw() & Mask_Final_Facing) != 0; }
@@ -99,42 +102,47 @@ namespace Movement
void operator &= (uint32 f) { raw() &= f; }
void operator |= (uint32 f) { raw() |= f; }
- void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations | Falling | Parabolic)) | Animation | anim; }
- void EnableParabolic() { raw() = (raw() & ~(Mask_Animations | Falling | Animation)) | Parabolic; }
- void EnableFalling() { raw() = (raw() & ~(Mask_Animations | Parabolic | Flying | Animation)) | Falling; }
- void EnableFlying() { raw() = (raw() & ~(Falling | Catmullrom)) | Flying; }
- void EnableCatmullRom() { raw() = (raw() & ~Flying) | Catmullrom; }
+ void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations | Falling | Parabolic | FallingSlow)) | Animation | (anim & Mask_Animations); }
+ void EnableParabolic() { raw() = (raw() & ~(Mask_Animations | Falling | Animation | FallingSlow)) | Parabolic; }
+ void EnableFlying() { raw() = (raw() & ~(Falling)) | Flying; }
+ void EnableFalling() { raw() = (raw() & ~(Mask_Animations | Parabolic | Animation | Flying)) | Falling; }
+ void EnableCatmullRom() { raw() = (raw() & ~SmoothGroundPath) | Catmullrom; }
void EnableFacingPoint() { raw() = (raw() & ~Mask_Final_Facing) | Final_Point; }
void EnableFacingAngle() { raw() = (raw() & ~Mask_Final_Facing) | Final_Angle; }
void EnableFacingTarget() { raw() = (raw() & ~Mask_Final_Facing) | Final_Target; }
void EnableTransportEnter() { raw() = (raw() & ~TransportExit) | TransportEnter; }
void EnableTransportExit() { raw() = (raw() & ~TransportEnter) | TransportExit; }
- uint8 animId : 8;
+ uint8 animId : 3;
+ bool unknown0 : 1;
+ bool fallingSlow : 1;
bool done : 1;
bool falling : 1;
bool no_spline : 1;
- bool parabolic : 1;
- bool walkmode : 1;
+ bool unknown2 : 1;
bool flying : 1;
bool orientationFixed : 1;
- bool final_point : 1;
- bool final_target : 1;
- bool final_angle : 1;
bool catmullrom : 1;
bool cyclic : 1;
bool enter_cycle : 1;
- bool animation : 1;
bool frozen : 1;
bool transportEnter : 1;
bool transportExit : 1;
+ bool unknown3 : 1;
+ bool unknown4 : 1;
+ bool orientationInversed : 1;
+ bool smoothGroundPath : 1;
+ bool walkmode : 1;
+ bool uncompressedPath : 1;
+ bool unknown6 : 1;
+ bool animation : 1;
+ bool parabolic : 1;
+ bool final_point : 1;
+ bool final_target : 1;
+ bool final_angle : 1;
bool unknown7 : 1;
bool unknown8 : 1;
- bool orientationInversed : 1;
- bool unknown10 : 1;
- bool unknown11 : 1;
- bool unknown12 : 1;
- bool unknown13 : 1;
+ bool unknown9 : 1;
};
#if defined( __GNUC__ )
#pragma pack()
diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp
index 87d8e4a0c34..e1a15fa52b5 100644
--- a/src/server/game/Movement/Spline/MoveSplineInit.cpp
+++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp
@@ -60,11 +60,10 @@ namespace Movement
{
MoveSpline& move_spline = *unit->movespline;
- // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes (movementInfo.transport.guid is 0 in that case)
- bool transport = unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID();
+ bool transport = unit->GetTransGUID() != 0;
Location real_position;
// there is a big chance that current position is unknown if current state is not finalized, need compute it
- // this also allows CalculatePath spline position and update map position in much greater intervals
+ // this also allows calculate spline position and update map position in much greater intervals
// Don't compute for transport movement if the unit is in a motion between two transports
if (!move_spline.Finalized() && move_spline.onTransport == transport)
real_position = move_spline.ComputePosition();
@@ -86,13 +85,13 @@ namespace Movement
if (args.path.empty())
return 0;
- // corrent first vertex
+ // correct first vertex
args.path[0] = real_position;
args.initialOrientation = real_position.orientation;
- move_spline.onTransport = transport;
+ move_spline.onTransport = (unit->GetTransGUID() != 0);
uint32 moveFlags = unit->m_movementInfo.GetMovementFlags();
- moveFlags |= (MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD);
+ moveFlags |= MOVEMENTFLAG_FORWARD;
if (moveFlags & MOVEMENTFLAG_ROOT)
moveFlags &= ~MOVEMENTFLAG_MASK_MOVING;
@@ -118,7 +117,7 @@ namespace Movement
WorldPacket data(SMSG_MONSTER_MOVE, 64);
data.append(unit->GetPackGUID());
- if (transport)
+ if (unit->GetTransGUID())
{
data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT);
data.appendPackGUID(unit->GetTransGUID());
@@ -139,7 +138,7 @@ namespace Movement
if (move_spline.Finalized())
return;
- bool transport = unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID();
+ bool transport = unit->GetTransGUID() != 0;
Location loc;
if (move_spline.onTransport == transport)
loc = move_spline.ComputePosition();
@@ -158,7 +157,7 @@ namespace Movement
}
args.flags = MoveSplineFlag::Done;
- unit->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_SPLINE_ENABLED);
+ unit->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FORWARD);
move_spline.onTransport = transport;
move_spline.Initialize(args);
@@ -179,10 +178,11 @@ namespace Movement
{
args.splineId = splineIdGen.NewId();
// Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes
- args.TransformForTransport = unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID();
+ args.TransformForTransport = unit->GetTransGUID() != 0;
// mix existing state into new
args.flags.walkmode = unit->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);
- args.flags.flying = unit->m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY));
+ args.flags.flying = unit->m_movementInfo.HasMovementFlag(MovementFlags(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY));
+ args.flags.smoothGroundPath = true; // enabled by default, CatmullRom mode or client config "pathSmoothing" will disable this
}
void MoveSplineInit::SetFacing(const Unit* target)
@@ -224,6 +224,12 @@ namespace Movement
args.path[1] = transform(dest);
}
+ void MoveSplineInit::SetFall()
+ {
+ args.flags.EnableFalling();
+ args.flags.fallingSlow = unit->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW);
+ }
+
Vector3 TransportPathTransform::operator()(Vector3 input)
{
if (_transformForTransport)
diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h
index a94c84d92f3..c968f660f58 100644
--- a/src/server/game/Movement/Spline/MoveSplineInit.h
+++ b/src/server/game/Movement/Spline/MoveSplineInit.h
@@ -102,27 +102,39 @@ namespace Movement
* if not enabled linear spline mode will be choosen. Disabled by default
*/
void SetSmooth();
- /* Enables CatmullRom spline interpolation mode, enables flying animation. Disabled by default
+
+ /* Waypoints in packets will be sent without compression
+ */
+ void SetUncompressed();
+
+ /* Enables flying animation. Disabled by default
*/
void SetFly();
+
/* Enables walk mode. Disabled by default
*/
void SetWalk(bool enable);
+
/* Makes movement cyclic. Disabled by default
*/
void SetCyclic();
+
/* Enables falling mode. Disabled by default
*/
void SetFall();
+
/* Enters transport. Disabled by default
*/
void SetTransportEnter();
+
/* Exits transport. Disabled by default
*/
void SetTransportExit();
+
/* Inverses unit model orientation. Disabled by default
*/
void SetOrientationInversed();
+
/* Fixes unit's model rotation. Disabled by default
*/
void SetOrientationFixed(bool enable);
@@ -148,8 +160,8 @@ namespace Movement
inline void MoveSplineInit::SetFly() { args.flags.EnableFlying(); }
inline void MoveSplineInit::SetWalk(bool enable) { args.flags.walkmode = enable; }
inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom(); }
+ inline void MoveSplineInit::SetUncompressed() { args.flags.uncompressedPath = true; }
inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true; }
- inline void MoveSplineInit::SetFall() { args.flags.EnableFalling(); }
inline void MoveSplineInit::SetVelocity(float vel) { args.velocity = vel; args.HasVelocity = true; }
inline void MoveSplineInit::SetOrientationInversed() { args.flags.orientationInversed = true;}
inline void MoveSplineInit::SetTransportEnter() { args.flags.EnableTransportEnter(); }
diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
index 51932877666..0793e51b164 100644
--- a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
+++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
@@ -19,7 +19,8 @@
#include "MovementPacketBuilder.h"
#include "MoveSpline.h"
-#include "ByteBuffer.h"
+#include "WorldPacket.h"
+#include "Object.h"
namespace Movement
{
@@ -42,7 +43,7 @@ namespace Movement
MonsterMoveFacingAngle = 4
};
- void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, ByteBuffer& data)
+ void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, WorldPacket& data)
{
MoveSplineFlag splineflags = move_spline.splineflags;
@@ -96,10 +97,10 @@ namespace Movement
data << uint8(MonsterMoveStop);
}
- void WriteLinearPath(const Spline<int32>& spline, ByteBuffer& data)
+ void WriteLinearPath(Spline<int32> const& spline, ByteBuffer& data)
{
uint32 last_idx = spline.getPointCount() - 3;
- const Vector3 * real_path = &spline.getPoint(1);
+ Vector3 const* real_path = &spline.getPoint(1);
data << last_idx;
data << real_path[last_idx]; // destination
@@ -116,14 +117,14 @@ namespace Movement
}
}
- void WriteCatmullRomPath(const Spline<int32>& spline, ByteBuffer& data)
+ void WriteUncompressedPath(Spline<int32> const& spline, ByteBuffer& data)
{
uint32 count = spline.getPointCount() - 3;
data << count;
data.append<Vector3>(&spline.getPoint(2), count);
}
- void WriteCatmullRomCyclicPath(const Spline<int32>& spline, ByteBuffer& data)
+ void WriteUncompressedCyclicPath(Spline<int32> const& spline, ByteBuffer& data)
{
uint32 count = spline.getPointCount() - 3;
data << uint32(count + 1);
@@ -131,61 +132,117 @@ namespace Movement
data.append<Vector3>(&spline.getPoint(1), count);
}
- void PacketBuilder::WriteMonsterMove(const MoveSpline& move_spline, ByteBuffer& data)
+ void PacketBuilder::WriteMonsterMove(const MoveSpline& move_spline, WorldPacket& data)
{
WriteCommonMonsterMovePart(move_spline, data);
- const Spline<int32>& spline = move_spline.spline;
+ Spline<int32> const& spline = move_spline.spline;
MoveSplineFlag splineflags = move_spline.splineflags;
- if (splineflags & MoveSplineFlag::Mask_CatmullRom)
+ if (splineflags & MoveSplineFlag::UncompressedPath)
{
- if (splineflags.cyclic)
- WriteCatmullRomCyclicPath(spline, data);
+ if (!splineflags.cyclic)
+ WriteUncompressedPath(spline, data);
else
- WriteCatmullRomPath(spline, data);
+ WriteUncompressedCyclicPath(spline, data);
}
else
WriteLinearPath(spline, data);
}
- void PacketBuilder::WriteCreate(const MoveSpline& move_spline, ByteBuffer& data)
+ void PacketBuilder::WriteCreateBits(MoveSpline const& moveSpline, ByteBuffer& data)
{
- //WriteClientStatus(mov, data);
- //data.append<float>(&mov.m_float_values[SpeedWalk], SpeedMaxCount);
- //if (mov.SplineEnabled())
+ if (!data.WriteBit(!moveSpline.Finalized()))
+ return;
+
+ data.WriteBits(uint8(moveSpline.spline.mode()), 2);
+ data.WriteBit(moveSpline.splineflags & (MoveSplineFlag::Parabolic | MoveSplineFlag::Animation));
+ data.WriteBits(moveSpline.getPath().size(), 22);
+ switch (moveSpline.splineflags & MoveSplineFlag::Mask_Final_Facing)
+ {
+ case MoveSplineFlag::Final_Target:
+ {
+ ObjectGuid targetGuid = moveSpline.facing.target;
+ data.WriteBits(2, 2);
+ data.WriteBit(targetGuid[4]);
+ data.WriteBit(targetGuid[3]);
+ data.WriteBit(targetGuid[7]);
+ data.WriteBit(targetGuid[2]);
+ data.WriteBit(targetGuid[6]);
+ data.WriteBit(targetGuid[1]);
+ data.WriteBit(targetGuid[0]);
+ data.WriteBit(targetGuid[5]);
+ break;
+ }
+ case MoveSplineFlag::Final_Angle:
+ data.WriteBits(0, 2);
+ break;
+ case MoveSplineFlag::Final_Point:
+ data.WriteBits(1, 2);
+ break;
+ default:
+ data.WriteBits(3, 2);
+ break;
+ }
+
+ data.WriteBit((moveSpline.splineflags & MoveSplineFlag::Parabolic) && moveSpline.effect_start_time < moveSpline.Duration());
+ data.WriteBits(moveSpline.splineflags.raw(), 25);
+ }
+
+ void PacketBuilder::WriteCreateData(MoveSpline const& moveSpline, ByteBuffer& data)
+ {
+ if (!moveSpline.Finalized())
{
- MoveSplineFlag const& splineFlags = move_spline.splineflags;
+ MoveSplineFlag const& splineFlags = moveSpline.splineflags;
- data << splineFlags.raw();
+ if ((splineFlags & MoveSplineFlag::Parabolic) && moveSpline.effect_start_time < moveSpline.Duration())
+ data << moveSpline.vertical_acceleration; // added in 3.1
+
+ data << moveSpline.timePassed();
if (splineFlags.final_angle)
- {
- data << move_spline.facing.angle;
- }
+ data << moveSpline.facing.angle;
else if (splineFlags.final_target)
{
- data << move_spline.facing.target;
+ ObjectGuid facingGuid = moveSpline.facing.target;
+ data.WriteByteSeq(facingGuid[5]);
+ data.WriteByteSeq(facingGuid[3]);
+ data.WriteByteSeq(facingGuid[7]);
+ data.WriteByteSeq(facingGuid[1]);
+ data.WriteByteSeq(facingGuid[6]);
+ data.WriteByteSeq(facingGuid[4]);
+ data.WriteByteSeq(facingGuid[2]);
+ data.WriteByteSeq(facingGuid[0]);
}
- else if (splineFlags.final_point)
+
+ uint32 nodes = moveSpline.getPath().size();
+ for (uint32 i = 0; i < nodes; ++i)
{
- data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
+ data << float(moveSpline.getPath()[i].z);
+ data << float(moveSpline.getPath()[i].x);
+ data << float(moveSpline.getPath()[i].y);
}
- data << move_spline.timePassed();
- data << move_spline.Duration();
- data << move_spline.GetId();
+ if (splineFlags.final_point)
+ data << moveSpline.facing.f.x << moveSpline.facing.f.z << moveSpline.facing.f.y;
- data << float(1.f); // splineInfo.duration_mod; added in 3.1
data << float(1.f); // splineInfo.duration_mod_next; added in 3.1
+ data << moveSpline.Duration();
+ if (splineFlags & (MoveSplineFlag::Parabolic | MoveSplineFlag::Animation))
+ data << moveSpline.effect_start_time; // added in 3.1
- data << move_spline.vertical_acceleration; // added in 3.1
- data << move_spline.effect_start_time; // added in 3.1
+ data << float(1.f); // splineInfo.duration_mod; added in 3.1
+ }
- uint32 nodes = move_spline.getPath().size();
- data << nodes;
- data.append<Vector3>(&move_spline.getPath()[0], nodes);
- data << uint8(move_spline.spline.mode()); // added in 3.1
- data << (move_spline.isCyclic() ? Vector3::zero() : move_spline.FinalDestination());
+ if (!moveSpline.isCyclic())
+ {
+ Vector3 dest = moveSpline.FinalDestination();
+ data << float(dest.z);
+ data << float(dest.x);
+ data << float(dest.y);
}
+ else
+ data << Vector3::zero();
+
+ data << moveSpline.GetId();
}
}
diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.h b/src/server/game/Movement/Spline/MovementPacketBuilder.h
index d1ad3d61eec..750cdc0fdbf 100644
--- a/src/server/game/Movement/Spline/MovementPacketBuilder.h
+++ b/src/server/game/Movement/Spline/MovementPacketBuilder.h
@@ -20,27 +20,25 @@
#ifndef TRINITYSERVER_PACKET_BUILDER_H
#define TRINITYSERVER_PACKET_BUILDER_H
-#include "Define.h"
+#include "Define.h" // for uint32
+#include "G3D/Vector3.h"
+using G3D::Vector3;
class ByteBuffer;
-namespace G3D
-{
- class Vector3;
-}
+class WorldPacket;
namespace Movement
{
- using G3D::Vector3;
-
class MoveSpline;
class PacketBuilder
{
- static void WriteCommonMonsterMovePart(const MoveSpline& mov, ByteBuffer& data);
+ static void WriteCommonMonsterMovePart(const MoveSpline& mov, WorldPacket& data);
public:
- static void WriteMonsterMove(const MoveSpline& mov, ByteBuffer& data);
+ static void WriteMonsterMove(const MoveSpline& mov, WorldPacket& data);
static void WriteStopMovement(Vector3 const& loc, uint32 splineId, ByteBuffer& data);
- static void WriteCreate(const MoveSpline& mov, ByteBuffer& data);
+ static void WriteCreateBits(MoveSpline const& moveSpline, ByteBuffer& data);
+ static void WriteCreateData(MoveSpline const& moveSpline, ByteBuffer& data);
};
}
#endif // TRINITYSERVER_PACKET_BUILDER_H
diff --git a/src/server/game/Movement/Spline/MovementTypedefs.h b/src/server/game/Movement/Spline/MovementTypedefs.h
index 635c43757be..134e7a45425 100644
--- a/src/server/game/Movement/Spline/MovementTypedefs.h
+++ b/src/server/game/Movement/Spline/MovementTypedefs.h
@@ -71,6 +71,8 @@ namespace Movement
extern double gravity;
extern UInt32Counter splineIdGen;
+ extern std::string MovementFlags_ToString(uint32 flags);
+ extern std::string MovementFlagsExtra_ToString(uint32 flags);
}
#endif // TRINITYSERVER_TYPEDEFS_H
diff --git a/src/server/game/Movement/Spline/MovementUtil.cpp b/src/server/game/Movement/Spline/MovementUtil.cpp
index 375859263ab..f5bdba378d1 100644
--- a/src/server/game/Movement/Spline/MovementUtil.cpp
+++ b/src/server/game/Movement/Spline/MovementUtil.cpp
@@ -98,82 +98,86 @@ namespace Movement
STR(Pitch_Up ), // 0x00000040,
STR(Pitch_Down ), // 0x00000080,
- STR(Walk ), // 0x00000100, // Walking
- STR(Ontransport ), // 0x00000200,
- STR(Levitation ), // 0x00000400,
- STR(Root ), // 0x00000800,
- STR(Falling ), // 0x00001000,
- STR(Fallingfar ), // 0x00002000,
- STR(Pendingstop ), // 0x00004000,
- STR(PendingSTRafestop ), // 0x00008000,
- STR(Pendingforward ), // 0x00010000,
- STR(Pendingbackward ), // 0x00020000,
- STR(PendingSTRafeleft ), // 0x00040000,
- STR(PendingSTRaferight ), // 0x00080000,
- STR(Pendingroot ), // 0x00100000,
- STR(Swimming ), // 0x00200000, // Appears With Fly Flag Also
- STR(Ascending ), // 0x00400000, // Swim Up Also
- STR(Descending ), // 0x00800000, // Swim Down Also
- STR(Can_Fly ), // 0x01000000, // Can Fly In 3.3?
- STR(Flying ), // 0x02000000, // Actual Flying Mode
- STR(Spline_Elevation ), // 0x04000000, // Used For Flight Paths
- STR(Spline_Enabled ), // 0x08000000, // Used For Flight Paths
- STR(Waterwalking ), // 0x10000000, // Prevent Unit From Falling Through Water
- STR(Safe_Fall ), // 0x20000000, // Active Rogue Safe Fall Spell (Passive)
- STR(Hover ), // 0x40000000
- STR(Unknown13 ), // 0x80000000
- STR(Unk1 ),
- STR(Unk2 ),
- STR(Unk3 ),
- STR(Fullspeedturning ),
- STR(Fullspeedpitching ),
- STR(Allow_Pitching ),
- STR(Unk4 ),
- STR(Unk5 ),
- STR(Unk6 ),
- STR(Unk7 ),
- STR(Interp_Move ),
- STR(Interp_Turning ),
- STR(Interp_Pitching ),
- STR(Unk8 ),
- STR(Unk9 ),
- STR(Unk10 ),
+ STR(Walking ), // 0x00000100, // Walking
+ STR(DisableGravity ), // 0x00000200,
+ STR(Root ), // 0x00000400,
+ STR(Falling ), // 0x00000800,
+ STR(FallingFar ), // 0x00001000,
+ STR(PendingStop ), // 0x00002000,
+ STR(PendingStrafeStop ), // 0x00004000,
+ STR(PendingForward ), // 0x00008000,
+ STR(PendingBackward ), // 0x00010000,
+ STR(PendingStrafeLeft ), // 0x00020000,
+ STR(PendingStrafeRight ), // 0x00040000,
+ STR(PendingRoot ), // 0x00080000,
+ STR(Swimming ), // 0x00100000, // Appears With Fly Flag Also
+ STR(Ascending ), // 0x00200000, // Swim Up Also
+ STR(Descending ), // 0x00400000, // Swim Down Also
+ STR(Can_Fly ), // 0x00800000, // Can Fly In 3.3?
+ STR(Flying ), // 0x01000000, // Actual Flying Mode
+ STR(Spline_Elevation ), // 0x02000000, // Used For Flight Paths
+ STR(Waterwalking ), // 0x04000000, // Prevent Unit From Falling Through Water
+ STR(Safe_Fall ), // 0x08000000, // Active Rogue Safe Fall Spell (Passive)
+ STR(Hover ), // 0x10000000
+ STR(Local_Dirty ), // 0x20000000
+ STR(None31 ), // 0x40000000
+ STR(None32 ), // 0x80000000
+ };
+
+ char const* g_MovementFlagExtra_names[] =
+ {
+ STR(NoStrafe ),
+ STR(NoJump ),
+ STR(FullSpeedTurning ),
+ STR(FullSpeedPitching ),
+ STR(Allow_Pitching ),
+ STR(Unk6 ),
+ STR(Unk7 ),
+ STR(Unk8 ),
+ STR(Unk9 ),
+ STR(Unk10 ),
+ STR(Unk11 ),
+ STR(Unk12 ),
+ STR(Unk13 ),
+ STR(Interpolated_Movement),
+ STR(Interpolated_Turning ),
+ STR(Interpolated_Pitching),
};
char const* g_SplineFlag_names[32] =
{
- STR(AnimBit1 ), // 0x00000001,
- STR(AnimBit2 ), // 0x00000002,
- STR(AnimBit3 ), // 0x00000004,
- STR(AnimBit4 ), // 0x00000008,
- STR(AnimBit5 ), // 0x00000010,
- STR(AnimBit6 ), // 0x00000020,
- STR(AnimBit7 ), // 0x00000040,
- STR(AnimBit8 ), // 0x00000080,
- STR(Done ), // 0x00000100,
- STR(Falling ), // 0x00000200, // Not Compartible With Trajectory Movement
- STR(No_Spline ), // 0x00000400,
- STR(Trajectory ), // 0x00000800, // Not Compartible With Fall Movement
- STR(Walkmode ), // 0x00001000,
- STR(Flying ), // 0x00002000, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation
- STR(Knockback ), // 0x00004000, // Model Orientation Fixed
- STR(Final_Point ), // 0x00008000,
- STR(Final_Target ), // 0x00010000,
- STR(Final_Angle ), // 0x00020000,
- STR(Catmullrom ), // 0x00040000, // Used Catmullrom Interpolation Mode
- STR(Cyclic ), // 0x00080000, // Movement By Cycled Spline
- STR(Enter_Cycle ), // 0x00100000, // Everytime Appears With Cyclic Flag In Monster Move Packet
- STR(Animation ), // 0x00200000, // Animationid (0...3), Uint32 Time, Not Compartible With Trajectory And Fall Movement
- STR(Unknown4 ), // 0x00400000, // Disables Movement By Path
- STR(Unknown5 ), // 0x00800000,
- STR(Unknown6 ), // 0x01000000,
- STR(Unknown7 ), // 0x02000000,
- STR(Unknown8 ), // 0x04000000,
- STR(OrientationInversed ), // 0x08000000, // Appears With Runmode Flag, Nodes ), // 1, Handles Orientation
- STR(Unknown10 ), // 0x10000000,
- STR(Unknown11 ), // 0x20000000,
- STR(Unknown12 ), // 0x40000000,
- STR(Unknown13 ), // 0x80000000,
+ STR(AnimBit1 ), // 0x00000001,
+ STR(AnimBit2 ), // 0x00000002,
+ STR(AnimBit3 ), // 0x00000004,
+ STR(Unknown0 ), // 0x00000008,
+ STR(FallingSlow ), // 0x00000010,
+ STR(Done ), // 0x00000020,
+ STR(Falling ), // 0x00000040, // Not Compartible With Trajectory Movement
+ STR(No_Spline ), // 0x00000080,
+ STR(Unknown2 ), // 0x00000100,
+ STR(Flying ), // 0x00000200, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation
+ STR(OrientationFixed ), // 0x00000400, // Model Orientation Fixed
+ STR(Catmullrom ), // 0x00000800, // Used Catmullrom Interpolation Mode
+ STR(Cyclic ), // 0x00001000, // Movement By Cycled Spline
+ STR(Enter_Cycle ), // 0x00002000, // Everytime Appears With Cyclic Flag In Monster Move Packet
+ STR(Frozen ), // 0x00004000,
+ STR(TransportEnter ), // 0x00008000
+ STR(TransportExit ), // 0x00010000
+ STR(Unknown3 ), // 0x00020000,
+ STR(Unknown4 ), // 0x00040000,
+ STR(OrientationInversed), // 0x00080000, // Appears With Runmode Flag, Nodes ), // 1, Handles Orientation
+ STR(SmoothGroundPath ), // 0x00100000,
+ STR(Walkmode ), // 0x00200000,
+ STR(UncompressedPath ), // 0x00400000,
+ STR(Unknown6 ), // 0x00800000,
+ STR(Animation ), // 0x01000000, // Animationid (0...3), Uint32 Time, Not Compartible With Trajectory And Fall Movement
+ STR(Parabolic ), // 0x02000000, // Not Compartible With Fall Movement
+ STR(Final_Point ), // 0x04000000,
+ STR(Final_Target ), // 0x08000000,
+ STR(Final_Angle ), // 0x10000000,
+ STR(Unknown7 ), // 0x20000000,
+ STR(Unknown8 ), // 0x40000000,
+ STR(Unknown9 ), // 0x80000000,
};
template<class Flags, int N>
@@ -192,4 +196,18 @@ namespace Movement
print_flags(raw(), g_SplineFlag_names, str);
return str;
}
+
+ std::string MovementFlags_ToString(uint32 flags)
+ {
+ std::string str;
+ print_flags(flags, g_MovementFlag_names, str);
+ return str;
+ }
+
+ std::string MovementFlagsExtra_ToString(uint32 flags)
+ {
+ std::string str;
+ print_flags(flags, g_MovementFlagExtra_names, str);
+ return str;
+ }
}
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.h b/src/server/game/OutdoorPvP/OutdoorPvP.h
index 9a7cc92c2ed..577d70021a6 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.h
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.h
@@ -30,11 +30,10 @@ enum OutdoorPvPTypes
OUTDOOR_PVP_NA = 2,
OUTDOOR_PVP_TF = 3,
OUTDOOR_PVP_ZM = 4,
- OUTDOOR_PVP_SI = 5,
- OUTDOOR_PVP_EP = 6
+ OUTDOOR_PVP_SI = 5
};
-#define MAX_OUTDOORPVP_TYPES 7
+#define MAX_OUTDOORPVP_TYPES 6
enum ObjectiveStates
{
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index a26b14af4b7..7c089eee07b 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -19,20 +19,21 @@
#include "QuestDef.h"
#include "Player.h"
#include "World.h"
+#include "ObjectMgr.h"
Quest::Quest(Field* questRecord)
{
Id = questRecord[0].GetUInt32();
Method = questRecord[1].GetUInt8();
Level = questRecord[2].GetInt16();
- MinLevel = questRecord[3].GetUInt8();
- MaxLevel = questRecord[4].GetUInt8();
+ MinLevel = uint32(questRecord[3].GetInt16());
+ MaxLevel = uint32(questRecord[4].GetInt16());
ZoneOrSort = questRecord[5].GetInt16();
Type = questRecord[6].GetUInt16();
SuggestedPlayers = questRecord[7].GetUInt8();
LimitTime = questRecord[8].GetUInt32();
RequiredClasses = questRecord[9].GetUInt16();
- RequiredRaces = questRecord[10].GetUInt16();
+ RequiredRaces = questRecord[10].GetUInt32();
RequiredSkillId = questRecord[11].GetUInt16();
RequiredSkillPoints = questRecord[12].GetUInt16();
RequiredFactionId1 = questRecord[13].GetUInt16();
@@ -61,91 +62,117 @@ Quest::Quest(Field* questRecord)
SourceSpellid = questRecord[36].GetUInt32();
Flags = questRecord[37].GetUInt32();
SpecialFlags = questRecord[38].GetUInt8();
- RewardTitleId = questRecord[39].GetUInt8();
- RequiredPlayerKills = questRecord[40].GetUInt8();
- RewardTalents = questRecord[41].GetUInt8();
- RewardArenaPoints = questRecord[42].GetUInt16();
-
+ MinimapTargetMark = questRecord[39].GetUInt8();
+ RewardTitleId = questRecord[40].GetUInt8();
+ RequiredPlayerKills = questRecord[41].GetUInt8();
+ RewardTalents = questRecord[42].GetUInt8();
+ RewardArenaPoints = questRecord[43].GetUInt16();
+ RewardSkillId = questRecord[44].GetUInt16();
+ RewardSkillPoints = questRecord[45].GetUInt8();
+ RewardReputationMask = questRecord[46].GetUInt8();
+ QuestGiverPortrait = questRecord[47].GetUInt32();
+ QuestTurnInPortrait = questRecord[48].GetUInt32();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
- RewardItemId[i] = questRecord[43+i].GetUInt32();
+ RewardItemId[i] = questRecord[49+i].GetUInt32();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
- RewardItemIdCount[i] = questRecord[47+i].GetUInt16();
+ RewardItemIdCount[i] = questRecord[53+i].GetUInt16();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- RewardChoiceItemId[i] = questRecord[51+i].GetUInt32();
+ RewardChoiceItemId[i] = questRecord[57+i].GetUInt32();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- RewardChoiceItemCount[i] = questRecord[57+i].GetUInt16();
+ RewardChoiceItemCount[i] = questRecord[63+i].GetUInt16();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewardFactionId[i] = questRecord[63+i].GetUInt16();
+ RewardFactionId[i] = questRecord[69+i].GetUInt16();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewardFactionValueId[i] = questRecord[68+i].GetInt32();
+ RewardFactionValueId[i] = questRecord[74+i].GetInt32();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewardFactionValueIdOverride[i] = questRecord[73+i].GetInt32();
-
- PointMapId = questRecord[78].GetUInt16();
- PointX = questRecord[79].GetFloat();
- PointY = questRecord[80].GetFloat();
- PointOption = questRecord[81].GetUInt32();
- Title = questRecord[82].GetString();
- Objectives = questRecord[83].GetString();
- Details = questRecord[84].GetString();
- EndText = questRecord[85].GetString();
- OfferRewardText = questRecord[86].GetString();
- RequestItemsText = questRecord[87].GetString();
- CompletedText = questRecord[88].GetString();
+ RewardFactionValueIdOverride[i] = questRecord[79+i].GetInt32();
+
+ PointMapId = questRecord[84].GetUInt16();
+ PointX = questRecord[85].GetFloat();
+ PointY = questRecord[86].GetFloat();
+ PointOption = questRecord[87].GetUInt32();
+ Title = questRecord[88].GetString();
+ Objectives = questRecord[89].GetString();
+ Details = questRecord[90].GetString();
+ EndText = questRecord[91].GetString();
+ CompletedText = questRecord[92].GetString();
+ OfferRewardText = questRecord[93].GetString();
+ RequestItemsText = questRecord[94].GetString();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- RequiredNpcOrGo[i] = questRecord[89+i].GetInt32();
+ RequiredNpcOrGo[i] = questRecord[95+i].GetInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- RequiredNpcOrGoCount[i] = questRecord[93+i].GetUInt16();
+ RequiredNpcOrGoCount[i] = questRecord[99+i].GetUInt16();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- RequiredSourceItemId[i] = questRecord[97+i].GetUInt32();
+ RequiredSourceItemId[i] = questRecord[103+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- RequiredSourceItemCount[i] = questRecord[101+i].GetUInt16();
+ RequiredSourceItemCount[i] = questRecord[107+i].GetUInt16();
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
- RequiredItemId[i] = questRecord[105+i].GetUInt32();
+ RequiredItemId[i] = questRecord[111+i].GetUInt32();
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
- RequiredItemCount[i] = questRecord[111+i].GetUInt16();
+ RequiredItemCount[i] = questRecord[117+i].GetUInt16();
- // int8 Unknown0 = questRecord[117].GetUInt8();
+ RequiredSpell = questRecord[123].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ObjectiveText[i] = questRecord[118+i].GetString();
+ ObjectiveText[i] = questRecord[124+i].GetString();
+
+ for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ RewardCurrencyId[i] = questRecord[128+i].GetUInt16();
+
+ for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ RewardCurrencyCount[i] = questRecord[132+i].GetUInt8();
+
+ for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ RequiredCurrencyId[i] = questRecord[136+i].GetUInt16();
+
+ for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ RequiredCurrencyCount[i] = questRecord[140+i].GetUInt8();
+
+ QuestGiverTextWindow = questRecord[144].GetString();
+ QuestGiverTargetName = questRecord[145].GetString();
+ QuestTurnTextWindow = questRecord[146].GetString();
+ QuestTurnTargetName = questRecord[147].GetString();
+ SoundAccept = questRecord[148].GetUInt16();
+ SoundTurnIn = questRecord[149].GetUInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- DetailsEmote[i] = questRecord[122+i].GetUInt16();
+ DetailsEmote[i] = questRecord[150+i].GetUInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- DetailsEmoteDelay[i] = questRecord[126+i].GetUInt32();
+ DetailsEmoteDelay[i] = questRecord[154+i].GetUInt32();
- EmoteOnIncomplete = questRecord[130].GetUInt16();
- EmoteOnComplete = questRecord[131].GetUInt16();
+ EmoteOnIncomplete = questRecord[158].GetUInt16();
+ EmoteOnComplete = questRecord[159].GetUInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- OfferRewardEmote[i] = questRecord[132+i].GetInt16();
+ OfferRewardEmote[i] = questRecord[160+i].GetInt16();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- OfferRewardEmoteDelay[i] = questRecord[136+i].GetInt32();
+ OfferRewardEmoteDelay[i] = questRecord[164+i].GetInt32();
- //int32 VerifiedBuild = questRecord[140].GetInt32();
+ //int32 VerifiedBuild = questRecord[168].GetInt32();
if (SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT)
Flags |= QUEST_FLAGS_AUTO_ACCEPT;
_reqItemsCount = 0;
- _reqCreatureOrGOcount = 0;
+ _reqNpcOrGoCount = 0;
_rewItemsCount = 0;
_rewChoiceItemsCount = 0;
+ _rewCurrencyCount = 0;
+ _reqCurrencyCount = 0;
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
if (RequiredItemId[i])
@@ -153,7 +180,7 @@ Quest::Quest(Field* questRecord)
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
if (RequiredNpcOrGo[i])
- ++_reqCreatureOrGOcount;
+ ++_reqNpcOrGoCount;
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
if (RewardItemId[i])
@@ -162,6 +189,14 @@ Quest::Quest(Field* questRecord)
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
if (RewardChoiceItemId[i])
++_rewChoiceItemsCount;
+
+ for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ if (RewardCurrencyId[i])
+ ++_rewCurrencyCount;
+
+ for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
+ if (RequiredCurrencyId[i])
+ ++_reqCurrencyCount;
}
uint32 Quest::XPValue(Player* player) const
@@ -203,6 +238,79 @@ int32 Quest::GetRewOrReqMoney() const
return int32(RewardOrRequiredMoney * sWorld->getRate(RATE_DROP_MONEY));
}
+void Quest::BuildExtraQuestInfo(WorldPacket& data, Player* player) const
+{
+ data << uint32(GetRewChoiceItemsCount());
+ for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
+ data << uint32(RewardChoiceItemId[i]);
+ for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
+ data << uint32(RewardChoiceItemCount[i]);
+ for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
+ {
+ if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardChoiceItemId[i]))
+ data << uint32(itemTemplate->DisplayInfoID);
+ else
+ data << uint32(0);
+ }
+
+ data << uint32(GetReqItemsCount());
+ for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ data << uint32(RewardItemId[i]);
+ for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ data << uint32(RewardItemIdCount[i]);
+ for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ {
+ if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardItemId[i]))
+ data << uint32(itemTemplate->DisplayInfoID);
+ else
+ data << uint32(0);
+ }
+
+ data << uint32(GetRewOrReqMoney());
+ data << uint32(XPValue(player) * sWorld->getRate(RATE_XP_QUEST));
+
+ data << uint32(GetCharTitleId());
+ data << uint32(0); // unk
+ data << float(0.0f); // unk
+ data << uint32(GetBonusTalents());
+ data << uint32(0); // unk
+ data << uint32(GetRewardReputationMask());
+
+ /* Pre cata struct, some of these unks might be the missing values in cata:
+ // rewarded honor points. Multiply with 10 to satisfy client
+ data << 10 * Trinity::Honor::hk_honor_at_level(_session->GetPlayer()->getLevel(), quest->GetRewHonorMultiplier());
+ data << float(0); // unk, honor multiplier?
+ data << uint32(0x08); // unused by client?
+ data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)
+ data << int32(quest->GetRewSpellCast()); // casted spell
+ data << uint32(0); // unknown
+ data << uint32(quest->GetBonusTalents()); // bonus talents
+ data << uint32(quest->GetRewArenaPoints()); // arena points
+ data << uint32(0);
+ */
+
+ for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids
+ data << uint32(RewardFactionId[i]);
+
+ for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid in QuestFactionReward.dbc (zero based)?
+ data << int32(RewardFactionValueId[i]);
+
+ for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward reputation override?
+ data << uint32(RewardFactionValueIdOverride[i]);
+
+ data << uint32(GetRewSpell());
+ data << uint32(GetRewSpellCast());
+
+ for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ data << uint32(RewardCurrencyId[i]);
+
+ for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
+ data << uint32(RewardCurrencyCount[i]);
+
+ data << uint32(GetRewardSkillId());
+ data << uint32(GetRewardSkillPoints());
+}
+
uint32 Quest::GetRewMoneyMaxLevel() const
{
if (HasFlag(QUEST_FLAGS_NO_MONEY_FROM_XP))
@@ -218,7 +326,7 @@ bool Quest::IsAutoAccept() const
bool Quest::IsAutoComplete() const
{
- return !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) && (Method == 0 || HasFlag(QUEST_FLAGS_AUTOCOMPLETE));
+ return !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) && Method == 0;
}
bool Quest::IsRaidQuest(Difficulty difficulty) const
@@ -253,7 +361,7 @@ uint32 Quest::CalculateHonorGain(uint8 level) const
uint32 honor = 0;
- if (GetRewHonorAddition() > 0 || GetRewHonorMultiplier() > 0.0f)
+ /*if (GetRewHonorAddition() > 0 || GetRewHonorMultiplier() > 0.0f)
{
// values stored from 0.. for 1...
TeamContributionPointsEntry const* tc = sTeamContributionPointsStore.LookupEntry(level);
@@ -262,7 +370,7 @@ uint32 Quest::CalculateHonorGain(uint8 level) const
honor = uint32(tc->value * GetRewHonorMultiplier() * 0.1f);
honor += GetRewHonorAddition();
- }
+ }*/
return honor;
}
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 350ef104ed4..79b7a4b428e 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -22,6 +22,7 @@
#include "Define.h"
#include "DatabaseEnv.h"
#include "SharedDefines.h"
+#include "WorldPacket.h"
#include "DBCEnums.h"
#include <string>
@@ -42,6 +43,8 @@ class ObjectMgr;
#define QUEST_REPUTATIONS_COUNT 5
#define QUEST_EMOTE_COUNT 4
#define QUEST_PVP_KILL_SLOT 0
+#define QUEST_REWARD_CURRENCY_COUNT 4
+#define QUEST_REQUIRED_CURRENCY_COUNT 4
enum QuestFailedReason
{
@@ -108,25 +111,25 @@ enum QuestStatus
enum QuestGiverStatus
{
- DIALOG_STATUS_NONE = 0,
- DIALOG_STATUS_UNAVAILABLE = 1,
- DIALOG_STATUS_LOW_LEVEL_AVAILABLE = 2,
- DIALOG_STATUS_LOW_LEVEL_REWARD_REP = 3,
- DIALOG_STATUS_LOW_LEVEL_AVAILABLE_REP = 4,
- DIALOG_STATUS_INCOMPLETE = 5,
- DIALOG_STATUS_REWARD_REP = 6,
- DIALOG_STATUS_AVAILABLE_REP = 7,
- DIALOG_STATUS_AVAILABLE = 8,
- DIALOG_STATUS_REWARD2 = 9, // no yellow dot on minimap
- DIALOG_STATUS_REWARD = 10, // yellow dot on minimap
+ DIALOG_STATUS_NONE = 0x000,
+ DIALOG_STATUS_UNK = 0x001,
+ DIALOG_STATUS_UNAVAILABLE = 0x002,
+ DIALOG_STATUS_LOW_LEVEL_AVAILABLE = 0x004,
+ DIALOG_STATUS_LOW_LEVEL_REWARD_REP = 0x008,
+ DIALOG_STATUS_LOW_LEVEL_AVAILABLE_REP = 0x010,
+ DIALOG_STATUS_INCOMPLETE = 0x020,
+ DIALOG_STATUS_REWARD_REP = 0x040,
+ DIALOG_STATUS_AVAILABLE_REP = 0x080,
+ DIALOG_STATUS_AVAILABLE = 0x100,
+ DIALOG_STATUS_REWARD2 = 0x200, // no yellow dot on minimap
+ DIALOG_STATUS_REWARD = 0x400, // yellow dot on minimap
// Custom value meaning that script call did not return any valid quest status
- DIALOG_STATUS_SCRIPTED_NO_STATUS = 0x1000,
+ DIALOG_STATUS_SCRIPTED_NO_STATUS = 0x1000
};
enum QuestFlags
{
- // Flags used at server and sent to client
QUEST_FLAGS_NONE = 0x00000000,
QUEST_FLAGS_STAY_ALIVE = 0x00000001, // Not used currently
QUEST_FLAGS_PARTY_ACCEPT = 0x00000002, // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT
@@ -144,11 +147,15 @@ enum QuestFlags
QUEST_FLAGS_FLAGS_PVP = 0x00002000, // Having this quest in log forces PvP flag
QUEST_FLAGS_UNAVAILABLE = 0x00004000, // Used on quests that are not generically available
QUEST_FLAGS_WEEKLY = 0x00008000,
- QUEST_FLAGS_AUTOCOMPLETE = 0x00010000, // auto complete
+ QUEST_FLAGS_AUTOCOMPLETE = 0x00010000, // Quests with this flag player submit automatically by special button in player gui
QUEST_FLAGS_DISPLAY_ITEM_IN_TRACKER = 0x00020000, // Displays usable item in quest tracker
QUEST_FLAGS_OBJ_TEXT = 0x00040000, // use Objective text as Complete text
QUEST_FLAGS_AUTO_ACCEPT = 0x00080000, // The client recognizes this flag as auto-accept. However, NONE of the current quests (3.3.5a) have this flag. Maybe blizz used to use it, or will use it in the future.
-
+ QUEST_FLAGS_UNK1 = 0x00100000, //
+ QUEST_FLAGS_AUTO_TAKE = 0x00200000, // Automatically suggestion of accepting quest. Not from npc.
+ //QUEST_FLAGS_UNK2 = 0x00400000,
+ //QUEST_FLAGS_UNK3 = 0x00800000, // Found in quest 14069
+ //QUEST_FLAGS_UNK4 = 0x01000000,
// ... 4.x added flags up to 0x80000000 - all unknown for now
};
@@ -185,6 +192,11 @@ struct QuestLocale
StringVector EndText;
StringVector CompletedText;
std::vector< StringVector > ObjectiveText;
+ // new on 4.x
+ StringVector QuestGiverTextWindow;
+ StringVector QuestGiverTargetName;
+ StringVector QuestTurnTextWindow;
+ StringVector QuestTurnTargetName;
};
// This Quest class provides a convenient way to access a few pretotaled (cached) quest details,
@@ -244,6 +256,10 @@ class Quest
std::string const& GetRequestItemsText() const { return RequestItemsText; }
std::string const& GetEndText() const { return EndText; }
std::string const& GetCompletedText() const { return CompletedText; }
+ std::string const& GetQuestGiverTextWindow() const { return QuestGiverTextWindow; }
+ std::string const& GetQuestGiverTargetName() const { return QuestGiverTargetName; }
+ std::string const& GetQuestTurnTextWindow() const { return QuestTurnTextWindow; }
+ std::string const& GetQuestTurnTargetName() const { return QuestTurnTargetName; }
int32 GetRewOrReqMoney() const;
uint32 GetRewHonorAddition() const { return RewardHonor; }
float GetRewHonorMultiplier() const { return RewardHonorMultiplier; }
@@ -256,12 +272,22 @@ class Quest
float GetPointX() const { return PointX; }
float GetPointY() const { return PointY; }
uint32 GetPointOpt() const { return PointOption; }
+ uint32 GetRequiredSpell() const { return RequiredSpell; }
+ uint32 GetSoundAccept() const { return SoundAccept; }
+ uint32 GetSoundTurnIn() const { return SoundTurnIn; }
uint32 GetIncompleteEmote() const { return EmoteOnIncomplete; }
uint32 GetCompleteEmote() const { return EmoteOnComplete; }
bool IsRepeatable() const { return SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE; }
bool IsAutoAccept() const;
bool IsAutoComplete() const;
uint32 GetFlags() const { return Flags; }
+ uint32 GetSpecialFlags() const { return SpecialFlags; }
+ uint32 GetMinimapTargetMark() const { return MinimapTargetMark; }
+ uint32 GetRewardSkillId() const { return RewardSkillId; }
+ uint32 GetRewardSkillPoints() const { return RewardSkillPoints; }
+ uint32 GetRewardReputationMask() const { return RewardReputationMask; }
+ uint32 GetQuestGiverPortrait() const { return QuestGiverPortrait; }
+ uint32 GetQuestTurnInPortrait() const { return QuestTurnInPortrait; }
bool IsDaily() const { return (Flags & QUEST_FLAGS_DAILY) != 0; }
bool IsWeekly() const { return (Flags & QUEST_FLAGS_WEEKLY) != 0; }
bool IsMonthly() const { return (SpecialFlags & QUEST_SPECIAL_FLAGS_MONTHLY) != 0; }
@@ -291,11 +317,20 @@ class Quest
uint32 DetailsEmoteDelay[QUEST_EMOTE_COUNT];
uint32 OfferRewardEmote[QUEST_EMOTE_COUNT];
uint32 OfferRewardEmoteDelay[QUEST_EMOTE_COUNT];
+ // 4.x
+ uint32 RewardCurrencyId[QUEST_REWARD_CURRENCY_COUNT];
+ uint32 RewardCurrencyCount[QUEST_REWARD_CURRENCY_COUNT];
+ uint32 RequiredCurrencyId[QUEST_REQUIRED_CURRENCY_COUNT];
+ uint32 RequiredCurrencyCount[QUEST_REQUIRED_CURRENCY_COUNT];
uint32 GetReqItemsCount() const { return _reqItemsCount; }
- uint32 GetReqCreatureOrGOcount() const { return _reqCreatureOrGOcount; }
+ uint32 GetReqCreatureOrGOcount() const { return _reqNpcOrGoCount; }
uint32 GetRewChoiceItemsCount() const { return _rewChoiceItemsCount; }
uint32 GetRewItemsCount() const { return _rewItemsCount; }
+ uint32 GetRewCurrencyCount() const { return _rewCurrencyCount; }
+ uint32 GetReqCurrencyCount() const { return _reqCurrencyCount; }
+
+ void BuildExtraQuestInfo(WorldPacket& data, Player* player) const;
typedef std::vector<int32> PrevQuests;
PrevQuests prevQuests;
@@ -305,9 +340,11 @@ class Quest
// cached data
private:
uint32 _reqItemsCount;
- uint32 _reqCreatureOrGOcount;
+ uint32 _reqNpcOrGoCount;
uint32 _rewChoiceItemsCount;
uint32 _rewItemsCount;
+ uint32 _rewCurrencyCount;
+ uint32 _reqCurrencyCount;
// table data
protected:
@@ -366,6 +403,20 @@ class Quest
uint32 PointOption;
uint32 EmoteOnIncomplete;
uint32 EmoteOnComplete;
+ // new in 4.x
+ uint32 MinimapTargetMark;
+ uint32 RewardSkillId;
+ uint32 RewardSkillPoints;
+ uint32 RewardReputationMask;
+ uint32 QuestGiverPortrait;
+ uint32 QuestTurnInPortrait;
+ uint32 RequiredSpell;
+ std::string QuestGiverTextWindow;
+ std::string QuestGiverTargetName;
+ std::string QuestTurnTextWindow;
+ std::string QuestTurnTargetName;
+ uint32 SoundAccept;
+ uint32 SoundTurnIn;
uint32 SpecialFlags; // custom flags, not sniffed/WDB
};
diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp
index f19d6d754cf..b136e6893cd 100644
--- a/src/server/game/Reputation/ReputationMgr.cpp
+++ b/src/server/game/Reputation/ReputationMgr.cpp
@@ -24,6 +24,7 @@
#include "World.h"
#include "ObjectMgr.h"
#include "ScriptMgr.h"
+#include "Opcodes.h"
#include "WorldSession.h"
const int32 ReputationMgr::PointsInRank[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000};
@@ -198,7 +199,7 @@ void ReputationMgr::SendState(FactionState const* faction)
void ReputationMgr::SendInitialReputations()
{
- uint8 count = 128;
+ uint16 count = 256;
WorldPacket data(SMSG_INITIALIZE_FACTIONS, 4 + count * 5);
data << uint32(count);
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 862b8dffddb..c9b65c3a046 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -49,6 +49,7 @@ void AddSC_account_commandscript();
void AddSC_achievement_commandscript();
void AddSC_arena_commandscript();
void AddSC_ban_commandscript();
+void AddSC_battlenet_account_commandscript();
void AddSC_bf_commandscript();
void AddSC_cast_commandscript();
void AddSC_character_commandscript();
@@ -106,6 +107,10 @@ void AddSC_boss_balinda();
void AddSC_boss_drekthar();
void AddSC_boss_galvangar();
void AddSC_boss_vanndar();
+void AddSC_boss_alizabal(); //Baradin Hold
+void AddSC_boss_occuthar();
+void AddSC_boss_pit_lord_argaloth();
+void AddSC_instance_baradin_hold();
void AddSC_blackrock_depths(); //Blackrock Depths
void AddSC_boss_ambassador_flamelash();
void AddSC_boss_anubshiah();
@@ -242,24 +247,19 @@ void AddSC_boss_halazzi();
void AddSC_boss_hex_lord_malacrass();
void AddSC_boss_janalai();
void AddSC_boss_nalorakk();
-void AddSC_boss_zuljin();
+void AddSC_boss_daakara();
void AddSC_instance_zulaman();
void AddSC_zulaman();
-void AddSC_boss_jeklik(); //Zul'Gurub
-void AddSC_boss_venoxis();
-void AddSC_boss_marli();
-void AddSC_boss_mandokir();
-void AddSC_boss_gahzranka();
-void AddSC_boss_thekal();
-void AddSC_boss_arlokk();
-void AddSC_boss_jindo();
-void AddSC_boss_hakkar();
-void AddSC_boss_grilek();
+void AddSC_boss_grilek(); // Zul'Gurub
void AddSC_boss_hazzarah();
+void AddSC_boss_jindo_the_godbreaker();
+void AddSC_boss_kilnara();
+void AddSC_boss_mandokir();
void AddSC_boss_renataki();
+void AddSC_boss_venoxis();
void AddSC_boss_wushoolay();
+void AddSC_boss_zanzil();
void AddSC_instance_zulgurub();
-
//void AddSC_alterac_mountains();
void AddSC_arathi_highlands();
void AddSC_blasted_lands();
@@ -351,12 +351,17 @@ void AddSC_instance_wailing_caverns();
void AddSC_boss_zum_rah(); //Zul'Farrak
void AddSC_zulfarrak();
void AddSC_instance_zulfarrak();
+void AddSC_instance_halls_of_origination();
+void AddSC_boss_temple_guardian_anhuur();
+void AddSC_boss_earthrager_ptah();
+void AddSC_boss_anraphet();
+void AddSC_instance_firelands();
+void AddSC_boss_alysrazor();
void AddSC_ashenvale();
void AddSC_azshara();
void AddSC_azuremyst_isle();
void AddSC_bloodmyst_isle();
-void AddSC_boss_azuregos();
void AddSC_darkshore();
void AddSC_desolace();
void AddSC_durotar();
@@ -671,6 +676,9 @@ void AddSC_shattrath_city();
void AddSC_terokkar_forest();
void AddSC_zangarmarsh();
+// Maelstrom
+void AddSC_kezan();
+
// Events
void AddSC_event_childrens_week();
@@ -685,7 +693,6 @@ void AddSC_shaman_pet_scripts();
// battlegrounds
// outdoor pvp
-void AddSC_outdoorpvp_ep();
void AddSC_outdoorpvp_hp();
void AddSC_outdoorpvp_na();
void AddSC_outdoorpvp_si();
@@ -710,6 +717,7 @@ void AddScripts()
AddKalimdorScripts();
AddOutlandScripts();
AddNorthrendScripts();
+ AddMaelstromScripts();
AddEventScripts();
AddPetScripts();
AddBattlegroundScripts();
@@ -752,6 +760,7 @@ void AddCommandScripts()
AddSC_achievement_commandscript();
AddSC_arena_commandscript();
AddSC_ban_commandscript();
+ AddSC_battlenet_account_commandscript();
AddSC_bf_commandscript();
AddSC_cast_commandscript();
AddSC_character_commandscript();
@@ -818,6 +827,10 @@ void AddEasternKingdomsScripts()
AddSC_boss_drekthar();
AddSC_boss_galvangar();
AddSC_boss_vanndar();
+ AddSC_boss_alizabal(); //Baradin Hold
+ AddSC_boss_occuthar();
+ AddSC_boss_pit_lord_argaloth();
+ AddSC_instance_baradin_hold();
AddSC_blackrock_depths(); //Blackrock Depths
AddSC_boss_ambassador_flamelash();
AddSC_boss_anubshiah();
@@ -954,22 +967,18 @@ void AddEasternKingdomsScripts()
AddSC_boss_hex_lord_malacrass();
AddSC_boss_janalai();
AddSC_boss_nalorakk();
- AddSC_boss_zuljin();
+ AddSC_boss_daakara();
AddSC_instance_zulaman();
AddSC_zulaman();
- AddSC_boss_jeklik(); //Zul'Gurub
- AddSC_boss_venoxis();
- AddSC_boss_marli();
- AddSC_boss_mandokir();
- AddSC_boss_gahzranka();
- AddSC_boss_thekal();
- AddSC_boss_arlokk();
- AddSC_boss_jindo();
- AddSC_boss_hakkar();
- AddSC_boss_grilek();
+ AddSC_boss_grilek(); // Zul'Gurub
AddSC_boss_hazzarah();
+ AddSC_boss_jindo_the_godbreaker();
+ AddSC_boss_kilnara();
+ AddSC_boss_mandokir();
AddSC_boss_renataki();
+ AddSC_boss_venoxis();
AddSC_boss_wushoolay();
+ AddSC_boss_zanzil();
AddSC_instance_zulgurub();
//AddSC_alterac_mountains();
@@ -1072,7 +1081,6 @@ void AddKalimdorScripts()
AddSC_azshara();
AddSC_azuremyst_isle();
AddSC_bloodmyst_isle();
- AddSC_boss_azuregos();
AddSC_darkshore();
AddSC_desolace();
AddSC_durotar();
@@ -1091,6 +1099,14 @@ void AddKalimdorScripts()
AddSC_thunder_bluff();
AddSC_ungoro_crater();
AddSC_winterspring();
+
+ AddSC_instance_halls_of_origination();
+ AddSC_boss_temple_guardian_anhuur();
+ AddSC_boss_earthrager_ptah();
+ AddSC_boss_anraphet();
+
+ AddSC_instance_firelands();
+ AddSC_boss_alysrazor();
#endif
}
@@ -1395,6 +1411,14 @@ void AddNorthrendScripts()
#endif
}
+
+void AddMaelstromScripts()
+{
+#ifdef SCRIPTS
+ AddSC_kezan();
+#endif
+}
+
void AddEventScripts()
{
#ifdef SCRIPTS
@@ -1417,7 +1441,6 @@ void AddPetScripts()
void AddOutdoorPvPScripts()
{
#ifdef SCRIPTS
- AddSC_outdoorpvp_ep();
AddSC_outdoorpvp_hp();
AddSC_outdoorpvp_na();
AddSC_outdoorpvp_si();
diff --git a/src/server/game/Scripting/ScriptLoader.h b/src/server/game/Scripting/ScriptLoader.h
index db4c5b0cf46..a68f78997b3 100644
--- a/src/server/game/Scripting/ScriptLoader.h
+++ b/src/server/game/Scripting/ScriptLoader.h
@@ -27,6 +27,7 @@ void AddEasternKingdomsScripts();
void AddKalimdorScripts();
void AddOutlandScripts();
void AddNorthrendScripts();
+void AddMaelstromScripts();
void AddEventScripts();
void AddPetScripts();
void AddBattlegroundScripts();
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 0d1983ab463..6d0be13c35e 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1187,7 +1187,7 @@ void ScriptMgr::OnPlayerTalentsReset(Player* player, bool noCost)
FOREACH_SCRIPT(PlayerScript)->OnTalentsReset(player, noCost);
}
-void ScriptMgr::OnPlayerMoneyChanged(Player* player, int32& amount)
+void ScriptMgr::OnPlayerMoneyChanged(Player* player, int64& amount)
{
FOREACH_SCRIPT(PlayerScript)->OnMoneyChanged(player, amount);
}
@@ -1359,12 +1359,12 @@ void ScriptMgr::OnGuildDisband(Guild* guild)
FOREACH_SCRIPT(GuildScript)->OnDisband(guild);
}
-void ScriptMgr::OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint32 &amount, bool isRepair)
+void ScriptMgr::OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint64 &amount, bool isRepair)
{
FOREACH_SCRIPT(GuildScript)->OnMemberWitdrawMoney(guild, player, amount, isRepair);
}
-void ScriptMgr::OnGuildMemberDepositMoney(Guild* guild, Player* player, uint32 &amount)
+void ScriptMgr::OnGuildMemberDepositMoney(Guild* guild, Player* player, uint64 &amount)
{
FOREACH_SCRIPT(GuildScript)->OnMemberDepositMoney(guild, player, amount);
}
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index 0b5813a7f58..104410a1345 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -60,7 +60,6 @@ class WorldPacket;
class WorldSocket;
class WorldObject;
-struct AchievementCriteriaData;
struct AuctionEntry;
struct ConditionSourceInfo;
struct Condition;
@@ -706,7 +705,7 @@ class PlayerScript : public UnitScript
virtual void OnTalentsReset(Player* /*player*/, bool /*noCost*/) { }
// Called when a player's money is modified (before the modification is done)
- virtual void OnMoneyChanged(Player* /*player*/, int32& /*amount*/) { }
+ virtual void OnMoneyChanged(Player* /*player*/, int64& /*amount*/) { }
// Called when a player gains XP (before anything is given)
virtual void OnGiveXP(Player* /*player*/, uint32& /*amount*/, Unit* /*victim*/) { }
@@ -826,10 +825,10 @@ class GuildScript : public ScriptObject
virtual void OnDisband(Guild* /*guild*/) { }
// Called when a guild member withdraws money from a guild bank.
- virtual void OnMemberWitdrawMoney(Guild* /*guild*/, Player* /*player*/, uint32& /*amount*/, bool /*isRepair*/) { }
+ virtual void OnMemberWitdrawMoney(Guild* /*guild*/, Player* /*player*/, uint64& /*amount*/, bool /*isRepair*/) { }
// Called when a guild member deposits money in a guild bank.
- virtual void OnMemberDepositMoney(Guild* /*guild*/, Player* /*player*/, uint32& /*amount*/) { }
+ virtual void OnMemberDepositMoney(Guild* /*guild*/, Player* /*player*/, uint64& /*amount*/) { }
// Called when a guild member moves an item in a guild bank.
virtual void OnItemMove(Guild* /*guild*/, Player* /*player*/, Item* /*pItem*/, bool /*isSrcBank*/, uint8 /*srcContainer*/, uint8 /*srcSlotId*/,
@@ -1052,7 +1051,7 @@ class ScriptMgr
void OnPlayerLevelChanged(Player* player, uint8 oldLevel);
void OnPlayerFreeTalentPointsChanged(Player* player, uint32 newPoints);
void OnPlayerTalentsReset(Player* player, bool noCost);
- void OnPlayerMoneyChanged(Player* player, int32& amount);
+ void OnPlayerMoneyChanged(Player* player, int64& amount);
void OnGivePlayerXP(Player* player, uint32& amount, Unit* victim);
void OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental);
void OnPlayerDuelRequest(Player* target, Player* challenger);
@@ -1092,8 +1091,8 @@ class ScriptMgr
void OnGuildInfoChanged(Guild* guild, const std::string& newInfo);
void OnGuildCreate(Guild* guild, Player* leader, const std::string& name);
void OnGuildDisband(Guild* guild);
- void OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint32 &amount, bool isRepair);
- void OnGuildMemberDepositMoney(Guild* guild, Player* player, uint32 &amount);
+ void OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint64 &amount, bool isRepair);
+ void OnGuildMemberDepositMoney(Guild* guild, Player* player, uint64 &amount);
void OnGuildItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId,
bool isDestBank, uint8 destContainer, uint8 destSlotId);
void OnGuildEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank);
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index ea02b83f2e8..cc5e9413b7a 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -16,1325 +16,1643 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- \ingroup u2w
-*/
-
#include "Opcodes.h"
#include "WorldSession.h"
+OpcodeTable opcodeTable;
+
+template<bool isInValidRange, bool isNonZero>
+void OpcodeTable::ValidateAndSetOpcode(uint16 /*opcode*/, char const* /*name*/, SessionStatus /*status*/, PacketProcessing /*processing*/, pOpcodeHandler /*handler*/)
+{
+ // if for some reason we are here, that means NUM_OPCODE_HANDLERS == 0 (or your compiler is broken)
+}
+
+template<>
+void OpcodeTable::ValidateAndSetOpcode<true, true>(uint16 opcode, char const* name, SessionStatus status, PacketProcessing processing, pOpcodeHandler handler)
+{
+ if (_internalTable[opcode] != NULL)
+ {
+ TC_LOG_ERROR("network", "Tried to override handler of %s with %s (opcode %u)", opcodeTable[opcode]->Name, name, opcode);
+ return;
+ }
+
+ _internalTable[opcode] = new OpcodeHandler(name, status, processing, handler);
+}
+
+template<>
+void OpcodeTable::ValidateAndSetOpcode<false, true>(uint16 opcode, char const* /*name*/, SessionStatus /*status*/, PacketProcessing /*processing*/, pOpcodeHandler /*handler*/)
+{
+ TC_LOG_ERROR("network", "Tried to set handler for an invalid opcode %d", opcode);
+}
+
+template<>
+void OpcodeTable::ValidateAndSetOpcode<true, false>(uint16 /*opcode*/, char const* name, SessionStatus /*status*/, PacketProcessing /*processing*/, pOpcodeHandler /*handler*/)
+{
+ TC_LOG_ERROR("network", "Opcode %s got value 0", name);
+}
+
/// Correspondence between opcodes and their names
-OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
+void OpcodeTable::Initialize()
{
- /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWorldTeleportOpcode },
- /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x00D*/ { "CMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x00E*/ { "SMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x01E*/ { "SMSG_REFER_A_FRIEND_EXPIRED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x032*/ { "SMSG_DESTRUCTIBLE_BUILDING_DAMAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCreateOpcode },
- /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharEnumOpcode },
- /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharDeleteOpcode },
- /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayerLoginOpcode },
- /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayerLogoutOpcode },
- /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutRequestOpcode },
- /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode },
- /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNameQueryOpcode },
- /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetNameQuery },
- /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryOpcode },
- /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleItemQuerySingleOpcode },
- /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePageTextQueryOpcode },
- /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestQueryOpcode },
- /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGameObjectQueryOpcode },
- /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCreatureQueryOpcode },
- /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoOpcode },
- /*0x063*/ { "SMSG_WHO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoisOpcode },
- /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleContactListOpcode },
- /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddFriendOpcode },
- /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelFriendOpcode },
- /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetContactNotesOpcode },
- /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddIgnoreOpcode },
- /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelIgnoreOpcode },
- /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteOpcode },
- /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupAcceptOpcode },
- /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupDeclineOpcode },
- /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupUninviteOpcode },
- /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupUninviteGuidOpcode },
- /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupSetLeaderOpcode },
- /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMethodOpcode },
- /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupDisbandOpcode },
- /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildCreateOpcode },
- /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildInviteOpcode },
- /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAcceptOpcode },
- /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDeclineOpcode },
- /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildInfoOpcode },
- /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRosterOpcode },
- /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildPromoteOpcode },
- /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDemoteOpcode },
- /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildLeaveOpcode },
- /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRemoveOpcode },
- /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDisbandOpcode },
- /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildLeaderOpcode },
- /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildMOTDOpcode },
- /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode },
- /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleJoinChannel },
- /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLeaveChannel },
- /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelList },
- /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelPassword },
- /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelSetOwner },
- /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelOwner },
- /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelModerator },
- /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnmoderator },
- /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelMute },
- /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnmute },
- /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelInvite },
- /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelKick },
- /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelBan },
- /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnban },
- /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelAnnouncements },
- /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL },
- /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUseItemOpcode },
- /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOpenItemOpcode },
- /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReadItem },
- /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGameObjectUseOpcode },
- /*0x0B2*/ { "CMSG_DESTROY_ITEMS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaTriggerOpcode },
- /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveTeleportAck },
- /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveWorldportAckOpcode },
- /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0E0*/ { "CMSG_MOVE_CHARM_PORT_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveRootAck },
- /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveUnRootAck },
- /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveKnockBackAck },
- /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveHoverAck },
- /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNextCinematicCamera },
- /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCompleteCinematic },
- /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialFlag },
- /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialClear },
- /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialReset },
- /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStandStateChangeOpcode },
- /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEmoteOpcode },
- /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTextEmoteOpcode },
- /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutostoreLootItemOpcode },
- /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoEquipItemOpcode },
- /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoStoreBagItemOpcode },
- /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapItem },
- /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapInvItemOpcode },
- /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSplitItemOpcode },
- /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoEquipItemSlotOpcode },
- /*0x110*/ { "CMSG_UNCLAIM_LICENSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDestroyItemOpcode },
- /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectOpcode },
- /*0x115*/ { "SMSG_INSPECT_RESULTS_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInitiateTradeOpcode },
- /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBeginTradeOpcode },
- /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBusyTradeOpcode },
- /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleIgnoreTradeOpcode },
- /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptTradeOpcode },
- /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode },
- /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode },
- /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeItemOpcode },
- /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleClearTradeItemOpcode },
- /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeGoldOpcode },
- /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionAtWar },
- /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionCheat },
- /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionButtonOpcode },
- /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCastSpellOpcode },
- /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCancelCastOpcode },
- /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAuraOpcode },
- /*0x137*/ { "SMSG_EQUIPMENT_SET_SAVED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelChanneling },
- /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSetSelectionOpcode },
- /*0x13E*/ { "CMSG_DELETEEQUIPMENT_SET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetDelete },
- /*0x13F*/ { "CMSG_INSTANCE_LOCK_RESPONSE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInstanceLockResponse },
- /*0x140*/ { "CMSG_DEBUG_PASSIVE_AURA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleAttackSwingOpcode },
- /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleAttackStopOpcode },
- /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x147*/ { "SMSG_INSTANCE_LOCK_WARNING_QUERY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x14B*/ { "SMSG_BATTLEFIELD_PORT_DENIED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x14C*/ { "CMSG_PERFORM_ACTION_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x14D*/ { "SMSG_RESUME_CAST_BAR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x14F*/ { "SMSG_SPELLBREAKLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x152*/ { "SMSG_BREAK_TARGET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRepopRequestOpcode },
- /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleResurrectResponseOpcode },
- /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootOpcode },
- /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMoneyOpcode },
- /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootReleaseOpcode },
- /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDuelAcceptedOpcode },
- /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDuelCancelledOpcode },
- /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x170*/ { "SMSG_REMOVED_FROM_PVP_QUEUE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMountSpecialAnimOpcode },
- /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetSetAction },
- /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAction },
- /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAbandon },
- /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetRename },
- /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGossipHelloOpcode },
- /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGossipSelectOptionOpcode },
- /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNpcTextQueryOpcode },
- /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQuestgiverStatusQueryOpcode},
- /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverHelloOpcode },
- /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQueryQuestOpcode},
- /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQuestAutoLaunch },
- /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverAcceptQuestOpcode},
- /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCompleteQuest },
- /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverRequestRewardOpcode},
- /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverChooseRewardOpcode},
- /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCancel },
- /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogSwapQuest },
- /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogRemoveQuest },
- /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestConfirmAccept },
- /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePushQuestToParty },
- /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleListInventoryOpcode },
- /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSellItemOpcode },
- /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyItemOpcode },
- /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyItemInSlotOpcode },
- /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiNodeStatusQueryOpcode },
- /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiQueryAvailableNodes },
- /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleActivateTaxiOpcode },
- /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTrainerListOpcode },
- /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTrainerBuySpellOpcode },
- /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBinderActivateOpcode },
- /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBankerActivateOpcode },
- /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyBankSlotOpcode },
- /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionShowListOpcode },
- /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionBuyOpcode },
- /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionShowSignOpcode },
- /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionSignOpcode },
- /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionDeclineOpcode },
- /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOfferPetitionOpcode },
- /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTurnInPetitionOpcode },
- /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionQueryOpcode },
- /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBugOpcode },
- /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayedTime },
- /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryTimeOpcode },
- /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReclaimCorpseOpcode },
- /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItemOpcode },
- /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMinimapPingOpcode },
- /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess },
- /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSetSheathedOpcode },
- /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1E3*/ { "CMSG_QUEST_POI_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPOIQuery },
- /*0x1E4*/ { "SMSG_QUEST_POI_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess },
- /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCastSpellOpcode },
- /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSaveGuildEmblemOpcode },
- /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTabardVendorActivateOpcode},
- /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleZoneUpdateOpcode },
- /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRandomRollOpcode },
- /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1FD*/ { "CMSG_CHANGEPLAYER_DIFFICULTY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x1FF*/ { "SMSG_LFG_PLAYER_REWARD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x200*/ { "SMSG_LFG_TELEPORT_DENIED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnlearnSkillOpcode },
- /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketCreateOpcode },
- /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketUpdateOpcode },
- /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestAccountData },
- /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateAccountData },
- /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x20E*/ { "SMSG_CHANGEPLAYER_DIFFICULTY_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketGetTicketOpcode },
- /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x214*/ { "SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseQueryOpcode },
- /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketDeleteOpcode },
- /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketSystemStatusOpcode},
- /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSpiritHealerActivateOpcode},
- /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x21E*/ { "SMSG_QUEST_FORCE_REMOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChatIgnoredOpcode },
- /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRankOpcode },
- /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAddRankOpcode },
- /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDelRankOpcode },
- /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetPublicNoteOpcode },
- /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetOfficerNoteOpcode },
- /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSendMail },
- /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetMailList },
- /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldListOpcode },
- /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x23F*/ { "SMSG_FORCE_SET_VEHICLE_REC_ID", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x240*/ { "CMSG_SET_VEHICLE_REC_ID_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemTextQuery },
- /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailTakeMoney },
- /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailTakeItem },
- /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailMarkAsRead },
- /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailReturnToSender },
- /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailDelete },
- /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailCreateTextItem },
- /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnTalentOpcode },
- /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTogglePvP },
- /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionHelloOpcode },
- /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionSellItem },
- /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionRemoveItem },
- /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListItems },
- /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListOwnerItems },
- /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionPlaceBid },
- /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x261*/ { "SMSG_COMBAT_EVENT_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListBidderItems },
- /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetAmmoOpcode },
- /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveMoverOpcode },
- /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCancelAuraOpcode },
- /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAutoRepeatSpellOpcode},
- /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleListStabledPetsOpcode },
- /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStablePet },
- /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnstablePet },
- /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyStableSlot },
- /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStableRevivePet },
- /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStableSwapPet },
- /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPushResult },
- /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPetInfoOpcode },
- /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleFarSightOpcode },
- /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupChangeSubGroupOpcode },
- /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPartyMemberStatsOpcode},
- /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoStoreBankItemOpcode },
- /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoBankItemOpcode },
- /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryNextMailTime },
- /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupRaidConvertOpcode },
- /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupAssistantLeaderOpcode},
- /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuybackItem },
- /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x292*/ { "CMSG_SET_SAVED_INSTANCE_EXTEND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetSavedInstanceExtend },
- /*0x293*/ { "SMSG_LFG_OFFER_CONTINUE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x294*/ { "CMSG_TEST_DROP_RATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x295*/ { "SMSG_TEST_DROP_RATE_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x296*/ { "CMSG_LFG_GET_STATUS", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleLfgGetStatus },
- /*0x297*/ { "SMSG_SHOW_MAILBOX", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x298*/ { "SMSG_RESET_RANGED_COMBAT_TIMER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x29A*/ { "SMSG_CHAT_NOT_IN_PARTY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelGrowthAuraOpcode },
- /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootRoll },
- /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMasterGiveOpcode },
- /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRepairItemOpcode },
- /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTalentWipeConfirmOpcode },
- /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSummonResponseOpcode },
- /*0x2AD*/ { "MSG_DEV_SHOWLABEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSelfResOpcode },
- /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2B9*/ { "CMSG_SHOWING_HELM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleShowingHelmOpcode },
- /*0x2BA*/ { "CMSG_SHOWING_CLOAK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleShowingCloakOpcode },
- /*0x2BB*/ { "SMSG_LFG_ROLE_CHOSEN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionBarToggles },
- /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionRenameOpcode },
- /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemNameQueryOpcode },
- /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharRenameOpcode },
- /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSplineDoneOpcode },
- /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRaidInfoOpcode },
- /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleMoveTimeSkippedOpcode },
- /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleFeatherFallAck },
- /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveWaterWalkAck },
- /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveNotActiveMover },
- /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldStatusOpcode },
- /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattleFieldPortOpcode },
- /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectHonorStatsOpcode },
- /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterHelloOpcode },
- /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePVPLogDataOpcode },
- /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldLeaveOpcode },
- /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaSpiritHealerQueryOpcode},
- /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaSpiritHealerQueueOpcode},
- /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_AUTHED, PROCESS_THREADSAFE, &WorldSession::HandleWardenDataOpcode },
- /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlegroundPlayerPositionsOpcode},
- /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetStopAttack },
- /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinOpcode },
- /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetSpellAutocastOpcode },
- /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildChangeInfoTextOpcode },
- /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleActivateTaxiExpressOpcode },
- /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionInactiveOpcode },
- /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetWatchedFactionOpcode },
- /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleResetInstancesOpcode },
- /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidTargetUpdateOpcode },
- /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckOpcode },
- /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetDungeonDifficultyOpcode},
- /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMSurveySubmit },
- /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x33E*/ { "SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x33F*/ { "SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x340*/ { "CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSetCanFlyAckOpcode },
- /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSocketOpcode },
- /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x34A*/ { "MSG_MOVE_UPDATE_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamQueryOpcode },
- /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamRosterOpcode },
- /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamInviteOpcode },
- /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamAcceptOpcode },
- /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamDeclineOpcode },
- /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamLeaveOpcode },
- /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamRemoveOpcode },
- /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamDisbandOpcode },
- /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamLeaderOpcode },
- /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinArena },
- /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x35C*/ { "CMSG_LFG_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode },
- /*0x35D*/ { "CMSG_LFG_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgLeaveOpcode },
- /*0x35E*/ { "CMSG_SEARCH_LFG_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrJoinOpcode },
- /*0x35F*/ { "CMSG_SEARCH_LFG_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrLeaveOpcode },
- /*0x360*/ { "SMSG_UPDATE_LFG_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x361*/ { "SMSG_LFG_PROPOSAL_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x362*/ { "CMSG_LFG_PROPOSAL_RESULT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgProposalResultOpcode },
- /*0x363*/ { "SMSG_LFG_ROLE_CHECK_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x364*/ { "SMSG_LFG_JOIN_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x365*/ { "SMSG_LFG_QUEUE_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetCommentOpcode },
- /*0x367*/ { "SMSG_LFG_UPDATE_PLAYER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x368*/ { "SMSG_LFG_UPDATE_PARTY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x369*/ { "SMSG_LFG_UPDATE_SEARCH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x36A*/ { "CMSG_LFG_SET_ROLES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetRolesOpcode },
- /*0x36B*/ { "CMSG_LFG_SET_NEEDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x36C*/ { "CMSG_LFG_SET_BOOT_VOTE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetBootVoteOpcode },
- /*0x36D*/ { "SMSG_LFG_BOOT_PROPOSAL_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x36E*/ { "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgPlayerLockInfoRequestOpcode},
- /*0x36F*/ { "SMSG_LFG_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x370*/ { "CMSG_LFG_TELEPORT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgTeleportOpcode },
- /*0x371*/ { "CMSG_LFD_PARTY_LOCK_INFO_REQUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgPartyLockInfoRequestOpcode},
- /*0x372*/ { "SMSG_LFG_PARTY_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTitleOpcode },
- /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelMountAuraOpcode },
- /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectArenaTeamsOpcode },
- /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTempEnchantmentOpcode},
- /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck },
- /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode },
- /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRealmSplitOpcode },
- /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePartyAssignmentOpcode },
- /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleTimeSyncResp },
- /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes },
- /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleVoiceSessionEnableOpcode },
- /*0x3B0*/ { "SMSG_VOICE_SESSION_ENABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3B1*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3B2*/ { "CMSG_GM_WHISPER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3B3*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3B4*/ { "MSG_GM_GEARRATING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3B5*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3B6*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3B7*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3B8*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3B9*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3BA*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3BB*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3BC*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3BD*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3BE*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3BF*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3C0*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3C1*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3C3*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3C4*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3C5*/ { "SMSG_KICK_REASON", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3C6*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckFinishedOpcode},
- /*0x3C7*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleComplainOpcode },
- /*0x3C8*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3C9*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3CA*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3CB*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3CD*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3CF*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3D0*/ { "CMSG_TARGET_CAST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3D1*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3D2*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelDisplayListQuery },
- /*0x3D3*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveVoiceChannel },
- /*0x3D4*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetChannelMemberCount },
- /*0x3D5*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3D6*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelVoiceOnOpcode },
- /*0x3D7*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3D8*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3D9*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3DA*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3DB*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3DC*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3DD*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3DE*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3DF*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3E0*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E1*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E2*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E3*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E4*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReportPvPAFK },
- /*0x3E5*/ { "SMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E6*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankerActivate },
- /*0x3E7*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankQueryTab },
- /*0x3E8*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3E9*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankSwapItems },
- /*0x3EA*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankBuyTab },
- /*0x3EB*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankUpdateTab },
- /*0x3EC*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankDepositMoney },
- /*0x3ED*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankWithdrawMoney },
- /*0x3EE*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankLogQuery },
- /*0x3EF*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetChannelWatch },
- /*0x3F0*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F1*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F2*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F3*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3F4*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F5*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F6*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3F7*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3F8*/ { "CMSG_SPELLCLICK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSpellClick },
- /*0x3F9*/ { "SMSG_LOOT_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3FA*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3FB*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x3FC*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x3FD*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildPermissions },
- /*0x3FE*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankMoneyWithdrawn },
- /*0x3FF*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildEventLogQueryOpcode },
- /*0x400*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMirrorImageDataRequest },
- /*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x403*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x404*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x405*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x406*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x407*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess },
- /*0x408*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x409*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleOptOutOfLootOpcode },
- /*0x40A*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryGuildBankTabText },
- /*0x40B*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetGuildBankTabText },
- /*0x40C*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x40D*/ { "CMSG_GRANT_LEVEL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGrantLevel },
- /*0x40E*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x40F*/ { "MSG_GM_CHANGE_ARENA_RATING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x410*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleChannelDeclineInvite },
- /*0x411*/ { "SMSG_GROUPACTION_THROTTLED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x412*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x413*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x414*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTotemDestroyed },
- /*0x415*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x416*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x417*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverStatusMultipleQuery},
- /*0x418*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x419*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetPlayerDeclinedNames },
- /*0x41A*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x41B*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x41C*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x41D*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x41E*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x41F*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x420*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptGrantLevel },
- /*0x421*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x422*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x423*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x424*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x425*/ { "CMSG_CHANGE_PERSONAL_ARENA_RATING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x426*/ { "CMSG_ALTER_APPEARANCE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAlterAppearance },
- /*0x427*/ { "SMSG_ENABLE_BARBER_SHOP", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x428*/ { "SMSG_BARBER_SHOP_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x429*/ { "CMSG_CALENDAR_GET_CALENDAR", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetCalendar },
- /*0x42A*/ { "CMSG_CALENDAR_GET_EVENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetEvent },
- /*0x42B*/ { "CMSG_CALENDAR_GUILD_FILTER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGuildFilter },
- /*0x42C*/ { "CMSG_CALENDAR_ARENA_TEAM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarArenaTeam },
- /*0x42D*/ { "CMSG_CALENDAR_ADD_EVENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarAddEvent },
- /*0x42E*/ { "CMSG_CALENDAR_UPDATE_EVENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarUpdateEvent },
- /*0x42F*/ { "CMSG_CALENDAR_REMOVE_EVENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarRemoveEvent },
- /*0x430*/ { "CMSG_CALENDAR_COPY_EVENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarCopyEvent },
- /*0x431*/ { "CMSG_CALENDAR_EVENT_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventInvite },
- /*0x432*/ { "CMSG_CALENDAR_EVENT_RSVP", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventRsvp },
- /*0x433*/ { "CMSG_CALENDAR_EVENT_REMOVE_INVITE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventRemoveInvite },
- /*0x434*/ { "CMSG_CALENDAR_EVENT_STATUS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventStatus },
- /*0x435*/ { "CMSG_CALENDAR_EVENT_MODERATOR_STATUS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventModeratorStatus},
- /*0x436*/ { "SMSG_CALENDAR_SEND_CALENDAR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x437*/ { "SMSG_CALENDAR_SEND_EVENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x438*/ { "SMSG_CALENDAR_FILTER_GUILD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x439*/ { "SMSG_CALENDAR_ARENA_TEAM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43A*/ { "SMSG_CALENDAR_EVENT_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43B*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43C*/ { "SMSG_CALENDAR_EVENT_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43D*/ { "SMSG_CALENDAR_COMMAND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43E*/ { "SMSG_CALENDAR_RAID_LOCKOUT_ADDED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x43F*/ { "SMSG_CALENDAR_RAID_LOCKOUT_REMOVED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x440*/ { "SMSG_CALENDAR_EVENT_INVITE_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x441*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x442*/ { "SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x443*/ { "SMSG_CALENDAR_EVENT_REMOVED_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x444*/ { "SMSG_CALENDAR_EVENT_UPDATED_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x445*/ { "SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x446*/ { "CMSG_CALENDAR_COMPLAIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarComplain },
- /*0x447*/ { "CMSG_CALENDAR_GET_NUM_PENDING", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetNumPending },
- /*0x448*/ { "SMSG_CALENDAR_SEND_NUM_PENDING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x449*/ { "CMSG_SAVE_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x44A*/ { "SMSG_NOTIFY_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x44B*/ { "CMSG_PLAY_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x44C*/ { "SMSG_PLAY_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x44D*/ { "CMSG_LOAD_DANCES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x44E*/ { "CMSG_STOP_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x44F*/ { "SMSG_STOP_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x450*/ { "CMSG_SYNC_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x451*/ { "CMSG_DANCE_QUERY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x452*/ { "SMSG_DANCE_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x453*/ { "SMSG_INVALIDATE_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x454*/ { "CMSG_DELETE_DANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x455*/ { "SMSG_LEARNED_DANCE_MOVES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x456*/ { "CMSG_LEARN_DANCE_MOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x457*/ { "CMSG_UNLEARN_DANCE_MOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x458*/ { "CMSG_SET_RUNE_COUNT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x459*/ { "CMSG_SET_RUNE_COOLDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x45A*/ { "MSG_MOVE_SET_PITCH_RATE_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x45B*/ { "MSG_MOVE_SET_PITCH_RATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x45C*/ { "SMSG_FORCE_PITCH_RATE_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x45D*/ { "CMSG_FORCE_PITCH_RATE_CHANGE_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x45E*/ { "SMSG_SPLINE_SET_PITCH_RATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x45F*/ { "CMSG_CALENDAR_EVENT_INVITE_NOTES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x460*/ { "SMSG_CALENDAR_EVENT_INVITE_NOTES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x461*/ { "SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateMissileTrajectory },
- /*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x464*/ { "SMSG_TRIGGER_MOVIE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x465*/ { "CMSG_COMPLETE_MOVIE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x466*/ { "CMSG_SET_GLYPH_SLOT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x467*/ { "CMSG_SET_GLYPH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x468*/ { "SMSG_ACHIEVEMENT_EARNED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x469*/ { "SMSG_DYNAMIC_DROP_ROLL_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x46A*/ { "SMSG_CRITERIA_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x46B*/ { "CMSG_QUERY_INSPECT_ACHIEVEMENTS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryInspectAchievements },
- /*0x46C*/ { "SMSG_RESPOND_INSPECT_ACHIEVEMENTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x46D*/ { "CMSG_DISMISS_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissControlledVehicle },
- /*0x46E*/ { "CMSG_COMPLETE_ACHIEVEMENT_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x46F*/ { "SMSG_QUESTUPDATE_ADD_PVP_KILL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x470*/ { "CMSG_SET_CRITERIA_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x471*/ { "SMSG_CALENDAR_RAID_LOCKOUT_UPDATED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x472*/ { "CMSG_UNITANIMTIER_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCustomize },
- /*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x475*/ { "SMSG_PET_RENAMEABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehicleExit },
- /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle},
- /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle},
- /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle},
- /*0x47A*/ { "CMSG_PET_LEARN_TALENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetLearnTalent },
- /*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x47C*/ { "SMSG_SET_PHASE_SHIFT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x47D*/ { "SMSG_ALL_ACHIEVEMENT_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x47E*/ { "CMSG_FORCE_SAY_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x47F*/ { "SMSG_HEALTH_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x480*/ { "SMSG_POWER_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x481*/ { "CMSG_GAMEOBJ_REPORT_USE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGameobjectReportUse },
- /*0x482*/ { "SMSG_HIGHEST_THREAT_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x483*/ { "SMSG_THREAT_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x484*/ { "SMSG_THREAT_REMOVE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x485*/ { "SMSG_THREAT_CLEAR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x486*/ { "SMSG_CONVERT_RUNE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x487*/ { "SMSG_RESYNC_RUNES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x488*/ { "SMSG_ADD_RUNE_POWER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x489*/ { "CMSG_START_QUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x48A*/ { "CMSG_REMOVE_GLYPH", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRemoveGlyph },
- /*0x48B*/ { "CMSG_DUMP_OBJECTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x48C*/ { "SMSG_DUMP_OBJECTS_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x48D*/ { "CMSG_DISMISS_CRITTER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissCritter },
- /*0x48E*/ { "SMSG_NOTIFY_DEST_LOC_SPELL_CAST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x48F*/ { "CMSG_AUCTION_LIST_PENDING_SALES", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListPendingSales },
- /*0x490*/ { "SMSG_AUCTION_LIST_PENDING_SALES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x491*/ { "SMSG_MODIFY_COOLDOWN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x492*/ { "SMSG_PET_UPDATE_COMBO_POINTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x493*/ { "CMSG_ENABLETAXI", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiQueryAvailableNodes },
- /*0x494*/ { "SMSG_PRE_RESURRECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x495*/ { "SMSG_AURA_UPDATE_ALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x496*/ { "SMSG_AURA_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x497*/ { "CMSG_FLOOD_GRACE_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x49A*/ { "SMSG_PET_REMOVED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle},
- /*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHearthAndResurrect },
- /*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x49E*/ { "SMSG_CRITERIA_DELETED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x49F*/ { "SMSG_ACHIEVEMENT_DELETED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A0*/ { "CMSG_SERVER_INFO_QUERY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4A1*/ { "SMSG_SERVER_INFO_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A2*/ { "CMSG_CHECK_LOGIN_CRITERIA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4A3*/ { "SMSG_SERVER_BUCK_DATA_START", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A4*/ { "CMSG_SET_BREATH", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4A5*/ { "CMSG_QUERY_VEHICLE_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4A6*/ { "SMSG_BATTLEGROUND_INFO_THROTTLED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A7*/ { "SMSG_PLAYER_VEHICLE_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A8*/ { "CMSG_PLAYER_VEHICLE_ENTER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEnterPlayerVehicle },
- /*0x4A9*/ { "CMSG_CONTROLLER_EJECT_PASSENGER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEjectPassenger },
- /*0x4AA*/ { "SMSG_PET_GUIDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4AB*/ { "SMSG_CLIENTCACHE_VERSION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4AC*/ { "CMSG_CHANGE_GDF_ARENA_RATING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4AD*/ { "CMSG_SET_ARENA_TEAM_RATING_BY_INDEX", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4AE*/ { "CMSG_SET_ARENA_TEAM_WEEKLY_GAMES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4AF*/ { "CMSG_SET_ARENA_TEAM_SEASON_GAMES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4B0*/ { "CMSG_SET_ARENA_MEMBER_WEEKLY_GAMES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4B1*/ { "CMSG_SET_ARENA_MEMBER_SEASON_GAMES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4B2*/ { "SMSG_ITEM_REFUND_INFO_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4B3*/ { "CMSG_ITEM_REFUND_INFO", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemRefundInfoRequest },
- /*0x4B4*/ { "CMSG_ITEM_REFUND", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemRefund },
- /*0x4B5*/ { "SMSG_ITEM_REFUND_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4B6*/ { "CMSG_CORPSE_MAP_POSITION_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseMapPositionQuery },
- /*0x4B7*/ { "SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4B8*/ { "CMSG_UNUSED5", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL },
- /*0x4B9*/ { "CMSG_UNUSED6", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4BA*/ { "CMSG_CALENDAR_EVENT_SIGNUP", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventSignup },
- /*0x4BB*/ { "SMSG_CALENDAR_CLEAR_PENDING_ACTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4BC*/ { "SMSG_EQUIPMENT_SET_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4BD*/ { "CMSG_EQUIPMENT_SET_SAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetSave },
- /*0x4BE*/ { "CMSG_UPDATE_PROJECTILE_POSITION", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateProjectilePosition },
- /*0x4BF*/ { "SMSG_SET_PROJECTILE_POSITION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4C0*/ { "SMSG_TALENTS_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4C1*/ { "CMSG_LEARN_PREVIEW_TALENTS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalents },
- /*0x4C2*/ { "CMSG_LEARN_PREVIEW_TALENTS_PET", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalentsPet },
- /*0x4C3*/ { "CMSG_SET_ACTIVE_TALENT_GROUP_OBSOLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4C4*/ { "CMSG_GM_GRANT_ACHIEVEMENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4C5*/ { "CMSG_GM_REMOVE_ACHIEVEMENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4C6*/ { "CMSG_GM_SET_CRITERIA_FOR_PLAYER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4C7*/ { "SMSG_ARENA_UNIT_DESTROYED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4C8*/ { "SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4C9*/ { "CMSG_PROFILEDATA_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4CA*/ { "SMSG_PROFILEDATA_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4CB*/ { "CMSG_START_BATTLEFIELD_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4CC*/ { "CMSG_END_BATTLEFIELD_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4CD*/ { "SMSG_MULTIPLE_PACKETS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4CE*/ { "SMSG_MOVE_GRAVITY_DISABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4CF*/ { "CMSG_MOVE_GRAVITY_DISABLE_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4D0*/ { "SMSG_MOVE_GRAVITY_ENABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D1*/ { "CMSG_MOVE_GRAVITY_ENABLE_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4D2*/ { "MSG_MOVE_GRAVITY_CHNG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D3*/ { "SMSG_SPLINE_MOVE_GRAVITY_DISABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D4*/ { "SMSG_SPLINE_MOVE_GRAVITY_ENABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D5*/ { "CMSG_EQUIPMENT_SET_USE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetUse },
- /*0x4D6*/ { "SMSG_EQUIPMENT_SET_USE_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D7*/ { "CMSG_FORCE_ANIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4D8*/ { "SMSG_FORCE_ANIM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4D9*/ { "CMSG_CHAR_FACTION_CHANGE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharFactionOrRaceChange },
- /*0x4DA*/ { "SMSG_CHAR_FACTION_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4DB*/ { "CMSG_PVP_QUEUE_STATS_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4DC*/ { "SMSG_PVP_QUEUE_STATS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4DD*/ { "CMSG_SET_PAID_SERVICE_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4DE*/ { "SMSG_BATTLEFIELD_MGR_ENTRY_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4DF*/ { "CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfEntryInviteResponse },
- /*0x4E0*/ { "SMSG_BATTLEFIELD_MGR_ENTERED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E1*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E2*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfQueueInviteResponse },
- /*0x4E3*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4E4*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E5*/ { "SMSG_BATTLEFIELD_MGR_EJECT_PENDING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E6*/ { "SMSG_BATTLEFIELD_MGR_EJECTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E7*/ { "CMSG_BATTLEFIELD_MGR_EXIT_REQUEST", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfExitRequest },
- /*0x4E8*/ { "SMSG_BATTLEFIELD_MGR_STATE_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E9*/ { "CMSG_BATTLEFIELD_MANAGER_ADVANCE_STATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4EA*/ { "CMSG_BATTLEFIELD_MANAGER_SET_NEXT_TRANSITION_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4EB*/ { "MSG_SET_RAID_DIFFICULTY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetRaidDifficultyOpcode },
- /*0x4EC*/ { "CMSG_TOGGLE_XP_GAIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4ED*/ { "SMSG_TOGGLE_XP_GAIN", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4EE*/ { "SMSG_GMRESPONSE_DB_ERROR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4EF*/ { "SMSG_GMRESPONSE_RECEIVED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4F0*/ { "CMSG_GMRESPONSE_RESOLVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMResponseResolve },
- /*0x4F1*/ { "SMSG_GMRESPONSE_STATUS_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4F2*/ { "SMSG_GMRESPONSE_CREATE_TICKET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4F3*/ { "CMSG_GMRESPONSE_CREATE_TICKET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4F4*/ { "CMSG_SERVERINFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4F5*/ { "SMSG_SERVERINFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4F6*/ { "CMSG_WORLD_STATE_UI_TIMER_UPDATE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleWorldStateUITimerUpdate },
- /*0x4F7*/ { "SMSG_WORLD_STATE_UI_TIMER_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4F8*/ { "CMSG_CHAR_RACE_CHANGE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharFactionOrRaceChange },
- /*0x4F9*/ { "MSG_VIEW_PHASE_SHIFT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4FA*/ { "SMSG_TALENTS_INVOLUNTARILY_RESET", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4FB*/ { "CMSG_DEBUG_SERVER_GEO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4FC*/ { "SMSG_DEBUG_SERVER_GEO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4FD*/ { "SMSG_LOOT_SLOT_CHANGED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4FE*/ { "UMSG_UPDATE_GROUP_INFO", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4FF*/ { "CMSG_READY_FOR_ACCOUNT_DATA_TIMES", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleReadyForAccountDataTimes },
- /*0x500*/ { "CMSG_QUERY_QUESTS_COMPLETED", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryQuestsCompleted },
- /*0x501*/ { "SMSG_QUERY_QUESTS_COMPLETED_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x502*/ { "CMSG_GM_REPORT_LAG", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReportLag },
- /*0x503*/ { "CMSG_AFK_MONITOR_INFO_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x504*/ { "SMSG_AFK_MONITOR_INFO_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x505*/ { "CMSG_AFK_MONITOR_INFO_CLEAR", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x506*/ { "SMSG_CORPSE_IS_NOT_IN_INSTANCE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x507*/ { "CMSG_GM_NUKE_CHARACTER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x508*/ { "CMSG_SET_ALLOW_LOW_LEVEL_RAID1", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x509*/ { "CMSG_SET_ALLOW_LOW_LEVEL_RAID2", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x50A*/ { "SMSG_CAMERA_SHAKE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x50B*/ { "SMSG_SOCKET_GEMS_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x50C*/ { "CMSG_SET_CHARACTER_MODEL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x50D*/ { "SMSG_REDIRECT_CLIENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x50E*/ { "CMSG_REDIRECTION_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x50F*/ { "SMSG_SUSPEND_COMMS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x510*/ { "CMSG_SUSPEND_COMMS_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x511*/ { "SMSG_FORCE_SEND_QUEUED_PACKETS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x512*/ { "CMSG_REDIRECTION_AUTH_PROOF", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x513*/ { "CMSG_DROP_NEW_CONNECTION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x514*/ { "SMSG_SEND_ALL_COMBAT_LOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x515*/ { "SMSG_OPEN_LFG_DUNGEON_FINDER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x516*/ { "SMSG_MOVE_SET_COLLISION_HGT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x517*/ { "CMSG_MOVE_SET_COLLISION_HGT_ACK", STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x518*/ { "MSG_MOVE_SET_COLLISION_HGT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x519*/ { "CMSG_CLEAR_RANDOM_BG_WIN_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x51A*/ { "CMSG_CLEAR_HOLIDAY_BG_WIN_TIME", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x51B*/ { "CMSG_COMMENTATOR_SKIRMISH_QUEUE_COMMAND", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x51C*/ { "SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT1", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x51D*/ { "SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT2", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x51E*/ { "SMSG_COMPRESSED_UNKNOWN_1310", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
+#define DEFINE_OPCODE_HANDLER(opcode, status, processing, handler) \
+ ValidateAndSetOpcode<(opcode < NUM_OPCODE_HANDLERS), (opcode != 0)>(opcode, #opcode, status, processing, handler);
+
+ DEFINE_OPCODE_HANDLER(CMSG_ACCEPT_LEVEL_GRANT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptGrantLevel );
+ DEFINE_OPCODE_HANDLER(CMSG_ACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ACTIVATETAXI, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleActivateTaxiOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ACTIVATETAXIEXPRESS, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleActivateTaxiExpressOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ADDON_REGISTERED_PREFIXES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonRegisteredPrefixesOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_ADD_FRIEND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddFriendOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ADD_IGNORE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddIgnoreOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ADD_VOICE_IGNORE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_ALTER_APPEARANCE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAlterAppearance );
+ DEFINE_OPCODE_HANDLER(CMSG_AREATRIGGER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaTriggerOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AREA_SPIRIT_HEALER_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaSpiritHealerQueryOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_AREA_SPIRIT_HEALER_QUEUE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaSpiritHealerQueueOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_ACCEPT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamAcceptOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_CREATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamCreateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_DECLINE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamDeclineOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_DISBAND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamDisbandOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamInviteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_LEADER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamLeaderOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_LEAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamLeaveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_REMOVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamRemoveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ARENA_TEAM_ROSTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamRosterOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ATTACKSTOP, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleAttackStopOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ATTACKSWING, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleAttackSwingOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_LIST_BIDDER_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListBidderItems );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_LIST_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListItems );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_LIST_OWNER_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListOwnerItems );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_LIST_PENDING_SALES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListPendingSales );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_PLACE_BID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionPlaceBid );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_REMOVE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionRemoveItem );
+ DEFINE_OPCODE_HANDLER(CMSG_AUCTION_SELL_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionSellItem );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTH_SESSION, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOBANK_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoBankItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOEQUIP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoEquipItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOEQUIP_ITEM_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoEquipItemSlotOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOSTORE_BAG_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoStoreBagItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOSTORE_BANK_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoStoreBankItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTOSTORE_LOOT_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutostoreLootItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_AUTO_DECLINE_GUILD_INVITES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoDeclineGuildInvites );
+ DEFINE_OPCODE_HANDLER(CMSG_BANKER_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBankerActivateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_LEAVE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBattlefieldLeaveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldListOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfEntryInviteResponse );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_EXIT_REQUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfExitRequest );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfQueueInviteResponse );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_PORT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattleFieldPortOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_STATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldStatusOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEGROUND_PLAYER_POSITIONS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBattlegroundPlayerPositionsOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEMASTER_JOIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEMASTER_JOIN_ARENA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinArena );
+ DEFINE_OPCODE_HANDLER(CMSG_BATTLEMASTER_JOIN_RATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_BEGIN_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBeginTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BINDER_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBinderActivateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BUG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBugOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BUSY_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBusyTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BUYBACK_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuybackItem );
+ DEFINE_OPCODE_HANDLER(CMSG_BUY_BANK_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyBankSlotOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_BUY_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_ADD_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarAddEvent );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_ARENA_TEAM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarArenaTeam );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_COMPLAIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarComplain );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_COPY_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarCopyEvent );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventInvite );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_MODERATOR_STATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventModeratorStatus);
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_REMOVE_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventRemoveInvite );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_RSVP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventRsvp );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_SIGNUP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventSignup );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_STATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventStatus );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GET_CALENDAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetCalendar );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GET_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetEvent );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GET_NUM_PENDING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetNumPending );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GUILD_FILTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGuildFilter );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_REMOVE_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarRemoveEvent );
+ DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_UPDATE_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarUpdateEvent );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAuraOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_AUTO_REPEAT_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAutoRepeatSpellOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_CAST, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCancelCastOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_CHANNELLING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelChanneling );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_MOUNT_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelMountAuraOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_QUEUED_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTempEnchantmentOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCastSpellOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANGEPLAYER_DIFFICULTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle);
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_ANNOUNCEMENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelAnnouncements );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_BAN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelBan );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_DISPLAY_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelDisplayListQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelInvite );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_KICK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelKick );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelList );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_MODERATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_MODERATOR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelModerator );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_MUTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelMute );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_OWNER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelOwner );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_PASSWORD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelPassword );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_ROSTER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_SET_OWNER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelSetOwner );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_SILENCE_ALL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_SILENCE_VOICE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_UNBAN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnban );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_UNMODERATOR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnmoderator );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_UNMUTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnmute );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_UNSILENCE_ALL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_UNSILENCE_VOICE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_VOICE_OFF, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelVoiceOnOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_VOICE_ON, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelVoiceOnOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_CREATE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCreateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_CUSTOMIZE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCustomize );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_DELETE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharDeleteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_ENUM, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharEnumOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_FACTION_CHANGE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharFactionOrRaceChange );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_RACE_CHANGE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharFactionOrRaceChange );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAR_RENAME, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharRenameOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAT_FILTERED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CHAT_IGNORED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChatIgnoredOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CLEAR_CHANNEL_WATCH, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CLEAR_RAID_MARKER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CLEAR_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleClearTradeItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_ENABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_ENTER_INSTANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_EXIT_INSTANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_GET_MAP_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_GET_PARTY_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_GET_PLAYER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_INSTANCE_COMMAND, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_SKIRMISH_QUEUE_COMMAND, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMMENTATOR_START_WARGAME, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_COMPLAIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleComplainOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_COMPLETE_CINEMATIC, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCompleteCinematic );
+ DEFINE_OPCODE_HANDLER(CMSG_COMPLETE_MOVIE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CONNECT_TO_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_CONTACT_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleContactListOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_CORPSE_MAP_POSITION_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseMapPositionQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_CREATURE_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCreatureQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DANCE_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_DEL_FRIEND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelFriendOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DEL_IGNORE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelIgnoreOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DEL_VOICE_IGNORE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_DESTROY_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDestroyItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DISMISS_CONTROLLED_VEHICLE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissControlledVehicle );
+ DEFINE_OPCODE_HANDLER(CMSG_DISMISS_CRITTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissCritter );
+ DEFINE_OPCODE_HANDLER(CMSG_DUEL_ACCEPTED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDuelAcceptedOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_DUEL_CANCELLED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDuelCancelledOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_EJECT_PASSENGER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEmoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ENABLETAXI, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiQueryAvailableNodes );
+ DEFINE_OPCODE_HANDLER(CMSG_ENABLE_NAGLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(CMSG_EQUIPMENT_SET_DELETE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetDelete );
+ DEFINE_OPCODE_HANDLER(CMSG_EQUIPMENT_SET_SAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetSave );
+ DEFINE_OPCODE_HANDLER(CMSG_EQUIPMENT_SET_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetUse );
+ DEFINE_OPCODE_HANDLER(CMSG_FAR_SIGHT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleFarSightOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_FORCE_MOVE_ROOT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveRootAck );
+ DEFINE_OPCODE_HANDLER(CMSG_FORCE_MOVE_UNROOT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveUnRootAck );
+ DEFINE_OPCODE_HANDLER(CMSG_GAMEOBJECT_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGameObjectQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GAMEOBJ_REPORT_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGameobjectReportUse );
+ DEFINE_OPCODE_HANDLER(CMSG_GAMEOBJ_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGameObjectUseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GET_MAIL_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetMailList );
+ DEFINE_OPCODE_HANDLER(CMSG_GET_MIRRORIMAGE_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMirrorImageDataRequest );
+ DEFINE_OPCODE_HANDLER(CMSG_GMRESPONSE_RESOLVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMResponseResolve );
+ DEFINE_OPCODE_HANDLER(CMSG_GMSURVEY_SUBMIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMSurveySubmit );
+ DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_CREATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketCreateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_DELETETICKET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketDeleteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_GETTICKET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketGetTicketOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_SYSTEMSTATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketSystemStatusOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_UPDATETEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketUpdateOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GM_REPORT_LAG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReportLag );
+ DEFINE_OPCODE_HANDLER(CMSG_GOSSIP_HELLO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGossipHelloOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GOSSIP_SELECT_OPTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGossipSelectOptionOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GRANT_LEVEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGrantLevel );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_ASSISTANT_LEADER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupAssistantLeaderOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_CHANGE_SUB_GROUP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupChangeSubGroupOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_DISBAND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupDisbandOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_INVITE_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteResponseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_RAID_CONVERT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupRaidConvertOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_REQUEST_JOIN_UPDATES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_SET_LEADER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupSetLeaderOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_SET_ROLES, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGroupSetRolesOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_SWAP_SUB_GROUP, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupSwapSubGroupOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GROUP_UNINVITE_GUID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupUninviteGuidOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ACCEPT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAcceptOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ACHIEVEMENT_MEMBERS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ACHIEVEMENT_PROGRESS_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAchievementProgressQuery);
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ADD_RANK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAddRankOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ASSIGN_MEMBER_RANK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAssignRankOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANKER_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankerActivate );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_BUY_TAB, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankBuyTab );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_DEPOSIT_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankDepositMoney );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_LOG_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankLogQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_MONEY_WITHDRAWN_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankMoneyWithdrawn );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_QUERY_TAB, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankQueryTab );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_QUERY_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryGuildBankTabText );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_SWAP_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankSwapItems );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_UPDATE_TAB, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankUpdateTab );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_WITHDRAW_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankWithdrawMoney );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_CHANGE_NAME_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_DECLINE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDeclineOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_DEL_RANK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDelRankOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_DEMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDemoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_DISBAND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDisbandOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_EVENT_LOG_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildEventLogQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_INFO_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildChangeInfoTextOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildInviteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_LEAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildLeaveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_MEMBER_SEND_SOR_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_MOTD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildMOTDOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_NEWS_UPDATE_STICKY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGuildNewsUpdateStickyOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_PERMISSIONS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildPermissions );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_PROMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildPromoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_QUERY, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_QUERY_NEWS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGuildQueryNewsOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_QUERY_RANKS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryRanksOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REMOVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRemoveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REPLACE_GUILD_MASTER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REQUEST_CHALLENGE_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REQUEST_MAX_DAILY_XP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRequestMaxDailyXP );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REQUEST_PARTY_STATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRequestPartyState );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_ROSTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRosterOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_SET_ACHIEVEMENT_TRACKING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_SET_GUILD_MASTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetGuildMaster );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_SET_NOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetNoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_SET_RANK_PERMISSIONS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetRankPermissionsOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_SWITCH_RANK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_HEARTH_AND_RESURRECT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleHearthAndResurrect );
+ DEFINE_OPCODE_HANDLER(CMSG_IGNORE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleIgnoreTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_INITIATE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInitiateTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_INSPECT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_INSPECT_HONOR_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectHonorStatsOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_INSTANCE_LOCK_WARNING_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_ITEM_REFUND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemRefund );
+ DEFINE_OPCODE_HANDLER(CMSG_ITEM_REFUND_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemRefundInfoRequest );
+ DEFINE_OPCODE_HANDLER(CMSG_ITEM_TEXT_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleItemTextQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_JOIN_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleJoinChannel );
+ DEFINE_OPCODE_HANDLER(CMSG_KEEP_ALIVE, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(CMSG_LEARN_PREVIEW_TALENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalents );
+ DEFINE_OPCODE_HANDLER(CMSG_LEARN_PREVIEW_TALENTS_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalentsPet );
+ DEFINE_OPCODE_HANDLER(CMSG_LEARN_TALENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnTalentOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LEAVE_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLeaveChannel );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_GET_STATUS, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleLfgGetStatus );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_JOIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_LEAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgLeaveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_LFR_JOIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_LFR_LEAVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_LOCK_INFO_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleLfgGetLockInfoOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_PROPOSAL_RESULT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgProposalResultOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_BOOT_VOTE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetBootVoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_COMMENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_ROLES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetRolesOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LFG_TELEPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgTeleportOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_ADD_RECRUIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderAddRecruit );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_BROWSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderBrowse );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_DECLINE_RECRUIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderDeclineRecruit );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_GET_APPLICATIONS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderGetApplications);
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_GET_RECRUITS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderGetRecruits );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_POST_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderPostRequest );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_REMOVE_RECRUIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderRemoveRecruit );
+ DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_SET_GUILD_POST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderSetGuildPost );
+ DEFINE_OPCODE_HANDLER(CMSG_LIST_INVENTORY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleListInventoryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOAD_SCREEN, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleLoadScreenOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOGOUT_CANCEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOGOUT_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutRequestOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOG_DISCONNECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_CURRENCY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_MASTER_GIVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMasterGiveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_METHOD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMethodOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMoneyOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_RELEASE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootReleaseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootRoll );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_CREATE_TEXT_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailCreateTextItem );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_DELETE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailDelete );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_MARK_AS_READ, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailMarkAsRead );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_RETURN_TO_SENDER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailReturnToSender );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_TAKE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailTakeItem );
+ DEFINE_OPCODE_HANDLER(CMSG_MAIL_TAKE_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailTakeMoney );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_BATTLEGROUND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_GUILD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_OFFICER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_PARTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_RAID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_ADDON_WHISPER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_AFK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_BATTLEGROUND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_DND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_GUILD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_OFFICER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_PARTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_RAID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_RAID_WARNING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_SAY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_WHISPER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MESSAGECHAT_YELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MINIGAME_MOVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_MOUNTSPECIAL_ANIM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMountSpecialAnimOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_CHNG_TRANSPORT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FALL_RESET, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FEATHER_FALL_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleFeatherFallAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_GRAVITY_DISABLE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_GRAVITY_ENABLE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_HOVER_ACK, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveHoverAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_KNOCK_BACK_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveKnockBackAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_NOT_ACTIVE_MOVER, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveNotActiveMover );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_CAN_FLY, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_CAN_FLY_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSetCanFlyAckOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_COLLISION_HEIGHT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleSetCollisionHeightAck );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_SPLINE_DONE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSplineDoneOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_TIME_SKIPPED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleMoveTimeSkippedOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_MOVE_WATER_WALK_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveWaterWalkAck );
+ DEFINE_OPCODE_HANDLER(CMSG_NAME_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNameQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_NEXT_CINEMATIC_CAMERA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNextCinematicCamera );
+ DEFINE_OPCODE_HANDLER(CMSG_NPC_TEXT_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNpcTextQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_OBJECT_UPDATE_FAILED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleObjectUpdateFailedOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_OBJECT_UPDATE_RESCUED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_OFFER_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOfferPetitionOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_OPENING_CINEMATIC, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOpeningCinematic );
+ DEFINE_OPCODE_HANDLER(CMSG_OPEN_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOpenItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_OPT_OUT_OF_LOOT, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleOptOutOfLootOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PAGE_TEXT_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePageTextQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PARTY_SILENCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_PARTY_UNSILENCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_PETITION_BUY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionBuyOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PETITION_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PETITION_SHOWLIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionShowListOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PETITION_SHOW_SIGNATURES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionShowSignOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PETITION_SIGN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionSignOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_ABANDON, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAbandon );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_ACTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAction );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCancelAuraOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCastSpellOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_LEARN_TALENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetLearnTalent );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_NAME_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetNameQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_RENAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetRename );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_SET_ACTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetSetAction );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_SPELL_AUTOCAST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetSpellAutocastOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PET_STOP_ATTACK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetStopAttack );
+ DEFINE_OPCODE_HANDLER(CMSG_PING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(CMSG_PLAYED_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayedTime );
+ DEFINE_OPCODE_HANDLER(CMSG_PLAYER_LOGIN, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayerLoginOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_PLAYER_VEHICLE_ENTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEnterPlayerVehicle );
+ DEFINE_OPCODE_HANDLER(CMSG_PLAY_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_PUSHQUESTTOPARTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePushQuestToParty );
+ DEFINE_OPCODE_HANDLER(CMSG_PVP_LOG_DATA, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandlePVPLogDataOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_BATTLEFIELD_STATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_MEMBERS_FOR_RECIPE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_MEMBER_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_REWARDS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGuildRewardsQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_XP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryXPOpcode ); // STATUS_AUTHED
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_INSPECT_ACHIEVEMENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryInspectAchievements );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_QUESTS_COMPLETED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryQuestsCompleted );
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryTimeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_ACCEPT_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverAcceptQuestOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_CHOOSE_REWARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverChooseRewardOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_COMPLETE_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCompleteQuest );
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_HELLO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverHelloOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_QUERY_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQueryQuestOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_REQUEST_REWARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverRequestRewardOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverStatusMultipleQuery);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_STATUS_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQuestgiverStatusQueryOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_QUESTLOG_REMOVE_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogRemoveQuest );
+ DEFINE_OPCODE_HANDLER(CMSG_QUEST_CONFIRM_ACCEPT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestConfirmAccept );
+ DEFINE_OPCODE_HANDLER(CMSG_QUEST_NPC_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_QUEST_POI_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPOIQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_QUEST_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_RANDOMIZE_CHAR_NAME, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRandomizeCharNameOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_READY_FOR_ACCOUNT_DATA_TIMES, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleReadyForAccountDataTimes );
+ DEFINE_OPCODE_HANDLER(CMSG_READ_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReadItem );
+ DEFINE_OPCODE_HANDLER(CMSG_REALM_SPLIT, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRealmSplitOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_RECLAIM_CORPSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReclaimCorpseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REDIRECTION_AUTH_PROOF, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_REFORGE_ITEM, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleReforgeItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REORDER_CHARACTERS, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleReorderCharacters );
+ DEFINE_OPCODE_HANDLER(CMSG_REPAIR_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRepairItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REPOP_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRepopRequestOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REPORT_PVP_AFK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReportPvPAFK );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestAccountData );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_CATEGORY_COOLDOWNS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestCategoryCooldowns );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_CEMETERY_LIST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_HOTFIX, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleRequestHotfix );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_INSPECT_RATED_BG_STATS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_PARTY_MEMBER_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPartyMemberStatsOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_PET_INFO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPetInfoOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_PVP_OPTIONS_ENABLED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestPvpOptions );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_PVP_REWARDS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestPvpReward );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RAID_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRaidInfoOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RATED_BG_INFO, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestRatedBgInfo );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RATED_BG_STATS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestRatedBgStats );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RESEARCH_HISTORY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_VEHICLE_EXIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehicleExit );
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_VEHICLE_NEXT_SEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle);
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_VEHICLE_PREV_SEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle);
+ DEFINE_OPCODE_HANDLER(CMSG_REQUEST_VEHICLE_SWITCH_SEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle);
+ DEFINE_OPCODE_HANDLER(CMSG_RESET_FACTION_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_RESET_INSTANCES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleResetInstancesOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_RESURRECT_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleResurrectResponseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_RETURN_TO_GRAVEYARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReturnToGraveyard );
+ DEFINE_OPCODE_HANDLER(CMSG_ROLE_POLL_BEGIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SAVE_CUF_PROFILES, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSaveCUFProfiles );
+ DEFINE_OPCODE_HANDLER(CMSG_SELF_RES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSelfResOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SELL_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSellItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SEND_MAIL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSendMail );
+ DEFINE_OPCODE_HANDLER(CMSG_SEND_SOR_REQUEST_VIA_ADDRESS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SEND_SOR_REQUEST_VIA_BNET_ACCOUNT_ID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SETSHEATHED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSetSheathedOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ACTIONBAR_TOGGLES, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionBarToggles );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ACTION_BUTTON, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionButtonOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ACTIVE_MOVER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveMoverOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ACTIVE_VOICE_CHANNEL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveVoiceChannel ); // STATUS_AUTHED
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ALLOW_LOW_LEVEL_RAID1, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_ALLOW_LOW_LEVEL_RAID2, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_CHANNEL_WATCH, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetChannelWatch );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_CONTACT_NOTES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetContactNotesOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_CURRENCY_FLAGS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_EVERYONE_IS_ASSISTANT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_FACTION_ATWAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionAtWar );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_FACTION_INACTIVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionInactiveOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_GUILD_BANK_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetGuildBankTabText );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_PET_SLOT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_PLAYER_DECLINED_NAMES, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetPlayerDeclinedNames );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_PREFERED_CEMETERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_PRIMARY_TALENT_TREE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_RELATIVE_POSITION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_SAVED_INSTANCE_EXTEND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetSavedInstanceExtend );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_SELECTION, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSetSelectionOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_TAXI_BENCHMARK_MODE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_TITLE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTitleOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_TRADE_CURRENCY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_TRADE_GOLD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeGoldOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_VEHICLE_REC_ID_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SET_WATCHED_FACTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetWatchedFactionOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SHOWING_CLOAK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleShowingCloakOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SHOWING_HELM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleShowingHelmOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SOCKET_GEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSocketOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SPELLCLICK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSpellClick );
+ DEFINE_OPCODE_HANDLER(CMSG_SPIRIT_HEALER_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSpiritHealerActivateOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_SPLIT_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSplitItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_STANDSTATECHANGE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStandStateChangeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_STOP_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SUBMIT_BUG, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SUBMIT_COMPLAIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SUGGESTION_SUBMIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SUMMON_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSummonResponseOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SUSPEND_TOKEN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_SWAP_INV_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapInvItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_SWAP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapItem );
+ DEFINE_OPCODE_HANDLER(CMSG_SYNC_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_TAXINODE_STATUS_QUERY, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiNodeStatusQueryOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_TAXIQUERYAVAILABLENODES, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTaxiQueryAvailableNodes );
+ DEFINE_OPCODE_HANDLER(CMSG_TELEPORT_TO_UNIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_TEXT_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTextEmoteOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_TIME_ADJUSTMENT_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_TIME_SYNC_RESP, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleTimeSyncResp );
+ DEFINE_OPCODE_HANDLER(CMSG_TIME_SYNC_RESP_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_TOGGLE_PVP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTogglePvP );
+ DEFINE_OPCODE_HANDLER(CMSG_TOTEM_DESTROYED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTotemDestroyed );
+ DEFINE_OPCODE_HANDLER(CMSG_TRAINER_BUY_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTrainerBuySpellOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_TRAINER_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTrainerListOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_TRANSMOGRIFY_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogrifyItems );
+ DEFINE_OPCODE_HANDLER(CMSG_TURN_IN_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTurnInPetitionOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_TUTORIAL_CLEAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialClear );
+ DEFINE_OPCODE_HANDLER(CMSG_TUTORIAL_FLAG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialFlag );
+ DEFINE_OPCODE_HANDLER(CMSG_TUTORIAL_RESET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialReset );
+ DEFINE_OPCODE_HANDLER(CMSG_UNACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_UNLEARN_SKILL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnlearnSkillOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_UNLEARN_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_UNREGISTER_ALL_ADDON_PREFIXES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnregisterAddonPrefixesOpcode);
+ DEFINE_OPCODE_HANDLER(CMSG_UPDATE_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateAccountData );
+ DEFINE_OPCODE_HANDLER(CMSG_UPDATE_MISSILE_TRAJECTORY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateMissileTrajectory );
+ DEFINE_OPCODE_HANDLER(CMSG_UPDATE_PROJECTILE_POSITION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateProjectilePosition );
+ DEFINE_OPCODE_HANDLER(CMSG_USED_FOLLOW, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_USE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUseItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_VIOLENCE_LEVEL, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleViolenceLevel );
+ DEFINE_OPCODE_HANDLER(CMSG_VOICE_SESSION_ENABLE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleVoiceSessionEnableOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_VOID_STORAGE_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleVoidStorageQuery );
+ DEFINE_OPCODE_HANDLER(CMSG_VOID_STORAGE_TRANSFER, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleVoidStorageTransfer );
+ DEFINE_OPCODE_HANDLER(CMSG_VOID_STORAGE_UNLOCK, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleVoidStorageUnlock );
+ DEFINE_OPCODE_HANDLER(CMSG_VOID_SWAP_ITEM, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleVoidSwapItem );
+ DEFINE_OPCODE_HANDLER(CMSG_WARDEN_DATA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWardenDataOpcode ); // STATUS_AUTHED
+ DEFINE_OPCODE_HANDLER(CMSG_WARGAME_ACCEPT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_WARGAME_START, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_WHO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_WHOIS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoisOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_WORLD_STATE_UI_TIMER_UPDATE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleWorldStateUITimerUpdate );
+ DEFINE_OPCODE_HANDLER(CMSG_WORLD_TELEPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWorldTeleportOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_WRAP_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItemOpcode );
+ DEFINE_OPCODE_HANDLER(CMSG_ZONEUPDATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleZoneUpdateOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_AUCTION_HELLO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionHelloOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_CHANNEL_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(MSG_CHANNEL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(MSG_CORPSE_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseQueryOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_INSPECT_ARENA_TEAMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectArenaTeamsOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_LIST_STABLED_PETS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleListStabledPetsOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_MINIMAP_PING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMinimapPingOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_CHARM_TELEPORT_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_FALL_LAND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_HEARTBEAT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_JUMP, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_FACING, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_PITCH, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RUN_MODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_WALK_MODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_ASCEND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_BACKWARD, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_DESCEND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_FORWARD, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_PITCH_DOWN, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_PITCH_UP, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_STRAFE_LEFT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_STRAFE_RIGHT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_SWIM, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_TURN_LEFT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_START_TURN_RIGHT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_ASCEND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_PITCH, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_STRAFE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_SWIM, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_TURN, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_TELEPORT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveTeleportAck );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_TELEPORT_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_TIME_SKIPPED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_TOGGLE_COLLISION_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_MOVE_WORLDPORT_ACK, STATUS_TRANSFER, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveWorldportAckOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_NOTIFY_PARTY_SQUELCH, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_PARTY_ASSIGNMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePartyAssignmentOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_PETITION_DECLINE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionDeclineOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_PETITION_RENAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionRenameOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_QUERY_NEXT_MAIL_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryNextMailTime );
+ DEFINE_OPCODE_HANDLER(MSG_QUEST_PUSH_RESULT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPushResult );
+ DEFINE_OPCODE_HANDLER(MSG_RAID_READY_CHECK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_RAID_READY_CHECK_CONFIRM, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(MSG_RAID_READY_CHECK_FINISHED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckFinishedOpcode);
+ DEFINE_OPCODE_HANDLER(MSG_RAID_TARGET_UPDATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidTargetUpdateOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_RANDOM_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRandomRollOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_SAVE_GUILD_EMBLEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSaveGuildEmblemOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_SET_DUNGEON_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetDungeonDifficultyOpcode);
+ DEFINE_OPCODE_HANDLER(MSG_SET_RAID_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetRaidDifficultyOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_TABARDVENDOR_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTabardVendorActivateOpcode);
+ DEFINE_OPCODE_HANDLER(MSG_TALENT_WIPE_CONFIRM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTalentWipeConfirmOpcode );
+ DEFINE_OPCODE_HANDLER(MSG_VERIFY_CONNECTIVITY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess );
+ DEFINE_OPCODE_HANDLER(SMSG_ACCOUNT_DATA_TIMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACCOUNT_INFO_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACCOUNT_RESTRICTED_WARNING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACHIEVEMENT_DELETED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACHIEVEMENT_EARNED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACTION_BUTTONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ACTIVATETAXIREPLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ADDON_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ADD_RUNE_POWER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AI_REACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ALL_ACHIEVEMENT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AREA_SPIRIT_HEALER_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AREA_TRIGGER_MESSAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AREA_TRIGGER_MOVEMENT_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_ERROR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_UNIT_DESTROYED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_ROSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ARENA_TEAM_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKERSTATEUPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSTART, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSTOP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSWING_BADFACING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSWING_CANT_ATTACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSWING_DEADTARGET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ATTACKSWING_NOTINRANGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_BIDDER_LIST_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_BIDDER_NOTIFICATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_LIST_PENDING_SALES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_LIST_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_OWNER_LIST_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_OWNER_NOTIFICATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUCTION_REMOVED_NOTIFICATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AURA_POINTS_DEPLETED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AURA_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AURA_UPDATE_ALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUTH_CHALLENGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AUTH_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AVAILABLE_VOICE_CHANNEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_AVERAGE_ITEM_LEVEL_INFORM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BARBER_SHOP_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_EJECTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_EJECT_PENDING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_ENTERED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_EXIT_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_QUEUE_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_STATE_CHANGE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_PLAYER_POSITIONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_PORT_DENIED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_RATED_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_QUEUED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_ACTIVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_NEEDCONFIRMATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_WAITFORGROUPS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEGROUND_INFO_THROTTLED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_JOINED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_LEFT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BINDER_CONFIRM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BINDPOINTUPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BREAK_TARGET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BUY_BANK_SLOT_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BUY_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_BUY_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_ARENA_TEAM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_CLEAR_PENDING_ACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_ALERT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_NOTES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_REMOVED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_REMOVED_ALERT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_UPDATED_ALERT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_FILTER_GUILD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_RAID_LOCKOUT_ADDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_RAID_LOCKOUT_REMOVED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_RAID_LOCKOUT_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_SEND_CALENDAR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_SEND_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_SEND_NUM_PENDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CAMERA_SHAKE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CANCEL_AUTO_REPEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CANCEL_COMBAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CAST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHANNEL_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHANNEL_MEMBER_COUNT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHARACTER_LOGIN_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_CREATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_DELETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_ENUM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_FACTION_CHANGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAR_RENAME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_IGNORED_ACCOUNT_MUTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_NOT_IN_PARTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_PLAYER_AMBIGUOUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_PLAYER_NOT_FOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_RESTRICTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_SERVER_DISCONNECTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_SERVER_RECONNECTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CHAT_WRONG_FACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLEAR_BOSS_EMOTES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLEAR_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLEAR_COOLDOWNS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLEAR_TARGET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLIENTCACHE_VERSION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CLIENT_CONTROL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMBAT_EVENT_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_MAP_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_PARTY_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_PLAYER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT1, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT2, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_STATE_CHANGED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMPLAIN_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_MOVES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMSAT_CONNECT_FAIL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMSAT_DISCONNECT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COMSAT_RECONNECT_TRY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CONTACT_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CONVERT_RUNE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COOLDOWN_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_COOLDOWN_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CORPSE_NOT_IN_INSTANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CORPSE_RECLAIM_DELAY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CREATURE_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CRITERIA_DELETED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CRITERIA_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CROSSED_INEBRIATION_THRESHOLD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CURRENCY_LOOT_REMOVED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CURRENCY_LOOT_RESTORED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_CUSTOM_LOAD_SCREEN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DAMAGE_CALC_LOG, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DANCE_QUERY_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DB_REPLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DEATH_RELEASE_LOC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DEBUG_RUNE_REGEN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DEFENSE_MESSAGE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DESTROY_OBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DESTRUCTIBLE_BUILDING_DAMAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DIFFERENT_INSTANCE_FROM_PARTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DISENCHANT_CREDIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DISMOUNT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DISMOUNTRESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DISPEL_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DISPLAY_GAME_ERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DONT_AUTO_PUSH_SPELLS_TO_ACTION_BAR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DROP_NEW_CONNECTION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_COUNTDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_INBOUNDS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_OUTOFBOUNDS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_REQUESTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUEL_WINNER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DUMP_RIDE_TICKETS_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_DURABILITY_DAMAGE_DEATH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ECHO_PARTY_SQUELCH, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EMOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ENABLE_BARBER_SHOP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ENCHANTMENTLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ENVIRONMENTALDAMAGELOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EQUIPMENT_SET_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EQUIPMENT_SET_SAVED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EQUIPMENT_SET_USE_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EXPECTED_SPAM_RECORDS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_EXPLORATION_EXPERIENCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FAILED_PLAYER_CONDITION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FEATURE_SYSTEM_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FEIGN_DEATH_RESISTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FISH_ESCAPED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FISH_NOT_HOOKED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FLIGHT_SPLINE_SYNC, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FLOOD_DETECTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FORCED_DEATH_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FORCE_SEND_QUEUED_PACKETS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FORCE_SET_VEHICLE_REC_ID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FORGE_MASTER_SET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_FRIEND_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMEOBJECT_CUSTOM_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMEOBJECT_DESPAWN_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMEOBJECT_PAGETEXT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMEOBJECT_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMEOBJECT_RESET_STATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMESPEED_SET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMETIME_SET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAMETIME_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAME_EVENT_DEBUG_LOG, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GAME_OBJECT_ACTIVATE_ANIM_KIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMRESPONSE_DB_ERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMRESPONSE_RECEIVED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMRESPONSE_STATUS_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_CREATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_DELETETICKET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_GETTICKET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_SYSTEMSTATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_UPDATETEXT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GM_MESSAGECHAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GM_PLAYER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GM_TICKET_STATUS_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GODMODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GOSSIP_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GOSSIP_MESSAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GOSSIP_POI, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUPACTION_THROTTLED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_CANCEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_DECLINE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_DESTROYED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_SET_LEADER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_SET_ROLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GROUP_UNINVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_DELETED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_EARNED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_MEMBERS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_BANK_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_BANK_LOG_QUERY_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_BANK_MONEY_WITHDRAWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_BANK_QUERY_TEXT_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_CHALLENGE_COMPLETED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_CHALLENGE_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_CHANGE_NAME_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_COMMAND_RESULT_2, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_CRITERIA_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_CRITERIA_DELETED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_DECLINE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_EVENT_LOG_QUERY_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_FLAGGED_FOR_RENAME, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_INVITE_CANCEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MAX_DAILY_XP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBERS_FOR_RECIPE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBER_DAILY_RESET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBER_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBER_UPDATE_NOTE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MOVE_COMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MOVE_STARTING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_NEWS_DELETED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_NEWS_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_PARTY_STATE_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_PERMISSIONS_QUERY_RESULTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_RANK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_RANKS_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_RENAMED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_REPUTATION_REACTION_CHANGED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_REPUTATION_WEEKLY_CAP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_RESET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_REWARDS_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_ROSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_UPDATE_ROSTER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP_GAIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_HEALTH_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_HIGHEST_THREAT_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_HOTFIX_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_HOTFIX_NOTIFY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INITIALIZE_FACTIONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INITIAL_SPELLS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INIT_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INIT_WORLD_STATES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSPECT_HONOR_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSPECT_RATED_BG_STATS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSPECT_RESULTS_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSPECT_TALENT, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSTANCE_LOCK_WARNING_QUERY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSTANCE_RESET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSTANCE_RESET_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INSTANCE_SAVE_CREATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INVALIDATE_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INVALIDATE_PLAYER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INVALID_PROMOTION_CODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_INVENTORY_CHANGE_FAILURE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_ADD_PASSIVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_ENCHANT_TIME_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_EXPIRE_PURCHASE_REFUND, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_PUSH_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_REFUND_INFO_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_REFUND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_REMOVE_PASSIVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_SEND_PASSIVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_TEXT_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ITEM_TIME_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LEARNED_DANCE_MOVES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LEARNED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LEVELUP_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_BOOT_PROPOSAL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_DISABLED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_JOIN_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_OFFER_CONTINUE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_PARTY_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_PLAYER_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_PLAYER_REWARD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_PROPOSAL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_QUEUE_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_ROLE_CHECK_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_ROLE_CHOSEN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_SLOT_INVALID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_TELEPORT_DENIED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_SEARCH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_STATUS_NONE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICANT_LIST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_BROWSE_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_POST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_RECRUIT_LIST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LIST_INVENTORY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOGIN_SETTIMESPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOGIN_VERIFY_WORLD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOGOUT_CANCEL_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOGOUT_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOGOUT_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOG_XPGAIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_ALL_PASSED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_CLEAR_MONEY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_CONTENTS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_ITEM_NOTIFY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_MASTER_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_MONEY_NOTIFY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_RELEASE_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_REMOVED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_ROLL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_ROLL_WON, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_SLOT_CHANGED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_LOOT_START_ROLL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MAIL_LIST_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MAP_OBJ_EVENTS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_IN_PROGRESS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MESSAGECHAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MESSAGE_BOX, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MINIGAME_SETUP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MINIGAME_STATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MIRRORIMAGE_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MISSILE_CANCEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MODIFY_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MONEY_NOTIFY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MONSTER_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MONSTER_MOVE_TRANSPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOTD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOUNTRESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOUNTSPECIAL_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_COLLISION_DISABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_COLLISION_ENABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_FEATHER_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_GRAVITY_DISABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_GRAVITY_ENABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_KNOCK_BACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_LAND_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_NORMAL_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_ROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_ACTIVE_MOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_CAN_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_COLLISION_HEIGHT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_COMPOUND_STATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_FLIGHT_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_RUN_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_SWIM_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_SWIM_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_TURN_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_WALK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_CAN_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_COLLISION_HEIGHT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_FLIGHT_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_KNOCK_BACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_PITCH_RATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_RUN_BACK_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_SWIM_BACK_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_SWIM_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_TURN_RATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_WALK_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MOVE_WATER_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_MULTIPLE_PACKETS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NAME_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NEW_TAXI_PATH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NEW_WORLD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NEW_WORLD_ABORT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NOTIFICATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NOTIFY_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NOTIFY_DEST_LOC_SPELL_CAST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_NPC_TEXT_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_OFFER_PETITION_ERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_OPEN_CONTAINER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_OPEN_LFG_DUNGEON_FINDER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_OVERRIDE_LIGHT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PAGE_TEXT_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PARTYKILLLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PARTY_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATS_FULL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PAUSE_MIRROR_TIMER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PERIODICAURALOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETGODMODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETITION_ALREADY_SIGNED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETITION_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETITION_SHOWLIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETITION_SHOW_SIGNATURES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PETITION_SIGN_RESULTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_ACTION_FEEDBACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_ACTION_SOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_ADDED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_BROKEN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_CAST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_DISMISS_SOUND, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_GUIDS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_LEARNED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_MODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_NAME_INVALID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_NAME_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_REMOVED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_RENAMEABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_SLOT_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_SPELLS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_TAME_FAILURE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PET_UPDATE_COMBO_POINTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYED_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYERBINDERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYERBOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYER_DIFFICULTY_CHANGE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYER_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYER_SKINNED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAYER_VEHICLE_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_DANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_MUSIC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_OBJECT_SOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_ONE_SHOT_ANIM_KIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_SOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_SPELL_VISUAL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_SPELL_VISUAL_KIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PLAY_TIME_WARNING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PONG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_POWER_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PRE_RESURRECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PROCRESIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PROPOSE_LEVEL_GRANT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PVP_CREDIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PVP_LOG_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_PVP_OPTIONS_ENABLED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUERY_TIME_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_OFFER_REWARD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_DETAILS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_INVALID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_REQUEST_ITEMS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTGIVER_STATUS_MULTIPLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTLOG_FULL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_ADD_KILL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_ADD_PVP_KILL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_FAILEDTIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUEST_CONFIRM_ACCEPT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUEST_FORCE_REMOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUEST_NPC_QUERY_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUEST_POI_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_QUEST_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_GROUP_ONLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_INSTANCE_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_INSTANCE_MESSAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_MARKERS_CHANGED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_READY_CHECK_THROTTLED_ERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RAID_SUMMON_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RANDOMIZE_CHAR_NAME, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RATED_BG_RATING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RATED_BG_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_READ_ITEM_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_READ_ITEM_OK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REALM_SPLIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REAL_GROUP_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RECEIVED_MAIL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REDIRECT_CLIENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_EXPIRED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_FAILURE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REFORGE_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REMOVED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REPORT_PVP_AFK_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REQUEST_CEMETERY_LIST_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_REQUEST_PVP_REWARDS_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESEARCH_COMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESEARCH_SETUP_HISTORY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESET_COMPRESSION_CONTEXT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESET_FAILED_NOTIFY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ROLE_POLL_BEGIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_RWHOIS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SELL_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SEND_MAIL_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SEND_UNLEARN_SPELLS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SERVERTIME, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SERVER_FIRST_ACHIEVEMENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SERVER_INFO_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SERVER_MESSAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SERVER_PERF, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_DF_FAST_LAUNCH_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_FACTION_ATWAR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_FACTION_STANDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_FACTION_VISIBLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_FLAT_SPELL_MODIFIER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_FORCED_REACTIONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PCT_SPELL_MODIFIER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PHASE_SHIFT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PLAY_HOVER_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PROFICIENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PROJECTILE_POSITION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SHOWTAXINODES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SHOW_BANK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SHOW_MAILBOX, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SHOW_RATINGS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SOCKET_GEMS_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SOR_START_EXPERIENCE_INCOMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLBREAKLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLDAMAGESHIELD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLDISPELLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLENERGIZELOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLHEALLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLINSTAKILLLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLINTERRUPTLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLLOGEXECUTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLLOGMISS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLNONMELEEDAMAGELOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLORDAMAGE_IMMUNE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELLSTEALLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_CATEGORY_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_DELAYED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_FAILED_OTHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_FAILURE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPELL_UPDATE_CHAIN_TARGETS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPIRIT_HEALER_CONFIRM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_COLLISION_DISABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_COLLISION_ENABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_GRAVITY_DISABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_GRAVITY_ENABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_ROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FEATHER_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FLYING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_LAND_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_NORMAL_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_RUN_MODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_SWIM_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_TURN_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_WALK_MODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_WALK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_WATER_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_START_SWIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_STOP_SWIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNSET_FLYING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNSET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_STABLE_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_STANDSTATE_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_START_MIRROR_TIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_START_TIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_STOP_DANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_STOP_MIRROR_TIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_STREAMING_MOVIE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUMMON_CANCEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUMMON_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUPERCEDED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUPPRESS_NPC_GREETINGS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUSPEND_COMMS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TALENTS_ERROR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TALENTS_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TALENTS_INVOLUNTARILY_RESET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TAXINODE_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TEST_DROP_RATE_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TEXT_EMOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_THREAT_CLEAR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_THREAT_REMOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_THREAT_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TIME_ADJUSTMENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TIME_SYNC_REQ, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TITLE_EARNED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TOGGLE_XP_GAIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TOTEM_CREATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRADE_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRADE_STATUS_EXTENDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRAINER_BUY_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRAINER_BUY_SUCCEEDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRAINER_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRANSFER_ABORTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRANSFER_PENDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRIGGER_CINEMATIC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TRIGGER_MOVIE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TURN_IN_PETITION_RESULTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_TUTORIAL_FLAGS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UNIT_HEALTH_FREQUENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UNIT_SPELLCAST_START, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_ACCOUNT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_COMBO_POINTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_CURRENCY_WEEK_LIMIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_DUNGEON_ENCOUNTER_FOR_LOOT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_INSTANCE_OWNERSHIP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_LAST_INSTANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_OBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_SERVER_PLAYER_POSITION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_UPDATE_WORLD_STATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_USERLIST_ADD, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_USERLIST_REMOVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_USERLIST_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICESESSION_FULL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICE_CHAT_STATUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICE_PARENTAL_CONTROLS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICE_SESSION_LEAVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICE_SESSION_ROSTER_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOICE_SET_TALKER_MUTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOID_ITEM_SWAP_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOID_STORAGE_CONTENTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOID_STORAGE_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOID_STORAGE_TRANSFER_CHANGES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_VOID_TRANSFER_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WAIT_QUEUE_FINISH, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WAIT_QUEUE_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WARDEN_DATA, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WARGAME_CHECK_ENTRY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WARGAME_REQUEST_SENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WEATHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WEEKLY_LAST_RESET, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WEEKLY_RESET_CURRENCY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WEEKLY_SPELL_USAGE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WEEKLY_SPELL_USAGE_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WHO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WHOIS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WORLD_SERVER_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_WORLD_STATE_UI_TIMER_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_XP_GAIN_ABORTED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_ZONE_UNDER_ATTACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+
+ // These opcodes are not in WPP
+
+ //DEFINE_OPCODE_HANDLER(CMSG_ACTIVE_PVP_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_ADD_PVP_MEDAL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_ADVANCE_SPAWN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AFK_MONITOR_INFO_CLEAR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AFK_MONITOR_INFO_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AUTH_SRP6_BEGIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AUTH_SRP6_PROOF, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AUTH_SRP6_RECODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AUTOEQUIP_GROUND_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_AUTOSTORE_GROUND_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_JOIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MANAGER_ADVANCE_STATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MANAGER_SET_NEXT_TRANSITION_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_REQUEST_SCORE_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); Need to send the response
+ //DEFINE_OPCODE_HANDLER(CMSG_BATTLEMASTER_HELLO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterHelloOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_BEASTMASTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BOOTME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BOT_DETECTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BOT_DETECTED2, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BUY_ITEM_IN_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyItemInSlotOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_BUY_LOTTERY_TICKET_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_BUY_STABLE_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyStableSlot );
+ //DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_INVITE_NOTES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CANCEL_GROWTH_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelGrowthAuraOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHANGE_GDF_ARENA_RATING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHANGE_PERSONAL_ARENA_RATING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHARACTER_POINT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_PLAYER_LOGIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_PLAYER_LOOKUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_SETMONEY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_SET_ARENA_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHEAT_SET_HONOR_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CHECK_LOGIN_CRITERIA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CLEAR_EXPLORATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CLEAR_HOLIDAY_BG_WIN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CLEAR_QUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CLEAR_RANDOM_BG_WIN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CLEAR_SERVER_BUCK_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_COMPLETE_ACHIEVEMENT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CONTROLLER_EJECT_PASSENGER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEjectPassenger );
+ //DEFINE_OPCODE_HANDLER(CMSG_COOLDOWN_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CREATEGAMEOBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CREATEITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_CREATEMONSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DBLOOKUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_ACTIONS_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_ACTIONS_STOP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_AISTATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_CHANGECELLZONE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_LIST_TARGETS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_PASSIVE_AURA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEBUG_SERVER_GEO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DECHARGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DECLINE_CHANNEL_INVITE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleChannelDeclineInvite );
+ //DEFINE_OPCODE_HANDLER(CMSG_DELETE_DANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DEL_PVP_MEDAL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DESTROYMONSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DESTROY_ITEMS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DISABLE_PVP_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DROP_NEW_CONNECTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_DUMP_OBJECTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_ENABLE_DAMAGE_LOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_END_BATTLEFIELD_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_EXPIRE_RAID_INSTANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FLAG_QUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FLAG_QUEST_FINISH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FLOOD_GRACE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FORCEACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FORCEACTIONONOTHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FORCEACTIONSHOW, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FORCE_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_FORCE_SAY_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GAMESPEED_SET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GAMETIME_SET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GETDEATHBINDZONE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GET_CHANNEL_MEMBER_COUNT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetChannelMemberCount );
+ //DEFINE_OPCODE_HANDLER(CMSG_GHOST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GMRESPONSE_CREATE_TICKET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_CHARACTER_RESTORE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_CHARACTER_SAVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_CREATE_ITEM_TARGET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_DESTROY_ONLINE_CORPSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_FREEZE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_GRANT_ACHIEVEMENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_INVIS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_MOVECORPSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_NUKE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_NUKE_ACCOUNT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_NUKE_CHARACTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_REMOVE_ACHIEVEMENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_REQUEST_PLAYER_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_RESURRECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_REVEALTO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_SET_CRITERIA_FOR_PLAYER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_SET_SECURITY_GROUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_SHOW_COMPLAINTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_SILENCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_SUMMONMOB, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_TEACH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_UBERINVIS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_UNSQUELCH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_UNTEACH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_UPDATE_TICKET_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_VISION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GM_WHISPER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GODMODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GROUP_CANCEL, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GROUP_UNINVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupUninviteOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_NOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_GUILD_CREATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildCreateOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_GUILD_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildInfoOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_IGNORE_KNOCKBACK_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_IGNORE_REQUIREMENTS_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_INSTANCE_LOCK_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInstanceLockResponse );
+ //DEFINE_OPCODE_HANDLER(CMSG_LEARN_DANCE_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LEARN_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LEVEL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_NEEDS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_JOIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LOAD_DANCES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LOTTERY_QUERY_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_LUA_USAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MAELSTROM_GM_SENT_MAIL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MAELSTROM_INVALIDATE_CACHE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MAELSTROM_RENAME_GUILD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MAKEMONSTERATTACKGUID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_COMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(CMSG_MEETINGSTONE_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_CHARACTER_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_CHARM_PORT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_CHARM_TELEPORT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_ENABLE_SWIM_TO_FLY_TRANS_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_RELATIVE_POSITION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_VEHICLE_REC_ID_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_START_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_MOVE_STOP_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_NEW_SPELL_SLOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_NO_SPELL_VARIANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PERFORM_ACTION_SET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PETGODMODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PET_LEVEL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PET_NAME_CACHE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PET_UNLEARN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PET_UNLEARN_TALENTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PLAYER_AI_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PLAYER_DIFFICULTY_CHANGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PLAYER_LOGOUT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayerLogoutOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_PROFILEDATA_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_PVP_QUEUE_STATS_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_MAX_XP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUERY_OBJECT_POSITION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUERY_OBJECT_ROTATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUERY_SERVER_BUCK_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUERY_VEHICLE_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_CANCEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCancel );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUESTGIVER_QUEST_AUTOLAUNCH, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQuestAutoLaunch );
+ //DEFINE_OPCODE_HANDLER(CMSG_QUESTLOG_SWAP_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogSwapQuest );
+ //DEFINE_OPCODE_HANDLER(CMSG_RECHARGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_REDIRECTION_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_REFER_A_FRIEND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_REMOVE_GLYPH, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRemoveGlyph );
+ //DEFINE_OPCODE_HANDLER(CMSG_REPLACE_ACCOUNT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_RUN_SCRIPT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SAVE_DANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SAVE_PLAYER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEARCH_LFG_JOIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrJoinOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEARCH_LFG_LEAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrLeaveOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEND_COMBAT_TRIGGER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEND_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEND_GENERAL_TRIGGER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SEND_LOCAL_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SERVERINFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SERVERTIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SERVER_BROADCAST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SERVER_COMMAND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SERVER_INFO_QUERY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SETDEATHBINDPOINT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ACTIVE_TALENT_GROUP_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ARENA_MEMBER_SEASON_GAMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ARENA_MEMBER_WEEKLY_GAMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ARENA_TEAM_RATING_BY_INDEX, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ARENA_TEAM_SEASON_GAMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_ARENA_TEAM_WEEKLY_GAMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_BREATH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_CHARACTER_MODEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_CRITERIA_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_DURABILITY_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_EXPLORATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_EXPLORATION_ALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_FACTION_CHEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionCheat );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_GLYPH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_GLYPH_SLOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_GRANTABLE_LEVELS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_LFG_COMMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetCommentOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_PAID_SERVICE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_PVP_RANK_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_PVP_TITLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_RUNE_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_RUNE_COUNT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_SKILL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_STAT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_TITLE_SUFFIX, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_WORLDSTATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SKILL_BUY_RANK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SKILL_BUY_STEP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_STABLE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStablePet );
+ //DEFINE_OPCODE_HANDLER(CMSG_STABLE_REVIVE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStableRevivePet );
+ //DEFINE_OPCODE_HANDLER(CMSG_STABLE_SWAP_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStableSwapPet );
+ //DEFINE_OPCODE_HANDLER(CMSG_START_BATTLEFIELD_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_START_QUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_STORE_LOOT_IN_SLOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_SUSPEND_COMMS_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TARGET_CAST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TARGET_SCRIPT_CAST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TAXICLEARALLNODES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TAXICLEARNODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TAXIENABLEALLNODES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TAXIENABLENODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TAXISHOWNODES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TEST_DROP_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TOGGLE_XP_GAIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_TRIGGER_CINEMATIC_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNCLAIM_LICENSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNDRESSPLAYER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNITANIMTIER_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNLEARN_DANCE_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNLEARN_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNLEARN_TALENTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNSTABLE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnstablePet );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNUSED5, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_UNUSED6, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_USE_SKILL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_VOICE_SET_TALKER_MUTED_REQUEST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_WEATHER_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_XP_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(CMSG_ZONE_MAP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_DELAY_GHOST_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_DEV_SHOWLABEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_ACCOUNT_ONLINE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_BIND_OTHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_CHANGE_ARENA_RATING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_DESTROY_CORPSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_GEARRATING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_RESETINSTANCELIMIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_SHOWLABEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_GM_SUMMON, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_ALL_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_FLIGHT_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_PITCH_RATE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RAW_POSITION_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RUN_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_SWIM_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_TURN_RATE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_WALK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_START_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_TOGGLE_FALL_LOGGING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_MOVE_TOGGLE_LOGGING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_NULL_ACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(MSG_PVP_LOG_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePVPLogDataOpcode );
+ //DEFINE_OPCODE_HANDLER(MSG_VIEW_PHASE_SHIFT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ //DEFINE_OPCODE_HANDLER(SMSG_AFK_MONITOR_INFO_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_AURACASTLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_BINDZONEREPLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_ACTION_PENDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_UPDATE_INVITE_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHANGEPLAYER_DIFFICULTY_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHARACTER_PROFILE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHARACTER_PROFILE_REALM_CONNECTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHEAT_PLAYER_LOOKUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CHECK_FOR_BOTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_COMBAT_LOG_MULTIPLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_GET_PLAYER_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_COMPLETION_NPC_RESPONCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_CORPSE_IS_NOT_IN_INSTANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DAMAGE_DONE_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DBLOOKUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DEBUGAURAPROC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DEBUG_AISTATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DEBUG_LIST_TARGETS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DEBUG_SERVER_GEO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DUMP_OBJECTS_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_DYNAMIC_DROP_ROLL_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_FORCEACTIONSHOW, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_FORCE_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_FORCE_DISPLAY_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GAMETIMEBIAS_SET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GHOSTEE_GONE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GMRESPONSE_CREATE_TICKET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GOGOGO_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_CANCEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_KNOWN_RECIPES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_SET_NOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_TRADESKILL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_IGNORE_REQUIREMENTS_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_INSPECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_JOINED_BATTLEGROUND_QUEUE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_KICK_REASON, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LFG_OPEN_FROM_GOSSIP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_SEARCH_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LOTTERY_QUERY_RESULT_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LOTTERY_RESULT_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_MEMBER_ADDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_SETQUEUE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MINIGAME_MOVE_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MOVE_CHARACTER_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_VEHICLE_REC_ID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_WALK_IN_AIR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SKIP_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_WALK_IN_AIR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_NPC_WONT_TALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_PET_UNLEARN_CONFIRM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_PLAYER_UNK_DEAD_ALIVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_PROFILEDATA_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_PUREMOUNT_CANCELLED_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_PVP_QUEUE_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_QUERY_OBJECT_POSITION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_QUERY_OBJECT_ROTATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_RAID_READY_CHECK_ERROR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_REMOVED_FROM_PVP_QUEUE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_RESET_RANGED_COMBAT_TIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_RESISTLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_RESUME_CAST_BAR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_RESURRECT_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SCRIPT_MESSAGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SEND_ALL_COMBAT_LOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SERVERINFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SERVER_BUCK_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SERVER_BUCK_DATA_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SET_EXTRA_AURA_INFO_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SPELL_CHANCE_PROC_LOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_SPELL_CHANCE_RESIST_PUSHBACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_VOICE_SESSION_ADJUST_PRIORITY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_VOICE_SESSION_ENABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_ZONE_MAP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+
+#undef DEFINE_OPCODE_HANDLER
};
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index 7b07abdf962..4047b1b42c5 100644
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -28,1318 +28,1353 @@
/// List of Opcodes
enum Opcodes
{
- MSG_NULL_ACTION = 0x000,
- CMSG_BOOTME = 0x001,
- CMSG_DBLOOKUP = 0x002,
- SMSG_DBLOOKUP = 0x003,
- CMSG_QUERY_OBJECT_POSITION = 0x004,
- SMSG_QUERY_OBJECT_POSITION = 0x005,
- CMSG_QUERY_OBJECT_ROTATION = 0x006,
- SMSG_QUERY_OBJECT_ROTATION = 0x007,
- CMSG_WORLD_TELEPORT = 0x008,
- CMSG_TELEPORT_TO_UNIT = 0x009,
- CMSG_ZONE_MAP = 0x00A,
- SMSG_ZONE_MAP = 0x00B,
- CMSG_DEBUG_CHANGECELLZONE = 0x00C,
- CMSG_MOVE_CHARACTER_CHEAT = 0x00D,
- SMSG_MOVE_CHARACTER_CHEAT = 0x00E,
- CMSG_RECHARGE = 0x00F,
- CMSG_LEARN_SPELL = 0x010,
- CMSG_CREATEMONSTER = 0x011,
- CMSG_DESTROYMONSTER = 0x012,
- CMSG_CREATEITEM = 0x013,
- CMSG_CREATEGAMEOBJECT = 0x014,
- SMSG_CHECK_FOR_BOTS = 0x015,
- CMSG_MAKEMONSTERATTACKGUID = 0x016,
- CMSG_BOT_DETECTED2 = 0x017,
- CMSG_FORCEACTION = 0x018,
- CMSG_FORCEACTIONONOTHER = 0x019,
- CMSG_FORCEACTIONSHOW = 0x01A,
- SMSG_FORCEACTIONSHOW = 0x01B,
- CMSG_PETGODMODE = 0x01C,
- SMSG_PETGODMODE = 0x01D,
- SMSG_REFER_A_FRIEND_EXPIRED = 0x01E,
- CMSG_WEATHER_SPEED_CHEAT = 0x01F,
- CMSG_UNDRESSPLAYER = 0x020,
- CMSG_BEASTMASTER = 0x021,
- CMSG_GODMODE = 0x022,
- SMSG_GODMODE = 0x023,
- CMSG_CHEAT_SETMONEY = 0x024,
- CMSG_LEVEL_CHEAT = 0x025,
- CMSG_PET_LEVEL_CHEAT = 0x026,
- CMSG_SET_WORLDSTATE = 0x027,
- CMSG_COOLDOWN_CHEAT = 0x028,
- CMSG_USE_SKILL_CHEAT = 0x029,
- CMSG_FLAG_QUEST = 0x02A,
- CMSG_FLAG_QUEST_FINISH = 0x02B,
- CMSG_CLEAR_QUEST = 0x02C,
- CMSG_SEND_EVENT = 0x02D,
- CMSG_DEBUG_AISTATE = 0x02E,
- SMSG_DEBUG_AISTATE = 0x02F,
- CMSG_DISABLE_PVP_CHEAT = 0x030,
- CMSG_ADVANCE_SPAWN_TIME = 0x031,
- SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x032,
- CMSG_AUTH_SRP6_BEGIN = 0x033,
- CMSG_AUTH_SRP6_PROOF = 0x034,
- CMSG_AUTH_SRP6_RECODE = 0x035,
- CMSG_CHAR_CREATE = 0x036,
- CMSG_CHAR_ENUM = 0x037,
- CMSG_CHAR_DELETE = 0x038,
- SMSG_AUTH_SRP6_RESPONSE = 0x039,
- SMSG_CHAR_CREATE = 0x03A,
- SMSG_CHAR_ENUM = 0x03B,
- SMSG_CHAR_DELETE = 0x03C,
- CMSG_PLAYER_LOGIN = 0x03D,
- SMSG_NEW_WORLD = 0x03E,
- SMSG_TRANSFER_PENDING = 0x03F,
- SMSG_TRANSFER_ABORTED = 0x040,
- SMSG_CHARACTER_LOGIN_FAILED = 0x041,
- SMSG_LOGIN_SETTIMESPEED = 0x042,
- SMSG_GAMETIME_UPDATE = 0x043,
- CMSG_GAMETIME_SET = 0x044,
- SMSG_GAMETIME_SET = 0x045,
- CMSG_GAMESPEED_SET = 0x046,
- SMSG_GAMESPEED_SET = 0x047,
- CMSG_SERVERTIME = 0x048,
- SMSG_SERVERTIME = 0x049,
- CMSG_PLAYER_LOGOUT = 0x04A,
- CMSG_LOGOUT_REQUEST = 0x04B,
- SMSG_LOGOUT_RESPONSE = 0x04C,
- SMSG_LOGOUT_COMPLETE = 0x04D,
- CMSG_LOGOUT_CANCEL = 0x04E,
- SMSG_LOGOUT_CANCEL_ACK = 0x04F,
- CMSG_NAME_QUERY = 0x050,
- SMSG_NAME_QUERY_RESPONSE = 0x051,
- CMSG_PET_NAME_QUERY = 0x052,
- SMSG_PET_NAME_QUERY_RESPONSE = 0x053,
- CMSG_GUILD_QUERY = 0x054,
- SMSG_GUILD_QUERY_RESPONSE = 0x055,
- CMSG_ITEM_QUERY_SINGLE = 0x056,
- CMSG_ITEM_QUERY_MULTIPLE = 0x057,
- SMSG_ITEM_QUERY_SINGLE_RESPONSE = 0x058,
- SMSG_ITEM_QUERY_MULTIPLE_RESPONSE = 0x059,
- CMSG_PAGE_TEXT_QUERY = 0x05A,
- SMSG_PAGE_TEXT_QUERY_RESPONSE = 0x05B,
- CMSG_QUEST_QUERY = 0x05C,
- SMSG_QUEST_QUERY_RESPONSE = 0x05D,
- CMSG_GAMEOBJECT_QUERY = 0x05E,
- SMSG_GAMEOBJECT_QUERY_RESPONSE = 0x05F,
- CMSG_CREATURE_QUERY = 0x060,
- SMSG_CREATURE_QUERY_RESPONSE = 0x061,
- CMSG_WHO = 0x062,
- SMSG_WHO = 0x063,
- CMSG_WHOIS = 0x064,
- SMSG_WHOIS = 0x065,
- CMSG_CONTACT_LIST = 0x066,
- SMSG_CONTACT_LIST = 0x067,
- SMSG_FRIEND_STATUS = 0x068,
- CMSG_ADD_FRIEND = 0x069,
- CMSG_DEL_FRIEND = 0x06A,
- CMSG_SET_CONTACT_NOTES = 0x06B,
- CMSG_ADD_IGNORE = 0x06C,
- CMSG_DEL_IGNORE = 0x06D,
- CMSG_GROUP_INVITE = 0x06E,
- SMSG_GROUP_INVITE = 0x06F,
- CMSG_GROUP_CANCEL = 0x070,
- SMSG_GROUP_CANCEL = 0x071,
- CMSG_GROUP_ACCEPT = 0x072,
- CMSG_GROUP_DECLINE = 0x073,
- SMSG_GROUP_DECLINE = 0x074,
- CMSG_GROUP_UNINVITE = 0x075,
- CMSG_GROUP_UNINVITE_GUID = 0x076,
- SMSG_GROUP_UNINVITE = 0x077,
- CMSG_GROUP_SET_LEADER = 0x078,
- SMSG_GROUP_SET_LEADER = 0x079,
- CMSG_LOOT_METHOD = 0x07A,
- CMSG_GROUP_DISBAND = 0x07B,
- SMSG_GROUP_DESTROYED = 0x07C,
- SMSG_GROUP_LIST = 0x07D,
- SMSG_PARTY_MEMBER_STATS = 0x07E,
- SMSG_PARTY_COMMAND_RESULT = 0x07F,
- UMSG_UPDATE_GROUP_MEMBERS = 0x080,
- CMSG_GUILD_CREATE = 0x081,
- CMSG_GUILD_INVITE = 0x082,
- SMSG_GUILD_INVITE = 0x083,
- CMSG_GUILD_ACCEPT = 0x084,
- CMSG_GUILD_DECLINE = 0x085,
- SMSG_GUILD_DECLINE = 0x086,
- CMSG_GUILD_INFO = 0x087,
- SMSG_GUILD_INFO = 0x088,
- CMSG_GUILD_ROSTER = 0x089,
- SMSG_GUILD_ROSTER = 0x08A,
- CMSG_GUILD_PROMOTE = 0x08B,
- CMSG_GUILD_DEMOTE = 0x08C,
- CMSG_GUILD_LEAVE = 0x08D,
- CMSG_GUILD_REMOVE = 0x08E,
- CMSG_GUILD_DISBAND = 0x08F,
- CMSG_GUILD_LEADER = 0x090,
- CMSG_GUILD_MOTD = 0x091,
- SMSG_GUILD_EVENT = 0x092,
- SMSG_GUILD_COMMAND_RESULT = 0x093,
- UMSG_UPDATE_GUILD = 0x094,
- CMSG_MESSAGECHAT = 0x095,
- SMSG_MESSAGECHAT = 0x096,
- CMSG_JOIN_CHANNEL = 0x097,
- CMSG_LEAVE_CHANNEL = 0x098,
- SMSG_CHANNEL_NOTIFY = 0x099,
- CMSG_CHANNEL_LIST = 0x09A,
- SMSG_CHANNEL_LIST = 0x09B,
- CMSG_CHANNEL_PASSWORD = 0x09C,
- CMSG_CHANNEL_SET_OWNER = 0x09D,
- CMSG_CHANNEL_OWNER = 0x09E,
- CMSG_CHANNEL_MODERATOR = 0x09F,
- CMSG_CHANNEL_UNMODERATOR = 0x0A0,
- CMSG_CHANNEL_MUTE = 0x0A1,
- CMSG_CHANNEL_UNMUTE = 0x0A2,
- CMSG_CHANNEL_INVITE = 0x0A3,
- CMSG_CHANNEL_KICK = 0x0A4,
- CMSG_CHANNEL_BAN = 0x0A5,
- CMSG_CHANNEL_UNBAN = 0x0A6,
- CMSG_CHANNEL_ANNOUNCEMENTS = 0x0A7,
- CMSG_CHANNEL_MODERATE = 0x0A8,
- SMSG_UPDATE_OBJECT = 0x0A9,
- SMSG_DESTROY_OBJECT = 0x0AA,
- CMSG_USE_ITEM = 0x0AB,
- CMSG_OPEN_ITEM = 0x0AC,
- CMSG_READ_ITEM = 0x0AD,
- SMSG_READ_ITEM_OK = 0x0AE,
- SMSG_READ_ITEM_FAILED = 0x0AF,
- SMSG_ITEM_COOLDOWN = 0x0B0,
- CMSG_GAMEOBJ_USE = 0x0B1,
- CMSG_DESTROY_ITEMS = 0x0B2,
- SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x0B3,
- CMSG_AREATRIGGER = 0x0B4,
- MSG_MOVE_START_FORWARD = 0x0B5,
- MSG_MOVE_START_BACKWARD = 0x0B6,
- MSG_MOVE_STOP = 0x0B7,
- MSG_MOVE_START_STRAFE_LEFT = 0x0B8,
- MSG_MOVE_START_STRAFE_RIGHT = 0x0B9,
- MSG_MOVE_STOP_STRAFE = 0x0BA,
- MSG_MOVE_JUMP = 0x0BB,
- MSG_MOVE_START_TURN_LEFT = 0x0BC,
- MSG_MOVE_START_TURN_RIGHT = 0x0BD,
- MSG_MOVE_STOP_TURN = 0x0BE,
- MSG_MOVE_START_PITCH_UP = 0x0BF,
- MSG_MOVE_START_PITCH_DOWN = 0x0C0,
- MSG_MOVE_STOP_PITCH = 0x0C1,
- MSG_MOVE_SET_RUN_MODE = 0x0C2,
- MSG_MOVE_SET_WALK_MODE = 0x0C3,
- MSG_MOVE_TOGGLE_LOGGING = 0x0C4,
- MSG_MOVE_TELEPORT = 0x0C5,
- MSG_MOVE_TELEPORT_CHEAT = 0x0C6,
- MSG_MOVE_TELEPORT_ACK = 0x0C7,
- MSG_MOVE_TOGGLE_FALL_LOGGING = 0x0C8,
- MSG_MOVE_FALL_LAND = 0x0C9,
- MSG_MOVE_START_SWIM = 0x0CA,
- MSG_MOVE_STOP_SWIM = 0x0CB,
- MSG_MOVE_SET_RUN_SPEED_CHEAT = 0x0CC,
- MSG_MOVE_SET_RUN_SPEED = 0x0CD,
- MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT = 0x0CE,
- MSG_MOVE_SET_RUN_BACK_SPEED = 0x0CF,
- MSG_MOVE_SET_WALK_SPEED_CHEAT = 0x0D0,
- MSG_MOVE_SET_WALK_SPEED = 0x0D1,
- MSG_MOVE_SET_SWIM_SPEED_CHEAT = 0x0D2,
- MSG_MOVE_SET_SWIM_SPEED = 0x0D3,
- MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT = 0x0D4,
- MSG_MOVE_SET_SWIM_BACK_SPEED = 0x0D5,
- MSG_MOVE_SET_ALL_SPEED_CHEAT = 0x0D6,
- MSG_MOVE_SET_TURN_RATE_CHEAT = 0x0D7,
- MSG_MOVE_SET_TURN_RATE = 0x0D8,
- MSG_MOVE_TOGGLE_COLLISION_CHEAT = 0x0D9,
- MSG_MOVE_SET_FACING = 0x0DA,
- MSG_MOVE_SET_PITCH = 0x0DB,
- MSG_MOVE_WORLDPORT_ACK = 0x0DC,
- SMSG_MONSTER_MOVE = 0x0DD,
- SMSG_MOVE_WATER_WALK = 0x0DE,
- SMSG_MOVE_LAND_WALK = 0x0DF,
- CMSG_MOVE_CHARM_PORT_CHEAT = 0x0E0,
- CMSG_MOVE_SET_RAW_POSITION = 0x0E1,
- SMSG_FORCE_RUN_SPEED_CHANGE = 0x0E2,
- CMSG_FORCE_RUN_SPEED_CHANGE_ACK = 0x0E3,
- SMSG_FORCE_RUN_BACK_SPEED_CHANGE = 0x0E4,
- CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK = 0x0E5,
- SMSG_FORCE_SWIM_SPEED_CHANGE = 0x0E6,
- CMSG_FORCE_SWIM_SPEED_CHANGE_ACK = 0x0E7,
- SMSG_FORCE_MOVE_ROOT = 0x0E8,
- CMSG_FORCE_MOVE_ROOT_ACK = 0x0E9,
- SMSG_FORCE_MOVE_UNROOT = 0x0EA,
- CMSG_FORCE_MOVE_UNROOT_ACK = 0x0EB,
- MSG_MOVE_ROOT = 0x0EC,
- MSG_MOVE_UNROOT = 0x0ED,
- MSG_MOVE_HEARTBEAT = 0x0EE,
- SMSG_MOVE_KNOCK_BACK = 0x0EF,
- CMSG_MOVE_KNOCK_BACK_ACK = 0x0F0,
- MSG_MOVE_KNOCK_BACK = 0x0F1,
- SMSG_MOVE_FEATHER_FALL = 0x0F2,
- SMSG_MOVE_NORMAL_FALL = 0x0F3,
- SMSG_MOVE_SET_HOVER = 0x0F4,
- SMSG_MOVE_UNSET_HOVER = 0x0F5,
- CMSG_MOVE_HOVER_ACK = 0x0F6,
- MSG_MOVE_HOVER = 0x0F7,
- CMSG_TRIGGER_CINEMATIC_CHEAT = 0x0F8,
- CMSG_OPENING_CINEMATIC = 0x0F9,
- SMSG_TRIGGER_CINEMATIC = 0x0FA,
- CMSG_NEXT_CINEMATIC_CAMERA = 0x0FB,
- CMSG_COMPLETE_CINEMATIC = 0x0FC,
- SMSG_TUTORIAL_FLAGS = 0x0FD,
- CMSG_TUTORIAL_FLAG = 0x0FE,
- CMSG_TUTORIAL_CLEAR = 0x0FF,
- CMSG_TUTORIAL_RESET = 0x100,
- CMSG_STANDSTATECHANGE = 0x101,
- CMSG_EMOTE = 0x102,
- SMSG_EMOTE = 0x103,
- CMSG_TEXT_EMOTE = 0x104,
- SMSG_TEXT_EMOTE = 0x105,
- CMSG_AUTOEQUIP_GROUND_ITEM = 0x106,
- CMSG_AUTOSTORE_GROUND_ITEM = 0x107,
- CMSG_AUTOSTORE_LOOT_ITEM = 0x108,
- CMSG_STORE_LOOT_IN_SLOT = 0x109,
- CMSG_AUTOEQUIP_ITEM = 0x10A,
- CMSG_AUTOSTORE_BAG_ITEM = 0x10B,
- CMSG_SWAP_ITEM = 0x10C,
- CMSG_SWAP_INV_ITEM = 0x10D,
- CMSG_SPLIT_ITEM = 0x10E,
- CMSG_AUTOEQUIP_ITEM_SLOT = 0x10F,
- CMSG_UNCLAIM_LICENSE = 0x110,
- CMSG_DESTROYITEM = 0x111,
- SMSG_INVENTORY_CHANGE_FAILURE = 0x112,
- SMSG_OPEN_CONTAINER = 0x113,
- CMSG_INSPECT = 0x114,
- SMSG_INSPECT_RESULTS_UPDATE = 0x115,
- CMSG_INITIATE_TRADE = 0x116,
- CMSG_BEGIN_TRADE = 0x117,
- CMSG_BUSY_TRADE = 0x118,
- CMSG_IGNORE_TRADE = 0x119,
- CMSG_ACCEPT_TRADE = 0x11A,
- CMSG_UNACCEPT_TRADE = 0x11B,
- CMSG_CANCEL_TRADE = 0x11C,
- CMSG_SET_TRADE_ITEM = 0x11D,
- CMSG_CLEAR_TRADE_ITEM = 0x11E,
- CMSG_SET_TRADE_GOLD = 0x11F,
- SMSG_TRADE_STATUS = 0x120,
- SMSG_TRADE_STATUS_EXTENDED = 0x121,
- SMSG_INITIALIZE_FACTIONS = 0x122,
- SMSG_SET_FACTION_VISIBLE = 0x123,
- SMSG_SET_FACTION_STANDING = 0x124,
- CMSG_SET_FACTION_ATWAR = 0x125,
- CMSG_SET_FACTION_CHEAT = 0x126,
- SMSG_SET_PROFICIENCY = 0x127,
- CMSG_SET_ACTION_BUTTON = 0x128,
- SMSG_ACTION_BUTTONS = 0x129,
- SMSG_INITIAL_SPELLS = 0x12A,
- SMSG_LEARNED_SPELL = 0x12B,
- SMSG_SUPERCEDED_SPELL = 0x12C,
- CMSG_NEW_SPELL_SLOT = 0x12D,
- CMSG_CAST_SPELL = 0x12E,
- CMSG_CANCEL_CAST = 0x12F,
- SMSG_CAST_FAILED = 0x130,
- SMSG_SPELL_START = 0x131,
- SMSG_SPELL_GO = 0x132,
- SMSG_SPELL_FAILURE = 0x133,
- SMSG_SPELL_COOLDOWN = 0x134,
- SMSG_COOLDOWN_EVENT = 0x135,
- CMSG_CANCEL_AURA = 0x136,
- SMSG_EQUIPMENT_SET_SAVED = 0x137,
- SMSG_PET_CAST_FAILED = 0x138,
- MSG_CHANNEL_START = 0x139,
- MSG_CHANNEL_UPDATE = 0x13A,
- CMSG_CANCEL_CHANNELLING = 0x13B,
- SMSG_AI_REACTION = 0x13C,
- CMSG_SET_SELECTION = 0x13D,
- CMSG_DELETEEQUIPMENT_SET = 0x13E,
- CMSG_INSTANCE_LOCK_RESPONSE = 0x13F,
- CMSG_DEBUG_PASSIVE_AURA = 0x140,
- CMSG_ATTACKSWING = 0x141,
- CMSG_ATTACKSTOP = 0x142,
- SMSG_ATTACKSTART = 0x143,
- SMSG_ATTACKSTOP = 0x144,
- SMSG_ATTACKSWING_NOTINRANGE = 0x145,
- SMSG_ATTACKSWING_BADFACING = 0x146,
- SMSG_INSTANCE_LOCK_WARNING_QUERY = 0x147,
- SMSG_ATTACKSWING_DEADTARGET = 0x148,
- SMSG_ATTACKSWING_CANT_ATTACK = 0x149,
- SMSG_ATTACKERSTATEUPDATE = 0x14A,
- SMSG_BATTLEFIELD_PORT_DENIED = 0x14B,
- CMSG_PERFORM_ACTION_SET = 0x14C,
- SMSG_RESUME_CAST_BAR = 0x14D,
- SMSG_CANCEL_COMBAT = 0x14E,
- SMSG_SPELLBREAKLOG = 0x14F,
- SMSG_SPELLHEALLOG = 0x150,
- SMSG_SPELLENERGIZELOG = 0x151,
- SMSG_BREAK_TARGET = 0x152,
- CMSG_SAVE_PLAYER = 0x153,
- CMSG_SETDEATHBINDPOINT = 0x154,
- SMSG_BINDPOINTUPDATE = 0x155,
- CMSG_GETDEATHBINDZONE = 0x156,
- SMSG_BINDZONEREPLY = 0x157,
- SMSG_PLAYERBOUND = 0x158,
- SMSG_CLIENT_CONTROL_UPDATE = 0x159,
- CMSG_REPOP_REQUEST = 0x15A,
- SMSG_RESURRECT_REQUEST = 0x15B,
- CMSG_RESURRECT_RESPONSE = 0x15C,
- CMSG_LOOT = 0x15D,
- CMSG_LOOT_MONEY = 0x15E,
- CMSG_LOOT_RELEASE = 0x15F,
- SMSG_LOOT_RESPONSE = 0x160,
- SMSG_LOOT_RELEASE_RESPONSE = 0x161,
- SMSG_LOOT_REMOVED = 0x162,
- SMSG_LOOT_MONEY_NOTIFY = 0x163,
- SMSG_LOOT_ITEM_NOTIFY = 0x164,
- SMSG_LOOT_CLEAR_MONEY = 0x165,
- SMSG_ITEM_PUSH_RESULT = 0x166,
- SMSG_DUEL_REQUESTED = 0x167,
- SMSG_DUEL_OUTOFBOUNDS = 0x168,
- SMSG_DUEL_INBOUNDS = 0x169,
- SMSG_DUEL_COMPLETE = 0x16A,
- SMSG_DUEL_WINNER = 0x16B,
- CMSG_DUEL_ACCEPTED = 0x16C,
- CMSG_DUEL_CANCELLED = 0x16D,
- SMSG_MOUNTRESULT = 0x16E,
- SMSG_DISMOUNTRESULT = 0x16F,
- SMSG_REMOVED_FROM_PVP_QUEUE = 0x170,
- CMSG_MOUNTSPECIAL_ANIM = 0x171,
- SMSG_MOUNTSPECIAL_ANIM = 0x172,
- SMSG_PET_TAME_FAILURE = 0x173,
- CMSG_PET_SET_ACTION = 0x174,
- CMSG_PET_ACTION = 0x175,
- CMSG_PET_ABANDON = 0x176,
- CMSG_PET_RENAME = 0x177,
- SMSG_PET_NAME_INVALID = 0x178,
- SMSG_PET_SPELLS = 0x179,
- SMSG_PET_MODE = 0x17A,
- CMSG_GOSSIP_HELLO = 0x17B,
- CMSG_GOSSIP_SELECT_OPTION = 0x17C,
- SMSG_GOSSIP_MESSAGE = 0x17D,
- SMSG_GOSSIP_COMPLETE = 0x17E,
- CMSG_NPC_TEXT_QUERY = 0x17F,
- SMSG_NPC_TEXT_UPDATE = 0x180,
- SMSG_NPC_WONT_TALK = 0x181,
- CMSG_QUESTGIVER_STATUS_QUERY = 0x182,
- SMSG_QUESTGIVER_STATUS = 0x183,
- CMSG_QUESTGIVER_HELLO = 0x184,
- SMSG_QUESTGIVER_QUEST_LIST = 0x185,
- CMSG_QUESTGIVER_QUERY_QUEST = 0x186,
- CMSG_QUESTGIVER_QUEST_AUTOLAUNCH = 0x187,
- SMSG_QUESTGIVER_QUEST_DETAILS = 0x188,
- CMSG_QUESTGIVER_ACCEPT_QUEST = 0x189,
- CMSG_QUESTGIVER_COMPLETE_QUEST = 0x18A,
- SMSG_QUESTGIVER_REQUEST_ITEMS = 0x18B,
- CMSG_QUESTGIVER_REQUEST_REWARD = 0x18C,
- SMSG_QUESTGIVER_OFFER_REWARD = 0x18D,
- CMSG_QUESTGIVER_CHOOSE_REWARD = 0x18E,
- SMSG_QUESTGIVER_QUEST_INVALID = 0x18F,
- CMSG_QUESTGIVER_CANCEL = 0x190,
- SMSG_QUESTGIVER_QUEST_COMPLETE = 0x191,
- SMSG_QUESTGIVER_QUEST_FAILED = 0x192,
- CMSG_QUESTLOG_SWAP_QUEST = 0x193,
- CMSG_QUESTLOG_REMOVE_QUEST = 0x194,
- SMSG_QUESTLOG_FULL = 0x195,
- SMSG_QUESTUPDATE_FAILED = 0x196,
- SMSG_QUESTUPDATE_FAILEDTIMER = 0x197,
- SMSG_QUESTUPDATE_COMPLETE = 0x198,
- SMSG_QUESTUPDATE_ADD_KILL = 0x199,
- SMSG_QUESTUPDATE_ADD_ITEM = 0x19A,
- CMSG_QUEST_CONFIRM_ACCEPT = 0x19B,
- SMSG_QUEST_CONFIRM_ACCEPT = 0x19C,
- CMSG_PUSHQUESTTOPARTY = 0x19D,
- CMSG_LIST_INVENTORY = 0x19E,
- SMSG_LIST_INVENTORY = 0x19F,
- CMSG_SELL_ITEM = 0x1A0,
- SMSG_SELL_ITEM = 0x1A1,
- CMSG_BUY_ITEM = 0x1A2,
- CMSG_BUY_ITEM_IN_SLOT = 0x1A3,
- SMSG_BUY_ITEM = 0x1A4,
- SMSG_BUY_FAILED = 0x1A5,
- CMSG_TAXICLEARALLNODES = 0x1A6,
- CMSG_TAXIENABLEALLNODES = 0x1A7,
- CMSG_TAXISHOWNODES = 0x1A8,
- SMSG_SHOWTAXINODES = 0x1A9,
- CMSG_TAXINODE_STATUS_QUERY = 0x1AA,
- SMSG_TAXINODE_STATUS = 0x1AB,
- CMSG_TAXIQUERYAVAILABLENODES = 0x1AC,
- CMSG_ACTIVATETAXI = 0x1AD,
- SMSG_ACTIVATETAXIREPLY = 0x1AE,
- SMSG_NEW_TAXI_PATH = 0x1AF,
- CMSG_TRAINER_LIST = 0x1B0,
- SMSG_TRAINER_LIST = 0x1B1,
- CMSG_TRAINER_BUY_SPELL = 0x1B2,
- SMSG_TRAINER_BUY_SUCCEEDED = 0x1B3,
- SMSG_TRAINER_BUY_FAILED = 0x1B4,
- CMSG_BINDER_ACTIVATE = 0x1B5,
- SMSG_PLAYERBINDERROR = 0x1B6,
- CMSG_BANKER_ACTIVATE = 0x1B7,
- SMSG_SHOW_BANK = 0x1B8,
- CMSG_BUY_BANK_SLOT = 0x1B9,
- SMSG_BUY_BANK_SLOT_RESULT = 0x1BA,
- CMSG_PETITION_SHOWLIST = 0x1BB,
- SMSG_PETITION_SHOWLIST = 0x1BC,
- CMSG_PETITION_BUY = 0x1BD,
- CMSG_PETITION_SHOW_SIGNATURES = 0x1BE,
- SMSG_PETITION_SHOW_SIGNATURES = 0x1BF,
- CMSG_PETITION_SIGN = 0x1C0,
- SMSG_PETITION_SIGN_RESULTS = 0x1C1,
- MSG_PETITION_DECLINE = 0x1C2,
- CMSG_OFFER_PETITION = 0x1C3,
- CMSG_TURN_IN_PETITION = 0x1C4,
- SMSG_TURN_IN_PETITION_RESULTS = 0x1C5,
- CMSG_PETITION_QUERY = 0x1C6,
- SMSG_PETITION_QUERY_RESPONSE = 0x1C7,
- SMSG_FISH_NOT_HOOKED = 0x1C8,
- SMSG_FISH_ESCAPED = 0x1C9,
- CMSG_BUG = 0x1CA,
- SMSG_NOTIFICATION = 0x1CB,
- CMSG_PLAYED_TIME = 0x1CC,
- SMSG_PLAYED_TIME = 0x1CD,
- CMSG_QUERY_TIME = 0x1CE,
- SMSG_QUERY_TIME_RESPONSE = 0x1CF,
- SMSG_LOG_XPGAIN = 0x1D0,
- SMSG_AURACASTLOG = 0x1D1,
- CMSG_RECLAIM_CORPSE = 0x1D2,
- CMSG_WRAP_ITEM = 0x1D3,
- SMSG_LEVELUP_INFO = 0x1D4,
- MSG_MINIMAP_PING = 0x1D5,
- SMSG_RESISTLOG = 0x1D6,
- SMSG_ENCHANTMENTLOG = 0x1D7,
- CMSG_SET_SKILL_CHEAT = 0x1D8,
- SMSG_START_MIRROR_TIMER = 0x1D9,
- SMSG_PAUSE_MIRROR_TIMER = 0x1DA,
- SMSG_STOP_MIRROR_TIMER = 0x1DB,
- CMSG_PING = 0x1DC,
- SMSG_PONG = 0x1DD,
- SMSG_CLEAR_COOLDOWN = 0x1DE,
- SMSG_GAMEOBJECT_PAGETEXT = 0x1DF,
- CMSG_SETSHEATHED = 0x1E0,
- SMSG_COOLDOWN_CHEAT = 0x1E1,
- SMSG_SPELL_DELAYED = 0x1E2,
- CMSG_QUEST_POI_QUERY = 0x1E3,
- SMSG_QUEST_POI_QUERY_RESPONSE = 0x1E4,
- CMSG_GHOST = 0x1E5,
- CMSG_GM_INVIS = 0x1E6,
- SMSG_INVALID_PROMOTION_CODE = 0x1E7,
- MSG_GM_BIND_OTHER = 0x1E8,
- MSG_GM_SUMMON = 0x1E9,
- SMSG_ITEM_TIME_UPDATE = 0x1EA,
- SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x1EB,
- SMSG_AUTH_CHALLENGE = 0x1EC,
- CMSG_AUTH_SESSION = 0x1ED,
- SMSG_AUTH_RESPONSE = 0x1EE,
- MSG_GM_SHOWLABEL = 0x1EF,
- CMSG_PET_CAST_SPELL = 0x1F0,
- MSG_SAVE_GUILD_EMBLEM = 0x1F1,
- MSG_TABARDVENDOR_ACTIVATE = 0x1F2,
- SMSG_PLAY_SPELL_VISUAL = 0x1F3,
- CMSG_ZONEUPDATE = 0x1F4,
- SMSG_PARTYKILLLOG = 0x1F5,
- SMSG_COMPRESSED_UPDATE_OBJECT = 0x1F6,
- SMSG_PLAY_SPELL_IMPACT = 0x1F7,
- SMSG_EXPLORATION_EXPERIENCE = 0x1F8,
- CMSG_GM_SET_SECURITY_GROUP = 0x1F9,
- CMSG_GM_NUKE = 0x1FA,
- MSG_RANDOM_ROLL = 0x1FB,
- SMSG_ENVIRONMENTALDAMAGELOG = 0x1FC,
- CMSG_CHANGEPLAYER_DIFFICULTY = 0x1FD,
- SMSG_RWHOIS = 0x1FE,
- SMSG_LFG_PLAYER_REWARD = 0x1FF, // uint32, uint8, uint32, uint32, uint32, uint32, uint32, uint8, for (uint8) {uint32, uint32, uint32}
- SMSG_LFG_TELEPORT_DENIED = 0x200, // uint32 (1, 2, 4, 6;0, 5, 7)
- CMSG_UNLEARN_SPELL = 0x201,
- CMSG_UNLEARN_SKILL = 0x202,
- SMSG_REMOVED_SPELL = 0x203,
- CMSG_DECHARGE = 0x204,
- CMSG_GMTICKET_CREATE = 0x205,
- SMSG_GMTICKET_CREATE = 0x206,
- CMSG_GMTICKET_UPDATETEXT = 0x207,
- SMSG_GMTICKET_UPDATETEXT = 0x208,
- SMSG_ACCOUNT_DATA_TIMES = 0x209,
- CMSG_REQUEST_ACCOUNT_DATA = 0x20A,
- CMSG_UPDATE_ACCOUNT_DATA = 0x20B,
- SMSG_UPDATE_ACCOUNT_DATA = 0x20C,
- SMSG_CLEAR_FAR_SIGHT_IMMEDIATE = 0x20D,
- SMSG_CHANGEPLAYER_DIFFICULTY_RESULT = 0x20E,
- CMSG_GM_TEACH = 0x20F,
- CMSG_GM_CREATE_ITEM_TARGET = 0x210,
- CMSG_GMTICKET_GETTICKET = 0x211,
- SMSG_GMTICKET_GETTICKET = 0x212,
- CMSG_UNLEARN_TALENTS = 0x213,
- SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT = 0x214,
- SMSG_GAMEOBJECT_DESPAWN_ANIM = 0x215,
- MSG_CORPSE_QUERY = 0x216,
- CMSG_GMTICKET_DELETETICKET = 0x217,
- SMSG_GMTICKET_DELETETICKET = 0x218,
- SMSG_CHAT_WRONG_FACTION = 0x219,
- CMSG_GMTICKET_SYSTEMSTATUS = 0x21A,
- SMSG_GMTICKET_SYSTEMSTATUS = 0x21B,
- CMSG_SPIRIT_HEALER_ACTIVATE = 0x21C,
- CMSG_SET_STAT_CHEAT = 0x21D,
- SMSG_QUEST_FORCE_REMOVE = 0x21E, // uint32 questid
- CMSG_SKILL_BUY_STEP = 0x21F,
- CMSG_SKILL_BUY_RANK = 0x220,
- CMSG_XP_CHEAT = 0x221,
- SMSG_SPIRIT_HEALER_CONFIRM = 0x222,
- CMSG_CHARACTER_POINT_CHEAT = 0x223,
- SMSG_GOSSIP_POI = 0x224,
- CMSG_CHAT_IGNORED = 0x225,
- CMSG_GM_VISION = 0x226,
- CMSG_SERVER_COMMAND = 0x227,
- CMSG_GM_SILENCE = 0x228,
- CMSG_GM_REVEALTO = 0x229,
- CMSG_GM_RESURRECT = 0x22A,
- CMSG_GM_SUMMONMOB = 0x22B,
- CMSG_GM_MOVECORPSE = 0x22C,
- CMSG_GM_FREEZE = 0x22D,
- CMSG_GM_UBERINVIS = 0x22E,
- CMSG_GM_REQUEST_PLAYER_INFO = 0x22F,
- SMSG_GM_PLAYER_INFO = 0x230,
- CMSG_GUILD_RANK = 0x231,
- CMSG_GUILD_ADD_RANK = 0x232,
- CMSG_GUILD_DEL_RANK = 0x233,
- CMSG_GUILD_SET_PUBLIC_NOTE = 0x234,
- CMSG_GUILD_SET_OFFICER_NOTE = 0x235,
- SMSG_LOGIN_VERIFY_WORLD = 0x236,
- CMSG_CLEAR_EXPLORATION = 0x237,
- CMSG_SEND_MAIL = 0x238,
- SMSG_SEND_MAIL_RESULT = 0x239,
- CMSG_GET_MAIL_LIST = 0x23A,
- SMSG_MAIL_LIST_RESULT = 0x23B,
- CMSG_BATTLEFIELD_LIST = 0x23C,
- SMSG_BATTLEFIELD_LIST = 0x23D,
- CMSG_BATTLEFIELD_JOIN = 0x23E,
- SMSG_FORCE_SET_VEHICLE_REC_ID = 0x23F,
- CMSG_SET_VEHICLE_REC_ID_ACK = 0x240,
- CMSG_TAXICLEARNODE = 0x241,
- CMSG_TAXIENABLENODE = 0x242,
- CMSG_ITEM_TEXT_QUERY = 0x243,
- SMSG_ITEM_TEXT_QUERY_RESPONSE = 0x244,
- CMSG_MAIL_TAKE_MONEY = 0x245,
- CMSG_MAIL_TAKE_ITEM = 0x246,
- CMSG_MAIL_MARK_AS_READ = 0x247,
- CMSG_MAIL_RETURN_TO_SENDER = 0x248,
- CMSG_MAIL_DELETE = 0x249,
- CMSG_MAIL_CREATE_TEXT_ITEM = 0x24A,
- SMSG_SPELLLOGMISS = 0x24B,
- SMSG_SPELLLOGEXECUTE = 0x24C,
- SMSG_DEBUGAURAPROC = 0x24D,
- SMSG_PERIODICAURALOG = 0x24E,
- SMSG_SPELLDAMAGESHIELD = 0x24F,
- SMSG_SPELLNONMELEEDAMAGELOG = 0x250,
- CMSG_LEARN_TALENT = 0x251,
- SMSG_RESURRECT_FAILED = 0x252,
- CMSG_TOGGLE_PVP = 0x253,
- SMSG_ZONE_UNDER_ATTACK = 0x254,
- MSG_AUCTION_HELLO = 0x255,
- CMSG_AUCTION_SELL_ITEM = 0x256,
- CMSG_AUCTION_REMOVE_ITEM = 0x257,
- CMSG_AUCTION_LIST_ITEMS = 0x258,
- CMSG_AUCTION_LIST_OWNER_ITEMS = 0x259,
- CMSG_AUCTION_PLACE_BID = 0x25A,
- SMSG_AUCTION_COMMAND_RESULT = 0x25B,
- SMSG_AUCTION_LIST_RESULT = 0x25C,
- SMSG_AUCTION_OWNER_LIST_RESULT = 0x25D,
- SMSG_AUCTION_BIDDER_NOTIFICATION = 0x25E,
- SMSG_AUCTION_OWNER_NOTIFICATION = 0x25F,
- SMSG_PROCRESIST = 0x260,
- SMSG_COMBAT_EVENT_FAILED = 0x261,
- SMSG_DISPEL_FAILED = 0x262,
- SMSG_SPELLORDAMAGE_IMMUNE = 0x263,
- CMSG_AUCTION_LIST_BIDDER_ITEMS = 0x264,
- SMSG_AUCTION_BIDDER_LIST_RESULT = 0x265,
- SMSG_SET_FLAT_SPELL_MODIFIER = 0x266,
- SMSG_SET_PCT_SPELL_MODIFIER = 0x267,
- CMSG_SET_AMMO = 0x268,
- SMSG_CORPSE_RECLAIM_DELAY = 0x269,
- CMSG_SET_ACTIVE_MOVER = 0x26A,
- CMSG_PET_CANCEL_AURA = 0x26B,
- CMSG_PLAYER_AI_CHEAT = 0x26C,
- CMSG_CANCEL_AUTO_REPEAT_SPELL = 0x26D,
- MSG_GM_ACCOUNT_ONLINE = 0x26E,
- MSG_LIST_STABLED_PETS = 0x26F,
- CMSG_STABLE_PET = 0x270,
- CMSG_UNSTABLE_PET = 0x271,
- CMSG_BUY_STABLE_SLOT = 0x272,
- SMSG_STABLE_RESULT = 0x273,
- CMSG_STABLE_REVIVE_PET = 0x274,
- CMSG_STABLE_SWAP_PET = 0x275,
- MSG_QUEST_PUSH_RESULT = 0x276,
- SMSG_PLAY_MUSIC = 0x277,
- SMSG_PLAY_OBJECT_SOUND = 0x278,
- CMSG_REQUEST_PET_INFO = 0x279,
- CMSG_FAR_SIGHT = 0x27A,
- SMSG_SPELLDISPELLOG = 0x27B,
- SMSG_DAMAGE_CALC_LOG = 0x27C,
- CMSG_ENABLE_DAMAGE_LOG = 0x27D,
- CMSG_GROUP_CHANGE_SUB_GROUP = 0x27E,
- CMSG_REQUEST_PARTY_MEMBER_STATS = 0x27F,
- CMSG_GROUP_SWAP_SUB_GROUP = 0x280,
- CMSG_RESET_FACTION_CHEAT = 0x281,
- CMSG_AUTOSTORE_BANK_ITEM = 0x282,
- CMSG_AUTOBANK_ITEM = 0x283,
- MSG_QUERY_NEXT_MAIL_TIME = 0x284,
- SMSG_RECEIVED_MAIL = 0x285,
- SMSG_RAID_GROUP_ONLY = 0x286,
- CMSG_SET_DURABILITY_CHEAT = 0x287,
- CMSG_SET_PVP_RANK_CHEAT = 0x288,
- CMSG_ADD_PVP_MEDAL_CHEAT = 0x289,
- CMSG_DEL_PVP_MEDAL_CHEAT = 0x28A,
- CMSG_SET_PVP_TITLE = 0x28B,
- SMSG_PVP_CREDIT = 0x28C,
- SMSG_AUCTION_REMOVED_NOTIFICATION = 0x28D,
- CMSG_GROUP_RAID_CONVERT = 0x28E,
- CMSG_GROUP_ASSISTANT_LEADER = 0x28F,
- CMSG_BUYBACK_ITEM = 0x290,
- SMSG_SERVER_MESSAGE = 0x291,
- CMSG_SET_SAVED_INSTANCE_EXTEND = 0x292,
- SMSG_LFG_OFFER_CONTINUE = 0x293,
- CMSG_TEST_DROP_RATE = 0x294,
- SMSG_TEST_DROP_RATE_RESULT = 0x295,
- CMSG_LFG_GET_STATUS = 0x296,
- SMSG_SHOW_MAILBOX = 0x297,
- SMSG_RESET_RANGED_COMBAT_TIMER = 0x298,
- SMSG_CHAT_NOT_IN_PARTY = 0x299, // uint32, errors: ERR_NOT_IN_GROUP (2, 51) and ERR_NOT_IN_RAID (3, 39, 40)
- CMSG_GMTICKETSYSTEM_TOGGLE = 0x29A,
- CMSG_CANCEL_GROWTH_AURA = 0x29B,
- SMSG_CANCEL_AUTO_REPEAT = 0x29C,
- SMSG_STANDSTATE_UPDATE = 0x29D,
- SMSG_LOOT_ALL_PASSED = 0x29E,
- SMSG_LOOT_ROLL_WON = 0x29F,
- CMSG_LOOT_ROLL = 0x2A0,
- SMSG_LOOT_START_ROLL = 0x2A1,
- SMSG_LOOT_ROLL = 0x2A2,
- CMSG_LOOT_MASTER_GIVE = 0x2A3,
- SMSG_LOOT_MASTER_LIST = 0x2A4,
- SMSG_SET_FORCED_REACTIONS = 0x2A5,
- SMSG_SPELL_FAILED_OTHER = 0x2A6,
- SMSG_GAMEOBJECT_RESET_STATE = 0x2A7,
- CMSG_REPAIR_ITEM = 0x2A8,
- SMSG_CHAT_PLAYER_NOT_FOUND = 0x2A9,
- MSG_TALENT_WIPE_CONFIRM = 0x2AA,
- SMSG_SUMMON_REQUEST = 0x2AB,
- CMSG_SUMMON_RESPONSE = 0x2AC,
- MSG_DEV_SHOWLABEL = 0x2AD,
- SMSG_MONSTER_MOVE_TRANSPORT = 0x2AE,
- SMSG_PET_BROKEN = 0x2AF,
- MSG_MOVE_FEATHER_FALL = 0x2B0,
- MSG_MOVE_WATER_WALK = 0x2B1,
- CMSG_SERVER_BROADCAST = 0x2B2,
- CMSG_SELF_RES = 0x2B3,
- SMSG_FEIGN_DEATH_RESISTED = 0x2B4,
- CMSG_RUN_SCRIPT = 0x2B5,
- SMSG_SCRIPT_MESSAGE = 0x2B6,
- SMSG_DUEL_COUNTDOWN = 0x2B7,
- SMSG_AREA_TRIGGER_MESSAGE = 0x2B8,
- CMSG_SHOWING_HELM = 0x2B9,
- CMSG_SHOWING_CLOAK = 0x2BA,
- SMSG_LFG_ROLE_CHOSEN = 0x2BB,
- SMSG_PLAYER_SKINNED = 0x2BC,
- SMSG_DURABILITY_DAMAGE_DEATH = 0x2BD,
- CMSG_SET_EXPLORATION = 0x2BE,
- CMSG_SET_ACTIONBAR_TOGGLES = 0x2BF,
- UMSG_DELETE_GUILD_CHARTER = 0x2C0,
- MSG_PETITION_RENAME = 0x2C1,
- SMSG_INIT_WORLD_STATES = 0x2C2,
- SMSG_UPDATE_WORLD_STATE = 0x2C3,
- CMSG_ITEM_NAME_QUERY = 0x2C4,
- SMSG_ITEM_NAME_QUERY_RESPONSE = 0x2C5,
- SMSG_PET_ACTION_FEEDBACK = 0x2C6,
- CMSG_CHAR_RENAME = 0x2C7,
- SMSG_CHAR_RENAME = 0x2C8,
- CMSG_MOVE_SPLINE_DONE = 0x2C9,
- CMSG_MOVE_FALL_RESET = 0x2CA,
- SMSG_INSTANCE_SAVE_CREATED = 0x2CB,
- SMSG_RAID_INSTANCE_INFO = 0x2CC,
- CMSG_REQUEST_RAID_INFO = 0x2CD,
- CMSG_MOVE_TIME_SKIPPED = 0x2CE,
- CMSG_MOVE_FEATHER_FALL_ACK = 0x2CF,
- CMSG_MOVE_WATER_WALK_ACK = 0x2D0,
- CMSG_MOVE_NOT_ACTIVE_MOVER = 0x2D1,
- SMSG_PLAY_SOUND = 0x2D2,
- CMSG_BATTLEFIELD_STATUS = 0x2D3,
- SMSG_BATTLEFIELD_STATUS = 0x2D4,
- CMSG_BATTLEFIELD_PORT = 0x2D5,
- MSG_INSPECT_HONOR_STATS = 0x2D6,
- CMSG_BATTLEMASTER_HELLO = 0x2D7,
- CMSG_MOVE_START_SWIM_CHEAT = 0x2D8,
- CMSG_MOVE_STOP_SWIM_CHEAT = 0x2D9,
- SMSG_FORCE_WALK_SPEED_CHANGE = 0x2DA,
- CMSG_FORCE_WALK_SPEED_CHANGE_ACK = 0x2DB,
- SMSG_FORCE_SWIM_BACK_SPEED_CHANGE = 0x2DC,
- CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK = 0x2DD,
- SMSG_FORCE_TURN_RATE_CHANGE = 0x2DE,
- CMSG_FORCE_TURN_RATE_CHANGE_ACK = 0x2DF,
- MSG_PVP_LOG_DATA = 0x2E0,
- CMSG_LEAVE_BATTLEFIELD = 0x2E1,
- CMSG_AREA_SPIRIT_HEALER_QUERY = 0x2E2,
- CMSG_AREA_SPIRIT_HEALER_QUEUE = 0x2E3,
- SMSG_AREA_SPIRIT_HEALER_TIME = 0x2E4,
- CMSG_GM_UNTEACH = 0x2E5,
- SMSG_WARDEN_DATA = 0x2E6,
- CMSG_WARDEN_DATA = 0x2E7,
- SMSG_GROUP_JOINED_BATTLEGROUND = 0x2E8,
- MSG_BATTLEGROUND_PLAYER_POSITIONS = 0x2E9,
- CMSG_PET_STOP_ATTACK = 0x2EA,
- SMSG_BINDER_CONFIRM = 0x2EB,
- SMSG_BATTLEGROUND_PLAYER_JOINED = 0x2EC,
- SMSG_BATTLEGROUND_PLAYER_LEFT = 0x2ED,
- CMSG_BATTLEMASTER_JOIN = 0x2EE,
- SMSG_ADDON_INFO = 0x2EF,
- CMSG_PET_UNLEARN = 0x2F0, // Deprecated 3.x
- SMSG_PET_UNLEARN_CONFIRM = 0x2F1, // Deprecated 3.x
- SMSG_PARTY_MEMBER_STATS_FULL = 0x2F2,
- CMSG_PET_SPELL_AUTOCAST = 0x2F3,
- SMSG_WEATHER = 0x2F4,
- SMSG_PLAY_TIME_WARNING = 0x2F5,
- SMSG_MINIGAME_SETUP = 0x2F6,
- SMSG_MINIGAME_STATE = 0x2F7,
- CMSG_MINIGAME_MOVE = 0x2F8,
- SMSG_MINIGAME_MOVE_FAILED = 0x2F9,
- SMSG_RAID_INSTANCE_MESSAGE = 0x2FA,
- SMSG_COMPRESSED_MOVES = 0x2FB,
- CMSG_GUILD_INFO_TEXT = 0x2FC,
- SMSG_CHAT_RESTRICTED = 0x2FD,
- SMSG_SPLINE_SET_RUN_SPEED = 0x2FE,
- SMSG_SPLINE_SET_RUN_BACK_SPEED = 0x2FF,
- SMSG_SPLINE_SET_SWIM_SPEED = 0x300,
- SMSG_SPLINE_SET_WALK_SPEED = 0x301,
- SMSG_SPLINE_SET_SWIM_BACK_SPEED = 0x302,
- SMSG_SPLINE_SET_TURN_RATE = 0x303,
- SMSG_SPLINE_MOVE_UNROOT = 0x304,
- SMSG_SPLINE_MOVE_FEATHER_FALL = 0x305,
- SMSG_SPLINE_MOVE_NORMAL_FALL = 0x306,
- SMSG_SPLINE_MOVE_SET_HOVER = 0x307,
- SMSG_SPLINE_MOVE_UNSET_HOVER = 0x308,
- SMSG_SPLINE_MOVE_WATER_WALK = 0x309,
- SMSG_SPLINE_MOVE_LAND_WALK = 0x30A,
- SMSG_SPLINE_MOVE_START_SWIM = 0x30B,
- SMSG_SPLINE_MOVE_STOP_SWIM = 0x30C,
- SMSG_SPLINE_MOVE_SET_RUN_MODE = 0x30D,
- SMSG_SPLINE_MOVE_SET_WALK_MODE = 0x30E,
- CMSG_GM_NUKE_ACCOUNT = 0x30F,
- MSG_GM_DESTROY_CORPSE = 0x310,
- CMSG_GM_DESTROY_ONLINE_CORPSE = 0x311,
- CMSG_ACTIVATETAXIEXPRESS = 0x312,
- SMSG_SET_FACTION_ATWAR = 0x313,
- SMSG_GAMETIMEBIAS_SET = 0x314,
- CMSG_DEBUG_ACTIONS_START = 0x315,
- CMSG_DEBUG_ACTIONS_STOP = 0x316,
- CMSG_SET_FACTION_INACTIVE = 0x317,
- CMSG_SET_WATCHED_FACTION = 0x318,
- MSG_MOVE_TIME_SKIPPED = 0x319,
- SMSG_SPLINE_MOVE_ROOT = 0x31A,
- CMSG_SET_EXPLORATION_ALL = 0x31B,
- SMSG_INVALIDATE_PLAYER = 0x31C,
- CMSG_RESET_INSTANCES = 0x31D,
- SMSG_INSTANCE_RESET = 0x31E,
- SMSG_INSTANCE_RESET_FAILED = 0x31F,
- SMSG_UPDATE_LAST_INSTANCE = 0x320,
- MSG_RAID_TARGET_UPDATE = 0x321,
- MSG_RAID_READY_CHECK = 0x322,
- CMSG_LUA_USAGE = 0x323,
- SMSG_PET_ACTION_SOUND = 0x324,
- SMSG_PET_DISMISS_SOUND = 0x325,
- SMSG_GHOSTEE_GONE = 0x326,
- CMSG_GM_UPDATE_TICKET_STATUS = 0x327,
- SMSG_GM_TICKET_STATUS_UPDATE = 0x328,
- MSG_SET_DUNGEON_DIFFICULTY = 0x329,
- CMSG_GMSURVEY_SUBMIT = 0x32A,
- SMSG_UPDATE_INSTANCE_OWNERSHIP = 0x32B,
- CMSG_IGNORE_KNOCKBACK_CHEAT = 0x32C,
- SMSG_CHAT_PLAYER_AMBIGUOUS = 0x32D,
- MSG_DELAY_GHOST_TELEPORT = 0x32E,
- SMSG_SPELLINSTAKILLLOG = 0x32F,
- SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x330,
- CMSG_CHAT_FILTERED = 0x331,
- SMSG_EXPECTED_SPAM_RECORDS = 0x332,
- SMSG_SPELLSTEALLOG = 0x333,
- CMSG_LOTTERY_QUERY_OBSOLETE = 0x334,
- SMSG_LOTTERY_QUERY_RESULT_OBSOLETE = 0x335,
- CMSG_BUY_LOTTERY_TICKET_OBSOLETE = 0x336,
- SMSG_LOTTERY_RESULT_OBSOLETE = 0x337,
- SMSG_CHARACTER_PROFILE = 0x338,
- SMSG_CHARACTER_PROFILE_REALM_CONNECTED = 0x339,
- SMSG_DEFENSE_MESSAGE = 0x33A,
- SMSG_INSTANCE_DIFFICULTY = 0x33B,
- MSG_GM_RESETINSTANCELIMIT = 0x33C,
- SMSG_MOTD = 0x33D,
- SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY= 0x33E,
- SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY= 0x33F,
- CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK= 0x340,
- MSG_MOVE_START_SWIM_CHEAT = 0x341,
- MSG_MOVE_STOP_SWIM_CHEAT = 0x342,
- SMSG_MOVE_SET_CAN_FLY = 0x343,
- SMSG_MOVE_UNSET_CAN_FLY = 0x344,
- CMSG_MOVE_SET_CAN_FLY_ACK = 0x345,
- CMSG_MOVE_SET_FLY = 0x346,
- CMSG_SOCKET_GEMS = 0x347,
- CMSG_ARENA_TEAM_CREATE = 0x348,
- SMSG_ARENA_TEAM_COMMAND_RESULT = 0x349,
- MSG_MOVE_UPDATE_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY= 0x34A,
- CMSG_ARENA_TEAM_QUERY = 0x34B,
- SMSG_ARENA_TEAM_QUERY_RESPONSE = 0x34C,
- CMSG_ARENA_TEAM_ROSTER = 0x34D,
- SMSG_ARENA_TEAM_ROSTER = 0x34E,
- CMSG_ARENA_TEAM_INVITE = 0x34F,
- SMSG_ARENA_TEAM_INVITE = 0x350,
- CMSG_ARENA_TEAM_ACCEPT = 0x351,
- CMSG_ARENA_TEAM_DECLINE = 0x352,
- CMSG_ARENA_TEAM_LEAVE = 0x353,
- CMSG_ARENA_TEAM_REMOVE = 0x354,
- CMSG_ARENA_TEAM_DISBAND = 0x355,
- CMSG_ARENA_TEAM_LEADER = 0x356,
- SMSG_ARENA_TEAM_EVENT = 0x357,
- CMSG_BATTLEMASTER_JOIN_ARENA = 0x358,
- MSG_MOVE_START_ASCEND = 0x359,
- MSG_MOVE_STOP_ASCEND = 0x35A,
- SMSG_ARENA_TEAM_STATS = 0x35B,
- CMSG_LFG_JOIN = 0x35C,
- CMSG_LFG_LEAVE = 0x35D,
- CMSG_SEARCH_LFG_JOIN = 0x35E,
- CMSG_SEARCH_LFG_LEAVE = 0x35F,
- SMSG_UPDATE_LFG_LIST = 0x360, // uint32, uint32, if (uint8) { uint32 count, for (count) { uint64} }, uint32 count2, uint32, for (count2) { uint64, uint32 flags, if (flags & 0x2) {string}, if (flags & 0x10) {for (3) uint8}, if (flags & 0x80) {uint64, uint32}}, uint32 count3, uint32, for (count3) {uint64, uint32 flags, if (flags & 0x1) {uint8, uint8, uint8, for (3) uint8, uint32, uint32, uint32, uint32, uint32, uint32, float, float, uint32, uint32, uint32, uint32, uint32, float, uint32, uint32, uint32, uint32, uint32, uint32}, if (flags&0x2) string, if (flags&0x4) uint8, if (flags&0x8) uint64, if (flags&0x10) uint8, if (flags&0x20) uint32, if (flags&0x40) uint8, if (flags& 0x80) {uint64, uint32}}
- SMSG_LFG_PROPOSAL_UPDATE = 0x361, // uint32, uint8, uint32, uint32, uint8, for (uint8) {uint32, uint8, uint8, uint8, uint8}
- CMSG_LFG_PROPOSAL_RESULT = 0x362,
- SMSG_LFG_ROLE_CHECK_UPDATE = 0x363, // uint32, uint8, for (uint8) uint32, uint8, for (uint8) { uint64, uint8, uint32, uint8, }
- SMSG_LFG_JOIN_RESULT = 0x364, // uint32 unk, uint32, if (unk == 6) { uint8 count, for (count) uint64 }
- SMSG_LFG_QUEUE_STATUS = 0x365, // uint32 dungeon, uint32 lfgtype, uint32, uint32, uint32, uint32, uint8, uint8, uint8, uint8
- CMSG_SET_LFG_COMMENT = 0x366,
- SMSG_LFG_UPDATE_PLAYER = 0x367, // uint8, if (uint8) { uint8, uint8, uint8, uint8, if (uint8) for (uint8) uint32, string}
- SMSG_LFG_UPDATE_PARTY = 0x368, // uint8, if (uint8) { uint8, uint8, uint8, for (3) uint8, uint8, if (uint8) for (uint8) uint32, string}
- SMSG_LFG_UPDATE_SEARCH = 0x369, // uint8
- CMSG_LFG_SET_ROLES = 0x36A,
- CMSG_LFG_SET_NEEDS = 0x36B,
- CMSG_LFG_SET_BOOT_VOTE = 0x36C,
- SMSG_LFG_BOOT_PROPOSAL_UPDATE = 0x36D, // uint8, uint8, uint8, uint64, uint32, uint32, uint32, uint32
- CMSG_LFD_PLAYER_LOCK_INFO_REQUEST = 0x36E,
- SMSG_LFG_PLAYER_INFO = 0x36F, // uint8, for (uint8) { uint32, uint8, uint32, uint32, uint32, uint32, uint8, for (uint8) {uint32, uint32, uint32}}, uint32, for (uint32) {uint32, uint32}
- CMSG_LFG_TELEPORT = 0x370,
- CMSG_LFD_PARTY_LOCK_INFO_REQUEST = 0x371,
- SMSG_LFG_PARTY_INFO = 0x372, // uint8, for (uint8) uint64
- SMSG_TITLE_EARNED = 0x373,
- CMSG_SET_TITLE = 0x374,
- CMSG_CANCEL_MOUNT_AURA = 0x375,
- SMSG_ARENA_ERROR = 0x376,
- MSG_INSPECT_ARENA_TEAMS = 0x377,
- SMSG_DEATH_RELEASE_LOC = 0x378,
- CMSG_CANCEL_TEMP_ENCHANTMENT = 0x379,
- SMSG_FORCED_DEATH_UPDATE = 0x37A,
- CMSG_CHEAT_SET_HONOR_CURRENCY = 0x37B,
- CMSG_CHEAT_SET_ARENA_CURRENCY = 0x37C,
- MSG_MOVE_SET_FLIGHT_SPEED_CHEAT = 0x37D,
- MSG_MOVE_SET_FLIGHT_SPEED = 0x37E,
- MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT = 0x37F,
- MSG_MOVE_SET_FLIGHT_BACK_SPEED = 0x380,
- SMSG_FORCE_FLIGHT_SPEED_CHANGE = 0x381,
- CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK = 0x382,
- SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE = 0x383,
- CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK = 0x384,
- SMSG_SPLINE_SET_FLIGHT_SPEED = 0x385,
- SMSG_SPLINE_SET_FLIGHT_BACK_SPEED = 0x386,
- CMSG_MAELSTROM_INVALIDATE_CACHE = 0x387,
- SMSG_FLIGHT_SPLINE_SYNC = 0x388,
- CMSG_SET_TAXI_BENCHMARK_MODE = 0x389,
- SMSG_JOINED_BATTLEGROUND_QUEUE = 0x38A,
- SMSG_REALM_SPLIT = 0x38B,
- CMSG_REALM_SPLIT = 0x38C,
- CMSG_MOVE_CHNG_TRANSPORT = 0x38D,
- MSG_PARTY_ASSIGNMENT = 0x38E,
- SMSG_OFFER_PETITION_ERROR = 0x38F,
- SMSG_TIME_SYNC_REQ = 0x390,
- CMSG_TIME_SYNC_RESP = 0x391,
- CMSG_SEND_LOCAL_EVENT = 0x392,
- CMSG_SEND_GENERAL_TRIGGER = 0x393,
- CMSG_SEND_COMBAT_TRIGGER = 0x394,
- CMSG_MAELSTROM_GM_SENT_MAIL = 0x395,
- SMSG_RESET_FAILED_NOTIFY = 0x396,
- SMSG_REAL_GROUP_UPDATE = 0x397,
- SMSG_LFG_DISABLED = 0x398,
- CMSG_ACTIVE_PVP_CHEAT = 0x399,
- CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY = 0x39A,
- SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE = 0x39B,
- SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE = 0x39C,
- SMSG_UPDATE_COMBO_POINTS = 0x39D,
- SMSG_VOICE_SESSION_ROSTER_UPDATE = 0x39E,
- SMSG_VOICE_SESSION_LEAVE = 0x39F,
- SMSG_VOICE_SESSION_ADJUST_PRIORITY = 0x3A0,
- CMSG_VOICE_SET_TALKER_MUTED_REQUEST = 0x3A1,
- SMSG_VOICE_SET_TALKER_MUTED = 0x3A2,
- 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,
- SMSG_SPELL_CHANCE_PROC_LOG = 0x3AA,
- CMSG_MOVE_SET_RUN_SPEED = 0x3AB,
- SMSG_DISMOUNT = 0x3AC,
- MSG_MOVE_UPDATE_CAN_FLY = 0x3AD,
- MSG_RAID_READY_CHECK_CONFIRM = 0x3AE,
- CMSG_VOICE_SESSION_ENABLE = 0x3AF,
- 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,
- SMSG_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,
- SMSG_GROUPACTION_THROTTLED = 0x411,
- SMSG_OVERRIDE_LIGHT = 0x412, // uint32 defaultMapLight, uint32 overrideLight, uint32 transitionTimeMs
- 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,
- CMSG_CALENDAR_EVENT_INVITE_NOTES = 0x45F,
- SMSG_CALENDAR_EVENT_INVITE_NOTES = 0x460,
- SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT = 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_CALENDAR_RAID_LOCKOUT_UPDATED = 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_SET_BREATH = 0x4A4,
- CMSG_QUERY_VEHICLE_STATUS = 0x4A5,
- SMSG_BATTLEGROUND_INFO_THROTTLED = 0x4A6, // empty, "You can't do that yet"
- SMSG_PLAYER_VEHICLE_DATA = 0x4A7, // guid+uint32 (vehicle)
- CMSG_PLAYER_VEHICLE_ENTER = 0x4A8, // uint64
- CMSG_CONTROLLER_EJECT_PASSENGER = 0x4A9, // uint64
- SMSG_PET_GUIDS = 0x4AA,
- SMSG_CLIENTCACHE_VERSION = 0x4AB,
- CMSG_CHANGE_GDF_ARENA_RATING = 0x4AC,
- CMSG_SET_ARENA_TEAM_RATING_BY_INDEX = 0x4AD,
- CMSG_SET_ARENA_TEAM_WEEKLY_GAMES = 0x4AE,
- CMSG_SET_ARENA_TEAM_SEASON_GAMES = 0x4AF,
- CMSG_SET_ARENA_MEMBER_WEEKLY_GAMES = 0x4B0,
- CMSG_SET_ARENA_MEMBER_SEASON_GAMES = 0x4B1,
- SMSG_ITEM_REFUND_INFO_RESPONSE = 0x4B2,
- CMSG_ITEM_REFUND_INFO = 0x4B3,
- CMSG_ITEM_REFUND = 0x4B4, // lua: ContainerRefundItemPurchase
- SMSG_ITEM_REFUND_RESULT = 0x4B5,
- CMSG_CORPSE_MAP_POSITION_QUERY = 0x4B6, // uint32
- SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE = 0x4B7, // 3*float+float
- CMSG_UNUSED5 = 0x4B8,
- CMSG_UNUSED6 = 0x4B9,
- CMSG_CALENDAR_EVENT_SIGNUP = 0x4BA, // uint64
- SMSG_CALENDAR_CLEAR_PENDING_ACTION = 0x4BB,
- SMSG_EQUIPMENT_SET_LIST = 0x4BC, // equipment manager list?
- CMSG_EQUIPMENT_SET_SAVE = 0x4BD,
- CMSG_UPDATE_PROJECTILE_POSITION = 0x4BE,
- SMSG_SET_PROJECTILE_POSITION = 0x4BF,
- SMSG_TALENTS_INFO = 0x4C0,
- CMSG_LEARN_PREVIEW_TALENTS = 0x4C1,
- CMSG_LEARN_PREVIEW_TALENTS_PET = 0x4C2,
- CMSG_SET_ACTIVE_TALENT_GROUP_OBSOLETE = 0x4C3,
- CMSG_GM_GRANT_ACHIEVEMENT = 0x4C4,
- CMSG_GM_REMOVE_ACHIEVEMENT = 0x4C5,
- CMSG_GM_SET_CRITERIA_FOR_PLAYER = 0x4C6,
- SMSG_ARENA_UNIT_DESTROYED = 0x4C7,
- SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED = 0x4C8, // uint32 "Can't modify arena team while queued or in a match."
- CMSG_PROFILEDATA_REQUEST = 0x4C9,
- SMSG_PROFILEDATA_RESPONSE = 0x4CA,
- CMSG_START_BATTLEFIELD_CHEAT = 0x4CB,
- CMSG_END_BATTLEFIELD_CHEAT = 0x4CC,
- SMSG_MULTIPLE_PACKETS = 0x4CD,
- SMSG_MOVE_GRAVITY_DISABLE = 0x4CE,
- CMSG_MOVE_GRAVITY_DISABLE_ACK = 0x4CF,
- SMSG_MOVE_GRAVITY_ENABLE = 0x4D0,
- CMSG_MOVE_GRAVITY_ENABLE_ACK = 0x4D1,
- MSG_MOVE_GRAVITY_CHNG = 0x4D2,
- SMSG_SPLINE_MOVE_GRAVITY_DISABLE = 0x4D3,
- SMSG_SPLINE_MOVE_GRAVITY_ENABLE = 0x4D4,
- CMSG_EQUIPMENT_SET_USE = 0x4D5,
- SMSG_EQUIPMENT_SET_USE_RESULT = 0x4D6,
- CMSG_FORCE_ANIM = 0x4D7,
- SMSG_FORCE_ANIM = 0x4D8,
- CMSG_CHAR_FACTION_CHANGE = 0x4D9,
- SMSG_CHAR_FACTION_CHANGE = 0x4DA,
- CMSG_PVP_QUEUE_STATS_REQUEST = 0x4DB,
- SMSG_PVP_QUEUE_STATS = 0x4DC,
- CMSG_SET_PAID_SERVICE_CHEAT = 0x4DD,
- SMSG_BATTLEFIELD_MGR_ENTRY_INVITE = 0x4DE, // uint32
- CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE = 0x4DF,
- SMSG_BATTLEFIELD_MGR_ENTERED = 0x4E0, // uint32, uint8, uint8
- SMSG_BATTLEFIELD_MGR_QUEUE_INVITE = 0x4E1, // uint32
- CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE = 0x4E2,
- CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST = 0x4E3,
- SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE = 0x4E4, // uint32, uint8
- SMSG_BATTLEFIELD_MGR_EJECT_PENDING = 0x4E5, // uint32
- SMSG_BATTLEFIELD_MGR_EJECTED = 0x4E6, // uint32, uint32, uint8
- CMSG_BATTLEFIELD_MGR_EXIT_REQUEST = 0x4E7,
- SMSG_BATTLEFIELD_MGR_STATE_CHANGE = 0x4E8, // uint32, uint32
- CMSG_BATTLEFIELD_MANAGER_ADVANCE_STATE = 0x4E9,
- CMSG_BATTLEFIELD_MANAGER_SET_NEXT_TRANSITION_TIME= 0x4EA,
- MSG_SET_RAID_DIFFICULTY = 0x4EB,
- CMSG_TOGGLE_XP_GAIN = 0x4EC,
- SMSG_TOGGLE_XP_GAIN = 0x4ED, // enable/disable XP gain console message
- SMSG_GMRESPONSE_DB_ERROR = 0x4EE, // empty
- SMSG_GMRESPONSE_RECEIVED = 0x4EF, // uint32, uint32, string[2000], string[4000][4]
- CMSG_GMRESPONSE_RESOLVE = 0x4F0,
- SMSG_GMRESPONSE_STATUS_UPDATE = 0x4F1, // uint8 (1 - EVENT_GMSURVEY_DISPLAY, 0 - EVENT_UPDATE_TICKET)
- SMSG_GMRESPONSE_CREATE_TICKET = 0x4F2,
- CMSG_GMRESPONSE_CREATE_TICKET = 0x4F3,
- CMSG_SERVERINFO = 0x4F4,
- SMSG_SERVERINFO = 0x4F5,
- CMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4F6,
- SMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4F7,
- CMSG_CHAR_RACE_CHANGE = 0x4F8,
- MSG_VIEW_PHASE_SHIFT = 0x4F9,
- SMSG_TALENTS_INVOLUNTARILY_RESET = 0x4FA, // uint8
- CMSG_DEBUG_SERVER_GEO = 0x4FB,
- SMSG_DEBUG_SERVER_GEO = 0x4FC,
- SMSG_LOOT_SLOT_CHANGED = 0x4FD,
- UMSG_UPDATE_GROUP_INFO = 0x4FE,
- CMSG_READY_FOR_ACCOUNT_DATA_TIMES = 0x4FF,
- CMSG_QUERY_QUESTS_COMPLETED = 0x500,
- SMSG_QUERY_QUESTS_COMPLETED_RESPONSE = 0x501,
- CMSG_GM_REPORT_LAG = 0x502,
- CMSG_AFK_MONITOR_INFO_REQUEST = 0x503,
- SMSG_AFK_MONITOR_INFO_RESPONSE = 0x504,
- CMSG_AFK_MONITOR_INFO_CLEAR = 0x505,
- SMSG_CORPSE_NOT_IN_INSTANCE = 0x506,
- CMSG_GM_NUKE_CHARACTER = 0x507,
- CMSG_SET_ALLOW_LOW_LEVEL_RAID1 = 0x508,
- CMSG_SET_ALLOW_LOW_LEVEL_RAID2 = 0x509,
- SMSG_CAMERA_SHAKE = 0x50A, // uint32 SpellEffectCameraShakes.dbc index, uint32
- SMSG_SOCKET_GEMS_RESULT = 0x50B,
- CMSG_SET_CHARACTER_MODEL = 0x50C,
- SMSG_REDIRECT_CLIENT = 0x50D, // uint32 ip, uint16 port, uint32 unk, uint8[20] hash (ip + port, seed=sessionkey)
- CMSG_REDIRECTION_FAILED = 0x50E, // something with networking
- SMSG_SUSPEND_COMMS = 0x50F,
- CMSG_SUSPEND_COMMS_ACK = 0x510,
- SMSG_FORCE_SEND_QUEUED_PACKETS = 0x511,
- CMSG_REDIRECTION_AUTH_PROOF = 0x512,
- CMSG_DROP_NEW_CONNECTION = 0x513,
- SMSG_SEND_ALL_COMBAT_LOG = 0x514,
- SMSG_OPEN_LFG_DUNGEON_FINDER = 0x515,
- SMSG_MOVE_SET_COLLISION_HGT = 0x516,
- CMSG_MOVE_SET_COLLISION_HGT_ACK = 0x517,
- MSG_MOVE_SET_COLLISION_HGT = 0x518,
- CMSG_CLEAR_RANDOM_BG_WIN_TIME = 0x519,
- CMSG_CLEAR_HOLIDAY_BG_WIN_TIME = 0x51A,
- CMSG_COMMENTATOR_SKIRMISH_QUEUE_COMMAND = 0x51B,
- SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT1 = 0x51C,
- SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT2 = 0x51D,
- SMSG_MULTIPLE_MOVES = 0x51E, // uncompressed version of SMSG_COMPRESSED_MOVES
- NUM_MSG_TYPES = 0x51F
+ NUM_OPCODE_HANDLERS = (0x7FFF+1),
+ UNKNOWN_OPCODE = (0xFFFF+1),
+ NULL_OPCODE = 0,
+ COMPRESSED_OPCODE_MASK = 0x8000,
+
+ CMSG_ACCEPT_LEVEL_GRANT = 0x0205,
+ CMSG_ACCEPT_TRADE = 0x7110,
+ CMSG_ACTIVATETAXI = 0x6E06,
+ CMSG_ACTIVATETAXIEXPRESS = 0x0515,
+ CMSG_ADDON_REGISTERED_PREFIXES = 0x0954,
+ CMSG_ADD_FRIEND = 0x6527,
+ CMSG_ADD_IGNORE = 0x4726,
+ CMSG_ADD_VOICE_IGNORE = 0x0F06,
+ CMSG_ALTER_APPEARANCE = 0x0914,
+ CMSG_AREATRIGGER = 0x0937,
+ CMSG_AREA_SPIRIT_HEALER_QUERY = 0x4907,
+ CMSG_AREA_SPIRIT_HEALER_QUEUE = 0x4815,
+ CMSG_ARENA_TEAM_ACCEPT = 0x2A25,
+ CMSG_ARENA_TEAM_CREATE = 0x04A1,
+ CMSG_ARENA_TEAM_DECLINE = 0x6925,
+ CMSG_ARENA_TEAM_DISBAND = 0x6504,
+ CMSG_ARENA_TEAM_INVITE = 0x2F27,
+ CMSG_ARENA_TEAM_LEADER = 0x4204,
+ CMSG_ARENA_TEAM_LEAVE = 0x0E16,
+ CMSG_ARENA_TEAM_QUERY = 0x0514,
+ CMSG_ARENA_TEAM_REMOVE = 0x2F05,
+ CMSG_ARENA_TEAM_ROSTER = 0x6F37,
+ CMSG_ATTACKSTOP = 0x4106,
+ CMSG_ATTACKSWING = 0x0926,
+ CMSG_AUCTION_LIST_BIDDER_ITEMS = 0x6937,
+ CMSG_AUCTION_LIST_ITEMS = 0x0324,
+ CMSG_AUCTION_LIST_OWNER_ITEMS = 0x0206,
+ CMSG_AUCTION_LIST_PENDING_SALES = 0x2C17,
+ CMSG_AUCTION_PLACE_BID = 0x2306,
+ CMSG_AUCTION_REMOVE_ITEM = 0x6426,
+ CMSG_AUCTION_SELL_ITEM = 0x4A06,
+ CMSG_AUTH_SESSION = 0x0449,
+ CMSG_AUTOBANK_ITEM = 0x2537,
+ CMSG_AUTOEQUIP_GROUND_ITEM = 0x0000,
+ CMSG_AUTOEQUIP_ITEM = 0x4304,
+ CMSG_AUTOEQUIP_ITEM_SLOT = 0x4A17,
+ CMSG_AUTOSTORE_BAG_ITEM = 0x0236,
+ CMSG_AUTOSTORE_BANK_ITEM = 0x0607,
+ CMSG_AUTOSTORE_GROUND_ITEM = 0x0000,
+ CMSG_AUTOSTORE_LOOT_ITEM = 0x0E34,
+ CMSG_AUTO_DECLINE_GUILD_INVITES = 0x2034,
+ CMSG_BANKER_ACTIVATE = 0x0005,
+ CMSG_BATTLEFIELD_JOIN = 0x0000,
+ CMSG_BATTLEFIELD_LEAVE = 0x3018,
+ CMSG_BATTLEFIELD_LIST = 0x3814,
+ CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE = 0x05A3,
+ CMSG_BATTLEFIELD_MGR_EXIT_REQUEST = 0x2490,
+ CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE = 0x0413,
+ CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST = 0x710C,
+ CMSG_BATTLEFIELD_PORT = 0x711A,
+ CMSG_BATTLEFIELD_REQUEST_SCORE_DATA = 0x0000,
+ CMSG_BATTLEFIELD_STATUS = 0x2500,
+ CMSG_BATTLEGROUND_PLAYER_POSITIONS = 0x3902,
+ CMSG_BATTLEMASTER_JOIN = 0x7902,
+ CMSG_BATTLEMASTER_JOIN_ARENA = 0x701C,
+ CMSG_BATTLEMASTER_JOIN_RATED = 0x3B18,
+ CMSG_BEGIN_TRADE = 0x721E,
+ CMSG_BINDER_ACTIVATE = 0x4006,
+ CMSG_BOT_DETECTED2 = 0x0000,
+ CMSG_BUG = 0x4035,
+ CMSG_BUSY_TRADE = 0x331C,
+ CMSG_BUYBACK_ITEM = 0x6C17,
+ CMSG_BUY_BANK_SLOT = 0x0425,
+ CMSG_BUY_ITEM = 0x0736,
+ CMSG_CALENDAR_ADD_EVENT = 0x0726,
+ CMSG_CALENDAR_ARENA_TEAM = 0x0204,
+ CMSG_CALENDAR_COMPLAIN = 0x4C36,
+ CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP = 0x0000,
+ CMSG_CALENDAR_COPY_EVENT = 0x0207,
+ CMSG_CALENDAR_EVENT_INVITE = 0x2435,
+ CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x6B35,
+ CMSG_CALENDAR_EVENT_REMOVE_INVITE = 0x4337,
+ CMSG_CALENDAR_EVENT_RSVP = 0x0227,
+ CMSG_CALENDAR_EVENT_SIGNUP = 0x6606,
+ CMSG_CALENDAR_EVENT_STATUS = 0x2D24,
+ CMSG_CALENDAR_GET_CALENDAR = 0x2814,
+ CMSG_CALENDAR_GET_EVENT = 0x6416,
+ CMSG_CALENDAR_GET_NUM_PENDING = 0x4D05,
+ CMSG_CALENDAR_GUILD_FILTER = 0x4A16,
+ CMSG_CALENDAR_REMOVE_EVENT = 0x6636,
+ CMSG_CALENDAR_UPDATE_EVENT = 0x2114,
+ CMSG_CANCEL_AURA = 0x0E26,
+ CMSG_CANCEL_AUTO_REPEAT_SPELL = 0x6C35,
+ CMSG_CANCEL_CAST = 0x0115,
+ CMSG_CANCEL_CHANNELLING = 0x6C25,
+ CMSG_CANCEL_GROWTH_AURA = 0x0000,
+ CMSG_CANCEL_MOUNT_AURA = 0x0635,
+ CMSG_CANCEL_QUEUED_SPELL = 0x7B1C,
+ CMSG_CANCEL_TEMP_ENCHANTMENT = 0x6C37,
+ CMSG_CANCEL_TRADE = 0x731E,
+ CMSG_CAST_SPELL = 0x4C07,
+ CMSG_CHANGEPLAYER_DIFFICULTY = 0x6107,
+ CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE = 0x7310,
+ CMSG_CHANNEL_ANNOUNCEMENTS = 0x1146,
+ CMSG_CHANNEL_BAN = 0x3D56,
+ CMSG_CHANNEL_DISPLAY_LIST = 0x2144,
+ CMSG_CHANNEL_INVITE = 0x0144,
+ CMSG_CHANNEL_KICK = 0x3156,
+ CMSG_CHANNEL_LIST = 0x1556,
+ CMSG_CHANNEL_MODERATE = 0x2944,
+ CMSG_CHANNEL_MODERATOR = 0x0146,
+ CMSG_CHANNEL_MUTE = 0x2554,
+ CMSG_CHANNEL_OWNER = 0x3D44,
+ CMSG_CHANNEL_PASSWORD = 0x2556,
+ CMSG_CHANNEL_ROSTER_INFO = 0x3546,
+ CMSG_CHANNEL_SET_OWNER = 0x3556,
+ CMSG_CHANNEL_SILENCE_ALL = 0x2154,
+ CMSG_CHANNEL_SILENCE_VOICE = 0x2D54,
+ CMSG_CHANNEL_UNBAN = 0x2D46,
+ CMSG_CHANNEL_UNMODERATOR = 0x1954,
+ CMSG_CHANNEL_UNMUTE = 0x3554,
+ CMSG_CHANNEL_UNSILENCE_ALL = 0x2546,
+ CMSG_CHANNEL_UNSILENCE_VOICE = 0x3146,
+ CMSG_CHANNEL_VOICE_OFF = 0x3144,
+ CMSG_CHANNEL_VOICE_ON = 0x1144,
+ CMSG_CHAR_CREATE = 0x4A36,
+ CMSG_CHAR_CUSTOMIZE = 0x2C34,
+ CMSG_CHAR_DELETE = 0x6425,
+ CMSG_CHAR_ENUM = 0x0502,
+ CMSG_CHAR_FACTION_CHANGE = 0x2735,
+ CMSG_CHAR_RACE_CHANGE = 0x0D24,
+ CMSG_CHAR_RENAME = 0x2327,
+ CMSG_CHAT_FILTERED = 0x0946,
+ CMSG_CHAT_IGNORED = 0x0D54,
+ CMSG_CLEAR_CHANNEL_WATCH = 0x2604,
+ CMSG_CLEAR_RAID_MARKER = 0x7300,
+ CMSG_CLEAR_TRADE_ITEM = 0x7018,
+ CMSG_COMMENTATOR_ENABLE = 0x0B07,
+ CMSG_COMMENTATOR_ENTER_INSTANCE = 0x4105,
+ CMSG_COMMENTATOR_EXIT_INSTANCE = 0x6136,
+ CMSG_COMMENTATOR_GET_MAP_INFO = 0x0026,
+ CMSG_COMMENTATOR_GET_PARTY_INFO = 0x2412,
+ CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x0D14,
+ CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x0917,
+ CMSG_COMMENTATOR_SKIRMISH_QUEUE_COMMAND = 0x0025,
+ CMSG_COMMENTATOR_START_WARGAME = 0x25A0,
+ CMSG_COMPLAIN = 0x0427,
+ CMSG_COMPLETE_CINEMATIC = 0x2116,
+ CMSG_COMPLETE_MOVIE = 0x4136,
+ CMSG_CONNECT_TO_FAILED = 0x2533,
+ CMSG_CONTACT_LIST = 0x4534,
+ CMSG_CORPSE_MAP_POSITION_QUERY = 0x6205,
+ CMSG_CREATURE_QUERY = 0x2706,
+ CMSG_DANCE_QUERY = 0x4E07,
+ CMSG_DECLINE_CHANNEL_INVITE = 0x0000,
+ CMSG_DEL_FRIEND = 0x6A15,
+ CMSG_DEL_IGNORE = 0x6D26,
+ CMSG_DEL_VOICE_IGNORE = 0x0024,
+ CMSG_DESTROY_ITEM = 0x4A27,
+ CMSG_DISMISS_CONTROLLED_VEHICLE = 0x3218,
+ CMSG_DISMISS_CRITTER = 0x4227,
+ CMSG_DUEL_ACCEPTED = 0x2136,
+ CMSG_DUEL_CANCELLED = 0x6624,
+ CMSG_EJECT_PASSENGER = 0x6927,
+ CMSG_EMOTE = 0x4C26,
+ CMSG_ENABLETAXI = 0x0C16,
+ CMSG_ENABLE_NAGLE = 0x4449,
+ CMSG_EQUIPMENT_SET_DELETE = 0x4D07,
+ CMSG_EQUIPMENT_SET_SAVE = 0x4F27,
+ CMSG_EQUIPMENT_SET_USE = 0x0417,
+ CMSG_FAR_SIGHT = 0x4835,
+ CMSG_FORCE_MOVE_ROOT_ACK = 0x701E,
+ CMSG_FORCE_MOVE_UNROOT_ACK = 0x7808,
+ CMSG_GAMEOBJECT_QUERY = 0x4017,
+ CMSG_GAMEOBJ_REPORT_USE = 0x4827,
+ CMSG_GAMEOBJ_USE = 0x4E17,
+ CMSG_GAMESPEED_SET = 0x0000,
+ CMSG_GAMETIME_SET = 0x0000,
+ CMSG_GETDEATHBINDZONE = 0x0000,
+ CMSG_GET_MAIL_LIST = 0x4D37,
+ CMSG_GET_MIRRORIMAGE_DATA = 0x0C25,
+ CMSG_GHOST = 0x0000,
+ CMSG_GMRESPONSE_RESOLVE = 0x6506,
+ CMSG_GMSURVEY_SUBMIT = 0x2724,
+ CMSG_GMTICKET_CREATE = 0x0137,
+ CMSG_GMTICKET_DELETETICKET = 0x6B14,
+ CMSG_GMTICKET_GETTICKET = 0x0326,
+ CMSG_GMTICKET_SYSTEMSTATUS = 0x4205,
+ CMSG_GMTICKET_UPDATETEXT = 0x0636,
+ CMSG_GM_INVIS = 0x0000,
+ CMSG_GM_NUKE = 0x0000,
+ CMSG_GM_REPORT_LAG = 0x6726,
+ CMSG_GM_SET_SECURITY_GROUP = 0x0000,
+ CMSG_GOSSIP_HELLO = 0x4525,
+ CMSG_GOSSIP_SELECT_OPTION = 0x0216,
+ CMSG_GRANT_LEVEL = 0x6D16,
+ CMSG_GROUP_ASSISTANT_LEADER = 0x6025,
+ CMSG_GROUP_CANCEL = 0x0000,
+ CMSG_GROUP_CHANGE_SUB_GROUP = 0x4124,
+ CMSG_GROUP_DISBAND = 0x2804,
+ CMSG_GROUP_INVITE = 0x0513,
+ CMSG_GROUP_INVITE_RESPONSE = 0x0410,
+ CMSG_GROUP_RAID_CONVERT = 0x6E27,
+ CMSG_GROUP_REQUEST_JOIN_UPDATES = 0x2583,
+ CMSG_GROUP_SET_LEADER = 0x4C17,
+ CMSG_GROUP_SET_ROLES = 0x25B1,
+ CMSG_GROUP_SWAP_SUB_GROUP = 0x0034,
+ CMSG_GROUP_UNINVITE = 0x0000,
+ CMSG_GROUP_UNINVITE_GUID = 0x2E07,
+ CMSG_GUILD_ACCEPT = 0x2531,
+ CMSG_GUILD_ACHIEVEMENT_MEMBERS = 0x3025,
+ CMSG_GUILD_ACHIEVEMENT_PROGRESS_QUERY = 0x3235,
+ CMSG_GUILD_ADD_RANK = 0x3030,
+ CMSG_GUILD_ASSIGN_MEMBER_RANK = 0x3032,
+ CMSG_GUILD_BANKER_ACTIVATE = 0x2E37,
+ CMSG_GUILD_BANK_BUY_TAB = 0x0C37,
+ CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x0707,
+ CMSG_GUILD_BANK_LOG_QUERY = 0x3224,
+ CMSG_GUILD_BANK_MONEY_WITHDRAWN_QUERY = 0x1225,
+ CMSG_GUILD_BANK_NOTE = 0x0000,
+ CMSG_GUILD_BANK_QUERY_TAB = 0x2E35,
+ CMSG_GUILD_BANK_QUERY_TEXT = 0x3220,
+ CMSG_GUILD_BANK_SWAP_ITEMS = 0x2315,
+ CMSG_GUILD_BANK_UPDATE_TAB = 0x0106,
+ CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x0037,
+ CMSG_GUILD_CHANGE_NAME_REQUEST = 0x1232,
+ CMSG_GUILD_DECLINE = 0x3231,
+ CMSG_GUILD_DEL_RANK = 0x3234,
+ CMSG_GUILD_DEMOTE = 0x1020,
+ CMSG_GUILD_DISBAND = 0x3226,
+ CMSG_GUILD_EVENT_LOG_QUERY = 0x1220,
+ CMSG_GUILD_INFO = 0x0000,
+ CMSG_GUILD_INFO_TEXT = 0x3227,
+ CMSG_GUILD_INVITE = 0x24B0,
+ CMSG_GUILD_LEAVE = 0x1021,
+ CMSG_GUILD_MEMBER_SEND_SOR_REQUEST = 0x3225,
+ CMSG_GUILD_MOTD = 0x1035,
+ CMSG_GUILD_NEWS_UPDATE_STICKY = 0x3223,
+ CMSG_GUILD_PERMISSIONS = 0x3022,
+ CMSG_GUILD_PROMOTE = 0x1030,
+ CMSG_GUILD_QUERY = 0x4426,
+ CMSG_GUILD_QUERY_NEWS = 0x3020,
+ CMSG_GUILD_QUERY_RANKS = 0x1026,
+ CMSG_GUILD_REMOVE = 0x1231,
+ CMSG_GUILD_REPLACE_GUILD_MASTER = 0x1034,
+ CMSG_GUILD_REQUEST_CHALLENGE_UPDATE = 0x1224,
+ CMSG_GUILD_REQUEST_MAX_DAILY_XP = 0x3232,
+ CMSG_GUILD_REQUEST_PARTY_STATE = 0x3900,
+ CMSG_GUILD_ROSTER = 0x1226,
+ CMSG_GUILD_SET_ACHIEVEMENT_TRACKING = 0x1027,
+ CMSG_GUILD_SET_GUILD_MASTER = 0x3034,
+ CMSG_GUILD_SET_NOTE = 0x1233,
+ CMSG_GUILD_SET_RANK_PERMISSIONS = 0x1024,
+ CMSG_GUILD_SWITCH_RANK = 0x1221,
+ CMSG_HEARTH_AND_RESURRECT = 0x4B34,
+ CMSG_IGNORE_TRADE = 0x7112,
+ CMSG_INITIATE_TRADE = 0x7916,
+ CMSG_INSPECT = 0x0927,
+ CMSG_INSPECT_HONOR_STATS = 0x791E,
+ CMSG_INSTANCE_LOCK_WARNING_RESPONSE = 0x6234,
+ CMSG_ITEM_REFUND = 0x6134,
+ CMSG_ITEM_REFUND_INFO = 0x2206,
+ CMSG_ITEM_TEXT_QUERY = 0x2406,
+ CMSG_JOIN_CHANNEL = 0x0156,
+ CMSG_KEEP_ALIVE = 0x0015,
+ CMSG_LEARN_PREVIEW_TALENTS = 0x2415,
+ CMSG_LEARN_PREVIEW_TALENTS_PET = 0x6E24,
+ CMSG_LEARN_TALENT = 0x0306,
+ CMSG_LEAVE_CHANNEL = 0x2D56,
+ CMSG_LFG_GET_STATUS = 0x2581,
+ CMSG_LFG_JOIN = 0x2430,
+ CMSG_LFG_LEAVE = 0x2433,
+ CMSG_LFG_LFR_JOIN = 0x0531,
+ CMSG_LFG_LFR_LEAVE = 0x0500,
+ CMSG_LFG_LOCK_INFO_REQUEST = 0x0412,
+ CMSG_LFG_PROPOSAL_RESULT = 0x0403,
+ CMSG_LFG_SET_BOOT_VOTE = 0x04B3,
+ CMSG_LFG_SET_COMMENT = 0x0530,
+ CMSG_LFG_SET_ROLES = 0x0480,
+ CMSG_LFG_TELEPORT = 0x2482,
+ CMSG_LF_GUILD_ADD_RECRUIT = 0x4448,
+ CMSG_LF_GUILD_BROWSE = 0x0548,
+ CMSG_LF_GUILD_DECLINE_RECRUIT = 0x1031,
+ CMSG_LF_GUILD_GET_APPLICATIONS = 0x1230,
+ CMSG_LF_GUILD_GET_RECRUITS = 0x3230,
+ CMSG_LF_GUILD_POST_REQUEST = 0x3237,
+ CMSG_LF_GUILD_REMOVE_RECRUIT = 0x3027,
+ CMSG_LF_GUILD_SET_GUILD_POST = 0x0448,
+ CMSG_LIST_INVENTORY = 0x2806,
+ CMSG_LOAD_SCREEN = 0x2422,
+ CMSG_LOGOUT_CANCEL = 0x2324,
+ CMSG_LOGOUT_REQUEST = 0x0A25,
+ CMSG_LOG_DISCONNECT = 0x446D,
+ CMSG_LOOT = 0x0127,
+ CMSG_LOOT_CURRENCY = 0x781C,
+ CMSG_LOOT_MASTER_GIVE = 0x4F35,
+ CMSG_LOOT_METHOD = 0x2F24,
+ CMSG_LOOT_MONEY = 0x6227,
+ CMSG_LOOT_RELEASE = 0x2007,
+ CMSG_LOOT_ROLL = 0x6934,
+ CMSG_MAIL_CREATE_TEXT_ITEM = 0x0B14,
+ CMSG_MAIL_DELETE = 0x6104,
+ CMSG_MAIL_MARK_AS_READ = 0x0C07,
+ CMSG_MAIL_RETURN_TO_SENDER = 0x0816,
+ CMSG_MAIL_TAKE_ITEM = 0x2B06,
+ CMSG_MAIL_TAKE_MONEY = 0x4034,
+ CMSG_MEETINGSTONE_INFO = 0x0000,
+ CMSG_MESSAGECHAT_ADDON_BATTLEGROUND = 0x0D46,
+ CMSG_MESSAGECHAT_ADDON_GUILD = 0x0544,
+ CMSG_MESSAGECHAT_ADDON_OFFICER = 0x3954,
+ CMSG_MESSAGECHAT_ADDON_PARTY = 0x0546,
+ CMSG_MESSAGECHAT_ADDON_RAID = 0x1D56,
+ CMSG_MESSAGECHAT_ADDON_WHISPER = 0x2146,
+ CMSG_MESSAGECHAT_AFK = 0x0D44,
+ CMSG_MESSAGECHAT_BATTLEGROUND = 0x2156,
+ CMSG_MESSAGECHAT_CHANNEL = 0x1D44,
+ CMSG_MESSAGECHAT_DND = 0x2946,
+ CMSG_MESSAGECHAT_EMOTE = 0x1156,
+ CMSG_MESSAGECHAT_GUILD = 0x3956,
+ CMSG_MESSAGECHAT_OFFICER = 0x1946,
+ CMSG_MESSAGECHAT_PARTY = 0x1D46,
+ CMSG_MESSAGECHAT_RAID = 0x2D44,
+ CMSG_MESSAGECHAT_RAID_WARNING = 0x0944,
+ CMSG_MESSAGECHAT_SAY = 0x1154,
+ CMSG_MESSAGECHAT_WHISPER = 0x0D56,
+ CMSG_MESSAGECHAT_YELL = 0x3544,
+ CMSG_MINIGAME_MOVE = 0x2A34,
+ CMSG_MOUNTSPECIAL_ANIM = 0x2807,
+ CMSG_MOVE_CHARM_TELEPORT_CHEAT = 0x0000,
+ CMSG_MOVE_CHNG_TRANSPORT = 0x3102,
+ CMSG_MOVE_ENABLE_SWIM_TO_FLY_TRANS_ACK = 0x0000,
+ CMSG_MOVE_FALL_RESET = 0x310A,
+ CMSG_MOVE_FEATHER_FALL_ACK = 0x3110,
+ CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK = 0x310E,
+ CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK = 0x7314,
+ CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK = 0x3100,
+ CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK = 0x3216,
+ CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK = 0x7818,
+ CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK = 0x7A16,
+ CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK = 0x7A10,
+ CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK = 0x7316,
+ CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK = 0x7210,
+ CMSG_MOVE_GRAVITY_DISABLE_ACK = 0x3118,
+ CMSG_MOVE_GRAVITY_ENABLE_ACK = 0x700A,
+ CMSG_MOVE_HOVER_ACK = 0x3318,
+ CMSG_MOVE_KNOCK_BACK_ACK = 0x721C,
+ CMSG_MOVE_NOT_ACTIVE_MOVER = 0x7A1A,
+ CMSG_MOVE_SET_CAN_FLY = 0x720E,
+ CMSG_MOVE_SET_CAN_FLY_ACK = 0x790C,
+ CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK = 0x3014,
+ CMSG_MOVE_SET_COLLISION_HEIGHT_ACK = 0x7114,
+ CMSG_MOVE_SET_RELATIVE_POSITION = 0x0000,
+ CMSG_MOVE_SET_VEHICLE_REC_ID_ACK = 0x0000,
+ CMSG_MOVE_SPLINE_DONE = 0x790E,
+ CMSG_MOVE_TIME_SKIPPED = 0x7A0A,
+ CMSG_MOVE_TOGGLE_COLLISION_ACK = 0x0000,
+ CMSG_MOVE_WATER_WALK_ACK = 0x3B00,
+ CMSG_NAME_QUERY = 0x2224,
+ CMSG_NEW_SPELL_SLOT = 0x0000,
+ CMSG_NEXT_CINEMATIC_CAMERA = 0x2014,
+ CMSG_NPC_TEXT_QUERY = 0x4E24,
+ CMSG_OBJECT_UPDATE_FAILED = 0x3808,
+ CMSG_OBJECT_UPDATE_RESCUED = 0x3906,
+ CMSG_OFFER_PETITION = 0x4817,
+ CMSG_OPENING_CINEMATIC = 0x0A16,
+ CMSG_OPEN_ITEM = 0x6A34,
+ CMSG_OPT_OUT_OF_LOOT = 0x6B16,
+ CMSG_PAGE_TEXT_QUERY = 0x6614,
+ CMSG_PARTY_SILENCE = 0x6B26,
+ CMSG_PARTY_UNSILENCE = 0x4D24,
+ CMSG_PETITION_BUY = 0x4E05,
+ CMSG_PETITION_QUERY = 0x4424,
+ CMSG_PETITION_SHOWLIST = 0x4617,
+ CMSG_PETITION_SHOW_SIGNATURES = 0x4F15,
+ CMSG_PETITION_SIGN = 0x0E04,
+ CMSG_PET_ABANDON = 0x0C24,
+ CMSG_PET_ACTION = 0x0226,
+ CMSG_PET_CANCEL_AURA = 0x4B25,
+ CMSG_PET_CAST_SPELL = 0x6337,
+ CMSG_PET_LEARN_TALENT = 0x6725,
+ CMSG_PET_NAME_CACHE = 0x0000,
+ CMSG_PET_NAME_QUERY = 0x6F24,
+ CMSG_PET_RENAME = 0x6406,
+ CMSG_PET_SET_ACTION = 0x6904,
+ CMSG_PET_SPELL_AUTOCAST = 0x2514,
+ CMSG_PET_STOP_ATTACK = 0x6C14,
+ CMSG_PING = 0x444D,
+ CMSG_PLAYED_TIME = 0x0804,
+ CMSG_PLAYER_DIFFICULTY_CHANGE = 0x0000,
+ CMSG_PLAYER_LOGIN = 0x05B1,
+ CMSG_PLAYER_LOGOUT = 0x0000,
+ CMSG_PLAYER_VEHICLE_ENTER = 0x2705,
+ CMSG_PLAY_DANCE = 0x6914,
+ CMSG_PUSHQUESTTOPARTY = 0x4B14,
+ CMSG_PVP_LOG_DATA = 0x7308,
+ CMSG_QUERY_BATTLEFIELD_STATE = 0x7202,
+ CMSG_QUERY_GUILD_MEMBERS_FOR_RECIPE = 0x1036,
+ CMSG_QUERY_GUILD_MEMBER_RECIPES = 0x1037,
+ CMSG_QUERY_GUILD_RECIPES = 0x3033,
+ CMSG_QUERY_GUILD_REWARDS = 0x3012,
+ CMSG_QUERY_GUILD_XP = 0x1237,
+ CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x4D27,
+ CMSG_QUERY_QUESTS_COMPLETED = 0x2317,
+ CMSG_QUERY_TIME = 0x0A36,
+ CMSG_QUESTGIVER_ACCEPT_QUEST = 0x6B37,
+ CMSG_QUESTGIVER_CANCEL = 0x0000,
+ CMSG_QUESTGIVER_CHOOSE_REWARD = 0x2125,
+ CMSG_QUESTGIVER_COMPLETE_QUEST = 0x0114,
+ CMSG_QUESTGIVER_HELLO = 0x0D17,
+ CMSG_QUESTGIVER_QUERY_QUEST = 0x2F14,
+ CMSG_QUESTGIVER_QUEST_AUTOLAUNCH = 0x0000,
+ CMSG_QUESTGIVER_REQUEST_REWARD = 0x2534,
+ CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x6305,
+ CMSG_QUESTGIVER_STATUS_QUERY = 0x4407,
+ CMSG_QUESTLOG_REMOVE_QUEST = 0x0D16,
+ CMSG_QUESTLOG_SWAP_QUEST = 0x0000,
+ CMSG_QUEST_CONFIRM_ACCEPT = 0x0D15,
+ CMSG_QUEST_NPC_QUERY = 0x7302,
+ CMSG_QUEST_POI_QUERY = 0x4037,
+ CMSG_QUEST_QUERY = 0x0D06,
+ CMSG_RANDOMIZE_CHAR_NAME = 0x2413,
+ CMSG_READY_FOR_ACCOUNT_DATA_TIMES = 0x2B16,
+ CMSG_READ_ITEM = 0x2F16,
+ CMSG_REALM_SPLIT = 0x2906,
+ CMSG_RECLAIM_CORPSE = 0x4036,
+ CMSG_REDIRECTION_AUTH_PROOF = 0x044D,
+ CMSG_REFORGE_ITEM = 0x331A,
+ CMSG_REORDER_CHARACTERS = 0x0593,
+ CMSG_REPAIR_ITEM = 0x2917,
+ CMSG_REPLACE_ACCOUNT_DATA = 0x0000,
+ CMSG_REPOP_REQUEST = 0x6235,
+ CMSG_REPORT_PVP_AFK = 0x6734,
+ CMSG_REQUEST_ACCOUNT_DATA = 0x6505,
+ CMSG_REQUEST_CATEGORY_COOLDOWNS = 0x7102,
+ CMSG_REQUEST_CEMETERY_LIST = 0x720A,
+ CMSG_REQUEST_HOTFIX = 0x2401,
+ CMSG_REQUEST_INSPECT_RATED_BG_STATS = 0x3010,
+ CMSG_REQUEST_PARTY_MEMBER_STATS = 0x0C04,
+ CMSG_REQUEST_PET_INFO = 0x4924,
+ CMSG_REQUEST_PVP_OPTIONS_ENABLED = 0x24A1,
+ CMSG_REQUEST_PVP_REWARDS = 0x780C,
+ CMSG_REQUEST_RAID_INFO = 0x2F26,
+ CMSG_REQUEST_RATED_BG_INFO = 0x2423,
+ CMSG_REQUEST_RATED_BG_STATS = 0x05B3,
+ CMSG_REQUEST_RESEARCH_HISTORY = 0x3306,
+ CMSG_REQUEST_VEHICLE_EXIT = 0x2B35,
+ CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x4434,
+ CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x4C04,
+ CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x4C14,
+ CMSG_RESET_FACTION_CHEAT = 0x4469,
+ CMSG_RESET_INSTANCES = 0x6E14,
+ CMSG_RESURRECT_RESPONSE = 0x6827,
+ CMSG_RETURN_TO_GRAVEYARD = 0x301E,
+ CMSG_ROLE_POLL_BEGIN = 0x0430,
+ CMSG_SAVE_CUF_PROFILES = 0x730E,
+ CMSG_SAVE_PLAYER = 0x0000,
+ CMSG_SEARCH_LFG_JOIN = 0x0000,
+ CMSG_SEARCH_LFG_LEAVE = 0x0000,
+ CMSG_SELF_RES = 0x6115,
+ CMSG_SELL_ITEM = 0x4E15,
+ CMSG_SEND_MAIL = 0x0523,
+ CMSG_SEND_SOR_REQUEST_VIA_ADDRESS = 0x0420,
+ CMSG_SEND_SOR_REQUEST_VIA_BNET_ACCOUNT_ID = 0x0482,
+ CMSG_SERVERTIME = 0x0000,
+ CMSG_SETDEATHBINDPOINT = 0x0000,
+ CMSG_SETSHEATHED = 0x4326,
+ CMSG_SET_ACTIONBAR_TOGGLES = 0x2506,
+ CMSG_SET_ACTION_BUTTON = 0x6F06,
+ CMSG_SET_ACTIVE_MOVER = 0x3314,
+ CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x4305,
+ CMSG_SET_ALLOW_LOW_LEVEL_RAID1 = 0x4435,
+ CMSG_SET_ALLOW_LOW_LEVEL_RAID2 = 0x0536,
+ CMSG_SET_CHANNEL_WATCH = 0x4517,
+ CMSG_SET_CONTACT_NOTES = 0x6135,
+ CMSG_SET_CURRENCY_FLAGS = 0x7306,
+ CMSG_SET_EVERYONE_IS_ASSISTANT = 0x2530,
+ CMSG_SET_FACTION_ATWAR = 0x0706,
+ CMSG_SET_FACTION_CHEAT = 0x0000,
+ CMSG_SET_FACTION_INACTIVE = 0x0E37,
+ CMSG_SET_GUILD_BANK_TEXT = 0x3023,
+ CMSG_SET_LFG_COMMENT = 0x0000,
+ CMSG_SET_PET_SLOT = 0x3A04,
+ CMSG_SET_PLAYER_DECLINED_NAMES = 0x6316,
+ CMSG_SET_PREFERED_CEMETERY = 0x311E,
+ CMSG_SET_PRIMARY_TALENT_TREE = 0x4524,
+ CMSG_SET_RELATIVE_POSITION = 0x311A,
+ CMSG_SET_SAVED_INSTANCE_EXTEND = 0x6706,
+ CMSG_SET_SELECTION = 0x0506,
+ CMSG_SET_SKILL_CHEAT = 0x0000,
+ CMSG_SET_TAXI_BENCHMARK_MODE = 0x4314,
+ CMSG_SET_TITLE = 0x2117,
+ CMSG_SET_TRADE_CURRENCY = 0x3312,
+ CMSG_SET_TRADE_GOLD = 0x3008,
+ CMSG_SET_TRADE_ITEM = 0x7B0C,
+ CMSG_SET_VEHICLE_REC_ID_ACK = 0x3108,
+ CMSG_SET_WATCHED_FACTION = 0x2434,
+ CMSG_SHOWING_CLOAK = 0x4135,
+ CMSG_SHOWING_HELM = 0x0735,
+ CMSG_SOCKET_GEMS = 0x2F04,
+ CMSG_SPELLCLICK = 0x0805,
+ CMSG_SPIRIT_HEALER_ACTIVATE = 0x2E26,
+ CMSG_SPLIT_ITEM = 0x0F17,
+ CMSG_STANDSTATECHANGE = 0x0535,
+ CMSG_START_QUEST = 0x0000,
+ CMSG_STOP_DANCE = 0x2907,
+ CMSG_STORE_LOOT_IN_SLOT = 0x0000,
+ CMSG_SUBMIT_BUG = 0x2520,
+ CMSG_SUBMIT_COMPLAIN = 0x2501,
+ CMSG_SUGGESTION_SUBMIT = 0x2512,
+ CMSG_SUMMON_RESPONSE = 0x6F27,
+ CMSG_SUSPEND_TOKEN = 0x046D,
+ CMSG_SWAP_INV_ITEM = 0x2614,
+ CMSG_SWAP_ITEM = 0x6326,
+ CMSG_SYNC_DANCE = 0x0036,
+ CMSG_TAXICLEARALLNODES = 0x0000,
+ CMSG_TAXIENABLEALLNODES = 0x0000,
+ CMSG_TAXINODE_STATUS_QUERY = 0x2F25,
+ CMSG_TAXIQUERYAVAILABLENODES = 0x6C06,
+ CMSG_TAXISHOWNODES = 0x0000,
+ CMSG_TELEPORT_TO_UNIT = 0x4206,
+ CMSG_TEXT_EMOTE = 0x2E24,
+ CMSG_TIME_ADJUSTMENT_RESPONSE = 0x3818,
+ CMSG_TIME_SYNC_RESP = 0x3B0C,
+ CMSG_TIME_SYNC_RESP_FAILED = 0x710A,
+ CMSG_TOGGLE_PVP = 0x6815,
+ CMSG_TOTEM_DESTROYED = 0x4207,
+ CMSG_TRAINER_BUY_SPELL = 0x4415,
+ CMSG_TRAINER_LIST = 0x2336,
+ CMSG_TRANSMOGRIFY_ITEMS = 0x3B0E,
+ CMSG_TRIGGER_CINEMATIC_CHEAT = 0x0000,
+ CMSG_TURN_IN_PETITION = 0x0B27,
+ CMSG_TUTORIAL_CLEAR = 0x6515,
+ CMSG_TUTORIAL_FLAG = 0x6C26,
+ CMSG_TUTORIAL_RESET = 0x2726,
+ CMSG_UNACCEPT_TRADE = 0x391A,
+ CMSG_UNLEARN_SKILL = 0x6106,
+ CMSG_UNLEARN_SPECIALIZATION = 0x3210,
+ CMSG_UNREGISTER_ALL_ADDON_PREFIXES = 0x3D54,
+ CMSG_UPDATE_ACCOUNT_DATA = 0x4736,
+ CMSG_UPDATE_MISSILE_TRAJECTORY = 0x781E,
+ CMSG_UPDATE_PROJECTILE_POSITION = 0x0E24,
+ CMSG_USED_FOLLOW = 0x7912,
+ CMSG_USE_ITEM = 0x2C06,
+ CMSG_VIOLENCE_LEVEL = 0x7816,
+ CMSG_VOICE_SESSION_ENABLE = 0x2314,
+ CMSG_VOID_STORAGE_QUERY = 0x790A,
+ CMSG_VOID_STORAGE_TRANSFER = 0x380E,
+ CMSG_VOID_STORAGE_UNLOCK = 0x7B14,
+ CMSG_VOID_SWAP_ITEM = 0x3204,
+ CMSG_WARDEN_DATA = 0x25A2,
+ CMSG_WARGAME_ACCEPT = 0x2410,
+ CMSG_WARGAME_START = 0x05A0,
+ CMSG_WHO = 0x6C15,
+ CMSG_WHOIS = 0x6B05,
+ CMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4605,
+ CMSG_WORLD_TELEPORT = 0x24B2,
+ CMSG_WRAP_ITEM = 0x4F06,
+ CMSG_ZONEUPDATE = 0x4F37,
+ MSG_AUCTION_HELLO = 0x2307,
+ MSG_CHANNEL_START = 0x0A15, // SMSG only?
+ MSG_CHANNEL_UPDATE = 0x2417, // SMSG only?
+ MSG_CORPSE_QUERY = 0x4336,
+ MSG_GM_BIND_OTHER = 0x0000,
+ MSG_GM_SHOWLABEL = 0x0000,
+ MSG_GM_SUMMON = 0x0000,
+ MSG_INSPECT_ARENA_TEAMS = 0x2704,
+ MSG_LIST_STABLED_PETS = 0x0834,
+ MSG_MINIMAP_PING = 0x6635,
+ MSG_MOVE_CHARM_TELEPORT_CHEAT = 0x7A08,
+ MSG_MOVE_FALL_LAND = 0x380A,
+ MSG_MOVE_HEARTBEAT = 0x3914,
+ MSG_MOVE_JUMP = 0x7A06,
+ MSG_MOVE_SET_ALL_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_COLLISION_HEIGHT = 0x0000,
+ MSG_MOVE_SET_FACING = 0x7914,
+ MSG_MOVE_SET_FLIGHT_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_PITCH = 0x7312,
+ MSG_MOVE_SET_RAW_POSITION_ACK = 0x0000,
+ MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_RUN_MODE = 0x791A,
+ MSG_MOVE_SET_RUN_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_SWIM_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_SET_TURN_RATE_CHEAT = 0x0000,
+ MSG_MOVE_SET_WALK_MODE = 0x7002,
+ MSG_MOVE_SET_WALK_SPEED_CHEAT = 0x0000,
+ MSG_MOVE_START_ASCEND = 0x390A,
+ MSG_MOVE_START_BACKWARD = 0x330A,
+ MSG_MOVE_START_DESCEND = 0x3800,
+ MSG_MOVE_START_FORWARD = 0x7814,
+ MSG_MOVE_START_PITCH_DOWN = 0x3908,
+ MSG_MOVE_START_PITCH_UP = 0x3304,
+ MSG_MOVE_START_STRAFE_LEFT = 0x3A16,
+ MSG_MOVE_START_STRAFE_RIGHT = 0x3A02,
+ MSG_MOVE_START_SWIM = 0x3206,
+ MSG_MOVE_START_TURN_LEFT = 0x700C,
+ MSG_MOVE_START_TURN_RIGHT = 0x7000,
+ MSG_MOVE_STOP = 0x320A,
+ MSG_MOVE_STOP_ASCEND = 0x7B00,
+ MSG_MOVE_STOP_PITCH = 0x7216,
+ MSG_MOVE_STOP_STRAFE = 0x3002,
+ MSG_MOVE_STOP_SWIM = 0x3802,
+ MSG_MOVE_STOP_TURN = 0x331E,
+ MSG_MOVE_TELEPORT = 0x55A0,
+ MSG_MOVE_TELEPORT_ACK = 0x390C,
+ MSG_MOVE_TELEPORT_CHEAT = 0x3A10,
+ MSG_MOVE_TIME_SKIPPED = 0x19B3,
+ MSG_MOVE_TOGGLE_COLLISION_CHEAT = 0x7B04,
+ MSG_MOVE_TOGGLE_FALL_LOGGING = 0x0000,
+ MSG_MOVE_TOGGLE_LOGGING = 0x0000,
+ MSG_MOVE_UPDATE_MOUSE = 0x0000,
+ MSG_MOVE_WORLDPORT_ACK = 0x2411,
+ MSG_NOTIFY_PARTY_SQUELCH = 0x4D06,
+ MSG_PARTY_ASSIGNMENT = 0x0424,
+ MSG_PETITION_DECLINE = 0x4905,
+ MSG_PETITION_RENAME = 0x4005,
+ MSG_PVP_LOG_DATA = 0x0000,
+ MSG_QUERY_NEXT_MAIL_TIME = 0x0F04,
+ MSG_QUEST_PUSH_RESULT = 0x4515,
+ MSG_RAID_READY_CHECK = 0x2304,
+ MSG_RAID_READY_CHECK_CONFIRM = 0x4F05,
+ MSG_RAID_READY_CHECK_FINISHED = 0x2E15,
+ MSG_RAID_TARGET_UPDATE = 0x2C36,
+ MSG_RANDOM_ROLL = 0x0905,
+ MSG_SAVE_GUILD_EMBLEM = 0x2404,
+ MSG_SET_DUNGEON_DIFFICULTY = 0x4925,
+ MSG_SET_RAID_DIFFICULTY = 0x0614,
+ MSG_START_MOVE_FORWARD = 0x0000,
+ MSG_TABARDVENDOR_ACTIVATE = 0x6926,
+ MSG_TALENT_WIPE_CONFIRM = 0x0107,
+ MSG_VERIFY_CONNECTIVITY = 0x4F57,
+ SMSG_ACCOUNT_DATA_TIMES = 0x4B05,
+ SMSG_ACCOUNT_INFO_RESPONSE = 0x10A7,
+ SMSG_ACCOUNT_RESTRICTED_WARNING = 0x51A7,
+ SMSG_ACHIEVEMENT_DELETED = 0x6A16,
+ SMSG_ACHIEVEMENT_EARNED = 0x4405,
+ SMSG_ACTION_BUTTONS = 0x38B5,
+ SMSG_ACTIVATETAXIREPLY = 0x6A37,
+ SMSG_ADDON_INFO = 0x2C14,
+ SMSG_ADD_RUNE_POWER = 0x6915,
+ SMSG_AI_REACTION = 0x0637,
+ SMSG_ALL_ACHIEVEMENT_DATA = 0x58B1,
+ SMSG_AREA_SPIRIT_HEALER_TIME = 0x0734,
+ SMSG_AREA_TRIGGER_MESSAGE = 0x4505,
+ SMSG_AREA_TRIGGER_MOVEMENT_UPDATE = 0x3DB1,
+ SMSG_ARENA_ERROR = 0x2D17,
+ SMSG_ARENA_UNIT_DESTROYED = 0x2637,
+ SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED = 0x6E34,
+ SMSG_ARENA_TEAM_COMMAND_RESULT = 0x39B3,
+ SMSG_ARENA_TEAM_EVENT = 0x0617,
+ SMSG_ARENA_TEAM_INVITE = 0x0F36,
+ SMSG_ARENA_TEAM_QUERY_RESPONSE = 0x6336,
+ SMSG_ARENA_TEAM_ROSTER = 0x2717,
+ SMSG_ARENA_TEAM_STATS = 0x4425,
+ SMSG_ATTACKERSTATEUPDATE = 0x0B25,
+ SMSG_ATTACKSTART = 0x2D15,
+ SMSG_ATTACKSTOP = 0x0934,
+ SMSG_ATTACKSWING_BADFACING = 0x0B36,
+ SMSG_ATTACKSWING_CANT_ATTACK = 0x0016,
+ SMSG_ATTACKSWING_DEADTARGET = 0x2B26,
+ SMSG_ATTACKSWING_NOTINRANGE = 0x6C07,
+ SMSG_AUCTION_BIDDER_LIST_RESULT = 0x0027,
+ SMSG_AUCTION_BIDDER_NOTIFICATION = 0x4E27,
+ SMSG_AUCTION_COMMAND_RESULT = 0x4C25,
+ SMSG_AUCTION_LIST_PENDING_SALES = 0x6A27,
+ SMSG_AUCTION_LIST_RESULT = 0x6637,
+ SMSG_AUCTION_OWNER_LIST_RESULT = 0x6C34,
+ SMSG_AUCTION_OWNER_NOTIFICATION = 0x4116,
+ SMSG_AUCTION_REMOVED_NOTIFICATION = 0x2334,
+ SMSG_AURACASTLOG = 0x0000,
+ SMSG_AURA_POINTS_DEPLETED = 0x7CB7,
+ SMSG_AURA_UPDATE = 0x4707,
+ SMSG_AURA_UPDATE_ALL = 0x6916,
+ SMSG_AUTH_CHALLENGE = 0x4542,
+ SMSG_AUTH_RESPONSE = 0x5DB6,
+ SMSG_AVAILABLE_VOICE_CHANNEL = 0x2E16,
+ SMSG_AVERAGE_ITEM_LEVEL_INFORM = 0x5DA7,
+ SMSG_BARBER_SHOP_RESULT = 0x6125,
+ SMSG_BATTLEFIELD_LIST = 0x71B5,
+ SMSG_BATTLEFIELD_MGR_EJECTED = 0x7DB7,
+ SMSG_BATTLEFIELD_MGR_EJECT_PENDING = 0x34A2,
+ SMSG_BATTLEFIELD_MGR_ENTERED = 0x5CA0,
+ SMSG_BATTLEFIELD_MGR_ENTRY_INVITE = 0x34B3,
+ SMSG_BATTLEFIELD_MGR_EXIT_REQUEST = 0x51B1,
+ SMSG_BATTLEFIELD_MGR_QUEUE_INVITE = 0x15A6,
+ SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE = 0x79B6,
+ SMSG_BATTLEFIELD_MGR_STATE_CHANGE = 0x35B4,
+ SMSG_BATTLEFIELD_PLAYER_POSITIONS = 0x58B4,
+ SMSG_BATTLEFIELD_PORT_DENIED = 0x35A3,
+ SMSG_BATTLEFIELD_RATED_INFO = 0x54A3,
+ SMSG_BATTLEFIELD_STATUS = 0x7DA1,
+ SMSG_BATTLEFIELD_STATUS_QUEUED = 0x35A1,
+ SMSG_BATTLEFIELD_STATUS_ACTIVE = 0x74A4,
+ SMSG_BATTLEFIELD_STATUS_NEEDCONFIRMATION = 0x59A0,
+ SMSG_BATTLEFIELD_STATUS_WAITFORGROUPS = 0x75A2,
+ SMSG_BATTLEFIELD_STATUS_FAILED = 0x71A7,
+ SMSG_BATTLEGROUND_INFO_THROTTLED = 0x34B2,
+ SMSG_BATTLEGROUND_PLAYER_JOINED = 0x50B0,
+ SMSG_BATTLEGROUND_PLAYER_LEFT = 0x59A6,
+ SMSG_BINDER_CONFIRM = 0x2835,
+ SMSG_BINDPOINTUPDATE = 0x0527,
+ SMSG_BINDZONEREPLY = 0x0000,
+ SMSG_BREAK_TARGET = 0x0105,
+ SMSG_BUY_BANK_SLOT_RESULT = 0x4806,
+ SMSG_BUY_FAILED = 0x6435,
+ SMSG_BUY_ITEM = 0x0F26,
+ SMSG_CALENDAR_ACTION_PENDING = 0x0000,
+ SMSG_CALENDAR_ARENA_TEAM = 0x0615,
+ SMSG_CALENDAR_CLEAR_PENDING_ACTION = 0x2106,
+ SMSG_CALENDAR_COMMAND_RESULT = 0x6F36,
+ SMSG_CALENDAR_EVENT_INVITE = 0x4E16,
+ SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x2A05,
+ SMSG_CALENDAR_EVENT_INVITE_NOTES = 0x0E17,
+ SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT = 0x2535,
+ SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x0725,
+ SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x2617,
+ SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x6625,
+ SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x6B06,
+ SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x6D35,
+ SMSG_CALENDAR_EVENT_STATUS = 0x2A27,
+ SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x0907,
+ SMSG_CALENDAR_FILTER_GUILD = 0x4A26,
+ SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x2305,
+ SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x2E25,
+ SMSG_CALENDAR_RAID_LOCKOUT_UPDATED = 0x4636,
+ SMSG_CALENDAR_SEND_CALENDAR = 0x6805,
+ SMSG_CALENDAR_SEND_EVENT = 0x0C35,
+ SMSG_CALENDAR_SEND_NUM_PENDING = 0x0C17,
+ SMSG_CALENDAR_UPDATE_INVITE_LIST = 0x0000,
+ SMSG_CAMERA_SHAKE = 0x4214,
+ SMSG_CANCEL_AUTO_REPEAT = 0x6436,
+ SMSG_CANCEL_COMBAT = 0x4F04,
+ SMSG_CAST_FAILED = 0x4D16,
+ SMSG_CHANNEL_LIST = 0x2214,
+ SMSG_CHANNEL_MEMBER_COUNT = 0x6414,
+ SMSG_CHANNEL_NOTIFY = 0x0825,
+ SMSG_CHARACTER_LOGIN_FAILED = 0x4417,
+ SMSG_CHAR_CREATE = 0x2D05,
+ SMSG_CHAR_CUSTOMIZE = 0x4F16,
+ SMSG_CHAR_DELETE = 0x0304,
+ SMSG_CHAR_ENUM = 0x10B0,
+ SMSG_CHAR_FACTION_CHANGE = 0x4C06,
+ SMSG_CHAR_RENAME = 0x2024,
+ SMSG_CHAT_IGNORED_ACCOUNT_MUTED = 0x15A4,
+ SMSG_CHAT_NOT_IN_PARTY = 0x6A14,
+ SMSG_CHAT_PLAYER_AMBIGUOUS = 0x2F34,
+ SMSG_CHAT_PLAYER_NOT_FOUND = 0x2526,
+ SMSG_CHAT_RESTRICTED = 0x6536,
+ SMSG_CHAT_SERVER_DISCONNECTED = 0x6D34,
+ SMSG_CHAT_SERVER_RECONNECTED = 0x6905,
+ SMSG_CHAT_WRONG_FACTION = 0x6724,
+ SMSG_CHECK_FOR_BOTS = 0x0000,
+ SMSG_CLEAR_BOSS_EMOTES = 0x19A3,
+ SMSG_CLEAR_COOLDOWN = 0x0627,
+ SMSG_CLEAR_COOLDOWNS = 0x59B4,
+ SMSG_CLEAR_FAR_SIGHT_IMMEDIATE = 0x2A04,
+ SMSG_CLEAR_TARGET = 0x4B26,
+ SMSG_CLIENTCACHE_VERSION = 0x2734,
+ SMSG_CLIENT_CONTROL_UPDATE = 0x2837,
+ SMSG_COMBAT_EVENT_FAILED = 0x2B07,
+ SMSG_COMBAT_LOG_MULTIPLE = 0x0000,
+ SMSG_COMMENTATOR_MAP_INFO = 0x0327,
+ SMSG_COMMENTATOR_PARTY_INFO = 0x38B0,
+ SMSG_COMMENTATOR_PLAYER_INFO = 0x2F36,
+ SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT1 = 0x2126,
+ SMSG_COMMENTATOR_SKIRMISH_QUEUE_RESULT2 = 0x6814,
+ SMSG_COMMENTATOR_STATE_CHANGED = 0x0737,
+ SMSG_COMPLAIN_RESULT = 0x6D24,
+ SMSG_COMPRESSED_MOVES = 0x0517,
+ SMSG_COMSAT_CONNECT_FAIL = 0x6317,
+ SMSG_COMSAT_DISCONNECT = 0x0316,
+ SMSG_COMSAT_RECONNECT_TRY = 0x4D35,
+ SMSG_CONTACT_LIST = 0x6017,
+ SMSG_CONVERT_RUNE = 0x4F14,
+ SMSG_COOLDOWN_CHEAT = 0x4537,
+ SMSG_COOLDOWN_EVENT = 0x4F26,
+ SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE = 0x0E35,
+ SMSG_CORPSE_NOT_IN_INSTANCE = 0x2A14,
+ SMSG_CORPSE_RECLAIM_DELAY = 0x0D34,
+ SMSG_CREATURE_QUERY_RESPONSE = 0x6024,
+ SMSG_CRITERIA_DELETED = 0x2915,
+ SMSG_CRITERIA_UPDATE = 0x6E37,
+ SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x2036,
+ SMSG_CURRENCY_LOOT_REMOVED = 0x1DB4,
+ SMSG_CURRENCY_LOOT_RESTORED = 0x30A0,
+ SMSG_CUSTOM_LOAD_SCREEN = 0x1DB6,
+ SMSG_DAMAGE_CALC_LOG = 0x2436,
+ SMSG_DAMAGE_DONE_OBSOLETE = 0x0000,
+ SMSG_DANCE_QUERY_RESPONSE = 0x2F06,
+ SMSG_DB_REPLY = 0x38A4,
+ SMSG_DEATH_RELEASE_LOC = 0x2F07,
+ SMSG_DEBUG_RUNE_REGEN = 0x31B3,
+ SMSG_DEFENSE_MESSAGE = 0x0314,
+ SMSG_DESTROY_OBJECT = 0x4724,
+ SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x4825,
+ SMSG_DIFFERENT_INSTANCE_FROM_PARTY = 0x15B1,
+ SMSG_DISENCHANT_CREDIT = 0x55A2,
+ SMSG_DISMOUNT = 0x2135,
+ SMSG_DISMOUNTRESULT = 0x0D25,
+ SMSG_DISPEL_FAILED = 0x0307,
+ SMSG_DISPLAY_GAME_ERROR = 0x31A6,
+ SMSG_DONT_AUTO_PUSH_SPELLS_TO_ACTION_BAR = 0x38A2,
+ SMSG_DROP_NEW_CONNECTION = 0x4D40,
+ SMSG_DUEL_COMPLETE = 0x2527,
+ SMSG_DUEL_COUNTDOWN = 0x4836,
+ SMSG_DUEL_INBOUNDS = 0x0A27,
+ SMSG_DUEL_OUTOFBOUNDS = 0x0C26,
+ SMSG_DUEL_REQUESTED = 0x4504,
+ SMSG_DUEL_WINNER = 0x2D36,
+ SMSG_DUMP_RIDE_TICKETS_RESPONSE = 0x11A3,
+ SMSG_DURABILITY_DAMAGE_DEATH = 0x4C27,
+ SMSG_ECHO_PARTY_SQUELCH = 0x0814,
+ SMSG_EMOTE = 0x0A34,
+ SMSG_ENABLE_BARBER_SHOP = 0x2D16,
+ SMSG_ENCHANTMENTLOG = 0x6035,
+ SMSG_ENVIRONMENTALDAMAGELOG = 0x6C05,
+ SMSG_EQUIPMENT_SET_LIST = 0x2E04,
+ SMSG_EQUIPMENT_SET_SAVED = 0x2216,
+ SMSG_EQUIPMENT_SET_USE_RESULT = 0x2424,
+ SMSG_EXPECTED_SPAM_RECORDS = 0x4D36,
+ SMSG_EXPLORATION_EXPERIENCE = 0x6716,
+ SMSG_FAILED_PLAYER_CONDITION = 0x19A4,
+ SMSG_FEATURE_SYSTEM_STATUS = 0x3DB7,
+ SMSG_FEIGN_DEATH_RESISTED = 0x0D05,
+ SMSG_FISH_ESCAPED = 0x2205,
+ SMSG_FISH_NOT_HOOKED = 0x0A17,
+ SMSG_FLIGHT_SPLINE_SYNC = 0x0924,
+ SMSG_FLOOD_DETECTED = 0x0542,
+ SMSG_FORCEACTIONSHOW = 0x0000,
+ SMSG_FORCED_DEATH_UPDATE = 0x2606,
+ SMSG_FORCE_DISPLAY_UPDATE = 0x0000,
+ SMSG_FORCE_SEND_QUEUED_PACKETS = 0x0140,
+ SMSG_FORCE_SET_VEHICLE_REC_ID = 0x70A1,
+ SMSG_FORGE_MASTER_SET = 0x70B7,
+ SMSG_FRIEND_STATUS = 0x0717,
+ SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x4936,
+ SMSG_GAMEOBJECT_DESPAWN_ANIM = 0x6735,
+ SMSG_GAMEOBJECT_PAGETEXT = 0x2925,
+ SMSG_GAMEOBJECT_QUERY_RESPONSE = 0x0915,
+ SMSG_GAMEOBJECT_RESET_STATE = 0x2A16,
+ SMSG_GAMESPEED_SET = 0x4E34,
+ SMSG_GAMETIME_SET = 0x0014,
+ SMSG_GAMETIME_UPDATE = 0x4127,
+ SMSG_GAME_EVENT_DEBUG_LOG = 0x31A7,
+ SMSG_GAME_OBJECT_ACTIVATE_ANIM_KIT = 0x14A3,
+ SMSG_GMRESPONSE_DB_ERROR = 0x0006,
+ SMSG_GMRESPONSE_RECEIVED = 0x2E34,
+ SMSG_GMRESPONSE_STATUS_UPDATE = 0x0A04,
+ SMSG_GMTICKET_CREATE = 0x2107,
+ SMSG_GMTICKET_DELETETICKET = 0x6D17,
+ SMSG_GMTICKET_GETTICKET = 0x2C15,
+ SMSG_GMTICKET_SYSTEMSTATUS = 0x0D35,
+ SMSG_GMTICKET_UPDATETEXT = 0x6535,
+ SMSG_GM_MESSAGECHAT = 0x6434,
+ SMSG_GM_PLAYER_INFO = 0x4A15,
+ SMSG_GM_TICKET_STATUS_UPDATE = 0x2C25,
+ SMSG_GODMODE = 0x0405,
+ SMSG_GOSSIP_COMPLETE = 0x0806,
+ SMSG_GOSSIP_MESSAGE = 0x2035,
+ SMSG_GOSSIP_POI = 0x4316,
+ SMSG_GROUPACTION_THROTTLED = 0x6524,
+ SMSG_GROUP_CANCEL = 0x4D25,
+ SMSG_GROUP_DECLINE = 0x6835,
+ SMSG_GROUP_DESTROYED = 0x2207,
+ SMSG_GROUP_INVITE = 0x31B2,
+ SMSG_GROUP_LIST = 0x4C24,
+ SMSG_GROUP_SET_LEADER = 0x0526,
+ SMSG_GROUP_SET_ROLE = 0x39A6,
+ SMSG_GROUP_UNINVITE = 0x0A07,
+ SMSG_GUILD_ACHIEVEMENT_DATA = 0x54B7,
+ SMSG_GUILD_ACHIEVEMENT_DELETED = 0x35A0,
+ SMSG_GUILD_ACHIEVEMENT_EARNED = 0x50B5,
+ SMSG_GUILD_ACHIEVEMENT_MEMBERS = 0x38A5,
+ SMSG_GUILD_BANK_LIST = 0x78A5,
+ SMSG_GUILD_BANK_LOG_QUERY_RESULT = 0x30B2,
+ SMSG_GUILD_BANK_MONEY_WITHDRAWN = 0x5DB4,
+ SMSG_GUILD_BANK_QUERY_TEXT_RESULT = 0x75A3,
+ SMSG_GUILD_CANCEL = 0x0000,
+ SMSG_GUILD_CHALLENGE_COMPLETED = 0x39A3,
+ SMSG_GUILD_CHALLENGE_UPDATED = 0x18B1,
+ SMSG_GUILD_CHANGE_NAME_RESULT = 0x3CB1,
+ SMSG_GUILD_COMMAND_RESULT = 0x7DB3,
+ SMSG_GUILD_COMMAND_RESULT_2 = 0x2707,
+ SMSG_GUILD_CRITERIA_DATA = 0x14B4,
+ SMSG_GUILD_CRITERIA_DELETED = 0x55B1,
+ SMSG_GUILD_DECLINE = 0x2C07,
+ SMSG_GUILD_EVENT = 0x0705,
+ SMSG_GUILD_EVENT_LOG_QUERY_RESULT = 0x10B2,
+ SMSG_GUILD_FLAGGED_FOR_RENAME = 0x30B6,
+ SMSG_GUILD_INVITE = 0x14A2,
+ SMSG_GUILD_INVITE_CANCEL = 0x0606,
+ SMSG_GUILD_KNOWN_RECIPES = 0x0000,
+ SMSG_GUILD_MAX_DAILY_XP = 0x79B5,
+ SMSG_GUILD_MEMBERS_FOR_RECIPE = 0x1CB7,
+ SMSG_GUILD_MEMBER_DAILY_RESET = 0x10A5,
+ SMSG_GUILD_MEMBER_RECIPES = 0x1CB0,
+ SMSG_GUILD_MEMBER_UPDATE_NOTE = 0x7CA0,
+ SMSG_GUILD_MOVE_COMPLETE = 0x11B2,
+ SMSG_GUILD_MOVE_STARTING = 0x70A4,
+ SMSG_GUILD_NEWS_DELETED = 0x74A7,
+ SMSG_GUILD_NEWS_UPDATE = 0x35A7,
+ SMSG_GUILD_PARTY_STATE_RESPONSE = 0x50A6,
+ SMSG_GUILD_PERMISSIONS_QUERY_RESULTS = 0x34A3,
+ SMSG_GUILD_QUERY_RESPONSE = 0x0E06,
+ SMSG_GUILD_RANK = 0x30B4,
+ SMSG_GUILD_RANKS_UPDATE = 0x5DA0,
+ SMSG_GUILD_RECIPES = 0x10B3,
+ SMSG_GUILD_RENAMED = 0x74A6,
+ SMSG_GUILD_REPUTATION_REACTION_CHANGED = 0x74B0,
+ SMSG_GUILD_REPUTATION_WEEKLY_CAP = 0x30B7,
+ SMSG_GUILD_RESET = 0x1CB5,
+ SMSG_GUILD_REWARDS_LIST = 0x1DB0,
+ SMSG_GUILD_ROSTER = 0x3DA3,
+ SMSG_GUILD_SET_NOTE = 0x0000,
+ SMSG_GUILD_TRADESKILL_UPDATE = 0x0000,
+ SMSG_GUILD_UPDATE_ROSTER = 0x18B0,
+ SMSG_GUILD_XP = 0x3DB0,
+ SMSG_GUILD_XP_GAIN = 0x14A1,
+ SMSG_GUILD_XP_UPDATE = 0x0000,
+ SMSG_HEALTH_UPDATE = 0x4734,
+ SMSG_HIGHEST_THREAT_UPDATE = 0x4104,
+ SMSG_HOTFIX_INFO = 0x19B5,
+ SMSG_HOTFIX_NOTIFY = 0x55A7,
+ SMSG_INITIALIZE_FACTIONS = 0x4634,
+ SMSG_INITIAL_SPELLS = 0x0104,
+ SMSG_INIT_CURRENCY = 0x15A5,
+ SMSG_INIT_WORLD_STATES = 0x4C15,
+ SMSG_INSPECT = 0x0000,
+ SMSG_INSPECT_HONOR_STATS = 0x79A5,
+ SMSG_INSPECT_RATED_BG_STATS = 0x19A5,
+ SMSG_INSPECT_RESULTS_UPDATE = 0x0C14,
+ SMSG_INSPECT_TALENT = 0x4014,
+ SMSG_INSTANCE_LOCK_WARNING_QUERY = 0x4F17,
+ SMSG_INSTANCE_RESET = 0x6F05,
+ SMSG_INSTANCE_RESET_FAILED = 0x4725,
+ SMSG_INSTANCE_SAVE_CREATED = 0x0124,
+ SMSG_INVALIDATE_DANCE = 0x0E27,
+ SMSG_INVALIDATE_PLAYER = 0x6325,
+ SMSG_INVALID_PROMOTION_CODE = 0x6F25,
+ SMSG_INVENTORY_CHANGE_FAILURE = 0x2236,
+ SMSG_ITEM_ADD_PASSIVE = 0x7CB4,
+ SMSG_ITEM_COOLDOWN = 0x4D14,
+ SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x0F27,
+ SMSG_ITEM_EXPIRE_PURCHASE_REFUND = 0x1CA0,
+ SMSG_ITEM_PUSH_RESULT = 0x0E15,
+ SMSG_ITEM_REFUND_INFO_RESPONSE = 0x15A3,
+ SMSG_ITEM_REFUND_RESULT = 0x5DB1,
+ SMSG_ITEM_REMOVE_PASSIVE = 0x39A1,
+ SMSG_ITEM_SEND_PASSIVE = 0x70B1,
+ SMSG_ITEM_TEXT_QUERY_RESPONSE = 0x2725,
+ SMSG_ITEM_TIME_UPDATE = 0x2407,
+ SMSG_JOINED_BATTLEGROUND_QUEUE = 0x0000,
+ SMSG_KICK_REASON = 0x0000,
+ SMSG_LEARNED_DANCE_MOVES = 0x0E05,
+ SMSG_LEARNED_SPELL = 0x58A2,
+ SMSG_LEVELUP_INFO = 0x0435,
+ SMSG_LFG_BOOT_PROPOSAL_UPDATE = 0x0F05,
+ SMSG_LFG_DISABLED = 0x0815,
+ SMSG_LFG_JOIN_RESULT = 0x38B6,
+ SMSG_LFG_OFFER_CONTINUE = 0x6B27,
+ SMSG_LFG_OPEN_FROM_GOSSIP = 0x0000,
+ SMSG_LFG_PARTY_INFO = 0x2325,
+ SMSG_LFG_PLAYER_INFO = 0x4B36,
+ SMSG_LFG_PLAYER_REWARD = 0x6834,
+ SMSG_LFG_PROPOSAL_UPDATE = 0x7DA6,
+ SMSG_LFG_QUEUE_STATUS = 0x78B4,
+ SMSG_LFG_ROLE_CHECK_UPDATE = 0x0336,
+ SMSG_LFG_ROLE_CHOSEN = 0x6A26,
+ SMSG_LFG_SLOT_INVALID = 0x54B5,
+ SMSG_LFG_TELEPORT_DENIED = 0x0E14,
+ SMSG_LFG_UPDATE_LIST = 0x0000,
+ SMSG_LFG_UPDATE_SEARCH = 0x54A1,
+ SMSG_LFG_UPDATE_STATUS = 0x31A4,
+ SMSG_LFG_UPDATE_STATUS_NONE = 0x7CA1,
+ SMSG_LF_GUILD_APPLICANT_LIST_UPDATED = 0x10A4,
+ SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED = 0x71A5,
+ SMSG_LF_GUILD_BROWSE_UPDATED = 0x1DA3,
+ SMSG_LF_GUILD_COMMAND_RESULT = 0x54A6,
+ SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED = 0x1CA5,
+ SMSG_LF_GUILD_POST_UPDATED = 0x35B7,
+ SMSG_LF_GUILD_RECRUIT_LIST_UPDATED = 0x1CB2,
+ SMSG_LIST_INVENTORY = 0x7CB0,
+ SMSG_LOAD_CUF_PROFILES = 0x50B1,
+ SMSG_LOGIN_SETTIMESPEED = 0x4D15,
+ SMSG_LOGIN_VERIFY_WORLD = 0x2005,
+ SMSG_LOGOUT_CANCEL_ACK = 0x6514,
+ SMSG_LOGOUT_COMPLETE = 0x2137,
+ SMSG_LOGOUT_RESPONSE = 0x0524,
+ SMSG_LOG_XPGAIN = 0x4514,
+ SMSG_LOOT_ALL_PASSED = 0x6237,
+ SMSG_LOOT_CLEAR_MONEY = 0x2B37,
+ SMSG_LOOT_CONTENTS = 0x11B1,
+ SMSG_LOOT_ITEM_NOTIFY = 0x6D15,
+ SMSG_LOOT_LIST = 0x6807,
+ SMSG_LOOT_MASTER_LIST = 0x0325,
+ SMSG_LOOT_MONEY_NOTIFY = 0x2836,
+ SMSG_LOOT_RELEASE_RESPONSE = 0x6D25,
+ SMSG_LOOT_REMOVED = 0x6817,
+ SMSG_LOOT_RESPONSE = 0x4C16,
+ SMSG_LOOT_ROLL = 0x6507,
+ SMSG_LOOT_ROLL_WON = 0x6617,
+ SMSG_LOOT_SLOT_CHANGED = 0x2935,
+ SMSG_LOOT_START_ROLL = 0x2227,
+ SMSG_MAIL_LIST_RESULT = 0x4217,
+ SMSG_MAP_OBJ_EVENTS = 0x54B2,
+ SMSG_MEETINGSTONE_COMPLETE = 0x0000,
+ SMSG_MEETINGSTONE_IN_PROGRESS = 0x2D35,
+ SMSG_MEETINGSTONE_MEMBER_ADDED = 0x0000,
+ SMSG_MEETINGSTONE_SETQUEUE = 0x0000,
+ SMSG_MESSAGECHAT = 0x2026,
+ SMSG_MESSAGE_BOX = 0x30A1,
+ SMSG_MINIGAME_SETUP = 0x6727,
+ SMSG_MINIGAME_STATE = 0x2E17,
+ SMSG_MIRRORIMAGE_DATA = 0x2634,
+ SMSG_MISSILE_CANCEL = 0x3DB4,
+ SMSG_MODIFY_COOLDOWN = 0x6016,
+ SMSG_MONEY_NOTIFY = 0x55B6,
+ SMSG_MONSTER_MOVE = 0x6E17,
+ SMSG_MONSTER_MOVE_TRANSPORT = 0x2004,
+ SMSG_MOTD = 0x0A35,
+ SMSG_MOUNTRESULT = 0x2225,
+ SMSG_MOUNTSPECIAL_ANIM = 0x0217,
+ SMSG_MOVE_COLLISION_DISABLE = 0x31B0,
+ SMSG_MOVE_COLLISION_ENABLE = 0x11A7,
+ SMSG_MOVE_FEATHER_FALL = 0x79B0,
+ SMSG_MOVE_GRAVITY_DISABLE = 0x75B2,
+ SMSG_MOVE_GRAVITY_ENABLE = 0x30B3,
+ SMSG_MOVE_KNOCK_BACK = 0x5CB4,
+ SMSG_MOVE_LAND_WALK = 0x34B7,
+ SMSG_MOVE_NORMAL_FALL = 0x51B6,
+ SMSG_MOVE_ROOT = 0x7DA0,
+ SMSG_MOVE_SET_ACTIVE_MOVER = 0x11B3,
+ SMSG_MOVE_SET_CAN_FLY = 0x3DA1,
+ SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x59A2,
+ SMSG_MOVE_SET_COLLISION_HEIGHT = 0x11B0,
+ SMSG_MOVE_SET_COMPOUND_STATE = 0x75A0,
+ SMSG_MOVE_SET_FLIGHT_BACK_SPEED = 0x30A2,
+ SMSG_MOVE_SET_FLIGHT_SPEED = 0x71A6,
+ SMSG_MOVE_SET_HOVER = 0x5CB3,
+ SMSG_MOVE_SET_PITCH_RATE = 0x75B0,
+ SMSG_MOVE_SET_RUN_BACK_SPEED = 0x71B1,
+ SMSG_MOVE_SET_RUN_SPEED = 0x3DB5,
+ SMSG_MOVE_SET_SWIM_BACK_SPEED = 0x5CA6,
+ SMSG_MOVE_SET_SWIM_SPEED = 0x15A7,
+ SMSG_MOVE_SET_TURN_RATE = 0x30A5,
+ SMSG_MOVE_SET_VEHICLE_REC_ID = 0x0000,
+ SMSG_MOVE_SET_WALK_IN_AIR = 0x0000,
+ SMSG_MOVE_SET_WALK_SPEED = 0x1DA4,
+ SMSG_MOVE_UNROOT = 0x7DB4,
+ SMSG_MOVE_UNSET_CAN_FLY = 0x15A2,
+ SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x7DB2,
+ SMSG_MOVE_UNSET_HOVER = 0x51B3,
+ SMSG_MOVE_UNSET_WALK_IN_AIR = 0x0000,
+ SMSG_MOVE_UPDATE_COLLISION_HEIGHT = 0x59A3,
+ SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED = 0x74A0,
+ SMSG_MOVE_UPDATE_FLIGHT_SPEED = 0x30B1,
+ SMSG_MOVE_UPDATE_KNOCK_BACK = 0x3DB2,
+ SMSG_MOVE_UPDATE_PITCH_RATE = 0x1DB5,
+ SMSG_MOVE_UPDATE_RUN_BACK_SPEED = 0x3DA6,
+ SMSG_MOVE_UPDATE_RUN_SPEED = 0x14A6,
+ SMSG_MOVE_UPDATE_SWIM_BACK_SPEED = 0x30B5,
+ SMSG_MOVE_UPDATE_SWIM_SPEED = 0x59B5,
+ SMSG_MOVE_UPDATE_TELEPORT = 0x50B2,
+ SMSG_MOVE_UPDATE_TURN_RATE = 0x5DA1,
+ SMSG_MOVE_UPDATE_WALK_SPEED = 0x54A2,
+ SMSG_MOVE_WATER_WALK = 0x75B1,
+ SMSG_MULTIPLE_PACKETS = 0x6736,
+ SMSG_NAME_QUERY_RESPONSE = 0x6E04,
+ SMSG_NEW_TAXI_PATH = 0x4B35,
+ SMSG_NEW_WORLD = 0x79B1,
+ SMSG_NEW_WORLD_ABORT = 0x14B7,
+ SMSG_NOTIFICATION = 0x14A0,
+ SMSG_NOTIFY_DANCE = 0x4904,
+ SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x6204,
+ SMSG_NPC_TEXT_UPDATE = 0x4436,
+ SMSG_NPC_WONT_TALK = 0x0000,
+ SMSG_OFFER_PETITION_ERROR = 0x2716,
+ SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x4D34,
+ SMSG_OPEN_CONTAINER = 0x4714,
+ SMSG_OPEN_LFG_DUNGEON_FINDER = 0x2C37,
+ SMSG_OVERRIDE_LIGHT = 0x4225,
+ SMSG_PAGE_TEXT_QUERY_RESPONSE = 0x2B14,
+ SMSG_PARTYKILLLOG = 0x4937,
+ SMSG_PARTY_COMMAND_RESULT = 0x6E07,
+ SMSG_PARTY_MEMBER_STATS = 0x2104,
+ SMSG_PARTY_MEMBER_STATS_FULL = 0x0215,
+ SMSG_PAUSE_MIRROR_TIMER = 0x4015,
+ SMSG_PERIODICAURALOG = 0x0416,
+ SMSG_PETGODMODE = 0x2E36,
+ SMSG_PETITION_ALREADY_SIGNED = 0x5DA3,
+ SMSG_PETITION_QUERY_RESPONSE = 0x4B37,
+ SMSG_PETITION_SHOWLIST = 0x6405,
+ SMSG_PETITION_SHOW_SIGNATURES = 0x0716,
+ SMSG_PETITION_SIGN_RESULTS = 0x6217,
+ SMSG_PET_ACTION_FEEDBACK = 0x0807,
+ SMSG_PET_ACTION_SOUND = 0x4324,
+ SMSG_PET_ADDED = 0x3CA5,
+ SMSG_PET_BROKEN = 0x2E27,
+ SMSG_PET_CAST_FAILED = 0x2B15,
+ SMSG_PET_DISMISS_SOUND = 0x2B05,
+ SMSG_PET_GUIDS = 0x2D26,
+ SMSG_PET_LEARNED_SPELL = 0x0507,
+ SMSG_PET_MODE = 0x2235,
+ SMSG_PET_NAME_INVALID = 0x6007,
+ SMSG_PET_NAME_QUERY_RESPONSE = 0x4C37,
+ SMSG_PET_REMOVED_SPELL = 0x6A04,
+ SMSG_PET_RENAMEABLE = 0x2B27,
+ SMSG_PET_SLOT_UPDATED = 0x51A3,
+ SMSG_PET_SPELLS = 0x4114,
+ SMSG_PET_TAME_FAILURE = 0x6B24,
+ SMSG_PET_UPDATE_COMBO_POINTS = 0x4325,
+ SMSG_PLAYED_TIME = 0x6037,
+ SMSG_PLAYERBINDERROR = 0x6A24,
+ SMSG_PLAYERBOUND = 0x2516,
+ SMSG_PLAYER_DIFFICULTY_CHANGE = 0x2217,
+ SMSG_PLAYER_MOVE = 0x79A2,
+ SMSG_PLAYER_SKINNED = 0x0116,
+ SMSG_PLAYER_UNK_DEAD_ALIVE = 0x0000,
+ SMSG_PLAYER_VEHICLE_DATA = 0x4115,
+ SMSG_PLAY_DANCE = 0x4704,
+ SMSG_PLAY_MUSIC = 0x4B06,
+ SMSG_PLAY_OBJECT_SOUND = 0x2635,
+ SMSG_PLAY_ONE_SHOT_ANIM_KIT = 0x4A35,
+ SMSG_PLAY_SOUND = 0x2134,
+ SMSG_PLAY_SPELL_VISUAL = 0x10B1,
+ SMSG_PLAY_SPELL_VISUAL_KIT = 0x55A5,
+ SMSG_PLAY_TIME_WARNING = 0x4814,
+ SMSG_PONG = 0x4D42,
+ SMSG_POWER_UPDATE = 0x4A07,
+ SMSG_PRE_RESURRECT = 0x6C36,
+ SMSG_PROCRESIST = 0x0426,
+ SMSG_PROPOSE_LEVEL_GRANT = 0x6114,
+ SMSG_PUREMOUNT_CANCELLED_OBSOLETE = 0x0000,
+ SMSG_PVP_CREDIT = 0x6015,
+ SMSG_PVP_LOG_DATA = 0x5CB2,
+ SMSG_PVP_OPTIONS_ENABLED = 0x50A1,
+ SMSG_QUERY_QUESTS_COMPLETED_RESPONSE = 0x6314,
+ SMSG_QUERY_TIME_RESPONSE = 0x2124,
+ SMSG_QUESTGIVER_OFFER_REWARD = 0x2427,
+ SMSG_QUESTGIVER_QUEST_COMPLETE = 0x55A4,
+ SMSG_QUESTGIVER_QUEST_DETAILS = 0x2425,
+ SMSG_QUESTGIVER_QUEST_FAILED = 0x4236,
+ SMSG_QUESTGIVER_QUEST_INVALID = 0x4016,
+ SMSG_QUESTGIVER_QUEST_LIST = 0x0134,
+ SMSG_QUESTGIVER_REQUEST_ITEMS = 0x6236,
+ SMSG_QUESTGIVER_STATUS = 0x2115,
+ SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x4F25,
+ SMSG_QUESTLOG_FULL = 0x0E36,
+ SMSG_QUESTUPDATE_ADD_ITEM = 0x0000,
+ SMSG_QUESTUPDATE_ADD_KILL = 0x0D27,
+ SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x4416,
+ SMSG_QUESTUPDATE_COMPLETE = 0x2937,
+ SMSG_QUESTUPDATE_FAILED = 0x6324,
+ SMSG_QUESTUPDATE_FAILEDTIMER = 0x6427,
+ SMSG_QUEST_NPC_QUERY_RESPONSE = 0x75A1,
+ SMSG_QUEST_CONFIRM_ACCEPT = 0x6F07,
+ SMSG_QUEST_FORCE_REMOVE = 0x6605,
+ SMSG_QUEST_POI_QUERY_RESPONSE = 0x6304,
+ SMSG_QUEST_QUERY_RESPONSE = 0x6936,
+ SMSG_RAID_GROUP_ONLY = 0x0837,
+ SMSG_RAID_INSTANCE_INFO = 0x6626,
+ SMSG_RAID_INSTANCE_MESSAGE = 0x6E15,
+ SMSG_RAID_MARKERS_CHANGED = 0x10A1,
+ SMSG_RAID_READY_CHECK_THROTTLED_ERROR = 0x2607,
+ SMSG_RAID_SUMMON_FAILED = 0x18B6,
+ SMSG_RANDOMIZE_CHAR_NAME = 0x38B1,
+ SMSG_RATED_BG_RATING = 0x15A1,
+ SMSG_RATED_BG_STATS = 0x34A1,
+ SMSG_READ_ITEM_FAILED = 0x0F16,
+ SMSG_READ_ITEM_OK = 0x2605,
+ SMSG_REALM_SPLIT = 0x2714,
+ SMSG_REAL_GROUP_UPDATE = 0x0F34,
+ SMSG_RECEIVED_MAIL = 0x2924,
+ SMSG_REDIRECT_CLIENT = 0x0942,
+ SMSG_REFER_A_FRIEND_EXPIRED = 0x4934,
+ SMSG_REFER_A_FRIEND_FAILURE = 0x2037,
+ SMSG_REFORGE_RESULT = 0x58A4,
+ SMSG_REMOVED_SPELL = 0x4804,
+ SMSG_REPORT_PVP_AFK_RESULT = 0x2D06,
+ SMSG_REQUEST_CEMETERY_LIST_RESPONSE = 0x30A7,
+ SMSG_REQUEST_PVP_REWARDS_RESPONSE = 0x5DA4,
+ SMSG_RESEARCH_COMPLETE = 0x35A6,
+ SMSG_RESEARCH_SETUP_HISTORY = 0x10B6,
+ SMSG_RESET_COMPRESSION_CONTEXT = 0x0142,
+ SMSG_RESET_FAILED_NOTIFY = 0x4616,
+ SMSG_RESISTLOG = 0x0000,
+ SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x15B0,
+ SMSG_RESURRECT_REQUEST = 0x2905,
+ SMSG_RESYNC_RUNES = 0x6224,
+ SMSG_ROLE_POLL_BEGIN = 0x70B0,
+ SMSG_RWHOIS = 0x2437,
+ SMSG_SELL_ITEM = 0x6105,
+ SMSG_SEND_MAIL_RESULT = 0x4927,
+ SMSG_SEND_UNLEARN_SPELLS = 0x4E25,
+ SMSG_SERVERTIME = 0x6327,
+ SMSG_SERVER_FIRST_ACHIEVEMENT = 0x6424,
+ SMSG_SERVER_INFO_RESPONSE = 0x74B5,
+ SMSG_SERVER_MESSAGE = 0x6C04,
+ SMSG_SERVER_PERF = 0x74B6,
+ SMSG_SET_AI_ANIM_KIT = 0x0000,
+ SMSG_SET_DF_FAST_LAUNCH_RESULT = 0x35B6,
+ SMSG_SET_FACTION_ATWAR = 0x4216,
+ SMSG_SET_FACTION_STANDING = 0x0126,
+ SMSG_SET_FACTION_VISIBLE = 0x2525,
+ SMSG_SET_FLAT_SPELL_MODIFIER = 0x2834,
+ SMSG_SET_FORCED_REACTIONS = 0x4615,
+ SMSG_SET_MELEE_ANIM_KIT = 0x0000,
+ SMSG_SET_MOVEMENT_ANIM_KIT = 0x0000,
+ SMSG_SET_PCT_SPELL_MODIFIER = 0x0224,
+ SMSG_SET_PHASE_SHIFT = 0x70A0,
+ SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x2B25,
+ SMSG_SET_PLAY_HOVER_ANIM = 0x30A6,
+ SMSG_SET_PROFICIENCY = 0x6207,
+ SMSG_SET_PROJECTILE_POSITION = 0x2616,
+ SMSG_SHOWTAXINODES = 0x2A36,
+ SMSG_SHOW_BANK = 0x2627,
+ SMSG_SHOW_MAILBOX = 0x2524,
+ SMSG_SHOW_RATINGS = 0x11B4,
+ SMSG_SOCKET_GEMS_RESULT = 0x6014,
+ SMSG_SOR_START_EXPERIENCE_INCOMPLETE = 0x7CA7,
+ SMSG_SPELLBREAKLOG = 0x6B17,
+ SMSG_SPELLDAMAGESHIELD = 0x2927,
+ SMSG_SPELLDISPELLOG = 0x4516,
+ SMSG_SPELLENERGIZELOG = 0x0414,
+ SMSG_SPELLHEALLOG = 0x2816,
+ SMSG_SPELLINSTAKILLLOG = 0x6216,
+ SMSG_SPELLINTERRUPTLOG = 0x1DA7,
+ SMSG_SPELLLOGEXECUTE = 0x0626,
+ SMSG_SPELLLOGMISS = 0x0625,
+ SMSG_SPELLNONMELEEDAMAGELOG = 0x4315,
+ SMSG_SPELLORDAMAGE_IMMUNE = 0x4507,
+ SMSG_SPELLSTEALLOG = 0x4E26,
+ SMSG_SPELL_CATEGORY_COOLDOWN = 0x71B6,
+ SMSG_SPELL_COOLDOWN = 0x4B16,
+ SMSG_SPELL_DELAYED = 0x0715,
+ SMSG_SPELL_FAILED_OTHER = 0x0C34,
+ SMSG_SPELL_FAILURE = 0x4535,
+ SMSG_SPELL_GO = 0x6E16,
+ SMSG_SPELL_START = 0x6415,
+ SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x6006,
+ SMSG_SPIRIT_HEALER_CONFIRM = 0x4917,
+ SMSG_SPLINE_MOVE_COLLISION_DISABLE = 0x35B1,
+ SMSG_SPLINE_MOVE_COLLISION_ENABLE = 0x3CB0,
+ SMSG_SPLINE_MOVE_GRAVITY_DISABLE = 0x5DB5,
+ SMSG_SPLINE_MOVE_GRAVITY_ENABLE = 0x3CA6,
+ SMSG_SPLINE_MOVE_ROOT = 0x51B4,
+ SMSG_SPLINE_MOVE_SET_ANIM = 0x4335,
+ SMSG_SPLINE_MOVE_SET_FEATHER_FALL = 0x3DA5,
+ SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED = 0x38B3,
+ SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED = 0x39A0,
+ SMSG_SPLINE_MOVE_SET_FLYING = 0x31B5,
+ SMSG_SPLINE_MOVE_SET_HOVER = 0x14B6,
+ SMSG_SPLINE_MOVE_SET_LAND_WALK = 0x3DA7,
+ SMSG_SPLINE_MOVE_SET_NORMAL_FALL = 0x38B2,
+ SMSG_SPLINE_MOVE_SET_PITCH_RATE = 0x14B0,
+ SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED = 0x3DB3,
+ SMSG_SPLINE_MOVE_SET_RUN_MODE = 0x75A7,
+ SMSG_SPLINE_MOVE_SET_RUN_SPEED = 0x51B7,
+ SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED = 0x59A1,
+ SMSG_SPLINE_MOVE_SET_SWIM_SPEED = 0x39A4,
+ SMSG_SPLINE_MOVE_SET_TURN_RATE = 0x78B5,
+ SMSG_SPLINE_MOVE_SET_WALK_MODE = 0x54B6,
+ SMSG_SPLINE_MOVE_SET_WALK_SPEED = 0x34A5,
+ SMSG_SPLINE_MOVE_SET_WATER_WALK = 0x50A2,
+ SMSG_SPLINE_MOVE_START_SWIM = 0x31A5,
+ SMSG_SPLINE_MOVE_STOP_SWIM = 0x1DA2,
+ SMSG_SPLINE_MOVE_UNROOT = 0x75B6,
+ SMSG_SPLINE_MOVE_UNSET_FLYING = 0x58A6,
+ SMSG_SPLINE_MOVE_UNSET_HOVER = 0x7DA5,
+ SMSG_SPLINE_MOVE_WATER_WALK = 0x50A2,
+ SMSG_STABLE_RESULT = 0x2204,
+ SMSG_STANDSTATE_UPDATE = 0x6F04,
+ SMSG_START_MIRROR_TIMER = 0x6824,
+ SMSG_START_TIMER = 0x59A5,
+ SMSG_STOP_DANCE = 0x4637,
+ SMSG_STOP_MIRROR_TIMER = 0x0B06,
+ SMSG_STREAMING_MOVIE = 0x15B7,
+ SMSG_SUMMON_CANCEL = 0x0B34,
+ SMSG_SUMMON_REQUEST = 0x2A07,
+ SMSG_SUPERCEDED_SPELL = 0x35B0,
+ SMSG_SUPPRESS_NPC_GREETINGS = 0x74B1,
+ SMSG_SUSPEND_COMMS = 0x4140,
+ SMSG_SUSPEND_TOKEN_RESPONSE = 0x14B1,
+ SMSG_TALENTS_ERROR = 0x0916,
+ SMSG_TALENTS_INFO = 0x6F26,
+ SMSG_TALENTS_INVOLUNTARILY_RESET = 0x2C27,
+ SMSG_TAXINODE_STATUS = 0x2936,
+ SMSG_TEST_DROP_RATE_RESULT = 0x6816,
+ SMSG_TEXT_EMOTE = 0x0B05,
+ SMSG_THREAT_CLEAR = 0x6437,
+ SMSG_THREAT_REMOVE = 0x2E05,
+ SMSG_THREAT_UPDATE = 0x4735,
+ SMSG_TIME_ADJUSTMENT = 0x79B7,
+ SMSG_TIME_SYNC_REQ = 0x3CA4,
+ SMSG_TITLE_EARNED = 0x2426,
+ SMSG_TOGGLE_XP_GAIN = 0x6704,
+ SMSG_TOTEM_CREATED = 0x2414,
+ SMSG_TRADE_STATUS = 0x5CA3,
+ SMSG_TRADE_STATUS_EXTENDED = 0x70A2,
+ SMSG_TRAINER_BUY_FAILED = 0x0004,
+ SMSG_TRAINER_BUY_SUCCEEDED = 0x6A05,
+ SMSG_TRAINER_LIST = 0x4414,
+ SMSG_TRANSFER_ABORTED = 0x0537,
+ SMSG_TRANSFER_PENDING = 0x18A6,
+ SMSG_TRIGGER_CINEMATIC = 0x6C27,
+ SMSG_TRIGGER_MOVIE = 0x4625,
+ SMSG_TURN_IN_PETITION_RESULTS = 0x0F07,
+ SMSG_TUTORIAL_FLAGS = 0x0B35,
+ SMSG_UNIT_HEALTH_FREQUENT = 0x2C26,
+ SMSG_UNIT_SPELLCAST_START = 0x2517,
+ SMSG_UPDATE_ACCOUNT_DATA = 0x6837,
+ SMSG_UPDATE_ACCOUNT_DATA_COMPLETE = 0x2015,
+ SMSG_UPDATE_COMBO_POINTS = 0x6B34,
+ SMSG_UPDATE_CURRENCY = 0x59B0,
+ SMSG_UPDATE_CURRENCY_WEEK_LIMIT = 0x70A7,
+ SMSG_UPDATE_DUNGEON_ENCOUNTER_FOR_LOOT = 0x3CB5,
+ SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT = 0x4007,
+ SMSG_UPDATE_INSTANCE_OWNERSHIP = 0x4915,
+ SMSG_UPDATE_LAST_INSTANCE = 0x0437,
+ SMSG_UPDATE_OBJECT = 0x4715,
+ SMSG_UPDATE_SERVER_PLAYER_POSITION = 0x74A3,
+ SMSG_UPDATE_WORLD_STATE = 0x4816,
+ SMSG_USERLIST_ADD = 0x0F37,
+ SMSG_USERLIST_REMOVE = 0x2006,
+ SMSG_USERLIST_UPDATE = 0x0135,
+ SMSG_VOICESESSION_FULL = 0x6225,
+ SMSG_VOICE_CHAT_STATUS = 0x0F15,
+ SMSG_VOICE_PARENTAL_CONTROLS = 0x0534,
+ SMSG_VOICE_SESSION_LEAVE = 0x2A24,
+ SMSG_VOICE_SESSION_ROSTER_UPDATE = 0x2A17,
+ SMSG_VOICE_SET_TALKER_MUTED = 0x6E35,
+ SMSG_VOID_ITEM_SWAP_RESPONSE = 0x78A2,
+ SMSG_VOID_STORAGE_CONTENTS = 0x75B4,
+ SMSG_VOID_STORAGE_FAILED = 0x18A7,
+ SMSG_VOID_STORAGE_TRANSFER_CHANGES = 0x51A6,
+ SMSG_VOID_TRANSFER_RESULT = 0x1DA6,
+ SMSG_WAIT_QUEUE_FINISH = 0x75B7,
+ SMSG_WAIT_QUEUE_UPDATE = 0x58A1,
+ SMSG_WARDEN_DATA = 0x31A0,
+ SMSG_WARGAME_CHECK_ENTRY = 0x3DA4,
+ SMSG_WARGAME_REQUEST_SENT = 0x59B2,
+ SMSG_WEATHER = 0x2904,
+ SMSG_WEEKLY_LAST_RESET = 0x50A5,
+ SMSG_WEEKLY_RESET_CURRENCY = 0x3CA1,
+ SMSG_WEEKLY_SPELL_USAGE = 0x39B7,
+ SMSG_WEEKLY_SPELL_USAGE_UPDATE = 0x11B5,
+ SMSG_WHO = 0x6907,
+ SMSG_WHOIS = 0x6917,
+ SMSG_WORLD_SERVER_INFO = 0x31A2,
+ SMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4A14,
+ SMSG_XP_GAIN_ABORTED = 0x50B4,
+ SMSG_ZONE_UNDER_ATTACK = 0x0A06,
};
/// Player state
@@ -1362,6 +1397,9 @@ enum PacketProcessing
class WorldSession;
class WorldPacket;
+class WorldSession;
+
+typedef void(WorldSession::*pOpcodeHandler)(WorldPacket& recvPacket);
#if defined(__GNUC__)
#pragma pack(1)
@@ -1371,13 +1409,49 @@ class WorldPacket;
struct OpcodeHandler
{
- char const* name;
- SessionStatus status;
- PacketProcessing packetProcessing;
- void (WorldSession::*handler)(WorldPacket& recvPacket);
+ OpcodeHandler() {}
+ OpcodeHandler(char const* _name, SessionStatus _status, PacketProcessing _processing, pOpcodeHandler _handler)
+ : Handler(_handler), Name(_name), Status(_status), ProcessingPlace(_processing) {}
+
+ pOpcodeHandler Handler;
+ char const* Name;
+ SessionStatus Status;
+ PacketProcessing ProcessingPlace;
};
-extern OpcodeHandler opcodeTable[NUM_MSG_TYPES];
+class OpcodeTable
+{
+ public:
+ OpcodeTable()
+ {
+ memset(_internalTable, 0, sizeof(_internalTable));
+ }
+
+ ~OpcodeTable()
+ {
+ for (uint16 i = 0; i < NUM_OPCODE_HANDLERS; ++i)
+ delete _internalTable[i];
+ }
+
+ void Initialize();
+
+ OpcodeHandler const* operator[](uint32 index) const
+ {
+ return _internalTable[index];
+ }
+
+ private:
+ template<bool isInValidRange, bool isNonZero>
+ void ValidateAndSetOpcode(uint16 opcode, char const* name, SessionStatus status, PacketProcessing processing, pOpcodeHandler handler);
+
+ // Prevent copying this structure
+ OpcodeTable(OpcodeTable const&);
+ OpcodeTable& operator=(OpcodeTable const&);
+
+ OpcodeHandler* _internalTable[NUM_OPCODE_HANDLERS];
+};
+
+extern OpcodeTable opcodeTable;
#if defined(__GNUC__)
#pragma pack()
@@ -1385,18 +1459,30 @@ extern OpcodeHandler opcodeTable[NUM_MSG_TYPES];
#pragma pack(pop)
#endif
-/// Lookup opcode name for human understandable logging
-inline const char* LookupOpcodeName(uint16 id)
-{
- if (id >= NUM_MSG_TYPES)
- return "Received unknown opcode, it's more than max!";
- return opcodeTable[id].name;
-}
+void InitOpcodes();
-inline std::string GetOpcodeNameForLogging(uint16 opcode)
+/// Lookup opcode name for human understandable logging
+inline std::string GetOpcodeNameForLogging(Opcodes id)
{
+ uint32 opcode = uint32(id);
std::ostringstream ss;
- ss << '[' << LookupOpcodeName(opcode) << " 0x" << std::hex << std::uppercase << opcode << std::nouppercase << " (" << std::dec << opcode << ")]";
+ ss << '[';
+
+ if (id < UNKNOWN_OPCODE)
+ {
+ if (OpcodeHandler const* handler = opcodeTable[uint32(id) & 0x7FFF])
+ {
+ ss << handler->Name;
+ if (opcode & COMPRESSED_OPCODE_MASK)
+ ss << "_COMPRESSED";
+ }
+ else
+ ss << "UNKNOWN OPCODE";
+ }
+ else
+ ss << "INVALID OPCODE";
+
+ ss << " 0x" << std::hex << std::uppercase << opcode << std::nouppercase << " (" << std::dec << opcode << ")]";
return ss.str();
}
diff --git a/src/server/game/Server/Protocol/PacketLog.cpp b/src/server/game/Server/Protocol/PacketLog.cpp
index 23dfb3538bc..a905b01c73c 100644
--- a/src/server/game/Server/Protocol/PacketLog.cpp
+++ b/src/server/game/Server/Protocol/PacketLog.cpp
@@ -78,7 +78,7 @@ void PacketLog::Initialize()
header.Signature[0] = 'P'; header.Signature[1] = 'K'; header.Signature[2] = 'T';
header.FormatVersion = 0x0301;
header.SnifferId = 'T';
- header.Build = 12340;
+ header.Build = 15595;
header.Locale[0] = 'e'; header.Locale[1] = 'n'; header.Locale[2] = 'U'; header.Locale[3] = 'S';
std::memset(header.SessionKey, 0, sizeof(header.SessionKey));
header.SniffStartUnixtime = time(NULL);
diff --git a/src/server/game/Server/WorldPacket.cpp b/src/server/game/Server/WorldPacket.cpp
new file mode 100644
index 00000000000..0658973f320
--- /dev/null
+++ b/src/server/game/Server/WorldPacket.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <zlib.h>
+#include "WorldPacket.h"
+#include "World.h"
+
+//! Compresses packet in place
+void WorldPacket::Compress(z_stream* compressionStream)
+{
+ Opcodes uncompressedOpcode = GetOpcode();
+ if (uncompressedOpcode & COMPRESSED_OPCODE_MASK)
+ {
+ TC_LOG_ERROR("network", "Packet with opcode 0x%04X is already compressed!", uncompressedOpcode);
+ return;
+ }
+
+ Opcodes opcode = Opcodes(uncompressedOpcode | COMPRESSED_OPCODE_MASK);
+ uint32 size = wpos();
+ uint32 destsize = compressBound(size);
+
+ std::vector<uint8> storage(destsize);
+
+ _compressionStream = compressionStream;
+ Compress(static_cast<void*>(&storage[0]), &destsize, static_cast<const void*>(contents()), size);
+ if (destsize == 0)
+ return;
+
+ clear();
+ reserve(destsize + sizeof(uint32));
+ *this << uint32(size);
+ append(&storage[0], destsize);
+ SetOpcode(opcode);
+ TC_LOG_INFO("network", "%s (len %u) successfully compressed to %04X (len %u)", GetOpcodeNameForLogging(uncompressedOpcode).c_str(), size, opcode, destsize);
+}
+
+//! Compresses another packet and stores it in self (source left intact)
+void WorldPacket::Compress(z_stream* compressionStream, WorldPacket const* source)
+{
+ ASSERT(source != this);
+
+ Opcodes uncompressedOpcode = source->GetOpcode();
+ if (uncompressedOpcode & COMPRESSED_OPCODE_MASK)
+ {
+ TC_LOG_ERROR("network", "Packet with opcode 0x%04X is already compressed!", uncompressedOpcode);
+ return;
+ }
+
+ Opcodes opcode = Opcodes(uncompressedOpcode | COMPRESSED_OPCODE_MASK);
+ uint32 size = source->size();
+ uint32 destsize = compressBound(size);
+
+ size_t sizePos = 0;
+ resize(destsize + sizeof(uint32));
+
+ _compressionStream = compressionStream;
+ Compress(static_cast<void*>(&_storage[0] + sizeof(uint32)), &destsize, static_cast<const void*>(source->contents()), size);
+ if (destsize == 0)
+ return;
+
+ put<uint32>(sizePos, size);
+ resize(destsize + sizeof(uint32));
+
+ SetOpcode(opcode);
+
+ TC_LOG_INFO("network", "%s (len %u) successfully compressed to %04X (len %u)", GetOpcodeNameForLogging(uncompressedOpcode).c_str(), size, opcode, destsize);
+}
+
+void WorldPacket::Compress(void* dst, uint32 *dst_size, const void* src, int src_size)
+{
+ _compressionStream->next_out = (Bytef*)dst;
+ _compressionStream->avail_out = *dst_size;
+ _compressionStream->next_in = (Bytef*)src;
+ _compressionStream->avail_in = (uInt)src_size;
+
+ int32 z_res = deflate(_compressionStream, Z_SYNC_FLUSH);
+ if (z_res != Z_OK)
+ {
+ TC_LOG_ERROR("network", "Can't compress packet (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg);
+ *dst_size = 0;
+ return;
+ }
+
+ if (_compressionStream->avail_in != 0)
+ {
+ TC_LOG_ERROR("network", "Can't compress packet (zlib: deflate not greedy)");
+ *dst_size = 0;
+ return;
+ }
+
+ *dst_size -= _compressionStream->avail_out;
+}
diff --git a/src/server/game/Server/WorldPacket.h b/src/server/game/Server/WorldPacket.h
new file mode 100644
index 00000000000..3e812621b48
--- /dev/null
+++ b/src/server/game/Server/WorldPacket.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITYCORE_WORLDPACKET_H
+#define TRINITYCORE_WORLDPACKET_H
+
+#include "Common.h"
+#include "Opcodes.h"
+#include "ByteBuffer.h"
+
+struct z_stream_s;
+
+class WorldPacket : public ByteBuffer
+{
+ public:
+ // just container for later use
+ WorldPacket() : ByteBuffer(0), m_opcode(UNKNOWN_OPCODE)
+ {
+ }
+
+ explicit WorldPacket(Opcodes opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { }
+
+ WorldPacket(WorldPacket&& packet) : ByteBuffer(std::move(packet)), m_opcode(packet.m_opcode)
+ {
+ }
+
+ WorldPacket(WorldPacket const& right) : ByteBuffer(right), m_opcode(right.m_opcode)
+ {
+ }
+
+ WorldPacket& operator=(WorldPacket const& right)
+ {
+ if (this != &right)
+ {
+ m_opcode = right.m_opcode;
+ ByteBuffer::operator =(right);
+ }
+
+ return *this;
+ }
+
+ void Initialize(Opcodes opcode, size_t newres=200)
+ {
+ clear();
+ _storage.reserve(newres);
+ m_opcode = opcode;
+ }
+
+ Opcodes GetOpcode() const { return m_opcode; }
+ void SetOpcode(Opcodes opcode) { m_opcode = opcode; }
+ void Compress(z_stream_s* compressionStream);
+ void Compress(z_stream_s* compressionStream, WorldPacket const* source);
+
+ protected:
+ Opcodes m_opcode;
+ void Compress(void* dst, uint32 *dst_size, const void* src, int src_size);
+ z_stream_s* _compressionStream;
+};
+
+#endif
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 279e69a4267..227555c1dfa 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -21,6 +21,7 @@
*/
#include "WorldSocket.h"
+#include <zlib.h>
#include "Config.h"
#include "Common.h"
#include "DatabaseEnv.h"
@@ -46,7 +47,6 @@
#include "Transport.h"
#include "WardenWin.h"
#include "WardenMac.h"
-#include "MoveSpline.h"
namespace {
@@ -56,14 +56,15 @@ std::string const DefaultPlayerName = "<none>";
bool MapSessionFilter::Process(WorldPacket* packet)
{
- OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];
+ Opcodes opcode = DropHighBytes(packet->GetOpcode());
+ OpcodeHandler const* opHandle = opcodeTable[opcode];
//let's check if our opcode can be really processed in Map::Update()
- if (opHandle.packetProcessing == PROCESS_INPLACE)
+ if (opHandle->ProcessingPlace == PROCESS_INPLACE)
return true;
//we do not process thread-unsafe packets
- if (opHandle.packetProcessing == PROCESS_THREADUNSAFE)
+ if (opHandle->ProcessingPlace == PROCESS_THREADUNSAFE)
return false;
Player* player = m_pSession->GetPlayer();
@@ -78,13 +79,14 @@ bool MapSessionFilter::Process(WorldPacket* packet)
//OR packet handler is not thread-safe!
bool WorldSessionFilter::Process(WorldPacket* packet)
{
- OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];
+ Opcodes opcode = DropHighBytes(packet->GetOpcode());
+ OpcodeHandler const* opHandle = opcodeTable[opcode];
//check if packet handler is supposed to be safe
- if (opHandle.packetProcessing == PROCESS_INPLACE)
+ if (opHandle->ProcessingPlace == PROCESS_INPLACE)
return true;
//thread-unsafe packets should be processed in World::UpdateSessions()
- if (opHandle.packetProcessing == PROCESS_THREADUNSAFE)
+ if (opHandle->ProcessingPlace == PROCESS_THREADUNSAFE)
return true;
//no player attached? -> our client! ^^
@@ -97,7 +99,7 @@ bool WorldSessionFilter::Process(WorldPacket* packet)
}
/// WorldSession constructor
-WorldSession::WorldSession(uint32 id, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter):
+WorldSession::WorldSession(uint32 id, uint32 battlenetAccountId, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter):
m_muteTime(mute_time),
m_timeOutTime(0),
AntiDOS(this),
@@ -106,6 +108,7 @@ WorldSession::WorldSession(uint32 id, std::shared_ptr<WorldSocket> sock, Account
m_Socket(sock),
_security(sec),
_accountId(id),
+ _battlenetAccountId(battlenetAccountId),
m_expansion(expansion),
_warden(NULL),
_logoutTime(0),
@@ -119,6 +122,7 @@ WorldSession::WorldSession(uint32 id, std::shared_ptr<WorldSocket> sock, Account
m_latency(0),
m_clientTimeDelay(0),
m_TutorialsChanged(false),
+ _filterAddonMessages(false),
recruiterId(recruiter),
isRecruiter(isARecruiter),
_RBACData(NULL),
@@ -136,6 +140,16 @@ WorldSession::WorldSession(uint32 id, std::shared_ptr<WorldSocket> sock, Account
}
InitializeQueryCallbackParameters();
+
+ _compressionStream = new z_stream();
+ _compressionStream->zalloc = (alloc_func)NULL;
+ _compressionStream->zfree = (free_func)NULL;
+ _compressionStream->opaque = (voidpf)NULL;
+ _compressionStream->avail_in = 0;
+ _compressionStream->next_in = NULL;
+ int32 z_res = deflateInit(_compressionStream, sWorld->getIntConfig(CONFIG_COMPRESSION));
+ if (z_res != Z_OK)
+ TC_LOG_ERROR("network", "Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res));
}
/// WorldSession destructor
@@ -161,6 +175,12 @@ WorldSession::~WorldSession()
delete packet;
LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); // One-time query
+
+ int32 z_res = deflateEnd(_compressionStream);
+ if (z_res != Z_OK && z_res != Z_DATA_ERROR) // Z_DATA_ERROR signals that internal state was BUSY
+ TC_LOG_ERROR("network", "Can't close packet compression stream (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res));
+
+ delete _compressionStream;
}
std::string const & WorldSession::GetPlayerName() const
@@ -186,11 +206,32 @@ uint32 WorldSession::GetGuidLow() const
}
/// Send a packet to the client
-void WorldSession::SendPacket(WorldPacket* packet)
+void WorldSession::SendPacket(WorldPacket* packet, bool forced /*= false*/)
{
if (!m_Socket)
return;
+ if (packet->GetOpcode() == NULL_OPCODE)
+ {
+ TC_LOG_ERROR("network.opcode", "Prevented sending of NULL_OPCODE to %s", GetPlayerInfo().c_str());
+ return;
+ }
+ else if (packet->GetOpcode() == UNKNOWN_OPCODE)
+ {
+ TC_LOG_ERROR("network.opcode", "Prevented sending of UNKNOWN_OPCODE to %s", GetPlayerInfo().c_str());
+ return;
+ }
+
+ if (!forced)
+ {
+ OpcodeHandler const* handler = opcodeTable[packet->GetOpcode()];
+ if (!handler || handler->Status == STATUS_UNHANDLED)
+ {
+ TC_LOG_ERROR("network.opcode", "Prevented sending disabled opcode %s to %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str(), GetPlayerInfo().c_str());
+ return;
+ }
+ }
+
#ifdef TRINITY_DEBUG
// Code for network use statistic
static uint64 sendPacketCount = 0;
@@ -281,107 +322,97 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
while (m_Socket && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater))
{
if (!AntiDOS.EvaluateOpcode(*packet, currentTime))
- {
KickPlayer();
- }
- else if (packet->GetOpcode() >= NUM_MSG_TYPES)
- {
- TC_LOG_ERROR("network.opcode", "Received non-existed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
- , GetPlayerInfo().c_str());
- sScriptMgr->OnUnknownPacketReceive(m_Socket, *packet);
- }
- else
+
+ OpcodeHandler const* opHandle = opcodeTable[packet->GetOpcode()];
+ try
{
- OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()];
- try
+ switch (opHandle->Status)
{
- switch (opHandle.status)
- {
- case STATUS_LOGGEDIN:
- if (!_player)
+ case STATUS_LOGGEDIN:
+ if (!_player)
+ {
+ // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
+ //! If player didn't log out a while ago, it means packets are being sent while the server does not recognize
+ //! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later.
+ if (!m_playerRecentlyLogout)
{
- // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
- //! If player didn't log out a while ago, it means packets are being sent while the server does not recognize
- //! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later.
- if (!m_playerRecentlyLogout)
- {
- //! Prevent infinite loop
- if (!firstDelayedPacket)
- firstDelayedPacket = packet;
- //! Because checking a bool is faster than reallocating memory
- deletePacket = false;
- QueuePacket(packet);
- //! Log
+ //! Prevent infinite loop
+ if (!firstDelayedPacket)
+ firstDelayedPacket = packet;
+ //! Because checking a bool is faster than reallocating memory
+ deletePacket = false;
+ QueuePacket(packet);
+ //! Log
TC_LOG_DEBUG("network", "Re-enqueueing packet with opcode %s with with status STATUS_LOGGEDIN. "
"Player is currently not in world yet.", GetOpcodeNameForLogging(packet->GetOpcode()).c_str());
- }
- }
- else if (_player->IsInWorld())
- {
- sScriptMgr->OnPacketReceive(m_Socket, *packet);
- (this->*opHandle.handler)(*packet);
- LogUnprocessedTail(packet);
}
- // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
- break;
- case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT:
- if (!_player && !m_playerRecentlyLogout && !m_playerLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout
- LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT",
- "the player has not logged in yet and not recently logout");
- else
- {
- // not expected _player or must checked in packet handler
- sScriptMgr->OnPacketReceive(m_Socket, *packet);
- (this->*opHandle.handler)(*packet);
- LogUnprocessedTail(packet);
- }
- break;
- case STATUS_TRANSFER:
- if (!_player)
- LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player has not logged in yet");
- else if (_player->IsInWorld())
- LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world");
- else
- {
- sScriptMgr->OnPacketReceive(m_Socket, *packet);
- (this->*opHandle.handler)(*packet);
- LogUnprocessedTail(packet);
- }
- break;
- case STATUS_AUTHED:
- // prevent cheating with skip queue wait
- if (m_inQueue)
- {
- LogUnexpectedOpcode(packet, "STATUS_AUTHED", "the player not pass queue yet");
- break;
- }
-
- // some auth opcodes can be recieved before STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes
- // however when we recieve CMSG_CHAR_ENUM we are surely no longer during the logout process.
- if (packet->GetOpcode() == CMSG_CHAR_ENUM)
- m_playerRecentlyLogout = false;
-
+ }
+ else if (_player->IsInWorld())
+ {
+ sScriptMgr->OnPacketReceive(m_Socket, *packet);
+ (this->*opHandle->Handler)(*packet);
+ LogUnprocessedTail(packet);
+ }
+ // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
+ break;
+ case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT:
+ if (!_player && !m_playerRecentlyLogout && !m_playerLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout
+ LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT",
+ "the player has not logged in yet and not recently logout");
+ else
+ {
+ // not expected _player or must checked in packet hanlder
+ sScriptMgr->OnPacketReceive(m_Socket, *packet);
+ (this->*opHandle->Handler)(*packet);
+ LogUnprocessedTail(packet);
+ }
+ break;
+ case STATUS_TRANSFER:
+ if (!_player)
+ LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player has not logged in yet");
+ else if (_player->IsInWorld())
+ LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world");
+ else
+ {
sScriptMgr->OnPacketReceive(m_Socket, *packet);
- (this->*opHandle.handler)(*packet);
+ (this->*opHandle->Handler)(*packet);
LogUnprocessedTail(packet);
+ }
+ break;
+ case STATUS_AUTHED:
+ // prevent cheating with skip queue wait
+ if (m_inQueue)
+ {
+ LogUnexpectedOpcode(packet, "STATUS_AUTHED", "the player not pass queue yet");
break;
- case STATUS_NEVER:
+ }
+
+ // some auth opcodes can be recieved before STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes
+ // however when we recieve CMSG_CHAR_ENUM we are surely no longer during the logout process.
+ if (packet->GetOpcode() == CMSG_CHAR_ENUM)
+ m_playerRecentlyLogout = false;
+
+ sScriptMgr->OnPacketReceive(m_Socket, *packet);
+ (this->*opHandle->Handler)(*packet);
+ LogUnprocessedTail(packet);
+ break;
+ case STATUS_NEVER:
TC_LOG_ERROR("network.opcode", "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
, GetPlayerInfo().c_str());
- break;
- case STATUS_UNHANDLED:
- TC_LOG_DEBUG("network.opcode", "Received not handled opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
+ break;
+ case STATUS_UNHANDLED:
+ TC_LOG_ERROR("network.opcode", "Received not handled opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
, GetPlayerInfo().c_str());
- break;
- }
- }
- catch (ByteBufferException const&)
- {
- TC_LOG_ERROR("misc", "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
- packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId());
- packet->hexlike();
+ break;
}
}
+ catch (ByteBufferException const&)
+ {
+ TC_LOG_ERROR("network", "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
+ packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId());
+ packet->hexlike();
+ }
if (deletePacket)
delete packet;
@@ -593,8 +624,11 @@ void WorldSession::SendNotification(const char *format, ...)
vsnprintf(szStr, 1024, format, ap);
va_end(ap);
- WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr) + 1));
- data << szStr;
+ size_t len = strlen(szStr);
+ WorldPacket data(SMSG_NOTIFICATION, 2 + len);
+ data.WriteBits(len, 13);
+ data.FlushBits();
+ data.append(szStr, len);
SendPacket(&data);
}
}
@@ -611,8 +645,11 @@ void WorldSession::SendNotification(uint32 string_id, ...)
vsnprintf(szStr, 1024, format, ap);
va_end(ap);
- WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr) + 1));
- data << szStr;
+ size_t len = strlen(szStr);
+ WorldPacket data(SMSG_NOTIFICATION, 2 + len);
+ data.WriteBits(len, 13);
+ data.FlushBits();
+ data.append(szStr, len);
SendPacket(&data);
}
}
@@ -651,15 +688,21 @@ void WorldSession::SendAuthWaitQue(uint32 position)
if (position == 0)
{
WorldPacket packet(SMSG_AUTH_RESPONSE, 1);
+ packet.WriteBit(0); // has queue info
+ packet.WriteBit(0); // has account info
+ packet.FlushBits();
packet << uint8(AUTH_OK);
SendPacket(&packet);
}
else
{
WorldPacket packet(SMSG_AUTH_RESPONSE, 6);
+ packet.WriteBit(1); // has queue info
+ packet.WriteBit(0); // unk queue bool
+ packet.WriteBit(0); // has account info
+ packet.FlushBits();
packet << uint8(AUTH_WAIT_QUEUE);
packet << uint32(position);
- packet << uint8(0); // unk
SendPacket(&packet);
}
}
@@ -785,159 +828,6 @@ void WorldSession::SaveTutorialsData(SQLTransaction &trans)
m_TutorialsChanged = false;
}
-void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi)
-{
- data >> mi->flags;
- data >> mi->flags2;
- data >> mi->time;
- data >> mi->pos.PositionXYZOStream();
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
- {
- data.readPackGUID(mi->transport.guid);
-
- data >> mi->transport.pos.PositionXYZOStream();
- data >> mi->transport.time;
- data >> mi->transport.seat;
-
- if (mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT))
- data >> mi->transport.time2;
- }
-
- if (mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (mi->HasExtraMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)))
- data >> mi->pitch;
-
- data >> mi->fallTime;
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_FALLING))
- {
- data >> mi->jump.zspeed;
- data >> mi->jump.sinAngle;
- data >> mi->jump.cosAngle;
- data >> mi->jump.xyspeed;
- }
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION))
- data >> mi->splineElevation;
-
- //! Anti-cheat checks. Please keep them in seperate if () blocks to maintain a clear overview.
- //! Might be subject to latency, so just remove improper flags.
- #ifdef TRINITY_DEBUG
- #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
- { \
- if (check) \
- { \
- TC_LOG_DEBUG("entities.unit", "WorldSession::ReadMovementInfo: Violation of MovementFlags found (%s). " \
- "MovementFlags: %u, MovementFlags2: %u for player GUID: %u. Mask %u will be removed.", \
- STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetPlayer()->GetGUIDLow(), maskToRemove); \
- mi->RemoveMovementFlag((maskToRemove)); \
- } \
- }
- #else
- #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
- if (check) \
- mi->RemoveMovementFlag((maskToRemove));
- #endif
-
-
- /*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid
- in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD.
- It will freeze clients that receive this player's movement info.
- */
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT),
- MOVEMENTFLAG_ROOT);
-
- //! Cannot hover without SPELL_AURA_HOVER
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !GetPlayer()->HasAuraType(SPELL_AURA_HOVER),
- MOVEMENTFLAG_HOVER);
-
- //! Cannot ascend and descend at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING),
- MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING);
-
- //! Cannot move left and right at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT),
- MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
-
- //! Cannot strafe left and right at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT),
- MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT);
-
- //! Cannot pitch up and down at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN),
- MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN);
-
- //! Cannot move forwards and backwards at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD),
- MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
-
- //! Cannot walk on water without SPELL_AURA_WATER_WALK
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK),
- MOVEMENTFLAG_WATERWALKING);
-
- //! Cannot feather fall without SPELL_AURA_FEATHER_FALL
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !GetPlayer()->HasAuraType(SPELL_AURA_FEATHER_FALL),
- MOVEMENTFLAG_FALLING_SLOW);
-
- /*! Cannot fly if no fly auras present. Exception is being a GM.
- Note that we check for account level instead of Player::IsGameMaster() because in some
- situations it may be feasable to use .gm fly on as a GM without having .gm on,
- e.g. aerial combat.
- */
-
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && GetSecurity() == SEC_PLAYER &&
- !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) &&
- !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED),
- MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY);
-
- //! Cannot fly and fall at the same time
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY) && mi->HasMovementFlag(MOVEMENTFLAG_FALLING),
- MOVEMENTFLAG_FALLING);
-
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ENABLED) &&
- (!GetPlayer()->movespline->Initialized() || GetPlayer()->movespline->Finalized()), MOVEMENTFLAG_SPLINE_ENABLED);
-
- #undef REMOVE_VIOLATING_FLAGS
-}
-
-void WorldSession::WriteMovementInfo(WorldPacket* data, MovementInfo* mi)
-{
- data->appendPackGUID(mi->guid);
-
- *data << mi->flags;
- *data << mi->flags2;
- *data << mi->time;
- *data << mi->pos.PositionXYZOStream();
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
- {
- data->appendPackGUID(mi->transport.guid);
-
- *data << mi->transport.pos.PositionXYZOStream();
- *data << mi->transport.time;
- *data << mi->transport.seat;
-
- if (mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT))
- *data << mi->transport.time2;
- }
-
- if (mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || mi->HasExtraMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING))
- *data << mi->pitch;
-
- *data << mi->fallTime;
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_FALLING))
- {
- *data << mi->jump.zspeed;
- *data << mi->jump.sinAngle;
- *data << mi->jump.cosAngle;
- *data << mi->jump.xyspeed;
- }
-
- if (mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION))
- *data << mi->splineElevation;
-}
-
void WorldSession::ReadAddonsInfo(WorldPacket &data)
{
if (data.rpos() + 4 > data.size())
@@ -1078,6 +968,57 @@ void WorldSession::SendAddonsInfo()
SendPacket(&data);
}
+bool WorldSession::IsAddonRegistered(const std::string& prefix) const
+{
+ if (!_filterAddonMessages) // if we have hit the softcap (64) nothing should be filtered
+ return true;
+
+ if (_registeredAddonPrefixes.empty())
+ return false;
+
+ std::vector<std::string>::const_iterator itr = std::find(_registeredAddonPrefixes.begin(), _registeredAddonPrefixes.end(), prefix);
+ return itr != _registeredAddonPrefixes.end();
+}
+
+void WorldSession::HandleUnregisterAddonPrefixesOpcode(WorldPacket& /*recvPacket*/) // empty packet
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_UNREGISTER_ALL_ADDON_PREFIXES");
+
+ _registeredAddonPrefixes.clear();
+}
+
+void WorldSession::HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket)
+{
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_ADDON_REGISTERED_PREFIXES");
+
+ // This is always sent after CMSG_UNREGISTER_ALL_ADDON_PREFIXES
+
+ uint32 count = recvPacket.ReadBits(25);
+
+ if (count > REGISTERED_ADDON_PREFIX_SOFTCAP)
+ {
+ // if we have hit the softcap (64) nothing should be filtered
+ _filterAddonMessages = false;
+ recvPacket.rfinish();
+ return;
+ }
+
+ std::vector<uint8> lengths(count);
+ for (uint32 i = 0; i < count; ++i)
+ lengths[i] = recvPacket.ReadBits(5);
+
+ for (uint32 i = 0; i < count; ++i)
+ _registeredAddonPrefixes.push_back(recvPacket.ReadString(lengths[i]));
+
+ if (_registeredAddonPrefixes.size() > REGISTERED_ADDON_PREFIX_SOFTCAP) // shouldn't happen
+ {
+ _filterAddonMessages = false;
+ return;
+ }
+
+ _filterAddonMessages = true;
+}
+
void WorldSession::SetPlayer(Player* player)
{
_player = player;
@@ -1253,7 +1194,7 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co
TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Ping: %u, Character: %s, flooding packet (opc: %s (0x%X), count: %u)",
Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetLatency(), Session->GetPlayerName().c_str(),
- opcodeTable[p.GetOpcode()].name, p.GetOpcode(), packetCounter.amountCounter);
+ opcodeTable[p.GetOpcode()]->Name, p.GetOpcode(), packetCounter.amountCounter);
switch (_policy)
{
@@ -1306,7 +1247,6 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_PLAYER_LOGOUT: // 0 1
case CMSG_LOGOUT_REQUEST: // 0 1
case CMSG_PET_RENAME: // 0 1
- case CMSG_QUESTGIVER_CANCEL: // 0 1
case CMSG_QUESTGIVER_REQUEST_REWARD: // 0 1
case CMSG_COMPLETE_CINEMATIC: // 0 1
case CMSG_BANKER_ACTIVATE: // 0 1
@@ -1316,8 +1256,6 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_DUEL_CANCELLED: // 0 1
case CMSG_CALENDAR_COMPLAIN: // 0 1
case CMSG_QUEST_QUERY: // 0 1.5
- case CMSG_ITEM_QUERY_SINGLE: // 0 1.5
- case CMSG_ITEM_NAME_QUERY: // 0 1.5
case CMSG_GAMEOBJECT_QUERY: // 0 1.5
case CMSG_CREATURE_QUERY: // 0 1.5
case CMSG_QUESTGIVER_STATUS_QUERY: // 0 1.5
@@ -1327,7 +1265,7 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_TAXIQUERYAVAILABLENODES: // 0 1.5
case CMSG_QUESTGIVER_QUERY_QUEST: // 0 1.5
case CMSG_PAGE_TEXT_QUERY: // 0 1.5
- case MSG_QUERY_GUILD_BANK_TEXT: // 0 1.5
+ case CMSG_GUILD_BANK_QUERY_TEXT: // 0 1.5
case MSG_CORPSE_QUERY: // 0 1.5
case MSG_MOVE_SET_FACING: // 0 1.5
case CMSG_REQUEST_PARTY_MEMBER_STATS: // 0 1.5
@@ -1342,28 +1280,44 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_SELF_RES: // 0 1.5
case CMSG_UNLEARN_SKILL: // 0 1.5
case CMSG_EQUIPMENT_SET_SAVE: // 0 1.5
- case CMSG_DELETEEQUIPMENT_SET: // 0 1.5
+ case CMSG_EQUIPMENT_SET_DELETE: // 0 1.5
case CMSG_DISMISS_CRITTER: // 0 1.5
case CMSG_REPOP_REQUEST: // 0 1.5
case CMSG_GROUP_INVITE: // 0 1.5
- case CMSG_GROUP_DECLINE: // 0 1.5
- case CMSG_GROUP_ACCEPT: // 0 1.5
+ case CMSG_GROUP_INVITE_RESPONSE: // 0 1.5
case CMSG_GROUP_UNINVITE_GUID: // 0 1.5
- case CMSG_GROUP_UNINVITE: // 0 1.5
case CMSG_GROUP_DISBAND: // 0 1.5
case CMSG_BATTLEMASTER_JOIN_ARENA: // 0 1.5
- case CMSG_LEAVE_BATTLEFIELD: // 0 1.5
- case MSG_GUILD_BANK_LOG_QUERY: // 0 2
+ case CMSG_BATTLEFIELD_LEAVE: // 0 1.5
+ case CMSG_GUILD_BANK_LOG_QUERY: // 0 2
case CMSG_LOGOUT_CANCEL: // 0 2
case CMSG_REALM_SPLIT: // 0 2
case CMSG_ALTER_APPEARANCE: // 0 2
case CMSG_QUEST_CONFIRM_ACCEPT: // 0 2
- case MSG_GUILD_EVENT_LOG_QUERY: // 0 2.5
+ case CMSG_GUILD_EVENT_LOG_QUERY: // 0 2.5
case CMSG_READY_FOR_ACCOUNT_DATA_TIMES: // 0 2.5
case CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY: // 0 2.5
case CMSG_BEGIN_TRADE: // 0 2.5
case CMSG_INITIATE_TRADE: // 0 3
- case CMSG_MESSAGECHAT: // 0 3.5
+ case CMSG_MESSAGECHAT_ADDON_BATTLEGROUND: // 0 3.5
+ case CMSG_MESSAGECHAT_ADDON_GUILD: // 0 3.5
+ case CMSG_MESSAGECHAT_ADDON_OFFICER: // 0 3.5
+ case CMSG_MESSAGECHAT_ADDON_PARTY: // 0 3.5
+ case CMSG_MESSAGECHAT_ADDON_RAID: // 0 3.5
+ case CMSG_MESSAGECHAT_ADDON_WHISPER: // 0 3.5
+ case CMSG_MESSAGECHAT_AFK: // 0 3.5
+ case CMSG_MESSAGECHAT_BATTLEGROUND: // 0 3.5
+ case CMSG_MESSAGECHAT_CHANNEL: // 0 3.5
+ case CMSG_MESSAGECHAT_DND: // 0 3.5
+ case CMSG_MESSAGECHAT_EMOTE: // 0 3.5
+ case CMSG_MESSAGECHAT_GUILD: // 0 3.5
+ case CMSG_MESSAGECHAT_OFFICER: // 0 3.5
+ case CMSG_MESSAGECHAT_PARTY: // 0 3.5
+ case CMSG_MESSAGECHAT_RAID: // 0 3.5
+ case CMSG_MESSAGECHAT_RAID_WARNING: // 0 3.5
+ case CMSG_MESSAGECHAT_SAY: // 0 3.5
+ case CMSG_MESSAGECHAT_WHISPER: // 0 3.5
+ case CMSG_MESSAGECHAT_YELL: // 0 3.5
case CMSG_INSPECT: // 0 3.5
case CMSG_AREA_SPIRIT_HEALER_QUERY: // not profiled
{
@@ -1389,8 +1343,7 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
break;
}
- case CMSG_GUILD_SET_PUBLIC_NOTE: // 1 2 1 async db query
- case CMSG_GUILD_SET_OFFICER_NOTE: // 1 2 1 async db query
+ case CMSG_GUILD_SET_NOTE: // 1 2 1 async db query
case CMSG_SET_CONTACT_NOTES: // 1 2.5 1 async db query
case CMSG_CALENDAR_GET_CALENDAR: // 0 1.5 medium upload bandwidth usage
case CMSG_GUILD_BANK_QUERY_TAB: // 0 3.5 medium upload bandwidth usage
@@ -1410,7 +1363,6 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_SPELLCLICK: // not profiled
case CMSG_GAMEOBJ_USE: // not profiled
case CMSG_GAMEOBJ_REPORT_USE: // not profiled
- case CMSG_REMOVE_GLYPH: // not profiled
{
maxPacketCounterAllowed = 20;
break;
@@ -1440,7 +1392,7 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: // not profiled
case CMSG_DISMISS_CONTROLLED_VEHICLE: // not profiled
case CMSG_REQUEST_VEHICLE_EXIT: // not profiled
- case CMSG_CONTROLLER_EJECT_PASSENGER: // not profiled
+ case CMSG_EJECT_PASSENGER: // not profiled
case CMSG_ITEM_REFUND: // not profiled
case CMSG_SOCKET_GEMS: // not profiled
case CMSG_WRAP_ITEM: // not profiled
@@ -1477,9 +1429,9 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_GUILD_DECLINE: // not profiled
case CMSG_GUILD_LEAVE: // not profiled
case CMSG_GUILD_DISBAND: // not profiled
- case CMSG_GUILD_LEADER: // not profiled
+ case CMSG_GUILD_SET_GUILD_MASTER: // not profiled
case CMSG_GUILD_MOTD: // not profiled
- case CMSG_GUILD_RANK: // not profiled
+ case CMSG_GUILD_SET_RANK_PERMISSIONS: // not profiled
case CMSG_GUILD_ADD_RANK: // not profiled
case CMSG_GUILD_DEL_RANK: // not profiled
case CMSG_GUILD_INFO_TEXT: // not profiled
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index d5b2146ae79..bd159475c37 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -31,6 +31,7 @@
#include "Opcodes.h"
#include "WorldPacket.h"
#include "Cryptography/BigNumber.h"
+#include "Opcodes.h"
#include "AccountMgr.h"
#include <unordered_set>
@@ -86,6 +87,8 @@ enum AccountDataType
#define GLOBAL_CACHE_MASK 0x15
#define PER_CHARACTER_CACHE_MASK 0xEA
+#define REGISTERED_ADDON_PREFIX_SOFTCAP 64
+
struct AccountData
{
AccountData() : Time(0), Data("") { }
@@ -121,12 +124,15 @@ enum ChatRestrictionType
enum CharterTypes
{
- GUILD_CHARTER_TYPE = 9,
+ GUILD_CHARTER_TYPE = 4,
ARENA_TEAM_CHARTER_2v2_TYPE = 2,
ARENA_TEAM_CHARTER_3v3_TYPE = 3,
- ARENA_TEAM_CHARTER_5v5_TYPE = 5
+ ARENA_TEAM_CHARTER_5v5_TYPE = 5,
};
+#define DB2_REPLY_SPARSE 2442913102
+#define DB2_REPLY_ITEM 1344507586
+
//class to deal with packet processing
//allows to determine if next packet is safe to be processed
class PacketFilter
@@ -137,6 +143,7 @@ public:
virtual bool Process(WorldPacket* /*packet*/) { return true; }
virtual bool ProcessLogout() const { return true; }
+ static Opcodes DropHighBytes(Opcodes opcode) { return Opcodes(opcode & 0xFFFF); }
protected:
WorldSession* const m_pSession;
@@ -208,7 +215,7 @@ struct PacketCounter
class WorldSession
{
public:
- WorldSession(uint32 id, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter);
+ WorldSession(uint32 id, uint32 battlenetAccountId, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter);
~WorldSession();
bool PlayerLoading() const { return m_playerLoading; }
@@ -218,20 +225,18 @@ class WorldSession
void ReadAddonsInfo(WorldPacket& data);
void SendAddonsInfo();
+ bool IsAddonRegistered(const std::string& prefix) const;
- void ReadMovementInfo(WorldPacket& data, MovementInfo* mi);
- void WriteMovementInfo(WorldPacket* data, MovementInfo* mi);
-
- void SendPacket(WorldPacket* packet);
+ void SendPacket(WorldPacket* packet, bool forced = false);
void SendNotification(const char *format, ...) ATTR_PRINTF(2, 3);
void SendNotification(uint32 string_id, ...);
void SendPetNameInvalid(uint32 error, std::string const& name, DeclinedName *declinedName);
void SendPartyResult(PartyOperation operation, std::string const& member, PartyResult res, uint32 val = 0);
void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2, 3);
- void SendSetPhaseShift(uint32 phaseShift);
+ void SendSetPhaseShift(std::set<uint32> const& phaseIds, std::set<uint32> const& terrainswaps, std::set<uint32> const& worldMapAreaSwaps);
void SendQueryTimeResponse();
- void SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos = 0);
+ void SendAuthResponse(uint8 code, bool queued, uint32 queuePos = 0);
void SendClientCacheVersion(uint32 version);
rbac::RBACData* GetRBACData();
@@ -241,6 +246,7 @@ class WorldSession
AccountTypes GetSecurity() const { return _security; }
uint32 GetAccountId() const { return _accountId; }
+ uint32 GetBattlenetAccountId() const { return _battlenetAccountId; }
Player* GetPlayer() const { return _player; }
std::string const& GetPlayerName() const;
std::string GetPlayerInfo() const;
@@ -283,12 +289,12 @@ class WorldSession
//void SendTestCreatureQueryOpcode(uint32 entry, uint64 guid, uint32 testvalue);
void SendNameQueryOpcode(uint64 guid);
+ bool CanOpenMailBox(uint64 guid);
+
void SendTrainerList(uint64 guid);
void SendTrainerList(uint64 guid, std::string const& strTitle);
void SendListInventory(uint64 guid);
void SendShowBank(uint64 guid);
- bool CanOpenMailBox(uint64 guid);
- void SendShowMailBox(uint64 guid);
void SendTabardVendorActivate(uint64 guid);
void SendSpiritResurrect();
void SendBindPoint(Creature* npc);
@@ -297,7 +303,7 @@ class WorldSession
void SendBattleGroundList(uint64 guid, BattlegroundTypeId bgTypeId = BATTLEGROUND_RB);
- void SendTradeStatus(TradeStatus status);
+ void SendTradeStatus(TradeStatus status, int8 clearSlot = 0);
void SendUpdateTrade(bool trader_data = true);
void SendCancelTrade();
@@ -336,9 +342,10 @@ class WorldSession
bool SendItemInfo(uint32 itemid, WorldPacket data);
//auction
void SendAuctionHello(uint64 guid, Creature* unit);
- void SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0);
+ void SendAuctionCommandResult(AuctionEntry* auction, uint32 Action, uint32 ErrorCode, uint32 bidError = 0);
void SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template);
void SendAuctionOwnerNotification(AuctionEntry* auction);
+ void SendAuctionRemovedNotification(uint32 auctionId, uint32 itemEntry, int32 randomPropertyId);
//Item Enchantment
void SendEnchantmentLog(uint64 target, uint64 caster, uint32 itemId, uint32 enchantId);
@@ -381,19 +388,15 @@ class WorldSession
else
m_timeOutTime -= diff;
}
- void ResetTimeOutTime()
- {
- m_timeOutTime = sWorld->getIntConfig(CONFIG_SOCKET_TIMEOUTTIME);
- }
- bool IsConnectionIdle() const
- {
- return (m_timeOutTime <= 0 && !m_inQueue);
- }
+ void ResetTimeOutTime() { m_timeOutTime = sWorld->getIntConfig(CONFIG_SOCKET_TIMEOUTTIME); }
+ bool IsConnectionIdle() const { return (m_timeOutTime <= 0 && !m_inQueue); }
// Recruit-A-Friend Handling
uint32 GetRecruiterId() const { return recruiterId; }
bool IsARecruiter() const { return isRecruiter; }
+ z_stream_s* GetCompressionStream() { return _compressionStream; }
+
public: // opcodes handlers
void Handle_NULL(WorldPacket& recvPacket); // not used
@@ -406,9 +409,13 @@ class WorldSession
void HandleCharCreateOpcode(WorldPacket& recvPacket);
void HandleCharCreateCallback(PreparedQueryResult result, CharacterCreateInfo* createInfo);
void HandlePlayerLoginOpcode(WorldPacket& recvPacket);
+ void HandleLoadScreenOpcode(WorldPacket& recvPacket);
void HandleCharEnum(PreparedQueryResult result);
void HandlePlayerLogin(LoginQueryHolder * holder);
void HandleCharFactionOrRaceChange(WorldPacket& recvData);
+ void HandleRandomizeCharNameOpcode(WorldPacket& recvData);
+ void HandleReorderCharacters(WorldPacket& recvData);
+ void HandleOpeningCinematic(WorldPacket& recvData);
// played time
void HandlePlayedTime(WorldPacket& recvPacket);
@@ -417,6 +424,7 @@ class WorldSession
void HandleMoveUnRootAck(WorldPacket& recvPacket);
void HandleMoveRootAck(WorldPacket& recvPacket);
void HandleLookingForGroup(WorldPacket& recvPacket);
+ void HandleReturnToGraveyard(WorldPacket& recvPacket);
// new inspect
void HandleInspectOpcode(WorldPacket& recvPacket);
@@ -443,6 +451,7 @@ class WorldSession
void HandleMoveTeleportAck(WorldPacket& recvPacket);
void HandleForceSpeedChangeAck(WorldPacket& recvData);
+ void HandleSetCollisionHeightAck(WorldPacket& recvPacket);
void HandlePingOpcode(WorldPacket& recvPacket);
void HandleRepopRequestOpcode(WorldPacket& recvPacket);
@@ -481,8 +490,6 @@ class WorldSession
void HandleDelIgnoreOpcode(WorldPacket& recvPacket);
void HandleSetContactNotesOpcode(WorldPacket& recvPacket);
void HandleBugOpcode(WorldPacket& recvPacket);
- void HandleSetAmmoOpcode(WorldPacket& recvPacket);
- void HandleItemNameQueryOpcode(WorldPacket& recvPacket);
void HandleAreaTriggerOpcode(WorldPacket& recvPacket);
@@ -525,11 +532,11 @@ class WorldSession
void HandleGroupInviteOpcode(WorldPacket& recvPacket);
//void HandleGroupCancelOpcode(WorldPacket& recvPacket);
- void HandleGroupAcceptOpcode(WorldPacket& recvPacket);
- void HandleGroupDeclineOpcode(WorldPacket& recvPacket);
+ void HandleGroupInviteResponseOpcode(WorldPacket& recvPacket);
void HandleGroupUninviteOpcode(WorldPacket& recvPacket);
void HandleGroupUninviteGuidOpcode(WorldPacket& recvPacket);
void HandleGroupSetLeaderOpcode(WorldPacket& recvPacket);
+ void HandleGroupSetRolesOpcode(WorldPacket& recvData);
void HandleGroupDisbandOpcode(WorldPacket& recvPacket);
void HandleOptOutOfLootOpcode(WorldPacket& recvData);
void HandleLootMethodOpcode(WorldPacket& recvPacket);
@@ -540,6 +547,7 @@ class WorldSession
void HandleRaidReadyCheckFinishedOpcode(WorldPacket& recvData);
void HandleGroupRaidConvertOpcode(WorldPacket& recvData);
void HandleGroupChangeSubGroupOpcode(WorldPacket& recvData);
+ void HandleGroupSwapSubGroupOpcode(WorldPacket& recvData);
void HandleGroupAssistantLeaderOpcode(WorldPacket& recvData);
void HandlePartyAssignmentOpcode(WorldPacket& recvData);
@@ -553,27 +561,41 @@ class WorldSession
void HandleTurnInPetitionOpcode(WorldPacket& recvData);
void HandleGuildQueryOpcode(WorldPacket& recvPacket);
- void HandleGuildCreateOpcode(WorldPacket& recvPacket);
void HandleGuildInviteOpcode(WorldPacket& recvPacket);
void HandleGuildRemoveOpcode(WorldPacket& recvPacket);
void HandleGuildAcceptOpcode(WorldPacket& recvPacket);
void HandleGuildDeclineOpcode(WorldPacket& recvPacket);
- void HandleGuildInfoOpcode(WorldPacket& recvPacket);
void HandleGuildEventLogQueryOpcode(WorldPacket& recvPacket);
void HandleGuildRosterOpcode(WorldPacket& recvPacket);
+ void HandleGuildRewardsQueryOpcode(WorldPacket& recvPacket);
void HandleGuildPromoteOpcode(WorldPacket& recvPacket);
void HandleGuildDemoteOpcode(WorldPacket& recvPacket);
+ void HandleGuildAssignRankOpcode(WorldPacket& recvPacket);
void HandleGuildLeaveOpcode(WorldPacket& recvPacket);
void HandleGuildDisbandOpcode(WorldPacket& recvPacket);
- void HandleGuildLeaderOpcode(WorldPacket& recvPacket);
+ void HandleGuildSetGuildMaster(WorldPacket& recvPacket);
void HandleGuildMOTDOpcode(WorldPacket& recvPacket);
- void HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket);
- void HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket);
- void HandleGuildRankOpcode(WorldPacket& recvPacket);
+ void HandleGuildNewsUpdateStickyOpcode(WorldPacket& recvPacket);
+ void HandleGuildSetNoteOpcode(WorldPacket& recvPacket);
+ void HandleGuildQueryRanksOpcode(WorldPacket& recvPacket);
+ void HandleGuildQueryNewsOpcode(WorldPacket& recvPacket);
+ void HandleGuildSetRankPermissionsOpcode(WorldPacket& recvPacket);
void HandleGuildAddRankOpcode(WorldPacket& recvPacket);
void HandleGuildDelRankOpcode(WorldPacket& recvPacket);
void HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket);
void HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket);
+ void HandleGuildRequestPartyState(WorldPacket& recvPacket);
+ void HandleGuildRequestMaxDailyXP(WorldPacket& recvPacket);
+ void HandleAutoDeclineGuildInvites(WorldPacket& recvPacket);
+
+ void HandleGuildFinderAddRecruit(WorldPacket& recvPacket);
+ void HandleGuildFinderBrowse(WorldPacket& recvPacket);
+ void HandleGuildFinderDeclineRecruit(WorldPacket& recvPacket);
+ void HandleGuildFinderGetApplications(WorldPacket& recvPacket);
+ void HandleGuildFinderGetRecruits(WorldPacket& recvPacket);
+ void HandleGuildFinderPostRequest(WorldPacket& recvPacket);
+ void HandleGuildFinderRemoveRecruit(WorldPacket& recvPacket);
+ void HandleGuildFinderSetGuildPost(WorldPacket& recvPacket);
void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket);
void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket);
@@ -602,6 +624,7 @@ class WorldSession
void HandleStableRevivePet(WorldPacket& recvPacket);
void HandleStableSwapPet(WorldPacket& recvPacket);
void HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId);
+ void SendTrainerBuyFailed(uint64 guid, uint32 spellId, uint32 reason);
void HandleDuelAcceptedOpcode(WorldPacket& recvPacket);
void HandleDuelCancelledOpcode(WorldPacket& recvPacket);
@@ -637,13 +660,13 @@ class WorldSession
void HandleMailCreateTextItem(WorldPacket& recvData);
void HandleQueryNextMailTime(WorldPacket& recvData);
void HandleCancelChanneling(WorldPacket& recvData);
+ void SendShowMailBox(uint64 guid);
void SendItemPageInfo(ItemTemplate* itemProto);
void HandleSplitItemOpcode(WorldPacket& recvPacket);
void HandleSwapInvItemOpcode(WorldPacket& recvPacket);
void HandleDestroyItemOpcode(WorldPacket& recvPacket);
void HandleAutoEquipItemOpcode(WorldPacket& recvPacket);
- void HandleItemQuerySingleOpcode(WorldPacket& recvPacket);
void HandleSellItemOpcode(WorldPacket& recvPacket);
void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket);
void HandleBuyItemOpcode(WorldPacket& recvPacket);
@@ -692,6 +715,7 @@ class WorldSession
void HandleQuestPushResult(WorldPacket& recvPacket);
void HandleMessagechatOpcode(WorldPacket& recvPacket);
+ void HandleAddonMessagechatOpcode(WorldPacket& recvPacket);
void SendPlayerNotFoundNotice(std::string const& name);
void SendPlayerAmbiguousNotice(std::string const& name);
void SendWrongFactionNotice();
@@ -699,6 +723,9 @@ class WorldSession
void HandleTextEmoteOpcode(WorldPacket& recvPacket);
void HandleChatIgnoredOpcode(WorldPacket& recvPacket);
+ void HandleUnregisterAddonPrefixesOpcode(WorldPacket& recvPacket);
+ void HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket);
+
void HandleReclaimCorpseOpcode(WorldPacket& recvPacket);
void HandleCorpseQueryOpcode(WorldPacket& recvPacket);
void HandleCorpseMapPositionQuery(WorldPacket& recvPacket);
@@ -738,7 +765,7 @@ class WorldSession
//Pet
void HandlePetAction(WorldPacket& recvData);
void HandlePetStopAttack(WorldPacket& recvData);
- void HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid, uint16 flag, uint64 guid2);
+ void HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid, uint16 flag, uint64 guid2, float x, float y, float z);
void HandlePetNameQuery(WorldPacket& recvData);
void HandlePetSetAction(WorldPacket& recvData);
void HandlePetAbandon(WorldPacket& recvData);
@@ -768,13 +795,17 @@ class WorldSession
void HandleBattlefieldLeaveOpcode(WorldPacket& recvData);
void HandleBattlemasterJoinArena(WorldPacket& recvData);
void HandleReportPvPAFK(WorldPacket& recvData);
+ void HandleRequestRatedBgInfo(WorldPacket& recvData);
+ void HandleRequestPvpOptions(WorldPacket& recvData);
+ void HandleRequestPvpReward(WorldPacket& recvData);
+ void HandleRequestRatedBgStats(WorldPacket& recvData);
// Battlefield
- void SendBfInvitePlayerToWar(uint32 battleId, uint32 zoneId, uint32 time);
- void SendBfInvitePlayerToQueue(uint32 battleId);
- void SendBfQueueInviteResponse(uint32 battleId, uint32 zoneId, bool canQueue = true, bool full = false);
- void SendBfEntered(uint32 battleId);
- void SendBfLeaveMessage(uint32 battleId, BFLeaveReason reason = BF_LEAVE_REASON_EXITED);
+ void SendBfInvitePlayerToWar(uint64 guid, uint32 zoneId, uint32 time);
+ void SendBfInvitePlayerToQueue(uint64 guid);
+ void SendBfQueueInviteResponse(uint64 guid, uint32 zoneId, bool canQueue = true, bool full = false);
+ void SendBfEntered(uint64 guid);
+ void SendBfLeaveMessage(uint64 guid, BFLeaveReason reason = BF_LEAVE_REASON_EXITED);
void HandleBfQueueInviteResponse(WorldPacket& recvData);
void HandleBfEntryInviteResponse(WorldPacket& recvData);
void HandleBfExitRequest(WorldPacket& recvData);
@@ -797,8 +828,9 @@ class WorldSession
// Looking for Dungeon/Raid
void HandleLfgSetCommentOpcode(WorldPacket& recvData);
- void HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& recvData);
- void HandleLfgPartyLockInfoRequestOpcode(WorldPacket& recvData);
+ void HandleLfgGetLockInfoOpcode(WorldPacket& recvData);
+ void SendLfgPlayerLockInfo();
+ void SendLfgPartyLockInfo();
void HandleLfgJoinOpcode(WorldPacket& recvData);
void HandleLfgLeaveOpcode(WorldPacket& recvData);
void HandleLfgSetRolesOpcode(WorldPacket& recvData);
@@ -809,8 +841,7 @@ class WorldSession
void HandleLfrLeaveOpcode(WorldPacket& recvData);
void HandleLfgGetStatus(WorldPacket& recvData);
- void SendLfgUpdatePlayer(lfg::LfgUpdateData const& updateData);
- void SendLfgUpdateParty(lfg::LfgUpdateData const& updateData);
+ void SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, bool party);
void SendLfgRoleChosen(uint64 guid, uint8 roles);
void SendLfgRoleCheckUpdate(lfg::LfgRoleCheck const& pRoleCheck);
void SendLfgLfrList(bool update);
@@ -827,6 +858,7 @@ class WorldSession
void HandleInspectArenaTeamsOpcode(WorldPacket& recvData);
void HandleArenaTeamQueryOpcode(WorldPacket& recvData);
void HandleArenaTeamRosterOpcode(WorldPacket& recvData);
+ void HandleArenaTeamCreateOpcode(WorldPacket& recvData);
void HandleArenaTeamInviteOpcode(WorldPacket& recvData);
void HandleArenaTeamAcceptOpcode(WorldPacket& recvData);
void HandleArenaTeamDeclineOpcode(WorldPacket& recvData);
@@ -869,6 +901,7 @@ class WorldSession
void HandleGuildBankBuyTab(WorldPacket& recvData);
void HandleQueryGuildBankTabText(WorldPacket& recvData);
void HandleSetGuildBankTabText(WorldPacket& recvData);
+ void HandleGuildQueryXPOpcode(WorldPacket& recvData);
// Refer-a-Friend
void HandleGrantLevel(WorldPacket& recvData);
@@ -896,12 +929,28 @@ class WorldSession
void SendCalendarRaidLockoutUpdated(InstanceSave const* save);
void HandleSetSavedInstanceExtend(WorldPacket& recvData);
+ // Void Storage
+ void HandleVoidStorageUnlock(WorldPacket& recvData);
+ void HandleVoidStorageQuery(WorldPacket& recvData);
+ void HandleVoidStorageTransfer(WorldPacket& recvData);
+ void HandleVoidSwapItem(WorldPacket& recvData);
+ void SendVoidStorageTransferResult(VoidTransferError result);
+
+ // Transmogrification
+ void HandleTransmogrifyItems(WorldPacket& recvData);
+
+ // Reforge
+ void HandleReforgeItemOpcode(WorldPacket& recvData);
+ void SendReforgeResult(bool success);
+
+ // Miscellaneous
void HandleSpellClick(WorldPacket& recvData);
void HandleMirrorImageDataRequest(WorldPacket& recvData);
void HandleAlterAppearance(WorldPacket& recvData);
void HandleRemoveGlyph(WorldPacket& recvData);
void HandleCharCustomize(WorldPacket& recvData);
void HandleQueryInspectAchievements(WorldPacket& recvData);
+ void HandleGuildAchievementProgressQuery(WorldPacket& recvData);
void HandleEquipmentSetSave(WorldPacket& recvData);
void HandleEquipmentSetDelete(WorldPacket& recvData);
void HandleEquipmentSetUse(WorldPacket& recvData);
@@ -912,7 +961,16 @@ class WorldSession
void HandleEjectPassenger(WorldPacket& data);
void HandleEnterPlayerVehicle(WorldPacket& data);
void HandleUpdateProjectilePosition(WorldPacket& recvPacket);
+ void HandleRequestHotfix(WorldPacket& recvPacket);
void HandleUpdateMissileTrajectory(WorldPacket& recvPacket);
+ void HandleViolenceLevel(WorldPacket& recvPacket);
+ void HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket);
+ void HandleRequestCategoryCooldowns(WorldPacket& recvPacket);
+ int32 HandleEnableNagleAlgorithm();
+
+ // Compact Unit Frames (4.x)
+ void HandleSaveCUFProfiles(WorldPacket& recvPacket);
+ void SendLoadCUFProfiles();
private:
void InitializeQueryCallbackParameters();
@@ -987,6 +1045,7 @@ class WorldSession
AccountTypes _security;
uint32 _accountId;
+ uint32 _battlenetAccountId;
uint8 m_expansion;
typedef std::list<AddonInfo> AddonsList;
@@ -1008,9 +1067,12 @@ class WorldSession
uint32 m_Tutorials[MAX_ACCOUNT_TUTORIAL_VALUES];
bool m_TutorialsChanged;
AddonsList m_addonsList;
+ std::vector<std::string> _registeredAddonPrefixes;
+ bool _filterAddonMessages;
uint32 recruiterId;
bool isRecruiter;
LockedQueue<WorldPacket*> _recvQueue;
+ z_stream_s* _compressionStream;
rbac::RBACData* _RBACData;
uint32 expireTime;
bool forceExit;
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index ea0bfc234bf..46a1bf8f16d 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -1,20 +1,20 @@
/*
-* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
-* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
-*
-* This program is free software; you can redistribute it and/or modify it
-* under the terms of the GNU General Public License as published by 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, see <http://www.gnu.org/licenses/>.
-*/
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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, see <http://www.gnu.org/licenses/>.
+ */
#include <memory>
#include "WorldSocket.h"
@@ -23,6 +23,7 @@
#include "ScriptMgr.h"
#include "SHA1.h"
#include "PacketLog.h"
+#include "BattlenetAccountMgr.h"
using boost::asio::ip::tcp;
@@ -34,15 +35,17 @@ WorldSocket::WorldSocket(tcp::socket&& socket)
void WorldSocket::Start()
{
AsyncReadHeader();
- HandleSendAuthSession();
+
+ // not an opcode. this packet sends raw string WORLD OF WARCRAFT CONNECTION - SERVER TO CLIENT"
+ // because of our implementation of WorldPacket sending, bytes "WO" become the opcode
+ WorldPacket packet(MSG_VERIFY_CONNECTIVITY);
+ packet << "RLD OF WARCRAFT CONNECTION - SERVER TO CLIENT";
+ AsyncWrite(packet);
}
void WorldSocket::HandleSendAuthSession()
{
WorldPacket packet(SMSG_AUTH_CHALLENGE, 37);
- packet << uint32(1); // 1...31
- packet << uint32(_authSeed);
-
BigNumber seed1;
seed1.SetRand(16 * 8);
packet.append(seed1.AsByteArray(16).get(), 16); // new encryption seeds
@@ -51,6 +54,8 @@ void WorldSocket::HandleSendAuthSession()
seed2.SetRand(16 * 8);
packet.append(seed2.AsByteArray(16).get(), 16); // new encryption seeds
+ packet << uint32(_authSeed);
+ packet << uint8(1);
AsyncWrite(packet);
}
@@ -78,7 +83,7 @@ void WorldSocket::ReadDataHandler(boost::system::error_code error, size_t transf
{
header->size -= sizeof(header->cmd);
- uint16 opcode = uint16(header->cmd);
+ Opcodes opcode = PacketFilter::DropHighBytes(Opcodes(header->cmd));
std::string opcodeName = GetOpcodeNameForLogging(opcode);
@@ -115,6 +120,36 @@ void WorldSocket::ReadDataHandler(boost::system::error_code error, size_t transf
TC_LOG_DEBUG("network", "%s", opcodeName.c_str());
sScriptMgr->OnPacketReceive(shared_from_this(), packet);
break;
+ case CMSG_LOG_DISCONNECT:
+ packet.rfinish(); // contains uint32 disconnectReason;
+ TC_LOG_DEBUG("network", "%s", opcodeName.c_str());
+ sScriptMgr->OnPacketReceive(shared_from_this(), packet);
+ return;
+ // not an opcode, client sends string "WORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER" without opcode
+ // first 4 bytes become the opcode (2 dropped)
+ case MSG_VERIFY_CONNECTIVITY:
+ {
+ TC_LOG_DEBUG("network", "%s", opcodeName.c_str());
+ sScriptMgr->OnPacketReceive(shared_from_this(), packet);
+ std::string str;
+ packet >> str;
+ if (str != "D OF WARCRAFT CONNECTION - CLIENT TO SERVER")
+ {
+ CloseSocket();
+ break;
+ }
+
+ HandleSendAuthSession();
+ break;
+ }
+ case CMSG_ENABLE_NAGLE:
+ {
+ TC_LOG_DEBUG("network", "%s", opcodeName.c_str());
+ sScriptMgr->OnPacketReceive(shared_from_this(), packet);
+ if (_worldSession)
+ _worldSession->HandleEnableNagleAlgorithm();
+ break;
+ }
default:
{
if (!_worldSession)
@@ -144,6 +179,9 @@ void WorldSocket::AsyncWrite(WorldPacket& packet)
if (sPacketLog->CanLogPacket())
sPacketLog->LogPacket(packet, SERVER_TO_CLIENT);
+ if (_worldSession && packet.size() > 0x400)
+ packet.Compress(_worldSession->GetCompressionStream());
+
TC_LOG_TRACE("network.opcode", "S->C: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(packet.GetOpcode()).c_str());
ServerPktHeader header(packet.size() + 2, packet.GetOpcode());
@@ -164,17 +202,57 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
uint8 digest[20];
uint32 clientSeed;
uint8 security;
+ uint16 clientBuild;
uint32 id;
+ uint32 addonSize;
LocaleConstant locale;
std::string account;
SHA1Hash sha;
- uint32 clientBuild;
- uint32 unk2, unk3, unk5, unk6, unk7;
- uint64 unk4;
- WorldPacket packet, SendAddonPacked;
BigNumber k;
bool wardenActive = sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED);
+ WorldPacket addonsData;
+
+ recvPacket.read_skip<uint32>();
+ recvPacket.read_skip<uint32>();
+ recvPacket.read_skip<uint8>();
+ recvPacket >> digest[10];
+ recvPacket >> digest[18];
+ recvPacket >> digest[12];
+ recvPacket >> digest[5];
+ recvPacket.read_skip<uint64>();
+ recvPacket >> digest[15];
+ recvPacket >> digest[9];
+ recvPacket >> digest[19];
+ recvPacket >> digest[4];
+ recvPacket >> digest[7];
+ recvPacket >> digest[16];
+ recvPacket >> digest[3];
+ recvPacket >> clientBuild;
+ recvPacket >> digest[8];
+ recvPacket.read_skip<uint32>();
+ recvPacket.read_skip<uint8>();
+ recvPacket >> digest[17];
+ recvPacket >> digest[6];
+ recvPacket >> digest[0];
+ recvPacket >> digest[1];
+ recvPacket >> digest[11];
+ recvPacket >> clientSeed;
+ recvPacket >> digest[2];
+ recvPacket.read_skip<uint32>();
+ recvPacket >> digest[14];
+ recvPacket >> digest[13];
+
+ recvPacket >> addonSize;
+ if (addonSize)
+ {
+ addonsData.resize(addonSize);
+ recvPacket.read((uint8*)addonsData.contents(), addonSize);
+ }
+
+ recvPacket.ReadBit();
+ uint32 accountNameLength = recvPacket.ReadBits(12);
+ account = recvPacket.ReadString(accountNameLength);
if (sWorld->IsClosed())
{
SendAuthResponseError(AUTH_REJECT);
@@ -182,29 +260,23 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
return;
}
- // Read the content of the packet
- recvPacket >> clientBuild;
- recvPacket >> unk2;
- recvPacket >> account;
- recvPacket >> unk3;
- recvPacket >> clientSeed;
- recvPacket >> unk5 >> unk6 >> unk7;
- recvPacket >> unk4;
- recvPacket.read(digest, 20);
-
- TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, unk3 %u, clientseed %u",
- clientBuild,
- unk2,
- account.c_str(),
- unk3,
- clientSeed);
-
// Get the account information from the realmd database
// 0 1 2 3 4 5 6 7 8
// SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ?
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);
-
- stmt->setString(0, account);
+ PreparedStatement* stmt;
+ uint32 battlenetAccountId = 0;
+ uint8 battlenetAccountIndex = 0;
+ if (Battlenet::AccountMgr::GetAccountIdAndIndex(account, &battlenetAccountId, &battlenetAccountIndex))
+ {
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_BNET);
+ stmt->setUInt32(0, battlenetAccountId);
+ stmt->setUInt8(1, battlenetAccountIndex);
+ }
+ else
+ {
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);
+ stmt->setString(0, account);
+ }
PreparedQueryResult result = LoginDatabase.Query(stmt);
@@ -367,13 +439,13 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
LoginDatabase.Execute(stmt);
// NOTE ATM the socket is single-threaded, have this in mind ...
- _worldSession = new WorldSession(id, shared_from_this(), AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter);
+ _worldSession = new WorldSession(id, battlenetAccountId, shared_from_this(), AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter);
_authCrypt.Init(&k);
_worldSession->LoadGlobalAccountData();
_worldSession->LoadTutorialsData();
- _worldSession->ReadAddonsInfo(recvPacket);
+ _worldSession->ReadAddonsInfo(addonsData);
_worldSession->LoadPermissions();
// At this point, we can safely hook a successful login
@@ -389,6 +461,8 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
void WorldSocket::SendAuthResponseError(uint8 code)
{
WorldPacket packet(SMSG_AUTH_RESPONSE, 1);
+ packet.WriteBit(0); // has queue info
+ packet.WriteBit(0); // has account info
packet << uint8(code);
AsyncWrite(packet);
@@ -400,8 +474,8 @@ void WorldSocket::HandlePing(WorldPacket& recvPacket)
uint32 latency;
// Get the ping packet content
- recvPacket >> ping;
recvPacket >> latency;
+ recvPacket >> ping;
if (_LastPingTime == steady_clock::time_point())
{
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 1fa08c2b5f1..4e1cbe743fd 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -30,7 +30,7 @@ namespace boost
}
#include "Common.h"
-#include "AuthCrypt.h"
+#include "WorldPacketCrypt.h"
#include "ServerPktHeader.h"
#include "Socket.h"
#include "Util.h"
@@ -119,7 +119,7 @@ private:
void HandlePing(WorldPacket& recvPacket);
uint32 _authSeed;
- AuthCrypt _authCrypt;
+ WorldPacketCrypt _authCrypt;
std::chrono::steady_clock::time_point _LastPingTime;
uint32 _OverSpeedPings;
diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h
index aa1f6a49413..628e4e0721d 100644
--- a/src/server/game/Spells/Auras/SpellAuraDefines.h
+++ b/src/server/game/Spells/Auras/SpellAuraDefines.h
@@ -200,7 +200,7 @@ enum AuraType
SPELL_AURA_MOD_MELEE_HASTE = 138,
SPELL_AURA_FORCE_REACTION = 139,
SPELL_AURA_MOD_RANGED_HASTE = 140,
- SPELL_AURA_MOD_RANGED_AMMO_HASTE = 141,
+ SPELL_AURA_141 = 141, // old SPELL_AURA_MOD_RANGED_AMMO_HASTE, unused now
SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142,
SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143,
SPELL_AURA_SAFE_FALL = 144,
@@ -212,14 +212,14 @@ enum AuraType
SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT = 150,
SPELL_AURA_TRACK_STEALTHED = 151, // Track Stealthed
SPELL_AURA_MOD_DETECTED_RANGE = 152, // Mod Detected Range
- SPELL_AURA_SPLIT_DAMAGE_FLAT = 153, // Split Damage Flat
+ SPELL_AURA_153 = 153, // old SPELL_AURA_SPLIT_DAMAGE_FLAT. unused 4.3.4
SPELL_AURA_MOD_STEALTH_LEVEL = 154, // Stealth Level Modifier
SPELL_AURA_MOD_WATER_BREATHING = 155, // Mod Water Breathing
SPELL_AURA_MOD_REPUTATION_GAIN = 156, // Mod Reputation Gain
SPELL_AURA_PET_DAMAGE_MULTI = 157, // Mod Pet Damage
SPELL_AURA_MOD_SHIELD_BLOCKVALUE = 158,
SPELL_AURA_NO_PVP_CREDIT = 159,
- SPELL_AURA_MOD_AOE_AVOIDANCE = 160,
+ SPELL_AURA_160 = 160, // old SPELL_AURA_MOD_AOE_AVOIDANCE. Unused 4.3.4
SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT = 161,
SPELL_AURA_POWER_BURN = 162,
SPELL_AURA_MOD_CRIT_DAMAGE_BONUS = 163,
@@ -228,7 +228,7 @@ enum AuraType
SPELL_AURA_MOD_ATTACK_POWER_PCT = 166,
SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT = 167,
SPELL_AURA_MOD_DAMAGE_DONE_VERSUS = 168,
- SPELL_AURA_MOD_CRIT_PERCENT_VERSUS = 169,
+ SPELL_AURA_169 = 169, // old SPELL_AURA_MOD_CRIT_PERCENT_VERSUS. unused 4.3.4
SPELL_AURA_DETECT_AMORE = 170,
SPELL_AURA_MOD_SPEED_NOT_STACK = 171,
SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK = 172,
@@ -237,7 +237,7 @@ enum AuraType
SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT = 175,
SPELL_AURA_SPIRIT_OF_REDEMPTION = 176,
SPELL_AURA_AOE_CHARM = 177,
- SPELL_AURA_MOD_DEBUFF_RESISTANCE = 178,
+ SPELL_AURA_178 = 178, // old SPELL_AURA_MOD_DEBUFF_RESISTANCE, unused
SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE = 179,
SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS = 180,
SPELL_AURA_181 = 181, // old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS - possible flat spell crit damage versus
@@ -258,7 +258,7 @@ enum AuraType
SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath
SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197,
SPELL_AURA_198 = 198, // old SPELL_AURA_MOD_ALL_WEAPON_SKILLS
- SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT = 199,
+ SPELL_AURA_199 = 199, // old SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT. unused 4.3.4
SPELL_AURA_MOD_XP_PCT = 200,
SPELL_AURA_FLY = 201,
SPELL_AURA_IGNORE_COMBAT_RESULT = 202,
@@ -271,12 +271,12 @@ enum AuraType
SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS = 209,
SPELL_AURA_MOD_VEHICLE_SPEED_ALWAYS = 210,
SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK = 211,
- SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT = 212,
+ SPELL_AURA_212 = 212, // old SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT. unused 4.3.4
SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT = 213,
SPELL_AURA_214 = 214,
SPELL_AURA_ARENA_PREPARATION = 215,
SPELL_AURA_HASTE_SPELLS = 216,
- SPELL_AURA_MOD_MELEE_HASTE_2 = 217, // NYI
+ SPELL_AURA_MOD_MELEE_HASTE_2 = 217,
SPELL_AURA_HASTE_RANGED = 218,
SPELL_AURA_MOD_MANA_REGEN_FROM_STAT = 219,
SPELL_AURA_MOD_RATING_FROM_STAT = 220,
@@ -289,7 +289,7 @@ enum AuraType
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_MOD_MAX_HEALTH = 230,
SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE = 231,
SPELL_AURA_MECHANIC_DURATION_MOD = 232,
SPELL_AURA_CHANGE_MODEL_FOR_ALL_HUMANOIDS = 233, // client-side only
@@ -318,7 +318,7 @@ enum AuraType
SPELL_AURA_NO_REAGENT_USE = 256,
SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS = 257,
SPELL_AURA_258 = 258,
- SPELL_AURA_MOD_HOT_PCT = 259,
+ SPELL_AURA_259 = 259, // old SPELL_AURA_MOD_HOT_PCT, unused 4.3.4
SPELL_AURA_SCREEN_EFFECT = 260,
SPELL_AURA_PHASE = 261,
SPELL_AURA_ABILITY_IGNORE_AURASTATE = 262,
@@ -327,19 +327,19 @@ enum AuraType
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_268 = 268, // old SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT. unused 4.3.4
SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 269,
- SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive
+ SPELL_AURA_270 = 270, // old SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST, unused 4.3.4
SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271,
SPELL_AURA_IGNORE_MELEE_RESET = 272,
SPELL_AURA_X_RAY = 273,
- SPELL_AURA_ABILITY_CONSUME_NO_AMMO = 274,
+ SPELL_AURA_274 = 274, // old SPELL_AURA_ABILITY_CONSUME_NO_AMMO, unused 4.3.4
SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275,
- SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC = 276, // NYI
- SPELL_AURA_MOD_MAX_AFFECTED_TARGETS = 277,
+ SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC = 276,
+ SPELL_AURA_277 = 277, // old SPELL_AURA_MOD_MAX_AFFECTED_TARGETS. unused 4.3.4
SPELL_AURA_MOD_DISARM_RANGED = 278,
SPELL_AURA_INITIALIZE_IMAGES = 279,
- SPELL_AURA_MOD_ARMOR_PENETRATION_PCT = 280,
+ SPELL_AURA_280 = 280, // old SPELL_AURA_MOD_ARMOR_PENETRATION_PCT unused 4.3.4
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
@@ -367,16 +367,70 @@ enum AuraType
SPELL_AURA_MOD_MINIMUM_SPEED = 305,
SPELL_AURA_306 = 306,
SPELL_AURA_HEAL_ABSORB_TEST = 307,
- SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER = 308, // NYI
- SPELL_AURA_309 = 309,
+ SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER = 308,
+ SPELL_AURA_309 = 309, // Not used in 4.3.4
SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE = 310,
SPELL_AURA_311 = 311,
- SPELL_AURA_312 = 312,
- SPELL_AURA_313 = 313,
+ SPELL_AURA_ANIM_REPLACEMENT_SET = 312,
+ SPELL_AURA_313 = 313, // Not used in 4.3.4 - related to mounts
SPELL_AURA_PREVENT_RESURRECTION = 314,
SPELL_AURA_UNDERWATER_WALKING = 315,
- SPELL_AURA_PERIODIC_HASTE = 316,
- TOTAL_AURAS = 317
+ SPELL_AURA_PERIODIC_HASTE = 316, // Not used in 4.3.4 (name from 3.3.5a)
+ SPELL_AURA_MOD_SPELL_POWER_PCT = 317,
+ SPELL_AURA_MASTERY = 318,
+ SPELL_AURA_MOD_MELEE_HASTE_3 = 319,
+ SPELL_AURA_MOD_RANGED_HASTE_2 = 320,
+ SPELL_AURA_321 = 321,
+ SPELL_AURA_INTERFERE_TARGETTING = 322, // NYI
+ SPELL_AURA_323 = 323, // Not used in 4.3.4
+ SPELL_AURA_324 = 324, // spell critical chance (probably by school mask)
+ SPELL_AURA_325 = 325, // Not used in 4.3.4
+ SPELL_AURA_PHASE_GROUP = 326, // Puts the player in all the phases that are in the group with id = miscB
+ SPELL_AURA_327 = 327, // Not used in 4.3.4
+ SPELL_AURA_PROC_ON_POWER_AMOUNT = 328,
+ SPELL_AURA_MOD_RUNE_REGEN_SPEED = 329, // NYI
+ SPELL_AURA_CAST_WHILE_WALKING = 330,
+ SPELL_AURA_FORCE_WEATHER = 331,
+ SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS = 332,
+ SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2 = 333,
+ SPELL_AURA_MOD_BLIND = 334, // NYI
+ SPELL_AURA_335 = 335,
+ SPELL_AURA_MOD_FLYING_RESTRICTIONS = 336, // NYI
+ SPELL_AURA_MOD_VENDOR_ITEMS_PRICES = 337,
+ SPELL_AURA_MOD_DURABILITY_LOSS = 338,
+ SPELL_AURA_INCREASE_SKILL_GAIN_CHANCE = 339, // NYI
+ SPELL_AURA_MOD_RESURRECTED_HEALTH_BY_GUILD_MEMBER = 340, // Increases health gained when resurrected by a guild member by X
+ SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN = 341, // Modifies cooldown of all spells using affected category
+ SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 = 342,
+ SPELL_AURA_343 = 343,
+ SPELL_AURA_MOD_AUTOATTACK_DAMAGE = 344, // NYI
+ SPELL_AURA_BYPASS_ARMOR_FOR_CASTER = 345,
+ SPELL_AURA_ENABLE_ALT_POWER = 346, // NYI
+ SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE = 347, // NYI
+ SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT = 348,
+ SPELL_AURA_MOD_CURRENCY_GAIN = 349,
+ SPELL_AURA_MOD_GATHERING_ITEMS_GAINED_PERCENT = 350, // NYI
+ SPELL_AURA_351 = 351,
+ SPELL_AURA_352 = 352,
+ SPELL_AURA_MOD_CAMOUFLAGE = 353, // NYI
+ SPELL_AURA_354 = 354, // Restoration Shaman mastery - mod healing based on target's health (less = more healing)
+ SPELL_AURA_355 = 355,
+ SPELL_AURA_356 = 356, // Arcane Mage mastery - mod damage based on current mana
+ SPELL_AURA_ENABLE_BOSS1_UNIT_FRAME = 357,
+ SPELL_AURA_WORGEN_ALTERED_FORM = 358,
+ SPELL_AURA_359 = 359,
+ SPELL_AURA_PROC_TRIGGER_SPELL_COPY = 360, // Procs the same spell that caused this proc (Dragonwrath, Tarecgosa's Rest)
+ SPELL_AURA_PROC_TRIGGER_SPELL_2 = 361,
+ SPELL_AURA_362 = 362, // Not used in 4.3.4
+ SPELL_AURA_MOD_NEXT_SPELL = 363, // Used by 101601 Throw Totem - causes the client to initialize spell cast with specified spell
+ SPELL_AURA_364 = 364, // Not used in 4.3.4
+ SPELL_AURA_MAX_FAR_CLIP_PLANE = 365, // Overrides client's View Distance setting to max("Fair", current_setting) and turns off terrain display
+ SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT = 366, // NYI - Sets spellpower equal to % of attack power, discarding all other bonuses (from gear and buffs)
+ SPELL_AURA_367 = 367,
+ SPELL_AURA_368 = 368, // Not used in 4.3.4
+ SPELL_AURA_ENABLE_POWER_BAR_TIMER = 369,
+ SPELL_AURA_SET_FAIR_FAR_CLIP = 370, // Overrides client's View Distance setting to max("Fair", current_setting)
+ TOTAL_AURAS = 371 // 4.3.4
};
enum AuraObjectType
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 1894776c990..da12ed3da77 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -38,6 +38,7 @@
#include "Vehicle.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
+#include "WeatherMgr.h"
#include "Pet.h"
#include "ReputationMgr.h"
@@ -76,7 +77,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH
&AuraEffect::HandleModStealthDetect, // 17 SPELL_AURA_MOD_DETECT
&AuraEffect::HandleModInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY
- &AuraEffect::HandleModInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION
+ &AuraEffect::HandleModInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECT
&AuraEffect::HandleNoImmediateEffect, // 20 SPELL_AURA_OBS_MOD_HEALTH implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, // 21 SPELL_AURA_OBS_MOD_POWER implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE
@@ -120,7 +121,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE
&AuraEffect::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE
&AuraEffect::HandleNoImmediateEffect, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL implemented in AuraEffect::PeriodicTick
- &AuraEffect::HandleUnused, // 63 unused (3.2.0) old SPELL_AURA_PERIODIC_MANA_FUNNEL
+ &AuraEffect::HandleUnused, // 63 unused (4.3.4) old SPELL_AURA_PERIODIC_MANA_FUNNEL
&AuraEffect::HandleNoImmediateEffect, // 64 SPELL_AURA_PERIODIC_MANA_LEECH implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK
&AuraEffect::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH
@@ -147,7 +148,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
&AuraEffect::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT implemented in Player::RegenerateHealth
&AuraEffect::HandleNoImmediateEffect, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT
- &AuraEffect::HandleUnused, // 90 unused (3.0.8a) old SPELL_AURA_MOD_RESIST_CHANCE
+ &AuraEffect::HandleUnused, // 90 unused (4.3.4) old SPELL_AURA_MOD_RESIST_CHANCE
&AuraEffect::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance
&AuraEffect::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING
&AuraEffect::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE
@@ -176,7 +177,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT
&AuraEffect::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult
&AuraEffect::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus
- &AuraEffect::HandleUnused, //119 unused (3.2.0) old SPELL_AURA_SHARE_PET_TRACKING
+ &AuraEffect::HandleUnused, //119 unused (4.3.4) old SPELL_AURA_SHARE_PET_TRACKING
&AuraEffect::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE
&AuraEffect::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY
&AuraEffect::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT
@@ -198,7 +199,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleModMeleeSpeedPct, //138 SPELL_AURA_MOD_MELEE_HASTE
&AuraEffect::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION
&AuraEffect::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE
- &AuraEffect::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE
+ &AuraEffect::HandleUnused, //141 SPELL_AURA_141
&AuraEffect::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
&AuraEffect::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
&AuraEffect::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
@@ -210,14 +211,14 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
&AuraEffect::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
&AuraEffect::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
- &AuraEffect::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
+ &AuraEffect::HandleUnused, //153 Unused (4.3.4) old SPELL_AURA_SPLIT_DAMAGE_FLAT
&AuraEffect::HandleModStealthLevel, //154 SPELL_AURA_MOD_STEALTH_LEVEL
&AuraEffect::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING
&AuraEffect::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN
&AuraEffect::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI
&AuraEffect::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE
&AuraEffect::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell
- &AuraEffect::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult
+ &AuraEffect::HandleUnused, //160 Unused (4.3.4) old SPELL_AURA_MOD_AOE_AVOIDANCE
&AuraEffect::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT
&AuraEffect::HandleNoImmediateEffect, //162 SPELL_AURA_POWER_BURN implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
@@ -226,19 +227,19 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT
&AuraEffect::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT
&AuraEffect::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
- &AuraEffect::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus
+ &AuraEffect::HandleUnused, //169 Unused (4.3.4) old SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
&AuraEffect::HandleNULL, //170 SPELL_AURA_DETECT_AMORE various spells that change visual of units for aura target (clientside?)
&AuraEffect::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK
&AuraEffect::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
- &AuraEffect::HandleUnused, //173 unused (3.2.0) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
+ &AuraEffect::HandleUnused, //173 unused (4.3.4) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
&AuraEffect::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus
&AuraEffect::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus
&AuraEffect::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end
&AuraEffect::HandleCharmConvert, //177 SPELL_AURA_AOE_CHARM
- &AuraEffect::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult
+ &AuraEffect::HandleUnused, //178 old SPELL_AURA_MOD_DEBUFF_RESISTANCE unused 4.3.4
&AuraEffect::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus
&AuraEffect::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus
- &AuraEffect::HandleUnused, //181 unused (3.2.0) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS
+ &AuraEffect::HandleUnused, //181 unused (4.3.4) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS
&AuraEffect::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT
&AuraEffect::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746 - miscvalue - spell school
&AuraEffect::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
@@ -255,8 +256,8 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist
&AuraEffect::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN - flat mod of spell cooldowns
&AuraEffect::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
- &AuraEffect::HandleUnused, //198 unused (3.2.0) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS
- &AuraEffect::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult
+ &AuraEffect::HandleUnused, //198 unused (4.3.4) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS
+ &AuraEffect::HandleUnused, //199 unused (4.3.4) old SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT
&AuraEffect::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::RewardPlayerAndGroupAtKill
&AuraEffect::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode...
&AuraEffect::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
@@ -269,19 +270,19 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //210 SPELL_AURA_MOD_VEHICLE_SPEED_ALWAYS
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
- &AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
+ &AuraEffect::HandleUnused, //212 Unused (4.3.4) old SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
&AuraEffect::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
&AuraEffect::HandleNULL, //214 Tamed Pet Passive
&AuraEffect::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION
&AuraEffect::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS
- &AuraEffect::HandleNULL, //217 69106 - killing spree helper - unknown use
+ &AuraEffect::HandleModMeleeSpeedPct, //217 SPELL_AURA_MOD_MELEE_HASTE_2
&AuraEffect::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
&AuraEffect::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
&AuraEffect::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT
&AuraEffect::HandleNULL, //221 SPELL_AURA_MOD_DETAUNT
&AuraEffect::HandleUnused, //222 unused (3.2.0) only for spell 44586 that not used in real spell cast
&AuraEffect::HandleNoImmediateEffect, //223 SPELL_AURA_RAID_PROC_FROM_CHARGE
- &AuraEffect::HandleUnused, //224 unused (3.0.8a)
+ &AuraEffect::HandleUnused, //224 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //225 SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE
&AuraEffect::HandleNoImmediateEffect, //226 SPELL_AURA_PERIODIC_DUMMY implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE implemented in AuraEffect::PeriodicTick
@@ -316,28 +317,28 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select
&AuraEffect::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select
&AuraEffect::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL
- &AuraEffect::HandleNoImmediateEffect, //259 SPELL_AURA_MOD_HOT_PCT implemented in Unit::SpellHealingBonus
+ &AuraEffect::HandleUnused, //259 unused (4.3.4) old SPELL_AURA_MOD_HOT_PCT
&AuraEffect::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code
&AuraEffect::HandlePhase, //261 SPELL_AURA_PHASE
&AuraEffect::HandleNoImmediateEffect, //262 SPELL_AURA_ABILITY_IGNORE_AURASTATE implemented in spell::cancast
&AuraEffect::HandleAuraAllowOnlyAbility, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask
&AuraEffect::HandleUnused, //264 unused (3.2.0)
- &AuraEffect::HandleUnused, //265 unused (3.2.0)
- &AuraEffect::HandleUnused, //266 unused (3.2.0)
+ &AuraEffect::HandleUnused, //265 unused (4.3.4)
+ &AuraEffect::HandleUnused, //266 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect
- &AuraEffect::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT
+ &AuraEffect::HandleUnused, //268 unused (4.3.4) old SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT.
&AuraEffect::HandleNoImmediateEffect, //269 SPELL_AURA_MOD_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage
- &AuraEffect::HandleNoImmediateEffect, //270 SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage
+ &AuraEffect::HandleUnused, //270 unused (4.3.4) old SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST
&AuraEffect::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus
&AuraEffect::HandleNoImmediateEffect, //272 SPELL_AURA_IGNORE_MELEE_RESET
&AuraEffect::HandleUnused, //273 clientside
- &AuraEffect::HandleNoImmediateEffect, //274 SPELL_AURA_CONSUME_NO_AMMO implemented in spell::CalculateDamageDoneForAllTargets
+ &AuraEffect::HandleUnused, //274 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select
&AuraEffect::HandleNULL, //276 mod damage % mechanic?
- &AuraEffect::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap
+ &AuraEffect::HandleUnused, //277 unused (4.3.4) old SPELL_AURA_MOD_MAX_AFFECTED_TARGETS
&AuraEffect::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon
&AuraEffect::HandleNoImmediateEffect, //279 SPELL_AURA_INITIALIZE_IMAGES
- &AuraEffect::HandleNoImmediateEffect, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT
+ &AuraEffect::HandleUnused, //280 unused (4.3.4) old SPELL_AURA_MOD_ARMOR_PENETRATION_PCT
&AuraEffect::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor
&AuraEffect::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
&AuraEffect::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
@@ -352,28 +353,82 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleAuraOpenStable, //292 SPELL_AURA_OPEN_STABLE
&AuraEffect::HandleAuraOverrideSpells, //293 SPELL_AURA_OVERRIDE_SPELLS auras which probably add set of abilities to their target based on it's miscvalue
&AuraEffect::HandleNoImmediateEffect, //294 SPELL_AURA_PREVENT_REGENERATE_POWER implemented in Player::Regenerate(Powers power)
- &AuraEffect::HandleUnused, //295 0 spells in 3.3.5
+ &AuraEffect::HandleUnused, //295 unused (4.3.4)
&AuraEffect::HandleAuraSetVehicle, //296 SPELL_AURA_SET_VEHICLE_ID sets vehicle on target
&AuraEffect::HandleNULL, //297 Spirit Burst spells
&AuraEffect::HandleNULL, //298 70569 - Strangulating, maybe prevents talk or cast
- &AuraEffect::HandleUnused, //299 unused
+ &AuraEffect::HandleUnused, //299 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //300 SPELL_AURA_SHARE_DAMAGE_PCT implemented in Unit::DealDamage
&AuraEffect::HandleNoImmediateEffect, //301 SPELL_AURA_SCHOOL_HEAL_ABSORB implemented in Unit::CalcHealAbsorb
- &AuraEffect::HandleUnused, //302 0 spells in 3.3.5
+ &AuraEffect::HandleUnused, //302 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //303 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
&AuraEffect::HandleAuraModFakeInebriation, //304 SPELL_AURA_MOD_DRUNK
&AuraEffect::HandleAuraModIncreaseSpeed, //305 SPELL_AURA_MOD_MINIMUM_SPEED
- &AuraEffect::HandleUnused, //306 0 spells in 3.3.5
- &AuraEffect::HandleUnused, //307 0 spells in 3.3.5
+ &AuraEffect::HandleUnused, //306 unused (4.3.4)
+ &AuraEffect::HandleUnused, //307 unused (4.3.4)
&AuraEffect::HandleNULL, //308 new aura for hunter traps
- &AuraEffect::HandleUnused, //309 0 spells in 3.3.5
+ &AuraEffect::HandleUnused, //309 unused (4.3.4)
&AuraEffect::HandleNoImmediateEffect, //310 SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE implemented in Spell::CalculateDamageDone
&AuraEffect::HandleNULL, //311 0 spells in 3.3.5
&AuraEffect::HandleNULL, //312 0 spells in 3.3.5
- &AuraEffect::HandleUnused, //313 0 spells in 3.3.5
+ &AuraEffect::HandleUnused, //313 unused (4.3.4)
&AuraEffect::HandlePreventResurrection, //314 SPELL_AURA_PREVENT_RESURRECTION todo
&AuraEffect::HandleNoImmediateEffect, //315 SPELL_AURA_UNDERWATER_WALKING todo
- &AuraEffect::HandleNoImmediateEffect, //316 SPELL_AURA_PERIODIC_HASTE implemented in AuraEffect::CalculatePeriodic
+ &AuraEffect::HandleNoImmediateEffect, //316 unused (4.3.4) old SPELL_AURA_PERIODIC_HASTE
+ &AuraEffect::HandleNULL, //317 SPELL_AURA_MOD_SPELL_POWER_PCT
+ &AuraEffect::HandleMastery, //318 SPELL_AURA_MASTERY
+ &AuraEffect::HandleModMeleeSpeedPct, //319 SPELL_AURA_MOD_MELEE_HASTE_3
+ &AuraEffect::HandleAuraModRangedHaste, //320 SPELL_AURA_MOD_RANGED_HASTE_2
+ &AuraEffect::HandleNULL, //321 SPELL_AURA_321
+ &AuraEffect::HandleNULL, //322 SPELL_AURA_INTERFERE_TARGETTING
+ &AuraEffect::HandleUnused, //323 unused (4.3.4)
+ &AuraEffect::HandleNULL, //324 SPELL_AURA_324
+ &AuraEffect::HandleUnused, //325 unused (4.3.4)
+ &AuraEffect::HandlePhaseGroup, //326 SPELL_AURA_PHASE_GROUP
+ &AuraEffect::HandleUnused, //327 unused (4.3.4)
+ &AuraEffect::HandleNoImmediateEffect, //328 SPELL_AURA_PROC_ON_POWER_AMOUNT implemented in Unit::HandleAuraProcOnPowerAmount
+ &AuraEffect::HandleNULL, //329 SPELL_AURA_MOD_RUNE_REGEN_SPEED
+ &AuraEffect::HandleNoImmediateEffect, //330 SPELL_AURA_CAST_WHILE_WALKING
+ &AuraEffect::HandleAuraForceWeather, //331 SPELL_AURA_FORCE_WEATHER
+ &AuraEffect::HandleNoImmediateEffect, //332 SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS implemented in WorldSession::HandleCastSpellOpcode
+ &AuraEffect::HandleNoImmediateEffect, //333 SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2 implemented in WorldSession::HandleCastSpellOpcode
+ &AuraEffect::HandleNULL, //334 SPELL_AURA_MOD_BLIND
+ &AuraEffect::HandleNULL, //335 SPELL_AURA_335
+ &AuraEffect::HandleNULL, //336 SPELL_AURA_MOD_FLYING_RESTRICTIONS
+ &AuraEffect::HandleNoImmediateEffect, //337 SPELL_AURA_MOD_VENDOR_ITEMS_PRICES
+ &AuraEffect::HandleNoImmediateEffect, //338 SPELL_AURA_MOD_DURABILITY_LOSS
+ &AuraEffect::HandleNULL, //339 SPELL_AURA_INCREASE_SKILL_GAIN_CHANCE
+ &AuraEffect::HandleNULL, //340 SPELL_AURA_MOD_RESURRECTED_HEALTH_BY_GUILD_MEMBER
+ &AuraEffect::HandleNULL, //341 SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN
+ &AuraEffect::HandleModMeleeRangedSpeedPct, //342 SPELL_AURA_MOD_MELEE_RANGED_HASTE_2
+ &AuraEffect::HandleNULL, //343 SPELL_AURA_343
+ &AuraEffect::HandleNULL, //344 SPELL_AURA_MOD_AUTOATTACK_DAMAGE
+ &AuraEffect::HandleNoImmediateEffect, //345 SPELL_AURA_BYPASS_ARMOR_FOR_CASTER
+ &AuraEffect::HandleEnableAltPower, //346 SPELL_AURA_ENABLE_ALT_POWER
+ &AuraEffect::HandleNULL, //347 SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE
+ &AuraEffect::HandleNoImmediateEffect, //348 SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT implemented in WorldSession::HandleLootMoneyOpcode
+ &AuraEffect::HandleNoImmediateEffect, //349 SPELL_AURA_MOD_CURRENCY_GAIN implemented in Player::ModifyCurrency
+ &AuraEffect::HandleNULL, //350 SPELL_AURA_MOD_GATHERING_ITEMS_GAINED_PERCENT
+ &AuraEffect::HandleNULL, //351 SPELL_AURA_351
+ &AuraEffect::HandleNULL, //352 SPELL_AURA_352
+ &AuraEffect::HandleNULL, //353 SPELL_AURA_MOD_CAMOUFLAGE
+ &AuraEffect::HandleNULL, //354 SPELL_AURA_354
+ &AuraEffect::HandleUnused, //355 unused (4.3.4)
+ &AuraEffect::HandleNULL, //356 SPELL_AURA_356
+ &AuraEffect::HandleNULL, //357 SPELL_AURA_ENABLE_BOSS1_UNIT_FRAME
+ &AuraEffect::HandleNULL, //358 SPELL_AURA_358
+ &AuraEffect::HandleNULL, //359 SPELL_AURA_359
+ &AuraEffect::HandleNULL, //360 SPELL_AURA_PROC_TRIGGER_SPELL_COPY
+ &AuraEffect::HandleNULL, //361 SPELL_AURA_PROC_TRIGGER_SPELL_2 implemented in Unit::ProcDamageAndSpellFor
+ &AuraEffect::HandleUnused, //362 unused (4.3.4)
+ &AuraEffect::HandleNULL, //363 SPELL_AURA_MOD_NEXT_SPELL
+ &AuraEffect::HandleUnused, //364 unused (4.3.4)
+ &AuraEffect::HandleNULL, //365 SPELL_AURA_MAX_FAR_CLIP_PLANE
+ &AuraEffect::HandleNULL, //366 SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT
+ &AuraEffect::HandleNULL, //367 SPELL_AURA_367
+ &AuraEffect::HandleUnused, //368 unused (4.3.4)
+ &AuraEffect::HandleNULL, //369 SPELL_AURA_ENABLE_POWER_BAR_TIMER
+ &AuraEffect::HandleNULL, //370 SPELL_AURA_SET_FAIR_FAR_CLIP
};
AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* caster):
@@ -419,7 +474,12 @@ void AuraEffect::GetApplicationList(std::list<AuraApplication*> & applicationLis
int32 AuraEffect::CalculateAmount(Unit* caster)
{
// default amount calculation
- int32 amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount, NULL);
+ int32 amount = 0;
+
+ if (!(m_spellInfo->AttributesEx8 & SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(m_spellInfo->Effects[m_effIndex].BonusMultiplier, 0.0f))
+ amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit());
+ else if (caster && caster->GetTypeId() == TYPEID_PLAYER)
+ amount = int32(caster->GetFloatValue(PLAYER_MASTERY) * m_spellInfo->Effects[m_effIndex].BonusMultiplier);
// check item enchant aura cast
if (!amount && caster)
@@ -469,9 +529,9 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
Unit::AuraEffectList const& overrideClassScripts = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (Unit::AuraEffectList::const_iterator itr = overrideClassScripts.begin(); itr != overrideClassScripts.end(); ++itr)
{
- if ((*itr)->IsAffectedOnSpell(m_spellInfo))
+ if ((*itr)->IsAffectingSpell(m_spellInfo))
{
- // Glyph of Fear, Glyph of Frost nova and similar auras
+ // Glyph of Frost nova and similar auras
if ((*itr)->GetMiscValue() == 7801)
{
AddPct(amount, (*itr)->GetAmount());
@@ -485,6 +545,45 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
case SPELL_AURA_MANA_SHIELD:
m_canBeRecalculated = false;
break;
+ case SPELL_AURA_MOUNTED:
+ if (MountCapabilityEntry const* mountCapability = GetBase()->GetUnitOwner()->GetMountCapability(uint32(GetMiscValueB())))
+ {
+ amount = mountCapability->Id;
+ m_canBeRecalculated = false;
+ }
+ break;
+ case SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE:
+ {
+ if (caster)
+ {
+ // if Level <= 70 resist = player level
+ int32 resist = caster->getLevel();
+
+ if (resist > 70 && resist < 81)
+ resist += (resist - 70) * 5;
+ else if (resist > 80)
+ resist += ((resist-70) * 5 + (resist - 80) * 7);
+
+ switch (GetId())
+ {
+ case 20043: // Aspect of the Wild
+ case 8185: // Elemental Resistance
+ case 19891: // Resistance Aura
+ case 79106: // Shadow Protection
+ case 79107: // Shadow Protection
+ amount = resist;
+ break;
+ case 79060: // Mark of the Wild
+ case 79061: // Mark of the Wild
+ case 79062: // Blessing of Kings
+ case 79063: // Blessing of Kings
+ case 90363: // Embrace of the Shale Spider
+ amount = resist / 2;
+ break;
+ }
+ break;
+ }
+ }
default:
break;
}
@@ -494,7 +593,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
return amount;
}
-void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
+void AuraEffect::CalculatePeriodic(Unit* caster, bool resetPeriodicTimer /*= true*/, bool load /*= false*/)
{
m_amplitude = m_spellInfo->Effects[m_effIndex].Amplitude;
@@ -545,8 +644,7 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
caster->ModSpellCastTime(m_spellInfo, m_amplitude);
}
- // and periodic time of auras affected by SPELL_AURA_PERIODIC_HASTE
- else if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellInfo) || m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
+ else if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
m_amplitude = int32(m_amplitude * caster->GetFloatValue(UNIT_MOD_CAST_SPEED));
}
}
@@ -564,9 +662,6 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
// reset periodic timer on aura create or on reapply when aura isn't dot
// possibly we should not reset periodic timers only when aura is triggered by proc
// or maybe there's a spell attribute somewhere
- bool resetPeriodicTimer = create
- || ((GetAuraType() != SPELL_AURA_PERIODIC_DAMAGE) && (GetAuraType() != SPELL_AURA_PERIODIC_DAMAGE_PERCENT));
-
if (resetPeriodicTimer)
{
m_periodicTimer = 0;
@@ -795,6 +890,16 @@ void AuraEffect::UpdatePeriodic(Unit* caster)
case 49472: // Drink Coffee
case 57073:
case 61830:
+ case 69176:
+ case 72623:
+ case 80166:
+ case 80167:
+ case 87958:
+ case 87959:
+ case 92736:
+ case 92797:
+ case 92800:
+ case 92803:
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
// Get SPELL_AURA_MOD_POWER_REGEN aura from spell
@@ -894,17 +999,11 @@ void AuraEffect::UpdatePeriodic(Unit* caster)
bool AuraEffect::CanPeriodicTickCrit(Unit const* caster) const
{
ASSERT(caster);
- if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_ABILITY_PERIODIC_CRIT, m_spellInfo))
- return true;
- // Rupture - since 3.3.3 can crit
- if (m_spellInfo->SpellIconID == 500 && m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
- return true;
-
- return false;
+ return caster->HasAuraTypeWithAffectMask(SPELL_AURA_ABILITY_PERIODIC_CRIT, m_spellInfo);
}
-bool AuraEffect::IsAffectedOnSpell(SpellInfo const* spell) const
+bool AuraEffect::IsAffectingSpell(SpellInfo const* spell) const
{
if (!spell)
return false;
@@ -1030,14 +1129,11 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
{
uint32 spellId = 0;
uint32 spellId2 = 0;
- //uint32 spellId3 = 0;
- uint32 HotWSpellId = 0;
switch (GetMiscValue())
{
case FORM_CAT:
spellId = 3025;
- HotWSpellId = 24900;
break;
case FORM_TREE:
spellId = 34123;
@@ -1051,12 +1147,6 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
case FORM_BEAR:
spellId = 1178;
spellId2 = 21178;
- HotWSpellId = 24899;
- break;
- case FORM_DIREBEAR:
- spellId = 9635;
- spellId2 = 21178;
- HotWSpellId = 24899;
break;
case FORM_BATTLESTANCE:
spellId = 21156;
@@ -1069,7 +1159,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
break;
case FORM_MOONKIN:
spellId = 24905;
- spellId2 = 69366;
+ spellId2 = 24907;
break;
case FORM_FLIGHT:
spellId = 33948;
@@ -1089,7 +1179,6 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
break;
case FORM_SHADOW:
spellId = 49868;
- spellId2 = 71167;
break;
case FORM_GHOSTWOLF:
spellId = 67116;
@@ -1123,7 +1212,9 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (target->GetTypeId() == TYPEID_PLAYER)
{
- const PlayerSpellMap& sp_list = target->ToPlayer()->GetSpellMap();
+ Player* plrTarget = target->ToPlayer();
+
+ PlayerSpellMap const& sp_list = plrTarget->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
@@ -1136,6 +1227,9 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR0_PASSIVE | SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
continue;
+ if ((spellInfo->AttributesEx8 & SPELL_ATTR8_MASTERY_SPECIALIZATION) && !plrTarget->IsCurrentSpecMasterySpell(spellInfo))
+ continue;
+
if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
target->CastSpell(target, itr->first, true, NULL, this);
}
@@ -1143,49 +1237,52 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
// Also do it for Glyphs
for (uint32 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
{
- if (uint32 glyphId = target->ToPlayer()->GetGlyph(i))
+ if (uint32 glyphId = plrTarget->GetGlyph(plrTarget->GetActiveSpec(), i))
{
if (GlyphPropertiesEntry const* glyph = sGlyphPropertiesStore.LookupEntry(glyphId))
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(glyph->SpellId);
if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR0_PASSIVE | SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
continue;
- if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
+
+ if (spellInfo->Stances & (1 << (GetMiscValue() - 1)))
target->CastSpell(target, glyph->SpellId, true, NULL, this);
}
}
}
// Leader of the Pack
- if (target->ToPlayer()->HasSpell(17007))
+ if (plrTarget->HasSpell(17007))
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(24932);
- if (spellInfo && spellInfo->Stances & (1<<(GetMiscValue()-1)))
+ if (spellInfo && spellInfo->Stances & (1 << (GetMiscValue() -1)))
target->CastSpell(target, 24932, true, NULL, this);
}
- // Improved Barkskin - apply/remove armor bonus due to shapeshift
- if (target->ToPlayer()->HasSpell(63410) || target->ToPlayer()->HasSpell(63411))
- {
- target->RemoveAurasDueToSpell(66530);
- if (GetMiscValue() == FORM_TRAVEL || GetMiscValue() == FORM_NONE) // "while in Travel Form or while not shapeshifted"
- target->CastSpell(target, 66530, true);
- }
+
// Heart of the Wild
- if (HotWSpellId)
- { // hacky, but the only way as spell family is not SPELLFAMILY_DRUID
- Unit::AuraEffectList const& mModTotalStatPct = target->GetAuraEffectsByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
- for (Unit::AuraEffectList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
- {
- // Heart of the Wild
- if ((*i)->GetSpellInfo()->SpellIconID == 240 && (*i)->GetMiscValue() == 3)
- {
- int32 HotWMod = (*i)->GetAmount() / 2; // For each 2% Intelligence, you get 1% stamina and 1% attack power.
+ if (AuraEffect const* heartOfTheWild = target->GetAuraEffectOfRankedSpell(17003, EFFECT_0))
+ {
+ uint32 heartOfTheWildSpellId = 0;
+ int32 heartOfTheWildAmount = 0;
- target->CastCustomSpell(target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
+ switch (GetMiscValue())
+ {
+ case FORM_CAT:
+ heartOfTheWildSpellId = 24900;
+ heartOfTheWildAmount = heartOfTheWild->GetSpellInfo()->Effects[EFFECT_1].CalcValue();
+ break;
+ case FORM_BEAR:
+ heartOfTheWildSpellId = 24899;
+ heartOfTheWildAmount = heartOfTheWild->GetSpellInfo()->Effects[EFFECT_2].CalcValue();
+ break;
+ default:
break;
- }
}
+
+ if (heartOfTheWildSpellId)
+ target->CastCustomSpell(target, heartOfTheWildSpellId, &heartOfTheWildAmount, NULL, NULL, true, NULL, this);
}
+
switch (GetMiscValue())
{
case FORM_CAT:
@@ -1193,7 +1290,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (target->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_DRUID, 0, 0x10000000, 0))
target->CastSpell(target, 62071, true);
// Nurturing Instinct
- if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT, SPELLFAMILY_DRUID, 2254, 0))
+ if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT, SPELLFAMILY_DRUID, 2254, EFFECT_0))
{
uint32 spellId3 = 0;
switch (aurEff->GetId())
@@ -1208,43 +1305,36 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
target->CastSpell(target, spellId3, true, NULL, this);
}
// Master Shapeshifter - Cat
- if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
+ if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_HEALING_DONE_PERCENT, SPELLFAMILY_GENERIC, 2851, EFFECT_0))
{
int32 bp = aurEff->GetAmount();
target->CastCustomSpell(target, 48420, &bp, NULL, NULL, true);
}
- break;
- case FORM_DIREBEAR:
+ break;
case FORM_BEAR:
// Master Shapeshifter - Bear
- if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
+ if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_HEALING_DONE_PERCENT, SPELLFAMILY_GENERIC, 2851, EFFECT_0))
{
int32 bp = aurEff->GetAmount();
target->CastCustomSpell(target, 48418, &bp, NULL, NULL, true);
}
// Survival of the Fittest
- if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DRUID, 961, 0))
+ if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DRUID, 961, EFFECT_0))
{
- int32 bp = aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue();
+ int32 bp = aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster());
target->CastCustomSpell(target, 62069, &bp, NULL, NULL, true, 0, this);
}
- break;
+ break;
case FORM_MOONKIN:
// Master Shapeshifter - Moonkin
- if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
+ if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_HEALING_DONE_PERCENT, SPELLFAMILY_GENERIC, 2851, EFFECT_0))
{
int32 bp = aurEff->GetAmount();
target->CastCustomSpell(target, 48421, &bp, NULL, NULL, true);
}
- break;
- // Master Shapeshifter - Tree of Life
- case FORM_TREE:
- if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
- {
- int32 bp = aurEff->GetAmount();
- target->CastCustomSpell(target, 48422, &bp, NULL, NULL, true);
- }
- break;
+ break;
+ default:
+ break;
}
}
}
@@ -1255,17 +1345,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (spellId2)
target->RemoveOwnedAura(spellId2, target->GetGUID());
- // Improved Barkskin - apply/remove armor bonus due to shapeshift
- if (Player* player=target->ToPlayer())
- {
- if (player->HasSpell(63410) || player->HasSpell(63411))
- {
- target->RemoveAurasDueToSpell(66530);
- target->CastSpell(target, 66530, true);
- }
- }
-
- const Unit::AuraEffectList& shapeshifts = target->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
+ Unit::AuraEffectList const& shapeshifts = target->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
AuraEffect* newAura = NULL;
// Iterate through all the shapeshift auras that the target has, if there is another aura with SPELL_AURA_MOD_SHAPESHIFT, then this aura is being removed due to that one being applied
for (Unit::AuraEffectList::const_iterator itr = shapeshifts.begin(); itr != shapeshifts.end(); ++itr)
@@ -1276,11 +1356,12 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
break;
}
}
+
Unit::AuraApplicationMap& tAuras = target->GetAppliedAuras();
for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
{
// Use the new aura to see on what stance the target will be
- uint32 newStance = (1<<((newAura ? newAura->GetMiscValue() : 0)-1));
+ uint32 newStance = (1 << ((newAura ? newAura->GetMiscValue() : 0) -1));
// If the stances are not compatible with the spell, remove it
if (itr->second->GetBase()->IsRemovedOnShapeLost(target) && !(itr->second->GetBase()->GetSpellInfo()->Stances & newStance))
@@ -1527,37 +1608,40 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app
Unit* target = aurApp->GetTarget();
- // no-phase is also phase state so same code for apply and remove
- uint32 newPhase = 0;
- Unit::AuraEffectList const& phases = target->GetAuraEffectsByType(SPELL_AURA_PHASE);
- if (!phases.empty())
- for (Unit::AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
- newPhase |= (*itr)->GetMiscValue();
+ std::set<uint32> const& oldPhases = target->GetPhases();
+ target->SetInPhase(GetMiscValueB(), false, apply);
+
+ // call functions which may have additional effects after chainging state of unit
+ // phase auras normally not expected at BG but anyway better check
+ if (apply)
+ {
+ // drop flag at invisibiliy in bg
+ target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
+ }
if (Player* player = target->ToPlayer())
{
- if (!newPhase)
- newPhase = PHASEMASK_NORMAL;
+ if (player->IsInWorld())
+ player->GetMap()->SendUpdateTransportVisibility(player, oldPhases);
+ player->UpdatePhasing();
+ }
+
+ // need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases)
+ if (target->IsVisible())
+ target->UpdateObjectVisibility();
+}
- // GM-mode have mask 0xFFFFFFFF
- if (player->IsGameMaster())
- newPhase = 0xFFFFFFFF;
+void AuraEffect::HandlePhaseGroup(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & AURA_EFFECT_HANDLE_REAL))
+ return;
- player->SetPhaseMask(newPhase, false);
- player->GetSession()->SendSetPhaseShift(newPhase);
- }
- else
- {
- if (!newPhase)
- {
- newPhase = PHASEMASK_NORMAL;
- if (Creature* creature = target->ToCreature())
- if (CreatureData const* data = sObjectMgr->GetCreatureData(creature->GetDBTableGUIDLow()))
- newPhase = data->phaseMask;
- }
+ Unit* target = aurApp->GetTarget();
- target->SetPhaseMask(newPhase, false);
- }
+ std::set<uint32> const& oldPhases = target->GetPhases();
+ std::set<uint32> const& phases = GetPhasesForGroup(GetMiscValueB());
+ for (auto phase : phases)
+ target->SetInPhase(phase, false, apply);
// call functions which may have additional effects after chainging state of unit
// phase auras normally not expected at BG but anyway better check
@@ -1567,6 +1651,13 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
}
+ if (Player* player = target->ToPlayer())
+ {
+ if (player->IsInWorld())
+ player->GetMap()->SendUpdateTransportVisibility(player, oldPhases);
+ player->UpdatePhasing();
+ }
+
// need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases)
if (target->IsVisible())
target->UpdateObjectVisibility();
@@ -1595,7 +1686,6 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
break;
case FORM_BEAR: // 0x05
- case FORM_DIREBEAR: // 0x08
case FORM_BATTLESTANCE: // 0x11
case FORM_DEFENSIVESTANCE: // 0x12
@@ -1645,7 +1735,6 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
case FORM_TRAVEL:
case FORM_AQUA:
case FORM_BEAR:
- case FORM_DIREBEAR:
case FORM_FLIGHT_EPIC:
case FORM_FLIGHT:
case FORM_MOONKIN:
@@ -1671,47 +1760,26 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (PowerType != POWER_MANA)
{
- uint32 oldPower = target->GetPower(PowerType);
+ int32 oldPower = target->GetPower(PowerType);
// reset power to default values only at power change
if (target->getPowerType() != PowerType)
target->setPowerType(PowerType);
- switch (form)
+ if (form == FORM_CAT || form == FORM_BEAR)
{
- case FORM_CAT:
- case FORM_BEAR:
- case FORM_DIREBEAR:
- {
- // get furor proc chance
- uint32 FurorChance = 0;
- if (AuraEffect const* dummy = target->GetDummyAuraEffect(SPELLFAMILY_DRUID, 238, 0))
- FurorChance = std::max(dummy->GetAmount(), 0);
+ // get furor proc chance
+ int32 FurorChance = 0;
+ if (AuraEffect const* dummy = target->GetDummyAuraEffect(SPELLFAMILY_DRUID, 238, 0))
+ FurorChance = std::max(dummy->GetAmount(), 0);
- switch (GetMiscValue())
- {
- case FORM_CAT:
- {
- int32 basePoints = int32(std::min(oldPower, FurorChance));
- target->SetPower(POWER_ENERGY, 0);
- target->CastCustomSpell(target, 17099, &basePoints, NULL, NULL, true, NULL, this);
- break;
- }
- case FORM_BEAR:
- case FORM_DIREBEAR:
- if (urand(0, 99) < FurorChance)
- target->CastSpell(target, 17057, true);
- break;
- default:
- {
- uint32 newEnergy = std::min(target->GetPower(POWER_ENERGY), FurorChance);
- target->SetPower(POWER_ENERGY, newEnergy);
- break;
- }
- }
- break;
+ if (form == FORM_CAT)
+ {
+ int32 basePoints = std::min<int32>(oldPower, FurorChance);
+ target->SetPower(POWER_ENERGY, 0);
+ target->CastCustomSpell(target, 17099, &basePoints, NULL, NULL, true, NULL, this);
}
- default:
- break;
+ else if (roll_chance_i(FurorChance))
+ target->CastSpell(target, 17057, true);
}
}
// stop handling the effect if it was removed by linked event
@@ -1748,7 +1816,6 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
{
// Nordrassil Harness - bonus
case FORM_BEAR:
- case FORM_DIREBEAR:
case FORM_CAT:
if (AuraEffect* dummy = target->GetAuraEffect(37315, 0))
target->CastSpell(target, 37316, true, NULL, dummy);
@@ -1762,7 +1829,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
case FORM_DEFENSIVESTANCE:
case FORM_BERSERKERSTANCE:
{
- uint32 Rage_val = 0;
+ int32 Rage_val = 0;
// Defensive Tactics
if (form == FORM_DEFENSIVESTANCE)
{
@@ -1811,9 +1878,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (!target->CanUseAttackType(BASE_ATTACK))
{
if (Item* pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND))
- {
target->ToPlayer()->_ApplyWeaponDamage(EQUIPMENT_SLOT_MAINHAND, pItem->GetTemplate(), NULL, apply);
- }
}
}
@@ -1823,10 +1888,10 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (target->GetTypeId() == TYPEID_PLAYER)
{
- SpellShapeshiftEntry const* shapeInfo = sSpellShapeshiftStore.LookupEntry(form);
+ SpellShapeshiftFormEntry const* shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form);
ASSERT(shapeInfo);
// Learn spells for shapeshift form - no need to send action bars or add spells to spellbook
- for (uint8 i = 0; i<MAX_SHAPESHIFT_SPELLS; ++i)
+ for (uint8 i = 0; i < MAX_SHAPESHIFT_SPELLS; ++i)
{
if (!shapeInfo->stanceSpell[i])
continue;
@@ -2110,9 +2175,7 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
if (apply)
{
/*
- WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
- data << target->GetGUID();
- data << uint8(0);
+ WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 0);
target->SendMessageToSet(&data, true);
*/
@@ -2158,9 +2221,7 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
else
{
/*
- WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
- data << target->GetGUID();
- data << uint8(1);
+ WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 0);
target->SendMessageToSet(&data, true);
*/
@@ -2204,8 +2265,8 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
AuraType type = GetAuraType();
- //Prevent handling aura twice
- if ((apply) ? target->GetAuraEffectsByType(type).size() > 1 : target->HasAuraType(type))
+ // Prevent handling aura twice
+ if (apply ? target->GetAuraEffectsByType(type).size() > 1 : target->HasAuraType(type))
return;
uint32 field, flag, slot;
@@ -2476,17 +2537,18 @@ void AuraEffect::HandleAuraModSkill(AuraApplication const* aurApp, uint8 mode, b
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_SKILL)))
return;
- Unit* target = aurApp->GetTarget();
- if (target->GetTypeId() != TYPEID_PLAYER)
+ Player* target = aurApp->GetTarget()->ToPlayer();
+ if (!target)
return;
uint32 prot = GetMiscValue();
int32 points = GetAmount();
- target->ToPlayer()->ModifySkillBonus(prot, ((apply) ? points: -points), GetAuraType() == SPELL_AURA_MOD_SKILL_TALENT);
if (prot == SKILL_DEFENSE)
- target->ToPlayer()->UpdateDefenseBonusesMod();
+ return;
+
+ target->ModifySkillBonus(prot, (apply ? points : -points), GetAuraType() == SPELL_AURA_MOD_SKILL_TALENT);
}
/****************************/
@@ -2530,6 +2592,11 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo
}
target->Mount(displayId, vehicleId, creatureEntry);
+
+ // cast speed aura
+ if (mode & AURA_EFFECT_HANDLE_REAL)
+ if (MountCapabilityEntry const* mountCapability = sMountCapabilityStore.LookupEntry(GetAmount()))
+ target->CastSpell(target, mountCapability->SpeedModSpell, true);
}
else
{
@@ -2538,7 +2605,13 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo
// need to remove ALL arura related to mounts, this will stop client crash with broom stick
// and never endless flying after using Headless Horseman's Mount
if (mode & AURA_EFFECT_HANDLE_REAL)
+ {
target->RemoveAurasByType(SPELL_AURA_MOUNTED);
+
+ // remove speed aura
+ if (MountCapabilityEntry const* mountCapability = sMountCapabilityStore.LookupEntry(GetAmount()))
+ target->RemoveAurasDueToSpell(mountCapability->SpeedModSpell, target->GetGUID());
+ }
}
}
@@ -3704,12 +3777,6 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
- if (GetMiscValue() < -1 || GetMiscValue() > 4)
- {
- TC_LOG_ERROR("spells", "WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
- return;
- }
-
Unit* target = aurApp->GetTarget();
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, true, -1);
if (abs(spellGroupVal) >= abs(GetAmount()))
@@ -3734,7 +3801,7 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
{
- if (GetMiscValue() == i || GetMiscValue() == -1)
+ if (GetMiscValueB() & 1 << i || !GetMiscValueB()) // 0 is also used for all stats
{
int32 spellGroupVal2 = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, true, i);
if (abs(spellGroupVal2) >= abs(GetAmount()))
@@ -3755,7 +3822,7 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
// recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_UNK4 0x00000010 flag)
// this check is total bullshit i think
- if (GetMiscValue() == STAT_STAMINA && (m_spellInfo->Attributes & SPELL_ATTR0_ABILITY))
+ if (GetMiscValueB() & 1 << STAT_STAMINA && (m_spellInfo->Attributes & SPELL_ATTR0_ABILITY))
target->SetHealth(std::max<uint32>(uint32(healthPct * target->GetMaxHealth() * 0.01f), (alive ? 1 : 0)));
}
@@ -3811,7 +3878,7 @@ void AuraEffect::HandleModPowerRegen(AuraApplication const* aurApp, uint8 mode,
// Update manaregen value
if (GetMiscValue() == POWER_MANA)
target->ToPlayer()->UpdateManaRegen();
- else if (GetMiscValue() == POWER_RUNE)
+ else if (GetMiscValue() == POWER_RUNES)
target->ToPlayer()->UpdateRuneRegen(RuneType(GetMiscValueB()));
// other powers are not immediate effects - implemented in Player::Regenerate, Creature::Regenerate
}
@@ -4132,6 +4199,7 @@ void AuraEffect::HandleModMeleeRangedSpeedPct(AuraApplication const* aurApp, uin
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
+ //! ToDo: Haste auras with the same handler _CAN'T_ stack together
Unit* target = aurApp->GetTarget();
target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply);
@@ -4178,6 +4246,7 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
+ //! ToDo: Haste auras with the same handler _CAN'T_ stack together
Unit* target = aurApp->GetTarget();
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_MELEE_HASTE);
if (abs(spellGroupVal) >= abs(GetAmount()))
@@ -4197,24 +4266,12 @@ void AuraEffect::HandleAuraModRangedHaste(AuraApplication const* aurApp, uint8 m
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
+ //! ToDo: Haste auras with the same handler _CAN'T_ stack together
Unit* target = aurApp->GetTarget();
target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float)GetAmount(), apply);
}
-void AuraEffect::HandleRangedAmmoHaste(AuraApplication const* aurApp, uint8 mode, bool apply) const
-{
- if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
- return;
-
- Unit* target = aurApp->GetTarget();
-
- if (target->GetTypeId() != TYPEID_PLAYER)
- return;
-
- target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float)GetAmount(), apply);
-}
-
/********************************/
/*** COMBAT RATING ***/
/********************************/
@@ -4302,23 +4359,6 @@ void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* au
target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()), apply);
}
-void AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
-{
- if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
- return;
-
- Unit* target = aurApp->GetTarget();
-
- // Recalculate bonus
- if (target->GetTypeId() == TYPEID_PLAYER && !(target->getClassMask() & CLASSMASK_WAND_USERS))
- target->ToPlayer()->UpdateAttackPowerAndDamage(true);
-}
-
-void AuraEffect::HandleAuraModAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
-{
- HandleAuraModAttackPowerOfArmor(aurApp, mode, apply);
-}
-
void AuraEffect::HandleAuraModAttackPowerOfArmor(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
@@ -4652,22 +4692,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
}
break;
}
- case 55198: // Tidal Force
- {
- target->CastSpell(target, 55166, true, NULL, this);
- // set 3 stacks and 3 charges (to make all auras not disappear at once)
- Aura* owner_aura = target->GetAura(55166, GetCasterGUID());
- if (owner_aura)
- {
- // This aura lasts 2 sec, need this hack to properly proc spells
- /// @todo drop aura charges for ApplySpellMod in ProcDamageAndSpell
- GetBase()->SetDuration(owner_aura->GetDuration());
- // Make aura be not charged-this prevents removing charge on not crit spells
- owner_aura->SetCharges(0);
- owner_aura->SetStackAmount(owner_aura->GetSpellInfo()->StackAmount);
- }
- break;
- }
case 39850: // Rocket Blast
if (roll_chance_i(20)) // backfire stun
target->CastSpell(target, 51581, true, NULL, this);
@@ -4693,10 +4717,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
if (caster)
target->GetMotionMaster()->MoveFall();
break;
- case 46699: // Requires No Ammo
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->ToPlayer()->RemoveAmmo(); // not use ammo and not allow use
- break;
case 52916: // Honor Among Thieves
if (target->GetTypeId() == TYPEID_PLAYER)
if (Unit* spellTarget = ObjectAccessor::GetUnit(*target, target->ToPlayer()->GetComboTarget()))
@@ -4789,8 +4809,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
case 60244: // Blood Parrot Despawn Aura
target->CastSpell((Unit*)NULL, GetAmount(), true, NULL, this);
break;
- case 58600: // Restricted Flight Area
- case 58730: // Restricted Flight Area
+ case 91604: // Restricted Flight Area
if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
target->CastSpell(target, 58601, true);
break;
@@ -4998,15 +5017,6 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod
if (!plCaster->isHonorOrXPTarget(target) ||
(target->GetTypeId() == TYPEID_UNIT && !target->ToCreature()->isTappedBy(plCaster)))
return;
-
- // If this is Drain Soul, check for Glyph of Drain Soul
- if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000))
- {
- // Glyph of Drain Soul - chance to create an additional Soul Shard
- if (AuraEffect* aur = caster->GetAuraEffect(58070, 0))
- if (roll_chance_i(aur->GetMiscValue()))
- caster->CastSpell(caster, 58068, true, 0, aur); // We _could_ simply do ++count here, but Blizz does it this way :)
- }
}
//Adding items
@@ -5290,7 +5300,7 @@ void AuraEffect::HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode,
Unit* target = aurApp->GetTarget();
- if (target->GetTypeId() != TYPEID_PLAYER || !target->IsInWorld())
+ if (!target->IsInWorld())
return;
uint32 vehicleId = GetMiscValue();
@@ -5303,6 +5313,9 @@ void AuraEffect::HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode,
else if (target->GetVehicleKit())
target->RemoveVehicleKit();
+ if (target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
WorldPacket data(SMSG_PLAYER_VEHICLE_DATA, target->GetPackGUID().size()+4);
data.appendPackGUID(target->GetGUID());
data << uint32(apply ? vehicleId : 0);
@@ -5326,6 +5339,18 @@ void AuraEffect::HandlePreventResurrection(AuraApplication const* aurApp, uint8
aurApp->GetTarget()->SetByteFlag(PLAYER_FIELD_BYTES, 0, PLAYER_FIELD_BYTE_RELEASE_TIMER);
}
+void AuraEffect::HandleMastery(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
+{
+ if (!(mode & AURA_EFFECT_HANDLE_REAL))
+ return;
+
+ Player* target = aurApp->GetTarget()->ToPlayer();
+ if (!target)
+ return;
+
+ target->UpdateMastery();
+}
+
void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
{
switch (GetSpellInfo()->SpellFamilyName)
@@ -5397,23 +5422,6 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
}
break;
}
- case SPELLFAMILY_ROGUE:
- {
- switch (GetSpellInfo()->Id)
- {
- // Master of Subtlety
- case 31666:
- if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
- target->RemoveAurasDueToSpell(31665);
- break;
- // Overkill
- case 58428:
- if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
- target->RemoveAurasDueToSpell(58427);
- break;
- }
- break;
- }
case SPELLFAMILY_HUNTER:
{
// Explosive Shot
@@ -5705,13 +5713,6 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)
case 66882:
target->CastCustomSpell(triggerSpellId, SPELLVALUE_RADIUS_MOD, (int32)((((float)m_tickNumber / 60) * 0.9f + 0.1f) * 10000 * 2 / 3), NULL, true, NULL, this);
return;
- // Beacon of Light
- case 53563:
- {
- // area aura owner casts the spell
- GetBase()->GetUnitOwner()->CastSpell(target, triggeredSpellInfo, true, 0, this, GetBase()->GetUnitOwner()->GetGUID());
- return;
- }
// Slime Spray - temporary here until preventing default effect works again
// added on 9.10.2010
case 69508:
@@ -5866,16 +5867,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000))
{
if (caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->isHonorOrXPTarget(target))
- {
- if (roll_chance_i(20))
- {
- caster->CastSpell(caster, 43836, true, 0, this);
- // Glyph of Drain Soul - chance to create an additional Soul Shard
- if (AuraEffect* aur = caster->GetAuraEffect(58070, 0))
- if (roll_chance_i(aur->GetMiscValue()))
- caster->CastSpell(caster, 58068, true, 0, aur);
- }
- }
+ caster->CastSpell(caster, 95810, true, 0, this);
}
if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_GENERIC)
{
@@ -5912,8 +5904,9 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
int32 dmg = damage;
+
if (!(GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
- caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
+ caster->ApplyResilience(target, &dmg);
damage = dmg;
caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, GetSpellInfo());
@@ -6000,7 +5993,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
int32 dmg = damage;
if (!(GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
- caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
+ caster->ApplyResilience(target, &dmg);
damage = dmg;
caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, m_spellInfo);
@@ -6104,15 +6097,6 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
if (maxval)
AddPct(TakenTotalMod, maxval);
- // Healing over time taken percent
- float minval_hot = (float)target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT);
- if (minval_hot)
- AddPct(TakenTotalMod, minval_hot);
-
- float maxval_hot = (float)target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT);
- if (maxval_hot)
- AddPct(TakenTotalMod, maxval_hot);
-
TakenTotalMod = std::max(TakenTotalMod, 0.0f);
damage = uint32(target->CountPctFromMaxHealth(damage));
@@ -6162,7 +6146,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
// Health Funnel
// damage caster for heal amount
- if (target != caster && GetSpellInfo()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL)
+ if (target != caster && GetSpellInfo()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL && GetSpellInfo()->Id != 755)
{
uint32 funnelDamage = GetSpellInfo()->ManaPerSecond; // damage is not affected by spell power
@@ -6219,10 +6203,6 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con
TC_LOG_INFO("spells", "PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), drainAmount, GetId());
- // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
- if (powerType == POWER_MANA)
- drainAmount -= target->GetSpellCritDamageReduction(drainAmount);
-
int32 drainedAmount = -target->ModifyPower(powerType, -drainAmount);
float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
@@ -6340,10 +6320,6 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
// ignore negative values (can be result apply spellmods to aura damage
int32 damage = std::max(m_amount, 0);
- // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
- if (powerType == POWER_MANA)
- damage -= target->GetSpellCritDamageReduction(damage);
-
uint32 gain = uint32(-target->ModifyPower(powerType, -damage));
float dmgMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
@@ -6503,3 +6479,52 @@ void AuraEffect::HandleRaidProcFromChargeWithValueAuraProc(AuraApplication* aurA
TC_LOG_DEBUG("spells", "AuraEffect::HandleRaidProcFromChargeWithValueAuraProc: Triggering spell %u from aura %u proc", triggerSpellId, GetId());
target->CastCustomSpell(target, triggerSpellId, &value, NULL, NULL, true, NULL, this, GetCasterGUID());
}
+
+void AuraEffect::HandleAuraForceWeather(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & AURA_EFFECT_HANDLE_REAL))
+ return;
+
+ Player* target = aurApp->GetTarget()->ToPlayer();
+
+ if (!target)
+ return;
+
+ if (apply)
+ {
+ WorldPacket data(SMSG_WEATHER, (4 + 4 + 1));
+
+ data << uint32(GetMiscValue()) << 1.0f << uint8(0);
+ target->GetSession()->SendPacket(&data);
+ }
+ else
+ {
+ // send weather for current zone
+ if (Weather* weather = WeatherMgr::FindWeather(target->GetZoneId()))
+ weather->SendWeatherUpdateToPlayer(target);
+ else
+ {
+ if (!WeatherMgr::AddWeather(target->GetZoneId()))
+ {
+ // send fine weather packet to remove old weather
+ WeatherMgr::SendFineWeatherUpdateToPlayer(target);
+ }
+ }
+ }
+}
+
+void AuraEffect::HandleEnableAltPower(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & AURA_EFFECT_HANDLE_REAL))
+ return;
+
+ uint32 altPowerId = GetMiscValue();
+ UnitPowerBarEntry const* powerEntry = sUnitPowerBarStore.LookupEntry(altPowerId);
+ if (!powerEntry)
+ return;
+
+ if (apply)
+ aurApp->GetTarget()->SetMaxPower(POWER_ALTERNATE_POWER, powerEntry->MaxPower);
+ else
+ aurApp->GetTarget()->SetMaxPower(POWER_ALTERNATE_POWER, 0);
+}
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index 5eec9021291..700bbb10417 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -59,7 +59,7 @@ class AuraEffect
void SetPeriodicTimer(int32 periodicTimer) { m_periodicTimer = periodicTimer; }
int32 CalculateAmount(Unit* caster);
- void CalculatePeriodic(Unit* caster, bool create = false, bool load = false);
+ void CalculatePeriodic(Unit* caster, bool resetPeriodicTimer = true, bool load = false);
void CalculateSpellMod();
void ChangeAmount(int32 newAmount, bool mark = true, bool onStackOrReapply = false);
void RecalculateAmount() { if (!CanBeRecalculated()) return; ChangeAmount(CalculateAmount(GetCaster()), false); }
@@ -86,7 +86,7 @@ class AuraEffect
bool IsPeriodic() const { return m_isPeriodic; }
void SetPeriodic(bool isPeriodic) { m_isPeriodic = isPeriodic; }
- bool IsAffectedOnSpell(SpellInfo const* spell) const;
+ bool IsAffectingSpell(SpellInfo const* spell) const;
bool HasSpellClassMask() const { return m_spellInfo->Effects[m_effIndex].SpellClassMask; }
void SendTickImmune(Unit* target, Unit* caster) const;
@@ -144,6 +144,8 @@ class AuraEffect
void HandleSpiritOfRedemption(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraGhost(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandlePhase(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandlePhaseGroup(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+
// unit model
void HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraTransform(AuraApplication const* aurApp, uint8 mode, bool apply) const;
@@ -252,7 +254,6 @@ class AuraEffect
void HandleModAttackSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModRangedHaste(AuraApplication const* aurApp, uint8 mode, bool apply) const;
- void HandleRangedAmmoHaste(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// combat rating
void HandleModRating(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModRatingFromStat(AuraApplication const* aurApp, uint8 mode, bool apply) const;
@@ -261,8 +262,6 @@ class AuraEffect
void HandleAuraModRangedAttackPower(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModRangedAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
- void HandleAuraModRangedAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
- void HandleAuraModAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModAttackPowerOfArmor(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// damage bonus
void HandleModDamageDone(AuraApplication const* aurApp, uint8 mode, bool apply) const;
@@ -290,6 +289,9 @@ class AuraEffect
void HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandlePreventResurrection(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleMastery(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleAuraForceWeather(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleEnableAltPower(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// aura effect periodic tick handlers
void HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const;
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 851d992d857..e38dc8fdf4a 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -147,6 +147,9 @@ void AuraApplication::_InitFlags(Unit* caster, uint8 effMask)
}
_flags |= positiveFound ? AFLAG_POSITIVE : AFLAG_NEGATIVE;
}
+
+ if (GetBase()->GetSpellInfo()->AttributesEx8 & SPELL_ATTR8_AURA_SEND_AMOUNT)
+ _flags |= AFLAG_ANY_EFFECT_AMOUNT_SENT;
}
void AuraApplication::_HandleEffect(uint8 effIndex, bool apply)
@@ -192,7 +195,7 @@ void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const
uint32 flags = _flags;
if (aura->GetMaxDuration() > 0 && !(aura->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_HIDE_DURATION))
flags |= AFLAG_DURATION;
- data << uint8(flags);
+ data << uint16(flags);
data << uint8(aura->GetCasterLevel());
// send stack amount for aura which could be stacked (never 0 - causes incorrect display) or charges
// stack amount has priority over charges (checked on retail with spell 50262)
@@ -206,6 +209,12 @@ void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const
data << uint32(aura->GetMaxDuration());
data << uint32(aura->GetDuration());
}
+
+ if (flags & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (AuraEffect const* eff = aura->GetEffect(i))
+ if (HasEffect(i)) // Not all of aura's effects have to be applied on every target
+ data << int32(eff->GetAmount());
}
void AuraApplication::ClientUpdate(bool remove)
@@ -337,7 +346,7 @@ m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0),
m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1),
m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false)
{
- if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel)
+ if (m_spellInfo->ManaPerSecond)
m_timeCla = 1 * IN_MILLISECONDS;
m_maxDuration = CalcMaxDuration(caster);
@@ -684,7 +693,7 @@ void Aura::Update(uint32 diff, Unit* caster)
m_timeCla -= diff;
else if (caster)
{
- if (int32 manaPerSecond = m_spellInfo->ManaPerSecond + m_spellInfo->ManaPerSecondPerLevel * caster->getLevel())
+ if (int32 manaPerSecond = m_spellInfo->ManaPerSecond)
{
m_timeCla += 1000 - diff;
@@ -755,18 +764,35 @@ void Aura::RefreshDuration(bool withMods)
else
SetDuration(GetMaxDuration());
- if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel)
+ if (m_spellInfo->ManaPerSecond)
m_timeCla = 1 * IN_MILLISECONDS;
}
void Aura::RefreshTimers()
{
m_maxDuration = CalcMaxDuration();
+ bool resetPeriodic = true;
+ if (m_spellInfo->AttributesEx8 & SPELL_ATTR8_DONT_RESET_PERIODIC_TIMER)
+ {
+ int32 minAmplitude = m_maxDuration;
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (AuraEffect const* eff = GetEffect(i))
+ if (int32 ampl = eff->GetAmplitude())
+ minAmplitude = std::min(ampl, minAmplitude);
+
+ // If only one tick remaining, roll it over into new duration
+ if (GetDuration() <= minAmplitude)
+ {
+ m_maxDuration += GetDuration();
+ resetPeriodic = false;
+ }
+ }
+
RefreshDuration();
Unit* caster = GetCaster();
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (HasEffect(i))
- GetEffect(i)->CalculatePeriodic(caster, false, false);
+ GetEffect(i)->CalculatePeriodic(caster, resetPeriodic, false);
}
void Aura::SetCharges(uint8 charges)
@@ -789,7 +815,7 @@ uint8 Aura::CalcMaxCharges(Unit* caster) const
if (Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, maxProcCharges);
- return maxProcCharges;
+ return uint8(maxProcCharges);
}
bool Aura::ModCharges(int32 num, AuraRemoveMode removeMode)
@@ -952,9 +978,12 @@ bool Aura::CanBeSaved() const
case 40075: // Fel Flak Fire
case 55849: // Power Spark
return false;
- break;
}
+ // When a druid logins, he doesnt have either eclipse power, nor the marker auras, nor the eclipse buffs. Dont save them.
+ if (GetId() == 67483 || GetId() == 67484 || GetId() == 48517 || GetId() == 48518)
+ return false;
+
// don't save auras removed by proc system
if (IsUsingCharges() && !GetCharges())
return false;
@@ -964,7 +993,7 @@ bool Aura::CanBeSaved() const
bool Aura::CanBeSentToClient() const
{
- return !IsPassive() || GetSpellInfo()->HasAreaAuraEffect() || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE);
+ return !IsPassive() || GetSpellInfo()->HasAreaAuraEffect() || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE) || HasEffectType(SPELL_AURA_CAST_WHILE_WALKING);
}
bool Aura::IsSingleTargetWith(Aura const* aura) const
@@ -1208,20 +1237,8 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
case SPELLFAMILY_MAGE:
if (!caster)
break;
- if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00000001 && GetSpellInfo()->SpellFamilyFlags[2] & 0x00000008)
- {
- // Glyph of Fireball
- if (caster->HasAura(56368))
- SetDuration(0);
- }
- else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00000020 && GetSpellInfo()->SpellVisual[0] == 13)
- {
- // Glyph of Frostbolt
- if (caster->HasAura(56370))
- SetDuration(0);
- }
/// @todo This should be moved to similar function in spell::hit
- else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x01000000)
+ if (GetSpellInfo()->SpellFamilyFlags[0] & 0x01000000)
{
// Polymorph Sound - Sheep && Penguin
if (GetSpellInfo()->SpellIconID == 82 && GetSpellInfo()->SpellVisual[0] == 12978)
@@ -1253,18 +1270,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
caster->CastSpell(caster, spellId, true);
}
break;
- case 44544: // Fingers of Frost
- {
- // See if we already have the indicator aura. If not, create one.
- if (Aura* aur = target->GetAura(74396))
- {
- // Aura already there. Refresh duration and set original charges
- aur->SetCharges(2);
- aur->RefreshDuration();
- }
- else
- target->AddAura(74396, target);
- }
default:
break;
}
@@ -1276,7 +1281,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (GetSpellInfo()->SpellFamilyFlags[0] & 0x02000000 && GetEffect(0))
{
// Improved Devouring Plague
- if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3790, 1))
+ if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3790, 0))
{
uint32 damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), GetEffect(0)->GetAmount(), DOT);
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT);
@@ -1306,49 +1311,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (target->HasAura(58039)) // Glyph of Blurred Speed
target->CastSpell(target, 61922, true); // Sprint (waterwalk)
break;
- case SPELLFAMILY_DEATHKNIGHT:
- if (!caster)
- break;
- // Frost Fever and Blood Plague
- if (GetSpellInfo()->SpellFamilyFlags[2] & 0x2)
- {
- // Can't proc on self
- if (GetCasterGUID() == target->GetGUID())
- break;
-
- AuraEffect* aurEff = NULL;
- // Ebon Plaguebringer / Crypt Fever
- Unit::AuraEffectList const& TalentAuras = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for (Unit::AuraEffectList::const_iterator itr = TalentAuras.begin(); itr != TalentAuras.end(); ++itr)
- {
- if ((*itr)->GetMiscValue() == 7282)
- {
- aurEff = *itr;
- // Ebon Plaguebringer - end search if found
- if ((*itr)->GetSpellInfo()->SpellIconID == 1766)
- break;
- }
- }
- if (aurEff)
- {
- uint32 spellId = 0;
- switch (aurEff->GetId())
- {
- // Ebon Plague
- case 51161: spellId = 51735; break;
- case 51160: spellId = 51734; break;
- case 51099: spellId = 51726; break;
- // Crypt Fever
- case 49632: spellId = 50510; break;
- case 49631: spellId = 50509; break;
- case 49032: spellId = 50508; break;
- default:
- TC_LOG_ERROR("spells", "Aura::HandleAuraSpecificMods: Unknown rank of Crypt Fever/Ebon Plague (%d) found", aurEff->GetId());
- }
- caster->CastSpell(target, spellId, true, 0, GetEffect(0));
- }
- }
- break;
}
}
// mods at aura remove
@@ -1377,54 +1339,9 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
target->CastSpell(target, 32612, true, NULL, GetEffect(1));
target->CombatStop();
break;
- case 74396: // Fingers of Frost
- // Remove the IGNORE_AURASTATE aura
- target->RemoveAurasDueToSpell(44544);
- break;
- case 44401: //Missile Barrage
- case 48108: //Hot Streak
- case 57761: //Fireball!
- if (removeMode != AURA_REMOVE_BY_EXPIRE || aurApp->GetBase()->IsExpired())
- break;
- if (target->HasAura(70752)) //Item - Mage T10 2P Bonus
- target->CastSpell(target, 70753, true);
- break;
default:
break;
}
- if (!caster)
- break;
- // Ice barrier - dispel/absorb remove
- if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[1] & 0x1)
- {
- // Shattered Barrier
- if (AuraEffect* dummy = caster->GetDummyAuraEffect(SPELLFAMILY_MAGE, 2945, 0))
- if (roll_chance_i(dummy->GetSpellInfo()->ProcChance))
- caster->CastSpell(target, 55080, true, NULL, GetEffect(0));
- }
- break;
- case SPELLFAMILY_WARRIOR:
- if (!caster)
- break;
- // Spell Reflection
- if (GetSpellInfo()->SpellFamilyFlags[1] & 0x2)
- {
- if (removeMode != AURA_REMOVE_BY_DEFAULT)
- {
- // Improved Spell Reflection
- if (caster->GetDummyAuraEffect(SPELLFAMILY_WARRIOR, 1935, 1))
- {
- // aura remove - remove auras from all party members
- std::list<Unit*> PartyMembers;
- target->GetPartyMembers(PartyMembers);
- for (std::list<Unit*>::iterator itr = PartyMembers.begin(); itr != PartyMembers.end(); ++itr)
- {
- if ((*itr)!= target)
- (*itr)->RemoveAurasWithFamily(SPELLFAMILY_WARRIOR, 0, 0x2, 0, GetCasterGUID());
- }
- }
- }
- }
break;
case SPELLFAMILY_WARLOCK:
if (!caster)
@@ -1450,18 +1367,8 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
case SPELLFAMILY_PRIEST:
if (!caster)
break;
- // Shadow word: Pain // Vampiric Touch
- if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00008000 || GetSpellInfo()->SpellFamilyFlags[1] & 0x00000400))
- {
- // Shadow Affinity
- if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 178, 1))
- {
- int32 basepoints0 = aurEff->GetAmount() * caster->GetCreateMana() / 100;
- caster->CastCustomSpell(caster, 64103, &basepoints0, NULL, NULL, true, NULL, GetEffect(0));
- }
- }
// Power word: shield
- else if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[0] & 0x00000001)
+ if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[0] & 0x00000001)
{
// Rapture
if (Aura const* aura = caster->GetAuraOfRankedSpell(47535))
@@ -1483,65 +1390,12 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
// effect on caster
if (AuraEffect const* aurEff = aura->GetEffect(0))
{
- float multiplier = (float)aurEff->GetAmount();
- if (aurEff->GetId() == 47535)
- multiplier -= 0.5f;
- else if (aurEff->GetId() == 47537)
- multiplier += 0.5f;
-
+ float multiplier = float(aurEff->GetAmount());
int32 basepoints0 = int32(CalculatePct(caster->GetMaxPower(POWER_MANA), multiplier));
caster->CastCustomSpell(caster, 47755, &basepoints0, NULL, NULL, true);
}
- // effect on aura target
- if (AuraEffect const* aurEff = aura->GetEffect(1))
- {
- if (!roll_chance_i(aurEff->GetAmount()))
- break;
-
- int32 triggeredSpellId = 0;
- switch (target->getPowerType())
- {
- case POWER_MANA:
- {
- int32 basepoints0 = int32(CalculatePct(target->GetMaxPower(POWER_MANA), 2));
- caster->CastCustomSpell(target, 63654, &basepoints0, NULL, NULL, true);
- break;
- }
- case POWER_RAGE: triggeredSpellId = 63653; break;
- case POWER_ENERGY: triggeredSpellId = 63655; break;
- case POWER_RUNIC_POWER: triggeredSpellId = 63652; break;
- default:
- break;
- }
- if (triggeredSpellId)
- caster->CastSpell(target, triggeredSpellId, true);
- }
}
}
- switch (GetId())
- {
- case 47788: // Guardian Spirit
- if (removeMode != AURA_REMOVE_BY_EXPIRE)
- break;
- if (caster->GetTypeId() != TYPEID_PLAYER)
- break;
-
- Player* player = caster->ToPlayer();
- // Glyph of Guardian Spirit
- if (AuraEffect* aurEff = player->GetAuraEffect(63231, 0))
- {
- if (!player->HasSpellCooldown(47788))
- break;
-
- player->RemoveSpellCooldown(GetSpellInfo()->Id, true);
- player->AddSpellCooldown(GetSpellInfo()->Id, 0, uint32(time(NULL) + aurEff->GetAmount()));
-
- WorldPacket data;
- player->BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, GetSpellInfo()->Id, aurEff->GetAmount()*IN_MILLISECONDS);
- player->SendDirectMessage(&data);
- }
- break;
- }
break;
case SPELLFAMILY_ROGUE:
// Remove Vanish on stealth remove
@@ -1592,32 +1446,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
break;
}
break;
- case SPELLFAMILY_ROGUE:
- // Stealth
- if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00400000)
- {
- // Master of subtlety
- if (AuraEffect const* aurEff = target->GetAuraEffectOfRankedSpell(31221, 0))
- {
- if (!apply)
- target->CastSpell(target, 31666, true);
- else
- {
- int32 basepoints0 = aurEff->GetAmount();
- target->CastCustomSpell(target, 31665, &basepoints0, NULL, NULL, true);
- }
- }
- // Overkill
- if (target->HasAura(58426))
- {
- if (!apply)
- target->CastSpell(target, 58428, true);
- else
- target->CastSpell(target, 58427, true);
- }
- break;
- }
- break;
case SPELLFAMILY_HUNTER:
switch (GetId())
{
@@ -1640,7 +1468,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
case SPELLFAMILY_PALADIN:
switch (GetId())
{
- case 31842: // Divine Illumination
+ case 31842: // Divine Favor
// Item - Paladin T10 Holy 2P Bonus
if (target->HasAura(70755))
{
@@ -2537,4 +2365,3 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster*
}
}
}
-
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 10339a6ac3a..bf518859b49 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -34,6 +34,7 @@
#include "Totem.h"
#include "Spell.h"
#include "DynamicObject.h"
+#include "Guild.h"
#include "Group.h"
#include "UpdateData.h"
#include "MapManager.h"
@@ -53,6 +54,7 @@
#include "SpellScript.h"
#include "InstanceScript.h"
#include "SpellInfo.h"
+#include "DB2Stores.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
@@ -548,7 +550,7 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme
// wand case
if ((m_caster->getClassMask() & CLASSMASK_WAND_USERS) != 0 && m_caster->GetTypeId() == TYPEID_PLAYER)
if (Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK))
- m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->Damage[0].DamageType);
+ m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->DamageType);
if (originalCasterGUID)
m_originalCasterGUID = originalCasterGUID;
@@ -824,7 +826,10 @@ void Spell::SelectSpellTargets()
else if (m_spellInfo->Speed > 0.0f)
{
float dist = m_caster->GetDistance(*m_targets.GetDstPos());
- m_delayMoment = (uint64) floor(dist / m_spellInfo->Speed * 1000.0f);
+ if (!(m_spellInfo->AttributesEx9 & SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
+ m_delayMoment = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
+ else
+ m_delayMoment = uint64(m_spellInfo->Speed * 1000.0f);
}
}
}
@@ -1114,14 +1119,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
{
// Other special target selection goes here
if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
- {
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- maxTargets += (*j)->GetAmount();
-
Trinity::Containers::RandomResizeList(targets, maxTargets);
- }
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
{
@@ -1164,6 +1162,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type");
return;
}
+
if (!referer)
return;
@@ -1185,6 +1184,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type");
return;
}
+
std::list<WorldObject*> targets;
float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions);
@@ -1195,14 +1195,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
{
// Other special target selection goes here
if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
- {
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- maxTargets += (*j)->GetAmount();
-
Trinity::Containers::RandomResizeList(targets, maxTargets);
- }
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
{
@@ -1633,6 +1626,9 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
CallScriptDestinationTargetSelectHandlers(dest, effIndex, SpellImplicitTargetInfo(TARGET_DEST_TRAJ));
m_targets.ModDst(dest);
}
+
+ if (Vehicle* veh = m_caster->GetVehicleKit())
+ veh->SetLastShootPos(*m_targets.GetDstPos());
}
void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
@@ -1964,8 +1960,9 @@ void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/)
(m_spellInfo->SpellFamilyFlags[0] & 0x18 || // Freezing and Frost Trap, Freezing Arrow
m_spellInfo->Id == 57879 || // Snake Trap - done this way to avoid double proc
m_spellInfo->SpellFamilyFlags[2] & 0x00024000)) // Explosive and Immolation Trap
-
+ {
m_procAttacker |= PROC_FLAG_DONE_TRAP_ACTIVATION;
+ }
/* Effects which are result of aura proc from triggered spell cannot proc
to prevent chain proc of these spells */
@@ -2076,7 +2073,11 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
if (dist < 5.0f)
dist = 5.0f;
- targetInfo.timeDelay = (uint64) floor(dist / m_spellInfo->Speed * 1000.0f);
+
+ if (!(m_spellInfo->AttributesEx9 & SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
+ targetInfo.timeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
+ else
+ targetInfo.timeDelay = uint64(m_spellInfo->Speed * 1000.0f);
// Calculate minimum incoming time
if (m_delayMoment == 0 || m_delayMoment > targetInfo.timeDelay)
@@ -2155,7 +2156,12 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask)
float dist = m_caster->GetDistance(go->GetPositionX(), go->GetPositionY(), go->GetPositionZ());
if (dist < 5.0f)
dist = 5.0f;
- target.timeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
+
+ if (!(m_spellInfo->AttributesEx9 & SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
+ target.timeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
+ else
+ target.timeDelay = uint64(m_spellInfo->Speed * 1000.0f);
+
if (m_delayMoment == 0 || m_delayMoment > target.timeDelay)
m_delayMoment = target.timeDelay;
}
@@ -2456,25 +2462,9 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
// disable effects to which unit is immune
SpellMissInfo returnVal = SPELL_MISS_IMMUNE;
for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber)
- {
if (effectMask & (1 << effectNumber))
- {
if (unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber))
effectMask &= ~(1 << effectNumber);
- else if (m_spellInfo->Effects[effectNumber].IsAura() && !m_spellInfo->IsPositiveEffect(effectNumber))
- {
- int32 debuff_resist_chance = unit->GetMaxPositiveAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(m_spellInfo->Dispel));
- debuff_resist_chance += unit->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(m_spellInfo->Dispel));
-
- if (debuff_resist_chance > 0)
- if (irand(0, 10000) <= (debuff_resist_chance * 100))
- {
- effectMask &= ~(1 << effectNumber);
- returnVal = SPELL_MISS_RESIST;
- }
- }
- }
- }
if (!effectMask)
return returnVal;
@@ -2485,14 +2475,14 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
if (Player* player = unit->ToPlayer())
{
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, m_spellInfo->Id);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id, 0, m_caster);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id, 0, 0, m_caster);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id);
}
if (Player* player = m_caster->ToPlayer())
{
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_CASTER, m_spellInfo->Id);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, 0, unit);
}
if (m_caster != unit)
@@ -2612,12 +2602,25 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
duration = m_originalCaster->ModSpellDuration(aurSpellInfo, unit, duration, positive, effectMask);
- // Haste modifies duration of channeled spells
- if (m_spellInfo->IsChanneled())
- m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this);
- // and duration of auras affected by SPELL_AURA_PERIODIC_HASTE
- else if (m_originalCaster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, aurSpellInfo) || m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
- duration = int32(duration * m_originalCaster->GetFloatValue(UNIT_MOD_CAST_SPEED));
+ if (duration > 0)
+ {
+ // Haste modifies duration of channeled spells
+ if (m_spellInfo->IsChanneled())
+ m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this);
+ else if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
+ {
+ int32 origDuration = duration;
+ duration = 0;
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (AuraEffect const* eff = m_spellAura->GetEffect(i))
+ if (int32 amplitude = eff->GetAmplitude()) // amplitude is hastened by UNIT_MOD_CAST_SPEED
+ duration = std::max(std::max(origDuration / amplitude, 1) * amplitude, duration);
+
+ // if there is no periodic effect
+ if (!duration)
+ duration = int32(origDuration * m_originalCaster->GetFloatValue(UNIT_MOD_CAST_SPEED));
+ }
+ }
if (duration != m_spellAura->GetMaxDuration())
{
@@ -2673,7 +2676,7 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask)
{
if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance))
{
- m_caster->CastSpell(unit, i->triggeredSpell, true);
+ m_caster->CastSpell(unit, i->triggeredSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_TARGET_CHECK));
TC_LOG_DEBUG("spells", "Spell %d triggered spell %d by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->triggeredSpell->Id);
// SPELL_AURA_ADD_TARGET_TRIGGER auras shouldn't trigger auras without duration
@@ -2882,6 +2885,10 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
m_needComboPoints = false;
SpellCastResult result = CheckCast(true);
+ // target is checked in too many locations and with different results to handle each of them
+ // handle just the general SPELL_FAILED_BAD_TARGETS result which is the default result for most DBC target checks
+ if (_triggeredCastFlags & TRIGGERED_IGNORE_TARGET_CHECK && result == SPELL_FAILED_BAD_TARGETS)
+ result = SPELL_CAST_OK;
if (result != SPELL_CAST_OK && !IsAutoRepeat()) //always cast autorepeat dummy for triggering
{
// Periodic auras should be interrupted when aura triggers a spell which can't be cast
@@ -2909,18 +2916,20 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
{
player->SetSpellModTakingSpell(this, true);
// calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail)
- m_casttime = m_spellInfo->CalcCastTime(this);
+ m_casttime = m_spellInfo->CalcCastTime(player->getLevel(), this);
player->SetSpellModTakingSpell(this, false);
}
else
m_casttime = 0; // Set cast time to 0 if .cheat casttime is enabled.
}
else
- m_casttime = m_spellInfo->CalcCastTime(this);
+ m_casttime = m_spellInfo->CalcCastTime(m_caster->getLevel(), this);
// don't allow channeled spells / spells with cast time to be cast while moving
// (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in)
- if ((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isMoving() && m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT)
+ // don't cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect
+ if (((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isMoving() &&
+ m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) && !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))
{
SendCastResult(SPELL_FAILED_MOVING);
finish(false);
@@ -3273,7 +3282,7 @@ void Spell::handle_immediate()
// Remove used for cast item if need (it can be already NULL after TakeReagents call
TakeCastItem();
- // handle ammo consumption for Hunter's volley spell
+ // handle ammo consumption for thrown weapons
if (m_spellInfo->IsRangedWeaponSpell() && m_spellInfo->IsChanneled())
TakeAmmo();
@@ -3408,6 +3417,9 @@ void Spell::_handle_finish_phase()
// Real add combo points from effects
if (m_comboPointGain)
m_caster->m_movedPlayer->GainSpellComboPoints(m_comboPointGain);
+
+ if (m_spellInfo->PowerType == POWER_HOLY_POWER && m_caster->m_movedPlayer->getClass() == CLASS_PALADIN)
+ HandleHolyPower(m_caster->m_movedPlayer);
}
if (m_caster->m_extraAttacks && GetSpellInfo()->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
@@ -3455,9 +3467,11 @@ void Spell::update(uint32 difftime)
}
// check if the player caster has moved before the spell finished
+ // with the exception of spells affected with SPELL_AURA_CAST_WHILE_WALKING effect
if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) &&
- (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)))
+ (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) &&
+ !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))
{
// don't cancel for melee, autorepeat, triggered and instant spells
if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered())
@@ -3564,7 +3578,7 @@ void Spell::finish(bool ok)
Unit::AuraEffectList const& vIgnoreReset = m_caster->GetAuraEffectsByType(SPELL_AURA_IGNORE_MELEE_RESET);
for (Unit::AuraEffectList::const_iterator i = vIgnoreReset.begin(); i != vIgnoreReset.end(); ++i)
{
- if ((*i)->IsAffectedOnSpell(m_spellInfo))
+ if ((*i)->IsAffectingSpell(m_spellInfo))
{
found = true;
break;
@@ -3600,13 +3614,46 @@ void Spell::finish(bool ok)
m_caster->AttackStop();
}
-void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError)
+void Spell::SendCastResult(SpellCastResult result)
+{
+ if (result == SPELL_CAST_OK)
+ return;
+
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time
+ return;
+
+ SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError);
+}
+
+void Spell::SendPetCastResult(SpellCastResult result)
{
- data << uint8(castCount); // single cast or multi 2.3 (0/1)
+ if (result == SPELL_CAST_OK)
+ return;
+
+ Unit* owner = m_caster->GetCharmerOrOwner();
+ if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ SendCastResult(owner->ToPlayer(), m_spellInfo, m_cast_count, result, SPELL_CUSTOM_ERROR_NONE, SMSG_PET_CAST_FAILED);
+}
+
+void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/, Opcodes opcode /*= SMSG_CAST_FAILED*/)
+{
+ if (result == SPELL_CAST_OK)
+ return;
+
+ WorldPacket data(opcode, (4+1+1));
+ data << uint8(cast_count);
data << uint32(spellInfo->Id);
data << uint8(result); // problem
switch (result)
{
+ case SPELL_FAILED_NOT_READY:
+ data << uint32(0); // unknown (value 1 update cooldowns on client flag)
+ break;
case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
data << uint32(spellInfo->RequiresSpellFocus); // SpellFocusObject.dbc id
break;
@@ -3659,9 +3706,29 @@ void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo con
data << uint32(proto->ItemLimitCategory);
break;
}
+ case SPELL_FAILED_PREVENTED_BY_MECHANIC:
+ data << uint32(spellInfo->GetAllEffectsMechanicMask()); // SpellMechanic.dbc id
+ break;
+ case SPELL_FAILED_NEED_EXOTIC_AMMO:
+ data << uint32(spellInfo->EquippedItemSubClassMask); // seems correct...
+ break;
+ case SPELL_FAILED_NEED_MORE_ITEMS:
+ data << uint32(0); // Item id
+ data << uint32(0); // Item count?
+ break;
+ case SPELL_FAILED_MIN_SKILL:
+ data << uint32(0); // SkillLine.dbc id
+ data << uint32(0); // required skill value
+ break;
+ case SPELL_FAILED_FISHING_TOO_LOW:
+ data << uint32(0); // required fishing skill
+ break;
case SPELL_FAILED_CUSTOM_ERROR:
data << uint32(customError);
break;
+ case SPELL_FAILED_SILENCED:
+ data << uint32(0); // Unknown
+ break;
case SPELL_FAILED_REAGENTS:
{
uint32 missingItem = 0;
@@ -3683,72 +3750,13 @@ void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo con
data << uint32(missingItem); // first missing item
break;
}
- case SPELL_FAILED_PREVENTED_BY_MECHANIC:
- data << uint32(spellInfo->Mechanic);
- break;
- case SPELL_FAILED_NEED_EXOTIC_AMMO:
- data << uint32(spellInfo->EquippedItemSubClassMask);
- break;
- case SPELL_FAILED_NEED_MORE_ITEMS:
- data << uint32(0); // Item entry
- data << uint32(0); // Count
- break;
- case SPELL_FAILED_MIN_SKILL:
- data << uint32(0); // SkillLine.dbc Id
- data << uint32(0); // Amount
- break;
- case SPELL_FAILED_FISHING_TOO_LOW:
- data << uint32(0); // Skill level
- break;
+ // TODO: SPELL_FAILED_NOT_STANDING
default:
break;
}
-}
-
-void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/)
-{
- if (result == SPELL_CAST_OK)
- return;
-
- WorldPacket data(SMSG_CAST_FAILED, 1 + 4 + 1);
- WriteCastResultInfo(data, caster, spellInfo, castCount, result, customError);
-
caster->GetSession()->SendPacket(&data);
}
-void Spell::SendCastResult(SpellCastResult result)
-{
- if (result == SPELL_CAST_OK)
- return;
-
- if (m_caster->GetTypeId() != TYPEID_PLAYER)
- return;
-
- if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time
- return;
-
- SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError);
-}
-
-void Spell::SendPetCastResult(SpellCastResult result)
-{
- if (result == SPELL_CAST_OK)
- return;
-
- Unit* owner = m_caster->GetCharmerOrOwner();
- if (!owner)
- return;
-
- Player* player = owner->ToPlayer();
- if (!player)
- return;
-
- WorldPacket data(SMSG_PET_CAST_FAILED, 1 + 4 + 1);
- WriteCastResultInfo(data, player, m_spellInfo, m_cast_count, result, m_customError);
-
- player->GetSession()->SendPacket(&data);
-}
-
void Spell::SendSpellStart()
{
if (!IsNeedSendToClient())
@@ -3756,19 +3764,17 @@ void Spell::SendSpellStart()
//TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_START id=%u", m_spellInfo->Id);
- uint32 castFlags = CAST_FLAG_UNKNOWN_2;
+ uint32 castFlags = CAST_FLAG_HAS_TRAJECTORY;
if ((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell)
castFlags |= CAST_FLAG_PENDING;
- if (m_spellInfo->Attributes & SPELL_ATTR0_REQ_AMMO)
- castFlags |= CAST_FLAG_AMMO;
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
(m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsPet()))
&& m_spellInfo->PowerType != POWER_HEALTH)
castFlags |= CAST_FLAG_POWER_LEFT_SELF;
- if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNE)
+ if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNES)
castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it
WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2));
@@ -3781,22 +3787,58 @@ void Spell::SendSpellStart()
data << uint8(m_cast_count); // pending spell cast?
data << uint32(m_spellInfo->Id); // spellId
data << uint32(castFlags); // cast flags
- data << int32(m_timer); // delay?
+ data << uint32(m_timer); // delay?
+ data << uint32(m_casttime);
m_targets.Write(data);
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
data << uint32(m_caster->GetPower((Powers)m_spellInfo->PowerType));
- if (castFlags & CAST_FLAG_AMMO)
- WriteAmmoToPacket(&data);
+ if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list
+ {
+ //TODO: There is a crash caused by a spell with CAST_FLAG_RUNE_LIST casted by a creature
+ //The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster
+ if (Player* player = m_caster->ToPlayer())
+ {
+ data << uint8(m_runesState); // runes state before
+ data << uint8(player->GetRunesState()); // runes state after
+ for (uint8 i = 0; i < MAX_RUNES; ++i)
+ {
+ // float casts ensure the division is performed on floats as we need float result
+ float baseCd = float(player->GetRuneBaseCooldown(i));
+ data << uint8((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
+ }
+ }
+ else
+ {
+ data << uint8(0);
+ data << uint8(0);
+ for (uint8 i = 0; i < MAX_RUNES; ++i)
+ data << uint8(0);
+ }
+ }
- if (castFlags & CAST_FLAG_UNKNOWN_23)
+ if (castFlags & CAST_FLAG_PROJECTILE)
+ {
+ data << uint32(0); // Ammo display ID
+ data << uint32(0); // Inventory Type
+ }
+
+ if (castFlags & CAST_FLAG_IMMUNITY)
{
data << uint32(0);
data << uint32(0);
}
+ if (castFlags & CAST_FLAG_HEAL_PREDICTION)
+ {
+ data << uint32(0);
+ data << uint8(0); // unkByte
+ // if (unkByte == 2)
+ // data.append(0);
+ }
+
m_caster->SendMessageToSet(&data, true);
}
@@ -3814,9 +3856,6 @@ void Spell::SendSpellGo()
if ((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell)
castFlags |= CAST_FLAG_PENDING;
- if (m_spellInfo->Attributes & SPELL_ATTR0_REQ_AMMO)
- castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
-
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
(m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsPet()))
&& m_spellInfo->PowerType != POWER_HEALTH)
@@ -3825,7 +3864,7 @@ void Spell::SendSpellGo()
if ((m_caster->GetTypeId() == TYPEID_PLAYER)
&& (m_caster->getClass() == CLASS_DEATH_KNIGHT)
&& m_spellInfo->RuneCostID
- && m_spellInfo->PowerType == POWER_RUNE
+ && m_spellInfo->PowerType == POWER_RUNES
&& !(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST))
{
castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it
@@ -3852,6 +3891,7 @@ void Spell::SendSpellGo()
data << uint8(m_cast_count); // pending spell cast?
data << uint32(m_spellInfo->Id); // spellId
data << uint32(castFlags); // cast flags
+ data << uint32(m_timer);
data << uint32(getMSTime()); // timestamp
WriteSpellGoTargets(&data);
@@ -3867,30 +3907,28 @@ void Spell::SendSpellGo()
//The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster
if (Player* player = m_caster->ToPlayer())
{
- uint8 runeMaskInitial = m_runesState;
- uint8 runeMaskAfterCast = player->GetRunesState();
- data << uint8(runeMaskInitial); // runes state before
- data << uint8(runeMaskAfterCast); // runes state after
+ data << uint8(m_runesState); // runes state before
+ data << uint8(player->GetRunesState()); // runes state after
for (uint8 i = 0; i < MAX_RUNES; ++i)
{
- uint8 mask = (1 << i);
- if (mask & runeMaskInitial && !(mask & runeMaskAfterCast)) // usable before andon cooldown now...
- {
- // float casts ensure the division is performed on floats as we need float result
- float baseCd = float(player->GetRuneBaseCooldown(i));
- data << uint8((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
- }
+ // float casts ensure the division is performed on floats as we need float result
+ float baseCd = float(player->GetRuneBaseCooldown(i));
+ data << uint8((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
}
}
}
+
if (castFlags & CAST_FLAG_ADJUST_MISSILE)
{
data << m_targets.GetElevation();
data << uint32(m_delayMoment);
}
- if (castFlags & CAST_FLAG_AMMO)
- WriteAmmoToPacket(&data);
+ if (castFlags & CAST_FLAG_PROJECTILE)
+ {
+ data << uint32(0); // Ammo display ID
+ data << uint32(0); // Inventory Type
+ }
if (castFlags & CAST_FLAG_VISUAL_CHAIN)
{
@@ -3903,79 +3941,21 @@ void Spell::SendSpellGo()
data << uint8(0);
}
- m_caster->SendMessageToSet(&data, true);
-}
-
-void Spell::WriteAmmoToPacket(WorldPacket* data)
-{
- uint32 ammoInventoryType = 0;
- uint32 ammoDisplayID = 0;
-
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ if (m_targets.GetTargetMask() & TARGET_FLAG_EXTRA_TARGETS)
{
- Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK);
- if (pItem)
+ data << uint32(0); // Extra targets count
+ /*
+ for (uint8 i = 0; i < count; ++i)
{
- ammoInventoryType = pItem->GetTemplate()->InventoryType;
- if (ammoInventoryType == INVTYPE_THROWN)
- ammoDisplayID = pItem->GetTemplate()->DisplayInfoID;
- else
- {
- uint32 ammoID = m_caster->ToPlayer()->GetUInt32Value(PLAYER_AMMO_ID);
- if (ammoID)
- {
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(ammoID);
- if (pProto)
- {
- ammoDisplayID = pProto->DisplayInfoID;
- ammoInventoryType = pProto->InventoryType;
- }
- }
- else if (m_caster->HasAura(46699)) // Requires No Ammo
- {
- ammoDisplayID = 5996; // normal arrow
- ammoInventoryType = INVTYPE_AMMO;
- }
- }
- }
- }
- else
- {
- for (uint8 i = 0; i < 3; ++i)
- {
- if (uint32 item_id = m_caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i))
- {
- if (ItemEntry const* itemEntry = sItemStore.LookupEntry(item_id))
- {
- if (itemEntry->Class == ITEM_CLASS_WEAPON)
- {
- switch (itemEntry->SubClass)
- {
- case ITEM_SUBCLASS_WEAPON_THROWN:
- ammoDisplayID = itemEntry->DisplayId;
- ammoInventoryType = itemEntry->InventoryType;
- break;
- case ITEM_SUBCLASS_WEAPON_BOW:
- case ITEM_SUBCLASS_WEAPON_CROSSBOW:
- ammoDisplayID = 5996; // is this need fixing?
- ammoInventoryType = INVTYPE_AMMO;
- break;
- case ITEM_SUBCLASS_WEAPON_GUN:
- ammoDisplayID = 5998; // is this need fixing?
- ammoInventoryType = INVTYPE_AMMO;
- break;
- }
-
- if (ammoDisplayID)
- break;
- }
- }
- }
+ data << float(0); // Target Position X
+ data << float(0); // Target Position Y
+ data << float(0); // Target Position Z
+ data << uint64(0); // Target Guid
}
+ */
}
- *data << uint32(ammoDisplayID);
- *data << uint32(ammoInventoryType);
+ m_caster->SendMessageToSet(&data, true);
}
/// Writes miss and hit targets for a SMSG_SPELL_GO packet
@@ -4087,11 +4067,49 @@ void Spell::ExecuteLogEffectExtraAttacks(uint8 effIndex, Unit* victim, uint32 at
*m_effectExecuteData[effIndex] << uint32(attCount);
}
-void Spell::ExecuteLogEffectInterruptCast(uint8 effIndex, Unit* victim, uint32 spellId)
-{
- InitEffectExecuteData(effIndex);
- m_effectExecuteData[effIndex]->append(victim->GetPackGUID());
- *m_effectExecuteData[effIndex] << uint32(spellId);
+void Spell::ExecuteLogEffectInterruptCast(uint8 /*effIndex*/, Unit* victim, uint32 spellId)
+{
+ ObjectGuid casterGuid = m_caster->GetGUID();
+ ObjectGuid targetGuid = victim->GetGUID();
+
+ WorldPacket data(SMSG_SPELLINTERRUPTLOG, 8 + 8 + 4 + 4);
+ data.WriteBit(targetGuid[4]);
+ data.WriteBit(casterGuid[5]);
+ data.WriteBit(casterGuid[6]);
+ data.WriteBit(casterGuid[1]);
+ data.WriteBit(casterGuid[3]);
+ data.WriteBit(casterGuid[0]);
+ data.WriteBit(targetGuid[3]);
+ data.WriteBit(targetGuid[5]);
+ data.WriteBit(targetGuid[1]);
+ data.WriteBit(casterGuid[4]);
+ data.WriteBit(casterGuid[7]);
+ data.WriteBit(targetGuid[7]);
+ data.WriteBit(targetGuid[6]);
+ data.WriteBit(targetGuid[2]);
+ data.WriteBit(casterGuid[2]);
+ data.WriteBit(targetGuid[0]);
+
+ data.WriteByteSeq(casterGuid[7]);
+ data.WriteByteSeq(casterGuid[6]);
+ data.WriteByteSeq(casterGuid[3]);
+ data.WriteByteSeq(casterGuid[2]);
+ data.WriteByteSeq(targetGuid[3]);
+ data.WriteByteSeq(targetGuid[6]);
+ data.WriteByteSeq(targetGuid[2]);
+ data.WriteByteSeq(targetGuid[4]);
+ data.WriteByteSeq(targetGuid[7]);
+ data.WriteByteSeq(targetGuid[0]);
+ data.WriteByteSeq(casterGuid[4]);
+ data << uint32(m_spellInfo->Id);
+ data.WriteByteSeq(targetGuid[1]);
+ data.WriteByteSeq(casterGuid[0]);
+ data.WriteByteSeq(casterGuid[5]);
+ data.WriteByteSeq(casterGuid[1]);
+ data << uint32(spellId);
+ data.WriteByteSeq(targetGuid[5]);
+
+ m_caster->SendMessageToSet(&data, true);
}
void Spell::ExecuteLogEffectDurabilityDamage(uint8 effIndex, Unit* victim, int32 itemId, int32 slot)
@@ -4181,7 +4199,25 @@ void Spell::SendChannelStart(uint32 duration)
data.append(m_caster->GetPackGUID());
data << uint32(m_spellInfo->Id);
data << uint32(duration);
-
+ data << uint8(0); // immunity (castflag & 0x04000000)
+ /*
+ if (immunity)
+ {
+ data << uint32(); // CastSchoolImmunities
+ data << uint32(); // CastImmunities
+ }
+ */
+ data << uint8(0); // healPrediction (castflag & 0x40000000)
+ /*
+ if (healPrediction)
+ {
+ data.appendPackGUID(channelTarget); // target packguid
+ data << uint32(); // spellid
+ data << uint8(0); // unk3
+ if (unk3 == 2)
+ data.append(); // unk packed guid (unused ?)
+ }
+ */
m_caster->SendMessageToSet(&data, true);
m_timer = duration;
@@ -4208,8 +4244,8 @@ void Spell::SendResurrectRequest(Player* target)
data << uint8(m_caster->GetTypeId() == TYPEID_PLAYER ? 0 : 1); // "you'll be afflicted with resurrection sickness"
// override delay sent with SMSG_CORPSE_RECLAIM_DELAY, set instant resurrection for spells with this attribute
- if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_RESURRECTION_TIMER)
- data << uint32(0);
+ // 4.2.2 edit : id of the spell used to resurect. (used client-side for Mass Resurect)
+ data << uint32(m_spellInfo->Id);
target->GetSession()->SendPacket(&data);
}
@@ -4297,7 +4333,7 @@ void Spell::TakePower()
bool hit = true;
if (m_caster->GetTypeId() == TYPEID_PLAYER)
{
- if (powerType == POWER_RAGE || powerType == POWER_ENERGY || powerType == POWER_RUNE)
+ if (powerType == POWER_RAGE || powerType == POWER_ENERGY || powerType == POWER_RUNES)
if (uint64 targetGUID = m_targets.GetUnitTargetGUID())
for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
if (ihit->targetGUID == targetGUID)
@@ -4313,7 +4349,7 @@ void Spell::TakePower()
}
}
- if (powerType == POWER_RUNE)
+ if (powerType == POWER_RUNES)
{
TakeRunePower(hit);
return;
@@ -4339,10 +4375,6 @@ void Spell::TakePower()
m_caster->ModifyPower(powerType, -m_powerCost);
else
m_caster->ModifyPower(powerType, -irand(0, m_powerCost/4));
-
- // Set the five second timer
- if (powerType == POWER_MANA && m_powerCost > 0)
- m_caster->SetLastManaUse(getMSTime());
}
void Spell::TakeAmmo()
@@ -4369,14 +4401,12 @@ void Spell::TakeAmmo()
m_caster->ToPlayer()->DestroyItemCount(pItem, count, true);
}
}
- else if (uint32 ammo = m_caster->ToPlayer()->GetUInt32Value(PLAYER_AMMO_ID))
- m_caster->ToPlayer()->DestroyItemCount(ammo, 1, true);
}
}
SpellCastResult Spell::CheckRuneCost(uint32 runeCostID)
{
- if (m_spellInfo->PowerType != POWER_RUNE || !runeCostID)
+ if (m_spellInfo->PowerType != POWER_RUNES || !runeCostID)
return SPELL_CAST_OK;
Player* player = m_caster->ToPlayer();
@@ -4585,6 +4615,41 @@ void Spell::HandleThreatSpells()
TC_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->_IsPositiveSpell() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size()));
}
+void Spell::HandleHolyPower(Player* caster)
+{
+ if (!caster)
+ return;
+
+ bool hit = true;
+ Player* modOwner = caster->GetSpellModOwner();
+
+ m_powerCost = caster->GetPower(POWER_HOLY_POWER); // Always use all the holy power we have
+
+ if (!m_powerCost || !modOwner)
+ return;
+
+ if (uint64 targetGUID = m_targets.GetUnitTargetGUID())
+ {
+ for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ {
+ if (ihit->targetGUID == targetGUID)
+ {
+ if (ihit->missCondition != SPELL_MISS_NONE && ihit->missCondition != SPELL_MISS_MISS)
+ hit = false;
+
+ break;
+ }
+ }
+
+ // The spell did hit the target, apply aura cost mods if there are any.
+ if (hit)
+ {
+ modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, m_powerCost);
+ m_caster->ModifyPower(POWER_HOLY_POWER, -m_powerCost);
+ }
+ }
+}
+
void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode)
{
effectHandleMode = mode;
@@ -4597,8 +4662,7 @@ void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOT
TC_LOG_DEBUG("spells", "Spell: %u Effect : %u", m_spellInfo->Id, eff);
- // we do not need DamageMultiplier here.
- damage = CalculateDamage(i, NULL);
+ damage = CalculateDamage(i, unitTarget);
bool preventDefault = CallScriptEffectHandlers((SpellEffIndex)i, mode);
@@ -4670,7 +4734,7 @@ SpellCastResult Spell::CheckCast(bool strict)
Unit::AuraEffectList const& ignore = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_SHAPESHIFT);
for (Unit::AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(m_spellInfo))
+ if (!(*i)->IsAffectingSpell(m_spellInfo))
continue;
checkForm = false;
break;
@@ -4696,7 +4760,7 @@ SpellCastResult Spell::CheckCast(bool strict)
Unit::AuraEffectList const& stateAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE);
for (Unit::AuraEffectList::const_iterator j = stateAuras.begin(); j != stateAuras.end(); ++j)
{
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
+ if ((*j)->IsAffectingSpell(m_spellInfo))
{
m_needComboPoints = false;
if ((*j)->GetMiscValue() == 1)
@@ -4728,7 +4792,8 @@ SpellCastResult Spell::CheckCast(bool strict)
// 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 && m_caster->ToPlayer()->isMoving())
+ // Do not cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect
+ if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->isMoving() && !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))
{
// skip stuck spell to allow use it in falling case and apply spell limitations at movement
if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK) &&
@@ -4836,14 +4901,14 @@ SpellCastResult Spell::CheckCast(bool strict)
if (!m_caster->ToPlayer()->InBattleground())
return SPELL_FAILED_ONLY_BATTLEGROUNDS;
- // do not allow spells to be cast in arenas
- // - with greater than 10 min CD without SPELL_ATTR4_USABLE_IN_ARENA flag
- // - with SPELL_ATTR4_NOT_USABLE_IN_ARENA flag
- if ((m_spellInfo->AttributesEx4 & SPELL_ATTR4_NOT_USABLE_IN_ARENA) ||
- (m_spellInfo->GetRecoveryTime() > 10 * MINUTE * IN_MILLISECONDS && !(m_spellInfo->AttributesEx4 & SPELL_ATTR4_USABLE_IN_ARENA)))
- if (MapEntry const* mapEntry = sMapStore.LookupEntry(m_caster->GetMapId()))
- if (mapEntry->IsBattleArena())
- return SPELL_FAILED_NOT_IN_ARENA;
+ // do not allow spells to be cast in arenas or rated battlegrounds
+ if (Player* player = m_caster->ToPlayer())
+ if (player->InArena()/* || player->InRatedBattleGround() NYI*/)
+ {
+ SpellCastResult castResult = CheckArenaAndRatedBattlegroundCastRules();
+ if (castResult != SPELL_CAST_OK)
+ return castResult;
+ }
// zone check
if (m_caster->GetTypeId() == TYPEID_UNIT || !m_caster->ToPlayer()->IsGameMaster())
@@ -4909,42 +4974,31 @@ SpellCastResult Spell::CheckCast(bool strict)
if (castResult != SPELL_CAST_OK)
return castResult;
- bool hasDispellableAura = false;
- bool hasNonDispelEffect = false;
- uint32 dispelMask = 0;
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DISPEL)
- {
- if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->AttributesEx & SPELL_ATTR1_MELEE_COMBAT_START)
- {
- hasDispellableAura = true;
- break;
- }
-
- dispelMask |= SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue));
- }
- else if (m_spellInfo->Effects[i].IsEffect())
- {
- hasNonDispelEffect = true;
- break;
- }
-
- if (!hasNonDispelEffect && !hasDispellableAura && dispelMask && !IsTriggered())
- {
- if (Unit* target = m_targets.GetUnitTarget())
- {
- DispelChargesList dispelList;
- target->GetDispellableAuraList(m_caster, dispelMask, dispelList);
- if (dispelList.empty())
- return SPELL_FAILED_NOTHING_TO_DISPEL;
- }
- }
-
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
// for effects of spells that have only one target
switch (m_spellInfo->Effects[i].Effect)
{
+ case SPELL_EFFECT_DUMMY:
+ {
+ if (m_spellInfo->Id == 19938) // Awaken Peon
+ {
+ Unit* unit = m_targets.GetUnitTarget();
+ if (!unit || !unit->HasAura(17743))
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+ else if (m_spellInfo->Id == 31789) // Righteous Defense
+ {
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ return SPELL_FAILED_DONT_REPORT;
+
+ Unit* target = m_targets.GetUnitTarget();
+ if (!target || !target->IsFriendlyTo(m_caster) || target->getAttackers().empty())
+ return SPELL_FAILED_BAD_TARGETS;
+
+ }
+ break;
+ }
case SPELL_EFFECT_LEARN_SPELL:
{
if (m_caster->GetTypeId() != TYPEID_PLAYER)
@@ -4968,6 +5022,15 @@ SpellCastResult Spell::CheckCast(bool strict)
break;
}
+ case SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB:
+ {
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ return SPELL_FAILED_BAD_TARGETS;
+ if (Guild* guild = m_caster->ToPlayer()->GetGuild())
+ if (guild->GetLeaderGUID() != m_caster->ToPlayer()->GetGUID())
+ return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
+ break;
+ }
case SPELL_EFFECT_LEARN_PET_SPELL:
{
// check target only for unit target case
@@ -5526,8 +5589,9 @@ SpellCastResult Spell::CheckCasterAuras() const
bool usableInStun = (m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_STUNNED) != 0;
// Glyph of Pain Suppression
+ // Allow Pain Suppression and Guardian Spirit to be cast while stunned
// there is no other way to handle it
- if (m_spellInfo->Id == 33206 && !m_caster->HasAura(63248))
+ if ((m_spellInfo->Id == 33206 || m_spellInfo->Id == 47788) && !m_caster->HasAura(63248))
usableInStun = false;
// Check whether the cast should be prevented by any state you might have.
@@ -5623,6 +5687,37 @@ SpellCastResult Spell::CheckCasterAuras() const
return SPELL_CAST_OK;
}
+SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules()
+{
+ bool isRatedBattleground = false; // NYI
+ bool isArena = !isRatedBattleground;
+
+ // check USABLE attributes
+ // USABLE takes precedence over NOT_USABLE
+ if (isRatedBattleground && m_spellInfo->AttributesEx9 & SPELL_ATTR9_USABLE_IN_RATED_BATTLEGROUNDS)
+ return SPELL_CAST_OK;
+
+ if (isArena && m_spellInfo->AttributesEx4 & SPELL_ATTR4_USABLE_IN_ARENA)
+ return SPELL_CAST_OK;
+
+ // check NOT_USABLE attributes
+ if (m_spellInfo->AttributesEx4 & SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG)
+ return isArena ? SPELL_FAILED_NOT_IN_ARENA : SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND;
+
+ if (isArena && m_spellInfo->AttributesEx9 & SPELL_ATTR9_NOT_USABLE_IN_ARENA)
+ return SPELL_FAILED_NOT_IN_ARENA;
+
+ // check cooldowns
+ uint32 spellCooldown = m_spellInfo->GetRecoveryTime();
+ if (isArena && spellCooldown > 10 * MINUTE * IN_MILLISECONDS) // not sure if still needed
+ return SPELL_FAILED_NOT_IN_ARENA;
+
+ if (isRatedBattleground && spellCooldown > 15 * MINUTE * IN_MILLISECONDS)
+ return SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND;
+
+ return SPELL_CAST_OK;
+}
+
bool Spell::CanAutoCast(Unit* target)
{
uint64 targetguid = target->GetGUID();
@@ -5743,8 +5838,8 @@ SpellCastResult Spell::CheckPower()
return SPELL_FAILED_UNKNOWN;
}
- //check rune cost only if a spell has PowerType == POWER_RUNE
- if (m_spellInfo->PowerType == POWER_RUNE)
+ //check rune cost only if a spell has PowerType == POWER_RUNES
+ if (m_spellInfo->PowerType == POWER_RUNES)
{
SpellCastResult failReason = CheckRuneCost(m_spellInfo->RuneCostID);
if (failReason != SPELL_CAST_OK)
@@ -5913,25 +6008,7 @@ SpellCastResult Spell::CheckItems()
totems -= 1;
}
if (totems != 0)
- return SPELL_FAILED_TOTEMS; //0x7C
-
- // Check items for TotemCategory (items presence in inventory)
- uint32 TotemCategory = 2;
- for (uint8 i = 0; i < 2; ++i)
- {
- if (m_spellInfo->TotemCategory[i] != 0)
- {
- if (player->HasItemTotemCategory(m_spellInfo->TotemCategory[i]))
- {
- TotemCategory -= 1;
- continue;
- }
- }
- else
- TotemCategory -= 1;
- }
- if (TotemCategory != 0)
- return SPELL_FAILED_TOTEM_CATEGORY; //0x7B
+ return SPELL_FAILED_TOTEMS;
}
// special checks for spell effects
@@ -5971,7 +6048,7 @@ SpellCastResult Spell::CheckItems()
}
case SPELL_EFFECT_ENCHANT_ITEM:
if (m_spellInfo->Effects[i].ItemType && m_targets.GetItemTarget()
- && (m_targets.GetItemTarget()->IsWeaponVellum() || m_targets.GetItemTarget()->IsArmorVellum()))
+ && (m_targets.GetItemTarget()->IsVellum()))
{
// cannot enchant vellum for other player
if (m_targets.GetItemTarget()->GetOwner() != m_caster)
@@ -6163,47 +6240,6 @@ SpellCastResult Spell::CheckItems()
case ITEM_SUBCLASS_WEAPON_GUN:
case ITEM_SUBCLASS_WEAPON_BOW:
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
- {
- uint32 ammo = player->GetUInt32Value(PLAYER_AMMO_ID);
- if (!ammo)
- {
- // Requires No Ammo
- if (m_caster->HasAura(46699))
- break; // skip other checks
-
- return SPELL_FAILED_NO_AMMO;
- }
-
- ItemTemplate const* ammoProto = sObjectMgr->GetItemTemplate(ammo);
- if (!ammoProto)
- return SPELL_FAILED_NO_AMMO;
-
- if (ammoProto->Class != ITEM_CLASS_PROJECTILE)
- return SPELL_FAILED_NO_AMMO;
-
- // check ammo ws. weapon compatibility
- switch (pItem->GetTemplate()->SubClass)
- {
- case ITEM_SUBCLASS_WEAPON_BOW:
- case ITEM_SUBCLASS_WEAPON_CROSSBOW:
- if (ammoProto->SubClass != ITEM_SUBCLASS_ARROW)
- return SPELL_FAILED_NO_AMMO;
- break;
- case ITEM_SUBCLASS_WEAPON_GUN:
- if (ammoProto->SubClass != ITEM_SUBCLASS_BULLET)
- return SPELL_FAILED_NO_AMMO;
- break;
- default:
- return SPELL_FAILED_NO_AMMO;
- }
-
- if (!player->HasItemCount(ammo))
- {
- player->SetUInt32Value(PLAYER_AMMO_ID, 0);
- return SPELL_FAILED_NO_AMMO;
- }
- break;
- }
case ITEM_SUBCLASS_WEAPON_WAND:
break;
default:
@@ -6491,7 +6527,7 @@ bool Spell::IsAutoActionResetSpell() const
bool Spell::IsNeedSendToClient() const
{
return m_spellInfo->SpellVisual[0] || m_spellInfo->SpellVisual[1] || m_spellInfo->IsChanneled() ||
- m_spellInfo->Speed > 0.0f || (!m_triggeredByAuraSpell && !IsTriggered());
+ (m_spellInfo->AttributesEx8 & SPELL_ATTR8_AURA_SEND_AMOUNT) || m_spellInfo->Speed > 0.0f || (!m_triggeredByAuraSpell && !IsTriggered());
}
bool Spell::HaveTargetsForEffect(uint8 effect) const
@@ -6659,12 +6695,6 @@ void Spell::HandleLaunchPhase()
multiplier[i] = m_spellInfo->Effects[i].CalcDamageMultiplier(m_originalCaster, this);
bool usesAmmo = (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_DIRECT_DAMAGE) != 0;
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_CONSUME_NO_AMMO);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- {
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- usesAmmo=false;
- }
for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
@@ -7151,7 +7181,7 @@ void Spell::PrepareTriggersExecutedOnHit()
Unit::AuraEffectList const& targetTriggers = m_caster->GetAuraEffectsByType(SPELL_AURA_ADD_TARGET_TRIGGER);
for (Unit::AuraEffectList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i)
{
- if (!(*i)->IsAffectedOnSpell(m_spellInfo))
+ if (!(*i)->IsAffectingSpell(m_spellInfo))
continue;
SpellInfo const* auraSpellInfo = (*i)->GetSpellInfo();
uint32 auraSpellIdx = (*i)->GetEffIndex();
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 9c4891b95f4..5b976ced426 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -40,11 +40,11 @@ enum SpellCastFlags
{
CAST_FLAG_NONE = 0x00000000,
CAST_FLAG_PENDING = 0x00000001, // aoe combat log?
- CAST_FLAG_UNKNOWN_2 = 0x00000002,
+ CAST_FLAG_HAS_TRAJECTORY = 0x00000002,
CAST_FLAG_UNKNOWN_3 = 0x00000004,
CAST_FLAG_UNKNOWN_4 = 0x00000008, // ignore AOE visual
CAST_FLAG_UNKNOWN_5 = 0x00000010,
- CAST_FLAG_AMMO = 0x00000020, // Projectiles visual
+ CAST_FLAG_PROJECTILE = 0x00000020,
CAST_FLAG_UNKNOWN_7 = 0x00000040,
CAST_FLAG_UNKNOWN_8 = 0x00000080,
CAST_FLAG_UNKNOWN_9 = 0x00000100,
@@ -69,7 +69,7 @@ enum SpellCastFlags
CAST_FLAG_UNKNOWN_28 = 0x08000000,
CAST_FLAG_UNKNOWN_29 = 0x10000000,
CAST_FLAG_UNKNOWN_30 = 0x20000000,
- CAST_FLAG_UNKNOWN_31 = 0x40000000,
+ CAST_FLAG_HEAL_PREDICTION = 0x40000000,
CAST_FLAG_UNKNOWN_32 = 0x80000000
};
@@ -258,7 +258,7 @@ class Spell
void EffectQuestClear(SpellEffIndex effIndex);
void EffectTeleUnitsFaceCaster(SpellEffIndex effIndex);
void EffectLearnSkill(SpellEffIndex effIndex);
- void EffectAddHonor(SpellEffIndex effIndex);
+ void EffectPlayMovie(SpellEffIndex effIndex);
void EffectTradeSkill(SpellEffIndex effIndex);
void EffectEnchantItemPerm(SpellEffIndex effIndex);
void EffectEnchantItemTmp(SpellEffIndex effIndex);
@@ -323,6 +323,7 @@ class Spell
void EffectEnergizePct(SpellEffIndex effIndex);
void EffectTriggerRitualOfSummoning(SpellEffIndex effIndex);
void EffectSummonRaFFriend(SpellEffIndex effIndex);
+ void EffectUnlockGuildVaultTab(SpellEffIndex effIndex);
void EffectKillCreditPersonal(SpellEffIndex effIndex);
void EffectKillCredit(SpellEffIndex effIndex);
void EffectQuestFail(SpellEffIndex effIndex);
@@ -341,8 +342,12 @@ class Spell
void EffectActivateSpec(SpellEffIndex effIndex);
void EffectPlaySound(SpellEffIndex effIndex);
void EffectRemoveAura(SpellEffIndex effIndex);
+ void EffectDamageFromMaxHealthPCT(SpellEffIndex effIndex);
void EffectCastButtons(SpellEffIndex effIndex);
void EffectRechargeManaGem(SpellEffIndex effIndex);
+ void EffectGiveCurrency(SpellEffIndex effIndex);
+ void EffectResurrectWithAura(SpellEffIndex effIndex);
+ void EffectCreateAreaTrigger(SpellEffIndex effIndex);
typedef std::set<Aura*> UsedSpellMods;
@@ -404,6 +409,7 @@ class Spell
SpellCastResult CheckPower();
SpellCastResult CheckRuneCost(uint32 runeCostID);
SpellCastResult CheckCasterAuras() const;
+ SpellCastResult CheckArenaAndRatedBattlegroundCastRules();
int32 CalculateDamage(uint8 i, Unit const* target) const { return m_caster->CalculateSpellDamage(target, m_spellInfo, i, &m_spellValue->EffectBasePoints[i]); }
@@ -415,15 +421,13 @@ class Spell
void DoCreateItem(uint32 i, uint32 itemtype);
void WriteSpellGoTargets(WorldPacket* data);
- void WriteAmmoToPacket(WorldPacket* data);
bool CheckEffectTarget(Unit const* target, uint32 eff) const;
bool CanAutoCast(Unit* target);
void CheckSrc() { if (!m_targets.HasSrc()) m_targets.SetSrc(*m_caster); }
void CheckDst() { if (!m_targets.HasDst()) m_targets.SetDst(*m_caster); }
- static void WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError);
- static void SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE);
+ static void SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE, Opcodes opcode = SMSG_CAST_FAILED);
void SendCastResult(SpellCastResult result);
void SendPetCastResult(SpellCastResult result);
void SendSpellStart();
@@ -445,6 +449,7 @@ class Spell
void SendChannelStart(uint32 duration);
void SendResurrectRequest(Player* target);
+ void HandleHolyPower(Player* caster);
void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode);
void HandleThreatSpells();
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 0ee494d2898..7623550d736 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -62,7 +62,10 @@
#include "AccountMgr.h"
#include "InstanceScript.h"
#include "PathGenerator.h"
+#include "Guild.h"
+#include "GuildMgr.h"
#include "ReputationMgr.h"
+#include "AreaTrigger.h"
pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
{
@@ -111,14 +114,14 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectJumpDest, // 42 SPELL_EFFECT_JUMP_DEST
&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
+ &Spell::EffectPlayMovie, // 45 SPELL_EFFECT_PLAY_MOVIE
&Spell::EffectUnused, // 46 SPELL_EFFECT_SPAWN clientside, unit appears as if it was just spawned
&Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
&Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
&Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
&Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
&Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
- &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
+ &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT unused
&Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
&Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
&Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
@@ -229,8 +232,26 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectNULL, //160 SPELL_EFFECT_160 1 spell - 45534
&Spell::EffectSpecCount, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
&Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
- &Spell::EffectNULL, //163 unused
+ &Spell::EffectUnused, //163 SPELL_EFFECT_163 unused
&Spell::EffectRemoveAura, //164 SPELL_EFFECT_REMOVE_AURA
+ &Spell::EffectDamageFromMaxHealthPCT, //165 SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT
+ &Spell::EffectGiveCurrency, //166 SPELL_EFFECT_GIVE_CURRENCY
+ &Spell::EffectNULL, //167 SPELL_EFFECT_167
+ &Spell::EffectNULL, //168 SPELL_EFFECT_168
+ &Spell::EffectNULL, //169 SPELL_EFFECT_DESTROY_ITEM
+ &Spell::EffectNULL, //170 SPELL_EFFECT_170
+ &Spell::EffectNULL, //171 SPELL_EFFECT_171
+ &Spell::EffectResurrectWithAura, //172 SPELL_EFFECT_RESURRECT_WITH_AURA
+ &Spell::EffectUnlockGuildVaultTab, //173 SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
+ &Spell::EffectNULL, //174 SPELL_EFFECT_174
+ &Spell::EffectUnused, //175 SPELL_EFFECT_175 unused
+ &Spell::EffectNULL, //176 SPELL_EFFECT_176
+ &Spell::EffectNULL, //177 SPELL_EFFECT_177
+ &Spell::EffectUnused, //178 SPELL_EFFECT_178 unused
+ &Spell::EffectCreateAreaTrigger, //179 SPELL_EFFECT_CREATE_AREATRIGGER
+ &Spell::EffectUnused, //180 SPELL_EFFECT_180 unused
+ &Spell::EffectUnused, //181 SPELL_EFFECT_181 unused
+ &Spell::EffectNULL, //182 SPELL_EFFECT_182
};
void Spell::EffectNULL(SpellEffIndex /*effIndex*/)
@@ -259,13 +280,13 @@ void Spell::EffectResurrectNew(SpellEffIndex effIndex)
Player* target = unitTarget->ToPlayer();
- if (target->isResurrectRequested()) // already have one active request
+ if (target->IsResurrectRequested()) // already have one active request
return;
uint32 health = damage;
uint32 mana = m_spellInfo->Effects[effIndex].MiscValue;
ExecuteLogEffectResurrect(effIndex, target);
- target->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
+ target->SetResurrectRequestData(m_caster, health, mana, 0);
SendResurrectRequest(target);
}
@@ -368,15 +389,8 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
}
case SPELLFAMILY_WARRIOR:
{
- // Shield Slam
- if (m_spellInfo->SpellFamilyFlags[1] & 0x200 && m_spellInfo->GetCategory() == 1209)
- {
- uint8 level = m_caster->getLevel();
- uint32 block_value = m_caster->GetShieldBlockValue(uint32(float(level) * 24.5f), uint32(float(level) * 34.5f));
- damage += int32(m_caster->ApplyEffectModifiers(m_spellInfo, effIndex, float(block_value)));
- }
// Victory Rush
- else if (m_spellInfo->SpellFamilyFlags[1] & 0x100)
+ if (m_spellInfo->Id == 34428)
ApplyPct(damage, m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
// Shockwave
else if (m_spellInfo->Id == 46968)
@@ -393,73 +407,12 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
// Incinerate Rank 1 & 2
if ((m_spellInfo->SpellFamilyFlags[1] & 0x000040) && m_spellInfo->SpellIconID == 2128)
{
- // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
+ // Incinerate does more dmg (dmg/6) if the target have Immolate debuff.
// Check aura state for speed but aura state set not only for Immolate spell
if (unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
{
if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x4, 0, 0))
- damage += damage/4;
- }
- }
- // Conflagrate - consumes Immolate or Shadowflame
- else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
- {
- AuraEffect const* aura = NULL; // found req. aura for damage calculation
-
- Unit::AuraEffectList const &mPeriodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE);
- for (Unit::AuraEffectList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
- {
- // for caster applied auras only
- if ((*i)->GetSpellInfo()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
- (*i)->GetCasterGUID() != m_caster->GetGUID())
- continue;
-
- // Immolate
- if ((*i)->GetSpellInfo()->SpellFamilyFlags[0] & 0x4)
- {
- aura = *i; // it selected always if exist
- break;
- }
-
- // Shadowflame
- if ((*i)->GetSpellInfo()->SpellFamilyFlags[2] & 0x00000002)
- aura = *i; // remember but wait possible Immolate as primary priority
- }
-
- // found Immolate or Shadowflame
- if (aura)
- {
- uint32 pdamage = uint32(std::max(aura->GetAmount(), 0));
- pdamage = m_caster->SpellDamageBonusDone(unitTarget, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
- pdamage = unitTarget->SpellDamageBonusTaken(m_caster, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
- uint32 pct_dir = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 1));
- uint8 baseTotalTicks = uint8(m_caster->CalcSpellDuration(aura->GetSpellInfo()) / aura->GetSpellInfo()->Effects[EFFECT_0].Amplitude);
- damage += int32(CalculatePct(pdamage * baseTotalTicks, pct_dir));
-
- uint32 pct_dot = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 2)) / 3;
- m_spellValue->EffectBasePoints[1] = m_spellInfo->Effects[EFFECT_1].CalcBaseValue(int32(CalculatePct(pdamage * baseTotalTicks, pct_dot)));
-
- apply_direct_bonus = false;
- // Glyph of Conflagrate
- if (!m_caster->HasAura(56235))
- unitTarget->RemoveAurasDueToSpell(aura->GetId(), m_caster->GetGUID());
-
- break;
- }
- }
- // Shadow Bite
- else if (m_spellInfo->SpellFamilyFlags[1] & 0x400000)
- {
- if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsPet())
- {
- if (Player* owner = m_caster->GetOwner()->ToPlayer())
- {
- if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARLOCK, 214, 0))
- {
- int32 bp0 = aurEff->GetId() == 54037 ? 4 : 8;
- m_caster->CastCustomSpell(m_caster, 54425, &bp0, NULL, NULL, true);
- }
- }
+ damage += damage / 6;
}
}
break;
@@ -490,20 +443,10 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
// Ferocious Bite
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/410) additional damage
- float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
- float multiple = ap / 410 + m_spellInfo->Effects[effIndex].DamageMultiplier;
- int32 energy = -(m_caster->ModifyPower(POWER_ENERGY, -30));
- damage += int32(energy * multiple);
- damage += int32(CalculatePct(m_caster->ToPlayer()->GetComboPoints() * ap, 7));
- }
- // Wrath
- else if (m_spellInfo->SpellFamilyFlags[0] & 0x00000001)
- {
- // Improved Insect Swarm
- if (AuraEffect const* aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 1771, 0))
- if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00200000, 0, 0))
- AddPct(damage, aurEff->GetAmount());
+ // converts each extra point of energy ( up to 25 energy ) into additional damage
+ int32 energy = -(m_caster->ModifyPower(POWER_ENERGY, -25));
+ // 25 energy = 100% more damage
+ AddPct(damage, energy * 4);
}
break;
}
@@ -575,77 +518,6 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
}
break;
}
- case SPELLFAMILY_HUNTER:
- {
- //Gore
- if (m_spellInfo->SpellIconID == 1578)
- {
- if (m_caster->HasAura(57627)) // Charge 6 sec post-affect
- damage *= 2;
- }
- // Steady Shot
- else if (m_spellInfo->SpellFamilyFlags[1] & 0x1)
- {
- bool found = false;
- // check dazed affect
- Unit::AuraEffectList const& decSpeedList = unitTarget->GetAuraEffectsByType(SPELL_AURA_MOD_DECREASE_SPEED);
- for (Unit::AuraEffectList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
- {
- if ((*iter)->GetSpellInfo()->SpellIconID == 15 && (*iter)->GetSpellInfo()->Dispel == 0)
- {
- found = true;
- break;
- }
- }
-
- /// @todo should this be put on taken but not done?
- if (found)
- damage += m_spellInfo->Effects[EFFECT_1].CalcValue();
-
- if (Player* caster = m_caster->ToPlayer())
- {
- // Add Ammo and Weapon damage plus RAP * 0.1
- if (Item* item = caster->GetWeaponForAttack(RANGED_ATTACK))
- {
- ItemTemplate const* weaponTemplate = item->GetTemplate();
- float dmg_min = weaponTemplate->Damage[0].DamageMin;
- float dmg_max = weaponTemplate->Damage[0].DamageMax;
- if (dmg_max == 0.0f && dmg_min > dmg_max)
- damage += int32(dmg_min);
- else
- damage += irand(int32(dmg_min), int32(dmg_max));
- damage += int32(caster->GetAmmoDPS() * weaponTemplate->Delay * 0.001f);
- }
- }
- }
- break;
- }
- case SPELLFAMILY_PALADIN:
- {
- // Hammer of the Righteous
- if (m_spellInfo->SpellFamilyFlags[1]&0x00040000)
- {
- float min_damage = m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE);
- float max_damage = m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE);
- if (Player* player = m_caster->ToPlayer()) // UNIT_FIELD_MINDAMAGE/MAXDAMAGE already include damage bonuses, so try to get them without damage bonuses
- player->CalculateMinMaxDamage(BASE_ATTACK, false, false, min_damage, max_damage);
-
- float average = (min_damage + max_damage) / 2;
- // Add main hand dps * effect[2] amount
- int32 count = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, EFFECT_2);
- damage += count * int32(average * IN_MILLISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
- break;
- }
- // Shield of Righteousness
- if (m_spellInfo->SpellFamilyFlags[EFFECT_1] & 0x100000)
- {
- uint8 level = m_caster->getLevel();
- uint32 block_value = m_caster->GetShieldBlockValue(uint32(float(level) * 29.5f), uint32(float(level) * 39.5f));
- damage += CalculatePct(block_value, m_spellInfo->Effects[EFFECT_1].CalcValue());
- break;
- }
- break;
- }
case SPELLFAMILY_DEATHKNIGHT:
{
// Blood Boil - bonus for diseased targets
@@ -755,15 +627,6 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
// special cases
switch (triggered_spell_id)
{
- // Mirror Image
- case 58832:
- {
- // Glyph of Mirror Image
- if (m_caster->HasAura(63093))
- m_caster->CastSpell(m_caster, 65047, true); // Mirror Image
-
- break;
- }
// Vanish (not exist)
case 18461:
{
@@ -796,10 +659,6 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
unitTarget->CastSpell(unitTarget, 7870, true);
return;
}
- // just skip
- case 23770: // Sayge's Dark Fortune of *
- // not exist, common cooldown can be implemented in scripts if need.
- return;
// Brittle Armor - (need add max stack of 24575 Brittle Armor)
case 29284:
{
@@ -1261,12 +1120,7 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex)
damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
- // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
- int32 power = damage;
- if (powerType == POWER_MANA)
- power -= unitTarget->GetSpellCritDamageReduction(power);
-
- int32 newDamage = -(unitTarget->ModifyPower(powerType, -int32(power)));
+ int32 newDamage = -(unitTarget->ModifyPower(powerType, -damage));
float gainMultiplier = 0.0f;
@@ -1344,12 +1198,7 @@ void Spell::EffectPowerBurn(SpellEffIndex effIndex)
damage = std::min(damage, maxDamage);
}
- int32 power = damage;
- // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
- if (powerType == POWER_MANA)
- power -= unitTarget->GetSpellCritDamageReduction(power);
-
- int32 newDamage = -(unitTarget->ModifyPower(powerType, -power));
+ int32 newDamage = -(unitTarget->ModifyPower(powerType, -damage));
// NO - Not a typo - EffectPowerBurn uses effect value multiplier - not effect damage multiplier
float dmgMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this);
@@ -1443,22 +1292,6 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
//addhealth += tickheal * tickcount;
//addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth, HEAL, unitTarget);
}
- // Nourish
- else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[1] & 0x2000000)
- {
- addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
-
- // Glyph of Nourish
- if (AuraEffect const* aurEff = m_caster->GetAuraEffect(62971, 0))
- {
- Unit::AuraEffectList const& Periodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
- for (Unit::AuraEffectList::const_iterator i = Periodic.begin(); i != Periodic.end(); ++i)
- {
- if (m_caster->GetGUID() == (*i)->GetCasterGUID())
- AddPct(addhealth, aurEff->GetAmount());
- }
- }
- }
// Death Pact - return pct of max health to caster
else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000)
addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(caster->CountPctFromMaxHealth(damage)), HEAL);
@@ -1604,7 +1437,7 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype)
if (msg != EQUIP_ERR_OK)
{
// convert to possible store amount
- if (msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS)
+ if (msg == EQUIP_ERR_INV_FULL || msg == EQUIP_ERR_ITEM_MAX_COUNT)
num_to_add -= no_space;
else
{
@@ -1633,6 +1466,11 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype)
// send info to the client
player->SendNewItem(pItem, num_to_add, true, bgType == 0);
+ if (pProto->Quality > ITEM_QUALITY_EPIC || (pProto->Quality == ITEM_QUALITY_EPIC && pProto->ItemLevel >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)]))
+ if (Guild* guild = player->GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_ITEM_CRAFTED, player->GetGUID(), 0, pProto->ItemId);
+
+
// we succeeded in creating at least one item, so a levelup is possible
if (bgType == 0)
player->UpdateCraftSkill(m_spellInfo->Id);
@@ -1721,7 +1559,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex)
if (!caster->IsInWorld())
return;
DynamicObject* dynObj = new DynamicObject(false);
- if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL))
+ if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL))
{
delete dynObj;
return;
@@ -1779,13 +1617,10 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
level_multiplier = 4;
break;
case 31930: // Judgements of the Wise
- case 63375: // Improved Stormstrike
+ case 63375: // Primal Wisdom
case 68082: // Glyph of Seal of Command
damage = int32(CalculatePct(unitTarget->GetCreateMana(), damage));
break;
- case 48542: // Revitalize
- damage = int32(CalculatePct(unitTarget->GetMaxPower(power), damage));
- break;
case 67490: // Runic Mana Injector (mana gain increased by 25% for engineers - 3.2.0 patch change)
{
if (Player* player = m_caster->ToPlayer())
@@ -1793,9 +1628,6 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
AddPct(damage, 25);
break;
}
- case 71132: // Glyph of Shadow Word: Pain
- damage = int32(CalculatePct(unitTarget->GetCreateMana(), 1)); // set 1 as value, missing in dbc
- break;
default:
break;
}
@@ -1803,7 +1635,7 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
if (level_diff > 0)
damage -= level_multiplier * level_diff;
- if (damage < 0)
+ if (damage < 0 && power != POWER_ECLIPSE)
return;
m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
@@ -2141,9 +1973,9 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex)
uint8 msg = player->CanEquipItem(m_CastItem->GetSlot(), dest, pNewItem, true);
- if (msg == EQUIP_ERR_OK || msg == EQUIP_ERR_CANT_DO_RIGHT_NOW)
+ if (msg == EQUIP_ERR_OK || msg == EQUIP_ERR_CLIENT_LOCKED_OUT)
{
- if (msg == EQUIP_ERR_CANT_DO_RIGHT_NOW) dest = EQUIPMENT_SLOT_MAINHAND;
+ if (msg == EQUIP_ERR_CLIENT_LOCKED_OUT) dest = EQUIPMENT_SLOT_MAINHAND;
// prevent crash at access and unexpected charges counting with item update queue corrupt
if (m_CastItem == m_targets.GetItemTarget())
@@ -2484,7 +2316,7 @@ void Spell::EffectDispel(SpellEffIndex effIndex)
// Devour Magic
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->GetCategory() == SPELLCATEGORY_DEVOUR_MAGIC)
{
- int32 heal_amount = m_spellInfo->Effects[EFFECT_1].CalcValue();
+ int32 heal_amount = m_spellInfo->Effects[EFFECT_1].CalcValue(m_caster);
m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
// Glyph of Felhunter
if (Unit* owner = m_caster->GetOwner())
@@ -2559,7 +2391,7 @@ void Spell::EffectAddFarsight(SpellEffIndex effIndex)
return;
DynamicObject* dynObj = new DynamicObject(true);
- if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
+ if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
{
delete dynObj;
return;
@@ -2624,7 +2456,7 @@ void Spell::EffectLearnSkill(SpellEffIndex effIndex)
unitTarget->ToPlayer()->SetSkill(skillid, m_spellInfo->Effects[effIndex].CalcValue(), std::max<uint16>(skillval, 1), tier->MaxSkill[damage - 1]);
}
-void Spell::EffectAddHonor(SpellEffIndex /*effIndex*/)
+void Spell::EffectPlayMovie(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
@@ -2632,27 +2464,11 @@ void Spell::EffectAddHonor(SpellEffIndex /*effIndex*/)
if (unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
- // not scale value for item based reward (/10 value expected)
- if (m_CastItem)
- {
- unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage/10);
- TC_LOG_DEBUG("spells", "SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(), unitTarget->ToPlayer()->GetGUIDLow());
+ uint32 movieId = GetSpellInfo()->Effects[effIndex].MiscValue;
+ if (!sMovieStore.LookupEntry(movieId))
return;
- }
- // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
- if (damage <= 50)
- {
- uint32 honor_reward = Trinity::Honor::hk_honor_at_level(unitTarget->getLevel(), float(damage));
- unitTarget->ToPlayer()->RewardHonor(NULL, 1, honor_reward);
- TC_LOG_DEBUG("spells", "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, unitTarget->ToPlayer()->GetGUIDLow());
- }
- else
- {
- //maybe we have correct honor_gain in damage already
- unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage);
- TC_LOG_DEBUG("spells", "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, unitTarget->ToPlayer()->GetGUIDLow());
- }
+ unitTarget->ToPlayer()->SendMovieStart(movieId);
}
void Spell::EffectTradeSkill(SpellEffIndex /*effIndex*/)
@@ -2680,7 +2496,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex)
return;
// Handle vellums
- if (itemTarget->IsWeaponVellum() || itemTarget->IsArmorVellum())
+ if (itemTarget->IsVellum())
{
// destroy one vellum from stack
uint32 count = 1;
@@ -2804,58 +2620,6 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex)
if (!player)
return;
- // Rockbiter Weapon apply to both weapon
- if (!itemTarget)
- return;
- if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[0] & 0x400000)
- {
- uint32 spell_id = 0;
-
- // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
- // Note: damage calculated (correctly) with rounding int32(float(v)) but
- // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
- switch (damage)
- {
- // Rank 1
- case 2: spell_id = 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
- // Rank 2
- case 4: spell_id = 36753; break; // 0% [ 7% == 4, 14% == 4]
- case 5: spell_id = 36751; break; // 20%
- // Rank 3
- case 6: spell_id = 36754; break; // 0% [ 7% == 6, 14% == 6]
- case 7: spell_id = 36755; break; // 20%
- // Rank 4
- case 9: spell_id = 36761; break; // 0% [ 7% == 6]
- case 10: spell_id = 36758; break; // 14%
- case 11: spell_id = 36760; break; // 20%
- default:
- TC_LOG_ERROR("spells", "Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW", damage);
- return;
- }
-
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
- if (!spellInfo)
- {
- TC_LOG_ERROR("spells", "Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id);
- return;
-
- }
-
- for (int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
- {
- if (Item* item = player->GetWeaponForAttack(WeaponAttackType(j)))
- {
- if (item->IsFitToSpellRequirements(m_spellInfo))
- {
- Spell* spell = new Spell(m_caster, spellInfo, TRIGGERED_FULL_MASK);
- SpellCastTargets targets;
- targets.SetItemTarget(item);
- spell->prepare(&targets);
- }
- }
- }
- return;
- }
if (!itemTarget)
return;
@@ -3106,9 +2870,6 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
return;
}
- if (m_spellInfo->Id == 62124)
- m_caster->CastSpell(unitTarget, 67485, true);
-
// Also use this effect to set the taunter's threat to the taunted creature's highest value
if (unitTarget->getThreatManager().getCurrentVictim())
{
@@ -3170,74 +2931,26 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
if (Aura* aur = unitTarget->GetAura(58567, m_caster->GetGUID()))
{
- // 58388 - Glyph of Devastate dummy aura.
- if (int32 num = (needCast ? 0 : 1) + (m_caster->HasAura(58388) ? 1 : 0))
+ if (int32 num = (needCast ? 0 : 1))
aur->ModStackAmount(num);
fixed_bonus += (aur->GetStackAmount() - 1) * CalculateDamage(2, unitTarget);
}
}
- if (m_spellInfo->SpellFamilyFlags[0] & 0x8000000) // Mocking Blow
- {
- if (unitTarget->IsImmunedToSpellEffect(m_spellInfo, EFFECT_1) || unitTarget->GetTypeId() == TYPEID_PLAYER)
- {
- m_damage = 0;
- return;
- }
- }
break;
}
case SPELLFAMILY_ROGUE:
{
- // Fan of Knives, Hemorrhage, Ghostly Strike
- if ((m_spellInfo->SpellFamilyFlags[1] & 0x40000)
- || (m_spellInfo->SpellFamilyFlags[0] & 0x6000000))
+ // Hemorrhage
+ if (m_spellInfo->SpellFamilyFlags[0] & 0x2000000)
{
- // Hemorrhage
- if (m_spellInfo->SpellFamilyFlags[0] & 0x2000000)
- {
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
- m_caster->ToPlayer()->AddComboPoints(unitTarget, 1, this);
- }
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ m_caster->ToPlayer()->AddComboPoints(unitTarget, 1, this);
// 50% more damage with daggers
if (m_caster->GetTypeId() == TYPEID_PLAYER)
if (Item* item = m_caster->ToPlayer()->GetWeaponForAttack(m_attackType, true))
if (item->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
totalDamagePercentMod *= 1.5f;
}
- // Mutilate (for each hand)
- else if (m_spellInfo->SpellFamilyFlags[1] & 0x6)
- {
- bool found = false;
- // fast check
- if (unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON, m_spellInfo, m_caster))
- found = true;
- // full aura scan
- else
- {
- Unit::AuraApplicationMap const& auras = unitTarget->GetAppliedAuras();
- for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
- {
- if (itr->second->GetBase()->GetSpellInfo()->Dispel == DISPEL_POISON)
- {
- found = true;
- break;
- }
- }
- }
-
- if (found)
- totalDamagePercentMod *= 1.2f; // 120% if poisoned
- }
- break;
- }
- case SPELLFAMILY_PALADIN:
- {
- // Seal of Command Unleashed
- if (m_spellInfo->Id == 20467)
- {
- spell_bonus += int32(0.08f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
- spell_bonus += int32(0.13f * m_caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()));
- }
break;
}
case SPELLFAMILY_SHAMAN:
@@ -3268,54 +2981,35 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
{
// Kill Shot - bonus damage from Ranged Attack Power
if (m_spellInfo->SpellFamilyFlags[1] & 0x800000)
- spell_bonus += int32(0.4f * m_caster->GetTotalAttackPowerValue(RANGED_ATTACK));
+ spell_bonus += int32(0.45f * m_caster->GetTotalAttackPowerValue(RANGED_ATTACK));
break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
- // Plague Strike
- if (m_spellInfo->SpellFamilyFlags[0] & 0x1)
- {
- // Glyph of Plague Strike
- if (AuraEffect const* aurEff = m_caster->GetAuraEffect(58657, EFFECT_0))
- AddPct(totalDamagePercentMod, aurEff->GetAmount());
- break;
- }
// Blood Strike
if (m_spellInfo->SpellFamilyFlags[0] & 0x400000)
{
- float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f;
+ float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f;
// Death Knight T8 Melee 4P Bonus
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
AddPct(bonusPct, aurEff->GetAmount());
AddPct(totalDamagePercentMod, bonusPct);
-
- // Glyph of Blood Strike
- if (m_caster->GetAuraEffect(59332, EFFECT_0))
- if (unitTarget->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
- AddPct(totalDamagePercentMod, 20);
break;
}
// Death Strike
if (m_spellInfo->SpellFamilyFlags[0] & 0x10)
{
// Glyph of Death Strike
+ // 2% more damage per 5 runic power, up to a maximum of 40%
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(59336, EFFECT_0))
- if (uint32 runic = std::min<uint32>(m_caster->GetPower(POWER_RUNIC_POWER), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()))
+ if (uint32 runic = std::min<uint32>(uint32(m_caster->GetPower(POWER_RUNIC_POWER) / 2.5f), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(m_caster)))
AddPct(totalDamagePercentMod, runic);
break;
}
// Obliterate (12.5% more damage per disease)
if (m_spellInfo->SpellFamilyFlags[1] & 0x20000)
{
- bool consumeDiseases = true;
- // Annihilation
- if (AuraEffect const* aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2710, EFFECT_0))
- // Do not consume diseases if roll sucesses
- if (roll_chance_i(aurEff->GetAmount()))
- consumeDiseases = false;
-
- float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), consumeDiseases) / 2.0f;
+ float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), false) / 2.0f;
// Death Knight T8 Melee 4P Bonus
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
AddPct(bonusPct, aurEff->GetAmount());
@@ -3331,7 +3025,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
// Heart Strike
if (m_spellInfo->SpellFamilyFlags[0] & 0x1000000)
{
- float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID());
+ float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID());
// Death Knight T8 Melee 4P Bonus
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
AddPct(bonusPct, aurEff->GetAmount());
@@ -3475,7 +3169,7 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex)
// check if we can interrupt spell
if ((spell->getState() == SPELL_STATE_CASTING
|| (spell->getState() == SPELL_STATE_PREPARING && spell->GetCastTime() > 0.0f))
- && curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE
+ && (curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE || curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_UNK)
&& ((i == CURRENT_GENERIC_SPELL && curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT)
|| (i == CURRENT_CHANNELED_SPELL && curSpellInfo->ChannelInterruptFlags & CHANNEL_INTERRUPT_FLAG_INTERRUPT)))
{
@@ -3519,6 +3213,9 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
return;
}
+ for (auto phase : m_caster->GetPhases())
+ pGameObj->SetInPhase(phase, false, true);
+
int32 duration = m_spellInfo->GetDuration();
pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
@@ -3540,6 +3237,9 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
if (linkedGO->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
{
+ for (auto phase : m_caster->GetPhases())
+ linkedGO->SetInPhase(phase, false, true);
+
linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
linkedGO->SetSpellId(m_spellInfo->Id);
@@ -4098,7 +3798,7 @@ void Spell::EffectSanctuary(SpellEffIndex /*effIndex*/)
// Vanish allows to remove all threat and cast regular stealth so other spells can be used
if (m_caster->GetTypeId() == TYPEID_PLAYER
&& m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE
- && (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_VANISH))
+ && (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG0_ROGUE_VANISH))
{
m_caster->ToPlayer()->RemoveAurasByType(SPELL_AURA_MOD_ROOT);
// Overkill
@@ -4161,7 +3861,7 @@ void Spell::EffectDuel(SpellEffIndex effIndex)
Map* map = m_caster->GetMap();
if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
- map, m_caster->GetPhaseMask(),
+ map, 0,
m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2,
m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2,
m_caster->GetPositionZ(),
@@ -4171,6 +3871,9 @@ void Spell::EffectDuel(SpellEffIndex effIndex)
return;
}
+ for (auto phase : m_caster->GetPhases())
+ pGameObj->SetInPhase(phase, false, true);
+
pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction());
pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1);
int32 duration = m_spellInfo->GetDuration();
@@ -4301,12 +4004,16 @@ void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
switch (m_glyphIndex)
{
case 0:
- case 1: minLevel = 15; break;
- case 2: minLevel = 50; break;
- case 3: minLevel = 30; break;
- case 4: minLevel = 70; break;
- case 5: minLevel = 80; break;
+ case 1:
+ case 6: minLevel = 25; break;
+ case 2:
+ case 3:
+ case 7: minLevel = 50; break;
+ case 4:
+ case 5:
+ case 8: minLevel = 75; break;
}
+
if (minLevel && m_caster->getLevel() < minLevel)
{
SendCastResult(SPELL_FAILED_GLYPH_SOCKET_LOCKED);
@@ -4314,13 +4021,13 @@ void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
}
// apply new one
- if (uint32 glyph = m_spellInfo->Effects[effIndex].MiscValue)
+ if (uint32 newGlyph = m_spellInfo->Effects[effIndex].MiscValue)
{
- if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
+ if (GlyphPropertiesEntry const* newGlyphProperties = sGlyphPropertiesStore.LookupEntry(newGlyph))
{
- if (GlyphSlotEntry const* gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
+ if (GlyphSlotEntry const* newGlyphSlot = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
{
- if (gp->TypeFlags != gs->TypeFlags)
+ if (newGlyphProperties->TypeFlags != newGlyphSlot->TypeFlags)
{
SendCastResult(SPELL_FAILED_INVALID_GLYPH);
return; // glyph slot mismatch
@@ -4328,17 +4035,26 @@ void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
}
// remove old glyph
- if (uint32 oldglyph = player->GetGlyph(m_glyphIndex))
+ if (uint32 oldGlyph = player->GetGlyph(player->GetActiveSpec(), m_glyphIndex))
{
- if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
+ if (GlyphPropertiesEntry const* oldGlyphProperties = sGlyphPropertiesStore.LookupEntry(oldGlyph))
{
- player->RemoveAurasDueToSpell(old_gp->SpellId);
+ player->RemoveAurasDueToSpell(oldGlyphProperties->SpellId);
player->SetGlyph(m_glyphIndex, 0);
}
}
- player->CastSpell(m_caster, gp->SpellId, true);
- player->SetGlyph(m_glyphIndex, glyph);
+ player->CastSpell(m_caster, newGlyphProperties->SpellId, true);
+ player->SetGlyph(m_glyphIndex, newGlyph);
+ player->SendTalentsInfoData(false);
+ }
+ }
+ else if (uint32 oldGlyph = player->GetGlyph(player->GetActiveSpec(), m_glyphIndex)) // Removing the glyph, get the old one
+ {
+ if (GlyphPropertiesEntry const* oldGlyphProperties = sGlyphPropertiesStore.LookupEntry(oldGlyph))
+ {
+ player->RemoveAurasDueToSpell(oldGlyphProperties->SpellId);
+ player->SetGlyph(m_glyphIndex, 0);
player->SendTalentsInfoData(false);
}
}
@@ -4508,12 +4224,15 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex)
Map* map = m_caster->GetMap();
if (!go->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
- m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
+ 0, x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
{
delete go;
return;
}
+ for (auto phase : m_caster->GetPhases())
+ go->SetInPhase(phase, false, true);
+
//pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
int32 duration = m_spellInfo->GetDuration();
go->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
@@ -4540,7 +4259,7 @@ void Spell::EffectResurrect(SpellEffIndex effIndex)
Player* target = unitTarget->ToPlayer();
- if (target->isResurrectRequested()) // already have one active request
+ if (target->IsResurrectRequested()) // already have one active request
return;
uint32 health = target->CountPctFromMaxHealth(damage);
@@ -4548,7 +4267,7 @@ void Spell::EffectResurrect(SpellEffIndex effIndex)
ExecuteLogEffectResurrect(effIndex, target);
- target->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
+ target->SetResurrectRequestData(m_caster, health, mana, 0);
SendResurrectRequest(target);
}
@@ -4695,6 +4414,7 @@ void Spell::EffectSelfResurrect(SpellEffIndex effIndex)
player->SetPower(POWER_MANA, mana);
player->SetPower(POWER_RAGE, 0);
player->SetPower(POWER_ENERGY, player->GetMaxPower(POWER_ENERGY));
+ player->SetPower(POWER_FOCUS, 0);
player->SpawnCorpseBones();
}
@@ -5137,12 +4857,15 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
GameObject* pGameObj = new GameObject;
if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
- m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
+ 0, fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
{
delete pGameObj;
return;
}
+ for (auto phase : m_caster->GetPhases())
+ pGameObj->SetInPhase(phase, false, true);
+
int32 duration = m_spellInfo->GetDuration();
switch (goinfo->type)
@@ -5203,8 +4926,11 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
{
GameObject* linkedGO = new GameObject;
if (linkedGO->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
- m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
+ 0, fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
{
+ for (auto phase : m_caster->GetPhases())
+ linkedGO->SetInPhase(phase, false, true);
+
linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
//linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
linkedGO->SetSpellId(m_spellInfo->Id);
@@ -5568,6 +5294,11 @@ void Spell::EffectCreateTamedPet(SpellEffIndex effIndex)
if (!pet)
return;
+ // relocate
+ float px, py, pz;
+ unitTarget->GetClosePoint(px, py, pz, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle());
+ pet->Relocate(px, py, pz, unitTarget->GetOrientation());
+
// add to world
pet->GetMap()->AddToMap(pet->ToCreature());
@@ -5752,6 +5483,7 @@ void Spell::EffectPlayMusic(SpellEffIndex effIndex)
WorldPacket data(SMSG_PLAY_MUSIC, 4);
data << uint32(soundid);
+ data << uint64(unitTarget->GetGUID());
unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
}
@@ -5787,8 +5519,7 @@ void Spell::EffectPlaySound(SpellEffIndex effIndex)
switch (m_spellInfo->Id)
{
- case 58730: // Restricted Flight Area
- case 58600: // Restricted Flight Area
+ case 91604: // Restricted Flight Area
unitTarget->ToPlayer()->GetSession()->SendNotification(LANG_ZONE_NOFLYZONE);
break;
default:
@@ -5805,6 +5536,7 @@ void Spell::EffectPlaySound(SpellEffIndex effIndex)
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << uint32(soundId);
+ data << uint64(m_caster->GetGUID());
unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
}
@@ -5819,6 +5551,28 @@ void Spell::EffectRemoveAura(SpellEffIndex effIndex)
unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].TriggerSpell);
}
+void Spell::EffectDamageFromMaxHealthPCT(SpellEffIndex /*effIndex*/)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ if (!unitTarget)
+ return;
+
+ m_damage += unitTarget->CountPctFromMaxHealth(damage);
+}
+
+void Spell::EffectGiveCurrency(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ unitTarget->ToPlayer()->ModifyCurrency(m_spellInfo->Effects[effIndex].MiscValue, damage);
+}
+
void Spell::EffectCastButtons(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
@@ -5850,10 +5604,10 @@ void Spell::EffectCastButtons(SpellEffIndex effIndex)
if (!p_caster->HasSpell(spell_id) || p_caster->HasSpellCooldown(spell_id))
continue;
- if (!(spellInfo->AttributesEx7 & SPELL_ATTR7_SUMMON_PLAYER_TOTEM))
+ if (!(spellInfo->AttributesEx9 & SPELL_ATTR9_SUMMON_PLAYER_TOTEM))
continue;
- uint32 cost = spellInfo->CalcPowerCost(m_caster, spellInfo->GetSchoolMask());
+ int32 cost = spellInfo->CalcPowerCost(m_caster, spellInfo->GetSchoolMask());
if (m_caster->GetPower(POWER_MANA) < cost)
continue;
@@ -5944,3 +5698,65 @@ void Spell::EffectSummonRaFFriend(SpellEffIndex effIndex)
m_caster->CastSpell(unitTarget, m_spellInfo->Effects[effIndex].TriggerSpell, true);
}
+
+void Spell::EffectUnlockGuildVaultTab(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
+ return;
+
+ // Safety checks done in Spell::CheckCast
+ Player* caster = m_caster->ToPlayer();
+ if (Guild* guild = caster->GetGuild())
+ guild->HandleBuyBankTab(caster->GetSession(), m_spellInfo->Effects[effIndex].BasePoints - 1); // Bank tabs start at zero internally
+}
+
+void Spell::EffectResurrectWithAura(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ if (!unitTarget || !unitTarget->IsInWorld())
+ return;
+
+ Player* target = unitTarget->ToPlayer();
+ if (!target)
+ return;
+
+ if (unitTarget->IsAlive())
+ return;
+
+ if (target->IsResurrectRequested()) // already have one active request
+ return;
+
+ uint32 health = target->CountPctFromMaxHealth(damage);
+ uint32 mana = CalculatePct(target->GetMaxPower(POWER_MANA), damage);
+ uint32 resurrectAura = 0;
+ if (sSpellMgr->GetSpellInfo(GetSpellInfo()->Effects[effIndex].TriggerSpell))
+ resurrectAura = GetSpellInfo()->Effects[effIndex].TriggerSpell;
+
+ if (resurrectAura && target->HasAura(resurrectAura))
+ return;
+
+ ExecuteLogEffectResurrect(effIndex, target);
+ target->SetResurrectRequestData(m_caster, health, mana, resurrectAura);
+ SendResurrectRequest(target);
+}
+
+void Spell::EffectCreateAreaTrigger(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
+ return;
+
+ Position pos;
+ if (!m_targets.HasDst())
+ pos = GetCaster()->GetPosition();
+ else
+ pos = destTarget->GetPosition();
+
+ // trigger entry/miscvalue relation is currently unknown, for now use MiscValue as trigger entry
+ uint32 triggerEntry = GetSpellInfo()->Effects[effIndex].MiscValue;
+
+ AreaTrigger * areaTrigger = new AreaTrigger;
+ if (!areaTrigger->CreateAreaTrigger(sObjectMgr->GenerateLowGuid(HIGHGUID_AREATRIGGER), triggerEntry, GetCaster(), GetSpellInfo(), pos))
+ delete areaTrigger;
+}
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 99c3d234ef8..4b6e4dc2ee7 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -15,8 +15,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "SpellAuraDefines.h"
#include "SpellInfo.h"
+#include "SpellAuraDefines.h"
+#include "SpellAuraEffects.h"
#include "SpellMgr.h"
#include "Spell.h"
#include "DBCStores.h"
@@ -318,34 +319,57 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_
{TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 107 TARGET_UNK_DEST_AREA_UNK_107
{TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 108 TARGET_GAMEOBJECT_CONE
{TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 109
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 110 TARGET_DEST_UNK_110
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 110 TARGET_DEST_UNK_110
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 111
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 112
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 113
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 114
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 115
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 116
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 117
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 118
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 119
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 120
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 121
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 122
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 123
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 124
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 125
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 126
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 127
};
-SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex)
+SpellEffectInfo::SpellEffectInfo(SpellEntry const* /*spellEntry*/, SpellInfo const* spellInfo, uint8 effIndex, SpellEffectEntry const* _effect)
{
+ SpellScalingEntry const* scaling = spellInfo->GetSpellScaling();
+
_spellInfo = spellInfo;
- _effIndex = effIndex;
- Effect = spellEntry->Effect[effIndex];
- ApplyAuraName = spellEntry->EffectApplyAuraName[effIndex];
- Amplitude = spellEntry->EffectAmplitude[effIndex];
- DieSides = spellEntry->EffectDieSides[effIndex];
- RealPointsPerLevel = spellEntry->EffectRealPointsPerLevel[effIndex];
- BasePoints = spellEntry->EffectBasePoints[effIndex];
- PointsPerComboPoint = spellEntry->EffectPointsPerComboPoint[effIndex];
- ValueMultiplier = spellEntry->EffectValueMultiplier[effIndex];
- DamageMultiplier = spellEntry->EffectDamageMultiplier[effIndex];
- BonusMultiplier = spellEntry->EffectBonusMultiplier[effIndex];
- MiscValue = spellEntry->EffectMiscValue[effIndex];
- MiscValueB = spellEntry->EffectMiscValueB[effIndex];
- Mechanic = Mechanics(spellEntry->EffectMechanic[effIndex]);
- TargetA = SpellImplicitTargetInfo(spellEntry->EffectImplicitTargetA[effIndex]);
- TargetB = SpellImplicitTargetInfo(spellEntry->EffectImplicitTargetB[effIndex]);
- RadiusEntry = spellEntry->EffectRadiusIndex[effIndex] ? sSpellRadiusStore.LookupEntry(spellEntry->EffectRadiusIndex[effIndex]) : NULL;
- ChainTarget = spellEntry->EffectChainTarget[effIndex];
- ItemType = spellEntry->EffectItemType[effIndex];
- TriggerSpell = spellEntry->EffectTriggerSpell[effIndex];
- SpellClassMask = spellEntry->EffectSpellClassMask[effIndex];
+ _effIndex = _effect ? _effect->EffectIndex : effIndex;
+ Effect = _effect ? _effect->Effect : 0;
+ ApplyAuraName = _effect ? _effect->EffectApplyAuraName : 0;
+ Amplitude = _effect ? _effect->EffectAmplitude : 0;
+ DieSides = _effect ? _effect->EffectDieSides : 0;
+ RealPointsPerLevel = _effect ? _effect->EffectRealPointsPerLevel : 0.0f;
+ BasePoints = _effect ? _effect->EffectBasePoints : 0;
+ PointsPerComboPoint = _effect ? _effect->EffectPointsPerComboPoint : 0.0f;
+ ValueMultiplier = _effect ? _effect->EffectValueMultiplier : 0.0f;
+ DamageMultiplier = _effect ? _effect->EffectDamageMultiplier : 0.0f;
+ BonusMultiplier = _effect ? _effect->EffectBonusMultiplier : 0.0f;
+ MiscValue = _effect ? _effect->EffectMiscValue : 0;
+ MiscValueB = _effect ? _effect->EffectMiscValueB : 0;
+ Mechanic = Mechanics(_effect ? _effect->EffectMechanic : 0);
+ TargetA = SpellImplicitTargetInfo(_effect ? _effect->EffectImplicitTargetA : 0);
+ TargetB = SpellImplicitTargetInfo(_effect ? _effect->EffectImplicitTargetB : 0);
+ RadiusEntry = _effect && _effect->EffectRadiusIndex ? sSpellRadiusStore.LookupEntry(_effect->EffectRadiusIndex) : NULL;
+ MaxRadiusEntry = _effect && _effect->EffectRadiusMaxIndex ? sSpellRadiusStore.LookupEntry(_effect->EffectRadiusMaxIndex) : NULL;
+ ChainTarget = _effect ? _effect->EffectChainTarget : 0;
+ ItemType = _effect ? _effect->EffectItemType : 0;
+ TriggerSpell = _effect ? _effect->EffectTriggerSpell : 0;
+ SpellClassMask = _effect ? _effect->EffectSpellClassMask : flag96(0);
ImplicitTargetConditions = NULL;
+ ScalingMultiplier = scaling ? scaling->Multiplier[_effIndex] : 0.0f;
+ DeltaScalingMultiplier = scaling ? scaling->RandomMultiplier[_effIndex] : 0.0f;
+ ComboScalingMultiplier = scaling ? scaling->OtherMultiplier[_effIndex] : 0.0f;
}
bool SpellEffectInfo::IsEffect() const
@@ -404,37 +428,73 @@ bool SpellEffectInfo::IsUnitOwnedAuraEffect() const
return IsAreaAuraEffect() || Effect == SPELL_EFFECT_APPLY_AURA;
}
-int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const* /*target*/) const
+int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const* target) const
{
float basePointsPerLevel = RealPointsPerLevel;
int32 basePoints = bp ? *bp : BasePoints;
- int32 randomPoints = int32(DieSides);
+ float comboDamage = PointsPerComboPoint;
// base amount modification based on spell lvl vs caster lvl
- if (caster)
+ if (ScalingMultiplier != 0.0f)
{
- int32 level = int32(caster->getLevel());
- if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0)
- level = int32(_spellInfo->MaxLevel);
- else if (level < int32(_spellInfo->BaseLevel))
- level = int32(_spellInfo->BaseLevel);
- level -= int32(_spellInfo->SpellLevel);
- basePoints += int32(level * basePointsPerLevel);
- }
+ if (caster)
+ {
+ int32 level = caster->getLevel();
+ if (target && _spellInfo->IsPositiveEffect(_effIndex) && (Effect == SPELL_EFFECT_APPLY_AURA))
+ level = target->getLevel();
+
+ if (GtSpellScalingEntry const* gtScaling = sGtSpellScalingStore.LookupEntry((_spellInfo->ScalingClass != -1 ? _spellInfo->ScalingClass - 1 : MAX_CLASSES - 1) * 100 + level - 1))
+ {
+ float multiplier = gtScaling->value;
+ if (_spellInfo->CastTimeMax > 0 && _spellInfo->CastTimeMaxLevel > level)
+ multiplier *= float(_spellInfo->CastTimeMin + (level - 1) * (_spellInfo->CastTimeMax - _spellInfo->CastTimeMin) / (_spellInfo->CastTimeMaxLevel - 1)) / float(_spellInfo->CastTimeMax);
+ if (_spellInfo->CoefLevelBase > level)
+ multiplier *= (1.0f - _spellInfo->CoefBase) * (float)(level - 1) / (float)(_spellInfo->CoefLevelBase - 1) + _spellInfo->CoefBase;
+
+ float preciseBasePoints = ScalingMultiplier * multiplier;
+ if (DeltaScalingMultiplier)
+ {
+ float delta = fabs(DeltaScalingMultiplier * ScalingMultiplier * multiplier * 0.5f);
+ preciseBasePoints += frand(-delta, delta);
+ }
- // roll in a range <1;EffectDieSides> as of patch 3.3.3
- switch (randomPoints)
+ basePoints = int32(preciseBasePoints);
+
+ if (ComboScalingMultiplier)
+ comboDamage = ComboScalingMultiplier * multiplier;
+ }
+ }
+ }
+ else
{
- case 0: break;
- case 1: basePoints += 1; break; // range 1..1
- default:
- // range can have positive (1..rand) and negative (rand..1) values, so order its for irand
- int32 randvalue = (randomPoints >= 1)
- ? irand(1, randomPoints)
- : irand(randomPoints, 1);
+ if (caster)
+ {
+ int32 level = int32(caster->getLevel());
+ if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0)
+ level = int32(_spellInfo->MaxLevel);
+ else if (level < int32(_spellInfo->BaseLevel))
+ level = int32(_spellInfo->BaseLevel);
+ level -= int32(_spellInfo->SpellLevel);
+ basePoints += int32(level * basePointsPerLevel);
+ }
- basePoints += randvalue;
- break;
+ // roll in a range <1;EffectDieSides> as of patch 3.3.3
+ int32 randomPoints = int32(DieSides);
+ switch (randomPoints)
+ {
+ case 0: break;
+ case 1: basePoints += 1; break; // range 1..1
+ default:
+ {
+ // range can have positive (1..rand) and negative (rand..1) values, so order its for irand
+ int32 randvalue = (randomPoints >= 1)
+ ? irand(1, randomPoints)
+ : irand(randomPoints, 1);
+
+ basePoints += randvalue;
+ break;
+ }
+ }
}
float value = float(basePoints);
@@ -443,14 +503,26 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
if (caster)
{
// bonus amount from combo points
- if (caster->m_movedPlayer)
+ if (caster->m_movedPlayer && comboDamage)
if (uint8 comboPoints = caster->m_movedPlayer->GetComboPoints())
- if (float comboDamage = PointsPerComboPoint)
- value += comboDamage* comboPoints;
+ value += comboDamage * comboPoints;
value = caster->ApplyEffectModifiers(_spellInfo, _effIndex, value);
// amount multiplication based on caster's level
+/* REVIEW - MERGE <<<<<<< HEAD
+ if (!_spellInfo->GetSpellScaling() && !basePointsPerLevel && (_spellInfo->Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION && _spellInfo->SpellLevel) &&
+ Effect != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE &&
+ Effect != SPELL_EFFECT_KNOCK_BACK &&
+ Effect != SPELL_EFFECT_ADD_EXTRA_ATTACKS &&
+ ApplyAuraName != SPELL_AURA_MOD_SPEED_ALWAYS &&
+ ApplyAuraName != SPELL_AURA_MOD_SPEED_NOT_STACK &&
+ ApplyAuraName != SPELL_AURA_MOD_INCREASE_SPEED &&
+ ApplyAuraName != SPELL_AURA_MOD_DECREASE_SPEED)
+ //there are many more: slow speed, -healing pct
+ value *= 0.25f * exp(caster->getLevel() * (70 - _spellInfo->SpellLevel) / 1000.0f);
+ //value = int32(value * (int32)getLevel() / (int32)(_spellInfo->spellLevel ? _spellInfo->spellLevel : 1));
+======= */
if (!caster->IsControlledByPlayer() &&
_spellInfo->SpellLevel && _spellInfo->SpellLevel != caster->getLevel() &&
!basePointsPerLevel && (_spellInfo->Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))
@@ -501,6 +573,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
value *= casterScaler->ratio / spellScaler->ratio;
}
}
+// REVIEW - MERGE >>>>>>> master
}
return int32(value);
@@ -535,16 +608,25 @@ bool SpellEffectInfo::HasRadius() const
return RadiusEntry != NULL;
}
+bool SpellEffectInfo::HasMaxRadius() const
+{
+ return MaxRadiusEntry != NULL;
+}
+
float SpellEffectInfo::CalcRadius(Unit* caster, Spell* spell) const
{
- if (!HasRadius())
+ const SpellRadiusEntry* entry = RadiusEntry;
+ if (!HasRadius() && HasMaxRadius())
+ entry = MaxRadiusEntry;
+
+ if (!entry)
return 0.0f;
- float radius = RadiusEntry->RadiusMin;
+ float radius = entry->RadiusMin;
if (caster)
{
- radius += RadiusEntry->RadiusPerLevel * caster->getLevel();
- radius = std::min(radius, RadiusEntry->RadiusMax);
+ radius += entry->RadiusPerLevel * caster->getLevel();
+ radius = std::min(radius, entry->RadiusMax);
if (Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(_spellInfo->Id, SPELLMOD_RADIUS, radius, spell);
}
@@ -591,7 +673,7 @@ SpellTargetObjectTypes SpellEffectInfo::GetUsedTargetObjectType() const
return _data[Effect].UsedTargetObjectType;
}
-SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
+SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{
// implicit target type used target object type
{EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 0
@@ -759,14 +841,29 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 162 SPELL_EFFECT_TALENT_SPEC_SELECT
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 163 SPELL_EFFECT_163
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 164 SPELL_EFFECT_REMOVE_AURA
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 165 SPELL_EFFECT_165
+ {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 166 SPELL_EFFECT_GIVE_CURRENCY
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 167 SPELL_EFFECT_167
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 168 SPELL_EFFECT_168
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_ITEM}, // 169 SPELL_EFFECT_DESTROY_ITEM
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 170 SPELL_EFFECT_170
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 171 SPELL_EFFECT_171
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 172 SPELL_EFFECT_172
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 173 SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 174 SPELL_EFFECT_174
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 175 SPELL_EFFECT_175
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 176 SPELL_EFFECT_176
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 177 SPELL_EFFECT_177
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 178 SPELL_EFFECT_178
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 179 SPELL_EFFECT_CREATE_AREATRIGGER
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 180 SPELL_EFFECT_180
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 181 SPELL_EFFECT_181
+ {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 182 SPELL_EFFECT_182
};
-SpellInfo::SpellInfo(SpellEntry const* spellEntry)
+SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntry const** effects)
{
Id = spellEntry->Id;
- CategoryEntry = spellEntry->Category ? sSpellCategoryStore.LookupEntry(spellEntry->Category) : NULL;
- Dispel = spellEntry->Dispel;
- Mechanic = spellEntry->Mechanic;
Attributes = spellEntry->Attributes;
AttributesEx = spellEntry->AttributesEx;
AttributesEx2 = spellEntry->AttributesEx2;
@@ -775,82 +872,148 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry)
AttributesEx5 = spellEntry->AttributesEx5;
AttributesEx6 = spellEntry->AttributesEx6;
AttributesEx7 = spellEntry->AttributesEx7;
+ AttributesEx8 = spellEntry->AttributesEx8;
+ AttributesEx9 = spellEntry->AttributesEx9;
+ AttributesEx10 = spellEntry->AttributesEx10;
AttributesCu = 0;
- Stances = spellEntry->Stances;
- StancesNot = spellEntry->StancesNot;
- Targets = spellEntry->Targets;
- TargetCreatureType = spellEntry->TargetCreatureType;
- RequiresSpellFocus = spellEntry->RequiresSpellFocus;
- FacingCasterFlags = spellEntry->FacingCasterFlags;
- CasterAuraState = spellEntry->CasterAuraState;
- TargetAuraState = spellEntry->TargetAuraState;
- CasterAuraStateNot = spellEntry->CasterAuraStateNot;
- TargetAuraStateNot = spellEntry->TargetAuraStateNot;
- CasterAuraSpell = spellEntry->casterAuraSpell;
- TargetAuraSpell = spellEntry->targetAuraSpell;
- ExcludeCasterAuraSpell = spellEntry->excludeCasterAuraSpell;
- ExcludeTargetAuraSpell = spellEntry->excludeTargetAuraSpell;
CastTimeEntry = spellEntry->CastingTimeIndex ? sSpellCastTimesStore.LookupEntry(spellEntry->CastingTimeIndex) : NULL;
- RecoveryTime = spellEntry->RecoveryTime;
- CategoryRecoveryTime = spellEntry->CategoryRecoveryTime;
- StartRecoveryCategory = spellEntry->StartRecoveryCategory;
- StartRecoveryTime = spellEntry->StartRecoveryTime;
- InterruptFlags = spellEntry->InterruptFlags;
- AuraInterruptFlags = spellEntry->AuraInterruptFlags;
- ChannelInterruptFlags = spellEntry->ChannelInterruptFlags;
- ProcFlags = spellEntry->procFlags;
- ProcChance = spellEntry->procChance;
- ProcCharges = spellEntry->procCharges;
- MaxLevel = spellEntry->maxLevel;
- BaseLevel = spellEntry->baseLevel;
- SpellLevel = spellEntry->spellLevel;
DurationEntry = spellEntry->DurationIndex ? sSpellDurationStore.LookupEntry(spellEntry->DurationIndex) : NULL;
PowerType = spellEntry->powerType;
- ManaCost = spellEntry->manaCost;
- ManaCostPerlevel = spellEntry->manaCostPerlevel;
- ManaPerSecond = spellEntry->manaPerSecond;
- ManaPerSecondPerLevel = spellEntry->manaPerSecondPerLevel;
- ManaCostPercentage = spellEntry->ManaCostPercentage;
- RuneCostID = spellEntry->runeCostID;
RangeEntry = spellEntry->rangeIndex ? sSpellRangeStore.LookupEntry(spellEntry->rangeIndex) : NULL;
Speed = spellEntry->speed;
- StackAmount = spellEntry->StackAmount;
- for (uint8 i = 0; i < 2; ++i)
- Totem[i] = spellEntry->Totem[i];
-
- for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i)
- Reagent[i] = spellEntry->Reagent[i];
-
- for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i)
- ReagentCount[i] = spellEntry->ReagentCount[i];
-
- EquippedItemClass = spellEntry->EquippedItemClass;
- EquippedItemSubClassMask = spellEntry->EquippedItemSubClassMask;
- EquippedItemInventoryTypeMask = spellEntry->EquippedItemInventoryTypeMask;
- for (uint8 i = 0; i < 2; ++i)
- TotemCategory[i] = spellEntry->TotemCategory[i];
for (uint8 i = 0; i < 2; ++i)
SpellVisual[i] = spellEntry->SpellVisual[i];
SpellIconID = spellEntry->SpellIconID;
ActiveIconID = spellEntry->activeIconID;
- for (uint8 i = 0; i < 16; ++i)
- SpellName[i] = spellEntry->SpellName[i];
-
- for (uint8 i = 0; i < 16; ++i)
- Rank[i] = spellEntry->Rank[i];
-
- MaxTargetLevel = spellEntry->MaxTargetLevel;
- MaxAffectedTargets = spellEntry->MaxAffectedTargets;
- SpellFamilyName = spellEntry->SpellFamilyName;
- SpellFamilyFlags = spellEntry->SpellFamilyFlags;
- DmgClass = spellEntry->DmgClass;
- PreventionType = spellEntry->PreventionType;
- AreaGroupId = spellEntry->AreaGroupId;
+ SpellName = spellEntry->SpellName;
+ Rank = spellEntry->Rank;
SchoolMask = spellEntry->SchoolMask;
+ RuneCostID = spellEntry->runeCostID;
+ SpellDifficultyId = spellEntry->SpellDifficultyId;
+ SpellScalingId = spellEntry->SpellScalingId;
+ SpellAuraOptionsId = spellEntry->SpellAuraOptionsId;
+ SpellAuraRestrictionsId = spellEntry->SpellAuraRestrictionsId;
+ SpellCastingRequirementsId = spellEntry->SpellCastingRequirementsId;
+ SpellCategoriesId = spellEntry->SpellCategoriesId;
+ SpellClassOptionsId = spellEntry->SpellClassOptionsId;
+ SpellCooldownsId = spellEntry->SpellCooldownsId;
+ SpellEquippedItemsId = spellEntry->SpellEquippedItemsId;
+ SpellInterruptsId = spellEntry->SpellInterruptsId;
+ SpellLevelsId = spellEntry->SpellLevelsId;
+ SpellPowerId = spellEntry->SpellPowerId;
+ SpellReagentsId = spellEntry->SpellReagentsId;
+ SpellShapeshiftId = spellEntry->SpellShapeshiftId;
+ SpellTargetRestrictionsId = spellEntry->SpellTargetRestrictionsId;
+ SpellTotemsId = spellEntry->SpellTotemsId;
+
+ // SpellDifficultyEntry
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- Effects[i] = SpellEffectInfo(spellEntry, this, i);
+ Effects[i] = SpellEffectInfo(spellEntry, this, i, effects[i]);
+
+ // SpellScalingEntry
+ SpellScalingEntry const* _scaling = GetSpellScaling();
+ CastTimeMin = _scaling ? _scaling->CastTimeMin : 0;
+ CastTimeMax = _scaling ?_scaling->CastTimeMax : 0;
+ CastTimeMaxLevel = _scaling ? _scaling->CastTimeMaxLevel : 0;
+ ScalingClass = _scaling ? _scaling->ScalingClass : 0;
+ CoefBase = _scaling ? _scaling->CoefBase : 0;
+ CoefLevelBase = _scaling ? _scaling->CoefLevelBase : 0;
+
+ // SpellAuraOptionsEntry
+ SpellAuraOptionsEntry const* _options = GetSpellAuraOptions();
+ ProcFlags = _options ? _options->procFlags : 0;
+ ProcChance = _options ? _options->procChance : 0;
+ ProcCharges = _options ? _options->procCharges : 0;
+ StackAmount = _options ? _options->StackAmount : 0;
+
+ // SpellAuraRestrictionsEntry
+ SpellAuraRestrictionsEntry const* _aura = GetSpellAuraRestrictions();
+ CasterAuraState = _aura ? _aura->CasterAuraState : 0;
+ TargetAuraState = _aura ? _aura->TargetAuraState : 0;
+ CasterAuraStateNot = _aura ? _aura->CasterAuraStateNot : 0;
+ TargetAuraStateNot = _aura ? _aura->TargetAuraStateNot : 0;
+ CasterAuraSpell = _aura ? _aura->casterAuraSpell : 0;
+ TargetAuraSpell = _aura ? _aura->targetAuraSpell : 0;
+ ExcludeCasterAuraSpell = _aura ? _aura->excludeCasterAuraSpell : 0;
+ ExcludeTargetAuraSpell = _aura ? _aura->excludeTargetAuraSpell : 0;
+
+ // SpellCastingRequirementsEntry
+ SpellCastingRequirementsEntry const* _castreq = GetSpellCastingRequirements();
+ RequiresSpellFocus = _castreq ? _castreq->RequiresSpellFocus : 0;
+ FacingCasterFlags = _castreq ? _castreq->FacingCasterFlags : 0;
+ AreaGroupId = _castreq ? _castreq->AreaGroupId : -1;
+
+ // SpellCategoriesEntry
+ SpellCategoriesEntry const* _categorie = GetSpellCategories();
+ CategoryEntry = _categorie ? sSpellCategoryStore.LookupEntry(_categorie->Category) : NULL;
+ Dispel = _categorie ? _categorie->Dispel : 0;
+ Mechanic = _categorie ? _categorie->Mechanic : 0;
+ StartRecoveryCategory = _categorie ? _categorie->StartRecoveryCategory : 0;
+ DmgClass = _categorie ? _categorie->DmgClass : 0;
+ PreventionType = _categorie ? _categorie->PreventionType : 0;
+
+ // SpellClassOptionsEntry
+ SpellClassOptionsEntry const* _class = GetSpellClassOptions();
+ SpellFamilyName = _class ? _class->SpellFamilyName : 0;
+ SpellFamilyFlags = _class ? _class->SpellFamilyFlags : flag96(0);
+
+ // SpellCooldownsEntry
+ SpellCooldownsEntry const* _cooldowns = GetSpellCooldowns();
+ RecoveryTime = _cooldowns ? _cooldowns->RecoveryTime : 0;
+ CategoryRecoveryTime = _cooldowns ? _cooldowns->CategoryRecoveryTime : 0;
+ StartRecoveryTime = _cooldowns ? _cooldowns->StartRecoveryTime : 0;
+
+ // SpellEquippedItemsEntry
+ SpellEquippedItemsEntry const* _equipped = GetSpellEquippedItems();
+ EquippedItemClass = _equipped ? _equipped->EquippedItemClass : -1;
+ EquippedItemSubClassMask = _equipped ?_equipped->EquippedItemSubClassMask : -1;
+ EquippedItemInventoryTypeMask = _equipped ? _equipped->EquippedItemInventoryTypeMask : -1;
+
+ // SpellInterruptsEntry
+ SpellInterruptsEntry const* _interrupt = GetSpellInterrupts();
+ InterruptFlags = _interrupt ? _interrupt->InterruptFlags : 0;
+ AuraInterruptFlags = _interrupt ? _interrupt->AuraInterruptFlags : 0;
+ ChannelInterruptFlags = _interrupt ? _interrupt->ChannelInterruptFlags : 0;
+
+ // SpellLevelsEntry
+ SpellLevelsEntry const* _levels = GetSpellLevels();
+ MaxLevel = _levels ? _levels->maxLevel : 0;
+ BaseLevel = _levels ? _levels->baseLevel : 0;
+ SpellLevel = _levels ? _levels->spellLevel : 0;
+
+ // SpellPowerEntry
+ SpellPowerEntry const* _power = GetSpellPower();
+ ManaCost = _power ? _power->manaCost : 0;
+ ManaCostPerlevel = _power ? _power->manaCostPerlevel : 0;
+ ManaCostPercentage = _power ? _power->ManaCostPercentage : 0;
+ ManaPerSecond = _power ? _power->manaPerSecond : 0;
+
+ // SpellReagentsEntry
+ SpellReagentsEntry const* _reagents = GetSpellReagents();
+ for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i)
+ Reagent[i] = _reagents ? _reagents->Reagent[i] : 0;
+ for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i)
+ ReagentCount[i] = _reagents ? _reagents->ReagentCount[i] : 0;
+
+ // SpellShapeshiftEntry
+ SpellShapeshiftEntry const* _shapeshift = GetSpellShapeshift();
+ Stances = _shapeshift ? _shapeshift->Stances : 0;
+ StancesNot = _shapeshift ? _shapeshift->StancesNot : 0;
+
+ // SpellTargetRestrictionsEntry
+ SpellTargetRestrictionsEntry const* _target = GetSpellTargetRestrictions();
+ Targets = _target ? _target->Targets : 0;
+ TargetCreatureType = _target ? _target->TargetCreatureType : 0;
+ MaxAffectedTargets = _target ? _target->MaxAffectedTargets : 0;
+
+ // SpellTotemsEntry
+ SpellTotemsEntry const* _totem = GetSpellTotems();
+ for (uint8 i = 0; i < 2; ++i)
+ TotemCategory[i] = _totem ? _totem->TotemCategory[i] : 0;
+ for (uint8 i = 0; i < 2; ++i)
+ Totem[i] = _totem ? _totem->Totem[i] : 0;
ChainEntry = NULL;
}
@@ -1254,7 +1417,6 @@ bool SpellInfo::IsAuraExclusiveBySpecificWith(SpellInfo const* spellInfo) const
SpellSpecificType spellSpec2 = spellInfo->GetSpellSpecific();
switch (spellSpec1)
{
- case SPELL_SPECIFIC_TRACKER:
case SPELL_SPECIFIC_WARLOCK_ARMOR:
case SPELL_SPECIFIC_MAGE_ARMOR:
case SPELL_SPECIFIC_ELEMENTAL_SHIELD:
@@ -1291,6 +1453,7 @@ bool SpellInfo::IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const* spellInf
case SPELL_SPECIFIC_AURA:
case SPELL_SPECIFIC_STING:
case SPELL_SPECIFIC_CURSE:
+ case SPELL_SPECIFIC_BANE:
case SPELL_SPECIFIC_ASPECT:
case SPELL_SPECIFIC_JUDGEMENT:
case SPELL_SPECIFIC_WARLOCK_CORRUPTION:
@@ -1317,10 +1480,10 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const
return SPELL_CAST_OK;
bool actAsShifted = false;
- SpellShapeshiftEntry const* shapeInfo = NULL;
+ SpellShapeshiftFormEntry const* shapeInfo = NULL;
if (form > 0)
{
- shapeInfo = sSpellShapeshiftStore.LookupEntry(form);
+ shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form);
if (!shapeInfo)
{
TC_LOG_ERROR("spells", "GetErrorAtShapeshiftedCast: unknown shapeshift %u", form);
@@ -1472,17 +1635,27 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
}
// aura limitations
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (player)
{
- if (!Effects[i].IsAura())
- continue;
- switch (Effects[i].ApplyAuraName)
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- case SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED:
- case SPELL_AURA_FLY:
+ if (!Effects[i].IsAura())
+ continue;
+
+ switch (Effects[i].ApplyAuraName)
{
- if (player && !player->IsKnowHowFlyIn(map_id, zone_id))
- return SPELL_FAILED_INCORRECT_AREA;
+ case SPELL_AURA_FLY:
+ {
+ if (!player->IsKnowHowFlyIn(map_id, zone_id))
+ return SPELL_FAILED_INCORRECT_AREA;
+ break;
+ }
+ case SPELL_AURA_MOUNTED:
+ {
+ if (Effects[i].MiscValueB && !player->GetMountCapability(Effects[i].MiscValueB))
+ return SPELL_FAILED_NOT_HERE;
+ break;
+ }
}
}
}
@@ -1690,8 +1863,8 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const
{
if (Effects[effIndex].ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT)
{
- SpellShapeshiftEntry const* shapeShiftEntry = sSpellShapeshiftStore.LookupEntry(Effects[effIndex].MiscValue);
- if (shapeShiftEntry && (shapeShiftEntry->flags1 & 1) == 0) // unk flag
+ SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(Effects[effIndex].MiscValue);
+ if (shapeShiftFromEntry && (shapeShiftFromEntry->flags1 & 1) == 0) // unk flag
checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED;
break;
}
@@ -1957,6 +2130,10 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const
}
case SPELLFAMILY_WARLOCK:
{
+ // Warlock (Bane of Doom | Bane of Agony | Bane of Havoc)
+ if (Id == 603 || Id == 980 || Id == 80240)
+ return SPELL_SPECIFIC_BANE;
+
// only warlock curses have this
if (Dispel == DISPEL_CURSE)
return SPELL_SPECIFIC_CURSE;
@@ -1993,15 +2170,14 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const
case SPELLFAMILY_PALADIN:
{
// Collection of all the seal family flags. No other paladin spell has any of those.
- if (SpellFamilyFlags[1] & 0x26000C00
- || SpellFamilyFlags[0] & 0x0A000000)
+ if (SpellFamilyFlags[1] & 0xA2000800)
return SPELL_SPECIFIC_SEAL;
if (SpellFamilyFlags[0] & 0x00002190)
return SPELL_SPECIFIC_HAND;
- // Judgement of Wisdom, Judgement of Light, Judgement of Justice
- if (Id == 20184 || Id == 20185 || Id == 20186)
+ // Judgement
+ if (Id == 20271)
return SPELL_SPECIFIC_JUDGEMENT;
// only paladin auras have this (for palaldin class family)
@@ -2089,18 +2265,29 @@ int32 SpellInfo::GetMaxDuration() const
return (DurationEntry->Duration[2] == -1) ? -1 : abs(DurationEntry->Duration[2]);
}
-uint32 SpellInfo::CalcCastTime(Spell* spell /*= NULL*/) const
+uint32 SpellInfo::CalcCastTime(uint8 level, Spell* spell /*= NULL*/) const
{
+ int32 castTime = 0;
+ if (!level && spell)
+ level = spell->GetCaster()->getLevel();
+
// not all spells have cast time index and this is all is pasiive abilities
- if (!CastTimeEntry)
- return 0;
+ if (level && CastTimeMax > 0)
+ {
+ castTime = CastTimeMax;
+ if (CastTimeMaxLevel > level)
+ castTime = CastTimeMin + int32(level - 1) * (CastTimeMax - CastTimeMin) / (CastTimeMaxLevel - 1);
+ }
+ else if (CastTimeEntry)
+ castTime = CastTimeEntry->CastTime;
- int32 castTime = CastTimeEntry->CastTime;
+ if (!castTime)
+ return 0;
if (spell)
spell->GetCaster()->ModSpellCastTime(this, castTime, spell);
- if (Attributes & SPELL_ATTR0_REQ_AMMO && (!IsAutoRepeatRangedSpell()))
+ if (Attributes & SPELL_ATTR0_REQ_AMMO && (!IsAutoRepeatRangedSpell()) && !(AttributesEx9 & SPELL_ATTR9_AIMED_SHOT))
castTime += 500;
return (castTime > 0) ? uint32(castTime) : 0;
@@ -2170,10 +2357,9 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) c
case POWER_RAGE:
case POWER_FOCUS:
case POWER_ENERGY:
- case POWER_HAPPINESS:
powerCost += int32(CalculatePct(caster->GetMaxPower(Powers(PowerType)), ManaCostPercentage));
break;
- case POWER_RUNE:
+ case POWER_RUNES:
case POWER_RUNIC_POWER:
TC_LOG_DEBUG("spells", "CalculateManaCost: Not implemented yet!");
break;
@@ -2182,17 +2368,27 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) c
return 0;
}
}
- SpellSchools school = GetFirstSchoolInMask(schoolMask);
- // Flat mod from caster auras by spell school
- powerCost += caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school);
+
+ // Flat mod from caster auras by spell school and power type
+ Unit::AuraEffectList const& auras = caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL);
+ for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
+ {
+ if (!((*i)->GetMiscValue() & schoolMask))
+ continue;
+ if (!((*i)->GetMiscValueB() & (1 << PowerType)))
+ continue;
+ powerCost += (*i)->GetAmount();
+ }
// Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
if (AttributesEx4 & SPELL_ATTR4_SPELL_VS_EXTEND_COST)
{
uint32 speed = 0;
+/* REVIEW - MERGE
if (SpellShapeshiftEntry const* ss = sSpellShapeshiftStore.LookupEntry(caster->GetShapeshiftForm()))
speed = ss->attackSpeed;
else
+*/
{
WeaponAttackType slot = BASE_ATTACK;
if (AttributesEx3 & SPELL_ATTR3_REQ_OFFHAND)
@@ -2219,8 +2415,16 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) c
}
}
- // PCT mod from user auras by school
- powerCost = int32(powerCost * (1.0f + caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER + school)));
+ // PCT mod from user auras by spell school and power type
+ Unit::AuraEffectList const& aurasPct = caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT);
+ for (Unit::AuraEffectList::const_iterator i = aurasPct.begin(); i != aurasPct.end(); ++i)
+ {
+ if (!((*i)->GetMiscValue() & schoolMask))
+ continue;
+ if (!((*i)->GetMiscValueB() & (1 << PowerType)))
+ continue;
+ powerCost += CalculatePct(powerCost, (*i)->GetAmount());
+ }
if (powerCost < 0)
powerCost = 0;
return powerCost;
@@ -2275,7 +2479,8 @@ SpellInfo const* SpellInfo::GetAuraRankForLevel(uint8 level) const
if (IsPositiveEffect(i) &&
(Effects[i].Effect == SPELL_EFFECT_APPLY_AURA ||
Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY ||
- Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID))
+ Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) &&
+ !Effects[i].ScalingMultiplier)
{
needRankSelection = true;
break;
@@ -2366,8 +2571,6 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
case 29214: // Wrath of the Plaguebringer
case 34700: // Allergic Reaction
case 54836: // Wrath of the Plaguebringer
- case 61987: // Avenging Wrath Marker
- case 61988: // Divine Shield exclude aura
return false;
case 30877: // Tag Murloc
case 61716: // Rabbit Costume
@@ -2381,9 +2584,6 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
}
break;
case SPELLFAMILY_MAGE:
- // Amplify Magic, Dampen Magic
- if (SpellFamilyFlags[0] == 0x00002000)
- return true;
// Ignite
if (SpellIconID == 45)
return true;
@@ -2399,23 +2599,11 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
break;
}
break;
- case SPELLFAMILY_HUNTER:
- // Aspect of the Viper
- if (Id == 34074)
- return true;
- break;
- case SPELLFAMILY_SHAMAN:
- if (Id == 30708)
- return false;
- break;
case SPELLFAMILY_ROGUE:
switch (Id)
{
// Envenom must be considered as a positive effect even though it deals damage
- case 32645: // Envenom (Rank 1)
- case 32684: // Envenom (Rank 2)
- case 57992: // Envenom (Rank 3)
- case 57993: // Envenom (Rank 4)
+ case 32645: // Envenom
return true;
default:
break;
@@ -2642,6 +2830,81 @@ bool SpellInfo::_IsPositiveTarget(uint32 targetA, uint32 targetB)
return true;
}
+SpellTargetRestrictionsEntry const* SpellInfo::GetSpellTargetRestrictions() const
+{
+ return SpellTargetRestrictionsId ? sSpellTargetRestrictionsStore.LookupEntry(SpellTargetRestrictionsId) : NULL;
+}
+
+SpellEquippedItemsEntry const* SpellInfo::GetSpellEquippedItems() const
+{
+ return SpellEquippedItemsId ? sSpellEquippedItemsStore.LookupEntry(SpellEquippedItemsId) : NULL;
+}
+
+SpellInterruptsEntry const* SpellInfo::GetSpellInterrupts() const
+{
+ return SpellInterruptsId ? sSpellInterruptsStore.LookupEntry(SpellInterruptsId) : NULL;
+}
+
+SpellLevelsEntry const* SpellInfo::GetSpellLevels() const
+{
+ return SpellLevelsId ? sSpellLevelsStore.LookupEntry(SpellLevelsId) : NULL;
+}
+
+SpellPowerEntry const* SpellInfo::GetSpellPower() const
+{
+ return SpellPowerId ? sSpellPowerStore.LookupEntry(SpellPowerId) : NULL;
+}
+
+SpellReagentsEntry const* SpellInfo::GetSpellReagents() const
+{
+ return SpellReagentsId ? sSpellReagentsStore.LookupEntry(SpellReagentsId) : NULL;
+}
+
+SpellScalingEntry const* SpellInfo::GetSpellScaling() const
+{
+ return SpellScalingId ? sSpellScalingStore.LookupEntry(SpellScalingId) : NULL;
+}
+
+SpellShapeshiftEntry const* SpellInfo::GetSpellShapeshift() const
+{
+ return SpellShapeshiftId ? sSpellShapeshiftStore.LookupEntry(SpellShapeshiftId) : NULL;
+}
+
+SpellTotemsEntry const* SpellInfo::GetSpellTotems() const
+{
+ return SpellTotemsId ? sSpellTotemsStore.LookupEntry(SpellTotemsId) : NULL;
+}
+
+SpellAuraOptionsEntry const* SpellInfo::GetSpellAuraOptions() const
+{
+ return SpellAuraOptionsId ? sSpellAuraOptionsStore.LookupEntry(SpellAuraOptionsId) : NULL;
+}
+
+SpellAuraRestrictionsEntry const* SpellInfo::GetSpellAuraRestrictions() const
+{
+ return SpellAuraRestrictionsId ? sSpellAuraRestrictionsStore.LookupEntry(SpellAuraRestrictionsId) : NULL;
+}
+
+SpellCastingRequirementsEntry const* SpellInfo::GetSpellCastingRequirements() const
+{
+ return SpellCastingRequirementsId ? sSpellCastingRequirementsStore.LookupEntry(SpellCastingRequirementsId) : NULL;
+}
+
+SpellCategoriesEntry const* SpellInfo::GetSpellCategories() const
+{
+ return SpellCategoriesId ? sSpellCategoriesStore.LookupEntry(SpellCategoriesId) : NULL;
+}
+
+SpellClassOptionsEntry const* SpellInfo::GetSpellClassOptions() const
+{
+ return SpellClassOptionsId ? sSpellClassOptionsStore.LookupEntry(SpellClassOptionsId) : NULL;
+}
+
+SpellCooldownsEntry const* SpellInfo::GetSpellCooldowns() const
+{
+ return SpellCooldownsId ? sSpellCooldownsStore.LookupEntry(SpellCooldownsId) : NULL;
+}
+
void SpellInfo::_UnloadImplicitTargetConditionLists()
{
// find the same instances of ConditionList and delete them.
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 562e0371fe1..ea29eb1b00f 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -29,6 +29,7 @@ class Player;
class Item;
class Spell;
class SpellInfo;
+class WorldObject;
struct SpellChainNode;
struct SpellTargetPosition;
struct SpellDurationEntry;
@@ -61,7 +62,7 @@ enum SpellCastTargetFlags
TARGET_FLAG_UNIT_MINIPET = 0x00010000, // pguid, used to validate target (if non combat pet)
TARGET_FLAG_GLYPH_SLOT = 0x00020000, // used in glyph spells
TARGET_FLAG_DEST_TARGET = 0x00040000, // sometimes appears with DEST_TARGET spells (may appear or not for a given spell)
- TARGET_FLAG_UNUSED20 = 0x00080000, // uint32 counter, loop { vec3 - screen position (?), guid }, not used so far
+ TARGET_FLAG_EXTRA_TARGETS = 0x00080000, // uint32 counter, loop { vec3 - screen position (?), guid }, not used so far
TARGET_FLAG_UNIT_PASSENGER = 0x00100000, // guessed, used to validate target (if vehicle passenger)
TARGET_FLAG_UNIT_MASK = TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY
@@ -166,7 +167,9 @@ enum SpellSpecificType
SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE = 25,
SPELL_SPECIFIC_WARRIOR_ENRAGE = 26,
SPELL_SPECIFIC_PRIEST_DIVINE_SPIRIT = 27,
- SPELL_SPECIFIC_HAND = 28
+ SPELL_SPECIFIC_HAND = 28,
+ SPELL_SPECIFIC_PHASE = 29,
+ SPELL_SPECIFIC_BANE = 30
};
enum SpellCustomAttributes
@@ -244,17 +247,22 @@ public:
SpellImplicitTargetInfo TargetA;
SpellImplicitTargetInfo TargetB;
SpellRadiusEntry const* RadiusEntry;
+ SpellRadiusEntry const* MaxRadiusEntry;
uint32 ChainTarget;
uint32 ItemType;
uint32 TriggerSpell;
flag96 SpellClassMask;
std::list<Condition*>* ImplicitTargetConditions;
+ // SpellScalingEntry
+ float ScalingMultiplier;
+ float DeltaScalingMultiplier;
+ float ComboScalingMultiplier;
SpellEffectInfo() : _spellInfo(NULL), _effIndex(0), Effect(0), ApplyAuraName(0), Amplitude(0), DieSides(0),
RealPointsPerLevel(0), BasePoints(0), PointsPerComboPoint(0), ValueMultiplier(0), DamageMultiplier(0),
BonusMultiplier(0), MiscValue(0), MiscValueB(0), Mechanic(MECHANIC_NONE), RadiusEntry(NULL), ChainTarget(0),
ItemType(0), TriggerSpell(0), ImplicitTargetConditions(NULL) {}
- SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex);
+ SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex, SpellEffectEntry const* effect);
bool IsEffect() const;
bool IsEffect(SpellEffects effectName) const;
@@ -272,6 +280,7 @@ public:
float CalcDamageMultiplier(Unit* caster, Spell* spell = NULL) const;
bool HasRadius() const;
+ bool HasMaxRadius() const;
float CalcRadius(Unit* caster = NULL, Spell* = NULL) const;
uint32 GetProvidedTargetMask() const;
@@ -304,6 +313,9 @@ public:
uint32 AttributesEx5;
uint32 AttributesEx6;
uint32 AttributesEx7;
+ uint32 AttributesEx8;
+ uint32 AttributesEx9;
+ uint32 AttributesEx10;
uint32 AttributesCu;
uint32 Stances;
uint32 StancesNot;
@@ -338,7 +350,6 @@ public:
uint32 ManaCost;
uint32 ManaCostPerlevel;
uint32 ManaPerSecond;
- uint32 ManaPerSecondPerLevel;
uint32 ManaCostPercentage;
uint32 RuneCostID;
SpellRangeEntry const* RangeEntry;
@@ -354,8 +365,8 @@ public:
uint32 SpellVisual[2];
uint32 SpellIconID;
uint32 ActiveIconID;
- char* SpellName[16];
- char* Rank[16];
+ char* SpellName;
+ char* Rank;
uint32 MaxTargetLevel;
uint32 MaxAffectedTargets;
uint32 SpellFamilyName;
@@ -364,11 +375,51 @@ public:
uint32 PreventionType;
int32 AreaGroupId;
uint32 SchoolMask;
+ uint32 SpellDifficultyId;
+ uint32 SpellScalingId;
+ uint32 SpellAuraOptionsId;
+ uint32 SpellAuraRestrictionsId;
+ uint32 SpellCastingRequirementsId;
+ uint32 SpellCategoriesId;
+ uint32 SpellClassOptionsId;
+ uint32 SpellCooldownsId;
+ uint32 SpellEquippedItemsId;
+ uint32 SpellInterruptsId;
+ uint32 SpellLevelsId;
+ uint32 SpellPowerId;
+ uint32 SpellReagentsId;
+ uint32 SpellShapeshiftId;
+ uint32 SpellTargetRestrictionsId;
+ uint32 SpellTotemsId;
+ // SpellScalingEntry
+ int32 CastTimeMin;
+ int32 CastTimeMax;
+ int32 CastTimeMaxLevel;
+ int32 ScalingClass;
+ float CoefBase;
+ int32 CoefLevelBase;
SpellEffectInfo Effects[MAX_SPELL_EFFECTS];
uint32 ExplicitTargetMask;
SpellChainNode const* ChainEntry;
- SpellInfo(SpellEntry const* spellEntry);
+ // struct access functions
+ SpellTargetRestrictionsEntry const* GetSpellTargetRestrictions() const;
+ SpellAuraOptionsEntry const* GetSpellAuraOptions() const;
+ SpellAuraRestrictionsEntry const* GetSpellAuraRestrictions() const;
+ SpellCastingRequirementsEntry const* GetSpellCastingRequirements() const;
+ SpellCategoriesEntry const* GetSpellCategories() const;
+ SpellClassOptionsEntry const* GetSpellClassOptions() const;
+ SpellCooldownsEntry const* GetSpellCooldowns() const;
+ SpellEquippedItemsEntry const* GetSpellEquippedItems() const;
+ SpellInterruptsEntry const* GetSpellInterrupts() const;
+ SpellLevelsEntry const* GetSpellLevels() const;
+ SpellPowerEntry const* GetSpellPower() const;
+ SpellReagentsEntry const* GetSpellReagents() const;
+ SpellScalingEntry const* GetSpellScaling() const;
+ SpellShapeshiftEntry const* GetSpellShapeshift() const;
+ SpellTotemsEntry const* GetSpellTotems() const;
+
+ SpellInfo(SpellEntry const* spellEntry, SpellEffectEntry const** effects);
~SpellInfo();
uint32 GetCategory() const;
@@ -448,7 +499,7 @@ public:
uint32 GetMaxTicks() const;
- uint32 CalcCastTime(Spell* spell = NULL) const;
+ uint32 CalcCastTime(uint8 level = 0, Spell* spell = NULL) const;
uint32 GetRecoveryTime() const;
int32 CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) const;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index bc97744fe32..0e5264bf56a 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -35,13 +35,13 @@
bool IsPrimaryProfessionSkill(uint32 skill)
{
SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(skill);
- if (!pSkill)
- return false;
-
- if (pSkill->categoryId != SKILL_CATEGORY_PROFESSION)
- return false;
+ return pSkill && pSkill->categoryId == SKILL_CATEGORY_PROFESSION;
+}
- return true;
+bool IsWeaponSkill(uint32 skill)
+{
+ SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(skill);
+ return pSkill && pSkill->categoryId == SKILL_CATEGORY_WEAPON;
}
bool IsPartOfSkillLine(uint32 skillId, uint32 spellId)
@@ -127,6 +127,9 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto,
// Seduction
else if (spellproto->SpellFamilyFlags[1] & 0x10000000)
return DIMINISHING_FEAR;
+ // Sin and Punishment (Priest spell, don't ask)
+ else if (spellproto->SpellIconID == 1869)
+ return DIMINISHING_NONE;
break;
}
case SPELLFAMILY_DRUID:
@@ -293,7 +296,7 @@ int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const
return 6 * IN_MILLISECONDS;
// Hunter's Mark
if (spellproto->SpellFamilyFlags[0] & 0x400)
- return 120 * IN_MILLISECONDS;
+ return 30 * IN_MILLISECONDS;
break;
}
case SPELLFAMILY_PALADIN:
@@ -320,7 +323,7 @@ int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const
break;
}
- return 10 * IN_MILLISECONDS;
+ return 8 * IN_MILLISECONDS;
}
bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group)
@@ -1153,19 +1156,7 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
// Extra conditions
switch (spellId)
{
- case 58600: // No fly Zone - Dalaran
- {
- if (!player)
- return false;
-
- AreaTableEntry const* pArea = GetAreaEntryByAreaID(player->GetAreaId());
- if (!(pArea && pArea->flags & AREA_FLAG_NO_FLY_ZONE))
- return false;
- if (!player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !player->HasAuraType(SPELL_AURA_FLY))
- return false;
- break;
- }
- case 58730: // No fly Zone - Wintergrasp
+ case 91604: // No fly Zone - Wintergrasp
{
if (!player)
return false;
@@ -1522,10 +1513,10 @@ void SpellMgr::LoadSpellLearnSpells()
{
Field* fields = result->Fetch();
- uint32 spell_id = fields[0].GetUInt16();
+ uint32 spell_id = fields[0].GetUInt32();
SpellLearnSpellNode node;
- node.spell = fields[1].GetUInt16();
+ node.spell = fields[1].GetUInt32();
node.active = fields[2].GetBool();
node.autoLearned = false;
@@ -1552,6 +1543,9 @@ void SpellMgr::LoadSpellLearnSpells()
++count;
} while (result->NextRow());
+ // copy state loaded from db
+ SpellLearnSpellMap dbSpellLearnSpells = mSpellLearnSpells;
+
// search auto-learned spells and add its to map also for use in unlearn spells/talents
uint32 dbc_count = 0;
for (uint32 spell = 0; spell < GetSpellInfoStoreSize(); ++spell)
@@ -1578,7 +1572,7 @@ void SpellMgr::LoadSpellLearnSpells()
// other required explicit dependent learning
dbc_node.autoLearned = entry->Effects[i].TargetA.GetTarget() == TARGET_UNIT_PET || GetTalentSpellCost(spell) > 0 || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP);
- SpellLearnSpellMapBounds db_node_bounds = GetSpellLearnSpellMapBounds(spell);
+ SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(spell);
bool found = false;
for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr)
@@ -1601,7 +1595,68 @@ void SpellMgr::LoadSpellLearnSpells()
}
}
- TC_LOG_INFO("server.loading", ">> Loaded %u spell learn spells + %u found in DBC in %u ms", count, dbc_count, GetMSTimeDiffToNow(oldMSTime));
+ uint32 mastery_count = 0;
+ for (uint32 i = 0; i < sTalentTabStore.GetNumRows(); ++i)
+ {
+ TalentTabEntry const* talentTab = sTalentTabStore.LookupEntry(i);
+ if (!talentTab)
+ continue;
+
+ for (uint32 c = CLASS_WARRIOR; c < MAX_CLASSES; ++c)
+ {
+ if (!(talentTab->ClassMask & (1 << (c - 1))))
+ continue;
+
+ uint32 masteryMainSpell = MasterySpells[c];
+
+ for (uint32 m = 0; m < MAX_MASTERY_SPELLS; ++m)
+ {
+ uint32 mastery = talentTab->MasterySpellId[m];
+ if (!mastery)
+ continue;
+
+ SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(masteryMainSpell);
+ bool found = false;
+ for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr)
+ {
+ if (itr->second.spell == mastery)
+ {
+ TC_LOG_ERROR("sql.sql", "Found redundant record (entry: %u, SpellID: %u) in `spell_learn_spell`, spell added automatically as mastery learned spell from TalentTab.dbc", masteryMainSpell, mastery);
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ // Check if it is already found in Spell.dbc, ignore silently if yes
+ SpellLearnSpellMapBounds dbc_node_bounds = GetSpellLearnSpellMapBounds(masteryMainSpell);
+ found = false;
+ for (SpellLearnSpellMap::const_iterator itr = dbc_node_bounds.first; itr != dbc_node_bounds.second; ++itr)
+ {
+ if (itr->second.spell == mastery)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ SpellLearnSpellNode masteryNode;
+ masteryNode.spell = mastery;
+ masteryNode.active = true;
+ masteryNode.autoLearned = false;
+
+ mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(masteryMainSpell, masteryNode));
+ ++mastery_count;
+ }
+ }
+ }
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u spell learn spells, %u found in Spell.dbc and %u from TalentTab.dbc in %u ms", count, dbc_count, mastery_count, GetMSTimeDiffToNow(oldMSTime));
}
void SpellMgr::LoadSpellTargetPositions()
@@ -2719,6 +2774,19 @@ void SpellMgr::LoadSpellAreas()
TC_LOG_INFO("server.loading", ">> Loaded %u spell area requirements in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+// Temporary structure to hold spell effect entries for faster loading
+struct SpellEffectArray
+{
+ SpellEffectArray()
+ {
+ effects[0] = NULL;
+ effects[1] = NULL;
+ effects[2] = NULL;
+ }
+
+ SpellEffectEntry const* effects[MAX_SPELL_EFFECTS];
+};
+
void SpellMgr::LoadSpellInfoStore()
{
uint32 oldMSTime = getMSTime();
@@ -2726,9 +2794,20 @@ void SpellMgr::LoadSpellInfoStore()
UnloadSpellInfoStore();
mSpellInfoMap.resize(sSpellStore.GetNumRows(), NULL);
+ std::map<uint32, SpellEffectArray> effectsBySpell;
+
+ for (uint32 i = 0; i < sSpellEffectStore.GetNumRows(); ++i)
+ {
+ SpellEffectEntry const* effect = sSpellEffectStore.LookupEntry(i);
+ if (!effect)
+ continue;
+
+ effectsBySpell[effect->EffectSpellId].effects[effect->EffectIndex] = effect;
+ }
+
for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i)
if (SpellEntry const* spellEntry = sSpellStore.LookupEntry(i))
- mSpellInfoMap[i] = new SpellInfo(spellEntry);
+ mSpellInfoMap[i] = new SpellInfo(spellEntry, effectsBySpell[i].effects);
TC_LOG_INFO("server.loading", ">> Loaded SpellInfo store in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
@@ -2923,7 +3002,7 @@ void SpellMgr::LoadSpellInfoCorrections()
SpellInfo* spellInfo = NULL;
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
- spellInfo = mSpellInfoMap[i];
+ spellInfo = (SpellInfo*)mSpellInfoMap[i];
if (!spellInfo)
continue;
@@ -2947,9 +3026,6 @@ void SpellMgr::LoadSpellInfoCorrections()
switch (spellInfo->Id)
{
- case 53096: // Quetz'lun's Judgment
- spellInfo->MaxAffectedTargets = 1;
- break;
case 42436: // Drink! (Brewfest)
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY);
break;
@@ -2974,7 +3050,6 @@ void SpellMgr::LoadSpellInfoCorrections()
case 63665: // Charge (Argent Tournament emote on riders)
case 31298: // Sleep (needs target selection script)
case 51904: // Summon Ghouls On Scarlet Crusade (this should use conditions table, script for this spell needs to be fixed)
- case 2895: // Wrath of Air Totem rank 1 (Aura)
case 68933: // Wrath of Air Totem rank 2 (Aura)
case 29200: // Purify Helboar Meat
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
@@ -3003,28 +3078,13 @@ void SpellMgr::LoadSpellInfoCorrections()
case 59372: // Energize Cores
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENEMY);
break;
- case 8494: // Mana Shield (rank 2)
- // because of bug in dbc
- spellInfo->ProcChance = 0;
- break;
- case 20335: // Heart of the Crusader
- case 20336:
- case 20337:
+ case 63320: // Glyph of Life Tap
case 53228: // Rapid Killing (Rank 1)
case 53232: // Rapid Killing (Rank 2)
- case 63320: // Glyph of Life Tap
// Entries were not updated after spell effect change, we have to do that manually :/
spellInfo->AttributesEx3 |= SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED;
break;
- case 5308: // Execute (Rank 1)
- case 20658: // Execute (Rank 2)
- case 20660: // Execute (Rank 3)
- case 20661: // Execute (Rank 4)
- case 20662: // Execute (Rank 5)
- case 25234: // Execute (Rank 6)
- case 25236: // Execute (Rank 7)
- case 47470: // Execute (Rank 8)
- case 47471: // Execute (Rank 9)
+ case 5308: // Execute
spellInfo->AttributesEx3 |= SPELL_ATTR3_CANT_TRIGGER_PROC;
break;
case 59725: // Improved Spell Reflection - aoe aura
@@ -3032,47 +3092,47 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER_AREA_PARTY);
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS_2);
break;
- case 44978: // Wild Magic
- case 45001:
- case 45002:
- case 45004:
- case 45006:
- case 45010:
case 31347: // Doom
+ case 36327: // Shoot Arcane Explosion Arrow
+ case 39365: // Thundering Storm
+ case 41071: // Raise Dead (HACK)
+ case 42442: // Vengeance Landing Cannonfire
+ case 42611: // Shoot
+ case 44978: // Wild Magic
+ case 45001: // Wild Magic
+ case 45002: // Wild Magic
+ case 45004: // Wild Magic
+ case 45006: // Wild Magic
+ case 45010: // Wild Magic
+ case 45761: // Shoot Gun
+ case 45863: // Cosmetic - Incinerate to Random Target
+ case 48246: // Ball of Flame
case 41635: // Prayer of Mending
case 44869: // Spectral Blast
case 45027: // Revitalize
case 45976: // Muru Portal Channel
- case 39365: // Thundering Storm
- case 41071: // Raise Dead (HACK)
case 52124: // Sky Darkener Assault
- case 42442: // Vengeance Landing Cannonfire
- case 45863: // Cosmetic - Incinerate to Random Target
- case 25425: // Shoot
- case 45761: // Shoot
- case 42611: // Shoot
- case 61588: // Blazing Harpoon
+ case 53096: // Quetz'lun's Judgment
case 52479: // Gift of the Harvester
- case 48246: // Ball of Flame
- case 36327: // Shoot Arcane Explosion Arrow
+ case 61588: // Blazing Harpoon
spellInfo->MaxAffectedTargets = 1;
break;
case 36384: // Skartax Purple Beam
spellInfo->MaxAffectedTargets = 2;
break;
- case 41376: // Spite
- case 39992: // Needle Spine
+ case 28542: // Life Drain - Sapphiron
+ case 29213: // Curse of the Plaguebringer - Noth
case 29576: // Multi-Shot
- case 40816: // Saber Lash
case 37790: // Spread Shot
- case 46771: // Flame Sear
- case 45248: // Shadow Blades
+ case 39992: // Needle Spine
+ case 40816: // Saber Lash
case 41303: // Soul Drain
+ case 41376: // Spite
+ case 45248: // Shadow Blades
+ case 46771: // Flame Sear
+ case 54171: // Divine Storm
case 54172: // Divine Storm (heal)
- case 29213: // Curse of the Plaguebringer - Noth
- case 28542: // Life Drain - Sapphiron
case 66588: // Flaming Spear
- case 54171: // Divine Storm
spellInfo->MaxAffectedTargets = 3;
break;
case 38310: // Multi-Shot
@@ -3100,23 +3160,20 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->MaxAffectedTargets = 15;
break;
case 33711: // Murmur's Touch
- case 38794:
+ case 38794: // Murmur's Touch
spellInfo->MaxAffectedTargets = 1;
spellInfo->Effects[EFFECT_0].TriggerSpell = 33760;
break;
case 17941: // Shadow Trance
case 22008: // Netherwind Focus
- case 31834: // Light's Grace
- case 34754: // Clearcasting
+ case 34477: // Misdirection
case 34936: // Backlash
case 48108: // Hot Streak
case 51124: // Killing Machine
case 54741: // Firestarter
case 57761: // Fireball!
- case 39805: // Lightning Overload
case 64823: // Item - Druid T8 Balance 4P Bonus
- case 34477: // Misdirection
- case 44401: // Missile Barrage
+ case 88819: // Daybreak
spellInfo->ProcCharges = 1;
break;
case 44544: // Fingers of Frost
@@ -3129,36 +3186,34 @@ void SpellMgr::LoadSpellInfoCorrections()
case 28200: // Ascendance (Talisman of Ascendance trinket)
spellInfo->ProcCharges = 6;
break;
- case 37408: // Oscillation Field
- spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS;
- break;
- case 47201: // Everlasting Affliction
- case 47202:
- case 47203:
- case 47204:
- case 47205:
+ case 47201: // Everlasting Affliction (1)
+ case 47202: // Everlasting Affliction (2)
+ case 47203: // Everlasting Affliction (3)
+ case 47204: // Everlasting Affliction (4)
+ case 47205: // Everlasting Affliction (5)
// add corruption to affected spells
spellInfo->Effects[EFFECT_1].SpellClassMask[0] |= 2;
break;
+ case 37408: // Oscillation Field
+ spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS;
+ break;
case 51852: // The Eye of Acherus (no spawn in phase 2 in db)
spellInfo->Effects[EFFECT_0].MiscValue |= 1;
break;
case 51912: // Crafty's Ultra-Advanced Proto-Typical Shortening Blaster
spellInfo->Effects[EFFECT_0].Amplitude = 3000;
break;
- case 29809: // Desecration Arm - 36 instead of 37 - typo? :/
- spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_7_YARDS);
- break;
// Master Shapeshifter: missing stance data for forms other than bear - bear version has correct data
// To prevent aura staying on target after talent unlearned
- case 48420:
+ case 48420: // Master Shapeshifter
+ case 24900: // Heart of the Wild - Cat Effect
spellInfo->Stances = 1 << (FORM_CAT - 1);
break;
- case 48421:
- spellInfo->Stances = 1 << (FORM_MOONKIN - 1);
+ case 24899: // Heart of the Wild - Bear Effect
+ spellInfo->Stances = 1 << (FORM_BEAR - 1);
break;
- case 48422:
- spellInfo->Stances = 1 << (FORM_TREE - 1);
+ case 48421: // Master Shapeshifter
+ spellInfo->Stances = 1 << (FORM_MOONKIN - 1);
break;
case 51466: // Elemental Oath (Rank 1)
case 51470: // Elemental Oath (Rank 2)
@@ -3174,23 +3229,9 @@ void SpellMgr::LoadSpellInfoCorrections()
case 64904: // Hymn of Hope
spellInfo->Effects[EFFECT_1].ApplyAuraName = SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT;
break;
- case 19465: // Improved Stings (Rank 2)
- spellInfo->Effects[EFFECT_2].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
- break;
case 30421: // Nether Portal - Perseverence
spellInfo->Effects[EFFECT_2].BasePoints += 30000;
break;
- case 16834: // Natural shapeshifter
- case 16835:
- spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(21);
- break;
- case 51735: // Ebon Plague
- case 51734:
- case 51726:
- spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS;
- spellInfo->SpellFamilyFlags[2] = 0x10;
- spellInfo->Effects[EFFECT_1].ApplyAuraName = SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN;
- break;
case 41913: // Parasitic Shadowfiend Passive
spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_DUMMY; // proc debuff, and summon infinite fiends
break;
@@ -3200,7 +3241,7 @@ void SpellMgr::LoadSpellInfoCorrections()
case 27915: // Anchor to Skulls
case 27931: // Anchor to Skulls
case 27937: // Anchor to Skulls
- spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(13);
+ spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(EFFECT_RADIUS_10_YARDS);
break;
// target allys instead of enemies, target A is src_caster, spells with effect like that have ally target
// this is the only known exception, probably just wrong data
@@ -3209,10 +3250,6 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY);
spellInfo->Effects[EFFECT_1].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY);
break;
- case 57994: // Wind Shear - improper data for EFFECT_1 in 3.3.5 DBC, but is correct in 4.x
- spellInfo->Effects[EFFECT_1].Effect = SPELL_EFFECT_MODIFY_THREAT_PERCENT;
- spellInfo->Effects[EFFECT_1].BasePoints = -6; // -5%
- break;
case 63675: // Improved Devouring Plague
spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS;
break;
@@ -3223,26 +3260,16 @@ void SpellMgr::LoadSpellInfoCorrections()
case 6474: // Earthbind Totem (instant pulse)
spellInfo->AttributesEx5 |= SPELL_ATTR5_START_PERIODIC_AT_APPLY;
break;
- case 52109: // Flametongue Totem rank 1 (Aura)
- case 52110: // Flametongue Totem rank 2 (Aura)
- case 52111: // Flametongue Totem rank 3 (Aura)
- case 52112: // Flametongue Totem rank 4 (Aura)
- case 52113: // Flametongue Totem rank 5 (Aura)
- case 58651: // Flametongue Totem rank 6 (Aura)
- case 58654: // Flametongue Totem rank 7 (Aura)
- case 58655: // Flametongue Totem rank 8 (Aura)
- spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
- spellInfo->Effects[EFFECT_1].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
- spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo();
- spellInfo->Effects[EFFECT_1].TargetB = SpellImplicitTargetInfo();
- break;
case 53241: // Marked for Death (Rank 1)
case 53243: // Marked for Death (Rank 2)
- case 53244: // Marked for Death (Rank 3)
- case 53245: // Marked for Death (Rank 4)
- case 53246: // Marked for Death (Rank 5)
spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(0x00067801, 0x10820001, 0x00000801);
break;
+ case 5176: // Wrath
+ case 2912: // Starfire
+ case 78674: // Starsurge
+ spellInfo->Effects[EFFECT_1].Effect = SPELL_EFFECT_DUMMY;
+ spellInfo->Effects[EFFECT_1].TargetA = TARGET_UNIT_CASTER;
+ break;
case 70728: // Exploit Weakness (needs target selection script)
case 70840: // Devious Minds (needs target selection script)
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
@@ -3277,26 +3304,9 @@ void SpellMgr::LoadSpellInfoCorrections()
case 45602: // Ride Carpet
spellInfo->Effects[EFFECT_0].BasePoints = 0; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)"
break;
- case 64745: // Item - Death Knight T8 Tank 4P Bonus
- case 64936: // Item - Warrior T8 Protection 4P Bonus
- spellInfo->Effects[EFFECT_0].BasePoints = 100; // 100% chance of procc'ing, not -10% (chance calculated in PrepareTriggersExecutedOnHit)
- break;
- case 19970: // Entangling Roots (Rank 6) -- Nature's Grasp Proc
- case 19971: // Entangling Roots (Rank 5) -- Nature's Grasp Proc
- case 19972: // Entangling Roots (Rank 4) -- Nature's Grasp Proc
- case 19973: // Entangling Roots (Rank 3) -- Nature's Grasp Proc
- case 19974: // Entangling Roots (Rank 2) -- Nature's Grasp Proc
- case 19975: // Entangling Roots (Rank 1) -- Nature's Grasp Proc
- case 27010: // Entangling Roots (Rank 7) -- Nature's Grasp Proc
- case 53313: // Entangling Roots (Rank 8) -- Nature's Grasp Proc
- spellInfo->CastTimeEntry = sSpellCastTimesStore.LookupEntry(1);
- break;
case 61719: // Easter Lay Noblegarden Egg Aura - Interrupt flags copied from aura which this aura is linked with
spellInfo->AuraInterruptFlags = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE;
break;
- case 70650: // Death Knight T10 Tank 2P Bonus
- spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_ADD_PCT_MODIFIER;
- break;
case 71838: // Drain Life - Bryntroll Normal
case 71839: // Drain Life - Bryntroll Heroic
spellInfo->AttributesEx2 |= SPELL_ATTR2_CANT_CRIT;
@@ -3376,7 +3386,7 @@ void SpellMgr::LoadSpellInfoCorrections()
case 64031: // Scrapyard Teleport
case 64032: // Formation Grounds Teleport
case 65042: // Prison of Yogg-Saron Teleport
- spellInfo->Effects[0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
+ spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
break;
// ENDOF ULDUAR SPELLS
//
@@ -3419,10 +3429,6 @@ void SpellMgr::LoadSpellInfoCorrections()
case 70861: // Sindragosa's Lair Teleport
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
break;
- case 69055: // Bone Slice (Lord Marrowgar)
- case 70814: // Bone Slice (Lord Marrowgar)
- spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_5_YARDS); // 5yd
- break;
case 69075: // Bone Storm (Lord Marrowgar)
case 70834: // Bone Storm (Lord Marrowgar)
case 70835: // Bone Storm (Lord Marrowgar)
@@ -3665,39 +3671,46 @@ void SpellMgr::LoadSpellInfoCorrections()
break;
// ENDOF EYE OF ETERNITY SPELLS
//
- // OCULUS SPELLS
- // The spells below are here because their effect 1 is giving warning due to
- // triggered spell not found in any dbc and is missing from encounter source* of data.
- // Even judged as clientside these spells can't be guessed for* now.
- case 49462: // Call Ruby Drake
- case 49461: // Call Amber Drake
- case 49345: // Call Emerald Drake
- spellInfo->Effects[EFFECT_1].Effect = 0;
- break;
- // ENDOF OCULUS SPELLS
- //
case 40055: // Introspection
case 40165: // Introspection
case 40166: // Introspection
case 40167: // Introspection
spellInfo->Attributes |= SPELL_ATTR0_NEGATIVE_1;
break;
- case 45524: // Chains of Ice
- spellInfo->Effects[EFFECT_2].TargetA = SpellImplicitTargetInfo();
- break;
case 2378: // Minor Fortitude
spellInfo->ManaCost = 0;
spellInfo->ManaPerSecond = 0;
break;
+ // Halls Of Origination spells
+ // Temple Guardian Anhuur
+ case 76606: // Disable Beacon Beams L
+ case 76608: // Disable Beacon Beams R
+ // Little hack, Increase the radius so it can hit the Cave In Stalkers in the platform.
+ spellInfo->Effects[EFFECT_0].MaxRadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_45_YARDS);
+ break;
+ case 75323: // Reverberating Hymn
+ // Aura is refreshed at 3 seconds, and the tick should happen at the fourth.
+ spellInfo->AttributesEx8 |= SPELL_ATTR8_DONT_RESET_PERIODIC_TIMER;
+ break;
case 24314: // Threatening Gaze
spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CAST | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_JUMP;
break;
+ case 5420: // Tree of Life (Passive)
+ spellInfo->Stances = 1 << (FORM_TREE - 1);
+ break;
+ case 49376: // Feral Charge (Cat Form)
+ spellInfo->AttributesEx3 &= ~SPELL_ATTR3_CANT_TRIGGER_PROC;
+ break;
case 45257: // Using Steam Tonk Controller
case 45440: // Steam Tonk Controller
case 60256: // Collect Sample
// Crashes client on pressing ESC
spellInfo->AttributesEx4 &= ~SPELL_ATTR4_TRIGGERED;
break;
+ case 96942: // Gaze of Occu'thar
+ case 101009: // Gaze of Occu'thar
+ spellInfo->AttributesEx &= ~SPELL_ATTR1_CHANNELED_1;
+ break;
// ISLE OF CONQUEST SPELLS
//
case 66551: // Teleport
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 448ddb9860b..f2555820b92 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -55,42 +55,40 @@ enum SpellFamilyFlag
// SPELLFAMILYFLAG2 = SpellFamilyFlags[2]
// Rogue
- SPELLFAMILYFLAG_ROGUE_VANISH = 0x00000800,
- SPELLFAMILYFLAG_ROGUE_VAN_EVAS_SPRINT = 0x00000860, // Vanish, Evasion, Sprint
- SPELLFAMILYFLAG1_ROGUE_COLDB_SHADOWSTEP = 0x00000240, // Cold Blood, Shadowstep
- SPELLFAMILYFLAG_ROGUE_KICK = 0x00000010, // Kick
- SPELLFAMILYFLAG1_ROGUE_DISMANTLE = 0x00100000, // Dismantle
- SPELLFAMILYFLAG_ROGUE_BLADE_FLURRY = 0x40000000, // Blade Flurry
- SPELLFAMILYFLAG1_ROGUE_BLADE_FLURRY = 0x00000800, // Blade Flurry
+ SPELLFAMILYFLAG0_ROGUE_VANISH = 0x00000800,
+ SPELLFAMILYFLAG0_ROGUE_VAN_SPRINT = 0x00000840, // Vanish, Sprint
+ SPELLFAMILYFLAG1_ROGUE_SHADOWSTEP = 0x00000200, // Shadowstep
+ SPELLFAMILYFLAG0_ROGUE_KICK = 0x00000010, // Kick
+ SPELLFAMILYFLAG1_ROGUE_DISMANTLE_SMOKE_BOMB = 0x80100000, // Dismantle, Smoke Bomb
// Warrior
- SPELLFAMILYFLAG_WARRIOR_CHARGE = 0x00000001,
- SPELLFAMILYFLAG_WARRIOR_SLAM = 0x00200000,
- SPELLFAMILYFLAG_WARRIOR_EXECUTE = 0x20000000,
- SPELLFAMILYFLAG_WARRIOR_CONCUSSION_BLOW = 0x04000000,
+ SPELLFAMILYFLAG_WARRIOR_CHARGE = 0x00000001,
+ SPELLFAMILYFLAG_WARRIOR_SLAM = 0x00200000,
+ SPELLFAMILYFLAG_WARRIOR_EXECUTE = 0x20000000,
+ SPELLFAMILYFLAG_WARRIOR_CONCUSSION_BLOW = 0x04000000,
// Warlock
- SPELLFAMILYFLAG_WARLOCK_LIFETAP = 0x00040000,
+ SPELLFAMILYFLAG_WARLOCK_LIFETAP = 0x00040000,
// Druid
- SPELLFAMILYFLAG2_DRUID_STARFALL = 0x00000100,
+ SPELLFAMILYFLAG2_DRUID_STARFALL = 0x00000100,
// Paladin
- SPELLFAMILYFLAG1_PALADIN_DIVINESTORM = 0x00020000,
+ SPELLFAMILYFLAG1_PALADIN_DIVINESTORM = 0x00020000,
// Shaman
- SPELLFAMILYFLAG_SHAMAN_FROST_SHOCK = 0x80000000,
- SPELLFAMILYFLAG_SHAMAN_HEALING_STREAM = 0x00002000,
- SPELLFAMILYFLAG_SHAMAN_MANA_SPRING = 0x00004000,
- SPELLFAMILYFLAG2_SHAMAN_LAVA_LASH = 0x00000004,
- SPELLFAMILYFLAG_SHAMAN_FIRE_NOVA = 0x28000000,
+ SPELLFAMILYFLAG_SHAMAN_FROST_SHOCK = 0x80000000,
+ SPELLFAMILYFLAG_SHAMAN_HEALING_STREAM = 0x00002000,
+ SPELLFAMILYFLAG_SHAMAN_MANA_SPRING = 0x00004000,
+ SPELLFAMILYFLAG2_SHAMAN_LAVA_LASH = 0x00000004,
+ SPELLFAMILYFLAG_SHAMAN_FIRE_NOVA = 0x28000000,
// Deathknight
- SPELLFAMILYFLAG_DK_DEATH_STRIKE = 0x00000010,
- SPELLFAMILYFLAG_DK_DEATH_COIL = 0x00002000,
+ SPELLFAMILYFLAG_DK_DEATH_STRIKE = 0x00000010,
+ SPELLFAMILYFLAG_DK_DEATH_COIL = 0x00002000,
/// @todo Figure out a more accurate name for the following familyflag(s)
- SPELLFAMILYFLAG_SHAMAN_TOTEM_EFFECTS = 0x04000000 // Seems to be linked to most totems and some totem effects
+ SPELLFAMILYFLAG_SHAMAN_TOTEM_EFFECTS = 0x04000000 // Seems to be linked to most totems and some totem effects
};
@@ -580,6 +578,8 @@ typedef std::map<int32, std::vector<int32> > SpellLinkedMap;
bool IsPrimaryProfessionSkill(uint32 skill);
+bool IsWeaponSkill(uint32 skill);
+
inline bool IsProfessionSkill(uint32 skill)
{
return IsPrimaryProfessionSkill(skill) || skill == SKILL_FISHING || skill == SKILL_COOKING || skill == SKILL_FIRST_AID;
diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp
index 8bd7a5a5e71..3fbbd34777b 100644
--- a/src/server/game/Texts/CreatureTextMgr.cpp
+++ b/src/server/game/Texts/CreatureTextMgr.cpp
@@ -327,6 +327,7 @@ void CreatureTextMgr::SendSound(Creature* source, uint32 sound, ChatMsg msgType,
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << uint32(sound);
+ data << uint64(source->GetGUID());
SendNonChatPacket(source, &data, msgType, whisperTarget, range, team, gmOnly);
}
diff --git a/src/server/game/Texts/CreatureTextMgr.h b/src/server/game/Texts/CreatureTextMgr.h
index 18dc7683b8d..aef38a1923e 100644
--- a/src/server/game/Texts/CreatureTextMgr.h
+++ b/src/server/game/Texts/CreatureTextMgr.h
@@ -151,7 +151,7 @@ class CreatureTextLocalizer
{
messageTemplate = new WorldPacket();
whisperGUIDpos = _builder(messageTemplate, loc_idx);
- ASSERT(messageTemplate->GetOpcode() != MSG_NULL_ACTION);
+ ASSERT(messageTemplate->GetOpcode() != NULL_OPCODE);
_packetCache[loc_idx] = new std::pair<WorldPacket*, size_t>(messageTemplate, whisperGUIDpos);
}
else
diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp
index 71d51153b4c..c6b1da46e6b 100644
--- a/src/server/game/Tickets/TicketMgr.cpp
+++ b/src/server/game/Tickets/TicketMgr.cpp
@@ -125,6 +125,11 @@ void GmTicket::WritePacket(WorldPacket& data) const
data << uint8(std::min(_escalatedStatus, TICKET_IN_ESCALATION_QUEUE)); // escalated data
data << uint8(_viewed ? GMTICKET_OPENEDBYGM_STATUS_OPENED : GMTICKET_OPENEDBYGM_STATUS_NOT_OPENED); // whether or not it has been viewed
+
+ // TODO: implement these
+ std::string waitTimeOverrideMessage = "";
+ data << waitTimeOverrideMessage;
+ data << uint32(0); // waitTimeOverrideMinutes
}
void GmTicket::SendResponse(WorldSession* session) const
diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp
index 6cec8ba0220..3cde5a6d70f 100644
--- a/src/server/game/Tools/PlayerDump.cpp
+++ b/src/server/game/Tools/PlayerDump.cpp
@@ -24,7 +24,7 @@
#include "AccountMgr.h"
#include "World.h"
-#define DUMP_TABLE_COUNT 27
+#define DUMP_TABLE_COUNT 29
struct DumpTable
{
char const* name;
@@ -39,6 +39,8 @@ static DumpTable dumpTables[DUMP_TABLE_COUNT] =
{ "character_achievement_progress", DTT_CHAR_TABLE },
{ "character_action", DTT_CHAR_TABLE },
{ "character_aura", DTT_CHAR_TABLE },
+ { "character_currency", DTT_CHAR_TABLE },
+ { "character_cuf_profiles", DTT_CHAR_TABLE },
{ "character_declinedname", DTT_CHAR_TABLE },
{ "character_equipmentsets", DTT_EQSET_TABLE},
{ "character_glyphs", DTT_CHAR_TABLE },
@@ -320,10 +322,13 @@ bool PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl
break;
case DTT_CHARACTER:
{
- if (result->GetFieldCount() <= 68) // avoid crashes on next check
+ if (result->GetFieldCount() <= 64) // avoid crashes on next check
+ {
TC_LOG_FATAL("misc", "PlayerDumpWriter::DumpTable - Trying to access non-existing or wrong positioned field (`deleteInfos_Account`) in `characters` table.");
+ return false;
+ }
- if (result->Fetch()[68].GetUInt32()) // characters.deleteInfos_Account - if filled error
+ if (result->Fetch()[64].GetUInt32()) // characters.deleteInfos_Account - if filled error
return false;
break;
}
@@ -543,18 +548,18 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (result)
- if (!changenth(line, 37, "1")) // characters.at_login set to "rename on login"
+ if (!changenth(line, 38, "1")) // characters.at_login set to "rename on login"
ROLLBACK(DUMP_FILE_BROKEN);
}
else if (!changenth(line, 3, name.c_str())) // characters.name
ROLLBACK(DUMP_FILE_BROKEN);
const char null[5] = "NULL";
- if (!changenth(line, 69, null)) // characters.deleteInfos_Account
+ if (!changenth(line, 63, null)) // characters.deleteInfos_Account
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 70, null)) // characters.deleteInfos_Name
+ if (!changenth(line, 64, null)) // characters.deleteInfos_Name
ROLLBACK(DUMP_FILE_BROKEN);
- if (!changenth(line, 71, null)) // characters.deleteDate
+ if (!changenth(line, 65, null)) // characters.deleteDate
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
diff --git a/src/server/game/Tools/PlayerDump.h b/src/server/game/Tools/PlayerDump.h
index ece2c0693e2..8be71f1a819 100644
--- a/src/server/game/Tools/PlayerDump.h
+++ b/src/server/game/Tools/PlayerDump.h
@@ -30,7 +30,8 @@ enum DumpTableType
DTT_CHAR_TABLE, // // character_achievement, character_achievement_progress,
// character_action, character_aura, character_homebind,
// character_queststatus, character_queststatus_rewarded, character_reputation,
- // character_spell, character_spell_cooldown, character_ticket, character_talent
+ // character_spell, character_spell_cooldown, character_ticket, character_talent.
+ // character_cuf_profiles, character_currency
DTT_EQSET_TABLE, // <- guid // character_equipmentsets
diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp
index da6a7dc1929..1a6127daa89 100644
--- a/src/server/game/Warden/WardenWin.cpp
+++ b/src/server/game/Warden/WardenWin.cpp
@@ -16,7 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "Cryptography/HMACSHA1.h"
+#include "Cryptography/HmacHash.h"
#include "Cryptography/WardenKeyGeneration.h"
#include "Common.h"
#include "WorldPacket.h"
@@ -283,7 +283,7 @@ void WardenWin::RequestData()
{
uint32 seed = rand32();
buff << uint32(seed);
- HmacHash hmac(4, (uint8*)&seed);
+ HmacSha1 hmac(4, (uint8*)&seed);
hmac.UpdateData(wd->Str);
hmac.Finalize();
buff.append(hmac.GetDigest(), hmac.GetLength());
diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp
index dea7dfa6819..cab232931b9 100644
--- a/src/server/game/Weather/Weather.cpp
+++ b/src/server/game/Weather/Weather.cpp
@@ -28,6 +28,7 @@
#include "ObjectMgr.h"
#include "Util.h"
#include "ScriptMgr.h"
+#include "Opcodes.h"
#include "WorldSession.h"
/// Create the Weather object
diff --git a/src/server/game/Weather/Weather.h b/src/server/game/Weather/Weather.h
index 0bdd6af6dc5..ae83fa67a84 100644
--- a/src/server/game/Weather/Weather.h
+++ b/src/server/game/Weather/Weather.h
@@ -46,7 +46,7 @@ struct WeatherData
enum WeatherState
{
WEATHER_STATE_FINE = 0,
- WEATHER_STATE_FOG = 1,
+ WEATHER_STATE_FOG = 1, // Used in some instance encounters.
WEATHER_STATE_LIGHT_RAIN = 3,
WEATHER_STATE_MEDIUM_RAIN = 4,
WEATHER_STATE_HEAVY_RAIN = 5,
diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp
index 938c91b0228..f18809b107a 100644
--- a/src/server/game/Weather/WeatherMgr.cpp
+++ b/src/server/game/Weather/WeatherMgr.cpp
@@ -26,6 +26,7 @@
#include "ObjectMgr.h"
#include "Player.h"
#include "WorldPacket.h"
+#include "Opcodes.h"
#include "WorldSession.h"
namespace WeatherMgr
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 533fbe6b2a4..14591db9eb6 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -41,11 +41,13 @@
#include "ObjectMgr.h"
#include "ArenaTeamMgr.h"
#include "GuildMgr.h"
+#include "GuildFinderMgr.h"
#include "TicketMgr.h"
#include "SpellMgr.h"
#include "GroupMgr.h"
#include "Chat.h"
#include "DBCStores.h"
+#include "DB2Stores.h"
#include "LootMgr.h"
#include "ItemEnchantmentMgr.h"
#include "MapManager.h"
@@ -114,6 +116,7 @@ World::World()
m_NextMonthlyQuestReset = 0;
m_NextRandomBGReset = 0;
m_NextGuildReset = 0;
+ m_NextCurrencyReset = 0;
m_defaultDbcLocale = LOCALE_enUS;
m_availableDbcLocaleMask = 0;
@@ -286,7 +289,7 @@ void World::AddSession_(WorldSession* s)
return;
}
- s->SendAuthResponse(AUTH_OK, true);
+ s->SendAuthResponse(AUTH_OK, false);
s->SendAddonsInfo();
s->SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
s->SendTutorialsData();
@@ -342,7 +345,7 @@ void World::AddQueuedPlayer(WorldSession* sess)
m_QueuedPlayer.push_back(sess);
// The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
- sess->SendAuthResponse(AUTH_WAIT_QUEUE, false, GetQueuePos(sess));
+ sess->SendAuthResponse(AUTH_WAIT_QUEUE, true, GetQueuePos(sess));
}
bool World::RemoveQueuedPlayer(WorldSession* sess)
@@ -416,6 +419,16 @@ void World::LoadConfigSettings(bool reload)
sLog->LoadFromConfig();
}
+ m_defaultDbcLocale = LocaleConstant(sConfigMgr->GetIntDefault("DBC.Locale", 0));
+
+ if (m_defaultDbcLocale >= TOTAL_LOCALES)
+ {
+ TC_LOG_ERROR("server.loading", "Incorrect DBC.Locale! Must be >= 0 and < %d (set to 0)", TOTAL_LOCALES);
+ m_defaultDbcLocale = LOCALE_enUS;
+ }
+
+ TC_LOG_INFO("server.loading", "Using %s DBC Locale", localeNames[m_defaultDbcLocale]);
+
///- Read the player limit and the Message of the day from the config file
SetPlayerAmountLimit(sConfigMgr->GetIntDefault("PlayerLimit", 100));
SetMotd(sConfigMgr->GetStringDefault("Motd", "Welcome to a Trinity Core Server."));
@@ -777,57 +790,84 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_START_PLAYER_MONEY] = sConfigMgr->GetIntDefault("StartPlayerMoney", 0);
if (int32(m_int_configs[CONFIG_START_PLAYER_MONEY]) < 0)
{
- TC_LOG_ERROR("server.loading", "StartPlayerMoney (%i) must be in range 0..%u. Set to %u.", m_int_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, 0);
+ TC_LOG_ERROR("server.loading", "StartPlayerMoney (%i) must be in range 0.." UI64FMTD ". Set to %u.", m_int_configs[CONFIG_START_PLAYER_MONEY], uint64(MAX_MONEY_AMOUNT), 0);
m_int_configs[CONFIG_START_PLAYER_MONEY] = 0;
}
- else if (m_int_configs[CONFIG_START_PLAYER_MONEY] > MAX_MONEY_AMOUNT)
+ else if (m_int_configs[CONFIG_START_PLAYER_MONEY] > 0x7FFFFFFF-1) // TODO: (See MAX_MONEY_AMOUNT)
{
TC_LOG_ERROR("server.loading", "StartPlayerMoney (%i) must be in range 0..%u. Set to %u.",
- m_int_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, MAX_MONEY_AMOUNT);
- m_int_configs[CONFIG_START_PLAYER_MONEY] = MAX_MONEY_AMOUNT;
+ m_int_configs[CONFIG_START_PLAYER_MONEY], 0x7FFFFFFF-1, 0x7FFFFFFF-1);
+ m_int_configs[CONFIG_START_PLAYER_MONEY] = 0x7FFFFFFF-1;
}
- m_int_configs[CONFIG_MAX_HONOR_POINTS] = sConfigMgr->GetIntDefault("MaxHonorPoints", 75000);
- if (int32(m_int_configs[CONFIG_MAX_HONOR_POINTS]) < 0)
+ m_int_configs[CONFIG_CURRENCY_RESET_HOUR] = sConfigMgr->GetIntDefault("Currency.ResetHour", 3);
+ if (m_int_configs[CONFIG_CURRENCY_RESET_HOUR] > 23)
{
- TC_LOG_ERROR("server.loading", "MaxHonorPoints (%i) can't be negative. Set to 0.", m_int_configs[CONFIG_MAX_HONOR_POINTS]);
- m_int_configs[CONFIG_MAX_HONOR_POINTS] = 0;
+ TC_LOG_ERROR("server.loading", "Currency.ResetHour (%i) can't be load. Set to 6.", m_int_configs[CONFIG_CURRENCY_RESET_HOUR]);
+ m_int_configs[CONFIG_CURRENCY_RESET_HOUR] = 3;
+ }
+ m_int_configs[CONFIG_CURRENCY_RESET_DAY] = sConfigMgr->GetIntDefault("Currency.ResetDay", 3);
+ if (m_int_configs[CONFIG_CURRENCY_RESET_DAY] > 6)
+ {
+ TC_LOG_ERROR("server.loading", "Currency.ResetDay (%i) can't be load. Set to 3.", m_int_configs[CONFIG_CURRENCY_RESET_DAY]);
+ m_int_configs[CONFIG_CURRENCY_RESET_DAY] = 3;
+ }
+ m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL] = sConfigMgr->GetIntDefault("Currency.ResetInterval", 7);
+ if (int32(m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL]) <= 0)
+ {
+ TC_LOG_ERROR("server.loading", "Currency.ResetInterval (%i) must be > 0, set to default 7.", m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL]);
+ m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL] = 7;
}
- m_int_configs[CONFIG_START_HONOR_POINTS] = sConfigMgr->GetIntDefault("StartHonorPoints", 0);
- if (int32(m_int_configs[CONFIG_START_HONOR_POINTS]) < 0)
+ m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS] = sConfigMgr->GetIntDefault("Currency.StartHonorPoints", 0);
+ if (int32(m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS]) < 0)
{
- TC_LOG_ERROR("server.loading", "StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.",
- m_int_configs[CONFIG_START_HONOR_POINTS], m_int_configs[CONFIG_MAX_HONOR_POINTS], 0);
- m_int_configs[CONFIG_START_HONOR_POINTS] = 0;
+ TC_LOG_ERROR("server.loading", "Currency.StartHonorPoints (%i) must be >= 0, set to default 0.", m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS]);
+ m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS] = 0;
}
- else if (m_int_configs[CONFIG_START_HONOR_POINTS] > m_int_configs[CONFIG_MAX_HONOR_POINTS])
+ m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS] = sConfigMgr->GetIntDefault("Currency.MaxHonorPoints", 4000);
+ if (int32(m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS]) < 0)
{
- TC_LOG_ERROR("server.loading", "StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.",
- m_int_configs[CONFIG_START_HONOR_POINTS], m_int_configs[CONFIG_MAX_HONOR_POINTS], m_int_configs[CONFIG_MAX_HONOR_POINTS]);
- m_int_configs[CONFIG_START_HONOR_POINTS] = m_int_configs[CONFIG_MAX_HONOR_POINTS];
+ TC_LOG_ERROR("server.loading", "Currency.MaxHonorPoints (%i) can't be negative. Set to default 4000.", m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS]);
+ m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS] = 4000;
}
+ m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS] *= 100; //precision mod
- m_int_configs[CONFIG_MAX_ARENA_POINTS] = sConfigMgr->GetIntDefault("MaxArenaPoints", 10000);
- if (int32(m_int_configs[CONFIG_MAX_ARENA_POINTS]) < 0)
+ m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS] = sConfigMgr->GetIntDefault("Currency.StartJusticePoints", 0);
+ if (int32(m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS]) < 0)
+ {
+ TC_LOG_ERROR("server.loading", "Currency.StartJusticePoints (%i) must be >= 0, set to default 0.", m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS]);
+ m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS] = 0;
+ }
+ m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS] = sConfigMgr->GetIntDefault("Currency.MaxJusticePoints", 4000);
+ if (int32(m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS]) < 0)
{
- TC_LOG_ERROR("server.loading", "MaxArenaPoints (%i) can't be negative. Set to 0.", m_int_configs[CONFIG_MAX_ARENA_POINTS]);
- m_int_configs[CONFIG_MAX_ARENA_POINTS] = 0;
+ TC_LOG_ERROR("server.loading", "Currency.MaxJusticePoints (%i) can't be negative. Set to default 4000.", m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS]);
+ m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS] = 4000;
}
+ m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS] *= 100; //precision mod
- m_int_configs[CONFIG_START_ARENA_POINTS] = sConfigMgr->GetIntDefault("StartArenaPoints", 0);
- if (int32(m_int_configs[CONFIG_START_ARENA_POINTS]) < 0)
+ m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS] = sConfigMgr->GetIntDefault("Currency.StartConquestPoints", 0);
+ if (int32(m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS]) < 0)
{
- TC_LOG_ERROR("server.loading", "StartArenaPoints (%i) must be in range 0..MaxArenaPoints(%u). Set to %u.",
- m_int_configs[CONFIG_START_ARENA_POINTS], m_int_configs[CONFIG_MAX_ARENA_POINTS], 0);
- m_int_configs[CONFIG_START_ARENA_POINTS] = 0;
+ TC_LOG_ERROR("server.loading", "Currency.StartConquestPoints (%i) must be >= 0, set to default 0.", m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS]);
+ m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS] = 0;
}
- else if (m_int_configs[CONFIG_START_ARENA_POINTS] > m_int_configs[CONFIG_MAX_ARENA_POINTS])
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP] = sConfigMgr->GetIntDefault("Currency.ConquestPointsWeekCap", 1650);
+ if (int32(m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP]) <= 0)
{
- TC_LOG_ERROR("server.loading", "StartArenaPoints (%i) must be in range 0..MaxArenaPoints(%u). Set to %u.",
- m_int_configs[CONFIG_START_ARENA_POINTS], m_int_configs[CONFIG_MAX_ARENA_POINTS], m_int_configs[CONFIG_MAX_ARENA_POINTS]);
- m_int_configs[CONFIG_START_ARENA_POINTS] = m_int_configs[CONFIG_MAX_ARENA_POINTS];
+ TC_LOG_ERROR("server.loading", "Currency.ConquestPointsWeekCap (%i) must be > 0, set to default 1650.", m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP]);
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP] = 1650;
}
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP] *= 100; //precision mod
+
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD] = sConfigMgr->GetIntDefault("Currency.ConquestPointsArenaReward", 180);
+ if (int32(m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD]) <= 0)
+ {
+ TC_LOG_ERROR("server.loading", "Currency.ConquestPointsArenaReward (%i) must be > 0, set to default 180.", m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD]);
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD] = 180;
+ }
+ m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD] *= 100; //precision mod
m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = sConfigMgr->GetIntDefault("RecruitAFriend.MaxLevel", 60);
if (m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
@@ -924,13 +964,10 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfigMgr->GetIntDefault("SkillGain.Crafting", 1);
- m_int_configs[CONFIG_SKILL_GAIN_DEFENSE] = sConfigMgr->GetIntDefault("SkillGain.Defense", 1);
-
m_int_configs[CONFIG_SKILL_GAIN_GATHERING] = sConfigMgr->GetIntDefault("SkillGain.Gathering", 1);
- m_int_configs[CONFIG_SKILL_GAIN_WEAPON] = sConfigMgr->GetIntDefault("SkillGain.Weapon", 1);
-
m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] = sConfigMgr->GetIntDefault("MaxOverspeedPings", 2);
+
if (m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] != 0 && m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] < 2)
{
TC_LOG_ERROR("server.loading", "MaxOverspeedPings (%i) must be in range 2..infinity (or 0 to disable check). Set to 2.", m_int_configs[CONFIG_MAX_OVERSPEED_PINGS]);
@@ -942,8 +979,6 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_DISABLE_BREATHING] = sConfigMgr->GetIntDefault("DisableWaterBreath", SEC_CONSOLE);
- m_bool_configs[CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL] = sConfigMgr->GetBoolDefault("AlwaysMaxSkillForLevel", false);
-
if (reload)
{
uint32 val = sConfigMgr->GetIntDefault("Expansion", 2);
@@ -1017,6 +1052,7 @@ void World::LoadConfigSettings(bool reload)
// always use declined names in the russian client
m_bool_configs[CONFIG_DECLINED_NAMES_USED] =
+
(m_int_configs[CONFIG_REALM_ZONE] == REALM_ZONE_RUSSIAN) ? true : sConfigMgr->GetBoolDefault("DeclinedNames", false);
m_float_configs[CONFIG_LISTEN_RANGE_SAY] = sConfigMgr->GetFloatDefault("ListenRange.Say", 25.0f);
@@ -1033,8 +1069,6 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfigMgr->GetIntDefault ("Arena.MaxRatingDifference", 150);
m_int_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfigMgr->GetIntDefault ("Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILLISECONDS);
m_int_configs[CONFIG_ARENA_RATED_UPDATE_TIMER] = sConfigMgr->GetIntDefault ("Arena.RatedUpdateTimer", 5 * IN_MILLISECONDS);
- m_bool_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfigMgr->GetBoolDefault("Arena.AutoDistributePoints", false);
- m_int_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfigMgr->GetIntDefault ("Arena.AutoDistributeInterval", 7);
m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetBoolDefault("Arena.QueueAnnouncer.Enable", false);
m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY] = sConfigMgr->GetBoolDefault("Arena.QueueAnnouncer.PlayerOnly", false);
m_int_configs[CONFIG_ARENA_SEASON_ID] = sConfigMgr->GetIntDefault ("Arena.ArenaSeason.ID", 1);
@@ -1060,6 +1094,9 @@ void World::LoadConfigSettings(bool reload)
TC_LOG_ERROR("server.loading", "ClientCacheVersion can't be negative %d, ignored.", clientCacheId);
}
+ m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] = sConfigMgr->GetIntDefault("Guild.NewsLogRecordsCount", GUILD_NEWSLOG_MAX_RECORDS);
+ if (m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] > GUILD_NEWSLOG_MAX_RECORDS)
+ m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] = GUILD_NEWSLOG_MAX_RECORDS;
m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = sConfigMgr->GetIntDefault("Guild.EventLogRecordsCount", GUILD_EVENTLOG_MAX_RECORDS);
if (m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] > GUILD_EVENTLOG_MAX_RECORDS)
m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = GUILD_EVENTLOG_MAX_RECORDS;
@@ -1200,12 +1237,12 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_ACC_PASSCHANGESEC] = sConfigMgr->GetIntDefault("Account.PasswordChangeSecurity", 0);
// Random Battleground Rewards
- m_int_configs[CONFIG_BG_REWARD_WINNER_HONOR_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerHonorFirst", 30);
- m_int_configs[CONFIG_BG_REWARD_WINNER_ARENA_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerArenaFirst", 25);
- m_int_configs[CONFIG_BG_REWARD_WINNER_HONOR_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerHonorLast", 15);
- m_int_configs[CONFIG_BG_REWARD_WINNER_ARENA_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerArenaLast", 0);
- m_int_configs[CONFIG_BG_REWARD_LOSER_HONOR_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardLoserHonorFirst", 5);
- m_int_configs[CONFIG_BG_REWARD_LOSER_HONOR_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardLoserHonorLast", 5);
+ m_int_configs[CONFIG_BG_REWARD_WINNER_HONOR_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerHonorFirst", 27000);
+ m_int_configs[CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerConquestFirst", 10000);
+ m_int_configs[CONFIG_BG_REWARD_WINNER_HONOR_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerHonorLast", 13500);
+ m_int_configs[CONFIG_BG_REWARD_WINNER_CONQUEST_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerConquestLast", 5000);
+ m_int_configs[CONFIG_BG_REWARD_LOSER_HONOR_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardLoserHonorFirst", 4500);
+ m_int_configs[CONFIG_BG_REWARD_LOSER_HONOR_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardLoserHonorLast", 3500);
// Max instances per hour
m_int_configs[CONFIG_MAX_INSTANCES_PER_HOUR] = sConfigMgr->GetIntDefault("AccountInstancesPerHour", 5);
@@ -1226,6 +1263,15 @@ void World::LoadConfigSettings(bool reload)
// MySQL ping time interval
m_int_configs[CONFIG_DB_PING_INTERVAL] = sConfigMgr->GetIntDefault("MaxPingTime", 30);
+ // Guild save interval
+ m_bool_configs[CONFIG_GUILD_LEVELING_ENABLED] = sConfigMgr->GetBoolDefault("Guild.LevelingEnabled", true);
+ m_int_configs[CONFIG_GUILD_SAVE_INTERVAL] = sConfigMgr->GetIntDefault("Guild.SaveInterval", 15);
+ m_int_configs[CONFIG_GUILD_MAX_LEVEL] = sConfigMgr->GetIntDefault("Guild.MaxLevel", 25);
+ m_int_configs[CONFIG_GUILD_UNDELETABLE_LEVEL] = sConfigMgr->GetIntDefault("Guild.UndeletableLevel", 4);
+ rate_values[RATE_XP_GUILD_MODIFIER] = sConfigMgr->GetFloatDefault("Guild.XPModifier", 0.25f);
+ m_int_configs[CONFIG_GUILD_DAILY_XP_CAP] = sConfigMgr->GetIntDefault("Guild.DailyXPCap", 7807500);
+ m_int_configs[CONFIG_GUILD_WEEKLY_REP_CAP] = sConfigMgr->GetIntDefault("Guild.WeeklyReputationCap", 4375);
+
// misc
m_bool_configs[CONFIG_PDUMP_NO_PATHS] = sConfigMgr->GetBoolDefault("PlayerDump.DisallowPaths", true);
m_bool_configs[CONFIG_PDUMP_NO_OVERWRITE] = sConfigMgr->GetBoolDefault("PlayerDump.DisallowOverwrite", true);
@@ -1255,8 +1301,6 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_PACKET_SPOOF_BANDURATION] = sConfigMgr->GetIntDefault("PacketSpoof.BanDuration", 86400);
- m_int_configs[CONFIG_BIRTHDAY_TIME] = sConfigMgr->GetIntDefault("BirthdayTime", 1222964635);
-
m_bool_configs[CONFIG_IP_BASED_ACTION_LOGGING] = sConfigMgr->GetBoolDefault("Allow.IP.Based.Action.Logging", false);
// call ScriptMgr if we're reloading the configuration
@@ -1331,7 +1375,7 @@ void World::SetInitialWorldSettings()
///- Load the DBC files
TC_LOG_INFO("server.loading", "Initialize data stores...");
LoadDBCStores(m_dataPath);
- DetectDBCLang();
+ LoadDB2Stores(m_dataPath);
TC_LOG_INFO("server.loading", "Loading SpellInfo store...");
sSpellMgr->LoadSpellInfoStore();
@@ -1367,7 +1411,6 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadCreatureLocales();
sObjectMgr->LoadGameObjectLocales();
sObjectMgr->LoadItemLocales();
- sObjectMgr->LoadItemSetNameLocales();
sObjectMgr->LoadQuestLocales();
sObjectMgr->LoadNpcTextLocales();
sObjectMgr->LoadPageTextLocales();
@@ -1419,6 +1462,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Spell Group Stack Rules...");
sSpellMgr->LoadSpellGroupStackRules();
+ TC_LOG_INFO("server.loading", "Loading Spell Phase Dbc Info...");
+ sObjectMgr->LoadPhaseInfo();
+
TC_LOG_INFO("server.loading", "Loading NPC Texts...");
sObjectMgr->LoadGossipText();
@@ -1435,7 +1481,10 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadItemTemplates();
TC_LOG_INFO("server.loading", "Loading Item set names..."); // must be after LoadItemPrototypes
- sObjectMgr->LoadItemSetNames();
+ sObjectMgr->LoadItemTemplateAddon();
+
+ TC_LOG_INFO("misc", "Loading Item Scripts..."); // must be after LoadItemPrototypes
+ sObjectMgr->LoadItemScriptNames();
TC_LOG_INFO("server.loading", "Loading Creature Model Based Info Data...");
sObjectMgr->LoadCreatureModelInfo();
@@ -1545,6 +1594,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Graveyard-zone links...");
sObjectMgr->LoadGraveyardZones();
+ TC_LOG_INFO("server.loading", "Loading Graveyard Orientations...");
+ sObjectMgr->LoadGraveyardOrientations();
+
TC_LOG_INFO("server.loading", "Loading spell pet auras...");
sSpellMgr->LoadSpellPetAuras();
@@ -1616,9 +1668,17 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Auctions...");
sAuctionMgr->LoadAuctions();
+ TC_LOG_INFO("server.loading", "Loading Guild XP for level...");
+ sGuildMgr->LoadGuildXpForLevel();
+
+ TC_LOG_INFO("server.loading", "Loading Guild rewards...");
+ sGuildMgr->LoadGuildRewards();
+
TC_LOG_INFO("server.loading", "Loading Guilds...");
sGuildMgr->LoadGuilds();
+ sGuildFinderMgr->LoadFromDB();
+
TC_LOG_INFO("server.loading", "Loading ArenaTeams...");
sArenaTeamMgr->LoadArenaTeams();
@@ -1661,6 +1721,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading World States..."); // must be loaded before battleground, outdoor PvP and conditions
LoadWorldStates();
+ TC_LOG_INFO("server.loading", "Loading Phase definitions...");
+ sObjectMgr->LoadPhaseDefinitions();
+
TC_LOG_INFO("server.loading", "Loading Conditions...");
sConditionMgr->LoadConditions();
@@ -1746,6 +1809,8 @@ void World::SetInitialWorldSettings()
m_timers[WUPDATE_PINGDB].SetInterval(getIntConfig(CONFIG_DB_PING_INTERVAL)*MINUTE*IN_MILLISECONDS); // Mysql ping time in minutes
+ m_timers[WUPDATE_GUILDSAVE].SetInterval(getIntConfig(CONFIG_GUILD_SAVE_INTERVAL) * MINUTE * IN_MILLISECONDS);
+
//to set mailtimer to return mails every day between 4 and 5 am
//mailtimer is increased when updating auctions
//one second is 1000 -(tested on win system)
@@ -1782,7 +1847,6 @@ void World::SetInitialWorldSettings()
///- Initialize Battlegrounds
TC_LOG_INFO("server.loading", "Starting Battleground System");
sBattlegroundMgr->LoadBattlegroundTemplates();
- sBattlegroundMgr->InitAutomaticArenaPointDistribution();
///- Initialize outdoor pvp
TC_LOG_INFO("server.loading", "Starting Outdoor PvP System");
@@ -1820,8 +1884,20 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Calculate guild limitation(s) reset time...");
InitGuildResetTime();
+ TC_LOG_INFO("server.loading", "Calculate next currency reset time...");
+ InitCurrencyResetTime();
+
LoadCharacterNameData();
+ TC_LOG_INFO("misc", "Initializing Opcodes...");
+ opcodeTable.Initialize();
+
+ TC_LOG_INFO("misc", "Loading hotfix info...");
+ sObjectMgr->LoadHotfixData();
+
+ TC_LOG_INFO("server.loading", "Loading missing KeyChains...");
+ sObjectMgr->LoadMissingKeyChains();
+
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
TC_LOG_INFO("server.worldserver", "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000));
@@ -1830,49 +1906,6 @@ void World::SetInitialWorldSettings()
sLog->SetRealmId(realmId);
}
-void World::DetectDBCLang()
-{
- uint8 m_lang_confid = sConfigMgr->GetIntDefault("DBC.Locale", 255);
-
- if (m_lang_confid != 255 && m_lang_confid >= TOTAL_LOCALES)
- {
- TC_LOG_ERROR("server.loading", "Incorrect DBC.Locale! Must be >= 0 and < %d (set to 0)", TOTAL_LOCALES);
- m_lang_confid = LOCALE_enUS;
- }
-
- ChrRacesEntry const* race = sChrRacesStore.LookupEntry(1);
-
- std::string availableLocalsStr;
-
- uint8 default_locale = TOTAL_LOCALES;
- for (uint8 i = default_locale-1; i < TOTAL_LOCALES; --i) // -1 will be 255 due to uint8
- {
- if (race->name[i][0] != '\0') // check by race names
- {
- default_locale = i;
- m_availableDbcLocaleMask |= (1 << i);
- availableLocalsStr += localeNames[i];
- availableLocalsStr += " ";
- }
- }
-
- if (default_locale != m_lang_confid && m_lang_confid < TOTAL_LOCALES &&
- (m_availableDbcLocaleMask & (1 << m_lang_confid)))
- {
- default_locale = m_lang_confid;
- }
-
- if (default_locale >= TOTAL_LOCALES)
- {
- TC_LOG_ERROR("server.loading", "Unable to determine your DBC Locale! (corrupt DBC?)");
- exit(1);
- }
-
- m_defaultDbcLocale = LocaleConstant(default_locale);
-
- TC_LOG_INFO("server.loading", "Using %s DBC Locale as default. All available DBC locales: %s", localeNames[m_defaultDbcLocale], availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str());
-}
-
void World::RecordTimeDiff(const char *text, ...)
{
if (m_updateTimeCount != 1)
@@ -1986,6 +2019,9 @@ void World::Update(uint32 diff)
if (m_gameTime > m_NextGuildReset)
ResetGuildCap();
+ if (m_gameTime > m_NextCurrencyReset)
+ ResetCurrencyWeekCap();
+
/// <ul><li> Handle auctions when the timer has passed
if (m_timers[WUPDATE_AUCTIONS].Passed())
{
@@ -2113,6 +2149,12 @@ void World::Update(uint32 diff)
WorldDatabase.KeepAlive();
}
+ if (m_timers[WUPDATE_GUILDSAVE].Passed())
+ {
+ m_timers[WUPDATE_GUILDSAVE].Reset();
+ sGuildMgr->SaveGuilds();
+ }
+
// update the instance reset times
sInstanceSaveMgr->Update();
@@ -2712,16 +2754,20 @@ void World::SendAutoBroadcast()
sWorld->SendWorldText(LANG_AUTO_BROADCAST, msg.c_str());
else if (abcenter == 1)
{
- WorldPacket data(SMSG_NOTIFICATION, (msg.size()+1));
- data << msg;
+ WorldPacket data(SMSG_NOTIFICATION, 2 + msg.length());
+ data.WriteBits(msg.length(), 13);
+ data.FlushBits();
+ data.WriteString(msg);
sWorld->SendGlobalMessage(&data);
}
else if (abcenter == 2)
{
sWorld->SendWorldText(LANG_AUTO_BROADCAST, msg.c_str());
- WorldPacket data(SMSG_NOTIFICATION, (msg.size()+1));
- data << msg;
+ WorldPacket data(SMSG_NOTIFICATION, 2 + msg.length());
+ data.WriteBits(msg.length(), 13);
+ data.FlushBits();
+ data.WriteString(msg);
sWorld->SendGlobalMessage(&data);
}
@@ -2861,6 +2907,35 @@ void World::InitGuildResetTime()
sWorld->setWorldState(WS_GUILD_DAILY_RESET_TIME, uint64(m_NextGuildReset));
}
+void World::InitCurrencyResetTime()
+{
+ time_t currencytime = uint64(sWorld->getWorldState(WS_CURRENCY_RESET_TIME));
+ if (!currencytime)
+ m_NextCurrencyReset = time_t(time(NULL)); // game time not yet init
+
+ // generate time by config
+ time_t curTime = time(NULL);
+ tm localTm = *localtime(&curTime);
+
+ localTm.tm_wday = getIntConfig(CONFIG_CURRENCY_RESET_DAY);
+ localTm.tm_hour = getIntConfig(CONFIG_CURRENCY_RESET_HOUR);
+ localTm.tm_min = 0;
+ localTm.tm_sec = 0;
+
+ // current week reset time
+ time_t nextWeekResetTime = mktime(&localTm);
+
+ // next reset time before current moment
+ if (curTime >= nextWeekResetTime)
+ nextWeekResetTime += getIntConfig(CONFIG_CURRENCY_RESET_INTERVAL) * DAY;
+
+ // normalize reset time
+ m_NextCurrencyReset = currencytime < curTime ? nextWeekResetTime - getIntConfig(CONFIG_CURRENCY_RESET_INTERVAL) * DAY : nextWeekResetTime;
+
+ if (!currencytime)
+ sWorld->setWorldState(WS_CURRENCY_RESET_TIME, uint64(m_NextCurrencyReset));
+}
+
void World::ResetDailyQuests()
{
TC_LOG_INFO("misc", "Daily quests reset for all characters.");
@@ -2876,6 +2951,18 @@ void World::ResetDailyQuests()
sPoolMgr->ChangeDailyQuests();
}
+void World::ResetCurrencyWeekCap()
+{
+ CharacterDatabase.Execute("UPDATE `character_currency` SET `week_count` = 0");
+
+ for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
+ if (itr->second->GetPlayer())
+ itr->second->GetPlayer()->ResetCurrencyWeekCap();
+
+ m_NextCurrencyReset = time_t(m_NextCurrencyReset + DAY * getIntConfig(CONFIG_CURRENCY_RESET_INTERVAL));
+ sWorld->setWorldState(WS_CURRENCY_RESET_TIME, uint64(m_NextCurrencyReset));
+}
+
void World::LoadDBAllowedSecurityLevel()
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL);
@@ -2987,11 +3074,14 @@ void World::ResetRandomBG()
void World::ResetGuildCap()
{
- TC_LOG_INFO("misc", "Guild Daily Cap reset.");
-
m_NextGuildReset = time_t(m_NextGuildReset + DAY);
sWorld->setWorldState(WS_GUILD_DAILY_RESET_TIME, uint64(m_NextGuildReset));
- sGuildMgr->ResetTimes();
+ uint32 week = getWorldState(WS_GUILD_WEEKLY_RESET_TIME);
+ week = week < 7 ? week + 1 : 1;
+
+ TC_LOG_INFO("misc", "Guild Daily Cap reset. Week: %u", week == 1);
+ sWorld->setWorldState(WS_GUILD_WEEKLY_RESET_TIME, week);
+ sGuildMgr->ResetTimes(week == 1);
}
void World::UpdateMaxSessionCounters()
@@ -3195,6 +3285,11 @@ CharacterNameData const* World::GetCharacterNameData(uint32 guid) const
return NULL;
}
+void World::UpdatePhaseDefinitions()
+{
+
+}
+
void World::ReloadRBAC()
{
// Passive reload, we mark the data as invalidated and next time a permission is checked it will be reloaded
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 7d3c7694463..00c897a6f00 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -44,11 +44,19 @@ class SystemMgr;
// ServerMessages.dbc
enum ServerMessageType
{
- SERVER_MSG_SHUTDOWN_TIME = 1,
- SERVER_MSG_RESTART_TIME = 2,
- SERVER_MSG_STRING = 3,
- SERVER_MSG_SHUTDOWN_CANCELLED = 4,
- SERVER_MSG_RESTART_CANCELLED = 5
+ SERVER_MSG_SHUTDOWN_TIME = 1,
+ SERVER_MSG_RESTART_TIME = 2,
+ SERVER_MSG_STRING = 3,
+ SERVER_MSG_SHUTDOWN_CANCELLED = 4,
+ SERVER_MSG_RESTART_CANCELLED = 5,
+ SERVER_MSG_BG_SHUTDOWN_TIME = 6,
+ SERVER_MSG_BG_RESTART_TIME = 7,
+ SERVER_MSG_INSTANCE_SHUTDOWN_TIME = 8,
+ SERVER_MSG_INSTANCE_RESTART_TIME = 9,
+ SERVER_MSG_CONTENT_READY = 10,
+ SERVER_MSG_TICKET_SERVICED_SOON = 11,
+ SERVER_MSG_WAIT_TIME_UNAVAILABLE = 12,
+ SERVER_MSG_TICKET_WAIT_TIME = 13,
};
enum ShutdownMask
@@ -77,6 +85,7 @@ enum WorldTimers
WUPDATE_MAILBOXQUEUE,
WUPDATE_DELETECHARS,
WUPDATE_PINGDB,
+ WUPDATE_GUILDSAVE,
WUPDATE_COUNT
};
@@ -106,7 +115,6 @@ enum WorldBoolConfigs
CONFIG_SKILL_MILLING,
CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY,
CONFIG_WEATHER,
- CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL,
CONFIG_QUEST_IGNORE_RAID,
CONFIG_DETECT_POS_COLLISION,
CONFIG_RESTRICTED_LFG_CHANNEL,
@@ -122,7 +130,6 @@ enum WorldBoolConfigs
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_BG_XP_FOR_KILL,
- CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_ARENA_SEASON_IN_PROGRESS,
@@ -149,6 +156,7 @@ enum WorldBoolConfigs
CONFIG_WARDEN_ENABLED,
CONFIG_ENABLE_MMAPS,
CONFIG_WINTERGRASP_ENABLE,
+ CONFIG_GUILD_LEVELING_ENABLED,
CONFIG_UI_QUESTLEVELS_IN_DIALOGS, // Should we add quest levels to the title in the NPC dialogs?
CONFIG_EVENT_ANNOUNCE,
CONFIG_STATS_LIMITS_ENABLE,
@@ -209,10 +217,16 @@ enum WorldIntConfigs
CONFIG_START_PLAYER_LEVEL,
CONFIG_START_HEROIC_PLAYER_LEVEL,
CONFIG_START_PLAYER_MONEY,
- CONFIG_MAX_HONOR_POINTS,
- CONFIG_START_HONOR_POINTS,
- CONFIG_MAX_ARENA_POINTS,
- CONFIG_START_ARENA_POINTS,
+ CONFIG_CURRENCY_START_JUSTICE_POINTS,
+ CONFIG_CURRENCY_MAX_JUSTICE_POINTS,
+ CONFIG_CURRENCY_START_HONOR_POINTS,
+ CONFIG_CURRENCY_MAX_HONOR_POINTS,
+ CONFIG_CURRENCY_START_CONQUEST_POINTS,
+ CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP,
+ CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD,
+ CONFIG_CURRENCY_RESET_HOUR,
+ CONFIG_CURRENCY_RESET_DAY,
+ CONFIG_CURRENCY_RESET_INTERVAL,
CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL,
CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE,
CONFIG_INSTANCE_RESET_TIME_HOUR,
@@ -237,9 +251,7 @@ enum WorldIntConfigs
CONFIG_SKILL_CHANCE_MINING_STEPS,
CONFIG_SKILL_CHANCE_SKINNING_STEPS,
CONFIG_SKILL_GAIN_CRAFTING,
- CONFIG_SKILL_GAIN_DEFENSE,
CONFIG_SKILL_GAIN_GATHERING,
- CONFIG_SKILL_GAIN_WEAPON,
CONFIG_MAX_OVERSPEED_PINGS,
CONFIG_EXPANSION,
CONFIG_CHATFLOOD_MESSAGE_COUNT,
@@ -273,7 +285,6 @@ enum WorldIntConfigs
CONFIG_ARENA_MAX_RATING_DIFFERENCE,
CONFIG_ARENA_RATING_DISCARD_TIMER,
CONFIG_ARENA_RATED_UPDATE_TIMER,
- CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
CONFIG_ARENA_SEASON_ID,
CONFIG_ARENA_START_RATING,
CONFIG_ARENA_START_PERSONAL_RATING,
@@ -291,6 +302,7 @@ enum WorldIntConfigs
CONFIG_LOGDB_CLEARINTERVAL,
CONFIG_LOGDB_CLEARTIME,
CONFIG_CLIENTCACHE_VERSION,
+ CONFIG_GUILD_NEWS_LOG_COUNT,
CONFIG_GUILD_EVENT_LOG_COUNT,
CONFIG_GUILD_BANK_EVENT_LOG_COUNT,
CONFIG_MIN_LEVEL_STAT_SAVE,
@@ -320,17 +332,21 @@ enum WorldIntConfigs
CONFIG_WINTERGRASP_BATTLETIME,
CONFIG_WINTERGRASP_NOBATTLETIME,
CONFIG_WINTERGRASP_RESTART_AFTER_CRASH,
+ CONFIG_GUILD_SAVE_INTERVAL,
+ CONFIG_GUILD_MAX_LEVEL,
+ CONFIG_GUILD_UNDELETABLE_LEVEL,
+ CONFIG_GUILD_DAILY_XP_CAP,
+ CONFIG_GUILD_WEEKLY_REP_CAP,
CONFIG_PACKET_SPOOF_POLICY,
CONFIG_PACKET_SPOOF_BANMODE,
CONFIG_PACKET_SPOOF_BANDURATION,
CONFIG_ACC_PASSCHANGESEC,
CONFIG_BG_REWARD_WINNER_HONOR_FIRST,
- CONFIG_BG_REWARD_WINNER_ARENA_FIRST,
CONFIG_BG_REWARD_WINNER_HONOR_LAST,
- CONFIG_BG_REWARD_WINNER_ARENA_LAST,
CONFIG_BG_REWARD_LOSER_HONOR_FIRST,
CONFIG_BG_REWARD_LOSER_HONOR_LAST,
- CONFIG_BIRTHDAY_TIME,
+ CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST,
+ CONFIG_BG_REWARD_WINNER_CONQUEST_LAST,
CONFIG_CREATURE_PICKPOCKET_REFILL,
INT_CONFIG_VALUE_COUNT
};
@@ -359,6 +375,7 @@ enum Rates
RATE_DROP_MONEY,
RATE_XP_KILL,
RATE_XP_QUEST,
+ RATE_XP_GUILD_MODIFIER,
RATE_XP_EXPLORE,
RATE_REPAIRCOST,
RATE_REPUTATION_GAIN,
@@ -477,6 +494,8 @@ enum WorldStates
WS_CLEANING_FLAGS = 20004, // Cleaning Flags
WS_GUILD_DAILY_RESET_TIME = 20006, // Next guild cap reset time
WS_MONTHLY_QUEST_RESET_TIME = 20007, // Next monthly reset time
+ // Cata specific custom worldstates
+ WS_GUILD_WEEKLY_RESET_TIME = 20050, // Next guild week reset time
};
/// Storage class for commands issued for delayed execution
@@ -613,7 +632,7 @@ class World
/// Get the maximum skill level a player can reach
uint16 GetConfigMaxSkillValue() const
{
- uint16 lvl = uint16(getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
+ uint8 lvl = uint8(getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
return lvl > 60 ? 300 + ((lvl - 60) * 75) / 10 : lvl * 5;
}
@@ -741,6 +760,7 @@ class World
void SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; }
void ResetEventSeasonalQuests(uint16 event_id);
+ void UpdatePhaseDefinitions();
void ReloadRBAC();
protected:
@@ -753,11 +773,13 @@ class World
void InitMonthlyQuestResetTime();
void InitRandomBGResetTime();
void InitGuildResetTime();
+ void InitCurrencyResetTime();
void ResetDailyQuests();
void ResetWeeklyQuests();
void ResetMonthlyQuests();
void ResetRandomBG();
void ResetGuildCap();
+ void ResetCurrencyWeekCap();
private:
World();
~World();
@@ -800,7 +822,6 @@ class World
AccountTypes m_allowedSecurityLevel;
LocaleConstant m_defaultDbcLocale; // from config for one from loaded DBC locales
uint32 m_availableDbcLocaleMask; // by loaded DBC
- void DetectDBCLang();
bool m_allowMovement;
std::string m_motd;
std::string m_dataPath;
@@ -817,12 +838,13 @@ class World
// CLI command holder to be thread safe
LockedQueue<CliCommandHolder*> cliCmdQueue;
- // next daily quests and random bg reset time
+ // scheduled reset times
time_t m_NextDailyQuestReset;
time_t m_NextWeeklyQuestReset;
time_t m_NextMonthlyQuestReset;
time_t m_NextRandomBGReset;
time_t m_NextGuildReset;
+ time_t m_NextCurrencyReset;
//Player Queue
Queue m_QueuedPlayer;