diff options
Diffstat (limited to 'src/server/game')
178 files changed, 25055 insertions, 19280 deletions
diff --git a/src/server/game/AI/CreatureAIRegistry.cpp b/src/server/game/AI/CreatureAIRegistry.cpp index e5c689da339..564eb7209f1 100755 --- a/src/server/game/AI/CreatureAIRegistry.cpp +++ b/src/server/game/AI/CreatureAIRegistry.cpp @@ -22,7 +22,6 @@ #include "GuardAI.h" #include "PetAI.h" #include "TotemAI.h" -#include "CreatureEventAI.h" #include "RandomMovementGenerator.h" #include "MovementGeneratorImpl.h" #include "CreatureAIRegistry.h" @@ -46,7 +45,6 @@ namespace AIRegistry (new CreatureAIFactory<CombatAI>("CombatAI"))->RegisterSelf(); (new CreatureAIFactory<ArcherAI>("ArcherAI"))->RegisterSelf(); (new CreatureAIFactory<TurretAI>("TurretAI"))->RegisterSelf(); - (new CreatureAIFactory<CreatureEventAI>("EventAI"))->RegisterSelf(); (new CreatureAIFactory<VehicleAI>("VehicleAI"))->RegisterSelf(); (new CreatureAIFactory<SmartAI>("SmartAI"))->RegisterSelf(); diff --git a/src/server/game/AI/EventAI/CreatureEventAI.cpp b/src/server/game/AI/EventAI/CreatureEventAI.cpp deleted file mode 100755 index aa14bc1b56e..00000000000 --- a/src/server/game/AI/EventAI/CreatureEventAI.cpp +++ /dev/null @@ -1,1386 +0,0 @@ -/* - * Copyright (C) 2008-2012 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 "Common.h" -#include "CreatureEventAI.h" -#include "CreatureEventAIMgr.h" -#include "ObjectMgr.h" -#include "Spell.h" -#include "World.h" -#include "Cell.h" -#include "CellImpl.h" -#include "GameEventMgr.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "InstanceScript.h" -#include "SpellMgr.h" -#include "CreatureAIImpl.h" -#include "ConditionMgr.h" - -bool CreatureEventAIHolder::UpdateRepeatTimer(Creature* creature, uint32 repeatMin, uint32 repeatMax) -{ - if (repeatMin == repeatMax) - Time = repeatMin; - else if (repeatMax > repeatMin) - Time = urand(repeatMin, repeatMax); - else - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", creature->GetEntry(), Event.event_id, Event.event_type); - Enabled = false; - return false; - } - - return true; -} - -int CreatureEventAI::Permissible(const Creature* creature) -{ - if (creature->GetAIName() == "EventAI") - return PERMIT_BASE_SPECIAL; - return PERMIT_BASE_NO; -} - -CreatureEventAI::CreatureEventAI(Creature* c) : CreatureAI(c) -{ - // Need make copy for filter unneeded steps and safe in case table reload - CreatureEventAI_Event_Map::const_iterator CreatureEvents = sEventAIMgr->GetCreatureEventAIMap().find(me->GetEntry()); - if (CreatureEvents != sEventAIMgr->GetCreatureEventAIMap().end()) - { - std::vector<CreatureEventAI_Event>::const_iterator i; - for (i = (*CreatureEvents).second.begin(); i != (*CreatureEvents).second.end(); ++i) - { - //Debug check - #ifndef TRINITY_DEBUG - if ((*i).event_flags & EFLAG_DEBUG_ONLY) - continue; - #endif - if (me->GetMap()->IsDungeon()) - { - if ((1 << (me->GetMap()->GetSpawnMode()+1)) & (*i).event_flags) - { - //event flagged for instance mode - m_CreatureEventAIList.push_back(CreatureEventAIHolder(*i)); - } - continue; - } - m_CreatureEventAIList.push_back(CreatureEventAIHolder(*i)); - } - //EventMap had events but they were not added because they must be for instance - if (m_CreatureEventAIList.empty()) - sLog->outError(LOG_FILTER_GENERAL, "CreatureEventAI: Creature %u has events but no events added to list because of instance flags.", me->GetEntry()); - } - else - sLog->outError(LOG_FILTER_GENERAL, "CreatureEventAI: EventMap for Creature %u is empty but creature is using CreatureEventAI.", me->GetEntry()); - - m_bEmptyList = m_CreatureEventAIList.empty(); - m_Phase = 0; - m_CombatMovementEnabled = true; - m_MeleeEnabled = true; - m_AttackDistance = 0.0f; - m_AttackAngle = 0.0f; - - m_InvincibilityHpLevel = 0; - - //Handle Spawned Events - if (!m_bEmptyList) - { - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - if (SpawnedEventConditionsCheck((*i).Event)) - ProcessEvent(*i); - } -} - -bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& holder, Unit* actionInvoker /*=NULL*/) -{ - if (!holder.Enabled || holder.Time) - return false; - - //Check the inverse phase mask (event doesn't trigger if current phase bit is set in mask) - if (holder.Event.event_inverse_phase_mask & (1 << m_Phase)) - return false; - - CreatureEventAI_Event const& event = holder.Event; - - //Check event conditions based on the event type, also reset events - switch (event.event_type) - { - case EVENT_T_TIMER: - if (!me->isInCombat()) - return false; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.timer.repeatMin, event.timer.repeatMax); - break; - case EVENT_T_TIMER_OOC: - if (me->isInCombat()) - return false; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.timer.repeatMin, event.timer.repeatMax); - break; - case EVENT_T_HP: - { - if (!me->isInCombat() || !me->GetMaxHealth()) - return false; - - uint32 perc = uint32(me->GetHealthPct()); - - if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) - return false; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax); - break; - } - case EVENT_T_MANA: - { - if (!me->isInCombat() || !me->GetMaxPower(POWER_MANA)) - return false; - - uint32 perc = (me->GetPower(POWER_MANA)*100) / me->GetMaxPower(POWER_MANA); - - if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) - return false; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax); - break; - } - case EVENT_T_AGGRO: - break; - case EVENT_T_KILL: - //Repeat Timers - holder.UpdateRepeatTimer(me, event.kill.repeatMin, event.kill.repeatMax); - break; - case EVENT_T_DEATH: - case EVENT_T_EVADE: - break; - case EVENT_T_SPELLHIT: - //Spell hit is special case, param1 and param2 handled within CreatureEventAI::SpellHit - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.spell_hit.repeatMin, event.spell_hit.repeatMax); - break; - case EVENT_T_RANGE: - //Repeat Timers - holder.UpdateRepeatTimer(me, event.range.repeatMin, event.range.repeatMax); - break; - case EVENT_T_OOC_LOS: - //Repeat Timers - holder.UpdateRepeatTimer(me, event.ooc_los.repeatMin, event.ooc_los.repeatMax); - break; - case EVENT_T_RESET: - case EVENT_T_SPAWNED: - break; - case EVENT_T_TARGET_HP: - { - if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->GetMaxHealth()) - return false; - - uint32 perc = uint32(me->getVictim()->GetHealthPct()); - - if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) - return false; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax); - break; - } - case EVENT_T_TARGET_CASTING: - if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->IsNonMeleeSpellCasted(false, false, true)) - return false; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.target_casting.repeatMin, event.target_casting.repeatMax); - break; - case EVENT_T_FRIENDLY_HP: - { - if (!me->isInCombat()) - return false; - - Unit* unit = DoSelectLowestHpFriendly((float)event.friendly_hp.radius, event.friendly_hp.hpDeficit); - if (!unit) - return false; - - actionInvoker = unit; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.friendly_hp.repeatMin, event.friendly_hp.repeatMax); - break; - } - case EVENT_T_FRIENDLY_IS_CC: - { - if (!me->isInCombat()) - return false; - - std::list<Creature*> pList; - DoFindFriendlyCC(pList, (float)event.friendly_is_cc.radius); - - //List is empty - if (pList.empty()) - return false; - - //We don't really care about the whole list, just return first available - actionInvoker = *(pList.begin()); - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.friendly_is_cc.repeatMin, event.friendly_is_cc.repeatMax); - break; - } - case EVENT_T_FRIENDLY_MISSING_BUFF: - { - std::list<Creature*> pList; - DoFindFriendlyMissingBuff(pList, (float)event.friendly_buff.radius, event.friendly_buff.spellId); - - //List is empty - if (pList.empty()) - return false; - - //We don't really care about the whole list, just return first available - actionInvoker = *(pList.begin()); - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.friendly_buff.repeatMin, event.friendly_buff.repeatMax); - break; - } - case EVENT_T_SUMMONED_UNIT: - { - //Prevent event from occuring on no unit or non creatures - if (!actionInvoker || actionInvoker->GetTypeId() != TYPEID_UNIT) - return false; - - //Creature id doesn't match up - if (actionInvoker->ToCreature()->GetEntry() != event.summon_unit.creatureId) - return false; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.summon_unit.repeatMin, event.summon_unit.repeatMax); - break; - } - case EVENT_T_TARGET_MANA: - { - if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->GetMaxPower(POWER_MANA)) - return false; - - uint32 perc = (me->getVictim()->GetPower(POWER_MANA)*100) / me->getVictim()->GetMaxPower(POWER_MANA); - - if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin) - return false; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax); - break; - } - case EVENT_T_REACHED_HOME: - case EVENT_T_RECEIVE_EMOTE: - break; - case EVENT_T_BUFFED: - { - //Note: checked only aura for effect 0, if need check aura for effect 1/2 then - // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx) - Aura const* aura = me->GetAura(event.buffed.spellId); - if (!aura || aura->GetStackAmount() < event.buffed.amount) - return false; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.buffed.repeatMin, event.buffed.repeatMax); - break; - } - case EVENT_T_TARGET_BUFFED: - { - //Prevent event from occuring on no unit - if (!actionInvoker) - return false; - - //Note: checked only aura for effect 0, if need check aura for effect 1/2 then - // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx) - Aura const* aura = actionInvoker->GetAura(event.buffed.spellId); - if (!aura || aura->GetStackAmount() < event.buffed.amount) - return false; - - //Repeat Timers - holder.UpdateRepeatTimer(me, event.buffed.repeatMin, event.buffed.repeatMax); - break; - } - default: - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", me->GetEntry(), holder.Event.event_id, holder.Event.event_type); - break; - } - - //Disable non-repeatable events - if (!(holder.Event.event_flags & EFLAG_REPEATABLE)) - holder.Enabled = false; - - //Store random here so that all random actions match up - uint32 rnd = rand(); - - //Return if chance for event is not met - if (holder.Event.event_chance <= rnd % 100) - return false; - - //Process actions - for (uint8 j = 0; j < MAX_ACTIONS; ++j) - ProcessAction(holder.Event.action[j], rnd, holder.Event.event_id, actionInvoker); - - return true; -} - -void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 eventId, Unit* actionInvoker) -{ - switch (action.type) - { - case ACTION_T_TEXT: - { - if (!action.text.TextId1) - return; - - int32 temp = action.text.TextId1; - - if (action.text.TextId2 && action.text.TextId3) - temp = RAND(action.text.TextId1, action.text.TextId2, action.text.TextId3); - else if (action.text.TextId2 && urand(0, 1)) - temp = action.text.TextId2; - - if (temp) - { - Unit* target = NULL; - - if (actionInvoker) - { - if (actionInvoker->GetTypeId() == TYPEID_PLAYER) - target = actionInvoker; - else if (Unit* owner = actionInvoker->GetOwner()) - { - if (owner->GetTypeId() == TYPEID_PLAYER) - target = owner; - } - } - else - { - target = me->getVictim(); - if (target && target->GetTypeId() != TYPEID_PLAYER) - if (Unit* owner = target->GetOwner()) - if (owner->GetTypeId() == TYPEID_PLAYER) - target = owner; - } - - DoScriptText(temp, me, target); - } - break; - } - case ACTION_T_SET_FACTION: - { - if (action.set_faction.factionId) - me->setFaction(action.set_faction.factionId); - else - { - if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(me->GetEntry())) - { - //if no id provided, assume reset and then use default - if (me->getFaction() != ci->faction_A) - me->setFaction(ci->faction_A); - } - } - break; - } - case ACTION_T_MORPH_TO_ENTRY_OR_MODEL: - { - if (action.morph.creatureId || action.morph.modelId) - { - //set model based on entry from creature_template - if (action.morph.creatureId) - { - if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(action.morph.creatureId)) - { - uint32 display_id = sObjectMgr->ChooseDisplayId(0, ci); - me->SetDisplayId(display_id); - } - } - //if no param1, then use value from param2 (modelId) - else - me->SetDisplayId(action.morph.modelId); - } - else - me->DeMorph(); - break; - } - case ACTION_T_SOUND: - me->PlayDirectSound(action.sound.soundId); - break; - case ACTION_T_EMOTE: - me->HandleEmoteCommand(action.emote.emoteId); - break; - case ACTION_T_RANDOM_SOUND: - { - int32 temp = GetRandActionParam(rnd, action.random_sound.soundId1, action.random_sound.soundId2, action.random_sound.soundId3); - if (temp >= 0) - me->PlayDirectSound(temp); - break; - } - case ACTION_T_RANDOM_EMOTE: - { - int32 temp = GetRandActionParam(rnd, action.random_emote.emoteId1, action.random_emote.emoteId2, action.random_emote.emoteId3); - if (temp >= 0) - me->HandleEmoteCommand(temp); - break; - } - case ACTION_T_CAST: - { - Unit* target = GetTargetByType(action.cast.target, actionInvoker); - Unit* caster = me; - - if (!target) - return; - - if (action.cast.castFlags & CAST_FORCE_TARGET_SELF) - caster = target; - - //Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered - bool canCast = !caster->IsNonMeleeSpellCasted(false) || (action.cast.castFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS)); - - // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them - if (action.cast.castFlags & CAST_AURA_NOT_PRESENT) - { - if (target->HasAura(action.cast.spellId)) - return; - } - - if (canCast) - { - const SpellInfo* tSpell = sSpellMgr->GetSpellInfo(action.cast.spellId); - - //Verify that spell exists - if (tSpell) - { - //Check if cannot cast spell - if (!(action.cast.castFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) && - !CanCast(target, tSpell, (action.cast.castFlags & CAST_TRIGGERED))) - { - //Melee current victim if flag not set - if (!(action.cast.castFlags & CAST_NO_MELEE_IF_OOM)) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) - { - m_AttackDistance = 0.0f; - m_AttackAngle = 0.0f; - - me->GetMotionMaster()->MoveChase(me->getVictim(), m_AttackDistance, m_AttackAngle); - } - } - } - else - { - //Interrupt any previous spell - if (caster->IsNonMeleeSpellCasted(false) && action.cast.castFlags & CAST_INTERRUPT_PREVIOUS) - caster->InterruptNonMeleeSpells(false); - - caster->CastSpell(target, action.cast.spellId, (action.cast.castFlags & CAST_TRIGGERED)); - } - } - else - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", eventId, me->GetEntry(), action.cast.spellId); - } - break; - } - case ACTION_T_SUMMON: - { - Unit* target = GetTargetByType(action.summon.target, actionInvoker); - - Creature* creature = NULL; - - if (action.summon.duration) - creature = me->SummonCreature(action.summon.creatureId, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, action.summon.duration); - else - creature = me->SummonCreature(action.summon.creatureId, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - if (!creature) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", action.summon.creatureId, eventId, me->GetEntry()); - else if (action.summon.target != TARGET_T_SELF && target) - creature->AI()->AttackStart(target); - break; - } - case ACTION_T_THREAT_SINGLE_PCT: - if (Unit* target = GetTargetByType(action.threat_single_pct.target, actionInvoker)) - me->getThreatManager().modifyThreatPercent(target, action.threat_single_pct.percent); - break; - case ACTION_T_THREAT_ALL_PCT: - { - std::list<HostileReference*>& threatList = me->getThreatManager().getThreatList(); - for (std::list<HostileReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i) - if (Unit* Temp = Unit::GetUnit(*me, (*i)->getUnitGuid())) - me->getThreatManager().modifyThreatPercent(Temp, action.threat_all_pct.percent); - break; - } - case ACTION_T_QUEST_EVENT: - if (Unit* target = GetTargetByType(action.quest_event.target, actionInvoker)) - if (target->GetTypeId() == TYPEID_PLAYER) - target->ToPlayer()->AreaExploredOrEventHappens(action.quest_event.questId); - break; - case ACTION_T_CAST_EVENT: - if (Unit* target = GetTargetByType(action.cast_event.target, actionInvoker)) - if (target->GetTypeId() == TYPEID_PLAYER) - target->ToPlayer()->CastedCreatureOrGO(action.cast_event.creatureId, me->GetGUID(), action.cast_event.spellId); - break; - case ACTION_T_SET_UNIT_FIELD: - { - Unit* target = GetTargetByType(action.set_unit_field.target, actionInvoker); - - // not allow modify important for integrity object fields - if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END) - return; - - if (target) - target->SetUInt32Value(action.set_unit_field.field, action.set_unit_field.value); - - break; - } - case ACTION_T_SET_UNIT_FLAG: - if (Unit* target = GetTargetByType(action.unit_flag.target, actionInvoker)) - target->SetFlag(UNIT_FIELD_FLAGS, action.unit_flag.value); - break; - case ACTION_T_REMOVE_UNIT_FLAG: - if (Unit* target = GetTargetByType(action.unit_flag.target, actionInvoker)) - target->RemoveFlag(UNIT_FIELD_FLAGS, action.unit_flag.value); - break; - case ACTION_T_AUTO_ATTACK: - m_MeleeEnabled = action.auto_attack.state != 0; - break; - case ACTION_T_COMBAT_MOVEMENT: - // ignore no affect case - if (m_CombatMovementEnabled == (action.combat_movement.state != 0)) - return; - - m_CombatMovementEnabled = action.combat_movement.state != 0; - - //Allow movement (create new targeted movement gen only if idle) - if (m_CombatMovementEnabled) - { - Unit* victim = me->getVictim(); - if (me->isInCombat() && victim) - { - if (action.combat_movement.melee) - { - me->AddUnitState(UNIT_STATE_MELEE_ATTACKING); - me->SendMeleeAttackStart(victim); - } - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE) - me->GetMotionMaster()->MoveChase(victim, m_AttackDistance, m_AttackAngle); // Targeted movement generator will start melee automatically, no need to send it explicitly - } - } - else - { - if (me->isInCombat()) - { - Unit* victim = me->getVictim(); - if (action.combat_movement.melee && victim) - { - me->ClearUnitState(UNIT_STATE_MELEE_ATTACKING); - me->SendMeleeAttackStop(victim); - } - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) - me->GetMotionMaster()->MoveIdle(); - } - } - break; - case ACTION_T_SET_PHASE: - m_Phase = action.set_phase.phase; - break; - case ACTION_T_INC_PHASE: - { - int32 new_phase = int32(m_Phase)+action.set_inc_phase.step; - if (new_phase < 0) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %d decrease m_Phase under 0. CreatureEntry = %d", eventId, me->GetEntry()); - m_Phase = 0; - } - else if (new_phase >= MAX_PHASE) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %d incremented m_Phase above %u. m_Phase mask cannot be used with phases past %u. CreatureEntry = %d", eventId, MAX_PHASE-1, MAX_PHASE-1, me->GetEntry()); - m_Phase = MAX_PHASE-1; - } - else - m_Phase = new_phase; - - break; - } - case ACTION_T_EVADE: - EnterEvadeMode(); - break; - case ACTION_T_FLEE_FOR_ASSIST: - me->DoFleeToGetAssistance(); - break; - case ACTION_T_QUEST_EVENT_ALL: - if (actionInvoker && actionInvoker->GetTypeId() == TYPEID_PLAYER) - { - if (Unit* Temp = Unit::GetUnit(*me, actionInvoker->GetGUID())) - if (Temp->GetTypeId() == TYPEID_PLAYER) - Temp->ToPlayer()->GroupEventHappens(action.quest_event_all.questId, me); - } - break; - case ACTION_T_CAST_EVENT_ALL: - { - std::list<HostileReference*>& threatList = me->getThreatManager().getThreatList(); - for (std::list<HostileReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i) - if (Unit* Temp = Unit::GetUnit(*me, (*i)->getUnitGuid())) - if (Temp->GetTypeId() == TYPEID_PLAYER) - Temp->ToPlayer()->CastedCreatureOrGO(action.cast_event_all.creatureId, me->GetGUID(), action.cast_event_all.spellId); - break; - } - case ACTION_T_REMOVEAURASFROMSPELL: - if (Unit* target = GetTargetByType(action.remove_aura.target, actionInvoker)) - target->RemoveAurasDueToSpell(action.remove_aura.spellId); - break; - case ACTION_T_RANGED_MOVEMENT: - m_AttackDistance = (float)action.ranged_movement.distance; - m_AttackAngle = action.ranged_movement.angle/180.0f*M_PI; - - if (m_CombatMovementEnabled) - { - me->GetMotionMaster()->MoveChase(me->getVictim(), m_AttackDistance, m_AttackAngle); - } - break; - case ACTION_T_RANDOM_PHASE: - m_Phase = GetRandActionParam(rnd, action.random_phase.phase1, action.random_phase.phase2, action.random_phase.phase3); - break; - case ACTION_T_RANDOM_PHASE_RANGE: - if (action.random_phase_range.phaseMin <= action.random_phase_range.phaseMax) - m_Phase = urand(action.random_phase_range.phaseMin, action.random_phase_range.phaseMax); - else - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 < Param1. Event = %d. CreatureEntry = %d", eventId, me->GetEntry()); - break; - case ACTION_T_SUMMON_ID: - { - Unit* target = GetTargetByType(action.summon_id.target, actionInvoker); - - CreatureEventAI_Summon_Map::const_iterator i = sEventAIMgr->GetCreatureEventAISummonMap().find(action.summon_id.spawnId); - if (i == sEventAIMgr->GetCreatureEventAISummonMap().end()) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", action.summon_id.creatureId, action.summon_id.spawnId, eventId, me->GetEntry()); - return; - } - - Creature* creature = NULL; - if ((*i).second.SpawnTimeSecs) - creature = me->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs); - else - creature = me->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - if (!creature) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", action.summon_id.creatureId, eventId, me->GetEntry()); - else if (action.summon_id.target != TARGET_T_SELF && target) - creature->AI()->AttackStart(target); - - break; - } - case ACTION_T_KILLED_MONSTER: - //first attempt player who tapped creature - if (Player* player = me->GetLootRecipient()) - player->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, player); // player as param is a hacky solution not to use GUID - else - { - //if not available, use actionInvoker - if (Unit* target = GetTargetByType(action.killed_monster.target, actionInvoker)) - if (Player* player2 = target->GetCharmerOrOwnerPlayerOrPlayerItself()) - player2->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, player2); - } - break; - case ACTION_T_SET_INST_DATA: - { - InstanceScript* instance = me->GetInstanceScript(); - if (!instance) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", eventId, me->GetEntry()); - return; - } - - instance->SetData(action.set_inst_data.field, action.set_inst_data.value); - break; - } - case ACTION_T_SET_INST_DATA64: - { - Unit* target = GetTargetByType(action.set_inst_data64.target, actionInvoker); - if (!target) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", eventId, me->GetEntry()); - return; - } - - InstanceScript* instance = me->GetInstanceScript(); - if (!instance) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", eventId, me->GetEntry()); - return; - } - - instance->SetData64(action.set_inst_data64.field, target->GetGUID()); - break; - } - case ACTION_T_UPDATE_TEMPLATE: - if (me->GetEntry() == action.update_template.creatureId) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", eventId, me->GetEntry()); - return; - } - - me->UpdateEntry(action.update_template.creatureId, action.update_template.team ? HORDE : ALLIANCE); - break; - case ACTION_T_DIE: - if (me->isDead()) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", eventId, me->GetEntry()); - return; - } - me->Kill(me); - break; - case ACTION_T_ZONE_COMBAT_PULSE: - { - me->SetInCombatWithZone(); - break; - } - case ACTION_T_CALL_FOR_HELP: - { - me->CallForHelp((float)action.call_for_help.radius); - break; - } - break; - - // TRINITY ONLY - case ACTION_T_MOVE_RANDOM_POINT: //dosen't work in combat - { - float x, y, z; - me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, (float)action.raw.param1); - me->GetMotionMaster()->MovePoint(0, x, y, z); - break; - } - case ACTION_T_SET_STAND_STATE: - me->SetStandState(UnitStandStateType(action.raw.param1)); - break; - case ACTION_T_SET_PHASE_MASK: - me->SetPhaseMask(action.raw.param1, true); - break; - case ACTION_T_SET_VISIBILITY: - me->SetVisible(bool(action.raw.param1)); - break; - case ACTION_T_SET_ACTIVE: - me->setActive(action.raw.param1 ? true : false); - break; - case ACTION_T_SET_AGGRESSIVE: - me->SetReactState(ReactStates(action.raw.param1)); - break; - case ACTION_T_ATTACK_START_PULSE: - AttackStart(me->SelectNearestTarget((float)action.raw.param1)); - break; - case ACTION_T_SUMMON_GO: - { - GameObject* object = NULL; - - float x, y, z; - me->GetPosition(x, y, z); - object = me->SummonGameObject(action.raw.param1, x, y, z, 0, 0, 0, 0, 0, action.raw.param2); - if (!object) - { - sLog->outError(LOG_FILTER_TSCR, "EventAI failed to spawn object %u. Spawn event %d is on creature %d", action.raw.param1, eventId, me->GetEntry()); - } - break; - } - - case ACTION_T_SET_SHEATH: - { - me->SetSheath(SheathState(action.set_sheath.sheath)); - break; - } - case ACTION_T_FORCE_DESPAWN: - { - me->DespawnOrUnsummon(action.forced_despawn.msDelay); - break; - } - case ACTION_T_SET_INVINCIBILITY_HP_LEVEL: - { - if (action.invincibility_hp_level.is_percent) - m_InvincibilityHpLevel = me->CountPctFromMaxHealth(action.invincibility_hp_level.hp_level); - else - m_InvincibilityHpLevel = action.invincibility_hp_level.hp_level; - break; - } - case ACTION_T_MOUNT_TO_ENTRY_OR_MODEL: - { - if (action.mount.creatureId || action.mount.modelId) - { - // set model based on entry from creature_template - if (action.mount.creatureId) - { - if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(action.mount.creatureId)) - { - uint32 display_id = sObjectMgr->ChooseDisplayId(0, cInfo); - me->Mount(display_id); - } - } - //if no param1, then use value from param2 (modelId) - else - me->Mount(action.mount.modelId); - } - else - me->Dismount(); - - break; - } - default: - break; - } -} - -void CreatureEventAI::JustRespawned() -{ - Reset(); - - if (m_bEmptyList) - return; - - //Handle Spawned Events - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - if (SpawnedEventConditionsCheck((*i).Event)) - ProcessEvent(*i); -} - -void CreatureEventAI::Reset() -{ - m_EventUpdateTime = EVENT_UPDATE_TIME; - m_EventDiff = 0; - - if (m_bEmptyList) - return; - - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - { - if ((*i).Event.event_type == EVENT_T_RESET) - ProcessEvent(*i); - } - - //Reset all events to enabled - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - { - CreatureEventAI_Event const& event = (*i).Event; - switch (event.event_type) - { - //Reset all out of combat timers - case EVENT_T_TIMER_OOC: - { - if ((*i).UpdateRepeatTimer(me, event.timer.initialMin, event.timer.initialMax)) - (*i).Enabled = true; - break; - } - //default: - //TODO: enable below code line / verify this is correct to enable events previously disabled (ex. aggro yell), instead of enable this in void EnterCombat() - //(*i).Enabled = true; - //(*i).Time = 0; - //break; - } - } -} - -void CreatureEventAI::JustReachedHome() -{ - if (!m_bEmptyList) - { - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - { - if ((*i).Event.event_type == EVENT_T_REACHED_HOME) - ProcessEvent(*i); - } - } - - Reset(); -} - -void CreatureEventAI::EnterEvadeMode() -{ - CreatureAI::EnterEvadeMode(); - - if (m_bEmptyList) - return; - - //Handle Evade events - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - { - if ((*i).Event.event_type == EVENT_T_EVADE) - ProcessEvent(*i); - } -} - -void CreatureEventAI::JustDied(Unit* killer) -{ - Reset(); - - if (m_bEmptyList) - return; - - //Handle Evade events - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - { - if ((*i).Event.event_type == EVENT_T_DEATH) - ProcessEvent(*i, killer); - } - - // reset phase after any death state events - m_Phase = 0; -} - -void CreatureEventAI::KilledUnit(Unit* victim) -{ - if (m_bEmptyList || victim->GetTypeId() != TYPEID_PLAYER) - return; - - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - { - if ((*i).Event.event_type == EVENT_T_KILL) - ProcessEvent(*i, victim); - } -} - -void CreatureEventAI::JustSummoned(Creature* unit) -{ - if (m_bEmptyList || !unit) - return; - - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - { - if ((*i).Event.event_type == EVENT_T_SUMMONED_UNIT) - ProcessEvent(*i, unit); - } -} - -void CreatureEventAI::EnterCombat(Unit* enemy) -{ - //Check for on combat start events - if (!m_bEmptyList) - { - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - { - CreatureEventAI_Event const& event = (*i).Event; - switch (event.event_type) - { - case EVENT_T_AGGRO: - (*i).Enabled = true; - ProcessEvent(*i, enemy); - break; - //Reset all in combat timers - case EVENT_T_TIMER: - if ((*i).UpdateRepeatTimer(me, event.timer.initialMin, event.timer.initialMax)) - (*i).Enabled = true; - break; - //All normal events need to be re-enabled and their time set to 0 - default: - (*i).Enabled = true; - (*i).Time = 0; - break; - } - } - } - - m_EventUpdateTime = EVENT_UPDATE_TIME; - m_EventDiff = 0; -} - -void CreatureEventAI::AttackStart(Unit* who) -{ - if (!who) - return; - - if (me->Attack(who, m_MeleeEnabled)) - { - if (m_CombatMovementEnabled) - { - me->GetMotionMaster()->MoveChase(who, m_AttackDistance, m_AttackAngle); - } - else - { - me->GetMotionMaster()->MoveIdle(); - } - } -} - -void CreatureEventAI::MoveInLineOfSight(Unit* who) -{ - if (me->getVictim()) - return; - - //Check for OOC LOS Event - if (!m_bEmptyList) - { - for (CreatureEventAIList::iterator itr = m_CreatureEventAIList.begin(); itr != m_CreatureEventAIList.end(); ++itr) - { - if ((*itr).Event.event_type == EVENT_T_OOC_LOS) - { - //can trigger if closer than fMaxAllowedRange - float fMaxAllowedRange = (float)((*itr).Event.ooc_los.maxRange); - - //if range is ok and we are actually in LOS - if (me->IsWithinDistInMap(who, fMaxAllowedRange) && me->IsWithinLOSInMap(who)) - { - //if friendly event&&who is not hostile OR hostile event&&who is hostile - if (((*itr).Event.ooc_los.noHostile && !me->IsHostileTo(who)) || - ((!(*itr).Event.ooc_los.noHostile) && me->IsHostileTo(who))) - ProcessEvent(*itr, who); - } - } - } - } - - CreatureAI::MoveInLineOfSight(who); -} - -void CreatureEventAI::SpellHit(Unit* unit, const SpellInfo* spell) -{ - if (m_bEmptyList) - return; - - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - if ((*i).Event.event_type == EVENT_T_SPELLHIT) - //If spell id matches (or no spell id) & if spell school matches (or no spell school) - if (!(*i).Event.spell_hit.spellId || spell->Id == (*i).Event.spell_hit.spellId) - if (spell->SchoolMask & (*i).Event.spell_hit.schoolMask) - ProcessEvent(*i, unit); -} - -void CreatureEventAI::UpdateAI(const uint32 diff) -{ - //Check if we are in combat (also updates calls threat update code) - bool Combat = UpdateVictim(); - - if (!m_bEmptyList) - { - //Events are only updated once every EVENT_UPDATE_TIME ms to prevent lag with large amount of events - if (m_EventUpdateTime <= diff) - { - m_EventDiff += diff; - - //Check for time based events - for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) - { - //Decrement Timers - if ((*i).Time) - { - if (m_EventDiff <= (*i).Time) - { - //Do not decrement timers if event cannot trigger in this phase - if (!((*i).Event.event_inverse_phase_mask & (1 << m_Phase))) - (*i).Time -= m_EventDiff; - - //Skip processing of events that have time remaining - continue; - } - else (*i).Time = 0; - } - - //Events that are updated every EVENT_UPDATE_TIME - switch ((*i).Event.event_type) - { - case EVENT_T_TIMER_OOC: - ProcessEvent(*i); - break; - case EVENT_T_TIMER: - case EVENT_T_MANA: - case EVENT_T_HP: - case EVENT_T_TARGET_HP: - case EVENT_T_TARGET_CASTING: - case EVENT_T_FRIENDLY_HP: - if (me->getVictim()) - ProcessEvent(*i); - break; - case EVENT_T_RANGE: - if (me->getVictim()) - if (me->IsInMap(me->getVictim()) && me->InSamePhase(me->getVictim())) - if (me->IsInRange(me->getVictim(), (float)(*i).Event.range.minDist, (float)(*i).Event.range.maxDist)) - ProcessEvent(*i); - break; - default: - break; - } - } - - m_EventDiff = 0; - m_EventUpdateTime = EVENT_UPDATE_TIME; - } - else - { - m_EventDiff += diff; - m_EventUpdateTime -= diff; - } - } - - //Melee Auto-Attack - if (Combat && m_MeleeEnabled) - DoMeleeAttackIfReady(); -} - -inline uint32 CreatureEventAI::GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3) -{ - switch (rnd % 3) - { - case 0: return param1; - case 1: return param2; - case 2: return param3; - } - return 0; -} - -inline int32 CreatureEventAI::GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3) -{ - switch (rnd % 3) - { - case 0: return param1; - case 1: return param2; - case 2: return param3; - } - return 0; -} - -inline Unit* CreatureEventAI::GetTargetByType(uint32 target, Unit* actionInvoker) -{ - switch (target) - { - case TARGET_T_SELF: - return me; - case TARGET_T_HOSTILE: - return me->getVictim(); - case TARGET_T_HOSTILE_SECOND_AGGRO: - return SelectTarget(SELECT_TARGET_TOPAGGRO, 1); - case TARGET_T_HOSTILE_LAST_AGGRO: - return SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0); - case TARGET_T_HOSTILE_RANDOM: - return SelectTarget(SELECT_TARGET_RANDOM, 0); - case TARGET_T_HOSTILE_RANDOM_NOT_TOP: - return SelectTarget(SELECT_TARGET_RANDOM, 1); - case TARGET_T_ACTION_INVOKER: - return actionInvoker; - default: - return NULL; - }; -} - -Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 minHPDiff) -{ - CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY())); - Cell cell(p); - cell.SetNoCreate(); - - Unit* unit = NULL; - - Trinity::MostHPMissingInRange u_check(me, range, minHPDiff); - Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange> searcher(me, unit, u_check); - - /* - typedef TYPELIST_4(GameObject, Creature*except pets*, DynamicObject, Corpse*Bones*) AllGridObjectTypes; - This means that if we only search grid then we cannot possibly return pets or players so this is safe - */ - TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher); - - cell.Visit(p, grid_unit_searcher, *me->GetMap(), *me, range); - return unit; -} - -void CreatureEventAI::DoFindFriendlyCC(std::list<Creature*>& _list, float range) -{ - CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY())); - Cell cell(p); - cell.SetNoCreate(); - - Trinity::FriendlyCCedInRange u_check(me, range); - Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange> searcher(me, _list, u_check); - - TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange>, GridTypeMapContainer > grid_creature_searcher(searcher); - - cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range); -} - -void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid) -{ - CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY())); - Cell cell(p); - cell.SetNoCreate(); - - Trinity::FriendlyMissingBuffInRange u_check(me, range, spellid); - Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange> searcher(me, _list, u_check); - - TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange>, GridTypeMapContainer > grid_creature_searcher(searcher); - - cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range); -} - -// ********************************* -// *** Functions used globally *** - -void CreatureEventAI::DoScriptText(int32 textEntry, WorldObject* source, Unit* target) -{ - if (!source) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText entry %i, invalid Source pointer.", textEntry); - return; - } - - if (textEntry >= 0) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText with source entry %u (TypeId=%u, guid=%u) attempts to process text entry %i, but text entry must be negative.", source->GetEntry(), source->GetTypeId(), source->GetGUIDLow(), textEntry); - return; - } - - CreatureEventAI_TextMap::const_iterator i = sEventAIMgr->GetCreatureEventAITextMap().find(textEntry); - - if (i == sEventAIMgr->GetCreatureEventAITextMap().end()) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText with source entry %u (TypeId=%u, guid=%u) could not find text entry %i.", source->GetEntry(), source->GetTypeId(), source->GetGUIDLow(), textEntry); - return; - } - - sLog->outDebug(LOG_FILTER_DATABASE_AI, "CreatureEventAI: DoScriptText: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u", textEntry, (*i).second.SoundId, (*i).second.Type, (*i).second.Language, (*i).second.Emote); - - if ((*i).second.SoundId) - { - if (sSoundEntriesStore.LookupEntry((*i).second.SoundId)) - source->PlayDirectSound((*i).second.SoundId); - else - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText entry %i tried to process invalid sound id %u.", textEntry, (*i).second.SoundId); - } - - if ((*i).second.Emote) - { - if (source->GetTypeId() == TYPEID_UNIT || source->GetTypeId() == TYPEID_PLAYER) - { - ((Unit*)source)->HandleEmoteCommand((*i).second.Emote); - } - else - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText entry %i tried to process emote for invalid TypeId (%u).", textEntry, source->GetTypeId()); - } - - switch ((*i).second.Type) - { - case CHAT_TYPE_SAY: - source->MonsterSay(textEntry, (*i).second.Language, target ? target->GetGUID() : 0); - break; - case CHAT_TYPE_YELL: - source->MonsterYell(textEntry, (*i).second.Language, target ? target->GetGUID() : 0); - break; - case CHAT_TYPE_TEXT_EMOTE: - source->MonsterTextEmote(textEntry, target ? target->GetGUID() : 0); - break; - case CHAT_TYPE_BOSS_EMOTE: - source->MonsterTextEmote(textEntry, target ? target->GetGUID() : 0, true); - break; - case CHAT_TYPE_WHISPER: - { - if (target && target->GetTypeId() == TYPEID_PLAYER) - source->MonsterWhisper(textEntry, target->GetGUID()); - else sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", textEntry); - }break; - case CHAT_TYPE_BOSS_WHISPER: - { - if (target && target->GetTypeId() == TYPEID_PLAYER) - source->MonsterWhisper(textEntry, target->GetGUID(), true); - else sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", textEntry); - }break; - case CHAT_TYPE_ZONE_YELL: - source->MonsterYellToZone(textEntry, (*i).second.Language, target ? target->GetGUID() : 0); - break; - } -} - -bool CreatureEventAI::CanCast(Unit* target, SpellInfo const* spell, bool triggered) -{ - //No target so we can't cast - if (!target || !spell) - return false; - - //Silenced so we can't cast - if (!triggered && me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) - return false; - - //Check for power - if (!triggered && me->GetPower((Powers)spell->PowerType) < spell->CalcPowerCost(me, spell->GetSchoolMask())) - return false; - - //Unit is out of range of this spell - if (!me->IsInRange(target, spell->GetMinRange(false), spell->GetMaxRange(false))) - return false; - - return true; -} - -void CreatureEventAI::ReceiveEmote(Player* player, uint32 textEmote) -{ - if (m_bEmptyList) - return; - - for (CreatureEventAIList::iterator itr = m_CreatureEventAIList.begin(); itr != m_CreatureEventAIList.end(); ++itr) - { - if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE) - { - if ((*itr).Event.receive_emote.emoteId != textEmote) - return; - - Condition cond; - cond.ConditionType = ConditionTypes((*itr).Event.receive_emote.condition); - cond.ConditionValue1 = (*itr).Event.receive_emote.conditionValue1; - cond.ConditionValue2 = (*itr).Event.receive_emote.conditionValue2; - - ConditionSourceInfo srcInfo = ConditionSourceInfo(player); - if (cond.Meets(srcInfo)) - { - sLog->outDebug(LOG_FILTER_DATABASE_AI, "CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing"); - ProcessEvent(*itr, player); - } - } - } -} - -void CreatureEventAI::DamageTaken(Unit* /*done_by*/, uint32& damage) -{ - if (m_InvincibilityHpLevel > 0 && me->GetHealth() < m_InvincibilityHpLevel+damage) - { - if (me->GetHealth() <= m_InvincibilityHpLevel) - damage = 0; - else - damage = me->GetHealth() - m_InvincibilityHpLevel; - } -} - -bool CreatureEventAI::SpawnedEventConditionsCheck(CreatureEventAI_Event const& event) -{ - if (event.event_type != EVENT_T_SPAWNED) - return false; - - switch (event.spawned.condition) - { - case SPAWNED_EVENT_ALWAY: - // always - return true; - case SPAWNED_EVENT_MAP: - // map ID check - return me->GetMapId() == event.spawned.conditionValue1; - case SPAWNED_EVENT_ZONE: - { - // zone ID check - uint32 zone, area; - me->GetZoneAndAreaId(zone, area); - return zone == event.spawned.conditionValue1 || area == event.spawned.conditionValue1; - } - default: - break; - } - - return false; -} diff --git a/src/server/game/AI/EventAI/CreatureEventAI.h b/src/server/game/AI/EventAI/CreatureEventAI.h deleted file mode 100755 index b9e1ae32be4..00000000000 --- a/src/server/game/AI/EventAI/CreatureEventAI.h +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright (C) 2008-2012 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 TRINITY_CREATURE_EAI_H -#define TRINITY_CREATURE_EAI_H - -#include "Common.h" -#include "Creature.h" -#include "CreatureAI.h" -#include "Unit.h" - -class Player; -class WorldObject; - -#define EVENT_UPDATE_TIME 500 -#define MAX_ACTIONS 3 -#define MAX_PHASE 32 - -enum EventAI_Type -{ - EVENT_T_TIMER = 0, // InitialMin, InitialMax, RepeatMin, RepeatMax - EVENT_T_TIMER_OOC = 1, // InitialMin, InitialMax, RepeatMin, RepeatMax - EVENT_T_HP = 2, // HPMax%, HPMin%, RepeatMin, RepeatMax - EVENT_T_MANA = 3, // ManaMax%, ManaMin% RepeatMin, RepeatMax - EVENT_T_AGGRO = 4, // NONE - EVENT_T_KILL = 5, // RepeatMin, RepeatMax - EVENT_T_DEATH = 6, // NONE - EVENT_T_EVADE = 7, // NONE - EVENT_T_SPELLHIT = 8, // SpellID, School, RepeatMin, RepeatMax - EVENT_T_RANGE = 9, // MinDist, MaxDist, RepeatMin, RepeatMax - EVENT_T_OOC_LOS = 10, // NoHostile, MaxRnage, RepeatMin, RepeatMax - EVENT_T_SPAWNED = 11, // Condition, CondValue1 - EVENT_T_TARGET_HP = 12, // HPMax%, HPMin%, RepeatMin, RepeatMax - EVENT_T_TARGET_CASTING = 13, // RepeatMin, RepeatMax - EVENT_T_FRIENDLY_HP = 14, // HPDeficit, Radius, RepeatMin, RepeatMax - EVENT_T_FRIENDLY_IS_CC = 15, // DispelType, Radius, RepeatMin, RepeatMax - EVENT_T_FRIENDLY_MISSING_BUFF = 16, // SpellId, Radius, RepeatMin, RepeatMax - EVENT_T_SUMMONED_UNIT = 17, // CreatureId, RepeatMin, RepeatMax - EVENT_T_TARGET_MANA = 18, // ManaMax%, ManaMin%, RepeatMin, RepeatMax - EVENT_T_QUEST_ACCEPT = 19, // QuestID - EVENT_T_QUEST_COMPLETE = 20, // - EVENT_T_REACHED_HOME = 21, // NONE - EVENT_T_RECEIVE_EMOTE = 22, // EmoteId, Condition, CondValue1, CondValue2 - EVENT_T_BUFFED = 23, // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 Repeat Min/Max - EVENT_T_TARGET_BUFFED = 24, // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 Repeat Min/Max - EVENT_T_RESET = 35, // Is it called after combat, when the creature respawn and spawn. -- TRINITY ONLY - - EVENT_T_END, -}; - -enum EventAI_ActionType -{ - ACTION_T_NONE = 0, // No action - ACTION_T_TEXT = 1, // TextId1, optionally -TextId2, optionally -TextId3(if -TextId2 exist). If more than just -TextId1 is defined, randomize. Negative values. - ACTION_T_SET_FACTION = 2, // FactionId (or 0 for default) - ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph) - ACTION_T_SOUND = 4, // SoundId - ACTION_T_EMOTE = 5, // EmoteId - ACTION_T_RANDOM_SAY = 6, // UNUSED - ACTION_T_RANDOM_YELL = 7, // UNUSED - ACTION_T_RANDOM_TEXTEMOTE = 8, // UNUSED - ACTION_T_RANDOM_SOUND = 9, // SoundId1, SoundId2, SoundId3 (-1 in any field means no output if randomed that field) - ACTION_T_RANDOM_EMOTE = 10, // EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field) - ACTION_T_CAST = 11, // SpellId, Target, CastFlags - ACTION_T_SUMMON = 12, // CreatureID, Target, Duration in ms - ACTION_T_THREAT_SINGLE_PCT = 13, // Threat%, Target - ACTION_T_THREAT_ALL_PCT = 14, // Threat% - ACTION_T_QUEST_EVENT = 15, // QuestID, Target - ACTION_T_CAST_EVENT = 16, // QuestID, SpellId, Target - must be removed as hack? - ACTION_T_SET_UNIT_FIELD = 17, // Field_Number, Value, Target - ACTION_T_SET_UNIT_FLAG = 18, // Flags (may be more than one field OR'd together), Target - ACTION_T_REMOVE_UNIT_FLAG = 19, // Flags (may be more than one field OR'd together), Target - ACTION_T_AUTO_ATTACK = 20, // AllowAttackState (0 = stop attack, anything else means continue attacking) - ACTION_T_COMBAT_MOVEMENT = 21, // AllowCombatMovement (0 = stop combat based movement, anything else continue attacking) - ACTION_T_SET_PHASE = 22, // Phase - ACTION_T_INC_PHASE = 23, // Value (may be negative to decrement phase, should not be 0) - ACTION_T_EVADE = 24, // No Params - ACTION_T_FLEE_FOR_ASSIST = 25, // No Params - ACTION_T_QUEST_EVENT_ALL = 26, // QuestID - ACTION_T_CAST_EVENT_ALL = 27, // CreatureId, SpellId - ACTION_T_REMOVEAURASFROMSPELL = 28, // Target, Spellid - ACTION_T_RANGED_MOVEMENT = 29, // Distance, Angle - ACTION_T_RANDOM_PHASE = 30, // PhaseId1, PhaseId2, PhaseId3 - ACTION_T_RANDOM_PHASE_RANGE = 31, // PhaseMin, PhaseMax - ACTION_T_SUMMON_ID = 32, // CreatureId, Target, SpawnId - ACTION_T_KILLED_MONSTER = 33, // CreatureId, Target - ACTION_T_SET_INST_DATA = 34, // Field, Data - ACTION_T_SET_INST_DATA64 = 35, // Field, Target - ACTION_T_UPDATE_TEMPLATE = 36, // Entry, Team - ACTION_T_DIE = 37, // No Params - ACTION_T_ZONE_COMBAT_PULSE = 38, // No Params - ACTION_T_CALL_FOR_HELP = 39, // Radius - ACTION_T_SET_SHEATH = 40, // Sheath (0-passive, 1-melee, 2-ranged) - ACTION_T_FORCE_DESPAWN = 41, // No Params - ACTION_T_SET_INVINCIBILITY_HP_LEVEL = 42, // MinHpValue, format(0-flat, 1-percent from max health) - ACTION_T_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to dismount) - - ACTION_T_SET_PHASE_MASK = 97, - ACTION_T_SET_STAND_STATE = 98, - ACTION_T_MOVE_RANDOM_POINT = 99, - ACTION_T_SET_VISIBILITY = 100, - ACTION_T_SET_ACTIVE = 101, //Apply - ACTION_T_SET_AGGRESSIVE = 102, //Apply - ACTION_T_ATTACK_START_PULSE = 103, //Distance - ACTION_T_SUMMON_GO = 104, //GameObjectID, DespawnTime in ms - - ACTION_T_END = 105, -}; - -enum Target -{ - //Self (me) - TARGET_T_SELF = 0, //Self cast - - //Hostile targets (if pet then returns pet owner) - TARGET_T_HOSTILE, //Our current target (ie: highest aggro) - TARGET_T_HOSTILE_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks) - TARGET_T_HOSTILE_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for) - TARGET_T_HOSTILE_RANDOM, //Just any random target on our threat list - TARGET_T_HOSTILE_RANDOM_NOT_TOP, //Any random target except top threat - - //Invoker targets (if pet then returns pet owner) - TARGET_T_ACTION_INVOKER, //Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF) - - //Hostile targets (including pets) - TARGET_T_HOSTILE_WPET, //Current target (can be a pet) - TARGET_T_HOSTILE_WPET_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks) - TARGET_T_HOSTILE_WPET_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for) - TARGET_T_HOSTILE_WPET_RANDOM, //Just any random target on our threat list - TARGET_T_HOSTILE_WPET_RANDOM_NOT_TOP, //Any random target except top threat - - TARGET_T_ACTION_INVOKER_WPET, - - TARGET_T_END -}; - -enum CastFlags -{ - CAST_INTERRUPT_PREVIOUS = 0x01, //Interrupt any spell casting - CAST_TRIGGERED = 0x02, //Triggered (this makes spell cost zero mana and have no cast time) - CAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range - CAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range - CAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself - CAST_AURA_NOT_PRESENT = 0x20, //Only casts the spell if the target does not have an aura from the spell -}; - -enum EventFlags -{ - EFLAG_REPEATABLE = 0x01, //Event repeats - EFLAG_DIFFICULTY_0 = 0x02, //Event only occurs in instance difficulty 0 - EFLAG_DIFFICULTY_1 = 0x04, //Event only occurs in instance difficulty 1 - EFLAG_DIFFICULTY_2 = 0x08, //Event only occurs in instance difficulty 2 - EFLAG_DIFFICULTY_3 = 0x10, //Event only occurs in instance difficulty 3 - EFLAG_RESERVED_5 = 0x20, - EFLAG_RESERVED_6 = 0x40, - EFLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build - - EFLAG_DIFFICULTY_ALL = (EFLAG_DIFFICULTY_0|EFLAG_DIFFICULTY_1|EFLAG_DIFFICULTY_2|EFLAG_DIFFICULTY_3) -}; - -enum SpawnedEventMode -{ - SPAWNED_EVENT_ALWAY = 0, - SPAWNED_EVENT_MAP = 1, - SPAWNED_EVENT_ZONE = 2 -}; - -// String text additional data, used in (CreatureEventAI) -struct StringTextData -{ - uint32 SoundId; - uint8 Type; - uint32 Language; - uint32 Emote; -}; -// Text Maps -typedef UNORDERED_MAP<int32, StringTextData> CreatureEventAI_TextMap; - -struct CreatureEventAI_Action -{ - EventAI_ActionType type: 16; - union - { - // ACTION_T_TEXT = 1 - struct - { - int32 TextId1; - int32 TextId2; - int32 TextId3; - } text; - // ACTION_T_SET_FACTION = 2 - struct - { - uint32 factionId; // faction or 0 for default) - } set_faction; - // ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3 - struct - { - uint32 creatureId; // set one from fields (or 0 for both to demorph) - uint32 modelId; - } morph; - // ACTION_T_SOUND = 4 - struct - { - uint32 soundId; - } sound; - // ACTION_T_EMOTE = 5 - struct - { - uint32 emoteId; - } emote; - // ACTION_T_RANDOM_SOUND = 9 - struct - { - int32 soundId1; // (-1 in any field means no output if randomed that field) - int32 soundId2; - int32 soundId3; - } random_sound; - // ACTION_T_RANDOM_EMOTE = 10 - struct - { - int32 emoteId1; // (-1 in any field means no output if randomed that field) - int32 emoteId2; - int32 emoteId3; - } random_emote; - // ACTION_T_CAST = 11 - struct - { - uint32 spellId; - uint32 target; - uint32 castFlags; - } cast; - // ACTION_T_SUMMON = 12 - struct - { - uint32 creatureId; - uint32 target; - uint32 duration; - } summon; - // ACTION_T_THREAT_SINGLE_PCT = 13 - struct - { - int32 percent; - uint32 target; - } threat_single_pct; - // ACTION_T_THREAT_ALL_PCT = 14 - struct - { - int32 percent; - } threat_all_pct; - // ACTION_T_QUEST_EVENT = 15 - struct - { - uint32 questId; - uint32 target; - } quest_event; - // ACTION_T_CAST_EVENT = 16 - struct - { - uint32 creatureId; - uint32 spellId; - uint32 target; - } cast_event; - // ACTION_T_SET_UNIT_FIELD = 17 - struct - { - uint32 field; - uint32 value; - uint32 target; - } set_unit_field; - // ACTION_T_SET_UNIT_FLAG = 18, // value provided mask bits that will be set - // ACTION_T_REMOVE_UNIT_FLAG = 19, // value provided mask bits that will be clear - struct - { - uint32 value; - uint32 target; - } unit_flag; - // ACTION_T_AUTO_ATTACK = 20 - struct - { - uint32 state; // 0 = stop attack, anything else means continue attacking - } auto_attack; - // ACTION_T_COMBAT_MOVEMENT = 21 - struct - { - uint32 state; // 0 = stop combat based movement, anything else continue attacking - uint32 melee; // if set: at stop send melee combat stop if in combat, use for terminate melee fighting state for switch to ranged - } combat_movement; - // ACTION_T_SET_PHASE = 22 - struct - { - uint32 phase; - } set_phase; - // ACTION_T_INC_PHASE = 23 - struct - { - int32 step; - } set_inc_phase; - // ACTION_T_QUEST_EVENT_ALL = 26 - struct - { - uint32 questId; - } quest_event_all; - // ACTION_T_CAST_EVENT_ALL = 27 - struct - { - uint32 creatureId; - uint32 spellId; - } cast_event_all; - // ACTION_T_REMOVEAURASFROMSPELL = 28 - struct - { - uint32 target; - uint32 spellId; - } remove_aura; - // ACTION_T_RANGED_MOVEMENT = 29 - struct - { - uint32 distance; - int32 angle; - } ranged_movement; - // ACTION_T_RANDOM_PHASE = 30 - struct - { - uint32 phase1; - uint32 phase2; - uint32 phase3; - } random_phase; - // ACTION_T_RANDOM_PHASE_RANGE = 31 - struct - { - uint32 phaseMin; - uint32 phaseMax; - } random_phase_range; - // ACTION_T_SUMMON_ID = 32 - struct - { - uint32 creatureId; - uint32 target; - uint32 spawnId; - } summon_id; - // ACTION_T_KILLED_MONSTER = 33 - struct - { - uint32 creatureId; - uint32 target; - } killed_monster; - // ACTION_T_SET_INST_DATA = 34 - struct - { - uint32 field; - uint32 value; - } set_inst_data; - // ACTION_T_SET_INST_DATA64 = 35 - struct - { - uint32 field; - uint32 target; - } set_inst_data64; - // ACTION_T_UPDATE_TEMPLATE = 36 - struct - { - uint32 creatureId; - uint32 team; - } update_template; - // ACTION_T_CALL_FOR_HELP = 39 - struct - { - uint32 radius; - } call_for_help; - // ACTION_T_SET_SHEATH = 40 - struct - { - uint32 sheath; - } set_sheath; - // ACTION_T_FORCE_DESPAWN = 41 - struct - { - uint32 msDelay; - } forced_despawn; - // ACTION_T_SET_INVINCIBILITY_HP_LEVEL = 42 - struct - { - uint32 hp_level; - uint32 is_percent; - } invincibility_hp_level; - // ACTION_T_MOUNT_TO_ENTRY_OR_MODEL = 43 - struct - { - uint32 creatureId; // set one from fields (or 0 for both to dismount) - uint32 modelId; - } mount; - // RAW - struct - { - uint32 param1; - uint32 param2; - uint32 param3; - } raw; - }; -}; - -struct CreatureEventAI_Event -{ - uint32 event_id; - - uint32 creature_id; - - uint32 event_inverse_phase_mask; - - EventAI_Type event_type : 16; - uint8 event_chance : 8; - uint8 event_flags : 8; - - union - { - // EVENT_T_TIMER = 0 - // EVENT_T_TIMER_OOC = 1 - struct - { - uint32 initialMin; - uint32 initialMax; - uint32 repeatMin; - uint32 repeatMax; - } timer; - // EVENT_T_HP = 2 - // EVENT_T_MANA = 3 - // EVENT_T_TARGET_HP = 12 - // EVENT_T_TARGET_MANA = 18 - struct - { - uint32 percentMax; - uint32 percentMin; - uint32 repeatMin; - uint32 repeatMax; - } percent_range; - // EVENT_T_KILL = 5 - struct - { - uint32 repeatMin; - uint32 repeatMax; - } kill; - // EVENT_T_SPELLHIT = 8 - struct - { - uint32 spellId; - uint32 schoolMask; // -1 ( == 0xffffffff) is ok value for full mask, or must be more limited mask like (0 < 1) = 1 for normal/physical school - uint32 repeatMin; - uint32 repeatMax; - } spell_hit; - // EVENT_T_RANGE = 9 - struct - { - uint32 minDist; - uint32 maxDist; - uint32 repeatMin; - uint32 repeatMax; - } range; - // EVENT_T_OOC_LOS = 10 - struct - { - uint32 noHostile; - uint32 maxRange; - uint32 repeatMin; - uint32 repeatMax; - } ooc_los; - // EVENT_T_SPAWNED = 11 - struct - { - uint32 condition; - uint32 conditionValue1; - } spawned; - // EVENT_T_TARGET_CASTING = 13 - struct - { - uint32 repeatMin; - uint32 repeatMax; - } target_casting; - // EVENT_T_FRIENDLY_HP = 14 - struct - { - uint32 hpDeficit; - uint32 radius; - uint32 repeatMin; - uint32 repeatMax; - } friendly_hp; - // EVENT_T_FRIENDLY_IS_CC = 15 - struct - { - uint32 dispelType; // unused ? - uint32 radius; - uint32 repeatMin; - uint32 repeatMax; - } friendly_is_cc; - // EVENT_T_FRIENDLY_MISSING_BUFF = 16 - struct - { - uint32 spellId; - uint32 radius; - uint32 repeatMin; - uint32 repeatMax; - } friendly_buff; - // EVENT_T_SUMMONED_UNIT = 17 - struct - { - uint32 creatureId; - uint32 repeatMin; - uint32 repeatMax; - } summon_unit; - // EVENT_T_QUEST_ACCEPT = 19 - // EVENT_T_QUEST_COMPLETE = 20 - struct - { - uint32 questId; - } quest; - // EVENT_T_RECEIVE_EMOTE = 22 - struct - { - uint32 emoteId; - uint32 condition; - uint32 conditionValue1; - uint32 conditionValue2; - } receive_emote; - // EVENT_T_BUFFED = 23 - // EVENT_T_TARGET_BUFFED = 24 - struct - { - uint32 spellId; - uint32 amount; - uint32 repeatMin; - uint32 repeatMax; - } buffed; - - // RAW - struct - { - uint32 param1; - uint32 param2; - uint32 param3; - uint32 param4; - } raw; - }; - - CreatureEventAI_Action action[MAX_ACTIONS]; -}; -//Event_Map -typedef UNORDERED_MAP<uint32, std::vector<CreatureEventAI_Event> > CreatureEventAI_Event_Map; - -struct CreatureEventAI_Summon -{ - //uint32 id; - - float position_x; - float position_y; - float position_z; - float orientation; - uint32 SpawnTimeSecs; -}; - -//EventSummon_Map -typedef UNORDERED_MAP<uint32, CreatureEventAI_Summon> CreatureEventAI_Summon_Map; - -struct CreatureEventAIHolder -{ - CreatureEventAIHolder(CreatureEventAI_Event const& p) : Event(p), Time(0), Enabled(true){} - - CreatureEventAI_Event Event; - uint32 Time; - bool Enabled; - - // helper - bool UpdateRepeatTimer(Creature* creature, uint32 repeatMin, uint32 repeatMax); -}; - -class CreatureEventAI : public CreatureAI -{ - public: - explicit CreatureEventAI(Creature* c); - ~CreatureEventAI() - { - m_CreatureEventAIList.clear(); - } - void JustRespawned(); - void Reset(); - void JustReachedHome(); - void EnterCombat(Unit* enemy); - void EnterEvadeMode(); - void JustDied(Unit* /*killer*/); - void KilledUnit(Unit* victim); - void JustSummoned(Creature* unit); - void AttackStart(Unit* who); - void MoveInLineOfSight(Unit* who); - void SpellHit(Unit* unit, const SpellInfo* spell); - void DamageTaken(Unit* done_by, uint32& damage); - void HealReceived(Unit* /*done_by*/, uint32& /*addhealth*/) {} - void UpdateAI(const uint32 diff); - void ReceiveEmote(Player* player, uint32 textEmote); - static int Permissible(const Creature*); - - bool ProcessEvent(CreatureEventAIHolder& holder, Unit* actionInvoker = NULL); - void ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 eventId, Unit* actionInvoker); - inline uint32 GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3); - inline int32 GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3); - inline Unit* GetTargetByType(uint32 target, Unit* actionInvoker); - - void DoScriptText(int32 textEntry, WorldObject* source, Unit* target); - bool CanCast(Unit* target, SpellInfo const* spell, bool triggered); - - bool SpawnedEventConditionsCheck(CreatureEventAI_Event const& event); - - Unit* DoSelectLowestHpFriendly(float range, uint32 minHPDiff); - void DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid); - void DoFindFriendlyCC(std::list<Creature*>& _list, float range); - - protected: - uint32 m_EventUpdateTime; // Time between event updates - uint32 m_EventDiff; // Time between the last event call - bool m_bEmptyList; - - typedef std::vector<CreatureEventAIHolder> CreatureEventAIList; - CreatureEventAIList m_CreatureEventAIList; // Holder for events (stores enabled, time, and eventid) - // Variables used by Events themselves - uint8 m_Phase; // Current phase, max 32 phases - bool m_CombatMovementEnabled; // If we allow targeted movment gen (movement twoards top threat) - bool m_MeleeEnabled; // If we allow melee auto attack - float m_AttackDistance; // Distance to attack from - float m_AttackAngle; // Angle of attack - uint32 m_InvincibilityHpLevel; // Minimal health level allowed at damage apply -}; -#endif diff --git a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp deleted file mode 100755 index 728b17b0bbf..00000000000 --- a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp +++ /dev/null @@ -1,743 +0,0 @@ -/* - * Copyright (C) 2008-2012 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 "Common.h" -#include "DatabaseEnv.h" -#include "CreatureEventAI.h" -#include "CreatureEventAIMgr.h" -#include "ObjectMgr.h" -#include "ObjectDefines.h" -#include "GridDefines.h" -#include "ConditionMgr.h" -#include "SpellMgr.h" -#include "SpellInfo.h" - -// ------------------- -void CreatureEventAIMgr::LoadCreatureEventAI_Texts() -{ - uint32 oldMSTime = getMSTime(); - - // Drop Existing Text Map, only done once and we are ready to add data from multiple sources. - m_CreatureEventAI_TextMap.clear(); - - // Load EventAI Text - sObjectMgr->LoadTrinityStrings("creature_ai_texts", MIN_CREATURE_AI_TEXT_STRING_ID, MAX_CREATURE_AI_TEXT_STRING_ID); - - // Gather Additional data from EventAI Texts 0 1 2 3 4 - QueryResult result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM creature_ai_texts"); - - if (!result) - { - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 additional CreatureEventAI Texts data. DB table `creature_ai_texts` is empty."); - - return; - } - - uint32 count = 0; - - do - { - Field* fields = result->Fetch(); - StringTextData temp; - - int32 i = fields[0].GetInt32(); - temp.SoundId = fields[1].GetUInt32(); - temp.Type = fields[2].GetUInt8(); - temp.Language = fields[3].GetUInt8(); - temp.Emote = fields[4].GetUInt16(); - - // range negative - if (i > MIN_CREATURE_AI_TEXT_STRING_ID || i <= MAX_CREATURE_AI_TEXT_STRING_ID) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` is not in valid range(%d-%d)", i, MIN_CREATURE_AI_TEXT_STRING_ID, MAX_CREATURE_AI_TEXT_STRING_ID); - continue; - } - - // range negative (must not happen, loaded from same table) - if (!sObjectMgr->GetTrinityStringLocale(i)) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` not found", i); - continue; - } - - if (temp.SoundId) - { - if (!sSoundEntriesStore.LookupEntry(temp.SoundId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` has Sound %u but sound does not exist.", i, temp.SoundId); - } - - if (!GetLanguageDescByID(temp.Language)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` using Language %u but Language does not exist.", i, temp.Language); - - if (temp.Type > CHAT_TYPE_ZONE_YELL) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` has Type %u but this Chat Type does not exist.", i, temp.Type); - - if (temp.Emote) - { - if (!sEmotesStore.LookupEntry(temp.Emote)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` has Emote %u but emote does not exist.", i, temp.Emote); - } - - m_CreatureEventAI_TextMap[i] = temp; - ++count; - } - while (result->NextRow()); - - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u additional CreatureEventAI Texts data in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); - -} - -void CreatureEventAIMgr::LoadCreatureEventAI_Summons() -{ - uint32 oldMSTime = getMSTime(); - - //Drop Existing EventSummon Map - m_CreatureEventAI_Summon_Map.clear(); - - // Gather additional data for EventAI - QueryResult result = WorldDatabase.Query("SELECT id, position_x, position_y, position_z, orientation, spawntimesecs FROM creature_ai_summons"); - - if (!result) - { - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 CreatureEventAI Summon definitions. DB table `creature_ai_summons` is empty."); - - return; - } - - uint32 count = 0; - - do - { - Field* fields = result->Fetch(); - - CreatureEventAI_Summon temp; - - uint32 i = fields[0].GetUInt32(); - temp.position_x = fields[1].GetFloat(); - temp.position_y = fields[2].GetFloat(); - temp.position_z = fields[3].GetFloat(); - temp.orientation = fields[4].GetFloat(); - temp.SpawnTimeSecs = fields[5].GetUInt32(); - - if (!Trinity::IsValidMapCoord(temp.position_x, temp.position_y, temp.position_z, temp.orientation)) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Summon id %u have wrong coordinates (%f, %f, %f, %f), skipping.", i, temp.position_x, temp.position_y, temp.position_z, temp.orientation); - continue; - } - - //Add to map - m_CreatureEventAI_Summon_Map[i] = temp; - ++count; - } - while (result->NextRow()); - - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u CreatureEventAI summon definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); - -} - -void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() -{ - uint32 oldMSTime = getMSTime(); - - //Drop Existing EventAI List - m_CreatureEventAI_Event_Map.clear(); - - // Gather event data - QueryResult result = WorldDatabase.Query("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, " - "event_param1, event_param2, event_param3, event_param4, " - "action1_type, action1_param1, action1_param2, action1_param3, " - "action2_type, action2_param1, action2_param2, action2_param3, " - "action3_type, action3_param1, action3_param2, action3_param3 " - "FROM creature_ai_scripts"); - - if (!result) - { - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 CreatureEventAI scripts. DB table `creature_ai_scripts` is empty."); - - return; - } - - uint32 count = 0; - - do - { - Field* fields = result->Fetch(); - - CreatureEventAI_Event temp; - temp.event_id = EventAI_Type(fields[0].GetUInt32()); - uint32 i = temp.event_id; - - temp.creature_id = fields[1].GetUInt32(); - uint32 creature_id = temp.creature_id; - - uint32 e_type = fields[2].GetUInt8(); - //Report any errors in event - if (e_type >= EVENT_T_END) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u have wrong type (%u), skipping.", i, e_type); - continue; - } - temp.event_type = EventAI_Type(e_type); - - temp.event_inverse_phase_mask = fields[3].GetInt32(); - temp.event_chance = fields[4].GetUInt32(); - temp.event_flags = fields[5].GetUInt32(); - temp.raw.param1 = fields[6].GetInt32(); - temp.raw.param2 = fields[7].GetInt32(); - temp.raw.param3 = fields[8].GetInt32(); - temp.raw.param4 = fields[9].GetInt32(); - - CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature_id); - //Creature does not exist in database - if (!cInfo) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, creature_id); - continue; - } - - // Only on the first script - if (cInfo->AIName != "EventAI" && m_CreatureEventAI_Event_Map[creature_id].empty()) - sLog->outError(LOG_FILTER_SQL, "Creature entry %u has EventAI scripts, but its AIName is not 'EventAI' - possible AI-mismatch?", temp.creature_id); - - //No chance of this event occuring - if (temp.event_chance == 0) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u has 0 percent chance. Event will never trigger!", i); - //Chance above 100, force it to be 100 - else if (temp.event_chance > 100) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event %u with more than 100 percent chance. Adjusting to 100 percent.", temp.creature_id, i); - temp.event_chance = 100; - } - - //Individual event checks - switch (temp.event_type) - { - case EVENT_T_TIMER: - case EVENT_T_TIMER_OOC: - if (temp.timer.initialMax < temp.timer.initialMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i); - if (temp.timer.repeatMax < temp.timer.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - case EVENT_T_HP: - case EVENT_T_MANA: - case EVENT_T_TARGET_HP: - case EVENT_T_TARGET_MANA: - if (temp.percent_range.percentMax > 100) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i); - - if (temp.percent_range.percentMax <= temp.percent_range.percentMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using percentage event(%u) with param1 <= param2 (MaxPercent <= MinPercent). Event will never trigger! ", temp.creature_id, i); - - if (temp.event_flags & EFLAG_REPEATABLE && !temp.percent_range.repeatMin && !temp.percent_range.repeatMax) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i); - temp.event_flags &= ~EFLAG_REPEATABLE; - } - break; - case EVENT_T_SPELLHIT: - if (temp.spell_hit.spellId) - { - SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.spell_hit.spellId); - if (!spell) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i); - continue; - } - - if ((temp.spell_hit.schoolMask & spell->SchoolMask) != spell->SchoolMask) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.spell_hit.schoolMask, i); - } - - if (!temp.spell_hit.schoolMask) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.spell_hit.schoolMask, i); - - if (temp.spell_hit.repeatMax < temp.spell_hit.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - case EVENT_T_RANGE: - if (temp.range.maxDist < temp.range.minDist) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (MaxDist < MinDist). Event will never repeat.", temp.creature_id, i); - if (temp.range.repeatMax < temp.range.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - case EVENT_T_OOC_LOS: - if (temp.ooc_los.repeatMax < temp.ooc_los.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - case EVENT_T_SPAWNED: - switch (temp.spawned.condition) - { - case SPAWNED_EVENT_ALWAY: - break; - case SPAWNED_EVENT_MAP: - if (!sMapStore.LookupEntry(temp.spawned.conditionValue1)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using spawned event(%u) with param1 = %u 'map specific' but with not existed map (%u) in param2. Event will never repeat.", temp.creature_id, i, temp.spawned.condition, temp.spawned.conditionValue1); - break; - case SPAWNED_EVENT_ZONE: - if (!GetAreaEntryByAreaID(temp.spawned.conditionValue1)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using spawned event(%u) with param1 = %u 'area specific' but with not existed area (%u) in param2. Event will never repeat.", temp.creature_id, i, temp.spawned.condition, temp.spawned.conditionValue1); - default: - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using invalid spawned event %u mode (%u) in param1", temp.creature_id, i, temp.spawned.condition); - break; - } - break; - case EVENT_T_FRIENDLY_HP: - if (temp.friendly_hp.repeatMax < temp.friendly_hp.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - case EVENT_T_FRIENDLY_IS_CC: - if (temp.friendly_is_cc.repeatMax < temp.friendly_is_cc.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - case EVENT_T_FRIENDLY_MISSING_BUFF: - { - SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.spell_hit.spellId); - if (!spell) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i); - continue; - } - if (temp.friendly_buff.repeatMax < temp.friendly_buff.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - } - case EVENT_T_KILL: - if (temp.kill.repeatMax < temp.kill.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - case EVENT_T_TARGET_CASTING: - if (temp.target_casting.repeatMax < temp.target_casting.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - case EVENT_T_SUMMONED_UNIT: - if (!sObjectMgr->GetCreatureTemplate(temp.summon_unit.creatureId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with not existed creature template id (%u) in param1, skipped.", temp.creature_id, i, temp.summon_unit.creatureId); - if (temp.summon_unit.repeatMax < temp.summon_unit.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - case EVENT_T_QUEST_ACCEPT: - case EVENT_T_QUEST_COMPLETE: - if (!sObjectMgr->GetQuestTemplate(temp.quest.questId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with not existed qyest id (%u) in param1, skipped.", temp.creature_id, i, temp.quest.questId); - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using not implemented event (%u) in event %u.", temp.creature_id, temp.event_id, i); - continue; - - case EVENT_T_AGGRO: - case EVENT_T_DEATH: - case EVENT_T_EVADE: - case EVENT_T_REACHED_HOME: - { - if (temp.event_flags & EFLAG_REPEATABLE) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has EFLAG_REPEATABLE set. Event can never be repeatable. Removing flag for event %u.", temp.creature_id, i); - temp.event_flags &= ~EFLAG_REPEATABLE; - } - - break; - } - - case EVENT_T_RECEIVE_EMOTE: - { - if (!sEmotesTextStore.LookupEntry(temp.receive_emote.emoteId)) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using event %u: param1 (EmoteTextId: %u) are not valid.", temp.creature_id, i, temp.receive_emote.emoteId); - continue; - } - if (temp.receive_emote.condition) - { - Condition cond; - cond.ConditionType = ConditionTypes(temp.receive_emote.condition); - cond.ConditionValue1 = temp.receive_emote.conditionValue1; - cond.ConditionValue2 = temp.receive_emote.conditionValue2; - if (!sConditionMgr->isConditionTypeValid(&cond)) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not valid.", temp.creature_id, i, temp.receive_emote.condition); - continue; - } - } - - if (!(temp.event_flags & EFLAG_REPEATABLE)) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using event %u: EFLAG_REPEATABLE not set. Event must always be repeatable. Flag applied.", temp.creature_id, i); - temp.event_flags |= EFLAG_REPEATABLE; - } - - break; - } - - case EVENT_T_BUFFED: - case EVENT_T_TARGET_BUFFED: - { - SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.buffed.spellId); - if (!spell) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i); - continue; - } - if (temp.buffed.repeatMax < temp.buffed.repeatMin) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - break; - } - - default: - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u using not checked at load event (%u) in event %u. Need check code update?", temp.creature_id, temp.event_id, i); - break; - } - - for (uint32 j = 0; j < MAX_ACTIONS; j++) - { - uint16 action_type = fields[10+(j*4)].GetUInt8(); - if (action_type >= ACTION_T_END) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u has incorrect action type (%u), replace by ACTION_T_NONE.", i, j+1, action_type); - temp.action[j].type = ACTION_T_NONE; - continue; - } - - CreatureEventAI_Action& action = temp.action[j]; - - action.type = EventAI_ActionType(action_type); - action.raw.param1 = fields[11+(j*4)].GetInt32(); - action.raw.param2 = fields[12+(j*4)].GetInt32(); - action.raw.param3 = fields[13+(j*4)].GetInt32(); - - //Report any errors in actions - switch (action.type) - { - case ACTION_T_NONE: - break; - case ACTION_T_TEXT: - { - if (action.text.TextId1 < 0) - { - if (m_CreatureEventAI_TextMap.find(action.text.TextId1) == m_CreatureEventAI_TextMap.end()) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param1 refrences non-existing entry in texts table.", i, j+1); - } - if (action.text.TextId2 < 0) - { - if (m_CreatureEventAI_TextMap.find(action.text.TextId2) == m_CreatureEventAI_TextMap.end()) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1); - - if (!action.text.TextId1) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u has param2, but param1 is not set. Required for randomized text.", i, j+1); - } - if (action.text.TextId3 < 0) - { - if (m_CreatureEventAI_TextMap.find(action.text.TextId3) == m_CreatureEventAI_TextMap.end()) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1); - - if (!action.text.TextId1 || !action.text.TextId2) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1); - } - break; - } - case ACTION_T_SET_FACTION: - if (action.set_faction.factionId !=0 && !sFactionStore.LookupEntry(action.set_faction.factionId)) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent FactionId %u.", i, j+1, action.set_faction.factionId); - action.set_faction.factionId = 0; - } - break; - case ACTION_T_MORPH_TO_ENTRY_OR_MODEL: - if (action.morph.creatureId !=0 || action.morph.modelId !=0) - { - if (action.morph.creatureId && !sObjectMgr->GetCreatureTemplate(action.morph.creatureId)) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, action.morph.creatureId); - action.morph.creatureId = 0; - } - - if (action.morph.modelId) - { - if (action.morph.creatureId) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u have unused ModelId %u with also set creature id %u.", i, j+1, action.morph.modelId, action.morph.creatureId); - action.morph.modelId = 0; - } - else if (!sCreatureDisplayInfoStore.LookupEntry(action.morph.modelId)) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, action.morph.modelId); - action.morph.modelId = 0; - } - } - } - break; - case ACTION_T_SOUND: - if (!sSoundEntriesStore.LookupEntry(action.sound.soundId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, action.sound.soundId); - break; - case ACTION_T_EMOTE: - if (!sEmotesStore.LookupEntry(action.emote.emoteId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.emote.emoteId); - break; - case ACTION_T_RANDOM_SOUND: - if (!sSoundEntriesStore.LookupEntry(action.random_sound.soundId1)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId1); - if (action.random_sound.soundId2 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId2)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId2); - if (action.random_sound.soundId3 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId3)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId3); - break; - case ACTION_T_RANDOM_EMOTE: - if (!sEmotesStore.LookupEntry(action.random_emote.emoteId1)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId1); - if (action.random_emote.emoteId2 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId2)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param2 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId2); - if (action.random_emote.emoteId3 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId3)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param3 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId3); - break; - case ACTION_T_CAST: - { - const SpellInfo* spell = sSpellMgr->GetSpellInfo(action.cast.spellId); - if (!spell) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast.spellId); - /* FIXME: temp.raw.param3 not have event tipes with recovery time in it.... - else - { - if (spell->RecoveryTime > 0 && temp.event_flags & EFLAG_REPEATABLE) - { - //output as debug for now, also because there's no general rule all spells have RecoveryTime - if (temp.event_param3 < spell->RecoveryTime) - sLog->outDebug("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1, action.cast.spellId, spell->RecoveryTime, temp.event_param3); - } - } - */ - - //Cast is always triggered if target is forced to cast on self - if (action.cast.castFlags & CAST_FORCE_TARGET_SELF) - action.cast.castFlags |= CAST_TRIGGERED; - - if (action.cast.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - } - case ACTION_T_SUMMON: - if (!sObjectMgr->GetCreatureTemplate(action.summon.creatureId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.summon.creatureId); - - if (action.summon.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - case ACTION_T_THREAT_SINGLE_PCT: - if (std::abs(action.threat_single_pct.percent) > 100) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_single_pct.percent); - if (action.threat_single_pct.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - case ACTION_T_THREAT_ALL_PCT: - if (std::abs(action.threat_all_pct.percent) > 100) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_all_pct.percent); - break; - case ACTION_T_QUEST_EVENT: - if (Quest const* qid = sObjectMgr->GetQuestTemplate(action.quest_event.questId)) - { - if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event.questId); - } - else - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event.questId); - - if (action.quest_event.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - - break; - case ACTION_T_CAST_EVENT: - if (!sObjectMgr->GetCreatureTemplate(action.cast_event.creatureId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.cast_event.creatureId); - if (!sSpellMgr->GetSpellInfo(action.cast_event.spellId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast_event.spellId); - if (action.cast_event.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - case ACTION_T_SET_UNIT_FIELD: - if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1); - if (action.set_unit_field.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - case ACTION_T_SET_UNIT_FLAG: - case ACTION_T_REMOVE_UNIT_FLAG: - if (action.unit_flag.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - case ACTION_T_SET_PHASE: - if (action.set_phase.phase >= MAX_PHASE) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phase >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); - break; - case ACTION_T_INC_PHASE: - if (action.set_inc_phase.step == 0) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1); - else if (std::abs(action.set_inc_phase.step) > MAX_PHASE-1) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u is change phase by too large for any use %i.", i, j+1, action.set_inc_phase.step); - break; - case ACTION_T_QUEST_EVENT_ALL: - if (Quest const* qid = sObjectMgr->GetQuestTemplate(action.quest_event_all.questId)) - { - if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event_all.questId); - } - else - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event_all.questId); - break; - case ACTION_T_CAST_EVENT_ALL: - if (!sObjectMgr->GetCreatureTemplate(action.cast_event_all.creatureId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.cast_event_all.creatureId); - if (!sSpellMgr->GetSpellInfo(action.cast_event_all.spellId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast_event_all.spellId); - break; - case ACTION_T_REMOVEAURASFROMSPELL: - if (!sSpellMgr->GetSpellInfo(action.remove_aura.spellId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.remove_aura.spellId); - if (action.remove_aura.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - case ACTION_T_RANDOM_PHASE: //PhaseId1, PhaseId2, PhaseId3 - if (action.random_phase.phase1 >= MAX_PHASE) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phase1 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); - if (action.random_phase.phase2 >= MAX_PHASE) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phase2 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); - if (action.random_phase.phase3 >= MAX_PHASE) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phase3 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); - break; - case ACTION_T_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax - if (action.random_phase_range.phaseMin >= MAX_PHASE) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phaseMin >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); - if (action.random_phase_range.phaseMin >= MAX_PHASE) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phaseMax >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); - if (action.random_phase_range.phaseMin >= action.random_phase_range.phaseMax) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set phaseMax <= phaseMin.", i, j+1); - std::swap(action.random_phase_range.phaseMin, action.random_phase_range.phaseMax); - // equal case processed at call - } - break; - case ACTION_T_SUMMON_ID: - if (!sObjectMgr->GetCreatureTemplate(action.summon_id.creatureId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.summon_id.creatureId); - if (action.summon_id.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - if (m_CreatureEventAI_Summon_Map.find(action.summon_id.spawnId) == m_CreatureEventAI_Summon_Map.end()) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u summons missing CreatureEventAI_Summon %u", i, j+1, action.summon_id.spawnId); - break; - case ACTION_T_KILLED_MONSTER: - if (!sObjectMgr->GetCreatureTemplate(action.killed_monster.creatureId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.killed_monster.creatureId); - if (action.killed_monster.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - case ACTION_T_SET_INST_DATA: - if (!(temp.event_flags & EFLAG_DIFFICULTY_ALL)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u. Cannot set instance data without difficulty event flags.", i, j+1); - if (action.set_inst_data.value > 4/*SPECIAL*/) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1); - break; - case ACTION_T_SET_INST_DATA64: - if (!(temp.event_flags & EFLAG_DIFFICULTY_ALL)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u. Cannot set instance data without difficulty event flags.", i, j+1); - if (action.set_inst_data64.target >= TARGET_T_END) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); - break; - case ACTION_T_UPDATE_TEMPLATE: - if (!sObjectMgr->GetCreatureTemplate(action.update_template.creatureId)) - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.update_template.creatureId); - break; - case ACTION_T_SET_SHEATH: - if (action.set_sheath.sheath >= MAX_SHEATH_STATE) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses wrong sheath state %u.", i, j+1, action.set_sheath.sheath); - action.set_sheath.sheath = SHEATH_STATE_UNARMED; - } - break; - case ACTION_T_SET_INVINCIBILITY_HP_LEVEL: - if (action.invincibility_hp_level.is_percent) - { - if (action.invincibility_hp_level.hp_level > 100) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses wrong percent value %u.", i, j+1, action.invincibility_hp_level.hp_level); - action.invincibility_hp_level.hp_level = 100; - } - } - break; - case ACTION_T_MOUNT_TO_ENTRY_OR_MODEL: - if (action.mount.creatureId != 0 || action.mount.modelId != 0) - { - if (action.mount.creatureId && !sObjectMgr->GetCreatureTemplate(action.mount.creatureId)) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses nonexistent Creature entry %u.", i, j+1, action.mount.creatureId); - action.morph.creatureId = 0; - } - - if (action.mount.modelId) - { - if (action.mount.creatureId) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u have unused ModelId %u with also set creature id %u.", i, j+1, action.mount.modelId, action.mount.creatureId); - action.mount.modelId = 0; - } - else if (!sCreatureDisplayInfoStore.LookupEntry(action.mount.modelId)) - { - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses nonexistent ModelId %u.", i, j+1, action.mount.modelId); - action.mount.modelId = 0; - } - } - } - break; - case ACTION_T_EVADE: //No Params - case ACTION_T_FLEE_FOR_ASSIST: //No Params - case ACTION_T_DIE: //No Params - case ACTION_T_ZONE_COMBAT_PULSE: //No Params - case ACTION_T_FORCE_DESPAWN: //No Params - case ACTION_T_AUTO_ATTACK: //AllowAttackState (0 = stop attack, anything else means continue attacking) - case ACTION_T_COMBAT_MOVEMENT: //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking) - case ACTION_T_RANGED_MOVEMENT: //Distance, Angle - case ACTION_T_CALL_FOR_HELP: //Distance - break; - - case ACTION_T_RANDOM_SAY: - case ACTION_T_RANDOM_YELL: - case ACTION_T_RANDOM_TEXTEMOTE: - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u currently unused ACTION type. Did you forget to update database?", i, j+1); - break; - - case ACTION_T_MOVE_RANDOM_POINT: - case ACTION_T_SET_STAND_STATE: - case ACTION_T_SET_PHASE_MASK: - case ACTION_T_SET_VISIBILITY: - case ACTION_T_SET_ACTIVE: - case ACTION_T_SET_AGGRESSIVE: - case ACTION_T_ATTACK_START_PULSE: - case ACTION_T_SUMMON_GO: - break; - - default: - sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u have currently not checked at load action type (%u). Need check code update?", i, j+1, action.type); - break; - } - } - - //Add to list - m_CreatureEventAI_Event_Map[creature_id].push_back(temp); - ++count; - - } - while (result->NextRow()); - - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u CreatureEventAI scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); - -} diff --git a/src/server/game/AI/EventAI/CreatureEventAIMgr.h b/src/server/game/AI/EventAI/CreatureEventAIMgr.h deleted file mode 100755 index 93e953681b6..00000000000 --- a/src/server/game/AI/EventAI/CreatureEventAIMgr.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2008-2012 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 TRINITY_CREATURE_EAI_MGR_H -#define TRINITY_CREATURE_EAI_MGR_H - -#include "Common.h" -#include "CreatureEventAI.h" - -class CreatureEventAIMgr -{ - friend class ACE_Singleton<CreatureEventAIMgr, ACE_Null_Mutex>; - - private: - CreatureEventAIMgr(){}; - ~CreatureEventAIMgr(){}; - - public: - void LoadCreatureEventAI_Texts(); - void LoadCreatureEventAI_Summons(); - void LoadCreatureEventAI_Scripts(); - - CreatureEventAI_Event_Map const& GetCreatureEventAIMap() const { return m_CreatureEventAI_Event_Map; } - CreatureEventAI_Summon_Map const& GetCreatureEventAISummonMap() const { return m_CreatureEventAI_Summon_Map; } - CreatureEventAI_TextMap const& GetCreatureEventAITextMap() const { return m_CreatureEventAI_TextMap; } - - private: - CreatureEventAI_Event_Map m_CreatureEventAI_Event_Map; - CreatureEventAI_Summon_Map m_CreatureEventAI_Summon_Map; - CreatureEventAI_TextMap m_CreatureEventAI_TextMap; -}; - -#define sEventAIMgr ACE_Singleton<CreatureEventAIMgr, ACE_Null_Mutex>::instance() -#endif diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index 76bb3aaa76a..1611ae2b85d 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -221,7 +221,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 diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 3b69408354e..a40024a81cd 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -676,7 +676,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_CALL_GROUPEVENTHAPPENS: if (Quest const* qid = sObjectMgr->GetQuestTemplate(e.action.quest.quest)) { - if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) + if (!qid->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT)) { sLog->outError(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u SpecialFlags for Quest entry %u does not include FLAGS_EXPLORATION_OR_EVENT(2), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.quest.quest); return false; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 05965d8ffa0..2a81339a930 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" diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 506495469d3..7a73b9f8f69 100755..100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -40,6 +40,7 @@ #include "BattlegroundAB.h" #include "Map.h" #include "InstanceScript.h" +#include "Group.h" namespace Trinity { @@ -155,14 +156,6 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) return false; } return true; - case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD: - if (player_dead.own_team_flag > 1) - { - sLog->outError(LOG_FILTER_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); - return false; - } - return true; case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA: case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA: { @@ -187,14 +180,6 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) } return true; } - case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA: - if (!GetAreaEntryByAreaID(area.id)) - { - sLog->outError(LOG_FILTER_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_T_LEVEL: if (level.minlevel > STRONG_MAX_LEVEL) { @@ -219,14 +204,6 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) return false; } return true; - case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY: - if (difficulty.difficulty >= MAX_DIFFICULTY) - { - sLog->outError(LOG_FILTER_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); - return false; - } - return true; case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT: if (map_players.maxcount <= 0) { @@ -269,14 +246,6 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) return false; } return true; - case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID: - if (!sMapStore.LookupEntry(map_id.mapId)) - { - sLog->outError(LOG_FILTER_SQL, "Table `achievement_criteria_requirement` (Entry: %u Type: %u) for requirement ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID (%u) has unknown map id in value1 (%u), ignored.", - criteria->ID, criteria->requiredType, dataType, map_id.mapId); - return false; - } - return true; case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE: if (!classRace.class_id && !classRace.race_id) { @@ -333,21 +302,8 @@ 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: @@ -362,11 +318,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(this, 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)) - 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: @@ -411,8 +362,6 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un 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; default: break; } @@ -428,45 +377,89 @@ bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target, return true; } -AchievementMgr::AchievementMgr(Player* player) +template<class T> +AchievementMgr<T>::AchievementMgr(T* owner) { - m_player = player; + _owner = owner; } -AchievementMgr::~AchievementMgr() +template<class T> +AchievementMgr<T>::~AchievementMgr() { } -void AchievementMgr::Reset() +template<class T> +void AchievementMgr<T>::SendPacket(WorldPacket* data) const { - 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); - } +} - 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); - } +template<> +void AchievementMgr<Guild>::SendPacket(WorldPacket* data) const +{ + GetOwner()->BroadcastPacket(data); +} - m_completedAchievements.clear(); - m_criteriaProgress.clear(); - DeleteFromDB(m_player->GetGUIDLow()); +template<> +void AchievementMgr<Player>::SendPacket(WorldPacket* data) const +{ + GetOwner()->GetSession()->SendPacket(data); +} - // re-fill data - CheckAllAchievementCriteria(); +template<class T> +void AchievementMgr<T>::RemoveCriteriaProgress(const AchievementCriteriaEntry* entry) +{ + CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID); + if (criteriaProgress == m_criteriaProgress.end()) + return; + + WorldPacket data(SMSG_CRITERIA_DELETED, 4); + data << uint32(entry->ID); + SendPacket(&data); + + m_criteriaProgress.erase(criteriaProgress); } -void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, bool evenIfCriteriaComplete) +template<> +void AchievementMgr<Guild>::RemoveCriteriaProgress(const AchievementCriteriaEntry* entry) +{ + 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, uint32 miscvalue1, uint32 miscvalue2, bool evenIfCriteriaComplete) { sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::ResetAchievementCriteria(%u, %u, %u)", type, miscvalue1, miscvalue2); // disable for gamemasters with GM-mode enabled - if (m_player->isGameMaster()) + if (GetOwner()->isGameMaster()) return; AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type); @@ -493,7 +486,19 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uin } } -void AchievementMgr::DeleteFromDB(uint32 lowguid) +template<> +void AchievementMgr<Guild>::ResetAchievementCriteria(AchievementCriteriaTypes /*type*/, uint32 /*miscvalue1*/, uint32 /*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(); @@ -508,7 +513,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()) { @@ -523,7 +550,7 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans) /// first new/changed record prefix if (!need_execute) { - ssdel << "DELETE FROM character_achievement WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND achievement IN ("; + ssdel << "DELETE FROM character_achievement WHERE guid = " << GetOwner()->GetGUIDLow() << " AND achievement IN ("; ssins << "INSERT INTO character_achievement (guid, achievement, date) VALUES "; need_execute = true; } @@ -536,7 +563,7 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans) // new/changed record data ssdel << iter->first; - ssins << '(' << GetPlayer()->GetGUIDLow() << ',' << iter->first << ',' << uint64(iter->second.date) << ')'; + ssins << '(' << GetOwner()->GetGUIDLow() << ',' << iter->first << ',' << uint64(iter->second.date) << ')'; /// mark as saved in db iter->second.changed = false; @@ -567,7 +594,7 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans) /// first new/changed record prefix (for any counter value) if (!need_execute_del) { - ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND criteria IN ("; + ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetOwner()->GetGUIDLow() << " AND criteria IN ("; need_execute_del = true; } /// next new/changed record prefix @@ -592,7 +619,7 @@ void AchievementMgr::SaveToDB(SQLTransaction& trans) ssins << ','; // new/changed record data - ssins << '(' << GetPlayer()->GetGUIDLow() << ',' << iter->first << ',' << iter->second.counter << ',' << iter->second.date << ')'; + ssins << '(' << GetOwner()->GetGUIDLow() << ',' << iter->first << ',' << iter->second.counter << ',' << iter->second.date << ')'; } /// mark as updated in db @@ -612,7 +639,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->setUInt32(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) { @@ -632,10 +713,10 @@ void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQ // 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)) - if (!GetPlayer()->HasTitle(titleEntry)) - GetPlayer()->SetTitle(titleEntry); + if (!GetOwner()->HasTitle(titleEntry)) + GetOwner()->SetTitle(titleEntry); } while (achievementResult->NextRow()); } @@ -656,9 +737,7 @@ void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQ sLog->outError(LOG_FILTER_ACHIEVEMENTSYS, "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; @@ -675,11 +754,136 @@ void AchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQ } } -void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) const +template<> +void AchievementMgr<Guild>::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult) { - if (GetPlayer()->GetSession()->PlayerLoading()) - return; + 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 = sAchievementStore.LookupEntry(achievementid); + if (!achievement) + continue; + CompletedAchievementData& ca = m_completedAchievements[achievementid]; + ca.date = time_t(fields[1].GetUInt32()); + Tokens 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; + + } 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 = sAchievementCriteriaStore.LookupEntry(id); + if (!criteria) + { + // we will remove not existed criteria for all guilds + sLog->outError(LOG_FILTER_GENERAL, "Non-existing achievement criteria %u data removed from table `guild_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) < 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()); + } +} + +template<class T> +void AchievementMgr<T>::Reset() +{ +} + +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(); + m_criteriaProgress.clear(); + DeleteFromDB(_owner->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 << uint32(secsToTimeBitFields(iter->second.date)); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[2]); + SendPacket(&data); + } + + while (!m_criteriaProgress.empty()) + if (AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(m_criteriaProgress.begin()->first)) + RemoveCriteriaProgress(criteria); + + m_completedAchievements.clear(); + DeleteFromDB(_owner->GetId()); +} + +template<class T> +void AchievementMgr<T>::SendAchievementEarned(AchievementEntry const* achievement) const +{ // Don't send for achievements with ACHIEVEMENT_FLAG_TRACKING if (achievement->flags & ACHIEVEMENT_FLAG_HIDDEN) return; @@ -688,47 +892,82 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::SendAchievementEarned(%u)", achievement->ID); #endif - if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId())) + if (Guild* guild = sGuildMgr->GetGuildById(GetOwner()->GetGuildId())) { - Trinity::AchievementChatBuilder say_builder(*GetPlayer(), CHAT_MSG_GUILD_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID); + Trinity::AchievementChatBuilder say_builder(*GetOwner(), CHAT_MSG_GUILD_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID); Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> say_do(say_builder); - guild->BroadcastWorker(say_do, GetPlayer()); + guild->BroadcastWorker(say_do); } - if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL|ACHIEVEMENT_FLAG_REALM_FIRST_REACH)) + if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH)) { // broadcast realm first reached - WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, strlen(GetPlayer()->GetName())+1+8+4+4); - data << GetPlayer()->GetName(); - data << uint64(GetPlayer()->GetGUID()); + WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, strlen(GetOwner()->GetName())+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()) { - CellCoord p = Trinity::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()); + CellCoord p = Trinity::ComputeCellCoord(GetOwner()->GetPositionX(), GetOwner()->GetPositionY()); Cell cell(p); cell.SetNoCreate(); - Trinity::AchievementChatBuilder say_builder(*GetPlayer(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID); + Trinity::AchievementChatBuilder say_builder(*GetOwner(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID); Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> say_do(say_builder); - Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> > say_worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), say_do); + Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> > say_worker(GetOwner(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), say_do); TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> >, WorldTypeMapContainer > message(say_worker); - cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY)); + cell.Visit(p, message, *GetOwner()->GetMap(), *GetOwner(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY)); } WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8); - data.append(GetPlayer()->GetPackGUID()); + data.append(GetOwner()->GetPackGUID()); data << uint32(achievement->ID); data << uint32(secsToTimeBitFields(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 << uint32(secsToTimeBitFields(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); } -void AchievementMgr::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const +template<class T> +void AchievementMgr<T>::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); data << uint32(entry->ID); @@ -736,7 +975,7 @@ void AchievementMgr::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, C // 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 @@ -744,17 +983,72 @@ void AchievementMgr::SendCriteriaUpdate(AchievementCriteriaEntry const* entry, C data << uint32(secsToTimeBitFields(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, NULL, referencePlayer); } static const uint32 achievIdByArenaSlot[MAX_ARENA_SLOT] = { 1057, 1107, 1108 }; @@ -769,18 +1063,23 @@ 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, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= NULL*/, Player* referencePlayer /*= NULL*/) { sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::UpdateAchievementCriteria(%u, %u, %u)", type, miscValue1, miscValue2); // disable for gamemasters with GM-mode enabled - if (m_player->isGameMaster()) + if (referencePlayer->isGameMaster()) return; - AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type); + AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type, IsGuild<T>()); for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i) { AchievementCriteriaEntry const* achievementCriteria = (*i); @@ -788,9 +1087,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (!achievement) continue; - if (!CanUpdateCriteria(achievementCriteria, achievement)) + if (!CanUpdateCriteria(achievementCriteria, achievement, miscValue1, miscValue2, 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 @@ -807,7 +1111,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if (!miscValue1) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; // std case: increment at miscvalue1 case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS: @@ -823,7 +1127,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if (!miscValue1) continue; - SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE); break; // std case: high value at miscvalue1 case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID: @@ -835,7 +1139,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if (!miscValue1) continue; - SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_HIGHEST); + SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_HIGHEST); break; // specialized cases @@ -845,14 +1149,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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, 1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: @@ -860,15 +1157,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if (!miscValue1) continue; - if (achievementCriteria->win_bg.bgMapID != GetPlayer()->GetMapId()) + if (achievementCriteria->win_bg.bgMapID != referencePlayer->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); + SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: @@ -879,41 +1171,33 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, miscValue2, referencePlayer, 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); + if (uint32 maxSkillvalue = referencePlayer->GetPureMaxSkillValue(achievementCriteria->learn_skill_level.skillID)) + SetCriteriaProgress(achievementCriteria, maxSkillvalue, referencePlayer); break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: if (m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end()) - SetCriteriaProgress(achievementCriteria, 1); + SetCriteriaProgress(achievementCriteria, 1, 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: @@ -925,7 +1209,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; } @@ -943,7 +1227,7 @@ 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: @@ -954,31 +1238,31 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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) + if (referencePlayer->GetMapId() != achievementCriteria->complete_battleground.mapID) continue; - SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, 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) + if (referencePlayer->GetMapId() != achievementCriteria->death_at_map.mapID) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_DEATH: { @@ -991,7 +1275,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui { if (achievIdByArenaSlot[j] == achievement->ID) { - Battleground* bg = GetPlayer()->GetBattleground(); + Battleground* bg = referencePlayer->GetBattleground(); if (!bg || !bg->isArena() || ArenaTeam::GetSlotByType(bg->GetArenaType()) != j) notfit = true; @@ -1001,7 +1285,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (notfit) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON: @@ -1010,7 +1294,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (!miscValue1) continue; - Map const* map = GetPlayer()->IsInWorld() ? GetPlayer()->GetMap() : sMapMgr->FindMap(GetPlayer()->GetMapId(), GetPlayer()->GetInstanceId()); + Map const* map = referencePlayer->IsInWorld() ? referencePlayer->GetMap() : sMapMgr->FindMap(referencePlayer->GetMapId(), referencePlayer->GetInstanceId()); if (!map || !map->IsDungeon()) continue; @@ -1026,7 +1310,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (!achievIdForDungeon[j][2]) break; // for } - else if (GetPlayer()->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL) + else if (referencePlayer->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL) { // dungeon in normal mode accepted if (!achievIdForDungeon[j][1]) @@ -1049,7 +1333,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui //FIXME: work only for instances where max == min for players if (((InstanceMap*)map)->GetMaxPlayers() != achievementCriteria->death_in_dungeon.manLimit) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; } @@ -1059,7 +1343,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if (miscValue1 != achievementCriteria->killed_by_creature.creatureEntry) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case @@ -1067,10 +1351,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; // if team check required: must kill by opposition faction - if (achievement->ID == 318 && miscValue2 == GetPlayer()->GetTeam()) + if (achievement->ID == 318 && miscValue2 == referencePlayer->GetTeam()) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: { @@ -1078,13 +1362,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer); break; } case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM: @@ -1093,7 +1372,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if (miscValue2 != achievementCriteria->death_from.type) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: { @@ -1106,15 +1385,15 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui else { // login case. - if (!GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) + if (!referencePlayer->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) continue; } if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria)) - if (!data->Meets(GetPlayer(), unit)) + if (!data->Meets(referencePlayer, unit)) continue; - SetCriteriaProgress(achievementCriteria, 1); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer); break; } case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: @@ -1123,15 +1402,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: @@ -1140,23 +1411,15 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, 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); + if (referencePlayer->HasSpell(achievementCriteria->learn_spell.spellID)) + SetCriteriaProgress(achievementCriteria, 1, referencePlayer); break; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: { @@ -1167,42 +1430,20 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, miscValue2, referencePlayer, 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); + SetCriteriaProgress(achievementCriteria, miscValue2, referencePlayer, 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); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case @@ -1212,15 +1453,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: // You _have_ to loot that item, just owning it when logging in does _not_ count! @@ -1228,7 +1461,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if (miscValue1 != achievementCriteria->own_item.itemID) continue; - SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, miscValue2, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: { @@ -1250,7 +1483,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui uint32 playerIndexOffset = uint32(exploreFlag) / 32; uint32 mask = 1<< (uint32(exploreFlag) % 32); - if (GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask) + if (referencePlayer->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask) { matchFound = true; break; @@ -1258,11 +1491,11 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui } if (matchFound) - SetCriteriaProgress(achievementCriteria, 1); + 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: { @@ -1270,14 +1503,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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()); + SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetExaltedFactionCount(), referencePlayer); break; } case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: @@ -1285,7 +1518,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // skip for login case if (!miscValue1) continue; - SetCriteriaProgress(achievementCriteria, 1); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer); break; } case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM: @@ -1298,12 +1531,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer); break; } @@ -1321,12 +1549,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: @@ -1336,15 +1559,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE: @@ -1355,7 +1571,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (achievementCriteria->additionalRequirements[0].additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP) { - if (GetPlayer()->GetMapId() != achievementCriteria->additionalRequirements[0].additionalRequirement_value) + if (referencePlayer->GetMapId() != achievementCriteria->additionalRequirements[0].additionalRequirement_value) continue; // map specific case (BG in fact) expected player targeted damage/heal @@ -1363,7 +1579,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; } - SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM: @@ -1373,7 +1589,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (miscValue1 != achievementCriteria->equip_item.itemID) continue; - SetCriteriaProgress(achievementCriteria, 1); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer); break; case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT: // miscvalue1 = go entry @@ -1382,7 +1598,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (miscValue1 != achievementCriteria->use_gameobject.goEntry) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT: if (!miscValue1) @@ -1390,7 +1606,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (miscValue1 != achievementCriteria->fish_in_gameobject.goEntry) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: { @@ -1398,8 +1614,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); @@ -1409,7 +1625,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui spellCount++; } } - SetCriteriaProgress(achievementCriteria, spellCount); + SetCriteriaProgress(achievementCriteria, spellCount, referencePlayer); break; } case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: @@ -1417,27 +1633,16 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, 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: @@ -1448,7 +1653,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui ItemTemplate const* proto = sObjectMgr->GetItemTemplate(miscValue1); if (!proto || proto->Quality < ITEM_QUALITY_EPIC) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE: @@ -1457,8 +1662,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); @@ -1466,26 +1671,26 @@ 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)); + SetCriteriaProgress(achievementCriteria, referencePlayer->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS), referencePlayer); break; case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS: if (!miscValue1 || miscValue1 != achievementCriteria->hk_class.classID) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE: if (!miscValue1 || miscValue1 != achievementCriteria->hk_race.raceID) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); 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: { @@ -1495,10 +1700,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui for (CompletedAchievementMap::iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr) if (AchievementEntry const* pAchievement = sAchievementStore.LookupEntry(itr->first)) points += pAchievement->points; - SetCriteriaProgress(achievementCriteria, points, PROGRESS_SET); + SetCriteriaProgress(achievementCriteria, points, referencePlayer, PROGRESS_SET); } else - SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE: @@ -1506,12 +1711,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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, 1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL: @@ -1522,12 +1722,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA: @@ -1535,7 +1730,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (!miscValue1 || miscValue1 != achievementCriteria->honorable_kill_at_area.areaID) continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING: @@ -1547,13 +1742,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 { 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; @@ -1561,7 +1756,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; } } @@ -1577,13 +1772,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 { 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; @@ -1591,9 +1786,9 @@ 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; } } @@ -1601,13 +1796,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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_CURRENCY: + if (!miscValue1 || !miscValue2) + continue; + if (miscValue1 != achievementCriteria->currencyGain.currency) + continue; + if (int64(miscValue2) < 0) + continue; + SetCriteriaProgress(achievementCriteria, miscValue2, referencePlayer, PROGRESS_ACCUMULATE); break; // FIXME: not triggered in code as result, need to implement case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID: @@ -1617,26 +1813,59 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE: case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE: case ACHIEVEMENT_CRITERIA_TYPE_TOTAL: + case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS: + case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL: + 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_UNK118: + case ACHIEVEMENT_CRITERIA_TYPE_UNK120: + case ACHIEVEMENT_CRITERIA_TYPE_UNK121: + case ACHIEVEMENT_CRITERIA_TYPE_UNK122: + case ACHIEVEMENT_CRITERIA_TYPE_UNK123: + case ACHIEVEMENT_CRITERIA_TYPE_UNK137: + case ACHIEVEMENT_CRITERIA_TYPE_UNK138: + case ACHIEVEMENT_CRITERIA_TYPE_UNK139: + case ACHIEVEMENT_CRITERIA_TYPE_UNK140: + case ACHIEVEMENT_CRITERIA_TYPE_UNK141: + case ACHIEVEMENT_CRITERIA_TYPE_UNK142: + case ACHIEVEMENT_CRITERIA_TYPE_UNK143: + case ACHIEVEMENT_CRITERIA_TYPE_UNK144: + case ACHIEVEMENT_CRITERIA_TYPE_UNK145: + case ACHIEVEMENT_CRITERIA_TYPE_UNK146: + case ACHIEVEMENT_CRITERIA_TYPE_UNK147: + case ACHIEVEMENT_CRITERIA_TYPE_UNK148: + case ACHIEVEMENT_CRITERIA_TYPE_UNK149: + case ACHIEVEMENT_CRITERIA_TYPE_UNK150: 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) { // counter can never complete if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER) @@ -1754,6 +1983,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; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: @@ -1782,9 +2013,6 @@ 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: @@ -1794,7 +2022,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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) @@ -1805,10 +2034,11 @@ 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) @@ -1870,7 +2100,8 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry) 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); @@ -1880,14 +2111,15 @@ 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, uint32 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; - sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue, m_player->GetGUIDLow()); + sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::SetCriteriaProgress(%u, %u) for (%s GUID: "UI64FMTD")", entry->ID, changeValue, GetLogNameForGuid(GetOwner()->GetGUID()), GetOwner()->GetGUID()); CriteriaProgress* progress = GetCriteriaProgress(entry); if (!progress) @@ -1930,38 +2162,28 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, progress->changed = true; progress->date = time(NULL); // set the date to the latest update. + AchievementEntry const* achievement = sAchievementStore.LookupEntry(entry->referredAchievement); 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, sAchievementStore.LookupEntry(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(const AchievementCriteriaEntry* entry) -{ - 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); + if (criteriaComplete && achievement->flags & ACHIEVEMENT_FLAG_SHOW_CRITERIA_MEMBERS && !progress->CompletedGUID) + progress->CompletedGUID = referencePlayer->GetGUID(); - 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()) { @@ -1983,12 +2205,18 @@ 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 = sAchievementStore.LookupEntry((*i)->referredAchievement); @@ -2000,18 +2228,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) { - if ((*i)->timerStartEvent != entry) + if ((*i)->timedCriteriaMiscId != entry) continue; TimedAchievementMap::iterator timedIter = m_timedAchievements.find((*i)->ID); @@ -2027,18 +2256,21 @@ void AchievementMgr::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, } } -void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) +template<class T> +void AchievementMgr<T>::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer) { sLog->outInfo(LOG_FILTER_ACHIEVEMENTSYS, "AchievementMgr::CompletedAchievement(%u)", achievement->ID); // disable for gamemasters with GM-mode enabled - if (m_player->isGameMaster()) + if (_owner->isGameMaster()) return; if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID)) return; - SendAchievementEarned(achievement); + if (!GetOwner()->GetSession()->PlayerLoading()) + SendAchievementEarned(achievement); + CompletedAchievementData& ca = m_completedAchievements[achievement->ID]; ca.date = time(NULL); ca.changed = true; @@ -2048,8 +2280,8 @@ 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); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, NULL, referencePlayer); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points, 0, NULL, referencePlayer); // reward items and titles if any AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement); @@ -2063,16 +2295,16 @@ 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) { - Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetPlayer()) : NULL; + Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetOwner()) : NULL; - int loc_idx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex(); + int loc_idx = GetOwner()->GetSession()->GetSessionDbLocaleIndex(); // subject and text std::string subject = reward->subject; @@ -2098,73 +2330,342 @@ 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); + sLog->outInfo(LOG_FILTER_GENERAL, "AchievementMgr<Guild>::CompletedAchievement(%u)", achievement->ID); + + if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID)) + return; + + 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); + + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, NULL, referencePlayer); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points, 0, NULL, referencePlayer); } -void AchievementMgr::SendRespondInspectAchievements(Player* player) const +struct VisibleAchievementPred +{ + bool operator()(CompletedAchievementMap::value_type const& val) + { + AchievementEntry const* achievement = sAchievementStore.LookupEntry(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 = uint64(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 << uint32(secsToTimeBitFields(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 << uint32(secsToTimeBitFields(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 { - AchievementEntry const* achievement = NULL; - for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter) + WorldPacket data(SMSG_GUILD_ACHIEVEMENT_DATA, m_completedAchievements.size() * (4 + 4) + 4); + data.WriteBits(m_completedAchievements.size(), 23); + for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr) { - // Skip hidden achievements - achievement = sAchievementStore.LookupEntry(iter->first); - if (achievement->flags & ACHIEVEMENT_FLAG_HIDDEN) + data << uint32(secsToTimeBitFields(itr->second.date)); + data << uint32(itr->first); + } + + receiver->GetSession()->SendPacket(&data); +} + +template<class T> +void AchievementMgr<T>::SendAchievementInfo(Player* receiver, uint32 achievementId /*= 0*/) const +{ +} + +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 * (0)); + + 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 << uint32(secsToTimeBitFields(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(iter->first); - *data << uint32(secsToTimeBitFields(iter->second.date)); + data << uint32(itr->first); + data << uint32(secsToTimeBitFields(itr->second.date)); } - *data << int32(-1); - for (CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter) + 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) { - *data << uint32(iter->first); - data->appendPackGUID(iter->second.counter); - data->append(GetPlayer()->GetPackGUID()); - *data << uint32(0); - *data << uint32(secsToTimeBitFields(iter->second.date)); - *data << uint32(0); - *data << uint32(0); + // send empty packet + WorldPacket data(SMSG_GUILD_CRITERIA_DATA, 3); + data.WriteBits(0, 21); + receiver->GetSession()->SendPacket(&data); + return; } - *data << int32(-1); + 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) + { + 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]); + } + + 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*/, Unit* unit, Player* referencePlayer) { if (DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, NULL)) return false; - if (achievement->mapID != -1 && GetPlayer()->GetMapId() != uint32(achievement->mapID)) + if (achievement->mapID != -1 && referencePlayer->GetMapId() != uint32(achievement->mapID)) + return false; + + // don't update already completed criteria + if (IsCompletedCriteria(criteria, achievement)) return false; - if ((achievement->requiredFaction == ACHIEVEMENT_FACTION_HORDE && GetPlayer()->GetTeam() != HORDE) || - (achievement->requiredFaction == ACHIEVEMENT_FACTION_ALLIANCE && GetPlayer()->GetTeam() != ALLIANCE)) + if ((achievement->requiredFaction == ACHIEVEMENT_FACTION_HORDE && referencePlayer->GetTeam() != HORDE) || + (achievement->requiredFaction == ACHIEVEMENT_FACTION_ALLIANCE && referencePlayer->GetTeam() != ALLIANCE)) return false; for (uint32 i = 0; i < MAX_CRITERIA_REQUIREMENTS; ++i) @@ -2175,11 +2676,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: @@ -2187,13 +2688,131 @@ bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, } } - // don't update already completed criteria - if (IsCompletedCriteria(criteria, achievement)) - return false; + // additional conditions + for (int8 i = 0; i < MAX_ADDITIONAL_CRITERIA_CONDITIONS; ++i) + { + if (!criteria->additionalConditionType[i]) + continue; + + uint32 value = criteria->additionalConditionValue[i]; + switch (criteria->additionalConditionType[i]) + { + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER: + if (!unit || !unit->ToPlayer()) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD: + if (!unit || unit->isAlive()) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_MOUNTED: + if (!unit || !unit->IsMounted()) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY: + if (uint32(referencePlayer->GetMap()->GetDifficulty()) != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP: + if (referencePlayer->GetMapId() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_ZONE: + if (referencePlayer->GetZoneId() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA: + if (referencePlayer->GetAreaId() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY: + if (!unit) + return false; + if (const Player* player = unit->ToPlayer()) + if (player->GetTeam() == referencePlayer->GetTeam()) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY: + if (!unit || !unit->ToCreature()) + return false; + if (unit->ToCreature()->GetEntry() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA: + if (!referencePlayer->HasAura(value)) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA: + if (!unit || !unit->HasAura(value)) + return false; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN: + if (ItemTemplate const * itemProto = sObjectMgr->GetItemTemplate(miscValue1)) + if (itemProto->Quality < value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS: + if (ItemTemplate const * itemProto = sObjectMgr->GetItemTemplate(miscValue1)) + if (itemProto->Quality < value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE: + if (referencePlayer->getRace() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS: + if (referencePlayer->getClass() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE: + if (!unit || !unit->ToPlayer()) + break; + if (unit->ToPlayer()->getRace() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS: + if (!unit || !unit->ToPlayer()) + break; + if (unit->ToPlayer()->getClass() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS: + if (referencePlayer->GetGroup() && referencePlayer->GetGroup()->GetMembersCount() >= value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE: + if (!unit || !unit->ToCreature()) + return false; + if (unit->ToCreature()->GetCreatureType() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL: + if (referencePlayer->getLevel() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL: + if (!unit || unit->getLevel() != value) + return false; + break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW: + if (!unit || unit->GetHealthPct() >= value) + return false; + break; + // generic, compare miscValue1 with DBC value + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX: + if (miscValue1 != value) + return false; + break; + default: + break; + } + } return true; } +template class AchievementMgr<Guild>; +template class AchievementMgr<Player>; + //========================================================== void AchievementGlobalMgr::LoadAchievementCriteriaList() { @@ -2205,20 +2824,28 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList() return; } + uint32 criterias = 0; + uint32 guildCriterias = 0; for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId) { AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId); if (!criteria) continue; - m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria); + AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement); + m_AchievementCriteriaListByAchievement[criteria->referredAchievement].push_back(criteria); + if (achievement && achievement->flags & ACHIEVEMENT_FLAG_GUILD) + ++guildCriterias, m_GuildAchievementCriteriasByType[criteria->requiredType].push_back(criteria); + else + ++criterias, m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria); + if (criteria->timeLimit) - m_AchievementCriteriasByTimedType[criteria->timedType].push_back(criteria); + m_AchievementCriteriasByTimedType[criteria->timedCriteriaStartType].push_back(criteria); } - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %lu achievement criteria in %u ms", (unsigned long)m_AchievementCriteriasByType->size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u achievement criteria and %u guild achievement crieteria in %u ms", criterias, guildCriterias, GetMSTimeDiffToNow(oldMSTime)); } void AchievementGlobalMgr::LoadAchievementReferenceList() @@ -2308,89 +2935,6 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData() } while (result->NextRow()); - // post loading checks - for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId) - { - AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId); - if (!criteria) - continue; - - switch (criteria->requiredType) - { - case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: // any cases - break; - case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: - { - AchievementEntry const* achievement = sAchievementStore.LookupEntry(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_FALL_WITHOUT_DYING: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: // any cases - break; - case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: // any cases - break; - 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_EQUIP_EPIC_ITEM: // any cases - break; - case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: // need skip generic cases - if (criteria->do_emote.count == 0) - continue; - break; - case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: // skip statistics - if (criteria->win_duel.duelCount == 0) - continue; - break; - case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: // any cases - break; - case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: // need skip generic cases - if (criteria->loot_type.lootTypeCount != 1) - continue; - break; - case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL: // any cases - break; - case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: - case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // only Children's Week achievements - { - AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement); - if (!achievement) - continue; - if (achievement->categoryId != CATEGORY_CHILDRENS_WEEK) - continue; - break; - } - case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: - break; - default: // type not use DB data, ignore - continue; - } - - if (!GetCriteriaDataSet(criteria) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, entryId, NULL)) - sLog->outError(LOG_FILTER_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); - } - sLog->outInfo(LOG_FILTER_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 c7d838fcb44..bcedbd09901 100755 --- a/src/server/game/Achievements/AchievementMgr.h +++ b/src/server/game/Achievements/AchievementMgr.h @@ -37,6 +37,7 @@ struct CriteriaProgress { uint32 counter; time_t date; // latest update time. + uint64 CompletedGUID; // GUID of the player that completed this criteria (guild achievements) bool changed; }; @@ -46,15 +47,13 @@ enum AchievementCriteriaDataType 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 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 @@ -62,12 +61,10 @@ enum AchievementCriteriaDataType ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE = 17, // min_score max_score player's team win bg and opposition team have team score in range ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT = 18, // 0 0 maker instance script call for check current criteria requirements fit 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 }; #define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 22 // maximum value in AchievementCriteriaDataType enum - class Player; class Unit; @@ -94,11 +91,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 @@ -106,11 +98,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 { @@ -127,11 +114,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 { @@ -165,12 +147,7 @@ struct AchievementCriteriaData uint32 item_level; uint32 item_quality; } equipped_item; - // ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20 - struct - { - uint32 mapId; - } map_id; - // ... + // raw struct { uint32 value1; @@ -233,6 +210,7 @@ typedef std::map<uint32, AchievementRewardLocale> AchievementRewardLocales; struct CompletedAchievementData { time_t date; + std::set<uint64> guids; bool changed; }; @@ -243,10 +221,11 @@ class Unit; class Player; class WorldPacket; +template<class T> class AchievementMgr { public: - AchievementMgr(Player* player); + AchievementMgr(T* owner); ~AchievementMgr(); void Reset(); @@ -254,13 +233,14 @@ class AchievementMgr 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 UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, Unit* 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 @@ -270,15 +250,15 @@ class AchievementMgr 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, uint32 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, Unit* unit, Player* referencePlayer); + void SendPacket(WorldPacket* data) const; - Player* m_player; + T* _owner; CriteriaProgressMap m_criteriaProgress; CompletedAchievementMap m_completedAchievements; typedef std::map<uint32, uint32> TimedAchievementMap; @@ -292,9 +272,9 @@ class AchievementGlobalMgr ~AchievementGlobalMgr() {} public: - 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 @@ -342,6 +322,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(); @@ -353,9 +351,13 @@ 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]; + // store achievement criterias by achievement to speed up lookup AchievementCriteriaListByAchievement m_AchievementCriteriaListByAchievement; + // store achievements by referenced achievement id to speed up lookup AchievementListByReferencedId m_AchievementListByReferencedId; diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index 84b5513b659..4c934991d44 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -29,7 +29,7 @@ #include "AuctionHouseMgr.h" #include "Item.h" #include "Language.h" -#include "Logging/Log.h" +#include "Log.h" #include <vector> enum eAuctionHouse @@ -89,7 +89,7 @@ uint32 AuctionHouseMgr::GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 //does not clear ram void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction& trans) { - Item* pItem = GetAItem(auction->item_guidlow); + Item* pItem = GetAItem(auction->itemGUIDLow); if (!pItem) return; @@ -143,9 +143,9 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction& if (bidder) { - bidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, bidder_guid, 0, 0, auction->item_template); + bidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, bidder_guid, 0, 0, auction->itemEntry); // FIXME: for offline player need also - bidder->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS, 1); + bidder->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS, 1); } MailDraft(auction->BuildAuctionMailSubject(AUCTION_WON), AuctionEntry::BuildAuctionMailBody(auction->owner, auction->bid, auction->buyout, 0, 0)) @@ -179,8 +179,8 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry* auction, SQLTransa //FIXME: what do if owner offline if (owner) { - owner->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS, profit); - owner->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD, auction->bid); + owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS, profit); + owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD, auction->bid); //send auction owner notification, bidder must be current! owner->GetSession()->SendAuctionOwnerNotification(auction); } @@ -195,7 +195,7 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry* auction, SQLTransa void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry* auction, SQLTransaction& trans) { //return an item in auction to its owner by mail - Item* pItem = GetAItem(auction->item_guidlow); + Item* pItem = GetAItem(auction->itemGUIDLow); if (!pItem) return; @@ -228,7 +228,7 @@ void AuctionHouseMgr::SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 new if (oldBidder || oldBidder_accId) { if (oldBidder && newBidder) - oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, newBidder->GetGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template); + oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, newBidder->GetGUID(), newPrice, auction->GetAuctionOutBid(), auction->itemEntry); MailDraft(auction->BuildAuctionMailSubject(AUCTION_OUTBIDDED), AuctionEntry::BuildAuctionMailBody(auction->owner, auction->bid, auction->buyout, auction->deposit, auction->GetAuctionCut())) .AddMoney(auction->bid) @@ -237,7 +237,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); @@ -246,6 +246,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)) @@ -275,17 +278,17 @@ void AuctionHouseMgr::LoadAuctionItems() Field* fields = result->Fetch(); uint32 item_guid = fields[11].GetUInt32(); - uint32 item_template = fields[12].GetUInt32(); + uint32 itemEntry = fields[12].GetUInt32(); - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item_template); + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry); if (!proto) { - sLog->outError(LOG_FILTER_GENERAL, "AuctionHouseMgr::LoadAuctionItems: Unknown item (GUID: %u id: #%u) in auction, skipped.", item_guid, item_template); + sLog->outError(LOG_FILTER_GENERAL, "AuctionHouseMgr::LoadAuctionItems: Unknown item (GUID: %u id: #%u) in auction, skipped.", item_guid, itemEntry); continue; } Item* item = NewItemOrBag(proto); - if (!item->LoadFromDB(item_guid, 0, fields, item_template)) + if (!item->LoadFromDB(item_guid, 0, fields, itemEntry)) { delete item; continue; @@ -411,7 +414,7 @@ void AuctionHouseObject::AddAuction(AuctionEntry* auction) sScriptMgr->OnAuctionAdd(this, auction); } -bool AuctionHouseObject::RemoveAuction(AuctionEntry* auction, uint32 /*item_template*/) +bool AuctionHouseObject::RemoveAuction(AuctionEntry* auction, uint32 /*itemEntry*/) { bool wasInMap = AuctionsMap.erase(auction->Id) ? true : false; @@ -465,14 +468,14 @@ void AuctionHouseObject::Update() sScriptMgr->OnAuctionSuccessful(this, auction); } - uint32 item_template = auction->item_template; + uint32 itemEntry = auction->itemEntry; ///- In any case clear the auction auction->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); - RemoveAuction(auction, item_template); - sAuctionMgr->RemoveAItem(auction->item_guidlow); + RemoveAuction(auction, itemEntry); + sAuctionMgr->RemoveAItem(auction->itemGUIDLow); } while (result->NextRow()); } @@ -518,7 +521,7 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr) { AuctionEntry* Aentry = itr->second; - Item* item = sAuctionMgr->GetAItem(Aentry->item_guidlow); + Item* item = sAuctionMgr->GetAItem(Aentry->itemGUIDLow); if (!item) continue; @@ -569,7 +572,7 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player if (itemRandProp) { - char* const* temp = itemRandProp->nameSuffix; + char* temp = itemRandProp->nameSuffix; //char* temp = itemRandProp->nameSuffix; // dbc local name @@ -601,16 +604,16 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player //this function inserts to WorldPacket auction's data bool AuctionEntry::BuildAuctionInfo(WorldPacket& data) const { - Item* item = sAuctionMgr->GetAItem(item_guidlow); + Item* item = sAuctionMgr->GetAItem(itemGUIDLow); if (!item) { - sLog->outError(LOG_FILTER_GENERAL, "AuctionEntry::BuildAuctionInfo: Auction %u has a non-existent item: %u", Id, item_guidlow); + sLog->outError(LOG_FILTER_GENERAL, "AuctionEntry::BuildAuctionInfo: Auction %u has a non-existent item: %u", Id, itemGUIDLow); return false; } 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))); @@ -623,13 +626,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; } @@ -658,7 +661,7 @@ void AuctionEntry::SaveToDB(SQLTransaction& trans) const PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AUCTION); stmt->setUInt32(0, Id); stmt->setUInt32(1, auctioneer); - stmt->setUInt32(2, item_guidlow); + stmt->setUInt32(2, itemGUIDLow); stmt->setUInt32(3, owner); stmt->setInt32 (4, int32(buyout)); stmt->setUInt64(5, uint64(expire_time)); @@ -673,8 +676,8 @@ bool AuctionEntry::LoadFromDB(Field* fields) { Id = fields[0].GetUInt32(); auctioneer = fields[1].GetUInt32(); - item_guidlow = fields[2].GetUInt32(); - item_template = fields[3].GetUInt32(); + itemGUIDLow = fields[2].GetUInt32(); + itemEntry = fields[3].GetUInt32(); itemCount = fields[4].GetUInt32(); owner = fields[5].GetUInt32(); buyout = fields[6].GetUInt32(); @@ -707,10 +710,10 @@ bool AuctionEntry::LoadFromDB(Field* fields) } // check if sold item exists for guid - // and item_template in fact (GetAItem will fail if problematic in result check in AuctionHouseMgr::LoadAuctionItems) - if (!sAuctionMgr->GetAItem(item_guidlow)) + // and itemEntry in fact (GetAItem will fail if problematic in result check in AuctionHouseMgr::LoadAuctionItems) + if (!sAuctionMgr->GetAItem(itemGUIDLow)) { - sLog->outError(LOG_FILTER_GENERAL, "Auction %u has not a existing item : %u", Id, item_guidlow); + sLog->outError(LOG_FILTER_GENERAL, "Auction %u has not a existing item : %u", Id, itemGUIDLow); return false; } return true; @@ -795,8 +798,8 @@ bool AuctionEntry::LoadFromFieldList(Field* fields) Id = fields[0].GetUInt32(); auctioneer = fields[1].GetUInt32(); - item_guidlow = fields[2].GetUInt32(); - item_template = fields[3].GetUInt32(); + itemGUIDLow = fields[2].GetUInt32(); + itemEntry = fields[3].GetUInt32(); itemCount = fields[4].GetUInt32(); owner = fields[5].GetUInt32(); buyout = fields[6].GetUInt32(); @@ -835,7 +838,7 @@ bool AuctionEntry::LoadFromFieldList(Field* fields) std::string AuctionEntry::BuildAuctionMailSubject(MailAuctionAnswers response) const { std::ostringstream strm; - strm << item_template << ":0:" << response << ':' << Id << ':' << itemCount; + strm << itemEntry << ":0:" << response << ':' << Id << ':' << itemCount; return strm.str(); } diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h index 049440f99d0..b7080101588 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.h +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h @@ -34,11 +34,15 @@ class WorldPacket; enum AuctionError { - AUCTION_OK = 0, - AUCTION_INTERNAL_ERROR = 2, - AUCTION_NOT_ENOUGHT_MONEY = 3, - AUCTION_ITEM_NOT_FOUND = 4, - CANNOT_BID_YOUR_AUCTION_ERROR = 10 + ERR_AUCTION_OK = 0, + ERR_AUCTION_INVENTORY = 1, + ERR_AUCTION_DATABASE_ERROR = 2, + ERR_AUCTION_NOT_ENOUGHT_MONEY = 3, + ERR_AUCTION_ITEM_NOT_FOUND = 4, + ERR_AUCTION_HIGHER_BID = 5, + ERR_AUCTION_BID_INCREMENT = 7, + ERR_AUCTION_BID_OWN = 10, + ERR_RESTRICTED_ACCOUNT = 13, }; enum AuctionAction @@ -63,8 +67,8 @@ struct AuctionEntry { uint32 Id; uint32 auctioneer; // creature low guid - uint32 item_guidlow; - uint32 item_template; + uint32 itemGUIDLow; + uint32 itemEntry; uint32 itemCount; uint32 owner; uint32 startbid; //maybe useless @@ -118,7 +122,7 @@ class AuctionHouseObject void AddAuction(AuctionEntry* auction); - bool RemoveAuction(AuctionEntry* auction, uint32 item_template); + bool RemoveAuction(AuctionEntry* auction, uint32 itemEntry); void Update(); @@ -166,7 +170,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 f074975c6a5..7f701f541a1 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -65,7 +65,7 @@ Battlefield::~Battlefield() // Called when a player enters the zone void Battlefield::HandlePlayerEnterZone(Player* player, uint32 /*zone*/) { - // If battle is started, + // If battle is started, // If not full of players > invite player to join the war // If full of players > announce to player that BF is full and kick him after a few second if he desn't leave if (IsWarTime()) @@ -885,9 +885,9 @@ GuidSet::iterator BfCapturePoint::HandlePlayerLeave(Player* player) { if (m_capturePoint) player->SendUpdateWorldState(m_capturePoint->GetGOInfo()->capturePoint.worldState1, 0); - + GuidSet::iterator current = m_activePlayers[player->GetTeamId()].find(player->GetGUID()); - + if (current == m_activePlayers[player->GetTeamId()].end()) return current; // return end() diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h index 5fa8d6b1bc8..07daf33d431 100644 --- a/src/server/game/Battlefield/Battlefield.h +++ b/src/server/game/Battlefield/Battlefield.h @@ -35,7 +35,7 @@ enum BattlefieldTypes enum BattlefieldIDs { - BATTLEFIELD_BATTLEID_WG = 1, // Wintergrasp battle + BATTLEFIELD_BATTLEID_WG = 1, // Wintergrasp battle }; enum BattlefieldObjectiveStates diff --git a/src/server/game/Battlefield/BattlefieldHandler.cpp b/src/server/game/Battlefield/BattlefieldHandler.cpp index 09c6f18f796..b852082d582 100644 --- a/src/server/game/Battlefield/BattlefieldHandler.cpp +++ b/src/server/game/Battlefield/BattlefieldHandler.cpp @@ -32,7 +32,7 @@ //Param3:(time) Time in second that the player have for accept void WorldSession::SendBfInvitePlayerToWar(uint32 BattleId, uint32 ZoneId, uint32 p_time) { - //Send packet + //Send packet WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, 12); data << uint32(BattleId); data << uint32(ZoneId); @@ -65,13 +65,13 @@ void WorldSession::SendBfQueueInviteResponse(uint32 BattleId,uint32 ZoneId, bool WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, 11); data << uint32(BattleId); data << uint32(ZoneId); - data << uint8((CanQueue ? 1 : 0)); //Accepted //0 you cannot queue wg //1 you are queued + 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); } -//This is call when player accept to join war +//This is call when player accept to join war //Param1:(BattleId) the BattleId of Bf void WorldSession::SendBfEntered(uint32 BattleId) { diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h index d8ad2c09e59..2528ab27141 100755 --- a/src/server/game/Battlegrounds/ArenaTeam.h +++ b/src/server/game/Battlegrounds/ArenaTeam.h @@ -57,7 +57,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 diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp index 55de445345b..9365172a4ca 100644 --- a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp +++ b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp @@ -149,16 +149,17 @@ void ArenaTeamMgr::DistributeArenaPoints() if (ArenaTeam* at = teamItr->second) at->UpdateArenaPointsHelper(PlayerPoints); + /* SQLTransaction trans = CharacterDatabase.BeginTransaction(); + // Cycle that gives points to all players 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); + player->ModifyConquestPoints(playerItr->second, &trans); else // Update database { stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ARENA_POINTS); @@ -169,6 +170,7 @@ void ArenaTeamMgr::DistributeArenaPoints() } CharacterDatabase.CommitTransaction(trans); + */ PlayerPoints.clear(); diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index eb5f3459edf..98b95b5d32b 100755 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -34,6 +34,8 @@ #include "SpellAuras.h" #include "SpellAuraEffects.h" #include "Util.h" +#include "Guild.h" +#include "GuildMgr.h" namespace Trinity { @@ -799,6 +801,7 @@ void Battleground::EndBattleground(uint32 winner) } } + bool guildAwarded = false; uint8 aliveWinners = GetAlivePlayersCountByTeam(winner); for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { @@ -851,7 +854,7 @@ void Battleground::EndBattleground(uint32 winner) { // update achievement BEFORE personal rating update uint32 rating = player->GetArenaPersonalRating(winner_arena_team->GetSlot()); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1); winner_arena_team->MemberWon(player, loser_matchmaker_rating, winner_matchmaker_change); } @@ -866,7 +869,10 @@ void Battleground::EndBattleground(uint32 winner) uint32 winner_kills = player->GetRandomWinner() ? BG_REWARD_WINNER_HONOR_LAST : BG_REWARD_WINNER_HONOR_FIRST; uint32 loser_kills = player->GetRandomWinner() ? BG_REWARD_LOSER_HONOR_LAST : BG_REWARD_LOSER_HONOR_FIRST; - uint32 winner_arena = player->GetRandomWinner() ? BG_REWARD_WINNER_ARENA_LAST : 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); // Reward winner team if (team == winner) @@ -874,13 +880,24 @@ void Battleground::EndBattleground(uint32 winner) if (IsRandom() || BattlegroundMgr::IsBGWeekend(GetTypeID())) { UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(winner_kills)); - if (CanAwardArenaPoints()) - player->ModifyArenaPoints(winner_arena); + /*if (CanAwardArenaPoints()) + player->ModifyConquestPoints(player->GetRandomWinner() ? BG_REWARD_WINNER_ARENA_LAST : BG_REWARD_WINNER_ARENA_FIRST);*/ if (!player->GetRandomWinner()) player->SetRandomWinner(true); } - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1); + if (!guildAwarded) + { + guildAwarded = true; + if (uint32 guildId = GetBgMap()->GetOwnerGuildId(player->GetTeam())) + if (Guild* guild = sGuildMgr->GetGuildById(guildId)) + { + guild->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1, 0, NULL, player); + if (isArena() && isRated() && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team) + guild->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, std::max<uint32>(winner_arena_team->GetRating(), 1), 0, NULL, player); + } + } } else { @@ -899,7 +916,7 @@ void Battleground::EndBattleground(uint32 winner) BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType()); player->GetSession()->SendPacket(&data); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); } if (isArena() && isRated() && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team) @@ -1643,6 +1660,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; } @@ -1703,6 +1721,8 @@ void Battleground::SendWarningToAll(int32 entry, ...) data << (uint32)(msg.length() + 1); data << msg.c_str(); data << (uint8)0; + data << (float)0.0f; // added in 4.2.0, unk + data << (uint8)0; // added in 4.2.0, unk for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER))) if (player->GetSession()) diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 01dfbb23033..234cda4105c 100755 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -177,10 +177,12 @@ 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 }; diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 0b107983379..86b06de2cec 100755 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -37,6 +37,8 @@ #include "BattlegroundRV.h" #include "BattlegroundIC.h" #include "BattlegroundRB.h" +#include "BattlegroundTP.h" +#include "BattlegroundBFG.h" #include "Chat.h" #include "Map.h" #include "MapInstanced.h" @@ -339,6 +341,16 @@ void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg) *data << uint32(0x00000002); // count of next fields *data << uint32(((BattlegroundICScore*)itr2->second)->BasesAssaulted); // bases asssulted *data << uint32(((BattlegroundICScore*)itr2->second)->BasesDefended); // bases defended + case 726: + *data << uint32(0x00000002); // count of next fields + *data << uint32(((BattlegroundTPScore*)itr2->second)->FlagCaptures); // flag captures + *data << uint32(((BattlegroundTPScore*)itr2->second)->FlagReturns); // flag returns + break; + case 761: + *data << uint32(0x00000002); // count of next fields + *data << uint32(((BattlegroundBFGScore*)itr2->second)->BasesAssaulted); // bases asssulted + *data << uint32(((BattlegroundBFGScore*)itr2->second)->BasesDefended); // bases defended + break; default: *data << uint32(0); break; @@ -375,6 +387,14 @@ void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg) *data << uint32(((BattlegroundICScore*)itr2->second)->BasesAssaulted); // bases asssulted *data << uint32(((BattlegroundICScore*)itr2->second)->BasesDefended); // bases defended break; + case BATTLEGROUND_TP: + *data << uint32(0x00000002); // count of next fields + *data << uint32(((BattlegroundTPScore*)itr2->second)->FlagCaptures); // flag captures + *data << uint32(((BattlegroundTPScore*)itr2->second)->FlagReturns); // flag returns + case BATTLEGROUND_BFG: + *data << uint32(0x00000002); // count of next fields + *data << uint32(((BattlegroundBFGScore*)itr2->second)->BasesAssaulted); // bases asssulted + *data << uint32(((BattlegroundBFGScore*)itr2->second)->BasesDefended); // bases defended case BATTLEGROUND_NA: case BATTLEGROUND_BE: case BATTLEGROUND_AA: @@ -595,6 +615,12 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId bgTypeId 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: bg = new BattlegroundRB(*(BattlegroundRB*)bg_template); break; @@ -643,6 +669,8 @@ uint32 BattlegroundMgr::CreateBattleground(CreateBattlegroundData& data) case BATTLEGROUND_DS: bg = new BattlegroundDS; break; case BATTLEGROUND_RV: bg = new BattlegroundRV; break; case BATTLEGROUND_IC: bg = new BattlegroundIC; break; + case BATTLEGROUND_TP: bg = new BattlegroundTP; break; + case BATTLEGROUND_BFG: bg = new BattlegroundBFG; break; case BATTLEGROUND_RB: bg = new BattlegroundRB; break; default: bg = new Battleground; @@ -774,7 +802,8 @@ void BattlegroundMgr::CreateInitialBattlegrounds() selectionWeight = fields[10].GetUInt8(); data.scriptId = sObjectMgr->GetScriptId(fields[11].GetCString()); - data.BattlegroundName = bl->name[sWorld->GetDefaultDbcLocale()]; + + //data.BattlegroundName = bl->name[sWorld->GetDefaultDbcLocale()]; data.MapID = bl->mapid[0]; if (!CreateBattleground(data)) @@ -812,7 +841,7 @@ void BattlegroundMgr::InitAutomaticArenaPointDistribution() sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Automatic Arena Point Distribution initialized."); } -void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere) +void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId) { if (!player) return; @@ -825,8 +854,8 @@ void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, uint64 guid loser_kills = Trinity::Honor::hk_honor_at_level(player->getLevel(), float(loser_kills)); data->Initialize(SMSG_BATTLEFIELD_LIST); + // TODO: Fix guid *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 @@ -933,6 +962,10 @@ BattlegroundQueueTypeId BattlegroundMgr::BGQueueTypeId(BattlegroundTypeId bgType return BATTLEGROUND_QUEUE_SA; 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_AA: @@ -973,6 +1006,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: @@ -1112,6 +1149,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; } } @@ -1126,6 +1165,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; } } diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h index 10a49408c06..4edad4da742 100755 --- a/src/server/game/Battlegrounds/BattlegroundMgr.h +++ b/src/server/game/Battlegrounds/BattlegroundMgr.h @@ -68,7 +68,7 @@ class BattlegroundMgr /* Packet Building */ void BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, Player* player); void BuildPlayerLeftBattlegroundPacket(WorldPacket* data, uint64 guid); - void BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere); + void BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId); void BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result); void BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value); void BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp index 8b2543f20ff..fa36f0b02aa 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -681,11 +681,11 @@ void BattlegroundAB::UpdatePlayerScore(Player* Source, uint32 type, uint32 value { case SCORE_BASES_ASSAULTED: ((BattlegroundABScore*)itr->second)->BasesAssaulted += value; - Source->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_ASSAULT_BASE); + Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_ASSAULT_BASE); break; case SCORE_BASES_DEFENDED: ((BattlegroundABScore*)itr->second)->BasesDefended += value; - Source->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_DEFEND_BASE); + Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_DEFEND_BASE); break; default: Battleground::UpdatePlayerScore(Source, type, value, doAddHonor); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp index 96fa899a746..37072866238 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp @@ -540,19 +540,19 @@ void BattlegroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value { case SCORE_GRAVEYARDS_ASSAULTED: ((BattlegroundAVScore*)itr->second)->GraveyardsAssaulted += value; - Source->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_GRAVEYARD); + Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_GRAVEYARD); break; case SCORE_GRAVEYARDS_DEFENDED: ((BattlegroundAVScore*)itr->second)->GraveyardsDefended += value; - Source->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_GRAVEYARD); + Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_GRAVEYARD); break; case SCORE_TOWERS_ASSAULTED: ((BattlegroundAVScore*)itr->second)->TowersAssaulted += value; - Source->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_TOWER); + Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_TOWER); break; case SCORE_TOWERS_DEFENDED: ((BattlegroundAVScore*)itr->second)->TowersDefended += value; - Source->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_TOWER); + Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_TOWER); break; case SCORE_MINES_CAPTURED: ((BattlegroundAVScore*)itr->second)->MinesCaptured += value; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp new file mode 100644 index 00000000000..52af3e23e11 --- /dev/null +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008-2012 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..35c9bef8b17 --- /dev/null +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008-2012 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" + +class BattlegroundBFGScore : public BattlegroundScore +{ + public: + BattlegroundBFGScore(): BasesAssaulted(0), BasesDefended(0) {}; + virtual ~BattlegroundBFGScore() {}; + + 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 9bab15d9b5e..35ea94ba607 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -816,7 +816,7 @@ void BattlegroundEY::UpdatePlayerScore(Player* Source, uint32 type, uint32 value { case SCORE_FLAG_CAPTURES: // flags captured ((BattlegroundEYScore*)itr->second)->FlagCaptures += value; - Source->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, EY_OBJECTIVE_CAPTURE_FLAG); + Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, EY_OBJECTIVE_CAPTURE_FLAG); break; default: Battleground::UpdatePlayerScore(Source, type, value, doAddHonor); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index 90571dfb758..ca2c3357a42 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -75,7 +75,7 @@ void BattlegroundIC::SendTransportInit(Player* player) if (!gunshipAlliance || !gunshipHorde) return; - UpdateData transData; + UpdateData transData(player->GetMapId()); gunshipAlliance->BuildCreateUpdateBlockForPlayer(&transData, player); gunshipHorde->BuildCreateUpdateBlockForPlayer(&transData, player); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp index 58f7cabc72d..f7f4df61be6 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp @@ -273,7 +273,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); @@ -912,8 +912,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); @@ -927,7 +928,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/BattlegroundTP.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp new file mode 100644 index 00000000000..5a19dff589f --- /dev/null +++ b/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008-2012 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..45be413e5cf --- /dev/null +++ b/src/server/game/Battlegrounds/Zones/BattlegroundTP.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008-2012 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" + +class BattlegroundTPScore : public BattlegroundScore +{ + public: + BattlegroundTPScore() : FlagCaptures(0), FlagReturns(0) {}; + virtual ~BattlegroundTPScore() {}; + + 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 8df6f93a082..d2f5d43c187 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -773,11 +773,11 @@ void BattlegroundWS::UpdatePlayerScore(Player* Source, uint32 type, uint32 value { case SCORE_FLAG_CAPTURES: // flags captured ((BattlegroundWGScore*)itr->second)->FlagCaptures += value; - Source->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_CAPTURE_FLAG); + Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_CAPTURE_FLAG); break; case SCORE_FLAG_RETURNS: // flags returned ((BattlegroundWGScore*)itr->second)->FlagReturns += value; - Source->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_RETURN_FLAG); + Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_RETURN_FLAG); break; default: Battleground::UpdatePlayerScore(Source, type, value, doAddHonor); diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index 68ae2d8ea38..874332d2364 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -134,7 +134,6 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Addons ${CMAKE_CURRENT_SOURCE_DIR}/AI ${CMAKE_CURRENT_SOURCE_DIR}/AI/CoreAI - ${CMAKE_CURRENT_SOURCE_DIR}/AI/EventAI ${CMAKE_CURRENT_SOURCE_DIR}/AI/ScriptedAI ${CMAKE_CURRENT_SOURCE_DIR}/AI/SmartScripts ${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouse diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h index 9564dbb381e..503bbc57c69 100755 --- a/src/server/game/Chat/Channels/Channel.h +++ b/src/server/game/Chat/Channels/Channel.h @@ -48,8 +48,8 @@ enum ChatNotify CHAT_MODE_CHANGE_NOTICE = 0x0C, //? CHAT_ANNOUNCEMENTS_ON_NOTICE = 0x0D, //+ "[%s] Channel announcements enabled by %s."; CHAT_ANNOUNCEMENTS_OFF_NOTICE = 0x0E, //+ "[%s] Channel announcements disabled by %s."; - // CHAT_MODERATION_ON_NOTICE = 0x0F, //+ "[%s] Channel moderation enabled by %s."; - // CHAT_MODERATION_OFF_NOTICE = 0x10, //+ "[%s] Channel moderation disabled by %s."; + CHAT_MODERATION_ON_NOTICE = 0x0F, //+ "[%s] Channel moderation enabled by %s."; + CHAT_MODERATION_OFF_NOTICE = 0x10, //+ "[%s] Channel moderation disabled by %s."; CHAT_MUTED_NOTICE = 0x11, //+ "[%s] You do not have permission to speak."; CHAT_PLAYER_KICKED_NOTICE = 0x12, //? "[%s] Player %s kicked by %s."; CHAT_BANNED_NOTICE = 0x13, //+ "[%s] You are banned from that channel."; diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index b5bad419c98..c4ea71f7c4e 100755 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -621,7 +621,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd) } //Note: target_guid used only in CHAT_MSG_WHISPER_INFORM mode (in this case channelName ignored) -void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit* speaker) +void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit* speaker, const char* addonPrefix /*= NULL*/) { uint32 messageLength = (message ? strlen(message) : 0) + 1; @@ -675,6 +675,13 @@ void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint *data << uint32(messageLength); *data << message; *data << uint8(0); + + if (type == CHAT_MSG_RAID_BOSS_WHISPER || type == CHAT_MSG_RAID_BOSS_EMOTE) + { + *data << float(0.0f); // Added in 4.2.0, unk + *data << uint8(0); // Added in 4.2.0, unk + } + return; } default: @@ -690,9 +697,16 @@ void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint { ASSERT(channelName); *data << channelName; + *data << uint64(target_guid); } + else if (type == uint8(CHAT_MSG_ADDON)) + { + ASSERT(addonPrefix); + *data << addonPrefix; + } + else + *data << uint64(target_guid); - *data << uint64(target_guid); *data << uint32(messageLength); *data << message; if (session != 0 && type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_DND && type != CHAT_MSG_AFK) diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index 269ebdd1d2f..c0560ee0e27 100755..100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -51,7 +51,7 @@ class ChatHandler explicit ChatHandler(Player* player) : m_session(player->GetSession()) {} virtual ~ChatHandler() {} - static void FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit* speaker); + static void FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit* speaker, const char* addonPrefix = NULL); void FillMessageData(WorldPacket* data, uint8 type, uint32 language, uint64 target_guid, const char* message) { diff --git a/src/server/game/Chat/ChatLink.cpp b/src/server/game/Chat/ChatLink.cpp index d26f937c43d..6860426c3eb 100644 --- a/src/server/game/Chat/ChatLink.cpp +++ b/src/server/game/Chat/ChatLink.cpp @@ -165,7 +165,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()) @@ -181,7 +181,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) @@ -304,30 +304,21 @@ 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; - memcpy(buffer, buffer + skillLineNameLength + 2, spellNameLength + 1); - } + // found the prefix, remove it to perform spellname validation below + // -2 = strlen(": ") + uint32 spellNameLength = strlen(buffer) - skillLineNameLength - 2; + memcpy(buffer, buffer + skillLineNameLength + 2, spellNameLength + 1); } } - bool res = false; - for (uint8 i = 0; i < TOTAL_LOCALES; ++i) - if (*_spell->SpellName[i] && strcmp(_spell->SpellName[i], buffer) == 0) - { - res = true; - break; - } + if (*_spell->SpellName && strcmp(_spell->SpellName, buffer) == 0) + return true; - if (!res) - sLog->outDebug(LOG_FILTER_CHATSYS, "ChatHandler::isValidChatMessage('%s'): linked spell (id: %u) name wasn't found in any localization", context, _spell->Id); - return res; + sLog->outDebug(LOG_FILTER_CHATSYS, "ChatHandler::isValidChatMessage('%s'): linked spell (id: %u) name wasn't found in any localization", context, _spell->Id); + return false; } // |color|Hachievement:achievement_id:player_guid:0:0:0:0:0:0:0:0|h[name]|h|r @@ -379,17 +370,11 @@ bool AchievementChatLink::ValidateName(char* buffer, const char* context) { ChatLink::ValidateName(buffer, context); - bool res = false; - for (uint8 i = 0; i < TOTAL_LOCALES; ++i) - if (*_achievement->name[i] && strcmp(_achievement->name[i], buffer) == 0) - { - res = true; - break; - } + if (*_achievement->name && strcmp(_achievement->name, buffer) == 0) + return true; - if (!res) - sLog->outDebug(LOG_FILTER_CHATSYS, "ChatHandler::isValidChatMessage('%s'): linked achievement (id: %u) name wasn't found in any localization", context, _achievement->ID); - return res; + sLog->outDebug(LOG_FILTER_CHATSYS, "ChatHandler::isValidChatMessage('%s'): linked achievement (id: %u) name wasn't found in any localization", context, _achievement->ID); + return false; } // |color|Htrade:spell_id:cur_value:max_value:player_guid:base64_data|h[name]|h|r diff --git a/src/server/game/Chat/ChatLink.h b/src/server/game/Chat/ChatLink.h index 392d28aca54..2301dc09f29 100644 --- a/src/server/game/Chat/ChatLink.h +++ b/src/server/game/Chat/ChatLink.h @@ -61,7 +61,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 87853a53b6c..ea2e8099aff 100755 --- a/src/server/game/Combat/ThreatManager.cpp +++ b/src/server/game/Combat/ThreatManager.cpp @@ -420,7 +420,7 @@ void ThreatManager::doAddThreat(Unit* victim, float threat) Unit* redirectTarget = victim->GetMisdirectionTarget(); if (redirectTarget) if (Aura* glyphAura = redirectTarget->GetAura(63326)) // Glyph of Vigilance - reducedThreadPercent += glyphAura->GetSpellInfo()->Effects[0].CalcValue(); + reducedThreadPercent += glyphAura->GetSpellInfo()->Effects[0].CalcValue(glyphAura->GetCaster()); float reducedThreat = threat * reducedThreadPercent / 100.0f; threat -= reducedThreat; diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 7bb28556514..ab3c6aba791 100755 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -28,7 +28,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); @@ -712,7 +712,7 @@ void ConditionMgr::LoadConditions(bool isReload) if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 conditions. DB table `conditions` is empty!"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 conditions. DB table `conditions` is empty!"); return; } diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp new file mode 100644 index 00000000000..2e1c25ced39 --- /dev/null +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -0,0 +1,112 @@ +/* + * 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 "Log.h" +#include "SharedDefines.h" +#include "SpellMgr.h" +#include "DB2fmt.h" + +#include <map> + +DB2Storage <ItemEntry> sItemStore(Itemfmt); +DB2Storage <ItemCurrencyCostEntry> sItemCurrencyCostStore(ItemCurrencyCostfmt); +DB2Storage <ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt); +DB2Storage <ItemSparseEntry> sItemSparseStore (ItemSparsefmt); + +typedef std::list<std::string> StoreProblemList1; + +uint32 DB2FilesCount = 0; + +static bool LoadDB2_assert_print(uint32 fsize,uint32 rsize, const std::string& filename) +{ + sLog->outError(LOG_FILTER_GENERAL, "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; +} + +struct LocalDB2Data +{ + LocalDB2Data(LocaleConstant loc) : defaultLocale(loc), availableDb2Locales(0xFFFFFFFF) {} + + LocaleConstant defaultLocale; + + // bitmasks for index of fullLocaleNameList + uint32 availableDb2Locales; +}; + +template<class T> +inline void LoadDB2(StoreProblemList1& errlist, DB2Storage<T>& storage, const std::string& db2_path, const std::string& 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())) + { + // sort problematic db2 to (1) non compatible and (2) nonexistent + if (FILE * f = fopen(db2_filename.c_str(), "rb")) + { + char buf[100]; + snprintf(buf, 100,"(exist, but have %d fields instead " SIZEFMTD ") Wrong client version DBC file?", storage.GetFieldCount(), strlen(storage.GetFormat())); + errlist.push_back(db2_filename + buf); + fclose(f); + } + else + errlist.push_back(db2_filename); + } +} + +void LoadDB2Stores(const std::string& dataPath) +{ + std::string db2Path = dataPath + "dbc/"; + + StoreProblemList1 bad_db2_files; + + LoadDB2(bad_db2_files, sItemStore, db2Path, "Item.db2"); + LoadDB2(bad_db2_files, sItemCurrencyCostStore, db2Path, "ItemCurrencyCost.db2"); + LoadDB2(bad_db2_files, sItemSparseStore, db2Path, "Item-sparse.db2"); + LoadDB2(bad_db2_files, sItemExtendedCostStore, db2Path, "ItemExtendedCost.db2"); + // error checks + if (bad_db2_files.size() >= DB2FilesCount) + { + sLog->outError(LOG_FILTER_GENERAL, "\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"; + + sLog->outError(LOG_FILTER_GENERAL, "\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) + { + sLog->outError(LOG_FILTER_GENERAL, "Please extract correct db2 files from client 4.3.4 15595."); + exit(1); + } + + sLog->outInfo(LOG_FILTER_GENERAL, ">> Initialized %d DB2 data stores.", DB2FilesCount); +} diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h new file mode 100644 index 00000000000..6cf719da70b --- /dev/null +++ b/src/server/game/DataStores/DB2Stores.h @@ -0,0 +1,34 @@ +/* + * 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 "Common.h" +#include "DB2Store.h" +#include "DB2Structure.h" + +#include <list> + +extern DB2Storage <ItemEntry> sItemStore; +extern DB2Storage <ItemCurrencyCostEntry> sItemCurrencyCostStore; +extern DB2Storage <ItemExtendedCostEntry> sItemExtendedCostStore; +extern DB2Storage <ItemSparseEntry> sItemSparseStore; + +void LoadDB2Stores(const std::string& dataPath); + +#endif
\ No newline at end of file diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h new file mode 100644 index 00000000000..386e8546236 --- /dev/null +++ b/src/server/game/DataStores/DB2Structure.h @@ -0,0 +1,158 @@ +/* + * 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 "DBCEnums.h" +#include "Define.h" +#include "Path.h" +#include "Util.h" +#include "Vehicle.h" +#include "SharedDefines.h" +#include "ItemPrototype.h" + +#include <map> +#include <set> +#include <vector> + +// 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 Unk0; // 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 + char* Name; // 96 + char* Name2; // 97 + char* Name3; // 98 + char* Name4; // 99 + char* 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 Unknown[5]; // 26-30 +}; + +// 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/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h new file mode 100644 index 00000000000..3cc3a9b7693 --- /dev/null +++ b/src/server/game/DataStores/DB2fmt.h @@ -0,0 +1,26 @@ +/* + * 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 + +const char Itemfmt[]="niiiiiii"; +const char ItemCurrencyCostfmt[]="xn"; +const char ItemSparsefmt[]="niiiffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisssssiiiiiiiiiiiiiiiiiiiiiifiiifii"; +const char ItemExtendedCostEntryfmt[]="nxxiiiiiiiiiiiixiiiiiiiiiixxxxx"; + +#endif diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index e73480cb4de..cd8accd3759 100755 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -22,7 +22,7 @@ // 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 -#define DEFAULT_MAX_LEVEL 80 +#define DEFAULT_MAX_LEVEL 85 // client supported max level for player/pets/etc. Avoid overflow or client stability affected. // also see GT_MAX_LEVEL define @@ -58,16 +58,24 @@ enum AchievementFaction 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_SUMM = 0x00000008, // Use summ criteria value from all reqirements (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_COUNTER = 0x00000001, // Just count statistic (never stop and complete) + ACHIEVEMENT_FLAG_HIDDEN = 0x00000002, // Not sent to client - internal use only + ACHIEVEMENT_FLAG_PLAY_NO_VISUAL = 0x00000004, // Client does not play achievement earned visual + ACHIEVEMENT_FLAG_SUMM = 0x00000008, // Use summ criteria value from all reqirements (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_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 @@ -84,6 +92,80 @@ enum AchievementCriteriaCondition ACHIEVEMENT_CRITERIA_CONDITION_UNK3 = 13, // unk }; +#define MAX_ADDITIONAL_CRITERIA_CONDITIONS 3 + +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_UNK9 = 9, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA = 10, + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_MOUNTED = 11, + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK12 = 12, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK13 = 13, // unused in 4.0.6a + 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 = 17, + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_ZONE = 18, + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK19 = 19, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY = 20, + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_YIELDS_XP = 21, // NYI + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK22 = 22, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK23 = 23, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_ARENA_TEAM_SIZE = 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_UNK31 = 31, // unused in 4.0.6a + 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_UNK35 = 35, // related to timed completing-quests achievements + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK36 = 36, // unused in 4.0.6a + 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, // NYI + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK42 = 42, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK43 = 43, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK44 = 44, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK45 = 45, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW = 46, + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK47 = 47, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK48 = 48, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK49 = 49, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK50 = 50, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK51 = 51, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK52 = 52, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK53 = 53, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK54 = 54, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK55 = 55, + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MIN_ACHIEVEMENT_POINTS = 56, // NYI + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK57 = 57, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_REQUIRES_LFG_GROUP = 58, // NYI + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK59 = 59, // unused in 4.0.6a + 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_UNK64 = 64, // unused in 4.0.6a + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK65 = 65, // Archaeology, item quality related + ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK66 = 66, // Archaeology, race related +}; + +#define MAX_ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TYPE 66 + enum AchievementCriteriaFlags { ACHIEVEMENT_CRITERIA_FLAG_SHOW_PROGRESS_BAR = 0x00000001, // Show progress as bar @@ -102,128 +184,150 @@ 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, }; enum AchievementCriteriaTypes { - ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0, - ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1, - ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5, - ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7, - ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8, - ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9, + 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, // you have to complete a daily quest x times in a row - ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, - ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11, - ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13, - ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14, - ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND= 15, - ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP= 16, - ACHIEVEMENT_CRITERIA_TYPE_DEATH= 17, - ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18, - ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19, - ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20, - ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER = 23, - ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24, - ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26, - ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27, - ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28, - ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL= 29, - ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE = 30, - ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31, - ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32, - ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33, - ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34, - ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL = 35, - ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36, - // TODO: the archievements 1162 and 1163 requires a special rating which can't be found in the dbc - ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39, - ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40, - ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41, - ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM= 42, - ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43, - ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK= 44, - ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT= 45, - ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION= 46, - ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION= 47, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, + 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, + ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP = 16, + ACHIEVEMENT_CRITERIA_TYPE_DEATH = 17, + ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19, + ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20, + ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER = 23, + ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24, + ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27, + ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28, + ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL = 29, + ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE = 30, + ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31, + ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32, + ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34, + ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL = 35, + ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36, + ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40, + ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42, + ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43, + ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK = 44, + ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT = 45, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION = 46, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION = 47, // noted: rewarded as soon as the player payed, not at taking place at the seat - ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP= 48, - ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49, + ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48, + ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49, // TODO: itemlevel is mentioned in text but not present in dbc - ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50, - ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT= 51, - ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52, - ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53, - ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54, - ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55, + ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50, + ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51, + ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52, + ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53, + ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54, + ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55, // TODO: in some cases map not present, and in some cases need do without die - ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56, - ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57, - ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS = 59, - ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS = 60, - ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS = 61, - ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62, - ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING = 63, - ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER = 65, - ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL = 66, - ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67, - ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68, - ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2= 69, - ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL= 70, - ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72, + ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56, + ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57, + ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS = 59, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS = 60, + ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS = 61, + ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING = 63, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER = 65, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL = 66, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67, + ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68, + ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 = 69, + ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL = 70, + ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72, // TODO: title id is not mentioned in dbc - ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE = 74, - ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS= 75, - ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76, - ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77, + ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE = 74, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75, + ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76, + ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77, // TODO: creature type (demon, undead etc.) is not stored in dbc - ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE = 78, - ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS= 80, - ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION= 82, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID= 83, - ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS= 84, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD = 85, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED = 86, - ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION = 87, - ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION = 88, - ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS = 89, - ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM = 90, - ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91, - ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93, - ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH = 95, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT = 97, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR = 99, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING = 100, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102, - ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED = 104, - ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106, - ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED = 107, - ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN = 108, - ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109, + ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE = 78, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS = 80, + ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION = 82, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID = 83, + ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS = 84, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD = 85, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED = 86, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION = 87, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION = 88, + ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS = 89, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM = 90, + ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91, + ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93, + ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102, + ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED = 104, + ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106, + ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED = 107, + ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN = 108, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109, // TODO: target entry is missing - ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110, - ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE= 112, - ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113, - ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114, - // 0..115 => 116 criteria types total - ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS = 115, + ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE = 112, + ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113, + ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114, + ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS = 115, + ACHIEVEMENT_CRITERIA_TYPE_UNK118 = 118, ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS = 119, - // 120 - // 121 - // 122 - // 123 - // 0..123 => 124 criteria types total - ACHIEVEMENT_CRITERIA_TYPE_TOTAL = 124, + ACHIEVEMENT_CRITERIA_TYPE_UNK120 = 120, + ACHIEVEMENT_CRITERIA_TYPE_UNK121 = 121, + ACHIEVEMENT_CRITERIA_TYPE_UNK122 = 122, + ACHIEVEMENT_CRITERIA_TYPE_UNK123 = 123, + 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_UNK137 = 137, + ACHIEVEMENT_CRITERIA_TYPE_UNK138 = 138, //struct { Flag flag; uint32 count; } 1: Guild Dungeon, 2:Guild Challenge, 3:Guild battlefield + ACHIEVEMENT_CRITERIA_TYPE_UNK139 = 139, //struct { uint32 count; } Guild Challenge + ACHIEVEMENT_CRITERIA_TYPE_UNK140 = 140, + ACHIEVEMENT_CRITERIA_TYPE_UNK141 = 141, + ACHIEVEMENT_CRITERIA_TYPE_UNK142 = 142, + ACHIEVEMENT_CRITERIA_TYPE_UNK143 = 143, + ACHIEVEMENT_CRITERIA_TYPE_UNK144 = 144, + ACHIEVEMENT_CRITERIA_TYPE_UNK145 = 145, + ACHIEVEMENT_CRITERIA_TYPE_UNK146 = 146, + ACHIEVEMENT_CRITERIA_TYPE_UNK147 = 147, + ACHIEVEMENT_CRITERIA_TYPE_UNK148 = 148, + ACHIEVEMENT_CRITERIA_TYPE_UNK149 = 149, + ACHIEVEMENT_CRITERIA_TYPE_UNK150 = 150, + // 0..144 => 145 criteria types total + ACHIEVEMENT_CRITERIA_TYPE_TOTAL = 151, }; enum AchievementCategory @@ -233,7 +337,7 @@ enum AchievementCategory enum AreaFlags { - AREA_FLAG_UNK0 = 0x00000001, // Unknown + 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 @@ -261,7 +365,8 @@ enum AreaFlags 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_NO_FLY_ZONE = 0x20000000, // Marks zones where you cannot fly + AREA_FLAG_UNK9 = 0x40000000, }; enum Difficulty @@ -286,7 +391,7 @@ enum Difficulty enum SpawnMask { - SPAWNMASK_CONTINENT = (1 << REGULAR_DIFFICULTY), // any any maps without spawn modes + SPAWNMASK_CONTINENT = (1 << REGULAR_DIFFICULTY), // any maps without spawn modes SPAWNMASK_DUNGEON_NORMAL = (1 << DUNGEON_DIFFICULTY_NORMAL), SPAWNMASK_DUNGEON_HEROIC = (1 << DUNGEON_DIFFICULTY_HEROIC), @@ -349,19 +454,25 @@ enum ItemEnchantmentType 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) + 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 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 + 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 @@ -389,7 +500,8 @@ enum SummonPropType 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_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 @@ -412,6 +524,11 @@ enum SummonPropFlags 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? + 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 @@ -452,4 +569,13 @@ 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 +}; + #endif diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 850c58bdf93..ffceb4e60aa 100755..100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -17,12 +17,11 @@ */ #include "DBCStores.h" - #include "Log.h" #include "SharedDefines.h" #include "SpellMgr.h" - #include "DBCfmt.h" +#include "ItemPrototype.h" #include <map> @@ -59,6 +58,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 <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryfmt); @@ -68,6 +68,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 <CreatureFamilyEntry> sCreatureFamilyStore(CreatureFamilyfmt); @@ -103,16 +104,36 @@ DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore(GtChanceToSp 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); @@ -130,6 +151,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); @@ -153,19 +180,44 @@ DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt); SpellCategoryStore sSpellCategoryStore; 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); + +SpellEffectMap sSpellEffectMap; +SpellReagentMap sSpellReagentMap; +SpellTotemMap sSpellTotemMap; + DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore(SpellCastTimefmt); +DBCStorage <SpellCategoriesEntry> sSpellCategoriesStore(SpellCategoriesEntryfmt); +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]; @@ -193,6 +245,7 @@ DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore(WMOAreaTableEntryfmt); DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt); DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore(WorldMapOverlayEntryfmt); DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt); +DBCStorage <PhaseEntry> sPhaseStores(PhaseEntryfmt); typedef std::list<std::string> StoreProblemList; @@ -276,34 +329,36 @@ 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, 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, 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, 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, sAchievementStore, dbcPath, "Achievement.dbc"/*, &CustomAchievementfmt, &CustomAchievementIndex*/);//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementCriteriaStore, dbcPath, "Achievement_Criteria.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTriggerStore, dbcPath, "AreaTrigger.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sAreaGroupStore, dbcPath, "AreaGroup.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sAreaPOIStore, dbcPath, "AreaPOI.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sAuctionHouseStore, dbcPath, "AuctionHouse.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sArmorLocationStore, dbcPath, "ArmorLocation.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sBankBagSlotPricesStore, dbcPath, "BankBagSlotPrices.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sBattlemasterListStore, dbcPath, "BattlemasterList.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sBarberShopStyleStore, dbcPath, "BarberShopStyle.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sCharStartOutfitStore, dbcPath, "CharStartOutfit.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sCharTitlesStore, dbcPath, "CharTitles.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sChrRacesStore, dbcPath, "ChrRaces.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sChrPowerTypesStore, dbcPath, "ChrClassesXPowerTypes.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureFamilyStore, dbcPath, "CreatureFamily.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureModelDataStore, dbcPath, "CreatureModelData.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureSpellDataStore, dbcPath, "CreatureSpellData.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureTypeStore, dbcPath, "CreatureType.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sCurrencyTypesStore, dbcPath, "CurrencyTypes.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sDestructibleModelDataStore, dbcPath, "DestructibleModelData.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sDungeonEncounterStore, dbcPath, "DungeonEncounter.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityCostsStore, dbcPath, "DurabilityCosts.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityQualityStore, dbcPath, "DurabilityQuality.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesStore, dbcPath, "Emotes.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesTextStore, dbcPath, "EmotesText.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sFactionStore, dbcPath, "Faction.dbc");//14545 for (uint32 i=0; i<sFactionStore.GetNumRows(); ++i) { FactionEntry const* faction = sFactionStore.LookupEntry(i); @@ -314,8 +369,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");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGameObjectDisplayInfoStore, dbcPath, "GameObjectDisplayInfo.dbc");//14545 for (uint32 i = 0; i < sGameObjectDisplayInfoStore.GetNumRows(); ++i) { if (GameObjectDisplayInfoEntry const* info = sGameObjectDisplayInfoStore.LookupEntry(i)) @@ -329,95 +384,130 @@ 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, sGtOCTClassCombatRatingScalarStore, dbcPath, "gtOCTClassCombatRatingScalar.dbc"); - LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTRegenHPStore, dbcPath, "gtOCTRegenHP.dbc"); + LoadDBC(availableDbcLocales, bad_dbc_files, sGemPropertiesStore, dbcPath, "GemProperties.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphPropertiesStore, dbcPath, "GlyphProperties.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphSlotStore, dbcPath, "GlyphSlot.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGtBarberShopCostBaseStore, dbcPath, "gtBarberShopCostBase.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGtCombatRatingsStore, dbcPath, "gtCombatRatings.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritBaseStore, dbcPath, "gtChanceToMeleeCritBase.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritStore, dbcPath, "gtChanceToMeleeCrit.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritBaseStore, dbcPath, "gtChanceToSpellCritBase.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritStore, dbcPath, "gtChanceToSpellCrit.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTClassCombatRatingScalarStore, dbcPath, "gtOCTClassCombatRatingScalar.dbc");//14545 + //LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTRegenHPStore, dbcPath, "gtOCTRegenHP.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTHpPerStaminaStore, dbcPath, "gtOCTHpPerStamina.dbc");//14545 //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");//14545 + 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");//14545 + 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");//14545 + 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, 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");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomPropertiesStore, dbcPath, "ItemRandomProperties.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomSuffixStore, dbcPath, "ItemRandomSuffix.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemSetStore, dbcPath, "ItemSet.dbc");//14545 + + LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorQualityStore, dbcPath, "ItemArmorQuality.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorShieldStore, dbcPath, "ItemArmorShield.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorTotalStore, dbcPath, "ItemArmorTotal.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageAmmoStore, dbcPath, "ItemDamageAmmo.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageOneHandStore, dbcPath, "ItemDamageOneHand.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageOneHandCasterStore,dbcPath, "ItemDamageOneHandCaster.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageRangedStore, dbcPath, "ItemDamageRanged.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageThrownStore, dbcPath, "ItemDamageThrown.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageTwoHandStore, dbcPath, "ItemDamageTwoHand.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageTwoHandCasterStore,dbcPath, "ItemDamageTwoHandCaster.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageWandStore, dbcPath, "ItemDamageWand.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemDisenchantLootStore, dbcPath, "ItemDisenchantLoot.dbc"); + + LoadDBC(availableDbcLocales, bad_dbc_files, sLFGDungeonStore, dbcPath, "LFGDungeons.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sLiquidTypeStore, dbcPath, "LiquidType.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sLockStore, dbcPath, "Lock.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sPhaseStores, dbcPath, "Phase.dbc");//14545 + + LoadDBC(availableDbcLocales, bad_dbc_files, sMailTemplateStore, dbcPath, "MailTemplate.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sMapStore, dbcPath, "Map.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sMapDifficultyStore, dbcPath, "MapDifficulty.dbc");//14545 // 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");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sMountTypeStore, dbcPath, "MountType.dbc");//14545 + + LoadDBC(availableDbcLocales, bad_dbc_files, sNameGenStore, dbcPath, "NameGen.dbc");//14545 + 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");//14545 - LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc"); + LoadDBC(availableDbcLocales, bad_dbc_files, sMovieStore, dbcPath, "Movie.dbc");//14545 - LoadDBC(availableDbcLocales, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc"); + LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc");//14545 + + LoadDBC(availableDbcLocales, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc");//14545 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");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sQuestFactionRewardStore, dbcPath, "QuestFactionReward.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sQuestSortStore, dbcPath, "QuestSort.dbc");//14545 - LoadDBC(availableDbcLocales, bad_dbc_files, sRandomPropertiesPointsStore, dbcPath, "RandPropPoints.dbc"); + LoadDBC(availableDbcLocales, bad_dbc_files, sRandomPropertiesPointsStore, dbcPath, "RandPropPoints.dbc");//14545 - 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, sSoundEntriesStore, dbcPath, "SoundEntries.dbc"); - LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex); + LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatDistributionStore, dbcPath, "ScalingStatDistribution.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatValuesStore, dbcPath, "ScalingStatValues.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineStore, dbcPath, "SkillLine.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineAbilityStore, dbcPath, "SkillLineAbility.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc"/*, &CustomSpellEntryfmt, &CustomSpellEntryIndex*/);// for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) { - SpellEntry const* spell = sSpellStore.LookupEntry(i); + SpellCategoriesEntry const* spell = sSpellCategoriesStore.LookupEntry(i); if (spell && spell->Category) sSpellCategoryStore[spell->Category].insert(i); } for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) { - SkillLineAbilityEntry const* skillLine = sSkillLineAbilityStore.LookupEntry(j); + SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j); if (!skillLine) continue; SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); - if (spellInfo && spellInfo->Attributes & SPELL_ATTR0_PASSIVE) { for (uint32 i = 1; i < sCreatureFamilyStore.GetNumRows(); ++i) { + SpellLevelsEntry const* levels = sSpellLevelsStore.LookupEntry(i); + if (!levels) + continue; + CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(i); if (!cFamily) continue; if (skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1]) continue; - if (spellInfo->spellLevel) + if (levels->spellLevel) continue; if (skillLine->learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL) @@ -428,20 +518,45 @@ void LoadDBCStores(const std::string& dataPath) } } - LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastTimesStore, dbcPath, "SpellCastTimes.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, sSpellReagentsStore, dbcPath,"SpellReagents.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellScalingStore, dbcPath,"SpellScaling.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellTotemsStore, dbcPath,"SpellTotems.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellTargetRestrictionsStore,dbcPath,"SpellTargetRestrictions.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellPowerStore, dbcPath,"SpellPower.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellLevelsStore, dbcPath,"SpellLevels.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellInterruptsStore, dbcPath,"SpellInterrupts.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellEquippedItemsStore, dbcPath,"SpellEquippedItems.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellClassOptionsStore, dbcPath,"SpellClassOptions.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCooldownsStore, dbcPath,"SpellCooldowns.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellAuraOptionsStore, dbcPath,"SpellAuraOptions.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellAuraRestrictionsStore, dbcPath,"SpellAuraRestrictions.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastingRequirementsStore, dbcPath,"SpellCastingRequirements.dbc");//14545 + + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoriesStore, dbcPath,"SpellCategories.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellEffectStore, dbcPath,"SpellEffect.dbc");//14545 + + for(uint32 i = 1; i < sSpellEffectStore.GetNumRows(); ++i) + { + if(SpellEffectEntry const *spellEffect = sSpellEffectStore.LookupEntry(i)) + sSpellEffectMap[spellEffect->EffectSpellId].effects[spellEffect->EffectIndex] = spellEffect; + } + + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastTimesStore, dbcPath, "SpellCastTimes.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDifficultyStore, dbcPath, "SpellDifficulty.dbc"/*, &CustomSpellDifficultyfmt, &CustomSpellDifficultyIndex*/);//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDurationStore, dbcPath, "SpellDuration.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellFocusObjectStore, dbcPath, "SpellFocusObject.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentStore, dbcPath, "SpellItemEnchantment.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentConditionStore, dbcPath, "SpellItemEnchantmentCondition.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRadiusStore, dbcPath, "SpellRadius.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRangeStore, dbcPath, "SpellRange.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRuneCostStore, dbcPath, "SpellRuneCost.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftStore, dbcPath, "SpellShapeshift.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftFormStore, dbcPath, "SpellShapeshiftForm.dbc");//14545 + //LoadDBC(availableDbcLocales, bad_dbc_files, sStableSlotPricesStore, dbcPath, "StableSlotPrices.dbc"); + LoadDBC(availableDbcLocales, bad_dbc_files, sSummonPropertiesStore, dbcPath, "SummonProperties.dbc");//14545 + + LoadDBC(availableDbcLocales, bad_dbc_files, sTalentStore, dbcPath, "Talent.dbc");//14545 // Create Spelldifficulty searcher for (uint32 i = 0; i < sSpellDifficultyStore.GetNumRows(); ++i) @@ -482,7 +597,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");//14545 // prepare fast data access to bit pos of talent ranks for use at inspecting { @@ -498,22 +613,27 @@ void LoadDBCStores(const std::string& dataPath) continue; // store class talent tab pages - uint32 cls = 1; - for (uint32 m=1; !(m & talentTabInfo->ClassMask) && cls < MAX_CLASSES; m <<= 1, ++cls) {} - - sTalentTabPages[cls][talentTabInfo->tabpage]=talentTabId; + for (uint32 cls = 1; cls < MAX_CLASSES; ++cls) + if (talentTabInfo->ClassMask & (1 << (cls - 1))) + sTalentTabPages[cls][talentTabInfo->tabpage] = talentTabId; } } - 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");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathStore, dbcPath, "TaxiPath.dbc");//14545 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");//14545 // Calculate path nodes count std::vector<uint32> pathLength; pathLength.resize(pathCount); // 0 and some other indexes not used @@ -536,11 +656,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)); @@ -572,10 +691,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) @@ -593,19 +712,19 @@ 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");//14545 - LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleStore, dbcPath, "Vehicle.dbc"); - LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleSeatStore, dbcPath, "VehicleSeat.dbc"); + LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleStore, dbcPath, "Vehicle.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleSeatStore, dbcPath, "VehicleSeat.dbc");//14545 - LoadDBC(availableDbcLocales, bad_dbc_files, sWMOAreaTableStore, dbcPath, "WMOAreaTable.dbc"); + LoadDBC(availableDbcLocales, bad_dbc_files, sWMOAreaTableStore, dbcPath, "WMOAreaTable.dbc");//14545 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");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapOverlayStore, dbcPath, "WorldMapOverlay.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sWorldSafeLocsStore, dbcPath, "WorldSafeLocs.dbc");//14545 // error checks if (bad_dbc_files.size() >= DBCFileCount) @@ -624,20 +743,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) { sLog->outError(LOG_FILTER_GENERAL, "You have _outdated_ DBC files. Please extract correct versions from current using client."); exit(1); } - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Initialized %d data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime)); + sLog->outInfo(LOG_FILTER_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) @@ -649,14 +773,41 @@ 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; +} + +SpellEffectEntry const* GetSpellEffectEntry(uint32 spellId, uint32 effect) +{ + SpellEffectMap::const_iterator itr = sSpellEffectMap.find(spellId); + if(itr == sSpellEffectMap.end()) + return NULL; + + return itr->second.effects[effect]; +} + +SpellReagentsEntry const* GetSpellReagentEntry(uint32 spellId, uint8 reagent) +{ + SpellReagentMap::const_iterator itr = sSpellReagentMap.find(spellId); + if(itr == sSpellReagentMap.end()) + return NULL; + + return itr->second.reagents[reagent]; +} + +SpellTotemsEntry const* GetSpellTotemEntry(uint32 spellId, uint8 totem) +{ + SpellTotemMap::const_iterator itr = sSpellTotemMap.find(spellId); + if(itr == sSpellTotemMap.end()) + return NULL; + + return itr->second.totems[totem]; } TalentSpellPos const* GetTalentSpellPos(uint32 spellId) @@ -724,7 +875,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)) @@ -733,6 +884,10 @@ uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId) return mapid; } +/* +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); @@ -743,11 +898,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()); } } @@ -866,6 +1027,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)) @@ -874,3 +1044,155 @@ uint32 GetLiquidFlags(uint32 liquidType) return 0; } +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; +} + diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index cd30ed587f8..f669049be5c 100755 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -28,9 +28,12 @@ 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); +SpellEffectEntry const* GetSpellEffectEntry(uint32 spellId, uint32 effect); +SpellReagentsEntry const* GetSpellReagentEntry(uint32 spellId, uint8 reagent); +SpellTotemsEntry const* GetSpellTotemEntry(uint32 spellId, uint8 totem); int32 GetAreaFlagByAreaID(uint32 area_id); // -1 if not found AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id); @@ -41,12 +44,16 @@ 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 }; + ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId); bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId); @@ -59,6 +66,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); @@ -71,6 +79,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 <BarberShopStyleEntry> sBarberShopStyleStore; @@ -80,6 +89,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 <CreatureFamilyEntry> sCreatureFamilyStore; @@ -107,15 +117,35 @@ extern DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore; extern DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore; extern DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore; 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; @@ -125,6 +155,11 @@ 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 <MapDifficultyEntry> sMapDifficultyStore; -- use GetMapDifficultyData insteed extern MapDifficultyMap sMapDifficultyMap; extern DBCStorage <MovieEntry> sMovieStore; @@ -150,8 +185,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; @@ -164,7 +215,6 @@ extern TaxiMask sAllianceTaxiNodesMask; extern TaxiMask sDeathKnightTaxiNodesMask; extern TaxiPathSetBySource sTaxiPathSetBySource; extern TaxiPathNodesByPath sTaxiPathNodesByPath; -extern DBCStorage <TeamContributionPointsEntry> sTeamContributionPointsStore; extern DBCStorage <TotemCategoryEntry> sTotemCategoryStore; extern DBCStorage <VehicleEntry> sVehicleStore; extern DBCStorage <VehicleSeatEntry> sVehicleSeatStore; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index fdec06f6f48..b12aee36fc1 100755..100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -44,28 +44,24 @@ 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 @@ -131,6 +127,13 @@ struct AchievementCriteriaEntry uint32 questCount; // 4 } complete_quests_in_zone; + // ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12 + struct + { + uint32 currency; + uint32 count; + } currencyGain; + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14 struct { @@ -260,7 +263,14 @@ struct AchievementCriteriaEntry struct { uint32 teamtype; // 3 {2, 3, 5} - uint32 PersonalRating; // 4 + uint32 teamrating; // 4 + } reach_team_rating; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39 + struct + { + uint32 teamtype; // 3 {2, 3, 5} + uint32 PersonalRating; // 4 } highest_personal_rating; // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40 @@ -370,6 +380,7 @@ struct AchievementCriteriaEntry } 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 @@ -504,15 +515,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 @@ -521,13 +536,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 unk13; // 17, + //float unk13; // 18, + //uint32 unk19; // 19, All zeros (4.2.2) + //uint32 unk20; // 20 4.0.0 + //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 @@ -553,16 +580,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 @@ -572,11 +597,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 @@ -585,8 +619,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 @@ -599,14 +632,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 @@ -615,12 +646,15 @@ struct BattlemasterListEntry int32 mapid[8]; // 1-8 mapid uint32 type; // 9 (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 @@ -635,46 +669,45 @@ struct CharStartOutfitEntry //uint32 Unknown1; // 38, unique values (index-like with gaps ordered in other way as ids) //uint32 Unknown2; // 39 //uint32 Unknown3; // 40 + //uint32 Unknown4; // 41 + //uint32 Unknown5; // 42 }; struct CharTitlesEntry { uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId() //uint32 unk1; // 1 flags? - char* name[16]; // 2-17 - // 18 string flag, unused - //char* name2[16]; // 19-34, unused - // 35 string flag, unused - uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES + char* name; // 2 m_name_lang + //char* name2; // 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 + uint32 APPerAgility; // 12 + //uint32 // 13 }; struct ChrRacesEntry @@ -689,15 +722,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 @@ -737,6 +778,7 @@ struct CreatureDisplayInfoEntry // 13 m_particleColorID // 14 m_creatureGeosetData // 15 m_objectEffectPackageID + // 16 }; struct CreatureFamilyEntry @@ -750,18 +792,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 @@ -789,9 +830,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 @@ -806,33 +846,45 @@ 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 unk5; // 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 @@ -842,7 +894,7 @@ struct DungeonEncounterEntry uint32 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 }; @@ -862,12 +914,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 @@ -889,10 +942,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 // 25 // helpers bool CanHaveReputation() const @@ -918,6 +970,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) @@ -931,6 +985,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) @@ -956,22 +1012,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 // 5 }; struct GlyphPropertiesEntry @@ -996,21 +1055,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; }; @@ -1034,10 +1097,15 @@ struct GtOCTRegenHPEntry float ratio; }; -//struct GtOCTRegenMPEntry -//{ -// float ratio; -//}; +struct GtOCTRegenMPEntry +{ + float ratio; +}; + +struct gtOCTHpPerStaminaEntry +{ + float ratio; +}; struct GtRegenHPPerSptEntry { @@ -1049,12 +1117,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 }; */ @@ -1062,8 +1151,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 }; */ @@ -1087,23 +1175,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 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 ID; // 0 - uint32 Class; // 1 - uint32 SubClass; // 2 some items have strange subclasses - int32 Unk0; // 3 - int32 Material; // 4 - uint32 DisplayId; // 5 - uint32 InventoryType; // 6 - uint32 Sheath; // 7 + 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 @@ -1122,34 +1292,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 @@ -1157,23 +1316,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 @@ -1182,35 +1337,33 @@ 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 (flags & 4) = IsHoliday - 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 unk; // 9 + uint32 type; // 10 + //uint32 unk2; // 11 + //char* unk3; // 12 + uint32 expansion; // 13 + //uint32 unk4; // 14 + uint32 grouptype; // 15 + //char* desc; // 16 Description // Helpers uint32 Entry() const { return ID + (type << 24); } }; @@ -1250,12 +1403,18 @@ struct LockEntry //uint32 Action[MAX_LOCK_CASE]; // 25-32 m_Action }; +struct PhaseEntry +{ + uint32 ID; // 0 + char* Name; // 1 + uint32 phaseShift; // 2 +}; + 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 @@ -1264,23 +1423,22 @@ struct MapEntry //char* internalname; // 1 unused uint32 map_type; // 2 //uint32 unk_330; // 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 - // 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) - // 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 + //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 unk_time; // 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; } @@ -1315,18 +1473,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 @@ -1336,6 +1528,7 @@ struct OverrideSpellDataEntry uint32 id; // 0 uint32 spellId[MAX_OVERRIDE_SPELL]; // 1-10 //uint32 unk0; // 11 + //uint32 unk3; // 12 possibly flag }; struct PvPDifficultyEntry @@ -1354,8 +1547,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 @@ -1384,78 +1576,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 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 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 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{ @@ -1487,14 +1624,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 @@ -1511,7 +1645,8 @@ struct SkillLineAbilityEntry uint32 learnOnGetSkill; // 9 m_acquireMethod uint32 max_value; // 10 m_trivialSkillLineRankHigh uint32 min_value; // 11 m_trivialSkillLineRankLow - //uint32 characterPoints[2]; // 12-13 m_characterPoints[2] + //uint32 // 12 + //uint32 // 13 4.0.0 }; struct SoundEntriesEntry @@ -1527,124 +1662,170 @@ 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 +}; + +struct SpellTotem +{ + SpellTotem() + { + totems[0] = NULL; + totems[1] = NULL; + } + SpellTotemsEntry const* totems[MAX_SPELL_TOTEMS]; +}; + +typedef std::map<uint32, SpellTotem> SpellTotemMap; + +// 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 unk_f1; // 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 + + // struct access functions + SpellEffectEntry const* GetSpellEffect(uint32 eff) const; +}; + +// 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; @@ -1669,16 +1850,15 @@ 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 { uint32 ID; - float radiusMin; + float radiusHostile; //uint32 Unk //always 0 - float radiusMax; + float radiusFriend; }; struct SpellRangeEntry @@ -1687,12 +1867,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 PowerDisplayId; // 5 m_powerDisplayID - id from PowerDisplay.dbc, new in 3.1 + //uint32 unk1; // 6 4.0.0 + //float unk2; // 7 4.3.0 }; struct SpellRuneCostEntry @@ -1707,21 +1946,84 @@ 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 unk1; // 5 unused, related to next field + uint32 attackSpeed; // 6 + 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 +}; + +struct SpellReagent +{ + SpellReagent() + { + reagents[0] = NULL; + reagents[1] = NULL; + reagents[2] = NULL; + reagents[3] = NULL; + reagents[4] = NULL; + reagents[5] = NULL; + reagents[6] = NULL; + reagents[7] = NULL; + } + SpellReagentsEntry const* reagents[MAX_SPELL_REAGENTS]; +}; + +typedef std::map<uint32, SpellReagent> SpellReagentMap; + +// 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 @@ -1738,15 +2040,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 @@ -1787,27 +2089,35 @@ 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 }; 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 spellIds[2]; // 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 @@ -1817,9 +2127,8 @@ 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] }; struct TaxiPathEntry @@ -1854,10 +2163,9 @@ struct TeamContributionPointsEntry struct TotemCategoryEntry { 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) + //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) }; #define MAX_VEHICLE_SEATS 8 @@ -1887,9 +2195,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 @@ -1970,8 +2278,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 @@ -1987,6 +2297,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 @@ -1996,9 +2309,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 @@ -2008,8 +2327,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 }; /* @@ -2055,6 +2373,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 { @@ -2077,6 +2402,19 @@ struct TalentSpellPos typedef std::map<uint32, TalentSpellPos> TalentSpellPosMap; +struct SpellEffect +{ + SpellEffect() + { + effects[0] = NULL; + effects[1] = NULL; + effects[2] = NULL; + } + SpellEffectEntry const* effects[3]; +}; + +typedef std::map<uint32, SpellEffect> SpellEffectMap; + struct TaxiPathBySourceAndDestination { TaxiPathBySourceAndDestination() : ID(0), price(0) {} @@ -2099,7 +2437,6 @@ struct TaxiPathNodePtr typedef Path<TaxiPathNodePtr, TaxiPathNodeEntry const> TaxiPathNodeList; typedef std::vector<TaxiPathNodeList> TaxiPathNodesByPath; -#define TaxiMaskSize 14 -typedef uint32 TaxiMask[TaxiMaskSize]; +#define TaxiMaskSize 114 +typedef uint8 TaxiMask[TaxiMaskSize]; #endif - diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 39d031e96f9..8dfc40d9b4e 100755 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -19,111 +19,155 @@ #ifndef TRINITY_DBCSFRM_H #define TRINITY_DBCSFRM_H -const char Achievementfmt[]="niixssssssssssssssssxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxii"; -const std::string CustomAchievementfmt="pppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaapapaaaaaaaaaaaaaaaaaapp"; -const std::string CustomAchievementIndex = "ID"; -const char AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiiiix"; -const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxiiiiixxx"; +// 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 + +const char Achievementfmt[]="niixsxiixixxii"; +//const std::string CustomAchievementfmt="pppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaapapaaaaaaaaaaaaaaaaaapp"; +//const std::string CustomAchievementIndex = "ID"; +const char AchievementCriteriafmt[]="niiiiiiiisiiiiixxiiiiii"; +const char AreaTableEntryfmt[]="iiinixxxxxisiiiiixxxxxxxxx"; const char AreaGroupEntryfmt[]="niiiiiii"; -const char AreaPOIEntryfmt[]="niiiiiiiiiiifffixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix"; -const char AreaTriggerEntryfmt[]="niffffffff"; -const char AuctionHouseEntryfmt[]="niiixxxxxxxxxxxxxxxxx"; +const char AreaPOIEntryfmt[]="niiiiiiiiiiiffixixxixx"; +const char AreaTriggerEntryfmt[]="nifffxxxfffff"; +const char ArmorLocationfmt[]="nfffff"; +const char AuctionHouseEntryfmt[]="niiix"; const char BankBagSlotPricesEntryfmt[]="ni"; -const char BarberShopStyleEntryfmt[]="nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii"; -const char BattlemasterListEntryfmt[]="niiiiiiiiixssssssssssssssssxiixx"; -const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; -const char CharTitlesEntryfmt[]="nxssssssssssssssssxxxxxxxxxxxxxxxxxxi"; -const char ChatChannelsEntryfmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxx"; - // ChatChannelsEntryfmt, index not used (more compact store) -const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii"; -const char ChrRacesEntryfmt[]="nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; +const char BarberShopStyleEntryfmt[]="nixxxiii"; +const char BattlemasterListEntryfmt[]="niiiiiiiiixsiiiixxxx"; +const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +const char CharTitlesEntryfmt[]="nxsxix"; +const char ChatChannelsEntryfmt[]="nixsx"; + +const char ChrClassesEntryfmt[]="nixsxxxixiiiix"; +const char ChrRacesEntryfmt[]="nxixiixixxxxixsxxxxxixxx"; +const char ChrClassesXPowerTypesfmt[]="nii"; + const char CinematicSequencesEntryfmt[]="nxxxxxxxxx"; -const char CreatureDisplayInfofmt[]="nixxfxxxxxxxxxxx"; -const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx"; -const char CreatureModelDatafmt[]="nxxxfxxxxxxxxxxffxxxxxxxxxxx"; +const char CreatureDisplayInfofmt[]="nixxfxxxxxxxxxxxx"; +const char CreatureModelDatafmt[]="nxxxxxxxxxxxxxffxxxxxxxxxxxxxxx"; +const char CreatureFamilyfmt[]="nfifiiiiixsx"; const char CreatureSpellDatafmt[]="niiiixxxx"; -const char CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx"; -const char CurrencyTypesfmt[]="xnxi"; -const char DestructibleModelDatafmt[]="nxxixxxixxxixxxixxx"; -const char DungeonEncounterfmt[]="niixissssssssssssssssxx"; +const char CreatureTypefmt[]="nxx"; +const char CurrencyTypesfmt[]="nxxxxxiiiix"; + +const char DestructibleModelDatafmt[]="ixxixxxixxxixxxixxxxxxxx"; +const char DungeonEncounterfmt[]="iiixisxx"; const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; const char DurabilityQualityfmt[]="nf"; -const char EmotesEntryfmt[]="nxxiiix"; +const char EmotesEntryfmt[]="nxxiiixx"; const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx"; -const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx"; +const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixsxx"; const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii"; -const char GameObjectDisplayInfofmt[]="nsxxxxxxxxxxffffffx"; -const char GemPropertiesEntryfmt[]="nixxi"; +const char GameObjectDisplayInfofmt[]="nsxxxxxxxxxxffffffxxx"; + +const char GemPropertiesEntryfmt[]="nixxix"; const char GlyphPropertiesfmt[]="niii"; const char GlyphSlotfmt[]="nii"; -const char GtBarberShopCostBasefmt[]="f"; -const char GtCombatRatingsfmt[]="f"; -const char GtChanceToMeleeCritBasefmt[]="f"; -const char GtChanceToMeleeCritfmt[]="f"; -const char GtChanceToSpellCritBasefmt[]="f"; -const char GtChanceToSpellCritfmt[]="f"; + +const char GtBarberShopCostBasefmt[]="xf"; +const char GtCombatRatingsfmt[]="xf"; +const char GtOCTHpPerStaminafmt[]="df"; +const char GtChanceToMeleeCritBasefmt[]="xf"; +const char GtChanceToMeleeCritfmt[]="xf"; +const char GtChanceToSpellCritBasefmt[]="xf"; +const char GtChanceToSpellCritfmt[]="xf"; const char GtOCTClassCombatRatingScalarfmt[]="df"; const char GtOCTRegenHPfmt[]="f"; //const char GtOCTRegenMPfmt[]="f"; -const char GtRegenHPPerSptfmt[]="f"; -const char GtRegenMPPerSptfmt[]="f"; +const char GtRegenMPPerSptfmt[]="xf"; +const char GtSpellScalingfmt[]="df"; +const char GtOCTBaseHPByClassfmt[]="df"; +const char GtOCTBaseMPByClassfmt[]="df"; +const char GuildPerkSpellsfmt[]="dii"; const char Holidaysfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiixxsiix"; -const char Itemfmt[]="niiiiiii"; -const char ItemBagFamilyfmt[]="nxxxxxxxxxxxxxxxxx"; +const char ImportPriceArmorfmt[]="nffff"; +const char ImportPriceQualityfmt[]="nf"; +const char ImportPriceShieldfmt[]="nf"; +const char ImportPriceWeaponfmt[]="nf"; +const char ItemPriceBasefmt[]="diff"; +const char ItemReforgefmt[]="nifif"; +const char ItemBagFamilyfmt[]="nx"; +const char ItemArmorQualityfmt[]="nfffffffi"; +const char ItemArmorShieldfmt[]="nifffffff"; +const char ItemArmorTotalfmt[]="niffff"; +const char ItemClassfmt[]="dixxfx"; +const char ItemDamagefmt[]="nfffffffi"; +const char ItemDisenchantLootfmt[]="niiiiii"; //const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx"; -//const char ItemCondExtCostsEntryfmt[]="xiii"; -const char ItemExtendedCostEntryfmt[]="niiiiiiiiiiiiiix"; -const char ItemLimitCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; -const char ItemRandomPropertiesfmt[]="nxiiixxssssssssssssssssx"; -const char ItemRandomSuffixfmt[]="nssssssssssssssssxxiiixxiiixx"; -const char ItemSetEntryfmt[]="dssssssssssssssssxiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii"; -const char LFGDungeonEntryfmt[]="nxxxxxxxxxxxxxxxxxiiiiiiixixxixixxxxxxxxxxxxxxxxx"; +const char ItemLimitCategoryEntryfmt[]="nxii"; +const char ItemRandomPropertiesfmt[]="nxiiixxs"; +const char ItemRandomSuffixfmt[]="nsxiiiiiiiiii"; +const char ItemSetEntryfmt[]="dsiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii"; +const char LFGDungeonEntryfmt[]="nxiiiiiiixixxixixxxxx"; const char LiquidTypefmt[]="nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; -const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxssssssssssssssssx"; -const char MapEntryfmt[]="nxixxssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxiix"; -const char MapDifficultyEntryfmt[]="diisxxxxxxxxxxxxxxxxiix"; -const char MovieEntryfmt[]="nxx"; -const char OverrideSpellDatafmt[]="niiiiiiiiiix"; -const char QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx"; +const char PhaseEntryfmt[]="nsi"; +const char MailTemplateEntryfmt[]="nxs"; +const char MapEntryfmt[]="nxixxxsixxixiffxiixi"; +const char MapDifficultyEntryfmt[]="diisiix"; +const char MovieEntryfmt[]="nxxx"; +const char MountCapabilityfmt[]="niiiiiii"; +const char MountTypefmt[]="niiiiiiiiiiiiiiiiiiiiiiii"; +const char NameGenfmt[] = "dsii"; +const char NumTalentsAtLevelfmt[]="df"; +const char OverrideSpellDatafmt[]="niiiiiiiiiixx"; +const char QuestSortEntryfmt[]="nx"; const char QuestXPfmt[]="niiiiiiiiii"; const char QuestFactionRewardfmt[]="niiiiiiiiii"; const char PvPDifficultyfmt[]="diiiii"; const char RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii"; -const char ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiii"; -const char ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiiiiiiii"; -const char SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi"; +const char ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiixi"; +const char ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"; +const char SkillLinefmt[]="nisxixi"; const char SkillLineAbilityfmt[]="niiiixxiiiiixx"; -const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char SpellCastTimefmt[]="nixx"; +const char SpellCategoriesEntryfmt[]="diiiiii"; const char SpellDifficultyfmt[]="niiii"; const std::string CustomSpellDifficultyfmt="ppppp"; const std::string CustomSpellDifficultyIndex="id"; const char SpellDurationfmt[]="niii"; -const char SpellEntryfmt[]="niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx"; +const char SpellEffectEntryfmt[]="nifiiiffiiiiiifiifiiiiiiiix"; +const char SpellEntryfmt[]="niiiiiiiiiiiiiiifiiiissxxiixxixiiiiiiixiiiiiiiix"; const std::string CustomSpellEntryfmt="papppppppppppapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa"; const std::string CustomSpellEntryIndex = "Id"; -const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; -const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiiiii"; +const char SpellFocusObjectfmt[]="nx"; +const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiisiiiiiiix"; const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; const char SpellRadiusfmt[]="nfxf"; -const char SpellRangefmt[]="nffffixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +const char SpellRangefmt[]="nffffixx"; +const char SpellReagentsEntryfmt[]="diiiiiiiiiiiiiiii"; +const char SpellScalingEntryfmt[]="diiiiffffffffffi"; +const char SpellTotemsEntryfmt[]="niiii"; +const char SpellTargetRestrictionsEntryfmt[]="nxiiii"; +const char SpellPowerEntryfmt[]="diiiixxx"; +const char SpellInterruptsEntryfmt[]="dixixi"; +const char SpellEquippedItemsEntryfmt[]="diii"; +const char SpellAuraOptionsEntryfmt[]="niiii"; +const char SpellAuraRestrictionsEntryfmt[]="diiiiiiii"; +const char SpellCastingRequirementsEntryfmt[]="dixxixi"; +const char SpellClassOptionsEntryfmt[]="dxiiiix"; +const char SpellCooldownsEntryfmt[]="diii"; +const char SpellLevelsEntryfmt[]="diii"; const char SpellRuneCostfmt[]="niiii"; -const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixiiixxiiiiiiii"; +const char SpellShapeshiftEntryfmt[]="nixixx"; +const char SpellShapeshiftFormfmt[]="nxxiixiiixxiiiiiiiixx"; const char StableSlotPricesfmt[] = "ni"; const char SummonPropertiesfmt[] = "niiiii"; -const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx"; -const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix"; -const char TaxiNodesEntryfmt[]="nifffssssssssssssssssxii"; +const char TalentEntryfmt[]="niiiiiiiiixxixxxxxx"; +const char TalentTabEntryfmt[]="nxxiiixxxxx"; +const char TalentTreePrimarySpellsfmt[]="diix"; +const char TaxiNodesEntryfmt[]="nifffsiixxx"; const char TaxiPathEntryfmt[]="niii"; const char TaxiPathNodeEntryfmt[]="diiifffiiii"; const char TeamContributionPointsfmt[]="df"; -const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; +const char TotemCategoryEntryfmt[]="nxii"; const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifiixx"; -const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx"; -const char WMOAreaTableEntryfmt[]="niiixxxxxiixxxxxxxxxxxxxxxxx"; -const char WorldMapAreaEntryfmt[]="xinxffffixx"; -const char WorldMapOverlayEntryfmt[]="nxiiiixxxxxxxxxxx"; -const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx"; +const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxxxxxxxxxx"; +const char WMOAreaTableEntryfmt[]="niiixxxxxiixxxx"; +const char WorldMapAreaEntryfmt[]="xinxffffixxxxx"; +const char WorldMapOverlayEntryfmt[]="nxiiiixxxxxxxxx"; +const char WorldSafeLocsEntryfmt[]="nifffx"; #endif diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index bb6c1dfdcc1..4bc1ca0a832 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -1899,7 +1899,7 @@ void LFGMgr::RewardDungeonDoneFor(const uint32 dungeonId, Player* player) // Update achievements if (dungeon->difficulty == DUNGEON_DIFFICULTY_HEROIC) - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS, 1); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS, 1); LfgReward const* reward = GetRandomDungeonReward(rDungeonId, player->getLevel()); if (!reward) diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index 60c0b7ad394..653a731b5b2 100755 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -32,7 +32,7 @@ Corpse::Corpse(CorpseType type) : WorldObject(type != CORPSE_BONES) 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; @@ -103,25 +103,25 @@ void Corpse::SaveToDB() SQLTransaction trans = CharacterDatabase.BeginTransaction(); DeleteFromDB(trans); + uint16 index = 0; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CORPSE); - stmt->setUInt32(0, GetGUIDLow()); // corpseGuid - stmt->setUInt32(1, GUID_LOPART(GetOwnerGUID())); // guid - stmt->setFloat (2, GetPositionX()); // posX - stmt->setFloat (3, GetPositionY()); // posY - stmt->setFloat (4, GetPositionZ()); // posZ - stmt->setFloat (5, GetOrientation()); // orientation - stmt->setUInt16(6, GetMapId()); // mapId - stmt->setUInt32(7, GetUInt32Value(CORPSE_FIELD_DISPLAY_ID)); // displayId - stmt->setString(8, _ConcatFields(CORPSE_FIELD_ITEM, EQUIPMENT_SLOT_END)); // itemCache - stmt->setUInt32(9, GetUInt32Value(CORPSE_FIELD_BYTES_1)); // bytes1 - stmt->setUInt32(10, GetUInt32Value(CORPSE_FIELD_BYTES_2)); // bytes2 - stmt->setUInt32(11, GetUInt32Value(CORPSE_FIELD_GUILD)); // guildId - stmt->setUInt8 (12, GetUInt32Value(CORPSE_FIELD_FLAGS)); // flags - stmt->setUInt8 (13, GetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS)); // dynFlags - stmt->setUInt32(14, uint32(m_time)); // time - stmt->setUInt8 (15, GetType()); // corpseType - stmt->setUInt32(16, GetInstanceId()); // instanceId - stmt->setUInt16(17, GetPhaseMask()); // phaseMask + stmt->setUInt32(index++, GetGUIDLow()); // corpseGuid + stmt->setUInt32(index++, GUID_LOPART(GetOwnerGUID())); // guid + stmt->setFloat (index++, GetPositionX()); // posX + stmt->setFloat (index++, GetPositionY()); // posY + stmt->setFloat (index++, GetPositionZ()); // posZ + stmt->setFloat (index++, GetOrientation()); // orientation + stmt->setUInt16(index++, GetMapId()); // mapId + stmt->setUInt32(index++, GetUInt32Value(CORPSE_FIELD_DISPLAY_ID)); // displayId + 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->setUInt8 (index++, GetUInt32Value(CORPSE_FIELD_FLAGS)); // flags + stmt->setUInt8 (index++, GetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS)); // dynFlags + stmt->setUInt32(index++, uint32(m_time)); // time + stmt->setUInt8 (index++, GetType()); // corpseType + stmt->setUInt32(index++, GetInstanceId()); // instanceId + stmt->setUInt16(index++, GetPhaseMask()); // phaseMask trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); @@ -161,9 +161,10 @@ void Corpse::DeleteFromDB(SQLTransaction& trans) bool Corpse::LoadCorpseFromDB(uint32 guid, Field* fields) { - uint32 ownerGuid = fields[17].GetUInt32(); - // 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[16].GetUInt32(); float posX = fields[0].GetFloat(); float posY = fields[1].GetFloat(); float posZ = fields[2].GetFloat(); @@ -176,15 +177,14 @@ 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].GetUInt16(); + uint32 instanceId = fields[13].GetUInt32(); + uint32 phaseMask = fields[14].GetUInt16(); // place SetLocationInstanceId(instanceId); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 866437d828c..6e2fc197a5f 100755 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -61,12 +61,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; @@ -77,10 +77,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; } @@ -327,6 +327,7 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data SetFloatValue(UNIT_FIELD_COMBATREACH, minfo->combat_reach); 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); @@ -380,6 +381,7 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data) SetAttackTime(RANGED_ATTACK, cInfo->rangeattacktime); SetUInt32Value(UNIT_FIELD_FLAGS, unit_flags); + SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER); SetUInt32Value(UNIT_DYNAMIC_FLAGS, dynamicflags); @@ -439,7 +441,7 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data) */ // TODO: Shouldn't we check whether or not the creature is in water first? - if (cInfo->InhabitType & INHABIT_WATER) + if (cInfo->InhabitType & INHABIT_WATER && IsInWater()) AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING); return true; @@ -1159,12 +1161,26 @@ void Creature::SelectLevel(const CreatureTemplate* cinfo) // 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); + SetMaxPower(POWER_RAGE, GetCreatePowers(POWER_RAGE)); + SetPower(POWER_RAGE, GetCreatePowers(POWER_RAGE)); + break; + case CLASS_ROGUE: + setPowerType(POWER_ENERGY); + SetMaxPower(POWER_ENERGY, GetCreatePowers(POWER_ENERGY)); + SetPower(POWER_ENERGY, GetCreatePowers(POWER_ENERGY)); + break; + default: + setPowerType(POWER_MANA); + SetMaxPower(POWER_MANA, mana); + SetPower(POWER_MANA, mana); + break; + } SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health); SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana); @@ -1734,7 +1750,10 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim) if (bcontinue) continue; - if (spellInfo->ManaCost > GetPower(POWER_MANA)) + if (bcontinue) + continue; + + if (spellInfo->ManaCost > (uint32)GetPower(POWER_MANA)) continue; float range = spellInfo->GetMaxRange(false); float minrange = spellInfo->GetMinRange(false); @@ -1778,7 +1797,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); @@ -2461,9 +2480,52 @@ 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); + ObjectGuid guid = GetGUID(); + if (enable) + { + WorldPacket data(SMSG_SPLINE_MOVE_SET_WALK_MODE, 9); + data.WriteBit(guid[7]); + data.WriteBit(guid[6]); + data.WriteBit(guid[5]); + data.WriteBit(guid[1]); + data.WriteBit(guid[3]); + data.WriteBit(guid[4]); + data.WriteBit(guid[2]); + data.WriteBit(guid[0]); + data.FlushBits(); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[3]); + SendMessageToSet(&data, false); + } + else + { + WorldPacket data(SMSG_SPLINE_MOVE_SET_RUN_MODE, 9); + data.WriteBit(guid[5]); + data.WriteBit(guid[6]); + data.WriteBit(guid[3]); + data.WriteBit(guid[7]); + data.WriteBit(guid[2]); + data.WriteBit(guid[0]); + data.WriteBit(guid[4]); + data.WriteBit(guid[1]); + data.FlushBits(); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[3]); + SendMessageToSet(&data, false); + } + return true; } @@ -2477,9 +2539,52 @@ bool Creature::SetDisableGravity(bool disable, bool packetOnly/*=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); + ObjectGuid guid = GetGUID(); + if (disable) + { + WorldPacket data(SMSG_SPLINE_MOVE_GRAVITY_DISABLE, 9); + data.WriteBit(guid[7]); + data.WriteBit(guid[3]); + data.WriteBit(guid[4]); + data.WriteBit(guid[2]); + data.WriteBit(guid[5]); + data.WriteBit(guid[1]); + data.WriteBit(guid[0]); + data.WriteBit(guid[6]); + data.FlushBits(); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[0]); + SendMessageToSet(&data, false); + } + else + { + WorldPacket data(SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9); + data.WriteBit(guid[5]); + data.WriteBit(guid[4]); + data.WriteBit(guid[7]); + data.WriteBit(guid[1]); + data.WriteBit(guid[3]); + data.WriteBit(guid[6]); + data.WriteBit(guid[2]); + data.WriteBit(guid[0]); + data.FlushBits(); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[5]); + SendMessageToSet(&data, false); + } + return true; } @@ -2498,8 +2603,51 @@ bool Creature::SetHover(bool enable) 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); + ObjectGuid guid = GetGUID(); + if (enable) + { + WorldPacket data(SMSG_SPLINE_MOVE_SET_HOVER, 9); + data.WriteBit(guid[3]); + data.WriteBit(guid[7]); + data.WriteBit(guid[0]); + data.WriteBit(guid[1]); + data.WriteBit(guid[4]); + data.WriteBit(guid[6]); + data.WriteBit(guid[2]); + data.WriteBit(guid[5]); + data.FlushBits(); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[6]); + SendMessageToSet(&data, false); + } + else + { + WorldPacket data(SMSG_SPLINE_MOVE_UNSET_HOVER, 9); + data.WriteBit(guid[6]); + data.WriteBit(guid[7]); + data.WriteBit(guid[4]); + data.WriteBit(guid[0]); + data.WriteBit(guid[3]); + data.WriteBit(guid[1]); + data.WriteBit(guid[5]); + data.WriteBit(guid[2]); + data.FlushBits(); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[1]); + SendMessageToSet(&data, false); + } + return true; } diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index c8ebf1aa13b..14a680d62d1 100755 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -95,6 +95,7 @@ struct CreatureTemplate uint8 minlevel; uint8 maxlevel; uint32 expansion; + uint32 expansionUnknown; // either 0 or 3, sent to the client / wdb uint32 faction_A; uint32 faction_H; uint32 npcflag; @@ -122,6 +123,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; @@ -137,6 +139,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]; @@ -175,10 +178,6 @@ struct CreatureTemplate // Benchmarked: Faster than std::map (insert/find) typedef UNORDERED_MAP<uint32, CreatureTemplate> CreatureTemplateContainer; -// Represents max amount of expansions. -// TODO: Add MAX_EXPANSION constant. -#define MAX_CREATURE_BASE_HP 3 - // Defines base stats for creatures (used to calculate HP/mana/armor). struct CreatureBaseStats { @@ -199,7 +198,7 @@ struct CreatureBaseStats if (!BaseMana) return 0; - return uint32((BaseMana * info->ModMana) + 0.5f); + return uint32((BaseMana * info->ModMana * info->ModManaExtra) + 0.5f); } uint32 GenerateArmor(CreatureTemplate const* info) const @@ -318,13 +317,14 @@ enum ChatType // 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 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; } @@ -344,12 +344,12 @@ struct VendorItemData } bool Empty() const { return m_items.empty(); } uint8 GetItemCount() const { return m_items.size(); } - void AddItem(uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost) + 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) @@ -407,7 +407,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 300 // Limitation in 4.x.x item count in SMSG_LIST_INVENTORY enum CreatureCellMoveState { @@ -526,11 +526,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature bool SetDisableGravity(bool disable, bool packetOnly = false); bool SetHover(bool enable); - uint32 GetShieldBlockValue() const //dunno mob block value - { - return (getLevel()/2 + uint32(GetStat(STAT_STRENGTH)/20)); - } - SpellSchoolMask GetMeleeDamageSchoolMask() const { return m_meleeDamageSchoolMask; } void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); } @@ -674,8 +669,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature void SetHomePosition(float x, float y, float z, float o) { m_homePosition.Relocate(x, y, z, o); } void SetHomePosition(const Position &pos) { m_homePosition.Relocate(pos); } - void GetHomePosition(float &x, float &y, float &z, float &ori) { m_homePosition.GetPosition(x, y, z, ori); } - Position GetHomePosition() { return m_homePosition; } + void GetHomePosition(float &x, float &y, float &z, float &ori) const { m_homePosition.GetPosition(x, y, z, ori); } + Position GetHomePosition() const { return m_homePosition; } void SetTransportHomePosition(float x, float y, float z, float o) { m_transportHomePosition.Relocate(x, y, z, o); } void SetTransportHomePosition(const Position &pos) { m_transportHomePosition.Relocate(pos); } diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index 63e186ffc42..05ec6f6920d 100755 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -281,11 +281,11 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote eEmote, const std::string& Title sLog->outDebug(LOG_FILTER_NETWORKIO, "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); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u", GUID_LOPART(npcGUID), questStatus); @@ -293,10 +293,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) @@ -307,86 +311,37 @@ 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); } } WorldPacket data(SMSG_QUESTGIVER_QUEST_DETAILS, 100); // guess size data << uint64(npcGUID); - data << uint64(0); // wotlk, something todo with quest sharing? + data << uint64(0); // either 0 or a npc guid (quest giver) data << uint32(quest->GetQuestId()); 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 << 10 * Trinity::Honor::hk_honor_at_level(_session->GetPlayer()->getLevel(), quest->GetRewHonorMultiplier()); - data << float(0.0f); // new 3.3.0, honor multiplier? - data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0) - data << int32(quest->GetRewSpellCast()); // casted 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) @@ -403,6 +358,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 (uint32 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) @@ -418,6 +377,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 (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) ObjectMgr::GetLocaleString(localeData->ObjectiveText[i], locale, questObjectiveText[i]); @@ -458,11 +421,16 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const data << float(0); // new reward honor (multipled by ~62 at client side) data << uint32(quest->GetSrcItemId()); // source item id data << uint32(quest->GetFlags() & 0xFFFF); // 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)) { @@ -491,7 +459,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid+1 QuestFactionReward.dbc? data << int32(quest->RewardFactionValueId[i]); - for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // unk (0) + for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // unknown usage data << int32(quest->RewardFactionValueIdOverride[i]); data << quest->GetPointMapId(); @@ -503,7 +471,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 (uint32 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) { @@ -514,7 +482,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 (uint32 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) @@ -523,9 +491,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 (uint32 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); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", quest->GetQuestId()); } @@ -534,6 +523,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(); int locale = _session->GetSessionDbLocaleIndex(); if (locale >= 0) @@ -542,6 +535,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); } } @@ -551,12 +548,19 @@ 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 uint32 emoteCount = 0; - for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i) + for (uint8 i = 0; i < QUEST_EMOTE_COUNT; ++i) { if (quest->OfferRewardEmote[i] <= 0) break; @@ -564,58 +568,13 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b } data << emoteCount; // Emote Count - for (uint32 i = 0; i < emoteCount; ++i) + for (uint8 i = 0; i < emoteCount; ++i) { data << uint32(quest->OfferRewardEmoteDelay[i]); // Delay Emote 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 << 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 (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); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), quest->GetQuestId()); @@ -651,7 +610,7 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, uint64 npcGUID, data << questTitle; data << requestItemsText; - data << uint32(0x00); // unknown + data << uint32(0); // unknown if (canComplete) data << quest->GetCompleteEmote(); @@ -659,10 +618,7 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, uint64 npcGUID, data << quest->GetIncompleteEmote(); // Close Window after cancel - if (closeOnCancel) - data << uint32(0x01); - else - data << uint32(0x00); + data << uint32(closeOnCancel); data << uint32(quest->GetFlags()); // 3.3.3 questFlags data << uint32(quest->GetSuggestedPlayers()); // SuggestedGroupNum @@ -685,14 +641,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); sLog->outDebug(LOG_FILTER_NETWORKIO, "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 15766bbcd59..237aad4e5b3 100755 --- a/src/server/game/Entities/Creature/GossipDef.h +++ b/src/server/game/Entities/Creature/GossipDef.h @@ -267,7 +267,7 @@ class PlayerMenu /*********************************************************/ /*** QUEST SYSTEM ***/ /*********************************************************/ - void SendQuestGiverStatus(uint8 questStatus, uint64 npcGUID) const; + void SendQuestGiverStatus(uint32 questStatus, uint64 npcGUID) const; void SendQuestGiverQuestList(QEmote eEmote, const std::string& Title, uint64 npcGUID); diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h index 537bbd9c099..f82dfa53f4d 100755 --- a/src/server/game/Entities/Creature/TemporarySummon.h +++ b/src/server/game/Entities/Creature/TemporarySummon.h @@ -34,7 +34,7 @@ class TempSummon : public Creature void SetTempSummonType(TempSummonType type); void SaveToDB(uint32 /*mapid*/, uint8 /*spawnMask*/, uint32 /*phaseMask*/) {} Unit* GetSummoner() const; - uint64 GetSummonerGUID() { return m_summonerGUID; } + uint64 GetSummonerGUID() const { return m_summonerGUID; } TempSummonType const& GetSummonType() { return m_type; } uint32 GetTimer() { return m_timer; } diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp index cd4a9443867..065333dc9e2 100755 --- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp +++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp @@ -33,7 +33,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; } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index b229f00fcd7..18ed5632793 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -29,7 +29,7 @@ #include "ScriptMgr.h" #include "CreatureAISelector.h" #include "Group.h" - +#include "MapManager.h" #include "GameObjectModel.h" #include "DynamicTree.h" @@ -38,7 +38,7 @@ GameObject::GameObject() : WorldObject(false), m_model(NULL), m_goValue(new Game 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; @@ -229,6 +229,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); @@ -310,7 +311,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); diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index eb2fa8f1a0e..b3efb47dd6f 100755 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -51,6 +51,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 diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index c032647d924..3eb9aabab14 100755 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -211,6 +211,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; } @@ -237,7 +241,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; @@ -644,8 +648,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 @@ -661,7 +665,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); } } @@ -781,10 +785,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; } @@ -795,10 +804,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; } @@ -807,10 +821,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; } @@ -818,15 +838,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; } @@ -838,8 +858,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; @@ -1196,3 +1216,307 @@ 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; + uint8 wepType = -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->ClothFactor; + break; + } + case ITEM_SUBCLASS_ARMOR_MAIL: + { + typeFactor = armorPrice->ClothFactor; + break; + } + case ITEM_SUBCLASS_ARMOR_PLATE: + { + typeFactor = armorPrice->ClothFactor; + 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: + wepType = 0; // unk enum, fall back + case INVTYPE_WEAPONOFFHAND: + wepType = 1; // unk enum, fall back + case INVTYPE_WEAPON: + wepType = 2; // unk enum, fall back + case INVTYPE_2HWEAPON: + wepType = 3; // unk enum, fall back + case INVTYPE_RANGED: + case INVTYPE_RANGEDRIGHT: + case INVTYPE_RELIC: + { + wepType = 4; // unk enum + + ImportPriceWeaponEntry const* weaponPrice = sImportPriceWeaponStore.LookupEntry(wepType + 1); + if (!weaponPrice) + return 0; + + typeFactor = weaponPrice->Factor; + break; + } + default: + return proto->BuyPrice; + } + + 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 (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 && 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 && 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; +} diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index a5f9ed5c008..b5ee171e6b1 100755 --- 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) @@ -315,10 +322,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); @@ -341,6 +349,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/ItemEnchantmentMgr.cpp b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp index f85bf80e145..5b427c48a4b 100755 --- a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp +++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp @@ -73,7 +73,7 @@ void LoadRandomEnchantmentsTable() sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u Item Enchantment definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty."); } uint32 GetItemEnchantMod(int32 entry) diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h index 5088a30157c..317e30b88f6 100755 --- 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 { @@ -140,7 +145,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 }; /* TODO @@ -189,7 +194,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 @@ -199,6 +210,20 @@ 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, + // ... +}; + +enum ItemVendorType +{ + ITEM_VENDOR_TYPE_ITEM = 1, + ITEM_VENDOR_TYPE_CURRENCY = 2, +}; + enum BAG_FAMILY_MASK { BAG_FAMILY_MASK_NONE = 0x00000000, @@ -216,7 +241,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 @@ -224,10 +250,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 { @@ -274,14 +302,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 }; @@ -294,7 +322,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 @@ -312,28 +340,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, @@ -358,27 +387,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 { @@ -389,11 +421,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 @@ -414,15 +446,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 @@ -439,22 +470,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 }; @@ -463,10 +496,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 { @@ -490,10 +525,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 { @@ -549,24 +585,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; @@ -589,11 +620,13 @@ struct ItemTemplate uint32 Class; // id from ItemClass.dbc uint32 SubClass; // id from ItemSubClass.dbc int32 Unk0; - std::string Name1; + std::string Name1; uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc uint32 Quality; uint32 Flags; uint32 Flags2; + float Unk430_1; + float Unk430_2; uint32 BuyCount; int32 BuyPrice; uint32 SellPrice; @@ -612,24 +645,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; @@ -639,7 +662,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 @@ -649,13 +671,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; @@ -689,29 +721,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; @@ -736,9 +745,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) @@ -750,17 +766,6 @@ struct ItemLocale StringVector Description; }; -struct ItemSetNameEntry -{ - std::string name; - uint32 InventoryType; -}; - -struct ItemSetNameLocale -{ - StringVector Name; -}; - // GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform #if defined(__GNUC__) #pragma pack() diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 2e4ad07f86d..2ccb5b68bca 100755..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 "Battlefield.h" #include "BattlefieldMgr.h" @@ -139,21 +140,8 @@ void Object::_Create(uint32 guidlow, uint32 entry, HighGuid guidhigh) uint64 guid = MAKE_NEW_GUID(guidlow, entry, guidhigh); SetUInt64Value(OBJECT_FIELD_GUID, guid); - uint32 type = 0; - switch (m_objectType) - { - //case TYPEID_ITEM: type = 3; break; - //case TYPEID_CONTAINER: type = 7; break; //+4 - //case TYPEID_UNIT: type = 9; break; //+2 - //case TYPEID_PLAYER: type = 25; break; //+16 - //case TYPEID_GAMEOBJECT: type = 33; break; //+8 - case TYPEID_DYNAMICOBJECT: type = 65; break; //+32 - //case TYPEID_CORPSE: type = 129; break; //+64 - default: type = m_objectType; break; - } - SetUInt32Value(OBJECT_FIELD_TYPE, type); - //SetUInt32Value(OBJECT_FIELD_TYPE, m_objectType); - m_PackGUID.wpos(0); + SetUInt16Value(OBJECT_FIELD_TYPE, 0, m_objectType); + m_PackGUID.clear(); m_PackGUID.appendPackGUID(GetGUID()); } @@ -189,40 +177,42 @@ 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) return; - uint8 updatetype = UPDATETYPE_CREATE_OBJECT; + uint8 updateType = UPDATETYPE_CREATE_OBJECT; uint16 flags = m_updateFlag; + uint32 valCount = m_valuesCount; + /** lower flag1 **/ if (target == this) // building packet for yourself flags |= UPDATEFLAG_SELF; + else if (GetTypeId() == TYPEID_PLAYER) + valCount = PLAYER_END_NOT_SELF; - if (flags & UPDATEFLAG_STATIONARY_POSITION) + switch (GetGUIDHigh()) { - // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses... - if (isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER)) - updatetype = UPDATETYPE_CREATE_OBJECT2; - - // UPDATETYPE_CREATE_OBJECT2 for pets... - if (target->GetPetGUID() == GetGUID()) - updatetype = UPDATETYPE_CREATE_OBJECT2; + case HIGHGUID_PLAYER: + case HIGHGUID_PET: + case HIGHGUID_CORPSE: + case HIGHGUID_DYNAMICOBJECT: + updateType = UPDATETYPE_CREATE_OBJECT2; + break; + case HIGHGUID_UNIT: + if (ToUnit()->ToTempSummon() && IS_PLAYER_GUID(ToUnit()->ToTempSummon()->GetSummonerGUID())) + updateType = UPDATETYPE_CREATE_OBJECT2; + break; + case HIGHGUID_GAMEOBJECT: + if (IS_PLAYER_GUID(ToGameObject()->GetOwnerGUID())) + updateType = UPDATETYPE_CREATE_OBJECT2; + break; + } + if (flags & UPDATEFLAG_STATIONARY_POSITION) + { // UPDATETYPE_CREATE_OBJECT2 for some gameobject types... if (isType(TYPEMASK_GAMEOBJECT)) { @@ -232,7 +222,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c case GAMEOBJECT_TYPE_DUEL_ARBITER: case GAMEOBJECT_TYPE_FLAGSTAND: case GAMEOBJECT_TYPE_FLAGDROP: - updatetype = UPDATETYPE_CREATE_OBJECT2; + updateType = UPDATETYPE_CREATE_OBJECT2; break; case GAMEOBJECT_TYPE_TRANSPORT: flags |= UPDATEFLAG_TRANSPORT; @@ -241,34 +231,29 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c break; } } - - if (isType(TYPEMASK_UNIT)) - { - if (((Unit*)this)->getVictim()) - flags |= UPDATEFLAG_HAS_TARGET; - } } - //sLog->outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2); + if (ToUnit() && ToUnit()->getVictim()) + flags |= UPDATEFLAG_HAS_TARGET; ByteBuffer buf(500); - buf << (uint8)updatetype; + buf << uint8(updateType); buf.append(GetPackGUID()); - buf << (uint8)m_objectTypeId; + buf << uint8(m_objectTypeId); _BuildMovementUpdate(&buf, flags); UpdateMask updateMask; - updateMask.SetCount(m_valuesCount); + updateMask.SetCount(valCount); _SetCreateBits(&updateMask, target); - _BuildValuesUpdate(updatetype, &buf, &updateMask, target); + _BuildValuesUpdate(updateType, &buf, &updateMask, target); data->AddUpdateBlock(buf); } void Object::SendUpdateToPlayer(Player* player) { // send create update to player - UpdateData upd; + UpdateData upd(player->GetMapId()); WorldPacket packet; BuildCreateUpdateBlockForPlayer(&upd, player); @@ -280,11 +265,15 @@ void Object::BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) c { ByteBuffer buf(500); - buf << (uint8) UPDATETYPE_VALUES; + buf << uint8(UPDATETYPE_VALUES); buf.append(GetPackGUID()); UpdateMask updateMask; - updateMask.SetCount(m_valuesCount); + uint32 valCount = m_valuesCount; + if (GetTypeId() == TYPEID_PLAYER && target != this) + valCount = PLAYER_END_NOT_SELF; + + updateMask.SetCount(valCount); _SetUpdateBits(&updateMask, target); _BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target); @@ -311,150 +300,308 @@ void Object::DestroyForPlayer(Player* target, bool onDeath) const void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const { - *data << uint16(flags); // update flags + 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); - // 0x20 if (flags & UPDATEFLAG_LIVING) { - ((Unit*)this)->BuildMovementPacket(data); + Unit const* self = ToUnit(); + ObjectGuid guid = GetGUID(); + uint32 movementFlags = self->m_movementInfo.GetMovementFlags(); + uint16 movementFlagsExtra = self->m_movementInfo.GetExtraMovementFlags(); + 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(0); + data->WriteBit(!((movementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || + (movementFlagsExtra & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING))); // Has pitch + data->WriteBit(self->IsSplineEnabled()); // Has spline data + data->WriteBit(movementFlagsExtra & MOVEMENTFLAG2_INTERPOLATED_TURNING);// Has fall data + data->WriteBit(!(movementFlags & MOVEMENTFLAG_SPLINE_ELEVATION)); // Has spline elevation + data->WriteBit(guid[5]); + data->WriteBit(self->m_movementInfo.t_guid); // Has transport data + data->WriteBit(0); // Is missing time + if (self->m_movementInfo.t_guid) + { + ObjectGuid transGuid = self->m_movementInfo.t_guid; + + data->WriteBit(transGuid[1]); + data->WriteBit(0); // Has transport time 2 + data->WriteBit(transGuid[4]); + data->WriteBit(transGuid[0]); + data->WriteBit(transGuid[6]); + data->WriteBit(0); // Has transport time 3 + data->WriteBit(transGuid[7]); + data->WriteBit(transGuid[5]); + data->WriteBit(transGuid[3]); + data->WriteBit(transGuid[2]); + } + + data->WriteBit(guid[4]); + if (self->IsSplineEnabled()) + Movement::PacketBuilder::WriteCreateBits(*self->movespline, *data); - *data << ((Unit*)this)->GetSpeed(MOVE_WALK); - *data << ((Unit*)this)->GetSpeed(MOVE_RUN); - *data << ((Unit*)this)->GetSpeed(MOVE_RUN_BACK); - *data << ((Unit*)this)->GetSpeed(MOVE_SWIM); - *data << ((Unit*)this)->GetSpeed(MOVE_SWIM_BACK); - *data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT); - *data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT_BACK); - *data << ((Unit*)this)->GetSpeed(MOVE_TURN_RATE); - *data << ((Unit*)this)->GetSpeed(MOVE_PITCH_RATE); + data->WriteBit(guid[6]); + if (movementFlagsExtra & MOVEMENTFLAG2_INTERPOLATED_TURNING) + data->WriteBit(movementFlags & MOVEMENTFLAG_FALLING); - // 0x08000000 - if (((Unit*)this)->m_movementInfo.GetMovementFlags() & MOVEMENTFLAG_SPLINE_ENABLED) - Movement::PacketBuilder::WriteCreate(*((Unit*)this)->movespline, *data); + 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) - { - Transport* transport = ((WorldObject*)this)->GetTransport(); - if (transport) - data->append(transport->GetPackGUID()); - else - *data << uint8(0); + WorldObject const* self = static_cast<WorldObject const*>(this); + ObjectGuid transGuid = self->m_movementInfo.t_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]); + } - *data << ((WorldObject*)this)->GetPositionX(); - *data << ((WorldObject*)this)->GetPositionY(); - if (isType(TYPEMASK_UNIT)) - *data << ((Unit*)this)->GetPositionZMinusOffset(); - else - *data << ((WorldObject*)this)->GetPositionZ(); + if (flags & UPDATEFLAG_HAS_TARGET) + { + ObjectGuid victimGuid = ToUnit()->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]); + } - if (transport) - { - *data << ((WorldObject*)this)->GetTransOffsetX(); - *data << ((WorldObject*)this)->GetTransOffsetY(); - *data << ((WorldObject*)this)->GetTransOffsetZ(); - } - else - { - *data << ((WorldObject*)this)->GetPositionX(); - *data << ((WorldObject*)this)->GetPositionY(); - if (isType(TYPEMASK_UNIT)) - *data << ((Unit*)this)->GetPositionZMinusOffset(); - else - *data << ((WorldObject*)this)->GetPositionZ(); - } + if (flags & UPDATEFLAG_ANIMKITS) + { + data->WriteBit(1); // Missing AnimKit1 + data->WriteBit(1); // Missing AnimKit2 + data->WriteBit(1); // Missing AnimKit3 + } - *data << ((WorldObject*)this)->GetOrientation(); + data->FlushBits(); - if (GetTypeId() == TYPEID_CORPSE) - *data << float(((WorldObject*)this)->GetOrientation()); - else - *data << float(0); - } - else + // Data + for (uint32 i = 0; i < unkLoopCounter; ++i) + *data << uint32(0); + + if (flags & UPDATEFLAG_LIVING) + { + Unit const* self = ToUnit(); + ObjectGuid guid = GetGUID(); + uint32 movementFlags = self->m_movementInfo.GetMovementFlags(); + uint16 movementFlagsExtra = self->m_movementInfo.GetExtraMovementFlags(); + if (GetTypeId() == TYPEID_UNIT) + movementFlags &= MOVEMENTFLAG_MASK_CREATURE_ALLOWED; + + data->WriteByteSeq(guid[4]); + *data << self->GetSpeed(MOVE_RUN_BACK); + if (movementFlagsExtra & MOVEMENTFLAG2_INTERPOLATED_TURNING) { - // 0x40 - if (flags & UPDATEFLAG_STATIONARY_POSITION) + if (movementFlags & MOVEMENTFLAG_FALLING) { - *data << ((WorldObject*)this)->GetPositionX(); - *data << ((WorldObject*)this)->GetPositionY(); - if (isType(TYPEMASK_UNIT)) - *data << ((Unit*)this)->GetPositionZMinusOffset(); - else - *data << ((WorldObject*)this)->GetPositionZ(); - *data << ((WorldObject*)this)->GetOrientation(); + *data << float(self->m_movementInfo.j_cosAngle); + *data << float(self->m_movementInfo.j_xyspeed); + *data << float(self->m_movementInfo.j_sinAngle); } + + *data << uint32(self->m_movementInfo.fallTime); + *data << float(self->m_movementInfo.j_zspeed); } - } - // 0x8 - if (flags & UPDATEFLAG_UNKNOWN) - { - *data << uint32(0); - } + *data << self->GetSpeed(MOVE_SWIM_BACK); + if (movementFlags & MOVEMENTFLAG_SPLINE_ELEVATION) + *data << float(self->m_movementInfo.splineElevation); - // 0x10 - if (flags & UPDATEFLAG_LOWGUID) - { - switch (GetTypeId()) + if (self->IsSplineEnabled()) + Movement::PacketBuilder::WriteCreateData(*self->movespline, *data); + + *data << float(self->GetPositionZMinusOffset()); + data->WriteByteSeq(guid[5]); + if (self->m_movementInfo.t_guid) { - 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; + ObjectGuid transGuid = self->m_movementInfo.t_guid; + + data->WriteByteSeq(transGuid[5]); + data->WriteByteSeq(transGuid[7]); + *data << uint32(self->GetTransTime()); + *data << float(self->GetTransOffsetO()); + //if (hasTransportTime2) + // *data << uint32(0); + + *data << float(self->GetTransOffsetY()); + *data << float(self->GetTransOffsetX()); + data->WriteByteSeq(transGuid[3]); + *data << float(self->GetTransOffsetZ()); + data->WriteByteSeq(transGuid[0]); + //if (hasTransportTime3) + // *data << uint32(0); + + *data << int8(self->GetTransSeat()); + data->WriteByteSeq(transGuid[1]); + data->WriteByteSeq(transGuid[6]); + data->WriteByteSeq(transGuid[2]); + data->WriteByteSeq(transGuid[4]); } - } - // 0x4 - if (flags & UPDATEFLAG_HAS_TARGET) - { - if (Unit* victim = ((Unit*)this)->getVictim()) - data->append(victim->GetPackGUID()); - else - *data << uint8(0); + *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_FLIGHT_BACK); + data->WriteByteSeq(guid[6]); + *data << self->GetSpeed(MOVE_TURN_RATE); + if (!G3D::fuzzyEq(self->GetOrientation(), 0.0f)) + *data << float(self->GetOrientation()); + + *data << self->GetSpeed(MOVE_RUN); + if ((movementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || + (movementFlagsExtra & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)) + *data << float(self->m_movementInfo.pitch); + + *data << self->GetSpeed(MOVE_FLIGHT); } - // 0x2 - if (flags & UPDATEFLAG_TRANSPORT) + if (flags & UPDATEFLAG_VEHICLE) { - *data << uint32(getMSTime()); // Unknown - getMSTime is wrong. + Unit const* self = ToUnit(); + *data << float(self->GetOrientation()); + *data << uint32(self->GetVehicleKit()->GetVehicleInfo()->m_ID); } - // 0x80 - if (flags & UPDATEFLAG_VEHICLE) + if (flags & UPDATEFLAG_GO_TRANSPORT_POSITION) { - // TODO: Allow players to aquire this updateflag. - *data << uint32(((Unit*)this)->GetVehicleKit()->GetVehicleInfo()->m_ID); - *data << float(((Creature*)this)->GetOrientation()); + WorldObject const* self = static_cast<WorldObject const*>(this); + ObjectGuid transGuid = self->m_movementInfo.t_guid; + + data->WriteBit(transGuid[0]); + data->WriteBit(transGuid[5]); + //if (hasTransportTime3) + // *data << uint32(0); + + 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(0); } - // 0x200 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) { - *data << int64(((GameObject*)this)->GetRotation()); + WorldObject const* self = static_cast<WorldObject const*>(this); + *data << float(self->GetOrientation()); + *data << float(self->GetPositionX()); + *data << float(self->GetPositionY()); + if (Unit const* unit = ToUnit()) + *data << float(unit->GetPositionZMinusOffset()); + else + *data << float(self->GetPositionZ()); } + + if (flags & UPDATEFLAG_HAS_TARGET) + { + ObjectGuid victimGuid = ToUnit()->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) + *data << uint32(getMSTime()); // Unknown - getMSTime is wrong. } -void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* updateMask, Player* target) const +void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* updateMask, Player* target) const { if (!target) return; @@ -496,7 +643,11 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* } } - WPAssert(updateMask && updateMask->GetCount() == m_valuesCount); + uint32 valCount = m_valuesCount; + if (GetTypeId() == TYPEID_PLAYER && target != this) + valCount = PLAYER_END_NOT_SELF; + + WPAssert(updateMask && updateMask->GetCount() == valCount); *data << (uint8)updateMask->GetBlockCount(); data->append(updateMask->GetMask(), updateMask->GetLength()); @@ -504,7 +655,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* // 2 specialized loops for speed optimization in non-unit case if (isType(TYPEMASK_UNIT)) // unit (creature/player) case { - for (uint16 index = 0; index < m_valuesCount; ++index) + for (uint16 index = 0; index < valCount; ++index) { if (updateMask->GetBit(index)) { @@ -668,7 +819,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* } else if (isType(TYPEMASK_GAMEOBJECT)) // gameobject case { - for (uint16 index = 0; index < m_valuesCount; ++index) + for (uint16 index = 0; index < valCount; ++index) { if (updateMask->GetBit(index)) { @@ -684,35 +835,28 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* *data << uint16(GO_DYNFLAG_LO_ACTIVATE); else *data << uint16(GO_DYNFLAG_LO_ACTIVATE | GO_DYNFLAG_LO_SPARKLE); - *data << uint16(-1); break; case GAMEOBJECT_TYPE_GENERIC: if (target->isGameMaster()) *data << uint16(0); else *data << uint16(GO_DYNFLAG_LO_SPARKLE); - *data << uint16(-1); break; case GAMEOBJECT_TYPE_GOOBER: if (target->isGameMaster()) *data << uint16(GO_DYNFLAG_LO_ACTIVATE); else *data << uint16(GO_DYNFLAG_LO_ACTIVATE | GO_DYNFLAG_LO_SPARKLE); - *data << uint16(-1); break; default: - // unknown, not happen. - *data << uint16(0); - *data << uint16(-1); + *data << uint16(0); // unknown, not happen. break; } } else - { - // disable quest object - *data << uint16(0); - *data << uint16(-1); - } + *data << uint16(0); // disable quest object + + *data << uint16(-1); } else if (index == GAMEOBJECT_FLAGS) { @@ -730,7 +874,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* } else // other objects case (no special index checks) { - for (uint16 index = 0; index < m_valuesCount; ++index) + for (uint16 index = 0; index < valCount; ++index) { if (updateMask->GetBit(index)) { @@ -759,7 +903,7 @@ void Object::BuildFieldsUpdate(Player* player, UpdateDataMapType& data_map) cons if (iter == data_map.end()) { - std::pair<UpdateDataMapType::iterator, bool> p = data_map.insert(UpdateDataMapType::value_type(player, UpdateData())); + std::pair<UpdateDataMapType::iterator, bool> p = data_map.insert(UpdateDataMapType::value_type(player, UpdateData(player->GetMapId()))); ASSERT(p.second); iter = p.first; } @@ -856,7 +1000,11 @@ void Object::_SetUpdateBits(UpdateMask* updateMask, Player* target) const GetUpdateFieldData(target, flags, isOwner, isItemOwner, hasSpecialInfo, isPartyMember); - for (uint16 index = 0; index < m_valuesCount; ++index, ++indexes) + uint32 valCount = m_valuesCount; + if (GetTypeId() == TYPEID_PLAYER && target != this) + valCount = PLAYER_END_NOT_SELF; + + for (uint16 index = 0; index < valCount; ++index, ++indexes) if (_fieldNotifyFlags & flags[index] || (flags[index] & UF_FLAG_SPECIAL_INFO && hasSpecialInfo) || (*indexes && IsUpdateFieldVisible(flags[index], isSelf, isOwner, isItemOwner, isPartyMember))) updateMask->SetBit(index); } @@ -873,7 +1021,11 @@ void Object::_SetCreateBits(UpdateMask* updateMask, Player* target) const GetUpdateFieldData(target, flags, isOwner, isItemOwner, hasSpecialInfo, isPartyMember); - for (uint16 index = 0; index < m_valuesCount; ++index, ++value) + uint32 valCount = m_valuesCount; + if (GetTypeId() == TYPEID_PLAYER && target != this) + valCount = PLAYER_END_NOT_SELF; + + for (uint16 index = 0; index < valCount; ++index, ++value) if (_fieldNotifyFlags & flags[index] || (flags[index] & UF_FLAG_SPECIAL_INFO && hasSpecialInfo) || (*value && IsUpdateFieldVisible(flags[index], isSelf, isOwner, isItemOwner, isPartyMember))) updateMask->SetBit(index); } @@ -1244,7 +1396,7 @@ void MovementInfo::OutDebug() sLog->outInfo(LOG_FILTER_GENERAL, "flags2 %u", flags2); sLog->outInfo(LOG_FILTER_GENERAL, "time %u current time " UI64FMTD "", flags2, uint64(::time(NULL))); sLog->outInfo(LOG_FILTER_GENERAL, "position: `%s`", pos.ToString().c_str()); - if (flags & MOVEMENTFLAG_ONTRANSPORT) + if (t_guid) { sLog->outInfo(LOG_FILTER_GENERAL, "TRANSPORT:"); sLog->outInfo(LOG_FILTER_GENERAL, "guid: " UI64FMTD, t_guid); @@ -1514,7 +1666,7 @@ void Position::RelocateOffset(const Position & offset) m_positionX = GetPositionX() + (offset.GetPositionX() * cos(GetOrientation()) + offset.GetPositionY() * sin(GetOrientation() + M_PI)); m_positionY = GetPositionY() + (offset.GetPositionY() * cos(GetOrientation()) + offset.GetPositionX() * sin(GetOrientation())); m_positionZ = GetPositionZ() + offset.GetPositionZ(); - m_orientation = GetOrientation() + offset.GetOrientation(); + SetOrientation(GetOrientation() + offset.GetOrientation()); } void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset) const @@ -1525,7 +1677,7 @@ void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset retOffset.m_positionX = dx * cos(GetOrientation()) + dy * sin(GetOrientation()); retOffset.m_positionY = dy * cos(GetOrientation()) - dx * sin(GetOrientation()); retOffset.m_positionZ = endPos.GetPositionZ() - GetPositionZ(); - retOffset.m_orientation = endPos.GetOrientation() - GetOrientation(); + retOffset.SetOrientation(endPos.GetOrientation() - GetOrientation()); } float Position::GetAngle(const Position* obj) const @@ -1573,13 +1725,13 @@ bool Position::HasInArc(float arc, const Position* obj) const return true; // move arc to range 0.. 2*pi - arc = MapManager::NormalizeOrientation(arc); + arc = NormalizeOrientation(arc); float angle = GetAngle(obj); angle -= m_orientation; // move angle to range -pi ... +pi - angle = MapManager::NormalizeOrientation(angle); + angle = NormalizeOrientation(angle); if (angle > M_PI) angle -= 2.0f*M_PI; @@ -2141,6 +2293,8 @@ void WorldObject::BuildMonsterChat(WorldPacket* data, uint8 msgtype, char const* *data << (uint32)(strlen(text)+1); *data << text; *data << (uint8)0; // ChatTag + *data << (float)0.0f; // added in 4.2.0, unk + *data << (uint8)0; // added in 4.2.0, unk } void Unit::BuildHeartBeatMsg(WorldPacket* data) const @@ -2774,7 +2928,7 @@ void WorldObject::GetNearPoint(WorldObject const* /*searcher*/, float &x, float void WorldObject::MovePosition(Position &pos, float dist, float angle) { - angle += m_orientation; + angle += GetOrientation(); float destx, desty, destz, ground, floor; destx = pos.m_positionX + dist * cos(angle); desty = pos.m_positionY + dist * sin(angle); @@ -2814,12 +2968,12 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle) Trinity::NormalizeMapCoord(pos.m_positionX); Trinity::NormalizeMapCoord(pos.m_positionY); UpdateGroundPositionZ(pos.m_positionX, pos.m_positionY, pos.m_positionZ); - pos.m_orientation = m_orientation; + pos.SetOrientation(GetOrientation()); } void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float angle) { - angle += m_orientation; + angle += GetOrientation(); float destx, desty, destz, ground, floor; pos.m_positionZ += 2.0f; destx = pos.m_positionX + dist * cos(angle); @@ -2882,7 +3036,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float Trinity::NormalizeMapCoord(pos.m_positionX); Trinity::NormalizeMapCoord(pos.m_positionY); UpdateAllowedPositionZ(pos.m_positionX, pos.m_positionY, pos.m_positionZ); - pos.m_orientation = m_orientation; + pos.SetOrientation(GetOrientation()); } void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index ab9ea2daea9..e3d940360f2 100755 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -119,6 +119,62 @@ class Transport; typedef 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 = 0LL; } + 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 +203,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; @@ -307,19 +362,24 @@ class Object void ForceValuesUpdateAtIndex(uint32); Player* ToPlayer() { if (GetTypeId() == TYPEID_PLAYER) return reinterpret_cast<Player*>(this); else return NULL; } - Player const* ToPlayer() const { if (GetTypeId() == TYPEID_PLAYER) return (Player const*)((Player*)this); else return NULL; } + Player const* ToPlayer() const { if (GetTypeId() == TYPEID_PLAYER) return reinterpret_cast<Player const*>(this); else return NULL; } + Creature* ToCreature() { if (GetTypeId() == TYPEID_UNIT) return reinterpret_cast<Creature*>(this); else return NULL; } - Creature const* ToCreature() const { if (GetTypeId() == TYPEID_UNIT) return (Creature const*)((Creature*)this); else return NULL; } + Creature const* ToCreature() const { if (GetTypeId() == TYPEID_UNIT) return reinterpret_cast<Creature const*>(this); else return NULL; } + + Unit* ToUnit() { if (isType(TYPEMASK_UNIT)) return reinterpret_cast<Unit*>(this); else return NULL; } + Unit const* ToUnit() const { if (isType(TYPEMASK_UNIT)) return reinterpret_cast<Unit const*>(this); else return NULL; } - Unit* ToUnit() { if (GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER) return reinterpret_cast<Unit*>(this); else return NULL; } - Unit const* ToUnit() const { if (GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER) return (const Unit*)((Unit*)this); else return NULL; } GameObject* ToGameObject() { if (GetTypeId() == TYPEID_GAMEOBJECT) return reinterpret_cast<GameObject*>(this); else return NULL; } - GameObject const* ToGameObject() const { if (GetTypeId() == TYPEID_GAMEOBJECT) return (const GameObject*)((GameObject*)this); else return NULL; } + GameObject const* ToGameObject() const { if (GetTypeId() == TYPEID_GAMEOBJECT) return reinterpret_cast<GameObject const*>(this); else return NULL; } Corpse* ToCorpse() { if (GetTypeId() == TYPEID_CORPSE) return reinterpret_cast<Corpse*>(this); else return NULL; } - Corpse const* ToCorpse() const { if (GetTypeId() == TYPEID_CORPSE) return (const Corpse*)((Corpse*)this); else return NULL; } - protected: + Corpse const* ToCorpse() const { if (GetTypeId() == TYPEID_CORPSE) return reinterpret_cast<Corpse const*>(this); else return NULL; } + + 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; } + protected: Object(); void _InitValues(); @@ -384,21 +444,24 @@ struct Position float m_positionX; float m_positionY; float m_positionZ; +// Better to limit access to m_orientation field, but this will be hard to achieve with many scripts using array initialization for this structure +//private: float m_orientation; +//public: void Relocate(float x, float y) { m_positionX = x; m_positionY = y;} void Relocate(float x, float y, float z) { m_positionX = x; m_positionY = y; m_positionZ = z; } void Relocate(float x, float y, float z, float orientation) - { m_positionX = x; m_positionY = y; m_positionZ = z; m_orientation = orientation; } + { m_positionX = x; m_positionY = y; m_positionZ = z; SetOrientation(orientation); } void Relocate(const Position &pos) - { m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; m_orientation = pos.m_orientation; } + { m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; SetOrientation(pos.m_orientation); } void Relocate(const Position* pos) - { m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; m_orientation = pos->m_orientation; } + { m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; SetOrientation(pos->m_orientation); } void RelocateOffset(const Position &offset); void SetOrientation(float orientation) - { m_orientation = orientation; } + { m_orientation = NormalizeOrientation(orientation); } float GetPositionX() const { return m_positionX; } float GetPositionY() const { return m_positionY; } @@ -465,6 +528,21 @@ struct Position bool HasInArc(float arcangle, const Position* pos) const; bool HasInLine(WorldObject const* target, float width) const; std::string ToString() const; + + // modulos a radian orientation to the range of 0..2PI + static float NormalizeOrientation(float o) + { + // fmod only supports positive numbers. Thus we have + // to emulate negative numbers + if (o < 0) + { + float mod = o *-1; + mod = fmod(mod, 2.0f * static_cast<float>(M_PI)); + mod = -mod + 2.0f * static_cast<float>(M_PI); + return mod; + } + return fmod(o, 2.0f * static_cast<float>(M_PI)); + } }; ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); @@ -474,25 +552,26 @@ ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& st struct MovementInfo { // common - uint64 guid; - uint32 flags; - uint16 flags2; + uint64 guid; + uint32 flags; + uint16 flags2; Position pos; - uint32 time; + uint32 time; // transport - uint64 t_guid; + uint64 t_guid; Position t_pos; - uint32 t_time; - uint32 t_time2; - int8 t_seat; + int8 t_seat; + uint32 t_time; + uint32 t_time2; + uint32 t_time3; // swimming/flying - float pitch; + float pitch; // falling - uint32 fallTime; + uint32 fallTime; // jumping - float j_zspeed, j_sinAngle, j_cosAngle, j_xyspeed; + float j_zspeed, j_cosAngle, j_sinAngle, j_xyspeed; // spline - float splineElevation; + float splineElevation; MovementInfo() { @@ -500,7 +579,7 @@ struct MovementInfo guid = 0; flags = 0; flags2 = 0; - time = t_time = t_time2 = fallTime = 0; + time = t_time = t_time2 = t_time3 = fallTime = 0; splineElevation = 0; pitch = j_zspeed = j_sinAngle = j_cosAngle = j_xyspeed = 0.0f; t_guid = 0; diff --git a/src/server/game/Entities/Object/ObjectDefines.h b/src/server/game/Entities/Object/ObjectDefines.h index c227d081d8b..9fd4279a79c 100755 --- a/src/server/game/Entities/Object/ObjectDefines.h +++ b/src/server/game/Entities/Object/ObjectDefines.h @@ -33,18 +33,19 @@ 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_CORPSE = 0xF101, // blizz F100 - HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT) - HIGHGUID_GROUP = 0x1F50, + 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 = 0x1FC, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT) + HIGHGUID_GROUP = 0x1F5, + HIGHGUID_GUILD = 0x1FF5, // new 4.x }; #define IS_EMPTY_GUID(Guid) (Guid == 0) @@ -64,19 +65,25 @@ enum HighGuid #define IS_TRANSPORT(Guid) (GUID_HIPART(Guid) == HIGHGUID_TRANSPORT) #define IS_MO_TRANSPORT(Guid) (GUID_HIPART(Guid) == HIGHGUID_MO_TRANSPORT) #define IS_GROUP(Guid) (GUID_HIPART(Guid) == HIGHGUID_GROUP) +#define IS_GUILD(Guid) (GUID_HIPART(Guid) == HIGHGUID_GUILD) // l - OBJECT_FIELD_GUID // e - OBJECT_FIELD_ENTRY for GO (except GAMEOBJECT_TYPE_MO_TRANSPORT) and creatures or UNIT_FIELD_PETNUMBER for pets // h - OBJECT_FIELD_GUID + 1 -#define MAKE_NEW_GUID(l, e, h) uint64(uint64(l) | (uint64(e) << 24) | (uint64(h) << 48)) +#define MAKE_NEW_GUID(l, e, h) uint64(uint64(l) | (uint64(e) << 32) | (uint64(h) << ((h == HIGHGUID_GUILD || h == HIGHGUID_CORPSE) ? 48 : 52))) -#define GUID_HIPART(x) (uint32)((uint64(x) >> 48) & 0x0000FFFF) +//#define GUID_HIPART(x) (uint32)((uint64(x) >> 52)) & 0x0000FFFF) +inline uint32 GUID_HIPART(uint64 guid) +{ + uint32 t = ((uint64(guid) >> 48) & 0x0000FFFF); + return (t == HIGHGUID_GUILD || t == HIGHGUID_CORPSE) ? t : ((uint32(t) >> 4) & 0x00000FFF); +} // We have different low and middle part size for different guid types #define _GUID_ENPART_2(x) 0 -#define _GUID_ENPART_3(x) (uint32)((uint64(x) >> 24) & UI64LIT(0x0000000000FFFFFF)) +#define _GUID_ENPART_3(x) (uint32)((uint64(x) >> 32) & UI64LIT(0x00000000000FFFFF)) #define _GUID_LOPART_2(x) (uint32)(uint64(x) & UI64LIT(0x00000000FFFFFFFF)) -#define _GUID_LOPART_3(x) (uint32)(uint64(x) & UI64LIT(0x0000000000FFFFFF)) +#define _GUID_LOPART_3(x) (uint32)(uint64(x) & UI64LIT(0x00000000FFFFFFFF)) inline bool IsGuidHaveEnPart(uint64 guid) { @@ -87,6 +94,7 @@ inline bool IsGuidHaveEnPart(uint64 guid) case HIGHGUID_DYNAMICOBJECT: case HIGHGUID_CORPSE: case HIGHGUID_GROUP: + case HIGHGUID_GUILD: return false; case HIGHGUID_GAMEOBJECT: case HIGHGUID_TRANSPORT: @@ -117,6 +125,7 @@ inline 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"; default: return "<unknown>"; } diff --git a/src/server/game/Entities/Object/Updates/UpdateData.cpp b/src/server/game/Entities/Object/Updates/UpdateData.cpp index 45464f19083..afe43ca245c 100755..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) { } @@ -45,104 +45,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) - { - sLog->outError(LOG_FILTER_GENERAL, "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) - { - sLog->outError(LOG_FILTER_GENERAL, "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) - { - sLog->outError(LOG_FILTER_GENERAL, "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) - { - sLog->outError(LOG_FILTER_GENERAL, "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) - { - sLog->outError(LOG_FILTER_GENERAL, "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; } @@ -151,5 +71,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 ff649b7cb2f..27a42be5c2d 100755 --- a/src/server/game/Entities/Object/Updates/UpdateData.h +++ b/src/server/game/Entities/Object/Updates/UpdateData.h @@ -25,32 +25,34 @@ 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(uint16 map); void AddOutOfRangeGUID(std::set<uint64>& guids); void AddOutOfRangeGUID(uint64 guid); @@ -62,11 +64,10 @@ 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); }; #endif diff --git a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.cpp index 95bdaef221b..2c15487180c 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 71b3f0cd4aa..5a4186c9894 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 825bda98ae6..3602cbea648 100755 --- 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 17b214857db..71a68fdba3c 100755 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -35,7 +35,7 @@ Pet::Pet(Player* owner, PetType type) : Guardian(NULL, owner, true), m_usedTalentCount(0), m_removed(false), m_owner(owner), -m_happinessTimer(7500), m_petType(type), m_duration(0), +m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false), m_declinedname(NULL) { m_unitTypeMask |= UNIT_MASK_PET; @@ -147,7 +147,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c if (!petentry) return false; - uint32 summon_spell_id = fields[15].GetUInt32(); + uint32 summon_spell_id = fields[14].GetUInt32(); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summon_spell_id); bool is_temporary_summoned = spellInfo && spellInfo->GetDuration() > 0; @@ -156,7 +156,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c if (current && is_temporary_summoned) return false; - PetType pet_type = PetType(fields[16].GetUInt8()); + PetType pet_type = PetType(fields[15].GetUInt8()); if (pet_type == HUNTER_PET) { CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petentry); @@ -223,8 +223,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: @@ -255,7 +253,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); } } @@ -303,13 +301,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 (!is_temporary_summoned) { - m_charmInfo->LoadPetActionBar(fields[13].GetString()); + m_charmInfo->LoadPetActionBar(fields[12].GetString()); _LoadSpells(); InitTalentForLevel(); // re-init to check talent count @@ -437,7 +435,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() << ',' @@ -450,8 +448,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) { @@ -512,12 +509,6 @@ void Pet::setDeathState(DeathState s) // overwrite virtual // pet corpse non lootable and non skinnable SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE); RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); - - //lose happiness when died and not in BG/Arena - MapEntry const* mapEntry = sMapStore.LookupEntry(GetMapId()); - if (!mapEntry || (mapEntry->map_type != MAP_ARENA && mapEntry->map_type != MAP_BATTLEGROUND)) - ModifyPower(POWER_HAPPINESS, -HAPPINESS_LEVEL_SIZE); - //SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } } @@ -611,18 +602,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: @@ -670,27 +649,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) { m_owner->RemovePet(this, mode, returnreagent); @@ -775,7 +733,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())); @@ -788,7 +746,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()); @@ -803,8 +761,6 @@ bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phas if (!Create(guid, map, phaseMask, cinfo->Entry, pet_number)) 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); @@ -857,6 +813,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); @@ -1893,6 +1850,8 @@ bool Pet::IsPermanentPetFor(Player* owner) 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 3475817816d..5759a58a575 100755 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -42,13 +42,6 @@ enum PetSaveMode PET_SAVE_NOT_IN_SLOT = 100 // for avoid conflict with stable size grow will use 100 }; -enum HappinessState -{ - UNHAPPY = 1, - CONTENT = 2, - HAPPY = 3 -}; - enum PetSpellState { PETSPELL_UNCHANGED = 0, @@ -108,8 +101,6 @@ enum PetNameInvalidReason typedef UNORDERED_MAP<uint32, PetSpell> PetSpellMap; typedef std::vector<uint32> AutoSpellList; -#define HAPPINESS_LEVEL_SIZE 333000 - #define ACTIVE_SPELLS_MAX 4 #define PET_FOLLOW_DIST 1.0f @@ -156,8 +147,6 @@ class Pet : public Guardian return m_autospells[pos]; } - void LoseHappiness(); - HappinessState GetHappinessState(); void GivePetXP(uint32 xp); void GivePetLevel(uint8 level); void SynchronizeLevelWithOwner(); @@ -227,7 +216,6 @@ class Pet : public Guardian Player* GetOwner() { return m_owner; } protected: Player* m_owner; - 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 f463a62e9fa..e20956879b3 100755..100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -74,23 +74,13 @@ #include "InstanceScript.h" #include <cmath> #include "AccountMgr.h" +#include "DB2Stores.h" #include "Battlefield.h" #include "BattlefieldMgr.h" +#include "BattlefieldMgr.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, @@ -205,15 +195,16 @@ void PlayerTaxi::LoadTaxiMask(const char* 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 + for (uint8 i = 0; i < TaxiMaskSize; ++i) + data << uint8(sTaxiNodesMask[i]); // all existed nodes } else { - for (uint8 i=0; i<TaxiMaskSize; i++) - data << uint32(m_taximask[i]); // known nodes + for (uint8 i = 0; i < TaxiMaskSize; ++i) + data << uint8(m_taximask[i]); // known nodes } } @@ -281,7 +272,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; } @@ -359,7 +350,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; @@ -433,6 +424,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()), @@ -624,10 +616,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->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, victim->GetEntry(), 1, victim, _killer); + } + } // == Player ==================================================== @@ -670,11 +670,10 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep 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 = 0; @@ -721,7 +720,7 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep m_DailyQuestChanged = false; m_lastDailyQuestTime = 0; - for (uint8 i=0; i<MAX_TIMERS; i++) + for (uint8 i=0; i < MAX_TIMERS; i++) m_MirrorTimer[i] = DISABLED_MIRROR_TIMER; m_MirrorTimerFlags = UNDERWATER_NONE; @@ -736,7 +735,7 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep for (uint8 j = 0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; ++j) { - m_bgBattlegroundQueueID[j].bgQueueTypeId = BATTLEGROUND_QUEUE_NONE; + m_bgBattlegroundQueueID[j].bgQueueTypeId = BATTLEGROUND_QUEUE_NONE; m_bgBattlegroundQueueID[j].invitedToInstance = 0; } @@ -748,7 +747,6 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep m_canBlock = false; m_canDualWield = false; m_canTitanGrip = false; - m_ammoDPS = 0.0f; m_temporaryUnsummonedPetNumber = 0; //cache for UNIT_CREATED_BY_SPELL to allow @@ -772,8 +770,6 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep unReadMails = 0; m_nextMailDelivereTime = 0; - m_resetTalentsCost = 0; - m_resetTalentsTime = 0; m_itemUpdateQueueBlocked = false; for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) @@ -789,17 +785,7 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep m_raidDifficulty = 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) { @@ -811,7 +797,6 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep m_baseRatingValue[i] = 0; m_baseSpellPower = 0; - m_baseFeralAP = 0; m_baseManaRegen = 0; m_baseHealthRegen = 0; m_spellPenetrationItemMod = 0; @@ -861,6 +846,8 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep m_SeasonalQuestChanged = false; SetPendingBind(0, 0); + + memset(_voidStorageItems, 0, VOID_STORAGE_MAX_SLOT * sizeof(VoidStorageItem*)); } Player::~Player() @@ -875,12 +862,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) @@ -897,6 +879,9 @@ Player::~Player() delete m_declinedname; delete m_runes; + for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i) + delete _voidStorageItems[i]; + sWorld->DecreasePlayerCount(); } @@ -975,6 +960,9 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo) } 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_MOD_CAST_HASTE, 1.0f); + SetFloatValue(PLAYER_FIELD_MOD_HASTE, 1.0f); + SetFloatValue(PLAYER_FIELD_MOD_RANGED_HASTE, 1.0f); SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); // default for players in 3.0.3 // -1 is default value @@ -988,8 +976,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); + SetUInt32Value(PLAYER_GUILDLEVEL, 0); SetUInt32Value(PLAYER_GUILD_TIMESTAMP, 0); for (int i = 0; i < KNOWN_TITLES_SIZE; ++i) @@ -998,8 +987,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 @@ -1018,8 +1005,8 @@ 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_START_HONOR_POINTS)); + SetCurrency(CURRENCY_TYPE_CONQUEST_POINTS, sWorld->getIntConfig(CONFIG_START_ARENA_POINTS)); // start with every map explored if (sWorld->getBoolConfig(CONFIG_START_ALL_EXPLORED)) @@ -1094,8 +1081,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); } @@ -1139,7 +1126,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) { @@ -1175,7 +1162,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; @@ -1185,11 +1172,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()); } } } @@ -1299,11 +1281,10 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage) sLog->outDebug(LOG_FILTER_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); } - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM, 1, type); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM, 1, type); } return final_damage; @@ -1842,9 +1823,9 @@ void Player::setDeathState(DeathState s) // passive spell if (!ressSpellId) ressSpellId = GetResurrectionSpellId(); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH, 1); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON, 1); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH, 1); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON, 1); GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH); GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH); GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH); @@ -1861,100 +1842,70 @@ void Player::setDeathState(DeathState s) SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); } -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) - { - sLog->outError(LOG_FILTER_PLAYER_LOADING, "Player %u has incorrect race/class pair. Don't build enum.", guid); - return false; - } - else if (!IsValidGender(gender)) - { - sLog->outError(LOG_FILTER_PLAYER_LOADING, "Player (%u) has incorrect gender (%hu), 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(); + Tokens 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); + customizationFlag = CHAR_CUSTOMIZE_FLAG_RACE; - // First login - *data << uint8(atLoginFlags & AT_LOGIN_FIRST ? 1 : 0); - - // 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)) { @@ -1963,32 +1914,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); - - Tokens 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); + SpellItemEnchantmentEntry const *enchant = NULL; + uint32 enchants = GetUInt32ValueFromArray(equipment, visualbase + 1); for (uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot) { // values stored in 2 uint16 @@ -2001,11 +1968,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; } @@ -2047,20 +2050,62 @@ uint8 Player::GetChatTag() const void Player::SendTeleportPacket(Position &oldPos) { - WorldPacket data2(MSG_MOVE_TELEPORT, 38); - data2.append(GetPackGUID()); - BuildMovementPacket(&data2); - Relocate(&oldPos); - SendMessageToSet(&data2, false); -} + ObjectGuid guid = GetGUID(); + ObjectGuid transGuid = GetTransGUID(); + + WorldPacket data(MSG_MOVE_TELEPORT, 38); + data.WriteBit(guid[6]); + data.WriteBit(guid[0]); + data.WriteBit(guid[3]); + data.WriteBit(guid[2]); + data.WriteBit(0); // unknown + data.WriteBit(uint64(transGuid)); + data.WriteBit(guid[1]); + if (transGuid) + { + data.WriteBit(transGuid[1]); + data.WriteBit(transGuid[3]); + data.WriteBit(transGuid[2]); + data.WriteBit(transGuid[5]); + data.WriteBit(transGuid[0]); + data.WriteBit(transGuid[7]); + data.WriteBit(transGuid[6]); + data.WriteBit(transGuid[4]); + } + + data.WriteBit(guid[4]); + data.WriteBit(guid[7]); + data.WriteBit(guid[5]); + data.FlushBits(); + + if (transGuid) + { + data.WriteByteSeq(transGuid[6]); + data.WriteByteSeq(transGuid[5]); + data.WriteByteSeq(transGuid[1]); + data.WriteByteSeq(transGuid[7]); + data.WriteByteSeq(transGuid[0]); + data.WriteByteSeq(transGuid[2]); + data.WriteByteSeq(transGuid[4]); + data.WriteByteSeq(transGuid[3]); + } + + data << uint32(0); // counter + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[5]); + data << float(GetPositionX()); + data.WriteByteSeq(guid[4]); + data << float(GetOrientation()); + data.WriteByteSeq(guid[7]); + data << float(GetPositionZMinusOffset()); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[6]); + data << float(GetPositionY()); -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); + Relocate(&oldPos); + SendDirectMessage(&data); } bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options) @@ -2117,15 +2162,14 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (m_transport) { - if (options & TELE_TO_NOT_LEAVE_TRANSPORT) - AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); - else + if (!(options & TELE_TO_NOT_LEAVE_TRANSPORT)) { m_transport->RemovePassenger(this); m_transport = NULL; m_movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); m_movementInfo.t_time = 0; m_movementInfo.t_seat = -1; + m_movementInfo.t_guid = 0; } } @@ -2167,15 +2211,14 @@ 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(&oldPos); Relocate(x, y, z, orientation); - SendTeleportAckPacket(); SendTeleportPacket(oldPos); // this automatically relocates to oldPos in order to broadcast the packet in the right place } } @@ -2259,10 +2302,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 (m_transport) - data << m_transport->GetEntry() << GetMapId(); + { + data.WriteBit(1); // has transport + data << GetMapId() << m_transport->GetEntry(); + } + else + data.WriteBit(0); // has transport + data << uint32(mapid); GetSession()->SendPacket(&data); } @@ -2292,11 +2341,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 (m_transport) - data << m_movementInfo.t_pos.PositionXYZOStream(); - else - data << m_teleport_dest.PositionXYZOStream(); + data << float(m_teleport_dest.GetPositionY()); GetSession()->SendPacket(&data); SendSavedInstances(); @@ -2337,13 +2386,14 @@ void Player::ProcessDelayedOperations() else SetFullHealth(); - if (GetMaxPower(POWER_MANA) > m_resurrectMana) + if (uint32(GetMaxPower(POWER_MANA)) > m_resurrectMana) SetPower(POWER_MANA, m_resurrectMana); else SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); SetPower(POWER_RAGE, 0); SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY)); + SetPower(POWER_ECLIPSE, 0); SpawnCorpseBones(); } @@ -2441,15 +2491,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) { @@ -2468,6 +2543,12 @@ void Player::RegenerateAll() m_regenTimerCount -= 2000; } + if (m_holyPowerRegenTimerCount >= 10000 && getClass() == CLASS_PALADIN) + { + Regenerate(POWER_HOLY_POWER); + m_holyPowerRegenTimerCount -= 10000; + } + m_regenTimer = 0; } @@ -2485,6 +2566,11 @@ void Player::Regenerate(Powers power) 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: @@ -2492,24 +2578,26 @@ void Player::Regenerate(Powers power) 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; + addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * ((0.001f * m_regenTimer) + CalculatePctF(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) + CalculatePctF(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 + CalculatePctF(6.0f, rangedHaste)) * sWorld->getRate(RATE_POWER_FOCUS); + break; + case POWER_ENERGY: // Regenerate energy (rogue) + addvalue += ((0.01f * m_regenTimer) + CalculatePctF(0.01f, meleeHaste)) * sWorld->getRate(RATE_POWER_ENERGY); break; case POWER_RUNIC_POWER: { @@ -2518,10 +2606,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: case POWER_HEALTH: break; default: @@ -2609,7 +2702,7 @@ 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()) { AuraEffectList const& mModHealthRegenPct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); @@ -2652,6 +2745,9 @@ void Player::ResetAllPowers() case POWER_RUNIC_POWER: SetPower(POWER_RUNIC_POWER, 0); break; + case POWER_ECLIPSE: + SetPower(POWER_ECLIPSE, 0); + break; default: break; } @@ -3003,23 +3099,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_STORED_POWERS*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); @@ -3039,8 +3133,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(); @@ -3058,7 +3152,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); @@ -3074,7 +3167,7 @@ void Player::GiveLevel(uint8 level) CharacterDatabase.CommitTransaction(trans); } - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); // Refer-A-Friend if (GetSession()->GetRecruiterId()) @@ -3097,33 +3190,33 @@ 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); + 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 (!AccountMgr::IsAdminAccount(GetSession()->GetSecurity())) - resetTalents(true); + ResetTalents(true); else SetFreeTalentPoints(0); } // else update amount of free points else - SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); + SetFreeTalentPoints(talentPointsForLevel - GetUsedTalentCount()); } if (!GetSession()->PlayerLoading()) @@ -3135,8 +3228,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); @@ -3151,6 +3244,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); @@ -3162,10 +3258,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)); @@ -3196,10 +3292,8 @@ void Player::InitStatsForLevel(bool reapplyMods) SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, 0.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 @@ -3213,7 +3307,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); @@ -3245,9 +3341,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); @@ -3282,8 +3378,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 @@ -3315,7 +3410,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 @@ -3330,7 +3425,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->Category); // spell category // send infinity cooldown in special format @@ -3376,15 +3471,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); } @@ -3471,8 +3566,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)) { @@ -3485,8 +3580,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; } } @@ -3497,7 +3592,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; @@ -3774,7 +3869,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()) @@ -3814,12 +3909,6 @@ bool Player::addSpell(uint32 spellId, bool active, bool learning, bool dependent if (!pSkill) continue; - if (!Has310Flyer(false) && pSkill->id == 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) - SetHas310Flyer(true); - if (HasSkill(pSkill->id)) continue; @@ -3864,11 +3953,11 @@ bool Player::addSpell(uint32 spellId, bool active, bool learning, bool dependent // not ranked skills for (SkillLineAbilityMap::const_iterator _spell_idx = skill_bounds.first; _spell_idx != skill_bounds.second; ++_spell_idx) { - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE, _spell_idx->second->skillId); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS, _spell_idx->second->skillId); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE, _spell_idx->second->skillId); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS, _spell_idx->second->skillId); } - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL, spellId); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL, spellId); } // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell @@ -3926,9 +4015,9 @@ void Player::learnSpell(uint32 spell_id, bool dependent) // 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); } @@ -4010,10 +4099,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) @@ -4084,16 +4173,6 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) SetSkill(pSkill->id, GetSkillStep(pSkill->id), 0, 0); } - - // most likely will never be used, haven't heard of cases where players unlearn a mount - if (Has310Flyer(false) && _spell_idx->second->skillId == SKILL_MOUNTS) - { - if (spellInfo) - 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 - } } } @@ -4148,8 +4227,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(); @@ -4163,40 +4253,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; - 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->GetSpellInfo(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); @@ -4347,31 +4403,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; @@ -4380,7 +4436,7 @@ uint32 Player::resetTalentsCost() const } } -bool Player::resetTalents(bool no_cost) +bool Player::ResetTalents(bool no_cost) { sScriptMgr->OnPlayerTalentsReset(this, no_cost); @@ -4390,7 +4446,7 @@ bool Player::resetTalents(bool no_cost) uint32 talentPointsForLevel = CalculateTalentsPoints(); - if (m_usedTalentCount == 0) + if (!GetUsedTalentCount()) { SetFreeTalentPoints(talentPointsForLevel); return false; @@ -4400,9 +4456,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; @@ -4443,27 +4499,37 @@ 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 + for (uint32 i = 0; i < MAX_TALENT_TABS; ++i) + { + std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(GetTalentTabPages(getClass())[i]); + if (specSpells) + for (size_t i = 0; i < specSpells->size(); ++i) + removeSpell(specSpells->at(i), true); + } + + SetPrimaryTalentTree(GetActiveSpec(), 0); + SetFreeTalentPoints(talentPointsForLevel); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); _SaveTalents(trans); _SaveSpells(trans); CharacterDatabase.CommitTransaction(trans); - SetFreeTalentPoints(talentPointsForLevel); - if (!no_cost) { - ModifyMoney(-(int32)cost); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS, cost); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS, 1); + 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 @@ -4477,12 +4543,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) @@ -4511,13 +4571,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); @@ -4544,13 +4597,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); - } } } @@ -4563,8 +4609,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 @@ -4716,7 +4762,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 @@ -5015,24 +5061,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: - sLog->outError(LOG_FILTER_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 @@ -5071,9 +5099,9 @@ void Player::BuildPlayerRepop() // convert player body to ghost SetHealth(1); - SetMovement(MOVE_WATER_WALK); + SendMovementSetWaterWalking(true); if (!GetSession()->isLogingOut()) - SetMovement(MOVE_UNROOT); + SetRooted(false); // BG - remove insignia related RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); @@ -5113,8 +5141,8 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) setDeathState(ALIVE); - SetMovement(MOVE_LAND_WALK); - SetMovement(MOVE_UNROOT); + SendMovementSetWaterWalking(false); + SetRooted(false); m_deathTimer = 0; @@ -5125,6 +5153,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 @@ -5174,7 +5204,7 @@ void Player::KillPlayer() if (IsFlying() && !GetTransport()) i_motionMaster.MoveFall(); - SetMovement(MOVE_ROOT); + SetRooted(true); StopMirrorTimers(); //disable timers(bars) @@ -5236,12 +5266,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; @@ -5292,9 +5320,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++) @@ -5313,6 +5338,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) @@ -5336,9 +5363,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++) @@ -5457,13 +5481,13 @@ uint32 Player::DurabilityRepair(uint16 pos, bool cost, float discountMod, bool g TotalCost = costs; } - else if (!HasEnoughMoney(costs)) + else if (!HasEnoughMoney(uint64(costs))) { sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "You do not have enough money"); return TotalCost; } else - ModifyMoney(-int32(costs)); + ModifyMoney(-int64(costs)); } } @@ -5580,7 +5604,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) { @@ -5616,7 +5640,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) @@ -5631,7 +5655,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; @@ -5699,7 +5723,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; } } @@ -5732,15 +5755,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(); @@ -5763,17 +5777,17 @@ void Player::GetDodgeFromAgility(float &diminishing, float &nondiminishing) // Table for base dodge values const float dodge_base[MAX_CLASSES] = { - 0.036640f, // Warrior - 0.034943f, // Paladi - -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] = @@ -5819,13 +5833,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 @@ -5863,29 +5877,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(); @@ -5917,6 +5908,8 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply) float RatingChange = value * GetRatingMultiplier(cr); ApplyAttackTimePercentMod(BASE_ATTACK, RatingChange, apply); ApplyAttackTimePercentMod(OFF_ATTACK, RatingChange, apply); + if (getClass() == CLASS_DEATH_KNIGHT) + UpdateAllRunesRegen(); break; } case CR_HASTE_RANGED: @@ -6059,25 +6052,27 @@ 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) { - uint32 new_value = value+step; + uint16 new_value = value + 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; + UpdateSkillEnchantments(skill_id, value, new_value); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id); return true; } @@ -6190,37 +6185,39 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) 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) { - uint32 new_value = SkillValue+step; - if (new_value > MaxValue) - new_value = MaxValue; + uint16 new_value = value + step; + if (new_value > max) + new_value = max; - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, MaxValue)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value); 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) + if (value < bsl && new_value >= bsl) { learnSkillRewardedSpells(SkillId, new_value); break; } } - UpdateSkillEnchantments(SkillId, SkillValue, new_value); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, SkillId); + + UpdateSkillEnchantments(SkillId, value, new_value); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, SkillId); sLog->outDebug(LOG_FILTER_PLAYER_SKILLS, "Player::UpdateSkillPro Chance=%3.1f%% taken", Chance / 10.0f); return true; } @@ -6299,16 +6296,12 @@ 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() @@ -6331,10 +6324,11 @@ void Player::UpdateSkillsForLevel() if (GetSkillRangeType(pSkill, false) != 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); + 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) @@ -6342,13 +6336,16 @@ void Player::UpdateSkillsForLevel() /// maximize skill always if (alwaysMaxSkill) { - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(maxSkill, maxSkill)); + 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; } + else if (max != maxconfskill) /// update max skill value if current max skill not maximized { - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(val, maxSkill)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, val); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxSkill); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; } @@ -6366,13 +6363,16 @@ void Player::UpdateSkillsToMaxSkillsForLevel() uint32 pskill = itr->first; if (IsProfessionOrRidingSkill(pskill)) continue; - uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); - uint32 data = GetUInt32Value(valueIndex); - uint32 max = SKILL_MAX(data); + + 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; } @@ -6394,33 +6394,43 @@ 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_VALUE_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); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); + + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); } else //remove { //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) @@ -6433,54 +6443,77 @@ 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) - if (!GetUInt32Value(PLAYER_SKILL_INDEX(i))) + for (uint32 i = 0; i < PLAYER_MAX_SKILLS; ++i) { - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(id); - if (!pSkill) + uint16 field = i / 2; + uint8 offset = i & 1; // i % 2 + + if (!GetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset)) { - sLog->outError(LOG_FILTER_PLAYER_SKILLS, "Skill not found in SkillLineStore: skill #%u", id); - return; - } + SkillLineEntry const* skillEntry = sSkillLineStore.LookupEntry(id); + if (!skillEntry) + { + sLog->outError(LOG_FILTER_GENERAL, "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)); - UpdateSkillEnchantments(id, currVal, newVal); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); + 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); + } - // insert new entry or update if not deleted old entry yet - if (itr != mSkillStatus.end()) - { - itr->second.pos = i; - itr->second.uState = SKILL_CHANGED; - } - else - mSkillStatus.insert(SkillStatusMap::value_type(id, SkillStatusData(i, SKILL_NEW))); + 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); - // apply skill bonuses - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i), 0); + UpdateSkillEnchantments(id, currVal, newVal); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); - // temporary bonuses - AuraEffectList const& mModSkill = GetAuraEffectsByType(SPELL_AURA_MOD_SKILL); - for (AuraEffectList::const_iterator j = mModSkill.begin(); j != mModSkill.end(); ++j) - if ((*j)->GetMiscValue() == int32(id)) + // insert new entry or update if not deleted old entry yet + if (itr != mSkillStatus.end()) + { + itr->second.pos = i; + itr->second.uState = SKILL_CHANGED; + } + else + mSkillStatus.insert(SkillStatusMap::value_type(id, SkillStatusData(i, SKILL_NEW))); + + // apply skill bonuses + 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) + if ((*j)->GetMiscValue() == int32(id)) (*j)->HandleEffect(this, AURA_EFFECT_HANDLE_SKILL, true); - // permanent bonuses - AuraEffectList const& mModSkillTalent = GetAuraEffectsByType(SPELL_AURA_MOD_SKILL_TALENT); - for (AuraEffectList::const_iterator j = mModSkillTalent.begin(); j != mModSkillTalent.end(); ++j) - if ((*j)->GetMiscValue() == int32(id)) + // permanent bonuses + AuraEffectList const& mModSkillTalent = GetAuraEffectsByType(SPELL_AURA_MOD_SKILL_TALENT); + for (AuraEffectList::const_iterator j = mModSkillTalent.begin(); j != mModSkillTalent.end(); ++j) + if ((*j)->GetMiscValue() == int32(id)) (*j)->HandleEffect(this, AURA_EFFECT_HANDLE_SKILL, true); - // Learn all spells for skill - learnSkillRewardedSpells(id, newVal); - return; + // Learn all spells for skill + learnSkillRewardedSpells(id, newVal); + return; + } } } } @@ -6503,7 +6536,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 @@ -6515,11 +6548,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; } @@ -6532,11 +6566,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; } @@ -6549,7 +6584,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 @@ -6561,8 +6599,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; } @@ -6575,7 +6616,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 @@ -6587,7 +6631,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 @@ -6599,17 +6646,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) @@ -6623,9 +6672,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); - sLog->outInfo(LOG_FILTER_NETWORKIO, "SMSG_ACTION_BUTTONS sent '%u' spec '%u' Sent", GetGUIDLow(), m_activeSpec); + sLog->outInfo(LOG_FILTER_NETWORKIO, "Action Buttons for '%u' spec '%u' Sent", GetGUIDLow(), GetActiveSpec()); } bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type) @@ -6820,7 +6872,7 @@ void Player::CheckAreaExploreAndOutdoor() { SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val)); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA); AreaTableEntry const* areaEntry = GetAreaEntryByAreaFlagAndMap(areaFlag, GetMapId()); if (!areaEntry) @@ -7065,16 +7117,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); } } @@ -7085,15 +7133,15 @@ void Player::UpdateHonorFields() ///Calculate the amount of honor gained based on the victim ///and the size of the group for which the honor is divided ///An exact honor value can also be given (overriding the calcs) -bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool pvptoken) +bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvptoken) { // do not reward honor in arenas, but enable onkill spellproc if (InArena()) { - if (!uVictim || uVictim == this || uVictim->GetTypeId() != TYPEID_PLAYER) + if (!victim || victim == this || victim->GetTypeId() != TYPEID_PLAYER) return false; - if (GetBGTeam() == uVictim->ToPlayer()->GetBGTeam()) + if (GetBGTeam() == victim->ToPlayer()->GetBGTeam()) return false; return true; @@ -7118,16 +7166,14 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool pvpt if (honor_f <= 0) { - if (!uVictim || uVictim == this || uVictim->HasAuraType(SPELL_AURA_NO_PVP_CREDIT)) + if (!victim || victim == this || victim->HasAuraType(SPELL_AURA_NO_PVP_CREDIT)) return false; - victim_guid = uVictim->GetGUID(); + victim_guid = victim->GetGUID(); - if (uVictim->GetTypeId() == TYPEID_PLAYER) + if (Player* plrVictim = victim->ToPlayer()) { - Player* victim = uVictim->ToPlayer(); - - if (GetTeam() == victim->GetTeam() && !sWorld->IsFFAPvPRealm()) + if (GetTeam() == plrVictim->GetTeam() && !sWorld->IsFFAPvPRealm()) return false; uint8 k_level = getLevel(); @@ -7172,7 +7218,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool pvpt } else { - if (!uVictim->ToCreature()->isRacialLeader()) + if (!victim->ToCreature()->isRacialLeader()) return false; honor_f = 100.0f; // ??? need more info @@ -7180,7 +7226,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool pvpt } } - if (uVictim != NULL) + if (victim != NULL) { if (groupsize > 1) honor_f /= groupsize; @@ -7198,16 +7244,14 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool pvpt // victim_rank [5..19] HK: <alliance\horde rank> // victim_rank [0, 20+] HK: <> WorldPacket data(SMSG_PVP_CREDIT, 4+8+4); - data << honor; - data << victim_guid; - data << victim_rank; + data << uint32(honor); + data << uint64(victim_guid); + data << uint32(victim_rank); 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) { @@ -7219,10 +7263,10 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool pvpt if (sWorld->getBoolConfig(CONFIG_PVP_TOKEN_ENABLE) && pvptoken) { - if (!uVictim || uVictim == this || uVictim->HasAuraType(SPELL_AURA_NO_PVP_CREDIT)) + if (!victim || victim == this || victim ->HasAuraType(SPELL_AURA_NO_PVP_CREDIT)) return true; - if (uVictim->GetTypeId() == TYPEID_PLAYER) + if (victim->GetTypeId() == TYPEID_PLAYER) { // Check if allowed to receive it in current map uint8 MapType = sWorld->getIntConfig(CONFIG_PVP_TOKEN_MAP_TYPE); @@ -7242,86 +7286,204 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool pvpt return true; } -void Player::SetHonorPoints(uint32 value) + +void Player::SendCurrencies() const { - 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); + ByteBuffer currencyData; + WorldPacket packet(SMSG_INIT_CURRENCY, 4 + m_currencies.size()*(5*4 + 1)); + packet.WriteBits(m_currencies.size(), 23); + + for (PlayerCurrenciesMap::const_iterator itr = m_currencies.begin(); itr != m_currencies.end(); ++itr) + { + CurrencyTypesEntry const* entry = sCurrencyTypesStore.LookupEntry(itr->first); + if (!entry) // should never happen + continue; + + uint32 precision = (entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? 100 : 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); + + currencyData << uint32(entry->ID); + if (weekCount) + currencyData << uint32(weekCount); + } + + packet.FlushBits(); + packet.append(currencyData); + GetSession()->SendPacket(&packet); } -void Player::SetArenaPoints(uint32 value) +uint32 Player::GetCurrency(uint32 id) const { - 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); + PlayerCurrenciesMap::const_iterator itr = m_currencies.find(id); + return itr != m_currencies.end() ? itr->second.totalCount : 0; } -void Player::ModifyHonorPoints(int32 value, SQLTransaction* trans /*=NULL*/) +bool Player::HasCurrency(uint32 id, uint32 count) const { - PreparedStatement* stmt = NULL; + PlayerCurrenciesMap::const_iterator itr = m_currencies.find(id); + return itr != m_currencies.end() && itr->second.totalCount >= count; +} - int32 newValue = int32(GetHonorPoints()) + value; - if (newValue < 0) - newValue = 0; - SetHonorPoints(uint32(newValue)); +void Player::ModifyCurrency(uint32 id, int32 count, bool printLog/* = true*/) +{ + if (!count) + return; - if (trans && !trans->null()) + CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(id); + ASSERT(currency); + + int32 precision = currency->Flags & CURRENCY_FLAG_HIGH_PRECISION ? 100 : 1; + uint32 oldTotalCount = 0; + uint32 oldWeekCount = 0; + PlayerCurrenciesMap::iterator itr = m_currencies.find(id); + if (itr == m_currencies.end()) { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_HONOR_POINTS); - stmt->setUInt32(0, newValue); - stmt->setUInt32(1, GetGUIDLow()); - (*trans)->Append(stmt); + PlayerCurrency cur; + cur.state = PLAYERCURRENCY_NEW; + cur.totalCount = 0; + cur.weekCount = 0; + m_currencies[id] = cur; + itr = m_currencies.find(id); + } + else + { + oldTotalCount = itr->second.totalCount; + oldWeekCount = itr->second.weekCount; } -} -void Player::ModifyArenaPoints(int32 value, SQLTransaction* trans /*=NULL*/) -{ - PreparedStatement* stmt = NULL; + int32 newTotalCount = int32(oldTotalCount) + count; + if (newTotalCount < 0) + newTotalCount = 0; - int32 newValue = int32(GetArenaPoints()) + value; - if (newValue < 0) - newValue = 0; - SetArenaPoints(uint32(newValue)); + int32 newWeekCount = int32(oldWeekCount) + (count > 0 ? count : 0); + if (newWeekCount < 0) + newWeekCount = 0; - if (trans && !trans->null()) + if (currency->TotalCap && int32(currency->TotalCap) < newTotalCount) { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_ARENA_POINTS); - stmt->setUInt32(0, newValue); - stmt->setUInt32(1, GetGUIDLow()); - (*trans)->Append(stmt); + int32 delta = newTotalCount - int32(currency->TotalCap); + newTotalCount = int32(currency->TotalCap); + newWeekCount -= delta; + } + + // TODO: fix conquest points + uint32 weekCap = _GetCurrencyWeekCap(currency); + if (weekCap && int32(weekCap) < newTotalCount) + { + int32 delta = newWeekCount - int32(weekCap); + newWeekCount = int32(weekCap); + newTotalCount -= delta; + } + + // if we change total, we must change week + ASSERT(((newTotalCount-oldTotalCount) != 0) == ((newWeekCount-oldWeekCount) != 0)); + + if (uint32(newTotalCount) != oldTotalCount) + { + if (itr->second.state != PLAYERCURRENCY_NEW) + itr->second.state = PLAYERCURRENCY_CHANGED; + + itr->second.totalCount = newTotalCount; + itr->second.weekCount = newWeekCount; + + // probably excessive checks + if (IsInWorld() && !GetSession()->PlayerLoading()) + { + if (count > 0) + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CURRENCY, id, count); + + 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*/) +{ + ModifyCurrency(id, int32(count) - GetCurrency(id), printLog); +} + +uint32 Player::_GetCurrencyWeekCap(const CurrencyTypesEntry* currency) const +{ + uint32 cap = currency->WeekCap; + switch (currency->ID) + { + case CURRENCY_TYPE_CONQUEST_POINTS: + { + // TODO: implement + cap = 0; + break; + } + case CURRENCY_TYPE_HONOR_POINTS: + { + uint32 honorcap = sWorld->getIntConfig(CONFIG_MAX_HONOR_POINTS); + if (honorcap > 0) + cap = honorcap; + break; + } + case CURRENCY_TYPE_JUSTICE_POINTS: + { + uint32 justicecap = sWorld->getIntConfig(CONFIG_MAX_JUSTICE_POINTS); + if (justicecap > 0) + cap = justicecap; + break; + } + } + + if (cap != currency->WeekCap && IsInWorld() && !GetSession()->PlayerLoading()) + { + WorldPacket packet(SMSG_UPDATE_CURRENCY_WEEK_LIMIT, 8); + packet << uint32(cap / ((currency->Flags & 0x8) ? 100 : 1)); + packet << uint32(currency->ID); + GetSession()->SendPacket(&packet); + } + + return cap; +} + 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 (PreparedQueryResult result = CharacterDatabase.Query(stmt)) + return result->Fetch()[0].GetUInt32(); - if (!result) - return 0; - - 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) - { - uint32 v = result->Fetch()[1].GetUInt8(); - return v; - } - else - return 0; + return 0; } uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type) @@ -7436,13 +7598,9 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) { SetGroupUpdateFlag(GROUP_UPDATE_FULL); if (GetSession() && group->isLFGGroup() && sLFGMgr->IsTeleported(GetGUID())) - { for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) - { if (Player* member = itr->getSource()) GetSession()->SendNameQueryOpcode(member->GetGUID()); - } - } } m_zoneUpdateId = newZone; @@ -7597,8 +7755,8 @@ void Player::DuelComplete(DuelCompleteType type) { data.Initialize(SMSG_DUEL_WINNER, (1+20)); // we guess size data << uint8(type == DUEL_WON ? 0 : 1); // 0 = just won; 1 = fled - data << duel->opponent->GetName(); data << GetName(); + data << duel->opponent->GetName(); SendMessageToSet(&data, true); } @@ -7623,10 +7781,10 @@ void Player::DuelComplete(DuelCompleteType type) } break; case DUEL_WON: - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL, 1); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL, 1); if (duel->opponent) { - duel->opponent->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1); + duel->opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1); //Credit for quest Death's Challenge if (getClass() == CLASS_DEATH_KNIGHT && duel->opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE) @@ -7721,10 +7879,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); @@ -7745,7 +7899,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; @@ -7759,12 +7913,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; } @@ -7897,9 +8049,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; @@ -7916,23 +8065,36 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -val, apply); m_spellPenetrationItemMod += apply ? val : -val; break; - // deprecated item mods - case ITEM_MOD_SPELL_HEALING_DONE: - case ITEM_MOD_SPELL_DAMAGE_DONE: + 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; + 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); if (armor) { @@ -7957,27 +8119,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 && ( @@ -7993,23 +8134,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) @@ -8028,18 +8152,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, &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; } } @@ -8065,10 +8191,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); } @@ -8312,7 +8434,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 float chance = (float)spellInfo->ProcChance; - if (spellData.SpellPPMRate) + if (proto->SpellPPMRate) { if (spellData.SpellId == 52781) // Persuasive Strike { @@ -8327,7 +8449,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 } } uint32 WeaponSpeed = GetAttackTime(attType); - chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate, spellInfo); + chance = GetPPMProcChance(WeaponSpeed, proto->SpellPPMRate, spellInfo); } else if (chance > 100.0f) { @@ -8342,6 +8464,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) @@ -8417,7 +8542,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 if (!spellInfo) { sLog->outError(LOG_FILTER_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; } @@ -8464,6 +8589,9 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 // Item enchantments spells casted 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) @@ -8530,9 +8658,6 @@ void Player::_RemoveAllItemMods() _ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), false); _ApplyItemBonuses(proto, i, false); - - if (i == EQUIPMENT_SLOT_RANGED) - _ApplyAmmoBonuses(); } } @@ -8559,9 +8684,6 @@ void Player::_ApplyAllItemMods() _ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), true); _ApplyItemBonuses(proto, i, true); - - if (i == EQUIPMENT_SLOT_RANGED) - _ApplyAmmoBonuses(); } } @@ -8606,63 +8728,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) @@ -8999,7 +9064,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); @@ -9029,9 +9094,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); } @@ -9068,9 +9134,6 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) case 2918: NumberOfFields = 8; break; - case 139: - NumberOfFields = 41; - break; case 1377: NumberOfFields = 15; break; @@ -9158,46 +9221,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); @@ -9670,6 +9693,27 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) data << uint32(4131) << uint32(0); // 10 WORLDSTATE_CRATES_REVEALED } 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; default: data << uint32(0x914) << uint32(0x0); // 7 data << uint32(0x913) << uint32(0x0); // 8 @@ -9720,7 +9764,7 @@ void Player::SendTalentWipeConfirm(uint64 guid) { 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); } @@ -9919,30 +9963,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; @@ -10004,14 +10028,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)) @@ -10036,11 +10052,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); @@ -10083,13 +10094,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); @@ -10115,11 +10119,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) @@ -10151,7 +10150,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); @@ -10233,8 +10232,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; } @@ -10293,10 +10290,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; @@ -10336,16 +10329,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)) @@ -10475,11 +10459,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) @@ -10492,7 +10476,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; } } @@ -10504,7 +10488,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) @@ -10514,7 +10498,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; } } } @@ -10522,36 +10506,6 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item return EQUIP_ERR_OK; } -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); @@ -10563,40 +10517,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 @@ -10630,26 +10576,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++) { @@ -10700,7 +10646,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++) { @@ -10756,7 +10702,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) @@ -10766,14 +10712,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; } } @@ -10809,7 +10755,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; } } @@ -10823,24 +10769,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) { @@ -10856,7 +10784,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 @@ -10880,7 +10808,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; } } } @@ -10888,67 +10816,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) { @@ -10964,7 +10831,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 @@ -10987,7 +10854,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; } } } @@ -10997,24 +10864,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) { @@ -11030,7 +10879,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) @@ -11048,7 +10897,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; } } } @@ -11066,7 +10915,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; } } } @@ -11074,48 +10923,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); @@ -11129,13 +10936,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); @@ -11153,7 +10960,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++) @@ -11169,14 +10976,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; } ////////////////////////////////////////////////////////////////////////// @@ -11187,13 +10994,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++) { @@ -11202,20 +11005,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++) @@ -11243,11 +11032,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; @@ -11261,32 +11050,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); @@ -11327,38 +11090,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) { @@ -11425,7 +11156,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; @@ -11457,10 +11188,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); @@ -11473,7 +11204,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 @@ -11489,27 +11220,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 (IsNonMeleeSpellCasted(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 swap ignore item (equipped also) InventoryResult res2 = CanEquipUniqueItem(pItem, swap ? eslot : uint8(NULL_SLOT)); @@ -11524,8 +11255,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; @@ -11534,16 +11265,16 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool 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) @@ -11552,10 +11283,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()) { @@ -11565,7 +11296,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); @@ -11573,7 +11304,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 @@ -11596,7 +11327,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 @@ -11612,7 +11343,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; } @@ -11620,29 +11351,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(); sLog->outDebug(LOG_FILTER_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) + if(pItem->IsCurrencyToken()) { sLog->outError(LOG_FILTER_PLAYER, "Possible hacking attempt: Player %s [guid: %u] tried to move token [guid: %u, entry: %u] out of the currency bag!", GetName(), 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) @@ -11656,10 +11386,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) @@ -11680,7 +11410,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) @@ -11811,16 +11541,16 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const sLog->outDebug(LOG_FILTER_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) @@ -11833,7 +11563,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. @@ -11851,7 +11581,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) @@ -11870,31 +11600,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; } @@ -11936,15 +11666,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; } @@ -11952,108 +11682,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 -{ - sLog->outDebug(LOG_FILTER_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); -} - Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update, int32 randomPropertyId) { AllowedLooterSet allowedLooters; @@ -12071,8 +11736,8 @@ Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update if (pItem) { ItemAddedQuestCheck(item, count); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, item, count); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, item, 1); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, item, count); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, item, 1); if (randomPropertyId) pItem->SetItemRandomProperties(randomPropertyId); pItem = StoreItem(dest, pItem, update); @@ -12161,10 +11826,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); @@ -12242,7 +11903,7 @@ Item* Player::EquipNewItem(uint16 pos, uint32 item, bool update) if (Item* pItem = Item::CreateItem(item, 1, this)) { ItemAddedQuestCheck(item, 1); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, item, 1); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, item, 1); return EquipItem(pos, pItem, update); } @@ -12352,8 +12013,8 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update) } // only for full equip instead adding to stack - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry()); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry()); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot); return pItem; } @@ -12374,8 +12035,8 @@ void Player::QuickEquipItem(uint16 pos, Item* pItem) pItem->SendUpdateToPlayer(this); } - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry()); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry()); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot); } } @@ -12383,7 +12044,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)); } @@ -12521,7 +12182,7 @@ void Player::MoveItemToInventory(ItemPosCountVec const& dest, Item* pItem, bool { // update quest counters ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount()); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount()); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount()); // store item Item* pLastItem = StoreItem(dest, pItem, update); @@ -12670,34 +12331,6 @@ void Player::DestroyItemCount(uint32 item, uint32 count, bool update, bool unequ } } - for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) - { - if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) - { - if (pItem->GetEntry() == item && !pItem->IsInTrade()) - { - if (pItem->GetCount() + remcount <= count) - { - // all keys can be unequipped - remcount += pItem->GetCount(); - DestroyItem(INVENTORY_SLOT_BAG_0, i, update); - - if (remcount >= count) - return; - } - else - { - ItemRemovedQuestCheck(pItem->GetEntry(), count - remcount); - pItem->SetCount(pItem->GetCount() - count + remcount); - if (IsInWorld() && update) - pItem->SendUpdateToPlayer(this); - pItem->SetState(ITEM_CHANGED, this); - return; - } - } - } - } - // in inventory bags for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { @@ -12775,11 +12408,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)) @@ -12830,11 +12458,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) @@ -12892,21 +12515,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; } @@ -13007,7 +12630,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; } @@ -13016,7 +12639,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; } @@ -13035,14 +12658,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; } @@ -13053,7 +12676,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; } @@ -13250,7 +12873,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; } @@ -13260,7 +12883,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; } @@ -13454,16 +13077,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); @@ -13476,26 +13099,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*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "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) { sLog->outDebug(LOG_FILTER_NETWORKIO, "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); } @@ -13599,6 +13218,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; @@ -13693,10 +13315,255 @@ 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_CRIT_TAKEN_MELEE, -int32(removeValue), apply); + ApplyRatingMod(CR_CRIT_TAKEN_RANGED, -int32(removeValue), apply); + ApplyRatingMod(CR_CRIT_TAKEN_SPELL, -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; + } + + 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_CRIT_TAKEN_MELEE, int32(addValue), apply); + ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(addValue), apply); + ApplyRatingMod(CR_CRIT_TAKEN_SPELL, 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; + } +} + 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) @@ -13707,6 +13574,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; @@ -13724,6 +13600,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) @@ -13765,13 +13646,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) { @@ -13817,7 +13698,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) { @@ -13981,10 +13862,6 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "+ %u RANGED_ATTACK_POWER", enchant_amount); break; -// case ITEM_MOD_FERAL_ATTACK_POWER: -// ApplyFeralAPBonus(enchant_amount, apply); -// sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "+ %u FERAL_ATTACK_POWER", enchant_amount); -// break; case ITEM_MOD_MANA_REGENERATION: ApplyManaRegenBonus(enchant_amount, apply); sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "+ %u MANA_REGENERATION", enchant_amount); @@ -14010,8 +13887,6 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply); sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "+ %u BLOCK_VALUE", enchant_amount); break; - case ITEM_MOD_SPELL_HEALING_DONE: // deprecated - case ITEM_MOD_SPELL_DAMAGE_DONE: // deprecated default: break; } @@ -14080,6 +13955,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; @@ -14120,17 +13998,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) @@ -14368,7 +14242,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(); @@ -14749,7 +14623,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) { @@ -14783,7 +14657,7 @@ bool Player::CanCompleteQuest(uint32 quest_id) if (q_status.Status == QUEST_STATUS_INCOMPLETE) { - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_DELIVER)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) { for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++) { @@ -14792,7 +14666,7 @@ bool Player::CanCompleteQuest(uint32 quest_id) } } - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) { for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++) { @@ -14804,19 +14678,19 @@ bool Player::CanCompleteQuest(uint32 quest_id) } } - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL)) if (qInfo->GetPlayersSlain() != 0 && q_status.PlayerCount < qInfo->GetPlayersSlain()) return false; - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT) && !q_status.Explored) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT) && !q_status.Explored) return false; - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_TIMED) && q_status.Timer == 0) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED) && q_status.Timer == 0) return false; if (qInfo->GetRewOrReqMoney() < 0) { - if (!HasEnoughMoney(-qInfo->GetRewOrReqMoney())) + if (!HasEnoughMoney(-int64(qInfo->GetRewOrReqMoney()))) return false; } @@ -14838,7 +14712,7 @@ bool Player::CanCompleteRepeatableQuest(Quest const* quest) if (!CanTakeQuest(quest, false)) return false; - if (quest->HasFlag(QUEST_TRINITY_FLAGS_DELIVER)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++) if (quest->RequiredItemId[i] && quest->RequiredItemCount[i] && !HasItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i])) return false; @@ -14864,7 +14738,7 @@ bool Player::CanRewardQuest(Quest const* quest, bool msg) return false; // prevent receive reward with quest items in bank - if (quest->HasFlag(QUEST_TRINITY_FLAGS_DELIVER)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) { for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++) { @@ -14879,7 +14753,7 @@ bool Player::CanRewardQuest(Quest const* quest, bool msg) } // 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; @@ -14941,19 +14815,19 @@ void Player::AddQuest(Quest const* quest, Object* questGiver) questStatusData.Status = QUEST_STATUS_INCOMPLETE; questStatusData.Explored = false; - if (quest->HasFlag(QUEST_TRINITY_FLAGS_DELIVER)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) { for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) questStatusData.ItemCount[i] = 0; } - if (quest->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) { for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) questStatusData.CreatureOrGOCount[i] = 0; } - if (quest->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL)) questStatusData.PlayerCount = 0; GiveQuestSourceItem(quest); @@ -14968,7 +14842,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver) GetReputationMgr().SetVisible(factionEntry); uint32 qtime = 0; - if (quest->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED)) { uint32 limittime = quest->GetLimitTime(); @@ -15024,7 +14898,7 @@ void Player::CompleteQuest(uint32 quest_id) if (qInfo->HasFlag(QUEST_FLAGS_AUTO_REWARDED)) RewardQuest(qInfo, 0, this, false); else - SendQuestComplete(quest_id); + SendQuestComplete(qInfo); } } } @@ -15124,7 +14998,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, ModifyMoney(moneyRew); if (moneyRew > 0) - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, uint32(moneyRew)); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, uint32(moneyRew)); } // honor reward @@ -15138,15 +15012,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()) { @@ -15161,8 +15032,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, SetDailyQuestStatus(quest_id); if (quest->IsDaily()) { - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, quest_id); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY, quest_id); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, quest_id); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY, quest_id); } } else if (quest->IsWeekly()) @@ -15190,9 +15061,9 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, CastSpell(this, quest->GetRewSpell(), true); if (quest->GetZoneOrSort() > 0) - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, quest->GetZoneOrSort()); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId()); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, quest->GetZoneOrSort()); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId()); uint32 zone = 0; uint32 area = 0; @@ -15239,7 +15110,7 @@ void Player::FailQuest(uint32 questId) SetQuestSlotState(log_slot, QUEST_STATE_FAIL); } - if (quest->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED)) { QuestStatusData& q_status = m_QuestStatus[questId]; @@ -15494,7 +15365,7 @@ bool Player::SatisfyQuestConditions(Quest const* qInfo, bool msg) bool Player::SatisfyQuestTimed(Quest const* qInfo, bool msg) { - if (!m_timedquests.empty() && qInfo->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) + if (!m_timedquests.empty() && qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED)) { if (msg) SendCanTakeQuestResponse(INVALIDREASON_QUEST_ONLY_ONE_TIMED); @@ -15665,7 +15536,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); @@ -15803,7 +15674,7 @@ uint16 Player::GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry) void Player::AdjustQuestReqItemCount(Quest const* quest, QuestStatusData& questStatusData) { - if (quest->HasFlag(QUEST_TRINITY_FLAGS_DELIVER)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) { for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) { @@ -15880,7 +15751,7 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count) continue; Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid); - if (!qInfo || !qInfo->HasFlag(QUEST_TRINITY_FLAGS_DELIVER)) + if (!qInfo || !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) continue; for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j) @@ -15897,7 +15768,8 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count) m_QuestStatusSave[questid] = true; - SendQuestUpdateAddItem(qInfo, j, additemcount); + //SendQuestUpdateAddItem(qInfo, j, additemcount); + // FIXME: verify if there's any packet sent updating item } if (CanCompleteQuest(questid)) CompleteQuest(questid); @@ -15918,7 +15790,7 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count) Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid); if (!qInfo) continue; - if (!qInfo->HasFlag(QUEST_TRINITY_FLAGS_DELIVER)) + if (!qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) continue; for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j) @@ -15972,7 +15844,7 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid) } GetAchievementMgr().StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_CREATURE, real_entry); // MUST BE CALLED FIRST - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, real_entry, addkillcount, guid ? GetMap()->GetCreature(guid) : NULL); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, real_entry, addkillcount, guid ? GetMap()->GetCreature(guid) : NULL); for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i) { @@ -15987,7 +15859,7 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid) QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid())) { - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST)) { for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) { @@ -16042,7 +15914,7 @@ void Player::KilledPlayerCredit() QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid())) { - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL)) { uint32 reqkill = qInfo->GetPlayersSlain(); uint16 curkill = q_status.PlayerCount; @@ -16084,7 +15956,7 @@ void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id) if (q_status.Status == QUEST_STATUS_INCOMPLETE) { - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST)) { for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) { @@ -16161,7 +16033,7 @@ void Player::TalkedToCreature(uint32 entry, uint64 guid) if (q_status.Status == QUEST_STATUS_INCOMPLETE) { - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) { for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) { @@ -16345,39 +16217,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); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest_id); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest->GetQuestId()); } } void Player::SendQuestReward(Quest const* quest, uint32 XP, Object* questGiver) { - uint32 questid = quest->GetQuestId(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "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(); + sLog->outDebug(LOG_FILTER_NETWORKIO, "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 << 10 * Trinity::Honor::hk_honor_at_level(getLevel(), quest->GetRewHonorMultiplier()); - 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); if (quest->GetQuestCompleteScript() != 0) @@ -16448,15 +16331,6 @@ void Player::SendPushToPartyResponse(Player* player, uint32 msg) } } -void Player::SendQuestUpdateAddItem(Quest const* /*quest*/, uint32 /*item_idx*/, uint16 /*count*/) -{ - WorldPacket data(SMSG_QUESTUPDATE_ADD_ITEM, 0); - sLog->outDebug(LOG_FILTER_NETWORKIO, "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)"); @@ -16675,12 +16549,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 46 47 + //"conquestPoints, totalHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, " + // 48 49 50 51 52 53 54 55 56 57 58 + //"health, power1, power2, power3, power4, power5, instance_id, speccount, activespec, exploredZones, equipmentCache, " + // 59 60 61 + //"knownTitles, actionBars, grantableLevels FROM characters WHERE guid = '%u'", guid); PreparedQueryResult result = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADFROM); if (!result) @@ -16745,8 +16621,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[57].GetCString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE); + _LoadIntoDataField(fields[59].GetCString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2); SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); @@ -16755,7 +16631,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_LOADACHIEVEMENTS), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS)); - uint32 money = fields[8].GetUInt32(); + uint64 money = fields[8].GetUInt64(); if (money > MAX_MONEY_AMOUNT) money = MAX_MONEY_AMOUNT; SetMoney(money); @@ -16763,16 +16639,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[47].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[46].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[60].GetUInt8()); InitDisplayIds(); @@ -16800,21 +16672,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 transGUID = fields[30].GetUInt32(); + uint32 transGUID = 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[54].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); } @@ -16822,8 +16696,6 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) _LoadArenaTeamInfo(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADARENAINFO)); - SetArenaPoints(fields[39].GetUInt32()); - // check arena teams integrity for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot) { @@ -16840,12 +16712,11 @@ 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()); + SetCurrency(CURRENCY_TYPE_CONQUEST_POINTS, fields[40].GetUInt32()); + SetCurrency(CURRENCY_TYPE_HONOR_POINTS, fields[41].GetUInt32()); + SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, fields[42].GetUInt32()); + SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[43].GetUInt16()); + SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[44].GetUInt16()); _LoadBoundInstances(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES)); _LoadInstanceTimeRestrictions(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADINSTANCELOCKTIMES)); @@ -16907,17 +16778,17 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) else if (transGUID) { m_movementInfo.t_guid = MAKE_NEW_GUID(transGUID, 0, HIGHGUID_MO_TRANSPORT); - m_movementInfo.t_pos.Relocate(fields[26].GetFloat(), fields[27].GetFloat(), fields[28].GetFloat(), fields[29].GetFloat()); + m_movementInfo.t_pos.Relocate(fields[27].GetFloat(), fields[28].GetFloat(), fields[29].GetFloat(), fields[30].GetFloat()); if (!Trinity::IsValidMapCoord( GetPositionX()+m_movementInfo.t_pos.m_positionX, GetPositionY()+m_movementInfo.t_pos.m_positionY, - GetPositionZ()+m_movementInfo.t_pos.m_positionZ, GetOrientation()+m_movementInfo.t_pos.m_orientation) || + GetPositionZ()+m_movementInfo.t_pos.m_positionZ, GetOrientation()+m_movementInfo.t_pos.GetOrientation()) || // transport size limited m_movementInfo.t_pos.m_positionX > 250 || m_movementInfo.t_pos.m_positionY > 250 || m_movementInfo.t_pos.m_positionZ > 250) { sLog->outError(LOG_FILTER_PLAYER, "Player (guidlow %d) have invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to bind location.", guid, GetPositionX()+m_movementInfo.t_pos.m_positionX, GetPositionY()+m_movementInfo.t_pos.m_positionY, - GetPositionZ()+m_movementInfo.t_pos.m_positionZ, GetOrientation()+m_movementInfo.t_pos.m_orientation); + GetPositionZ()+m_movementInfo.t_pos.m_positionZ, GetOrientation()+m_movementInfo.t_pos.GetOrientation()); RelocateToHomebind(); } @@ -17083,28 +16954,28 @@ 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].GetCString()); // 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) { sLog->outError(LOG_FILTER_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(); // Honor system // Update Honor kills data 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; @@ -17164,14 +17035,14 @@ 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[55].GetUInt8()); + SetActiveSpec(fields[56].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; - sLog->outError(LOG_FILTER_PLAYER, "Player %s(GUID: %u) has SpecCount = %u and ActiveSpec = %u.", GetName(), GetGUIDLow(), m_specsCount, m_activeSpec); + SetActiveSpec(0); + sLog->outError(LOG_FILTER_PLAYER, "Player %s(GUID: %u) has SpecCount = %u and ActiveSpec = %u.", GetName(), GetGUIDLow(), GetSpecsCount(), GetActiveSpec()); } _LoadTalents(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADTALENTS)); @@ -17201,6 +17072,9 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) _LoadInventory(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADINVENTORY), time_diff); + if (IsVoidStorageUnlocked()) + _LoadVoidStorage(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADVOIDSTORAGE)); + // update items with duration and realtime UpdateItemDuration(time_diff, true); @@ -17213,7 +17087,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[45].GetUInt32(); if (curTitle && !HasTitle(curTitle)) curTitle = 0; @@ -17236,12 +17110,38 @@ 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[48].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 (GetPowerIndexByClass(Powers(i), getClass()) != MAX_POWERS) + { + uint32 savedPower = fields[49+loadedPowers].GetUInt32(); + uint32 maxPower = GetUInt32Value(UNIT_FIELD_MAXPOWER1 + loadedPowers); + SetPower(Powers(i), (savedPower > maxPower) ? maxPower : savedPower); + if (++loadedPowers >= MAX_STORED_POWERS) + break; + } + } + + for (; loadedPowers < MAX_STORED_POWERS; ++loadedPowers) + SetUInt32Value(UNIT_FIELD_POWER1 + loadedPowers, 0); + + SetPower(POWER_ECLIPSE, 0); + + // must be after loading spells and talents + Tokens 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); + else if (i == GetActiveSpec()) + SetAtLoginFlag(AT_LOGIN_RESET_TALENTS); // invalid tree, reset talents } sLog->outDebug(LOG_FILTER_PLAYER_LOADING, "The value of player %s after load item and aura is: ", m_name.c_str()); @@ -17296,7 +17196,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) } // RaF stuff. - m_grantableLevels = fields[66].GetUInt8(); + m_grantableLevels = fields[61].GetUInt8(); if (GetSession()->IsARecruiter() || (GetSession()->GetRecruiterId() != 0)) SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_REFER_A_FRIEND); @@ -17305,7 +17205,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) _LoadDeclinedNames(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES)); - m_achievementMgr.CheckAllAchievementCriteria(); + m_achievementMgr.CheckAllAchievementCriteria(this); _LoadEquipmentSets(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS)); @@ -17465,7 +17365,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)) { @@ -17589,7 +17489,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff) { std::map<uint64, 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 { @@ -17636,6 +17536,52 @@ 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) + { + sLog->outError(LOG_FILTER_PLAYER, "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid id (item id: " UI64FMTD ", entry: %u).", GetGUIDLow(), GetName(), itemId, itemEntry); + continue; + } + + if (!sObjectMgr->GetItemTemplate(itemEntry)) + { + sLog->outError(LOG_FILTER_PLAYER, "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid entry (item id: " UI64FMTD ", entry: %u).", GetGUIDLow(), GetName(), itemId, itemEntry); + continue; + } + + if (slot >= VOID_STORAGE_MAX_SLOT) + { + sLog->outError(LOG_FILTER_PLAYER, "Player::_LoadVoidStorage - Player (GUID: %u, name: %s) has an item with an invalid slot (item id: " UI64FMTD ", entry: %u, slot: %u).", GetGUIDLow(), GetName(), itemId, itemEntry, slot); + continue; + } + + if (!sObjectMgr->GetPlayerByLowGUID(creatorGuid)) + { + sLog->outError(LOG_FILTER_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(), 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) { PreparedStatement* stmt = NULL; @@ -17850,8 +17796,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(); @@ -17923,7 +17869,7 @@ void Player::_LoadQuestStatus(PreparedQueryResult result) time_t quest_time = time_t(fields[3].GetUInt32()); - if (quest->HasFlag(QUEST_TRINITY_FLAGS_TIMED) && !GetQuestRewardStatus(quest_id)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED) && !GetQuestRewardStatus(quest_id)) { AddTimedQuest(quest_id); @@ -18001,8 +17947,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); @@ -18355,14 +18301,17 @@ void Player::SendRaidInfo() InstanceSave* save = itr->second.save; data << uint32(save->GetMapId()); // map id data << uint32(save->GetDifficulty()); // difficulty + data << uint32(0); // Unknown 4.2.2 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(0); // Unknown 4.2.2 ++counter; } } } + data.put<uint32>(p_counter, counter); GetSession()->SendPacket(&data); } @@ -18387,8 +18336,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); @@ -18401,7 +18350,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); } @@ -18534,7 +18483,7 @@ bool Player::_LoadHomeBind(PreparedQueryResult result) PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); if (!info) { - sLog->outError(LOG_FILTER_PLAYER, "Player (Name %s) has incorrect race/class pair. Can't be loaded.", GetName()); + sLog->outError(LOG_FILTER_PLAYER, "Player (Name %s) has incorrect race/class (%u/%u) pair. Can't be loaded.", GetName(), uint32(getRace()), uint32(getClass())); return false; } @@ -18626,7 +18575,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)); @@ -18649,8 +18598,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); @@ -18661,26 +18615,34 @@ 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++, GetCurrency(CURRENCY_TYPE_CONQUEST_POINTS)); + stmt->setUInt32(index++, GetCurrency(CURRENCY_TYPE_HONOR_POINTS)); 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 (GetPowerIndexByClass(Powers(i), getClass()) != MAX_POWERS) + { + stmt->setUInt32(index++, GetUInt32Value(UNIT_FIELD_POWER1 + storedPowers)); + if (++storedPowers >= MAX_STORED_POWERS) + break; + } + } + + for (; storedPowers < MAX_STORED_POWERS; ++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) @@ -18701,15 +18663,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); } @@ -18723,7 +18683,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)); @@ -18760,8 +18720,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); @@ -18772,26 +18737,34 @@ 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++, GetCurrency(CURRENCY_TYPE_CONQUEST_POINTS)); + stmt->setUInt32(index++, GetCurrency(CURRENCY_TYPE_HONOR_POINTS)); 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 (GetPowerIndexByClass(Powers(i), getClass()) != MAX_POWERS) + { + stmt->setUInt32(index++, GetUInt32Value(UNIT_FIELD_POWER1 + storedPowers)); + if (++storedPowers >= MAX_STORED_POWERS) + break; + } + } + + for (; storedPowers < MAX_STORED_POWERS; ++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) @@ -18814,7 +18787,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) @@ -18838,6 +18810,7 @@ void Player::SaveToDB(bool create /*=false*/) _SaveBGData(trans); _SaveInventory(trans); + _SaveVoidStorage(trans); _SaveQuestStatus(trans); _SaveDailyQuestStatus(trans); _SaveWeeklyQuestStatus(trans); @@ -18877,7 +18850,7 @@ void Player::SaveInventoryAndGoldToDB(SQLTransaction& trans) void Player::SaveGoldToDB(SQLTransaction& trans) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_MONEY); - stmt->setUInt32(0, GetMoney()); + stmt->setUInt64(0, GetMoney()); stmt->setUInt32(1, GetGUIDLow()); trans->Append(stmt); } @@ -18893,7 +18866,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())); @@ -18908,7 +18881,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; @@ -18918,7 +18891,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++); @@ -19077,7 +19050,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; } } @@ -19107,6 +19080,37 @@ 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_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_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::_SaveMail(SQLTransaction& trans) { if (!m_mailsLoaded) @@ -19367,9 +19371,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) { @@ -19380,7 +19386,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_UDP_CHAR_SKILLS); @@ -19389,13 +19394,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; } } @@ -19458,7 +19462,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_STORED_POWERS; ++i) stmt->setUInt32(index++, GetMaxPower(Powers(i))); for (uint8 i = 0; i < MAX_STATS; ++i) @@ -19729,7 +19733,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); @@ -19916,13 +19920,16 @@ void Player::StopCastingCharm() } } -inline void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language) const +inline void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix /*= NULL*/) const { *data << uint8(msgtype); *data << uint32(language); *data << uint64(GetGUID()); *data << uint32(0); // constant unknown time - *data << uint64(GetGUID()); + if (addonPrefix) + *data << addonPrefix; + else + *data << uint64(GetGUID()); *data << uint32(text.length() + 1); *data << text; *data << uint8(GetChatTag()); @@ -19958,13 +19965,21 @@ void Player::TextEmote(const std::string& text) SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT)); } -void Player::Whisper(const std::string& text, uint32 language, uint64 receiver) +void Player::WhisperAddon(const std::string& text, const std::string& prefix, Player* receiver) { - bool isAddonMessage = language == LANG_ADDON; + std::string _text(text); + sScriptMgr->OnPlayerChat(this, CHAT_MSG_WHISPER, LANG_UNIVERSAL, _text, receiver); - if (!isAddonMessage) // if not addon data - language = LANG_UNIVERSAL; // whispers should always be readable + if (!receiver->GetSession()->IsAddonRegistered(prefix)) + return; + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildPlayerChat(&data, CHAT_MSG_WHISPER, _text, LANG_UNIVERSAL, prefix.c_str()); + receiver->GetSession()->SendPacket(&data); +} + +void Player::Whisper(const std::string& text, uint32 language, uint64 receiver) +{ Player* rPlayer = ObjectAccessor::FindPlayer(receiver); std::string _text(text); @@ -19977,22 +19992,13 @@ void Player::Whisper(const std::string& text, uint32 language, uint64 receiver) BuildPlayerChat(&data, CHAT_MSG_WHISPER, _text, language); rPlayer->GetSession()->SendPacket(&data); - // not send confirmation for addon messages - if (!isAddonMessage) - { - data.Initialize(SMSG_MESSAGECHAT, 200); - rPlayer->BuildPlayerChat(&data, CHAT_MSG_WHISPER_INFORM, _text, language); - GetSession()->SendPacket(&data); - } + data.Initialize(SMSG_MESSAGECHAT, 200); + rPlayer->BuildPlayerChat(&data, CHAT_MSG_WHISPER_INFORM, _text, language); + GetSession()->SendPacket(&data); } - else if (!isAddonMessage) - // announce to player that player he is whispering to is dnd and cannot receive his message + else // announce to player that player he is whispering to is dnd and cannot receive his message ChatHandler(this).PSendSysMessage(LANG_PLAYER_DND, rPlayer->GetName(), rPlayer->dndMsg.c_str()); - // rest stuff shouldn't happen in case of addon message - if (isAddonMessage) - return; - if (!isAcceptWhispers() && !isGameMaster() && !rPlayer->isGameMaster()) { SetAcceptWhispers(true); @@ -20283,33 +20289,37 @@ bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod void Player::AddSpellMod(SpellModifier* mod, bool apply) { sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "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 @@ -20724,7 +20734,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)); @@ -20737,9 +20747,9 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc } //Checks and preparations done, DO FLIGHT - ModifyMoney(-(int32)totalcost); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1); + ModifyMoney(-int64(totalcost)); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1); // prevent stealth flight //RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); @@ -20875,7 +20885,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); @@ -20895,7 +20905,6 @@ void Player::InitDataForForm(bool reapplyMods) break; } case FORM_BEAR: - case FORM_DIREBEAR: { if (getPowerType() != POWER_RAGE) setPowerType(POWER_RAGE); @@ -20944,12 +20953,12 @@ 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) +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) { 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) { @@ -20959,19 +20968,19 @@ 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); - 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], 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->RequiredCurrency[i]) + ModifyCurrency(iece->RequiredCurrency[i], -int32(iece->RequiredCurrencyCount[i])); } } @@ -20980,7 +20989,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()); @@ -20988,7 +20997,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(); @@ -21006,6 +21015,110 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c return true; } +bool Player::BuyCurrencyFromVendorSlot(uint64 vendorGuid, uint32 vendorSlot, uint32 currency, uint32 count) +{ + vendorSlot += 1; + + // 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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "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 (crItem->ExtendedCost) + { + ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost); + if (!iece) + { + sLog->outError(LOG_FILTER_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] * count))) + { + 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; + } + + uint32 precision = (entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? 100 : 1; + + if (!HasCurrency(iece->RequiredCurrency[i], (iece->RequiredCurrencyCount[i] * count) / precision)) + { + 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; + } + } + 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, crItem->maxcount); + + 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) { @@ -21073,31 +21186,44 @@ 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 (pProto->BuyCount != count) { - sLog->outError(LOG_FILTER_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)) + ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost); + if (!iece) { - SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL); + sLog->outError(LOG_FILTER_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] * count))) + { + 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; + } + + uint32 precision = (entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? 100 : 1; + + if (!HasCurrency(iece->RequiredCurrency[i], (iece->RequiredCurrencyCount[i] * count) / precision)) { SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); return false; @@ -21105,7 +21231,7 @@ 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); @@ -21127,7 +21253,7 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 // reputation discount price = uint32(floor(price * GetReputationPriceDiscount(creature))); - if (!HasEnoughMoney(price)) + if (!HasEnoughMoney(uint64(price))) { SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, item, 0); return false; @@ -21141,9 +21267,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)) @@ -21151,7 +21277,7 @@ 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; } @@ -21539,7 +21665,7 @@ void Player::ToggleMetaGemsActive(uint8 exceptslot, bool apply) //cycle all equipped items for (int slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) { - //enchants for the slot being socketed are handled by WorldSession::HandleSocketOpcode(WorldPacket& recv_data) + //enchants for the slot being socketed are handled by WorldSession::HandleSocketOpcode(WorldPacket& recvData) if (slot == exceptslot) continue; @@ -21823,7 +21949,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) { @@ -21915,16 +22041,16 @@ void Player::InitPrimaryProfessions() SetFreePrimaryProfessions(sWorld->getIntConfig(CONFIG_MAX_PRIMARY_TRADE_SKILL)); } -void Player::ModifyMoney(int32 d) +void Player::ModifyMoney(int64 d) { sScriptMgr->OnPlayerMoneyChanged(this, d); if (d < 0) - SetMoney (GetMoney() > uint32(-d) ? GetMoney() + d : 0); + SetMoney (GetMoney() > uint64(-d) ? GetMoney() + d : 0); else { - uint32 newAmount = 0; - if (GetMoney() < uint32(MAX_MONEY_AMOUNT - d)) + uint64 newAmount = 0; + if (GetMoney() < uint64(MAX_MONEY_AMOUNT - d)) newAmount = GetMoney() + d; else { @@ -21933,7 +22059,7 @@ void Player::ModifyMoney(int32 d) if (d) SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL); } - SetMoney (newAmount); + SetMoney(newAmount); } } @@ -22073,12 +22199,6 @@ void Player::SendInitialPacketsBeforeAddToMap() SendTalentsInfoData(false); - // SMSG_INSTANCE_DIFFICULTY - data.Initialize(SMSG_INSTANCE_DIFFICULTY, 4+4); - data << uint32(GetMap()->GetDifficulty()); - data << uint32(0); - GetSession()->SendPacket(&data); - SendInitialSpells(); data.Initialize(SMSG_SEND_UNLEARN_SPELLS, 4); @@ -22087,7 +22207,7 @@ void Player::SendInitialPacketsBeforeAddToMap() SendInitialActionButtons(); m_reputationMgr.SendInitialReputations(); - m_achievementMgr.SendAllAchievementData(); + m_achievementMgr.SendAllAchievementData(this); SendEquipmentSetList(); @@ -22104,6 +22224,7 @@ void Player::SendInitialPacketsBeforeAddToMap() // SMSG_UPDATE_WORLD_STATE // SMSG_POWER_UPDATE + SendCurrencies(); SetMover(this); } @@ -22138,16 +22259,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); - } + SendMoveRoot(2); SendAurasForTarget(this); SendEnchantmentDurations(); // must be after add to map @@ -22183,18 +22299,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); } @@ -22535,6 +22641,7 @@ void Player::ResetWeeklyQuestStatus() m_weeklyquests.clear(); // DB data deleted in caller m_WeeklyQuestChanged = false; + } void Player::ResetSeasonalQuestStatus(uint16 event_id) @@ -22661,7 +22768,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) { @@ -22729,7 +22836,7 @@ void Player::SummonIfPossible(bool agree) m_summon_expire = 0; - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS, 1); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS, 1); TeleportTo(m_summon_mapid, m_summon_x, m_summon_y, m_summon_z, GetOrientation()); } @@ -23084,14 +23191,15 @@ void Player::ResurectUsingRequestData() else SetFullHealth(); - if (GetMaxPower(POWER_MANA) > m_resurrectMana) + if (uint32(GetMaxPower(POWER_MANA)) > m_resurrectMana) SetPower(POWER_MANA, m_resurrectMana); 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); SpawnCorpseBones(); } @@ -23569,27 +23677,22 @@ 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); } bool Player::isTotalImmune() @@ -23698,17 +23801,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; } @@ -23803,7 +23914,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 @@ -23852,7 +23963,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; } @@ -23903,9 +24014,9 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot) --loot->unlootedCount; SendNewItem(newitem, uint32(item->count), false, false, true); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, loot->loot_type, item->count); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item->itemid, item->count); + 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_EPIC_ITEM, item->itemid, item->count); } else SendEquipError(msg, NULL, NULL, item->itemid); @@ -23913,16 +24024,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)); + + // 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; + + NumTalentsAtLevelEntry const* dkBase = sNumTalentsAtLevelStore.LookupEntry(55); + if (!dkBase) + return 0; - uint32 talentPointsForLevel = getLevel() < 56 ? 0 : getLevel() - 55; - talentPointsForLevel += m_questRewardTalentCount; + float talentPointsForLevel = count->Talents - dkBase->Talents; + talentPointsForLevel += float(GetQuestRewardedTalentCount()); - if (talentPointsForLevel > base_talent) - talentPointsForLevel = base_talent; + if (talentPointsForLevel > baseForLevel) + talentPointsForLevel = baseForLevel; return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT)); } @@ -23948,6 +24073,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 @@ -23990,14 +24116,28 @@ void Player::_LoadSkills(PreparedQueryResult result) continue; } - // enable unlearn button for primary professions only + uint16 field = count / 2; + uint8 offset = count & 1; + + SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, skill); + uint16 step = 0; + + if (pSkill->categoryId == SKILL_CATEGORY_SECONDARY) + step = max / 75; + if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) - SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, 1)); - else - SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, 0)); + { + step = max / 75; + + if (professionCount < 2) + SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + professionCount++, skill); + } - 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))); @@ -24016,9 +24156,15 @@ 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; + + 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); } // special settings @@ -24109,7 +24255,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 @@ -24117,12 +24263,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)) @@ -24136,7 +24282,7 @@ void Player::HandleFall(MovementInfo const& movementInfo) { // calculate total z distance of the fall float z_diff = m_lastFallZ - movementInfo.pos.GetPositionZ(); - //sLog->outDebug("zDiff = %f", z_diff); + //sLog->outDebug(LOG_FILTER_GENERAL, "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 @@ -24171,7 +24317,7 @@ void Player::HandleFall(MovementInfo const& movementInfo) // recheck alive, might have died of EnvironmentalDamage, avoid cases when player die in fact like Spirit of Redemption case if (isAlive() && final_damage < original_health) - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100)); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100)); } //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction @@ -24183,37 +24329,45 @@ void Player::HandleFall(MovementInfo const& movementInfo) void Player::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= NULL*/) { - GetAchievementMgr().UpdateAchievementCriteria(type, miscValue1, miscValue2, unit); + GetAchievementMgr().UpdateAchievementCriteria(type, miscValue1, miscValue2, unit, this); + + // Update only individual achievement criteria here, otherwise we may get multiple updates + // from a single boss kill + if (sAchievementMgr->IsGroupCriteriaType(type)) + return; + + if (Guild* guild = sGuildMgr->GetGuildById(GetGuildId())) + guild->GetAchievementMgr().UpdateAchievementCriteria(type, miscValue1, miscValue2, unit, this); } void Player::CompletedAchievement(AchievementEntry const* entry) { - GetAchievementMgr().CompletedAchievement(entry); + GetAchievementMgr().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 @@ -24228,11 +24382,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) @@ -24247,33 +24401,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); } } } @@ -24283,28 +24436,43 @@ 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) { sLog->outError(LOG_FILTER_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); + + sLog->outInfo(LOG_FILTER_GENERAL, "TalentID: %u Rank: %u Spell: %u Spec: %u\n", talentId, talentRank, spellid, GetActiveSpec()); - sLog->outInfo(LOG_FILTER_PLAYER, "TalentID: %u Rank: %u Spell: %u Spec: %u\n", talentId, talentRank, spellid, m_activeSpec); + // 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); + } // update free talent points SetFreeTalentPoints(CurTalentPoints - (talentRank - curtalent_maxrank + 1)); + return true; } void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank) @@ -24445,7 +24613,7 @@ 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) @@ -24514,17 +24682,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 @@ -24573,7 +24742,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 } } } @@ -24904,7 +25073,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; @@ -24913,15 +25082,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()); } @@ -24933,7 +25098,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; @@ -24943,7 +25108,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); } @@ -24966,7 +25131,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) { @@ -24989,7 +25154,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 { @@ -25006,7 +25171,7 @@ void Player::UpdateSpecCount(uint8 count) if (curCount == count) return; - if (m_activeSpec >= count) + if (GetActiveSpec() >= count) ActivateSpec(0); SQLTransaction trans = CharacterDatabase.BeginTransaction(); @@ -25033,11 +25198,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); @@ -25115,10 +25279,19 @@ void Player::ActivateSpec(uint8 spec) } } + // Remove spec specific spells + for (uint32 i = 0; i < MAX_TALENT_TABS; ++i) + { + std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(GetTalentTabPages(getClass())[i]); + if (specSpells) + for (size_t i = 0; i < specSpells->size(); ++i) + removeSpell(specSpells->at(i), 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); @@ -25148,7 +25321,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 @@ -25156,10 +25329,15 @@ 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); + // 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) @@ -25169,13 +25347,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); } @@ -25187,6 +25365,9 @@ 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() @@ -25212,6 +25393,7 @@ void Player::SetReputation(uint32 factionentry, uint32 value) { GetReputationMgr().SetReputation(sFactionStore.LookupEntry(factionentry), value); } + uint32 Player::GetReputation(uint32 factionentry) { return GetReputationMgr().GetReputation(sFactionStore.LookupEntry(factionentry)); @@ -25219,7 +25401,7 @@ uint32 Player::GetReputation(uint32 factionentry) std::string Player::GetGuildName() { - return sGuildMgr->GetGuildById(GetGuildId())->GetName(); + return GetGuildId() ? sGuildMgr->GetGuildById(GetGuildId())->GetName() : ""; } void Player::SendDuelCountdown(uint32 counter) @@ -25268,18 +25450,40 @@ 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->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 { - data << uint32(iece->reqitem[i]); - data << uint32(iece->reqitemcount[i]); + data << uint32(iece->RequiredCurrencyCount[i]); + 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); } @@ -25306,6 +25510,51 @@ 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) + { + data << uint32(iece->RequiredCurrencyCount[i]); + 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)) @@ -25317,10 +25566,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; } @@ -25339,10 +25585,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) { @@ -25358,25 +25604,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 @@ -25390,10 +25622,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_CURRENCIES; ++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; @@ -25408,13 +25640,7 @@ void Player::RefundItem(Item* item) 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); + // Grant back Arena and Honor points ? SaveInventoryAndGoldToDB(trans); @@ -25503,6 +25729,106 @@ bool Player::IsInWhisperWhiteList(uint64 guid) return false; } +uint8 Player::GetNextVoidStorageFreeSlot() const +{ + for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i) + if (!_voidStorageItems[i]) // unused item + return i; + + return VOID_STORAGE_MAX_SLOT; +} + +uint8 Player::GetNumOfVoidStorageFreeSlots() const +{ + uint8 count = 0; + + for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i) + if (!_voidStorageItems[i]) + count++; + + return count; +} + +uint8 Player::AddVoidStorageItem(const VoidStorageItem& item) +{ + int8 slot = GetNextVoidStorageFreeSlot(); + + if (slot >= VOID_STORAGE_MAX_SLOT) + { + GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL); + return 255; + } + + _voidStorageItems[slot] = new VoidStorageItem(item.ItemId, item.ItemEntry, + item.CreatorGuid, item.ItemRandomPropertyId, item.ItemSuffixFactor); + return slot; +} + +void Player::AddVoidStorageItemAtSlot(uint8 slot, const VoidStorageItem& item) +{ + if (slot >= VOID_STORAGE_MAX_SLOT) + { + GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL); + return; + } + + if (_voidStorageItems[slot]) + { + sLog->outError(LOG_FILTER_GENERAL, "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(), _voidStorageItems[slot]->ItemId, _voidStorageItems[slot]->ItemEntry, slot); + GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1); + return; + } + + _voidStorageItems[slot] = new VoidStorageItem(item.ItemId, item.ItemId, + item.CreatorGuid, item.ItemRandomPropertyId, item.ItemSuffixFactor); +} + +void Player::DeleteVoidStorageItem(uint8 slot) +{ + if (slot >= VOID_STORAGE_MAX_SLOT) + { + GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1); + return; + } + + delete _voidStorageItems[slot]; + _voidStorageItems[slot] = NULL; +} + +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; +} + +VoidStorageItem* Player::GetVoidStorageItem(uint8 slot) const +{ + if (slot >= VOID_STORAGE_MAX_SLOT) + { + GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1); + return NULL; + } + + return _voidStorageItems[slot]; +} + +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; +} + bool Player::SetHover(bool enable) { if (!Unit::SetHover(enable)) @@ -25513,9 +25839,56 @@ bool Player::SetHover(bool enable) void Player::SendMovementSetCanFly(bool apply) { - WorldPacket data(apply ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, 12); - data.append(GetPackGUID()); - data << uint32(0); //! movement counter + ObjectGuid guid = GetGUID(); + WorldPacket data; + if (apply) + { + data.Initialize(SMSG_MOVE_SET_CAN_FLY, 1 + 8 + 4); + data.WriteBit(guid[1]); + data.WriteBit(guid[6]); + data.WriteBit(guid[5]); + data.WriteBit(guid[0]); + data.WriteBit(guid[7]); + data.WriteBit(guid[4]); + data.WriteBit(guid[2]); + data.WriteBit(guid[3]); + + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[3]); + + data << uint32(0); //! movement counter + + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[5]); + } + else + { + data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 1 + 8 + 4); + data.WriteBit(guid[1]); + data.WriteBit(guid[4]); + data.WriteBit(guid[2]); + data.WriteBit(guid[5]); + data.WriteBit(guid[0]); + data.WriteBit(guid[3]); + data.WriteBit(guid[6]); + data.WriteBit(guid[7]); + + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[6]); + + data << uint32(0); //! movement counter + + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[7]); + } SendDirectMessage(&data); } @@ -25539,16 +25912,140 @@ void Player::SendMovementSetHover(bool apply) void Player::SendMovementSetWaterWalking(bool apply) { - WorldPacket data(apply ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, 12); - data.append(GetPackGUID()); - data << uint32(0); //! movement counter + ObjectGuid guid = GetGUID(); + WorldPacket data; + if (apply) + { + data.Initialize(SMSG_MOVE_WATER_WALK, 1 + 4 + 8); + data.WriteBit(guid[4]); + data.WriteBit(guid[7]); + data.WriteBit(guid[6]); + data.WriteBit(guid[0]); + data.WriteBit(guid[1]); + data.WriteBit(guid[3]); + data.WriteBit(guid[5]); + data.WriteBit(guid[2]); + + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[2]); + + data << uint32(0); //! movement counter + + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[6]); + } + else + { + data.Initialize(SMSG_MOVE_LAND_WALK, 1 + 4 + 8); + data.WriteBit(guid[5]); + data.WriteBit(guid[1]); + data.WriteBit(guid[6]); + data.WriteBit(guid[2]); + data.WriteBit(guid[3]); + data.WriteBit(guid[4]); + data.WriteBit(guid[0]); + data.WriteBit(guid[7]); + + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[2]); + + data << uint32(0); //! movement counter + } SendDirectMessage(&data); } void Player::SendMovementSetFeatherFall(bool apply) { - WorldPacket data(apply ? SMSG_MOVE_FEATHER_FALL : SMSG_MOVE_NORMAL_FALL, 12); - data.append(GetPackGUID()); - data << uint32(0); //! movement counter + ObjectGuid guid = GetGUID(); + WorldPacket data; + + if (apply) + { + data.Initialize(SMSG_MOVE_FEATHER_FALL, 1 + 4 + 8); + data.WriteBit(guid[3]); + data.WriteBit(guid[1]); + data.WriteBit(guid[7]); + data.WriteBit(guid[0]); + data.WriteBit(guid[4]); + data.WriteBit(guid[2]); + data.WriteBit(guid[5]); + data.WriteBit(guid[6]); + + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[2]); + + data << uint32(0); //! movement counter + + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[6]); + } + else + { + data.Initialize(SMSG_MOVE_NORMAL_FALL, 1 + 4 + 8); + + data << uint32(0); //! movement counter + + data.WriteBit(guid[3]); + data.WriteBit(guid[0]); + data.WriteBit(guid[1]); + data.WriteBit(guid[5]); + data.WriteBit(guid[7]); + data.WriteBit(guid[4]); + data.WriteBit(guid[6]); + data.WriteBit(guid[2]); + + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[6]); + } + + SendDirectMessage(&data); +} + +void Player::SendMovementSetCollisionHeight(float height) +{ + ObjectGuid guid = GetGUID(); + WorldPacket data(SMSG_MOVE_SET_COLLISION_HEIGHT, 2 + 8 + 4 + 4); + data.WriteBits(0, 2); + data.WriteBit(guid[6]); + data.WriteBit(guid[1]); + data.WriteBit(guid[4]); + data.WriteBit(guid[7]); + data.WriteBit(guid[5]); + data.WriteBit(guid[2]); + data.WriteBit(guid[0]); + data.WriteBit(guid[3]); + data.FlushBits(); + + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[5]); + data << uint32(sWorld->GetGameTime()); // Packet counter + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[7]); + data << float(height); + SendDirectMessage(&data); } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 358eebb7548..09c7e0ff2a1 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -44,6 +44,7 @@ #include<vector> struct Mail; +struct ItemExtendedCostEntry; class Channel; class Creature; class DynamicObject; @@ -57,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 @@ -124,9 +125,25 @@ struct SpellModifier Aura* const ownerAura; }; +enum PlayerCurrencyState +{ + PLAYERCURRENCY_UNCHANGED = 0, + PLAYERCURRENCY_CHANGED = 1, + PLAYERCURRENCY_NEW = 2, + PLAYERCURRENCY_REMOVED = 3 +}; + +struct PlayerCurrency +{ + PlayerCurrencyState state; + uint32 totalCount; + uint32 weekCount; +}; + typedef UNORDERED_MAP<uint32, PlayerTalent*> PlayerTalentMap; typedef UNORDERED_MAP<uint32, PlayerSpell*> PlayerSpellMap; typedef std::list<SpellModifier*> SpellModList; +typedef UNORDERED_MAP<uint32, PlayerCurrency> PlayerCurrenciesMap; typedef std::list<uint64> WhisperListContainer; @@ -141,9 +158,9 @@ typedef UNORDERED_MAP<uint32 /*instanceId*/, time_t/*releaseTime*/> InstanceTime 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 }; @@ -205,20 +222,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; } @@ -348,14 +351,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, @@ -397,7 +392,7 @@ enum PlayerFlags PLAYER_FLAGS_UNK26 = 0x04000000, PLAYER_FLAGS_UNK27 = 0x08000000, PLAYER_FLAGS_UNK28 = 0x10000000, - PLAYER_FLAGS_UNK29 = 0x20000000, + PLAYER_FLAGS_VOID_UNLOCKED = 0x20000000, // void storage PLAYER_FLAGS_UNK30 = 0x40000000, PLAYER_FLAGS_UNK31 = 0x80000000, }; @@ -470,7 +465,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 @@ -484,7 +479,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. @@ -556,7 +550,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) }; @@ -618,18 +612,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, @@ -677,22 +659,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 @@ -807,6 +791,7 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADQUESTSTATUSREW = 29, PLAYER_LOGIN_QUERY_LOADINSTANCELOCKTIMES = 30, PLAYER_LOGIN_QUERY_LOADSEASONALQUESTSTATUS = 31, + PLAYER_LOGIN_QUERY_LOADVOIDSTORAGE = 32, MAX_PLAYER_LOGIN_QUERY, }; @@ -823,7 +808,7 @@ enum PlayerDelayedOperations // Player summoning auto-decline time (in secs) #define MAX_PLAYER_SUMMON_DELAY (2*MINUTE) -#define MAX_MONEY_AMOUNT (0x7FFFFFFF-1) +#define MAX_MONEY_AMOUNT (UI64LIT(9999999999)) // TODO: Move this restriction to worldserver.conf, default to this value, hardcap at uint64.max struct InstancePlayerBind { @@ -865,12 +850,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, @@ -907,14 +886,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; @@ -976,6 +955,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 @@ -997,8 +1003,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); @@ -1018,12 +1024,12 @@ 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 casted by item use - uint64 m_items[TRADE_SLOT_COUNT]; // traded itmes from m_player side including non-traded slot + uint64 m_items[TRADE_SLOT_COUNT]; // traded items from m_player side including non-traded slot }; class KillRewarder @@ -1058,6 +1064,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; @@ -1093,7 +1143,7 @@ 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); @@ -1139,8 +1189,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); @@ -1189,7 +1237,8 @@ class Player : public Unit, public GridObject<Player> void Yell(const std::string& text, const uint32 language); void TextEmote(const std::string& text); void Whisper(const std::string& text, const uint32 language, uint64 receiver); - void BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language) const; + void WhisperAddon(const std::string& text, const std::string& prefix, Player* receiver); + void BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix = NULL) const; /*********************************************************/ /*** STORAGE SYSTEM ***/ @@ -1276,11 +1325,13 @@ class Player : public Unit, public GridObject<Player> void AddRefundReference(uint32 it); void DeleteRefundReference(uint32 it); + void SendCurrencies() const; + uint32 GetCurrency(uint32 id) const; + bool HasCurrency(uint32 id, uint32 count) const; + void SetCurrency(uint32 id, uint32 count, bool printLog = true); + void ModifyCurrency(uint32 id, int32 count, bool printLog = true); + 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); @@ -1305,10 +1356,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; } @@ -1325,6 +1375,7 @@ class Player : public Unit, public GridObject<Player> } 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; @@ -1344,6 +1395,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); @@ -1474,14 +1526,13 @@ class Player : public Unit, public GridObject<Player> void UpdateForQuestWorldObjects(); bool CanShareQuest(uint32 quest_id) const; - void SendQuestComplete(uint32 quest_id); + void SendQuestComplete(Quest const* quest); void SendQuestReward(Quest const* quest, uint32 XP, Object* questGiver); void SendQuestFailed(uint32 questId, InventoryResult reason = EQUIP_ERR_OK); void SendQuestTimerFailed(uint32 quest_id); void SendCanTakeQuestResponse(uint32 msg) const; void SendQuestConfirmAccept(Quest const* quest, Player* pReceiver); void SendPushToPartyResponse(Player* player, uint32 msg); - void SendQuestUpdateAddItem(Quest const* quest, uint32 item_idx, uint16 count); void SendQuestUpdateAddCreatureOrGo(Quest const* quest, uint64 guid, uint32 creatureOrGO_idx, uint16 old_count, uint16 add_count); void SendQuestUpdateAddPlayer(Quest const* quest, uint16 old_count, uint16 add_count); @@ -1510,6 +1561,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; } + static bool IsValidRace(uint8 Race) { return (1 << (Race - 1)) & RACEMASK_ALL_PLAYABLE; } /*********************************************************/ /*** SAVE SYSTEM ***/ @@ -1541,19 +1594,19 @@ 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); } - void ModifyMoney(int32 d); - bool HasEnoughMoney(uint32 amount) const { return (GetMoney() >= amount); } - bool HasEnoughMoney(int32 amount) const + uint64 GetMoney() const { return GetUInt64Value(PLAYER_FIELD_COINAGE); } + void ModifyMoney(int64 d); + bool HasEnoughMoney(uint64 amount) const { return GetMoney() >= amount; } + bool HasEnoughMoney(int64 amount) const { if (amount > 0) - return (GetMoney() >= (uint32) amount); + return (GetMoney() >= (uint64)amount); return true; } - void SetMoney(uint32 value) + void SetMoney(uint64 value) { - SetUInt32Value(PLAYER_FIELD_COINAGE, value); + SetUInt64Value(PLAYER_FIELD_COINAGE, value); MoneyChanged(value); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED); } @@ -1650,42 +1703,57 @@ class Player : public Unit, public GridObject<Player> void SetReputation(uint32 factionentry, uint32 value); uint32 GetReputation(uint32 factionentry); std::string GetGuildName(); - uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); } - void SetFreeTalentPoints(uint32 points); - bool resetTalents(bool no_cost = false); - uint32 resetTalentsCost() const; + + // 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 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) { - m_Glyphs[m_activeSpec][slot] = glyph; + _talentMgr->SpecInfo[GetActiveSpec()].Glyphs[slot] = glyph; SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); } - uint32 GetGlyph(uint8 slot) { return m_Glyphs[m_activeSpec][slot]; } + uint32 GetGlyph(uint8 spec, uint8 slot) const { return _talentMgr->SpecInfo[spec].Glyphs[slot]; } + + 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_POINTS2); } - void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2, profs); } + 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; } @@ -1760,7 +1828,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); @@ -1805,11 +1873,22 @@ 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) + { + if (guildId) + SetUInt64Value(OBJECT_FIELD_DATA, MAKE_NEW_GUID(guildId, 0, HIGHGUID_GUILD)); + else + SetUInt64Value(OBJECT_FIELD_DATA, 0); + + SetUInt16Value(OBJECT_FIELD_TYPE, 1, guildId != 0); + } + void SetRank(uint8 rankId) { SetUInt32Value(PLAYER_GUILDRANK, rankId); } - uint8 GetRank() { return uint8(GetUInt32Value(PLAYER_GUILDRANK)); } + uint32 GetRank() { return 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() { return GetUInt32Value(PLAYER_GUILDID); } + uint32 GetGuildId() const { return GetUInt32Value(OBJECT_FIELD_DATA); /* return only lower part */ } static uint32 GetGuildIdFromDB(uint64 guid); static uint8 GetRankFromDB(uint64 guid); int GetGuildIdInvited() { return m_GuildIdInvited; } @@ -1861,9 +1940,7 @@ 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 UpdateDamagePhysical(WeaponAttackType attType); void ApplySpellPowerBonus(int32 amount, bool apply); void UpdateSpellDamageAndHealingBonus(); @@ -1877,9 +1954,7 @@ class Player : public Unit, public GridObject<Player> 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; @@ -1904,6 +1979,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; } @@ -1942,7 +2018,6 @@ class Player : public Unit, public GridObject<Player> void SendMessageToSet(WorldPacket* data, Player const* skipped_rcvr); void SendTeleportPacket(Position &oldPos); - void SendTeleportAckPacket(); Corpse* GetCorpse() const; void SpawnCorpseBones(); @@ -1970,8 +2045,6 @@ class Player : public Unit, public GridObject<Player> } bool IsMirrorTimerActive(MirrorTimerType type) { return m_MirrorTimer[type] == getMaxTimer(type); } - void SetMovement(PlayerMovementType pType); - bool CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone); void JoinedChannel(Channel* c); @@ -2036,15 +2109,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 = NULL); //! If trans is specified, honor save query will be added to trans - void ModifyArenaPoints(int32 value, SQLTransaction* trans = NULL); //! 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 @@ -2059,7 +2127,7 @@ class Player : public Unit, public GridObject<Player> void UpdateCorpseReclaimDelay(); void SendCorpseReclaimDelay(bool load = false); - uint32 GetShieldBlockValue() const; // overwrite Unit version (virtual) + uint32 GetBlockPercent() { return GetUInt32Value(PLAYER_SHIELD_BLOCK); } bool CanParry() const { return m_canParry; } void SetCanParry(bool value); bool CanBlock() const { return m_canBlock; } @@ -2089,7 +2157,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); @@ -2441,7 +2508,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; } @@ -2457,8 +2525,8 @@ class Player : public Unit, public GridObject<Player> void AddRunePower(uint8 index); void InitRunes(); - AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } - AchievementMgr const& GetAchievementMgr() const { return m_achievementMgr; } + AchievementMgr<Player>& GetAchievementMgr() { return m_achievementMgr; } + AchievementMgr<Player> const& GetAchievementMgr() const { return m_achievementMgr; } void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, Unit* unit = NULL); void CompletedAchievement(AchievementEntry const* entry); @@ -2488,6 +2556,7 @@ class Player : public Unit, public GridObject<Player> void SendMovementSetHover(bool apply); void SendMovementSetWaterWalking(bool apply); void SendMovementSetFeatherFall(bool apply); + void SendMovementSetCollisionHeight(float height); bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); } @@ -2525,10 +2594,25 @@ class Player : public Unit, public GridObject<Player> } } + // 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; + uint32 m_holyPowerRegenTimerCount; + uint32 m_focusRegenTimerCount; float m_powerFraction[MAX_POWERS]; uint32 m_contestedPvPTimer; @@ -2574,6 +2658,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); @@ -2603,6 +2688,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); @@ -2647,6 +2733,11 @@ class Player : public Unit, public GridObject<Player> Item* m_items[PLAYER_SLOTS_COUNT]; uint32 m_currentBuybackSlot; + PlayerCurrenciesMap m_currencies; + uint32 _GetCurrencyWeekCap(const CurrencyTypesEntry* currency) const; + + VoidStorageItem* _voidStorageItems[VOID_STORAGE_MAX_SLOT]; + std::vector<Item*> m_itemUpdateQueue; bool m_itemUpdateQueueBlocked; @@ -2669,22 +2760,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; @@ -2737,7 +2823,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; @@ -2748,10 +2833,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; @@ -2795,6 +2876,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); @@ -2839,7 +2921,7 @@ 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; diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 88d3108dbe2..d5163d04297 100755 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -169,7 +169,7 @@ void MapManager::LoadTransportNPCs() Transport::Transport(uint32 period, uint32 script) : GameObject(), m_pathTime(0), m_timer(0), currenttguid(0), m_period(period), ScriptId(script), m_nextNodeTime(0) { - m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION); + m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION); } Transport::~Transport() @@ -580,7 +580,7 @@ void Transport::UpdateForMap(Map const* targetMap) { if (this != itr->getSource()->GetTransport()) { - UpdateData transData; + UpdateData transData(GetMapId()); BuildCreateUpdateBlockForPlayer(&transData, itr->getSource()); WorldPacket packet; transData.BuildPacket(&packet); @@ -590,7 +590,7 @@ void Transport::UpdateForMap(Map const* targetMap) } else { - UpdateData transData; + UpdateData transData(targetMap->GetId()); BuildOutOfRangeUpdateBlock(&transData); WorldPacket out_packet; transData.BuildPacket(&out_packet); @@ -638,8 +638,7 @@ uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, } creature->SetTransport(this); - creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); - creature->m_movementInfo.guid = GetGUID(); + creature->m_movementInfo.t_guid = GetGUID(); creature->m_movementInfo.t_pos.Relocate(x, y, z, o); if (anim) @@ -679,7 +678,7 @@ uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, void Transport::UpdatePosition(MovementInfo* mi) { - float transport_o = mi->pos.m_orientation - mi->t_pos.m_orientation; + float transport_o = mi->pos.GetOrientation() - mi->t_pos.GetOrientation(); float transport_x = mi->pos.m_positionX - (mi->t_pos.m_positionX * cos(transport_o) - mi->t_pos.m_positionY*sin(transport_o)); float transport_y = mi->pos.m_positionY - (mi->t_pos.m_positionY * cos(transport_o) + mi->t_pos.m_positionX*sin(transport_o)); float transport_z = mi->pos.m_positionZ - mi->t_pos.m_positionZ; @@ -717,7 +716,7 @@ void Transport::CalculatePassengerPosition(float& x, float& y, float& z, float& //! This method transforms supplied global coordinates into local offsets void Transport::CalculatePassengerOffset(float& x, float& y, float& z, float& o) { - o -= GetOrientation(); + o = o - GetOrientation(); z -= GetPositionZ(); y -= GetPositionY(); // y = searchedY * cos(o) + searchedX * sin(o) x -= GetPositionX(); // x = searchedX * cos(o) + searchedY * sin(o + pi) diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 5cec0cf4375..f5b313987e3 100755 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -70,9 +70,6 @@ bool Player::UpdateStats(Stats stat) switch (stat) { - case STAT_STRENGTH: - UpdateShieldBlockValue(); - break; case STAT_AGILITY: UpdateArmor(); UpdateAllCritPercentages(); @@ -93,24 +90,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(); @@ -171,7 +156,6 @@ bool Player::UpdateAllStats() UpdateAllCritPercentages(); UpdateAllSpellCritChances(); UpdateDefenseBonusesMod(); - UpdateShieldBlockValue(); UpdateSpellDamageAndHealingBonus(); UpdateManaRegen(); UpdateExpertise(BASE_ATTACK); @@ -205,7 +189,6 @@ void Player::UpdateArmor() 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 @@ -229,22 +212,25 @@ void Player::UpdateArmor() float Player::GetHealthBonusFromStamina() { - float stamina = GetStat(STAT_STAMINA); + // Taken from PaperDollFrame.lua - 4.3.4.15595 + gtOCTHpPerStaminaEntry const* hpBase = sGtOCTHpPerStaminaStore.LookupEntry((getClass() - 1) * GT_MAX_LEVEL + getLevel() - 1); - float baseStam = stamina < 20 ? stamina : 20; + float stamina = GetStat(STAT_STAMINA); + float baseStam = std::min(20.0f, stamina); float moreStam = stamina - baseStam; - return baseStam + (moreStam*10.0f); + return baseStam + moreStam * hpBase->ratio; } float Player::GetManaBonusFromIntellect() { + // Taken from PaperDollFrame.lua - 4.3.4.15595 float intellect = GetStat(STAT_INTELLECT); - float baseInt = intellect < 20 ? intellect : 20; + float baseInt = std::min(20.0f, intellect); float moreInt = intellect - baseInt; - return baseInt + (moreInt*15.0f); + return baseInt + (moreInt * 15.0f); } void Player::UpdateMaxHealth() @@ -273,33 +259,24 @@ 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; + val2 = level * 2.0f + GetStat(STAT_AGILITY) * 2.0f - 20.0f; break; case CLASS_ROGUE: val2 = level + GetStat(STAT_AGILITY) - 10.0f; @@ -307,106 +284,19 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) 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; } } 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 = CalculatePctN(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 = CalculatePctN(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); @@ -415,32 +305,15 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods - 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 += CalculatePctN(GetStat(Stats((*i)->GetMiscValue())), (*i)->GetAmount()); - } - } - else + if (!ranged) { - AuraEffectList const& mAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); - for (AuraEffectList::const_iterator i = mAPbyStat.begin(); i != mAPbyStat.end(); ++i) - attPowerMod += CalculatePctN(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 //automatically update weapon damage after attack power modification @@ -463,11 +336,6 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) } } -void Player::UpdateShieldBlockValue() -{ - SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue()); -} - void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& min_damage, float& max_damage) { UnitMods unitMod; @@ -488,7 +356,7 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo float att_speed = GetAPMultiplier(attType, normalized); - float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; + float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * att_speed; float base_pct = GetModifierValue(unitMod, BASE_PCT); float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; @@ -498,12 +366,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; - weapon_mindamage = lvl*0.85f*att_speed; - weapon_maxdamage = lvl*1.25f*att_speed; + if (GetShapeshiftForm() == FORM_CAT) + { + weapon_mindamage = weapon_mindamage / weaponSpeed; + weapon_maxdamage = weapon_maxdamage / weaponSpeed; + } + else if (GetShapeshiftForm() == FORM_BEAR) + { + weapon_mindamage = weapon_mindamage / weaponSpeed + weapon_mindamage / 2.5; + weapon_maxdamage = weapon_mindamage / weaponSpeed + weapon_maxdamage / 2.5; + } } else if (!CanUseAttackType(attType)) //check if player not in form but still can't use (disarm case) { @@ -517,11 +393,13 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo weapon_mindamage = BASE_MINDAMAGE; weapon_maxdamage = BASE_MAXDAMAGE; } + /* + TODO: Is this still needed after ammo has been removed? else if (attType == RANGED_ATTACK) //add ammo DPS to ranged damage { - weapon_mindamage += GetAmmoDPS() * att_speed; - weapon_maxdamage += GetAmmoDPS() * att_speed; - } + weapon_mindamage += ammo * att_speed; + weapon_maxdamage += ammo * att_speed; + }*/ min_damage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct; max_damage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct; @@ -567,8 +445,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 @@ -639,43 +515,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 @@ -707,12 +556,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 @@ -836,9 +685,8 @@ 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 power_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); @@ -848,9 +696,7 @@ void Player::UpdateManaRegen() // 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; - } // Set regen rate in cast state apply only on spirit based regen int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); @@ -882,6 +728,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); @@ -968,22 +821,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 index_mod = UNIT_FIELD_ATTACK_POWER_MODS; uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; - index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; } float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); - float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field - SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field //automatically update weapon damage after attack power modification @@ -1098,7 +947,7 @@ bool Guardian::UpdateStats(Stats stat) if (aurEff) { SpellInfo const* spellInfo = aurEff->GetSpellInfo(); // Then get the SpellProto and add the dummy effect value - AddPctN(mod, spellInfo->Effects[EFFECT_1].CalcValue()); // Ravenous Dead edits the original scale + AddPctN(mod, spellInfo->Effects[EFFECT_1].CalcValue(owner)); // Ravenous Dead edits the original scale } // Glyph of the Ghoul aurEff = owner->GetAuraEffect(58686, 0); @@ -1117,18 +966,6 @@ bool Guardian::UpdateStats(Stats stat) 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->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value - AddPctN(mod, spellInfo->Effects[EFFECT_0].CalcValue()); - } - } ownersBonus = float(owner->GetStat(stat)) * mod; value += ownersBonus; } @@ -1287,19 +1124,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->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value - mod += CalculatePctN(1.0f, sProto->Effects[1].CalcValue()); - } - } - bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod; SetBonusDamage(int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod)); } @@ -1333,13 +1157,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); @@ -1386,27 +1207,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; - } - } - 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 3f088c556f6..76644b1aa99 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -167,7 +167,7 @@ m_HostileRefManager(this) 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; @@ -378,12 +378,13 @@ void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed) init.Launch(); } -void Unit::UpdateSplineMovement(uint32 t_diff) +enum MovementIntervals { - enum{ - POSITION_UPDATE_DELAY = 400, - }; + POSITION_UPDATE_DELAY = 400, +}; +void Unit::UpdateSplineMovement(uint32 t_diff) +{ if (movespline->Finalized()) return; @@ -395,35 +396,37 @@ void Unit::UpdateSplineMovement(uint32 t_diff) m_movesplineTimer.Update(t_diff); if (m_movesplineTimer.Passed() || arrived) - { - m_movesplineTimer.Reset(POSITION_UPDATE_DELAY); - Movement::Location loc = movespline->ComputePosition(); + UpdateSplinePosition(); +} - if (HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) +void Unit::UpdateSplinePosition() +{ + m_movesplineTimer.Reset(POSITION_UPDATE_DELAY); + Movement::Location loc = movespline->ComputePosition(); + if (GetTransGUID()) + { + Position& pos = m_movementInfo.t_pos; + pos.m_positionX = loc.x; + pos.m_positionY = loc.y; + pos.m_positionZ = loc.z; + pos.SetOrientation(loc.orientation); + if (Unit* vehicle = GetVehicleBase()) { - Position& pos = m_movementInfo.t_pos; - pos.m_positionX = loc.x; - pos.m_positionY = loc.y; - pos.m_positionZ = loc.z; - pos.m_orientation = loc.orientation; - if (Unit* vehicle = GetVehicleBase()) - { - loc.x += vehicle->GetPositionX(); - loc.y += vehicle->GetPositionY(); - loc.z += vehicle->GetPositionZMinusOffset(); - loc.orientation = vehicle->GetOrientation(); - } - else if (Transport* trans = GetTransport()) - trans->CalculatePassengerPosition(loc.x, loc.y, loc.z, loc.orientation); + loc.x += vehicle->GetPositionX(); + loc.y += vehicle->GetPositionY(); + loc.z += vehicle->GetPositionZMinusOffset(); + loc.orientation = vehicle->GetOrientation(); } - - UpdatePosition(loc.x, loc.y, loc.z, loc.orientation); + else if (Transport* trans = GetTransport()) + trans->CalculatePassengerPosition(loc.x, loc.y, loc.z, loc.orientation); } + + UpdatePosition(loc.x, loc.y, loc.z, loc.orientation); } void Unit::DisableSpline() { - m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD)); + m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FORWARD); movespline->_Interrupt(); } @@ -590,32 +593,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; @@ -626,7 +610,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; } @@ -696,7 +680,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam // call before auras are removed if (Player* killer = GetCharmerOrOwnerPlayerOrPlayerItself()) - killer->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, victim); + killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, victim); } Kill(victim, durabilityLoss); @@ -729,7 +713,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) @@ -936,7 +920,6 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama return; SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask); - uint32 crTypeMask = victim->GetCreatureTypeMask(); if (IsDamageReducedByArmor(damageSchoolMask, spellInfo)) damage = CalcArmorReducedDamage(victim, damage, spellInfo, attackType); @@ -977,9 +960,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) AddPctF(damage, critPctDamageMod); } @@ -987,12 +967,11 @@ 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 = CalculatePctN(damage, value); damage -= damageInfo->blocked; } @@ -1165,10 +1144,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) AddPctF(damageInfo->damage, mod); break; @@ -1188,19 +1163,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 = CalculatePctN(damageInfo->damage, damageInfo->target->isBlockCritical() ? damageInfo->target->GetBlockPercent() * 2 : damageInfo->target->GetBlockPercent()); damageInfo->damage -= damageInfo->blocked_amount; damageInfo->cleanDamage += damageInfo->blocked_amount; break; @@ -1375,7 +1340,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) victim->DealDamageMods(this, damage, NULL); // TODO: Move this to a packet handler - WorldPacket data(SMSG_SPELLDAMAGESHIELD, (8+8+4+4+4+4)); + WorldPacket data(SMSG_SPELLDAMAGESHIELD, 8 + 8 + 4 + 4 + 4 + 4 + 4); data << uint64(victim->GetGUID()); data << uint64(GetGUID()); data << uint32(i_spellProto->Id); @@ -1383,6 +1348,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); @@ -1426,6 +1392,14 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo uint32 newdamage = 0; 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 = CalculatePctN(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); @@ -1433,14 +1407,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(AddPctN(armor, -(*j)->GetAmount())); - } - AuraEffectList const& ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j) { @@ -1448,27 +1414,9 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo armor = floor(AddPctN(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()); @@ -1478,7 +1426,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 = CalculatePctF(maxArmorPen, bonusPct + ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION)); + float armorPen = CalculatePctF(maxArmorPen, ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION)); // Got the value, apply it armor -= std::min(armorPen, maxArmorPen); } @@ -1559,11 +1507,6 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe float damageResisted = float(damage * i / 10); - 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() & schoolMask) && (*j)->IsAffectedOnSpell(spellInfo)) - AddPctN(damageResisted, -(*j)->GetAmount()); - AuraEffectList const& ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j) if ((*j)->GetMiscValue() & schoolMask) @@ -1590,7 +1533,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()); } RoundToInterval(auraAbsorbMod, 0.0f, 100.0f); @@ -1713,40 +1656,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(), next; (itr != vSplitDamagePctCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr) { @@ -1906,7 +1815,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); @@ -2164,7 +2073,7 @@ void Unit::SendMeleeAttackStop(Unit* victim) sLog->outInfo(LOG_FILTER_UNITS, "%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) @@ -2177,9 +2086,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; @@ -2227,19 +2134,9 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) if (spell->DmgClass == SPELL_DAMAGE_CLASS_RANGED) attType = RANGED_ATTACK; - int32 attackerWeaponSkill; - // skill value for these spells (for example judgements) is 5* level - if (spell->DmgClass == SPELL_DAMAGE_CLASS_RANGED && !spell->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 missChance = uint32(MeleeSpellMissChance(victim, attType, skillDiff, spell->Id) * 100.0f); + uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, spell->Id) * 100.0f); // Roll miss uint32 tmp = missChance; if (roll < tmp) @@ -2323,7 +2220,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) AuraEffectList const& ignore = GetAuraEffectsByType(SPELL_AURA_IGNORE_COMBAT_RESULT); for (AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) { - if (!(*i)->IsAffectedOnSpell(spell)) + if (!(*i)->IsAffectingSpell(spell)) continue; switch ((*i)->GetMiscValue()) { @@ -2339,7 +2236,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) 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)); @@ -2358,7 +2255,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) 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); @@ -2374,7 +2271,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) 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; @@ -2412,17 +2309,11 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) if (Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spell->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); - // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will ignore target's avoidance effects if (!(spell->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); - // Reduce spell hit chance for Area of effect spells from victim SPELL_AURA_MOD_AOE_AVOIDANCE aura - if (spell->IsTargetingArea()) - modHitChance -= victim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE); // Decrease hit chance from victim rating bonus if (victim->GetTypeId() == TYPEID_PLAYER) @@ -2454,26 +2345,6 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) int32 resist_chance = victim->GetMechanicResistChance(spell) * 100; tmp += resist_chance; - // Chance resist debuff - if (!spell->IsPositive()) - { - bool bNegativeAura = true; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (spell->Effects[i].ApplyAuraName == 0) - { - bNegativeAura = false; - break; - } - } - - if (bNegativeAura) - { - tmp += victim->GetMaxPositiveAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spell->Dispel)) * 100; - tmp += victim->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spell->Dispel)) * 100; - } - } - // Roll chance if (rand < tmp) return SPELL_MISS_RESIST; @@ -2619,9 +2490,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 @@ -2640,7 +2508,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 @@ -4171,7 +4039,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; } @@ -4231,7 +4099,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; @@ -4479,7 +4347,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(); } @@ -4498,7 +4366,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)) AddPctN(multiplier, (*i)->GetAmount()); } @@ -4516,7 +4384,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(); } @@ -4530,7 +4398,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(); } @@ -4868,8 +4736,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); } @@ -5012,6 +4883,127 @@ bool Unit::HandleSpellCritChanceAuraProc(Unit* victim, uint32 /*damage*/, AuraEf return true; } +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 + // sLog->outError("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) + { + sLog->outError(LOG_FILTER_SPELLS_AURAS, "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: + { + // 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: + { + // 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) { @@ -5587,6 +5579,19 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 69384; 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; } @@ -5599,7 +5604,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere return false; // mana reward - basepoints0 = CalculatePctN(int32(GetMaxPower(POWER_MANA)), triggerAmount); + basepoints0 = CalculatePctN(GetMaxPower(POWER_MANA), triggerAmount); target = this; triggered_spell_id = 29442; break; @@ -5638,7 +5643,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere break; } - // Hot Streak + // Hot Streak & Improved Hot Streak if (dummySpell->SpellIconID == 2999) { if (effIndex != 0) @@ -5651,7 +5656,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)) @@ -5660,20 +5665,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere counter->SetAmount(25); return true; } - // Burnout - if (dummySpell->SpellIconID == 2998) - { - if (!procSpell) - return false; - - int32 cost = int32(procSpell->ManaCost + CalculatePctU(GetCreateMana(), procSpell->ManaCostPercentage)); - basepoints0 = CalculatePctN(cost, triggerAmount); - if (basepoints0 <= 0) - return false; - triggered_spell_id = 44450; - target = this; - break; - } // Incanter's Regalia set (add trigger chance to Mana Shield) if (dummySpell->SpellFamilyFlags[0] & 0x8000) { @@ -5707,21 +5698,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere case 11119: case 11120: case 12846: - case 12847: - case 12848: { - switch (dummySpell->Id) - { - case 11119: basepoints0 = int32(0.04f * damage); break; - case 11120: basepoints0 = int32(0.08f * damage); break; - case 12846: basepoints0 = int32(0.12f * damage); break; - case 12847: basepoints0 = int32(0.16f * damage); break; - case 12848: basepoints0 = int32(0.20f * damage); break; - default: - sLog->outError(LOG_FILTER_UNITS, "Unit::HandleDummyAuraProc: non handled spell id: %u (IG)", dummySpell->Id); - return false; - } - + basepoints0 = CalculatePctN(damage, triggerAmount); triggered_spell_id = 12654; basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE); break; @@ -5733,16 +5711,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere 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); - } + // Remove Frost Nova cooldown + player->RemoveSpellCooldown(122, true); break; } // Blessing of Ancient Kings (Val'anyr, Hammer of Ancient Kings) @@ -5764,19 +5734,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 64413; 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; } @@ -5800,14 +5757,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere RemoveAura(dummySpell->Id); return false; } - // Improved Spell Reflection - case 59088: - case 59089: - { - triggered_spell_id = 59725; - target = this; - break; - } } // Retaliation @@ -5843,20 +5792,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere target = this; break; } - // Damage Shield - if (dummySpell->SpellIconID == 3214) - { - triggered_spell_id = 59653; - // % of amount blocked - basepoints0 = CalculatePctN(int32(GetShieldBlockValue()), triggerAmount); - break; - } - // Glyph of Blocking - if (dummySpell->Id == 58375) - { - triggered_spell_id = 58374; - break; - } // Glyph of Sunder Armor if (dummySpell->Id == 58387) { @@ -5933,19 +5868,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } switch (dummySpell->Id) { - // Siphon Life - case 63108: - { - if (!damage) - break; - // Glyph of Siphon Life - if (HasAura(56216)) - triggerAmount += triggerAmount / 4; - triggered_spell_id = 63106; - target = this; - basepoints0 = CalculatePctN(int32(damage), triggerAmount); - break; - } // Glyph of Shadowflame case 63310: { @@ -5965,41 +5887,12 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // 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 = CalculatePctN(int32(damage), triggerAmount); target = this; triggered_spell_id = 30294; + // Replenishment + CastSpell(this, 57669, true, castItem, triggeredByAura); break; } // Shadowflame (Voidheart Raiment set bonus) @@ -6054,7 +5947,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (triggeredByAura->GetCasterGUID() != victim->GetGUID()) return false; - // Energize 0.25% of max. mana + // Energize 1% of max. mana victim->CastSpell(victim, 57669, true, castItem, triggeredByAura); return true; // no hidden cooldown } @@ -6079,8 +5972,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // 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)) + // Proc only from Cure Disease on self cast + if (procSpell->Id != 528 || victim != this || !roll_chance_i(triggerAmount)) return false; triggered_spell_id = 64136; target = this; @@ -6095,9 +5988,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere return false; // heal amount - int32 total = CalculatePctN(int32(damage), triggerAmount); - int32 team = total / 5; - int32 self = total - team; + int32 self = CalculatePctN(int32(damage), triggerAmount); + int32 team = CalculatePctN(int32(damage), triggerAmount / 2); CastCustomSpell(this, 15290, &team, &self, NULL, true, castItem, triggeredByAura); return true; // no hidden cooldown } @@ -6125,25 +6017,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (!GoPoH) return false; - int EffIndex = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++) - { - if (GoPoH->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA) - { - EffIndex = i; - break; - } - } - int32 tickcount = GoPoH->GetMaxDuration() / GoPoH->Effects[EffIndex].Amplitude; - if (!tickcount) - return false; - + int32 tickcount = GoPoH->GetMaxDuration() / GoPoH->Effects[EFFECT_0].Amplitude; basepoints0 = CalculatePctN(int32(damage), triggerAmount) / tickcount; break; } - // Improved Shadowform - case 47570: + // Phantasm case 47569: + case 47570: { if (!roll_chance_i(triggerAmount)) return false; @@ -6154,9 +6034,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // 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; @@ -6216,8 +6093,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (procSpell->SpellIconID != 62) return false; - int32 mana_perc = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcValue(); - basepoints0 = int32(CalculatePctN(GetCreatePowers(POWER_MANA), mana_perc) / 10); + basepoints0 = int32(CalculatePctN(GetCreatePowers(POWER_MANA), triggerAmount) / 5); triggered_spell_id = 54833; target = this; break; @@ -6228,7 +6104,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 54846; break; } - // Glyph of Shred + // Glyph of Bloodletting case 54815: { if (!target) @@ -6237,15 +6113,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 @@ -6260,19 +6135,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: { @@ -6281,13 +6143,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 = triggerAmount * 2; - // Improved Leader of the Pack - // Check cooldown of heal spell cooldown - if (GetTypeId() == TYPEID_PLAYER && !ToPlayer()->HasSpellCooldown(34299)) - CastCustomSpell(this, 60889, &basepoints1, 0, 0, true, 0, triggeredByAura); + // Regenerate 4% mana + int32 mana = CalculatePctN(GetCreateMana(), triggerAmount); + CastCustomSpell(this, 68285, &mana, NULL, NULL, true, castItem, triggeredByAura); break; } // Healing Touch (Dreamwalker Raiment set) @@ -6299,15 +6157,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 = CalculatePctN(int32(damage), triggerAmount); - triggered_spell_id = 54755; - break; - } // Healing Touch Refund (Idol of Longevity trinket) case 28847: { @@ -6395,26 +6244,8 @@ 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; - } // Living Seed - else if (dummySpell->SpellIconID == 2860) + if (dummySpell->SpellIconID == 2860) { triggered_spell_id = 48504; basepoints0 = CalculatePctN(int32(damage), triggerAmount); @@ -6450,11 +6281,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere { 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 @@ -6478,27 +6304,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere switch (dummySpell->SpellIconID) { - case 2116: // Quick Recovery - { - if (!procSpell) - return false; - - // energy cost save - basepoints0 = CalculatePctN(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)) + if (Aura* aur = GetAura(5171)) { - aur->GetBase()->SetDuration(aur->GetSpellInfo()->GetMaxDuration(), true); + aur->SetDuration(aur->GetSpellInfo()->GetMaxDuration(), true); return true; } return false; @@ -6517,8 +6329,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere { case 267: // Improved Mend Pet { - int32 chance = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcValue(); - if (!roll_chance_i(chance)) + if (!roll_chance_i(triggerAmount)) return false; triggered_spell_id = 24406; @@ -6529,23 +6340,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere 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); + basepoints0 = CalculatePctN(procSpell->CalcPowerCost(this, SpellSchoolMask(procSpell->SchoolMask)), triggerAmount); if (basepoints0 <= 0) return false; @@ -6554,38 +6349,15 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere 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) + // This effect only from Rapid Killing (focus 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; + triggered_spell_id = 58883; + basepoints0 = CalculatePctN(GetMaxPower(POWER_FOCUS), triggerAmount); break; } } @@ -6600,17 +6372,12 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere target = this; break; } - case 57870: // Glyph of Mend Pet - { - victim->CastSpell(victim, 57894, true, NULL, NULL, GetGUID()); - return true; - } } break; } case SPELLFAMILY_PALADIN: { - // Seal of Righteousness - melee proc dummy (addition ${$MWS*(0.022*$AP+0.044*$SPH)} damage) + // Seal of Righteousness - melee proc dummy (addition (MWS * (0.011 * AP.022 * holy spell power) * 100 / 100) damage) if (dummySpell->SpellFamilyFlags[0] & 0x8000000) { if (effIndex != 0) @@ -6619,7 +6386,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere float ap = GetTotalAttackPowerValue(BASE_ATTACK); int32 holy = SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_HOLY) + victim->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_HOLY); - basepoints0 = (int32)GetAttackTime(BASE_ATTACK) * int32(ap * 0.022f + 0.044f * holy) / 1000; + basepoints0 = (int32)GetAttackTime(BASE_ATTACK) * int32(ap * 0.011f + 0.022f * holy) / 1000; break; } // Light's Beacon - Beacon of Light @@ -6636,8 +6403,22 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere { if (beaconTarget->IsWithinLOSInMap(victim)) { - basepoints0 = damage; - victim->CastCustomSpell(beaconTarget, 53654, &basepoints0, NULL, NULL, true); + int32 percent = 0; + switch (procSpell->Id) + { + case 85673: // Word of Glory + case 20473: // Holy Shock + case 19750: // Flash of Light + case 82326: // Divine Light + case 85222: // Light of Dawn + percent = triggerAmount; // 50% heal from these spells + break; + case 635: // Holy Light + percent = triggerAmount * 2; // 100% heal from Holy Light + break; + } + basepoints0 = CalculatePctN(damage, percent); + victim->CastCustomSpell(beaconTarget, 53652, &basepoints0, NULL, NULL, true); return true; } } @@ -6649,96 +6430,10 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere { target = this; triggered_spell_id = 31930; - // replenishment - CastSpell(this, 57669, true, castItem, triggeredByAura); - break; - } - // Sanctified Wrath - if (dummySpell->SpellIconID == 3029) - { - triggered_spell_id = 57318; - target = this; - basepoints0 = triggerAmount; - CastCustomSpell(target, triggered_spell_id, &basepoints0, &basepoints0, NULL, true, castItem, triggeredByAura); - return true; - } - // Sacred Shield - if (dummySpell->SpellFamilyFlags[1] & 0x80000) - { - if (procFlag & PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS) - { - if (procSpell->SpellFamilyName == SPELLFAMILY_PALADIN && (procSpell->SpellFamilyFlags[0] & 0x40000000)) - { - basepoints0 = damage / 12; - - if (basepoints0) - CastCustomSpell(this, 66922, &basepoints0, NULL, NULL, true, 0, triggeredByAura, victim->GetGUID()); - - return true; - } - else - return false; - } - else if (damage > 0) - triggered_spell_id = 58597; - - // Item - Paladin T8 Holy 4P Bonus - if (Unit* caster = triggeredByAura->GetCaster()) - if (AuraEffect const* aurEff = caster->GetAuraEffect(64895, 0)) - cooldown = aurEff->GetAmount(); - - target = this; - 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) { - // 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: - { - // 2% of base mana - 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(CalculatePctN(victim->GetCreateMana(), 2)); - victim->CastCustomSpell(victim, 20268, &basepoints0, NULL, NULL, true, 0, triggeredByAura); - } - return true; - } // Holy Power (Redemption Armor set) case 28789: { @@ -6770,24 +6465,10 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } break; } - case 25899: // Greater Blessing of Sanctuary - case 20911: // Blessing of Sanctuary - { - target = this; - switch (target->getPowerType()) - { - case POWER_MANA: - triggered_spell_id = 57319; - break; - default: - return false; - } - break; - } - // Seal of Vengeance (damage calc on apply aura) + // Seal of Truth (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 @@ -6800,7 +6481,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) @@ -6816,61 +6497,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; - - 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(CalculatePctN(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) @@ -6892,13 +6525,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere break; } - // Glyph of Holy Light - case 54937: - { - triggered_spell_id = 54968; - basepoints0 = CalculatePctN(int32(damage), triggerAmount); - break; - } // Item - Paladin T8 Holy 2P Bonus case 64890: { @@ -6978,14 +6604,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: { @@ -7058,26 +6676,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: - { - sLog->outError(LOG_FILTER_UNITS, "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) { @@ -7245,23 +6844,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 = CalculatePctN(totemSpell->Effects[EFFECT_0].CalcValue(), triggerAmount); - int32 bp1 = CalculatePctN(totemSpell->Effects[EFFECT_1].CalcValue(), triggerAmount); - CastCustomSpell(this, 63283, &bp0, &bp1, NULL, true); - return true; - } - } - return false; - } break; } // Frozen Power @@ -7287,7 +6869,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere break; } // Earth Shield - if (dummySpell->SpellFamilyFlags[1] & 0x00000400) + if (dummySpell->Id == 974) { // 3.0.8: Now correctly uses the Shaman's own spell critical strike chance to determine the chance of a critical heal. originalCaster = triggeredByAura->GetCasterGUID(); @@ -7347,109 +6929,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: - sLog->outError(LOG_FILTER_UNITS, "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; @@ -7458,7 +6950,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()) @@ -7467,14 +6959,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 = CalculatePctN(int32(damage), triggerAmount); - break; - } // Butchery if (dummySpell->SpellIconID == 2664) { @@ -7508,40 +6992,14 @@ 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) { basepoints0 = CalculatePctN(int32(damage), triggerAmount); - // Glyph of Unholy Blight - if (AuraEffect* glyph=GetAuraEffect(63332, 0)) - AddPctN(basepoints0, glyph->GetAmount()); - triggered_spell_id = 50536; 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 = CalculatePctN(int32(damage), triggerAmount); - triggered_spell_id = 51460; - break; - } // Threat of Thassarian if (dummySpell->SpellIconID == 2023) { @@ -7554,45 +7012,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; } @@ -7611,51 +7036,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 = CalculatePctN(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: @@ -7745,6 +7125,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere return true; } + bool Unit::HandleObsModEnergyAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown) { SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo(); @@ -7758,22 +7139,12 @@ bool Unit::HandleObsModEnergyAuraProc(Unit* victim, uint32 /*damage*/, AuraEffec Unit* target = victim; int32 basepoints0 = 0; + /* switch (dummySpell->SpellFamilyName) { - case SPELLFAMILY_HUNTER: - { - // Aspect of the Viper - if (dummySpell->SpellFamilyFlags[1] & 0x40000) - { - uint32 maxmana = GetMaxPower(POWER_MANA); - basepoints0 = CalculatePctF(maxmana, GetAttackTime(RANGED_ATTACK) / 1000.0f); - target = this; - triggered_spell_id = 34075; - break; - } - break; - } + } + */ // processed charge only counting case if (!triggered_spell_id) return true; @@ -7811,23 +7182,13 @@ bool Unit::HandleModDamagePctTakenAuraProc(Unit* victim, uint32 /*damage*/, Aura Unit* target = victim; int32 basepoints0 = 0; + /* switch (dummySpell->SpellFamilyName) { - case SPELLFAMILY_PALADIN: - { - // Blessing of Sanctuary - if (dummySpell->SpellFamilyFlags[0] & 0x10000000) - { - switch (getPowerType()) - { - case POWER_MANA: triggered_spell_id = 57319; break; - default: - return false; - } - } - break; - } + } + */ + // processed charge only counting case if (!triggered_spell_id) return true; @@ -7856,7 +7217,7 @@ bool Unit::HandleModDamagePctTakenAuraProc(Unit* victim, uint32 /*damage*/, Aura // 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(); @@ -7914,30 +7275,8 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp break; case SPELLFAMILY_PALADIN: { - // Infusion of Light - if (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 = CalculatePctN(int32(damage / 12), dummySpell->Effects[EFFECT_2].CalcValue()); - // Item - Paladin T9 Holy 4P Bonus - if (AuraEffect const* aurEff = GetAuraEffect(67191, 0)) - AddPctN(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); @@ -7966,24 +7305,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) ? true : false; - } // Empowered Fire case 31656: case 31657: @@ -8211,6 +7534,13 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg if (charge->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL)) RemoveAurasDueToSpell(50240); } + // Warrior - Vigilance, SPELLFAMILY_GENERIC + if (auraSpellInfo->Id == 50720) + { + target = triggeredByAura->GetCaster(); + if (!target) + return false; + } } break; case SPELLFAMILY_MAGE: @@ -8235,78 +7565,12 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg RemoveAuraFromStack(auraSpellInfo->Id); return false; } - if (auraSpellInfo->Id == 50720) - { - target = triggeredByAura->GetCaster(); - if (!target) - 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(CalculatePctN(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: { // Greater Heal Refund if (auraSpellInfo->Id == 37594) trigger_spell_id = 37595; - // Blessed Recovery - else if (auraSpellInfo->SpellIconID == 1875) - { - switch (auraSpellInfo->Id) - { - case 27811: trigger_spell_id = 27813; break; - case 27815: trigger_spell_id = 27817; break; - case 27816: trigger_spell_id = 27818; break; - default: - sLog->outError(LOG_FILTER_UNITS, "Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id); - return false; - } - basepoints0 = CalculatePctN(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: @@ -8320,8 +7584,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: @@ -8335,8 +7598,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; } @@ -8452,42 +7714,6 @@ 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 casted 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: - sLog->outError(LOG_FILTER_UNITS, "Unit::HandleProcTriggerSpell: Spell %u not handled in HShock", procSpell->Id); - return false; - } - } - SpellInfo const* originalSpell = sSpellMgr->GetSpellInfo(originalSpellId); - if (!originalSpell) - { - sLog->outError(LOG_FILTER_UNITS, "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 + CalculatePctU(GetCreateMana(), originalSpell->ManaCostPercentage)); - basepoints0 = CalculatePctN(cost, auraSpellInfo->Effects[1].CalcValue()); - trigger_spell_id = 20272; - target = this; - } break; } break; @@ -8522,77 +7748,26 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg 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)) + if (!HealthBelowPctDamaged(30, damage)) { - basepoints0 = int32(auraSpellInfo->Effects[EFFECT_0].CalcValue() * GetMaxHealth() / 100.0f); + basepoints0 = int32(CountPctFromMaxHealth(triggerAmount)); target = this; trigger_spell_id = 31616; - // TODO: Threat part + if (victim && victim->isAlive()) + victim->getThreatManager().modifyThreatPercent(this, -10); } 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 = CalculatePctN(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; @@ -8666,7 +7841,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg ItemTemplate const* weapon = item->GetTemplate(); - float weaponDPS = weapon->getDPS(); + float weaponDPS = weapon->DPS; float attackPower = GetTotalAttackPowerValue(BASE_ATTACK) / 14.0f; float weaponSpeed = float(weapon->Delay) / 1000.0f; basepoints0 = int32((weaponDPS + attackPower) * weaponSpeed); @@ -8691,7 +7866,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg // Deflection case 52420: { - if (!HealthBelowPct(35)) + if (!HealthBelowPctDamaged(35, damage)) return false; break; } @@ -8704,16 +7879,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: { @@ -8748,24 +7913,14 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg // 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) @@ -8786,52 +7941,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 @@ -8841,14 +7955,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 @@ -8865,12 +7971,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg CastSpell(this, 70721, true); break; } - // Shamanistic Rage triggered spell - case 30824: - { - basepoints0 = int32(CalculatePctN(GetTotalAttackPowerValue(BASE_ATTACK), triggerAmount)); - break; - } // Enlightenment (trigger only from mana cost spells) case 35095: { @@ -8878,22 +7978,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 { @@ -8932,35 +8016,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: { @@ -9055,7 +8110,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(); @@ -9069,27 +8124,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% @@ -9109,26 +8143,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; } @@ -9192,10 +8206,6 @@ void Unit::setPowerType(Powers new_powertype) case POWER_ENERGY: SetMaxPower(POWER_ENERGY, GetCreatePowers(POWER_ENERGY)); break; - case POWER_HAPPINESS: - SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); - SetPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); - break; } } @@ -9644,7 +8654,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 @@ -9677,7 +8687,7 @@ void Unit::SetOwnerGUID(uint64 owner) SetFieldNotifyFlag(UF_FLAG_OWNER); - UpdateData udata; + UpdateData udata(GetMapId()); WorldPacket packet; BuildValuesUpdateBlockForPlayer(&udata, player); udata.BuildPacket(&packet); @@ -10044,15 +9054,15 @@ 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->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, victim); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, victim); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED, addhealth); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED, addhealth); } if (Player* player = victim->ToPlayer()) { - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED, gain); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED, addhealth); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED, gain); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED, addhealth); } return gain; @@ -10271,7 +9281,7 @@ void Unit::SendEnergizeSpellLog(Unit* victim, uint32 spellID, uint32 damage, Pow SendMessageToSet(&data, true); } -void Unit::EnergizeBySpell(Unit* victim, uint32 spellID, uint32 damage, Powers powerType) +void Unit::EnergizeBySpell(Unit* victim, uint32 spellID, int32 damage, Powers powerType) { SendEnergizeSpellLog(victim, spellID, damage, powerType); // needs to be called after sending spell log @@ -10340,26 +9350,40 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue()))) AddPctN(DoneTotalMod, (*i)->GetAmount()); + // Add SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC percent bonus + AddPctN(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); 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)) AddPctN(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))) + AddPctN(DoneTotalMod, (*i)->GetAmount()); + } + case 6916: // Death's Embrace heal effect + case 6925: + case 6927: + if (HealthBelowPct(CalculateSpellDamage(this, (*i)->GetSpellInfo(), EFFECT_2))) + AddPctN(DoneTotalMod, (*i)->GetAmount()); + break; // Soul Siphon case 4992: case 4993: @@ -10374,8 +9398,8 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) { Aura const* aura = itr->second->GetBase(); - SpellInfo const* m_spell = aura->GetSpellInfo(); - if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK || !(m_spell->SpellFamilyFlags[1] & 0x0004071B || m_spell->SpellFamilyFlags[0] & 0x8044C402)) + SpellInfo const* spell = aura->GetSpellInfo(); + if (spell->SpellFamilyName != SPELLFAMILY_WARLOCK || !(spell->SpellFamilyFlags[1] & 0x0004071B || spell->SpellFamilyFlags[0] & 0x8044C402)) continue; modPercent += stepPercent * aura->GetStackAmount(); if (modPercent >= maxPercent) @@ -10387,12 +9411,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin AddPctN(DoneTotalMod, modPercent); break; } - case 6916: // Death's Embrace - case 6925: - case 6927: - if (HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, spellProto, this)) - AddPctN(DoneTotalMod, (*i)->GetAmount()); - break; case 5481: // Starfire Bonus { if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x200002, 0, 0)) @@ -10411,65 +9429,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin DoneTotal += (*i)->GetAmount(); break; } - // Tundra Stalker - // Merciless Combat - case 7277: - { - // Merciless Combat - if ((*i)->GetSpellInfo()->SpellIconID == 2656) - { - if (!victim->HealthAbovePct(35)) - AddPctN(DoneTotalMod, (*i)->GetAmount()); - } - // Tundra Stalker - else - { - // Frost Fever (target debuff) - if (victim->HasAura(55095)) - AddPctN(DoneTotalMod, (*i)->GetAmount()); - break; - } - break; - } - // Rage of Rivendare - case 7293: - { - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0x02000000, 0)) - AddPctF(DoneTotalMod, (*i)->GetSpellInfo()->GetRank() * 2.0f); - break; - } - // Twisted Faith - case 7377: - { - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetGUID())) - AddPctN(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)) - AddPctN(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(); - AddPctN(DoneTotalMod, bonus); - } - break; - } } } @@ -10479,89 +9438,35 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin 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) { AddPctN(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())) - AddPctN(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())) - AddPctN(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())) AddPctN(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)) - AddPctN(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) - AddPctU(DoneTotalMod, 10 * stacks); - } - break; - case SPELLFAMILY_DRUID: - // Thorns - if (spellProto->SpellFamilyFlags[0] & 0x100) - { - // Brambles - if (AuraEffect* aurEff = GetAuraEffectOfRankedSpell(16836, 0)) - AddPctN(DoneTotalMod, aurEff->GetAmount()); - } break; case SPELLFAMILY_WARLOCK: // Fire and Brimstone @@ -10579,59 +9484,17 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin // Drain Soul - increased damage for targets under 25 % HP if (spellProto->SpellFamilyFlags[0] & 0x00004000) if (HasAura(100001)) - DoneTotalMod *= 4; - // Shadow Bite (15% increase from each dot) + DoneTotalMod *= 2; + // Shadow Bite (30% increase from each dot) if (spellProto->SpellFamilyFlags[1] & 0x00400000 && isPet()) if (uint8 count = victim->GetDoTsByCaster(GetOwnerGUID())) - AddPctN(DoneTotalMod, 15 * count); - 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())) - AddPctN(DoneTotalMod, aurEff->GetAmount()); + AddPctN(DoneTotalMod, 30 * count); break; case SPELLFAMILY_DEATHKNIGHT: - // Improved Icy Touch - if (spellProto->SpellFamilyFlags[0] & 0x2) - if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2721, 0)) - AddPctN(DoneTotalMod, aurEff->GetAmount()); - // Sigil of the Vengeful Heart if (spellProto->SpellFamilyFlags[0] & 0x2000) if (AuraEffect* aurEff = GetAuraEffect(64962, EFFECT_1)) - AddPctN(DoneTotal, 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) - AddPctN(DoneTotalMod, aurEff->GetAmount()); - - // Impurity (dummy effect) - if (GetTypeId() == TYPEID_PLAYER) - { - PlayerSpellMap playerSpells = ToPlayer()->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = playerSpells.begin(); itr != playerSpells.end(); ++itr) - { - if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled) - continue; - switch (itr->first) - { - case 49220: - case 49633: - case 49635: - case 49636: - case 49638: - { - if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first)) - AddPctN(ApCoeffMod, proto->Effects[0].CalcValue()); - } - break; - } - } - } + DoneTotal += aurEff->GetAmount(); break; } @@ -10735,8 +9598,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui { if (GetTypeId() != TYPEID_PLAYER) continue; - float mod = ToPlayer()->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE) * (-8.0f); - AddPctF(TakenTotalMod, std::max(mod, float((*i)->GetAmount()))); + AddPctN(TakenTotalMod, (*i)->GetAmount()); } break; } @@ -10745,7 +9607,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui // 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)) AddPctN(TakenTotalMod, (*i)->GetAmount()); // Mod damage from spell mechanic @@ -10907,7 +9769,7 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas 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; int32 modChance = 0; switch ((*i)->GetMiscValue()) @@ -11043,6 +9905,11 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas 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(); + crit_chance = crit_chance > 0.0f ? crit_chance : 0.0f; if (roll_chance_f(crit_chance)) return true; @@ -11069,9 +9936,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) AddPctF(crit_bonus, crit_mod); @@ -11086,30 +9950,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)); @@ -11140,7 +9986,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()) { @@ -11155,12 +10001,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui if (victim->HealthBelowPct(50)) AddPctN(DoneTotalMod, (*i)->GetAmount()); break; - case 7798: // Glyph of Regrowth - { - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0)) - AddPctN(DoneTotalMod, (*i)->GetAmount()); - break; - } case 8477: // Nourish Heal Boost { int32 stepPercent = (*i)->GetAmount(); @@ -11180,12 +10020,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui AddPctN(DoneTotalMod, modPercent); break; } - case 7871: // Glyph of Lesser Healing Wave - { - if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0, 0x00000400, 0, GetGUID())) - AddPctN(DoneTotalMod, (*i)->GetAmount()); - break; - } default: break; } @@ -11237,23 +10071,9 @@ 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); } - // Gift of the Naaru - if (spellProto->SpellFamilyFlags[2] & 0x80000000 && spellProto->SpellIconID == 329) - { - int32 apBonus = int32(std::max(GetTotalAttackPowerValue(BASE_ATTACK), GetTotalAttackPowerValue(RANGED_ATTACK))); - if (apBonus > DoneAdvertisedBenefit) - DoneTotal += int32(apBonus * 0.22f); // 22% of AP per tick - else - DoneTotal += int32(DoneAdvertisedBenefit * 0.377f); // 37.7% of BH per tick - } - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { switch (spellProto->Effects[i].ApplyAuraName) @@ -11309,18 +10129,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) - AddPctF(TakenTotalMod, minval_hot); - - float maxval_hot = float(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT)); - if (maxval_hot) - AddPctF(TakenTotalMod, maxval_hot); - } - // Check for table values SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id); float coeff = 0; @@ -11351,16 +10159,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)) AddPctN(TakenTotalMod, (*i)->GetAmount()); for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) @@ -11659,80 +10463,13 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue()))) AddPctN(DoneTotalMod, (*i)->GetAmount()); + // Add SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC percent bonus + if (spellProto) + AddPctN(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); - 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)) - AddPctN(DoneTotalMod, (*i)->GetAmount()); - } - // Tundra Stalker - else - { - // Frost Fever (target debuff) - if (victim->HasAura(55095)) - AddPctN(DoneTotalMod, (*i)->GetAmount()); - } - break; - } - // Rage of Rivendare - case 7293: - { - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0x02000000, 0)) - AddPctF(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)) - AddPctN(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(); - AddPctN(DoneTotalMod, bonus); - } - break; - } - } - } - - // Custom scripted damage - 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) - AddPctN(DoneTotalMod, aurEff->GetAmount()); - break; - } + // AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); float tmpDamage = float(int32(pdamage) + DoneFlatBenefit) * DoneTotalMod; @@ -11785,7 +10522,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)) AddPctN(TakenTotalMod, (*i)->GetAmount()); // Mod damage from spell mechanic @@ -11988,11 +10725,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); @@ -12007,13 +10740,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()); @@ -12048,6 +10775,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; +} + void Unit::SetInCombatWith(Unit* enemy) { Unit* eOwner = enemy->GetCharmerOrOwnerOrSelf(); @@ -12470,16 +11255,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) { @@ -12501,7 +11286,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)); } bool Unit::IsAlwaysVisibleFor(WorldObject const* seer) const @@ -12686,44 +11471,205 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) propagateSpeedChange(); WorldPacket data; + ObjectGuid guid = GetGUID(); if (!forced) { switch (mtype) { case MOVE_WALK: - data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4); + data.Initialize(SMSG_SPLINE_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4); + data.WriteBit(guid[0]); + data.WriteBit(guid[6]); + data.WriteBit(guid[7]); + data.WriteBit(guid[3]); + data.WriteBit(guid[5]); + data.WriteBit(guid[1]); + data.WriteBit(guid[2]); + data.WriteBit(guid[4]); + data.FlushBits(); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[3]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[5]); break; case MOVE_RUN: - data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+2+4+4+4+4+4+4+4); + data.Initialize(SMSG_SPLINE_MOVE_SET_RUN_SPEED, 1 + 8 + 4); + data.WriteBit(guid[4]); + data.WriteBit(guid[0]); + data.WriteBit(guid[5]); + data.WriteBit(guid[7]); + data.WriteBit(guid[6]); + data.WriteBit(guid[3]); + data.WriteBit(guid[1]); + data.WriteBit(guid[2]); + data.FlushBits(); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[4]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[1]); break; case MOVE_RUN_BACK: - data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); + data.Initialize(SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED, 1 + 8 + 4); + data.WriteBit(guid[1]); + data.WriteBit(guid[2]); + data.WriteBit(guid[6]); + data.WriteBit(guid[0]); + data.WriteBit(guid[3]); + data.WriteBit(guid[7]); + data.WriteBit(guid[5]); + data.WriteBit(guid[4]); + data.FlushBits(); + data.WriteByteSeq(guid[1]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[7]); break; case MOVE_SWIM: - data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+2+4+4+4+4+4+4+4); + data.Initialize(SMSG_SPLINE_MOVE_SET_SWIM_SPEED, 1 + 8 + 4); + data.WriteBit(guid[4]); + data.WriteBit(guid[2]); + data.WriteBit(guid[5]); + data.WriteBit(guid[0]); + data.WriteBit(guid[7]); + data.WriteBit(guid[6]); + data.WriteBit(guid[3]); + data.WriteBit(guid[1]); + data.FlushBits(); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[4]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[3]); break; case MOVE_SWIM_BACK: - data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); + data.Initialize(SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED, 1 + 8 + 4); + data.WriteBit(guid[0]); + data.WriteBit(guid[1]); + data.WriteBit(guid[3]); + data.WriteBit(guid[6]); + data.WriteBit(guid[4]); + data.WriteBit(guid[5]); + data.WriteBit(guid[7]); + data.WriteBit(guid[2]); + data.FlushBits(); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[6]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[2]); break; case MOVE_TURN_RATE: - data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+2+4+4+4+4+4+4+4); + data.Initialize(SMSG_SPLINE_MOVE_SET_TURN_RATE, 1 + 8 + 4); + data.WriteBit(guid[2]); + data.WriteBit(guid[4]); + data.WriteBit(guid[6]); + data.WriteBit(guid[1]); + data.WriteBit(guid[3]); + data.WriteBit(guid[5]); + data.WriteBit(guid[7]); + data.WriteBit(guid[0]); + data.FlushBits(); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[0]); break; case MOVE_FLIGHT: - data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+2+4+4+4+4+4+4+4); + data.Initialize(SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED, 1 + 8 + 4); + data.WriteBit(guid[7]); + data.WriteBit(guid[4]); + data.WriteBit(guid[0]); + data.WriteBit(guid[1]); + data.WriteBit(guid[3]); + data.WriteBit(guid[6]); + data.WriteBit(guid[5]); + data.WriteBit(guid[2]); + data.FlushBits(); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[6]); + data << float(GetSpeed(mtype)); break; case MOVE_FLIGHT_BACK: - data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); + data.Initialize(SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED, 1 + 8 + 4); + data.WriteBit(guid[2]); + data.WriteBit(guid[1]); + data.WriteBit(guid[6]); + data.WriteBit(guid[5]); + data.WriteBit(guid[0]); + data.WriteBit(guid[3]); + data.WriteBit(guid[4]); + data.WriteBit(guid[7]); + data.FlushBits(); + data.WriteByteSeq(guid[5]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[4]); break; case MOVE_PITCH_RATE: - data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8+4+2+4+4+4+4+4+4+4); + data.Initialize(SMSG_SPLINE_MOVE_SET_PITCH_RATE, 1 + 8 + 4); + data.WriteBit(guid[3]); + data.WriteBit(guid[5]); + data.WriteBit(guid[6]); + data.WriteBit(guid[1]); + data.WriteBit(guid[0]); + data.WriteBit(guid[4]); + data.WriteBit(guid[7]); + data.WriteBit(guid[2]); + data.FlushBits(); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[2]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[4]); break; default: sLog->outError(LOG_FILTER_UNITS, "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype); return; } - BuildMovementPacket(&data); - data << float(GetSpeed(mtype)); SendMessageToSet(&data, true); } else @@ -12742,41 +11688,198 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) switch (mtype) { case MOVE_WALK: - data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16); + data.Initialize(SMSG_MOVE_SET_WALK_SPEED, 1 + 8 + 4 + 4); + data.WriteBit(guid[0]); + data.WriteBit(guid[4]); + data.WriteBit(guid[5]); + data.WriteBit(guid[2]); + data.WriteBit(guid[3]); + data.WriteBit(guid[1]); + data.WriteBit(guid[6]); + data.WriteBit(guid[7]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[5]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[2]); + data << uint32(0); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[3]); break; case MOVE_RUN: - data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17); + data.Initialize(SMSG_MOVE_SET_RUN_SPEED, 1 + 8 + 4 + 4); + data.WriteBit(guid[6]); + data.WriteBit(guid[1]); + data.WriteBit(guid[5]); + data.WriteBit(guid[2]); + data.WriteBit(guid[7]); + data.WriteBit(guid[0]); + data.WriteBit(guid[3]); + data.WriteBit(guid[4]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[4]); + data << uint32(0); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[2]); break; case MOVE_RUN_BACK: - data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16); + data.Initialize(SMSG_MOVE_SET_RUN_BACK_SPEED, 1 + 8 + 4 + 4); + data.WriteBit(guid[0]); + data.WriteBit(guid[6]); + data.WriteBit(guid[2]); + data.WriteBit(guid[1]); + data.WriteBit(guid[3]); + data.WriteBit(guid[4]); + data.WriteBit(guid[5]); + data.WriteBit(guid[7]); + data.WriteByteSeq(guid[5]); + data << uint32(0); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[6]); break; case MOVE_SWIM: - data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16); + data.Initialize(SMSG_MOVE_SET_SWIM_SPEED, 1 + 8 + 4 + 4); + data.WriteBit(guid[5]); + data.WriteBit(guid[4]); + data.WriteBit(guid[7]); + data.WriteBit(guid[3]); + data.WriteBit(guid[2]); + data.WriteBit(guid[0]); + data.WriteBit(guid[1]); + data.WriteBit(guid[6]); + data.WriteByteSeq(guid[0]); + data << uint32(0); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[2]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[4]); break; case MOVE_SWIM_BACK: - data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16); + data.Initialize(SMSG_MOVE_SET_SWIM_BACK_SPEED, 1 + 8 + 4 + 4); + data.WriteBit(guid[4]); + data.WriteBit(guid[2]); + data.WriteBit(guid[3]); + data.WriteBit(guid[6]); + data.WriteBit(guid[5]); + data.WriteBit(guid[1]); + data.WriteBit(guid[0]); + data.WriteBit(guid[7]); + data << uint32(0); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[1]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[2]); break; case MOVE_TURN_RATE: - data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16); + data.Initialize(SMSG_MOVE_SET_TURN_RATE, 1 + 8 + 4 + 4); + data.WriteBit(guid[7]); + data.WriteBit(guid[2]); + data.WriteBit(guid[1]); + data.WriteBit(guid[0]); + data.WriteBit(guid[4]); + data.WriteBit(guid[5]); + data.WriteBit(guid[6]); + data.WriteBit(guid[3]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[2]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[0]); + data << uint32(0); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[4]); break; case MOVE_FLIGHT: - data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16); + data.Initialize(SMSG_MOVE_SET_FLIGHT_SPEED, 1 + 8 + 4 + 4); + data.WriteBit(guid[0]); + data.WriteBit(guid[5]); + data.WriteBit(guid[1]); + data.WriteBit(guid[6]); + data.WriteBit(guid[3]); + data.WriteBit(guid[2]); + data.WriteBit(guid[7]); + data.WriteBit(guid[4]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[5]); + data << float(GetSpeed(mtype)); + data << uint32(0); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[4]); break; case MOVE_FLIGHT_BACK: - data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16); + data.Initialize(SMSG_MOVE_SET_FLIGHT_BACK_SPEED, 1 + 8 + 4 + 4); + data.WriteBit(guid[1]); + data.WriteBit(guid[2]); + data.WriteBit(guid[6]); + data.WriteBit(guid[4]); + data.WriteBit(guid[7]); + data.WriteBit(guid[3]); + data.WriteBit(guid[0]); + data.WriteBit(guid[5]); + data.WriteByteSeq(guid[3]); + data << uint32(0); + data.WriteByteSeq(guid[6]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[7]); break; case MOVE_PITCH_RATE: - data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16); + data.Initialize(SMSG_MOVE_SET_PITCH_RATE, 1 + 8 + 4 + 4); + data.WriteBit(guid[1]); + data.WriteBit(guid[2]); + data.WriteBit(guid[6]); + data.WriteBit(guid[7]); + data.WriteBit(guid[0]); + data.WriteBit(guid[3]); + data.WriteBit(guid[5]); + data.WriteBit(guid[4]); + data << float(GetSpeed(mtype)); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[0]); + data << uint32(0); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[5]); break; default: sLog->outError(LOG_FILTER_UNITS, "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); } } @@ -13407,7 +12510,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 @@ -13463,7 +12566,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; @@ -13583,8 +12685,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; @@ -13595,14 +12696,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)); @@ -13686,22 +12787,71 @@ void Unit::SetMaxHealth(uint32 val) SetHealth(val); } -void Unit::SetPower(Powers power, uint32 val) +uint32 Unit::GetPowerIndexByClass(uint32 powerId, uint32 classId) const { - if (GetPower(power) == val) + ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(classId); + + ASSERT(classEntry && "Class not found"); + + uint32 index = 0; + for (uint32 i = 0; i <= sChrPowerTypesStore.GetNumRows(); ++i) + { + ChrPowerTypesEntry const* powerEntry = sChrPowerTypesStore.LookupEntry(i); + if (!powerEntry) + continue; + + if (powerEntry->classId != classId) + continue; + + if (powerEntry->power == powerId) + return index; + + ++index; + } + + // return invalid value - this class doesn't use this power + return MAX_POWERS; +}; + +int32 Unit::GetPower(Powers power) const +{ + uint32 powerIndex = GetPowerIndexByClass(power, getClass()); + if (powerIndex == MAX_POWERS) + return 0; + + return GetUInt32Value(UNIT_FIELD_POWER1 + powerIndex); +} + +int32 Unit::GetMaxPower(Powers power) const +{ + uint32 powerIndex = GetPowerIndexByClass(power, getClass()); + if (powerIndex == MAX_POWERS) + return 0; + + return GetInt32Value(UNIT_FIELD_MAXPOWER1 + powerIndex); +} + +void Unit::SetPower(Powers power, int32 val) +{ + uint32 powerIndex = GetPowerIndexByClass(power, getClass()); + 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 ? true : false); + 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 ? true : false); + } // group update if (Player* player = ToPlayer()) @@ -13717,17 +12867,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 = GetPowerIndexByClass(power, getClass()); + if (powerIndex == MAX_POWERS) + return; + + int32 cur_power = GetPower(power); + SetInt32Value(UNIT_FIELD_MAXPOWER1 + powerIndex, val); // group update if (GetTypeId() == TYPEID_PLAYER) @@ -13749,19 +12899,32 @@ void Unit::SetMaxPower(Powers power, uint32 val) SetPower(power, val); } -uint32 Unit::GetCreatePowers(Powers power) const +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 0; + case POWER_HOLY_POWER: + return 0; + case POWER_HEALTH: + return 0; default: break; } @@ -14171,6 +13334,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; @@ -14200,6 +13364,7 @@ bool InitTriggerAuraData() 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; @@ -14458,6 +13623,13 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u takeCharges = true; break; } + case SPELL_AURA_PROC_ON_POWER_AMOUNT: + { + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "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: sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); if (HandleObsModEnergyAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) @@ -14469,6 +13641,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u takeCharges = true; break; case SPELL_AURA_MOD_MELEE_HASTE: + case SPELL_AURA_MOD_MELEE_HASTE_3: { sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); if (HandleHasteAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) @@ -14746,14 +13919,13 @@ void Unit::StopMoving() { ClearUnitState(UNIT_STATE_MOVING); - // not need send any packets if not in world - if (!IsInWorld()) + // not need send any packets if not in world or not moving + if (!IsInWorld() || movespline->Finalized()) return; - Movement::MoveSplineInit init(*this); - init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); - init.SetFacing(GetOrientation()); - init.Launch(); + // Update position using old spline + UpdateSplinePosition(); + Movement::MoveSplineInit(*this).Stop(); } void Unit::SendMovementFlagUpdate() @@ -15450,6 +14622,13 @@ 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::Kill(Unit* victim, bool durabilityLoss) { // Prevent killing unit twice (and giving reward from kill twice) @@ -15549,7 +14728,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) - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, victim); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, victim); // if talent known but not triggered (check priest class for speedup check) bool spiritOfRedemption = false; @@ -15605,11 +14784,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))) { - sLog->outDebug(LOG_FILTER_UNITS, "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))); + sLog->outDebug(LOG_FILTER_UNITS, "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) @@ -15705,9 +14886,9 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) if (victim->GetTypeId() == TYPEID_PLAYER) { if (GetTypeId() == TYPEID_UNIT) - victim->ToPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry()); + victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry()); else if (GetTypeId() == TYPEID_PLAYER && victim != this) - victim->ToPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1, ToPlayer()->GetTeam()); + victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1, ToPlayer()->GetTeam()); } // Hook for OnPVPKill Event @@ -15799,6 +14980,63 @@ void Unit::SetControlled(bool apply, UnitState state) } } +void Unit::SendMoveRoot(uint32 value) +{ + ObjectGuid guid = GetGUID(); + WorldPacket data(SMSG_MOVE_ROOT, 1 + 8 + 4); + data.WriteBit(guid[2]); + data.WriteBit(guid[7]); + data.WriteBit(guid[6]); + data.WriteBit(guid[0]); + data.WriteBit(guid[5]); + data.WriteBit(guid[4]); + data.WriteBit(guid[1]); + data.WriteBit(guid[3]); + + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[5]); + + data << uint32(value); + + + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[6]); + + SendMessageToSet(&data, true); +} + +void Unit::SendMoveUnroot(uint32 value) +{ + ObjectGuid guid = GetGUID(); + WorldPacket data(SMSG_MOVE_UNROOT, 1 + 8 + 4); + data.WriteBit(guid[0]); + data.WriteBit(guid[1]); + data.WriteBit(guid[3]); + data.WriteBit(guid[7]); + data.WriteBit(guid[5]); + data.WriteBit(guid[2]); + data.WriteBit(guid[4]); + data.WriteBit(guid[6]); + + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[1]); + + data << uint32(value); + + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[4]); + data.WriteByteSeq(guid[5]); + + SendMessageToSet(&data, true); +} + void Unit::SetStunned(bool apply) { if (apply) @@ -15818,10 +15056,7 @@ void Unit::SetStunned(bool apply) else SetStandState(UNIT_STAND_STATE_STAND); - WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8); - data.append(GetPackGUID()); - data << uint32(0); - SendMessageToSet(&data, true); + SendMoveRoot(0); CastStop(); } @@ -15837,11 +15072,7 @@ void Unit::SetStunned(bool apply) 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); - + SendMoveUnroot(0); RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT); } } @@ -15861,18 +15092,30 @@ void Unit::SetRooted(bool apply) AddUnitMovementFlag(MOVEMENTFLAG_ROOT); if (GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10); - data.append(GetPackGUID()); - data << m_rootTimes; - SendMessageToSet(&data, true); - } + SendMoveRoot(m_rootTimes); else { + ObjectGuid guid = GetGUID(); WorldPacket data(SMSG_SPLINE_MOVE_ROOT, 8); - data.append(GetPackGUID()); + data.WriteBit(guid[5]); + data.WriteBit(guid[4]); + data.WriteBit(guid[6]); + data.WriteBit(guid[1]); + data.WriteBit(guid[3]); + data.WriteBit(guid[7]); + data.WriteBit(guid[2]); + data.WriteBit(guid[0]); + data.FlushBits(); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[4]); SendMessageToSet(&data, true); - ToCreature()->StopMoving(); + StopMoving(); } } else @@ -15880,16 +15123,28 @@ void Unit::SetRooted(bool apply) 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); - } + SendMoveUnroot(++m_rootTimes); else { + ObjectGuid guid = GetGUID(); WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8); - data.append(GetPackGUID()); + data.WriteBit(guid[0]); + data.WriteBit(guid[1]); + data.WriteBit(guid[6]); + data.WriteBit(guid[5]); + data.WriteBit(guid[3]); + data.WriteBit(guid[2]); + data.WriteBit(guid[7]); + data.WriteBit(guid[4]); + data.FlushBits(); + data.WriteByteSeq(guid[6]); + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[1]); + data.WriteByteSeq(guid[5]); + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[0]); + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[4]); SendMessageToSet(&data, true); } @@ -16401,9 +15656,29 @@ void Unit::SetAuraStack(uint32 spellId, Unit* target, uint32 stack) void Unit::SendPlaySpellVisual(uint32 id) { - WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 8 + 4); - data << uint64(GetGUID()); + ObjectGuid guid = GetGUID(); + + WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 4 * 3 + 8); + data << uint32(0); data << uint32(id); // SpellVisualKit.dbc index + data << uint32(0); + 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, false); } @@ -16478,7 +15753,7 @@ void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool // 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); @@ -16486,14 +15761,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; @@ -16589,11 +15856,47 @@ 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 = NULL; if (GetTypeId() == TYPEID_PLAYER) - player = (Player*)this; + player = ToPlayer(); else if (Unit* charmer = GetCharmer()) { player = charmer->ToPlayer(); @@ -16602,23 +15905,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); } } @@ -16666,6 +15958,72 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) 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) { @@ -16700,30 +16058,32 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) } } // 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) @@ -16745,6 +16105,73 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) 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) { @@ -16779,23 +16206,26 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) } } // 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) @@ -16815,7 +16245,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) } 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 @@ -16916,6 +16346,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; } @@ -16929,16 +16374,7 @@ void Unit::JumpTo(float speedXY, float speedZ, bool forward) { float vcos = cos(angle+GetOrientation()); float vsin = 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); } } @@ -17188,45 +16624,79 @@ void Unit::BuildMovementPacket(ByteBuffer *data) const *data << GetPositionZMinusOffset(); *data << GetOrientation(); - // 0x00000200 - if (GetUnitMovementFlags() & MOVEMENTFLAG_ONTRANSPORT) + bool onTransport = m_movementInfo.t_guid != 0; + bool hasInterpolatedMovement = m_movementInfo.flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT; + bool time3 = false; + bool swimming = ((GetUnitMovementFlags() & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) + || (m_movementInfo.flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)); + bool interPolatedTurning = m_movementInfo.flags2 & MOVEMENTFLAG2_INTERPOLATED_TURNING; + bool jumping = GetUnitMovementFlags() & MOVEMENTFLAG_FALLING; + bool splineElevation = GetUnitMovementFlags() & MOVEMENTFLAG_SPLINE_ELEVATION; + bool splineData = false; + + data->WriteBits(GetUnitMovementFlags(), 30); + data->WriteBits(m_movementInfo.flags2, 12); + data->WriteBit(onTransport); + if (onTransport) + { + data->WriteBit(hasInterpolatedMovement); + data->WriteBit(time3); + } + + data->WriteBit(swimming); + data->WriteBit(interPolatedTurning); + if (interPolatedTurning) + data->WriteBit(jumping); + + data->WriteBit(splineElevation); + data->WriteBit(splineData); + + data->FlushBits(); // reset bit stream + + *data << uint64(GetGUID()); + *data << uint32(getMSTime()); + *data << float(GetPositionX()); + *data << float(GetPositionY()); + *data << float(GetPositionZ()); + *data << float(GetOrientation()); + + if (onTransport) { if (m_vehicle) - data->append(m_vehicle->GetBase()->GetPackGUID()); + *data << uint64(m_vehicle->GetBase()->GetGUID()); else if (GetTransport()) - data->append(GetTransport()->GetPackGUID()); - else - *data << (uint8)0; + *data << uint64(GetTransport()->GetGUID()); + else // probably should never happen + *data << (uint64)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.t_time2); + *data << uint32(GetTransTime()); + if (hasInterpolatedMovement) + *data << int32(0); // Transport Time 2 + if (time3) + *data << int32(0); // Transport Time 3 } - // 0x02200000 - if ((GetUnitMovementFlags() & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) - || (m_movementInfo.flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)) + if (swimming) *data << (float)m_movementInfo.pitch; - *data << (uint32)m_movementInfo.fallTime; - - // 0x00001000 - if (GetUnitMovementFlags() & MOVEMENTFLAG_FALLING) + if (interPolatedTurning) { + *data << (uint32)m_movementInfo.fallTime; *data << (float)m_movementInfo.j_zspeed; - *data << (float)m_movementInfo.j_sinAngle; - *data << (float)m_movementInfo.j_cosAngle; - *data << (float)m_movementInfo.j_xyspeed; + if (jumping) + { + *data << (float)m_movementInfo.j_sinAngle; + *data << (float)m_movementInfo.j_cosAngle; + *data << (float)m_movementInfo.j_xyspeed; + } } - // 0x04000000 - if (GetUnitMovementFlags() & MOVEMENTFLAG_SPLINE_ELEVATION) + if (splineElevation) *data << (float)m_movementInfo.splineElevation; } @@ -17306,7 +16776,7 @@ void Unit::SendThreatListUpdate() { uint32 count = getThreatManager().getThreatList().size(); - //sLog->outDebug(LOG_FILTER_UNITS, "WORLD: Send SMSG_THREAT_UPDATE Message"); + sLog->outDebug(LOG_FILTER_UNITS, "WORLD: Send SMSG_THREAT_UPDATE Message"); WorldPacket data(SMSG_THREAT_UPDATE, 8 + count * 8); data.append(GetPackGUID()); data << uint32(count); @@ -17358,27 +16828,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 AddPctN(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; @@ -17695,3 +17160,8 @@ void Unit::SendMovementCanFlyChange() BuildMovementPacket(&data); SendMessageToSet(&data, false); } + +bool Unit::IsSplineEnabled() const +{ + return movespline->Initialized(); +} diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 46dbf4829a6..9dcb981c95a 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -35,6 +35,7 @@ #include "SpellInfo.h" #include "Path.h" #include "WorldPacket.h" +#include "WorldSession.h" #include "Timer.h" #include <list> @@ -201,7 +202,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, @@ -417,9 +418,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, @@ -439,7 +444,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 @@ -636,7 +641,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% @@ -661,6 +666,9 @@ 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_REFORGER = 0x08000000, // reforging + UNIT_NPC_FLAG_TRANSMOGRIFIER = 0x10000000, // transmogrification + UNIT_NPC_FLAG_VAULTKEEPER = 0x20000000, // void storage }; enum MovementFlags @@ -675,28 +683,26 @@ 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 // TODO: Check if PITCH_UP and PITCH_DOWN really belong here.. MOVEMENTFLAG_MASK_MOVING = @@ -710,6 +716,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, @@ -719,20 +731,16 @@ 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_UNK7 = 0x00000020, + MOVEMENTFLAG2_UNK8 = 0x00000040, + MOVEMENTFLAG2_UNK9 = 0x00000080, + MOVEMENTFLAG2_UNK10 = 0x00000100, + MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00000200, + MOVEMENTFLAG2_INTERPOLATED_TURNING = 0x00000400, + MOVEMENTFLAG2_INTERPOLATED_PITCHING = 0x00000800, }; enum UnitTypeMask @@ -1335,14 +1343,17 @@ 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; + 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); + uint32 GetPowerIndexByClass(uint32 powerId, uint32 classId) const; + uint32 GetAttackTime(WeaponAttackType att) const { float f_BaseAttackTime = GetFloatValue(UNIT_FIELD_BASEATTACKTIME+att) / m_modAttackSpeedPct[att]; @@ -1405,6 +1416,9 @@ 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); uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } void DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb); @@ -1447,7 +1461,7 @@ class Unit : public WorldObject void ApplyResilience(const Unit* victim, float * crit, int32 * damage, bool isCrit, CombatRating type) const; - float MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const; + float MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, uint32 spellId) const; SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spell); SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spell); SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spell, bool canReflect = false); @@ -1469,21 +1483,8 @@ class Unit : public WorldObject return true; } - virtual uint32 GetShieldBlockValue() const =0; - uint32 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); - } + virtual uint32 GetBlockPercent() { return 30; } - return value; - } uint32 GetUnitMeleeSkill(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } uint32 GetDefenseSkillValue(Unit const* target = NULL) const; uint32 GetWeaponSkillValue(WeaponAttackType attType, Unit const* target = NULL) const; @@ -1555,7 +1556,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, uint32 Damage, Powers powertype); - void EnergizeBySpell(Unit* victim, uint32 SpellID, uint32 Damage, Powers powertype); + void EnergizeBySpell(Unit* victim, uint32 SpellID, int32 Damage, Powers powertype); uint32 SpellNonMeleeDamageLog(Unit* victim, uint32 spellID, uint32 damage); void CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo, CustomSpellValues const* value, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, uint64 originalCaster = 0); @@ -1592,6 +1593,7 @@ 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); @@ -1851,7 +1853,7 @@ 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; + 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]; } @@ -1888,7 +1890,7 @@ class Unit : public WorldObject inline bool IsInFeralForm() const { ShapeshiftForm form = GetShapeshiftForm(); - return form == FORM_CAT || form == FORM_BEAR || form == FORM_DIREBEAR; + return form == FORM_CAT || form == FORM_BEAR; } inline bool IsInDisallowedMountForm() const @@ -2083,6 +2085,7 @@ class Unit : public WorldObject 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; } + bool IsSplineEnabled() const; float GetPositionZMinusOffset() const { @@ -2181,7 +2184,7 @@ class Unit : public WorldObject bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY); } void SetCanFly(bool apply); - 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); } @@ -2304,6 +2307,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 HandleHasteAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleSpellCritChanceAuraProc(Unit* victim, uint32 damage, AuraEffect* triggredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); @@ -2316,16 +2320,21 @@ class Unit : public WorldObject bool HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura); void UpdateSplineMovement(uint32 t_diff); + void UpdateSplinePosition(); // player or player's pet float GetCombatRatingReduction(CombatRating cr) const; uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const; + protected: + void SendMoveRoot(uint32 value); + void SendMoveUnroot(uint32 value); void SetFeared(bool apply); void SetConfused(bool apply); void SetStunned(bool apply); void SetRooted(bool apply); + private: uint32 m_rootTimes; uint32 m_state; // Even derived shouldn't modify diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 710821f2f24..50370ba48de 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -342,12 +342,11 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING)) unit->AddUnitState(UNIT_STATE_ONVEHICLE); - unit->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); VehicleSeatEntry const* veSeat = seat->second.SeatInfo; unit->m_movementInfo.t_pos.m_positionX = veSeat->m_attachmentOffsetX; unit->m_movementInfo.t_pos.m_positionY = veSeat->m_attachmentOffsetY; unit->m_movementInfo.t_pos.m_positionZ = veSeat->m_attachmentOffsetZ; - unit->m_movementInfo.t_pos.m_orientation = 0; + unit->m_movementInfo.t_pos.SetOrientation(0); unit->m_movementInfo.t_time = 0; // 1 for player unit->m_movementInfo.t_seat = seat->first; unit->m_movementInfo.t_guid = _me->GetGUID(); @@ -362,9 +361,9 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) if (_me->IsInWorld()) { - unit->SendClearTarget(); // SMSG_BREAK_TARGET + unit->SendClearTarget(); // SMSG_BREAK_TARGET unit->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) - // also adds MOVEMENTFLAG_ROOT + // also adds MOVEMENTFLAG_ROOT Movement::MoveSplineInit init(*unit); init.DisableTransportPathTransformations(); init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); @@ -419,7 +418,6 @@ void Vehicle::RemovePassenger(Unit* unit) if (_me->IsInWorld()) { - unit->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); unit->m_movementInfo.t_pos.Relocate(0, 0, 0, 0); unit->m_movementInfo.t_time = 0; unit->m_movementInfo.t_seat = 0; @@ -450,7 +448,7 @@ void Vehicle::RelocatePassengers(float x, float y, float z, float ang) float px = x + passenger->m_movementInfo.t_pos.m_positionX; float py = y + passenger->m_movementInfo.t_pos.m_positionY; float pz = z + passenger->m_movementInfo.t_pos.m_positionZ; - float po = ang + passenger->m_movementInfo.t_pos.m_orientation; + float po = ang + passenger->m_movementInfo.t_pos.GetOrientation(); passenger->UpdatePosition(px, py, pz, po); } diff --git a/src/server/game/Entities/Vehicle/VehicleDefines.h b/src/server/game/Entities/Vehicle/VehicleDefines.h index df34a61d444..fe7840c9878 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 bead65bbfdd..be9bd7ecbf3 100755 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -210,7 +210,7 @@ void GameEventMgr::LoadFromDB() if (!result) { mGameEvent.clear(); - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 game events. DB table `game_event` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 game events. DB table `game_event` is empty."); return; } @@ -791,13 +791,11 @@ 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) - { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 vendor additions in game events. DB table `game_event_npc_vendor` is empty."); - } else { uint32 count = 0; @@ -820,6 +818,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]; @@ -838,7 +837,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); @@ -1041,14 +1040,14 @@ uint32 GameEventMgr::Update() // return the next e // changed, save to DB the gameevent state, will be updated in next update cycle SaveWorldEventStateToDB(itr); - //sLog->outDebug("GameEvent %u is active", itr->first); + //sLog->outDebug(LOG_FILTER_GENERAL, "GameEvent %u is active", itr->first); // queue for activation if (!IsActiveEvent(itr)) activate.insert(itr); } else { - //sLog->outDebug("GameEvent %u is not active", itr->first); + //sLog->outDebug(LOG_FILTER_GENERAL, "GameEvent %u is not active", itr->first); if (IsActiveEvent(itr)) deactivate.insert(itr); else @@ -1176,9 +1175,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); } } @@ -1206,7 +1205,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id) if (!map->Instanceable() && map->IsGridLoaded(data->posX, data->posY)) { Creature* creature = new Creature; - //sLog->outDebug("Spawning creature %u", *itr); + //sLog->outDebug(LOG_FILTER_GENERAL, "Spawning creature %u", *itr); if (!creature->LoadCreatureFromDB(*itr, map)) delete creature; } @@ -1233,7 +1232,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id) if (!map->Instanceable() && map->IsGridLoaded(data->posX, data->posY)) { GameObject* pGameobject = new GameObject; - //sLog->outDebug("Spawning gameobject %u", *itr); + //sLog->outDebug(LOG_FILTER_GENERAL, "Spawning gameobject %u", *itr); //TODO: find out when it is add to map if (!pGameobject->LoadGameObjectFromDB(*itr, map, false)) delete pGameobject; diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h index d9b5890bfe5..ce1d10e327a 100755 --- a/src/server/game/Events/GameEventMgr.h +++ b/src/server/game/Events/GameEventMgr.h @@ -85,6 +85,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/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 08a76008fde..b87cb2d7fbf 100755..100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -45,6 +45,8 @@ #include "ScriptMgr.h" #include "SpellScript.h" #include "PoolMgr.h" +#include "DB2Structure.h" +#include "DB2Stores.h" ScriptMapMap sQuestEndScripts; ScriptMapMap sQuestStartScripts; @@ -177,7 +179,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,7 +231,7 @@ bool SpellClickInfo::IsFitToRequirements(Unit const* clicker, Unit const* clicke } ObjectMgr::ObjectMgr(): _auctionId(1), _equipmentSetGuid(1), - _itemTextId(1), _mailId(1), _hiPetNumber(1), _hiCharGuid(1), + _itemTextId(1), _mailId(1), _hiPetNumber(1), _voidItemId(1), _hiCharGuid(1), _hiCreatureGuid(1), _hiPetGuid(1), _hiVehicleGuid(1), _hiItemGuid(1), _hiGoGuid(1), _hiDoGuid(1), _hiCorpseGuid(1), _hiMoTransGuid(1) {} @@ -240,10 +244,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_) - delete[] _playerClassInfo[class_].levelInfo; - for (int race = 0; race < MAX_RACES; ++race) for (int class_ = 0; class_ < MAX_CLASSES; ++class_) delete[] _playerInfo[race][class_].levelInfo; @@ -367,19 +367,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_A, faction_H, npcflag, speed_walk, speed_run, " - // 22 23 24 25 26 27 28 29 30 31 32 - "scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, " - // 33 34 35 36 37 38 39 40 41 42 + // 9 10 11 12 13 14 15 16 17 18 19 20 21 + "modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, exp_unk, faction_A, faction_H, npcflag, speed_walk, " + // 22 23 24 25 26 27 28 29 30 31 32 33 + "speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, " + // 34 35 36 37 38 39 40 41 42 43 "dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, " - // 43 44 45 46 47 48 49 50 51 52 53 - "type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, " - // 54 55 56 57 58 59 60 61 62 63 64 65 66 - "spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, " - // 67 68 69 70 71 72 73 74 75 76 77 - "InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, " - // 78 79 80 81 82 83 + // 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 87 " questItem6, movementId, RegenHealth, equipment_id, mechanic_immune_mask, flags_extra, ScriptName " "FROM creature_template;"); @@ -419,65 +419,68 @@ void ObjectMgr::LoadCreatureTemplates() creatureTemplate.minlevel = fields[14].GetUInt8(); creatureTemplate.maxlevel = fields[15].GetUInt8(); creatureTemplate.expansion = uint32(fields[16].GetInt16()); - creatureTemplate.faction_A = uint32(fields[17].GetUInt16()); - creatureTemplate.faction_H = uint32(fields[18].GetUInt16()); - creatureTemplate.npcflag = fields[19].GetUInt32(); - creatureTemplate.speed_walk = fields[20].GetFloat(); - creatureTemplate.speed_run = fields[21].GetFloat(); - creatureTemplate.scale = fields[22].GetFloat(); - creatureTemplate.rank = uint32(fields[23].GetUInt8()); - creatureTemplate.mindmg = fields[24].GetFloat(); - creatureTemplate.maxdmg = fields[25].GetFloat(); - creatureTemplate.dmgschool = uint32(fields[26].GetInt8()); - creatureTemplate.attackpower = fields[27].GetUInt32(); - creatureTemplate.dmg_multiplier = fields[28].GetFloat(); - creatureTemplate.baseattacktime = fields[29].GetUInt32(); - creatureTemplate.rangeattacktime = fields[30].GetUInt32(); - creatureTemplate.unit_class = uint32(fields[31].GetUInt8()); - creatureTemplate.unit_flags = 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.expansionUnknown = uint32(fields[17].GetUInt16()); + creatureTemplate.faction_A = uint32(fields[18].GetUInt16()); + creatureTemplate.faction_H = 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.dynamicflags = fields[34].GetUInt32(); + creatureTemplate.family = uint32(fields[35].GetUInt8()); + creatureTemplate.trainer_type = uint32(fields[36].GetUInt8()); + creatureTemplate.trainer_spell = fields[37].GetUInt32(); + 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.equipmentId = fields[81].GetUInt32(); - creatureTemplate.MechanicImmuneMask = fields[82].GetUInt32(); - creatureTemplate.flags_extra = fields[83].GetUInt32(); - creatureTemplate.ScriptID = GetScriptId(fields[84].GetCString()); + creatureTemplate.movementId = fields[82].GetUInt32(); + creatureTemplate.RegenHealth = fields[83].GetBool(); + creatureTemplate.equipmentId = fields[84].GetUInt32(); + creatureTemplate.MechanicImmuneMask = fields[85].GetUInt32(); + creatureTemplate.flags_extra = fields[86].GetUInt32(); + creatureTemplate.ScriptID = GetScriptId(fields[87].GetCString()); ++count; } @@ -850,12 +853,18 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) const_cast<CreatureTemplate*>(cInfo)->scale = 1.0f; } - if (cInfo->expansion > (MAX_CREATURE_BASE_HP - 1)) + if (cInfo->expansion > MAX_CREATURE_BASE_HP) { - sLog->outError(LOG_FILTER_SQL, "Table `creature_template` lists creature (Entry: %u) with expansion %u. Ignored and set to 0.", cInfo->Entry, cInfo->expansion); + sLog->outError(LOG_FILTER_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_CREATURE_BASE_HP) + { + sLog->outError(LOG_FILTER_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)) { sLog->outError(LOG_FILTER_SQL, "Table `creature_template` lists creature (Entry: %u) with disallowed `flags_extra` %u, removing incorrect flag.", cInfo->Entry, badFlags); @@ -1163,7 +1172,7 @@ void ObjectMgr::LoadLinkedRespawn() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 linked respawns. DB table `linked_respawn` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 linked respawns. DB table `linked_respawn` is empty."); return; } @@ -1394,7 +1403,7 @@ void ObjectMgr::LoadCreatures() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 creatures. DB table `creature` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 creatures. DB table `creature` is empty."); return; } @@ -1454,7 +1463,7 @@ void ObjectMgr::LoadCreatures() } if (data.spawnMask & ~spawnMasks[data.mapid]) - sLog->outError(LOG_FILTER_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); + sLog->outError(LOG_FILTER_SQL, "Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u) spawnMasks[data.mapid]: %u.", guid, data.spawnMask, data.mapid, spawnMasks[data.mapid]); bool ok = true; for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff) @@ -1703,7 +1712,7 @@ void ObjectMgr::LoadGameobjects() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 gameobjects. DB table `gameobject` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 gameobjects. DB table `gameobject` is empty."); return; } @@ -1996,582 +2005,504 @@ void ObjectMgr::LoadItemLocales() sLog->outInfo(LOG_FILTER_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, unk0, 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) - { - sLog->outInfo(LOG_FILTER_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.Unk0 = fields[3].GetInt32(); - itemTemplate.Name1 = fields[4].GetString(); - itemTemplate.DisplayInfoID = fields[5].GetUInt32(); - itemTemplate.Quality = uint32(fields[6].GetUInt8()); - itemTemplate.Flags = uint32(fields[7].GetInt64()); - 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) - { - sLog->outError(LOG_FILTER_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.Unk0 != dbcitem->Unk0) - { - sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) does not have a correct Unk0 (%i), must be %i .", entry, itemTemplate.Unk0, dbcitem->Unk0); - if (enforceDBCAttributes) - itemTemplate.Unk0 = dbcitem->Unk0; - } - if (itemTemplate.Material != dbcitem->Material) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) { - sLog->outError(LOG_FILTER_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 - sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) does not exist in item.dbc! (not correct id?).", entry); - - if (itemTemplate.Class >= MAX_ITEM_CLASS) - { - sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) has wrong Class value (%u)", entry, itemTemplate.Class); - itemTemplate.Class = ITEM_CLASS_MISC; - } - - if (itemTemplate.SubClass >= MaxItemSubclassValues[itemTemplate.Class]) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) - sLog->outError(LOG_FILTER_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) - sLog->outError(LOG_FILTER_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) - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) has wrong BuyCount value (%u), set to default(1).", entry, itemTemplate.BuyCount); - itemTemplate.BuyCount = 1; - } - - if (itemTemplate.InventoryType >= MAX_INVTYPE) - { - sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) has wrong InventoryType value (%u)", entry, itemTemplate.InventoryType); - itemTemplate.InventoryType = INVTYPE_NON_EQUIP; - } - - if (itemTemplate.RequiredSkill >= MAX_SKILL_TYPE) - { - sLog->outError(LOG_FILTER_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)) - sLog->outError(LOG_FILTER_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)) - sLog->outError(LOG_FILTER_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)) - { - sLog->outError(LOG_FILTER_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) - sLog->outError(LOG_FILTER_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)) - { - sLog->outError(LOG_FILTER_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* armorToral = sItemArmorTotalStore.LookupEntry(itemlevel); + if (!armorQuality || !armorToral) + return 0; - if (itemTemplate.RequiredReputationRank == MIN_REPUTATION_RANK) - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) + return 0; - if (itemTemplate.ContainerSlots > MAX_BAG_SIZE) - { - sLog->outError(LOG_FILTER_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] * armorToral->Value[quality] * location->Value[itemSubclass - 1] + 0.5f); + } - if (itemTemplate.StatsCount > MAX_ITEM_PROTO_STATS) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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: - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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)) - { - sLog->outError(LOG_FILTER_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)) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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)) - { - sLog->outError(LOG_FILTER_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)) - { - sLog->outError(LOG_FILTER_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) - sLog->outError(LOG_FILTER_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)) - sLog->outError(LOG_FILTER_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)) - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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) { - sLog->outError(LOG_FILTER_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))) - { - sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) has wrong RandomSuffix (%u)", entry, itemTemplate.RandomSuffix); - itemTemplate.RandomSuffix = 0; - } - - if (itemTemplate.ItemSet && !sItemSetStore.LookupEntry(itemTemplate.ItemSet)) - { - sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) have wrong ItemSet (%u)", entry, itemTemplate.ItemSet); - itemTemplate.ItemSet = 0; - } - - if (itemTemplate.Area && !GetAreaEntryByAreaID(itemTemplate.Area)) - sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) has wrong Area (%u)", entry, itemTemplate.Area); - - if (itemTemplate.Map && !sMapStore.LookupEntry(itemTemplate.Map)) - sLog->outError(LOG_FILTER_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) - continue; - - ItemBagFamilyEntry const* bf = sItemBagFamilyStore.LookupEntry(j+1); - if (!bf) - { - sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) has bag family bit set not listed in ItemBagFamily.dbc, remove bit", entry); - itemTemplate.BagFamily &= ~mask; + if (itemTemplate.RequiredLevel <= 60 || (itemTemplate.RequiredSkill && itemTemplate.RequiredSkillRank <= 300)) continue; - } - - if (BAG_FAMILY_MASK_CURRENCY_TOKENS & mask) - { - CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemTemplate.ItemId); - if (!ctEntry) - { - sLog->outError(LOG_FILTER_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)) - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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)) - sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) has wrong GemProperties (%u)", entry, itemTemplate.GemProperties); - - if (itemTemplate.FoodType >= MAX_PET_DIET) - { - sLog->outError(LOG_FILTER_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)) - { - sLog->outError(LOG_FILTER_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)) - { - sLog->outError(LOG_FILTER_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.Unk0 = db2Data->Unk0; + itemTemplate.Name1 = sparse->Name; + 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; + 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, Unk0, 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 { - sLog->outError(LOG_FILTER_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.Unk0 = fields[3].GetInt32(); + itemTemplate.Name1 = fields[4].GetString(); + itemTemplate.DisplayInfoID = fields[5].GetUInt32(); + itemTemplate.Quality = uint32(fields[6].GetUInt8()); + itemTemplate.Flags = uint32(fields[7].GetInt64()); + 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; @@ -2596,124 +2527,77 @@ void ObjectMgr::LoadItemTemplates() for (std::set<uint32>::const_iterator itr = notFoundOutfit.begin(); itr != notFoundOutfit.end(); ++itr) sLog->outError(LOG_FILTER_SQL, "Item (Entry: %u) does not exist in `item_template` but is referenced in `CharStartOutfit.dbc`", *itr); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u item templates 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; + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u item templates from Item-sparse.db2 and %u from database in %u ms", sparseCount, dbCount, GetMSTimeDiffToNow(oldMSTime)); } -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)) + { + sLog->outError(LOG_FILTER_SQL, "Item %u specified in `item_template_addon` does not exist, skipped.", itemId); + continue; + } - sLog->outInfo(LOG_FILTER_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) + { + sLog->outError(LOG_FILTER_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()); + } + sLog->outInfo(LOG_FILTER_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) - { - sLog->outInfo(LOG_FILTER_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()) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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)) { - sLog->outError(LOG_FILTER_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; + sLog->outError(LOG_FILTER_SQL, "Item %u specified in `item_script_names` does not exist, skipped.", itemId); + continue; } - else - sLog->outError(LOG_FILTER_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()); } - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u item set names in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + sLog->outInfo(LOG_FILTER_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() @@ -2729,7 +2613,7 @@ void ObjectMgr::LoadVehicleTemplateAccessories() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 vehicle template accessories. DB table `vehicle_template_accessory` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 vehicle template accessories. DB table `vehicle_template_accessory` is empty."); return; } @@ -2824,7 +2708,7 @@ void ObjectMgr::LoadPetLevelInfo() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 level pet stats definitions. DB table `pet_levelstats` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 level pet stats definitions. DB table `pet_levelstats` is empty."); return; } @@ -2971,7 +2855,7 @@ void ObjectMgr::LoadPlayerInfo() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 player create definitions. DB table `playercreateinfo` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 player create definitions. DB table `playercreateinfo` is empty."); exit(1); } else @@ -3129,7 +3013,7 @@ void ObjectMgr::LoadPlayerInfo() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 player create spells. DB table `%s` is empty.", sWorld->getBoolConfig(CONFIG_START_ALL_SPELLS) ? "playercreateinfo_spell_custom" : "playercreateinfo_spell"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 player create spells. DB table `%s` is empty.", sWorld->getBoolConfig(CONFIG_START_ALL_SPELLS) ? "playercreateinfo_spell_custom" : "playercreateinfo_spell"); } else @@ -3185,7 +3069,7 @@ void ObjectMgr::LoadPlayerInfo() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 player create actions. DB table `playercreateinfo_action` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 player create actions. DB table `playercreateinfo_action` is empty."); } else @@ -3221,86 +3105,6 @@ void ObjectMgr::LoadPlayerInfo() } } - // Loading levels data (class only dependent) - sLog->outInfo(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 level health/mana definitions. DB table `game_event_condition` is empty."); - - exit(1); - } - - uint32 count = 0; - - do - { - Field* fields = result->Fetch(); - - uint32 current_class = fields[0].GetUInt8(); - if (current_class >= MAX_CLASSES) - { - sLog->outError(LOG_FILTER_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)) - { - sLog->outInfo(LOG_FILTER_GENERAL, "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* pClassInfo = &_playerClassInfo[current_class]; - - if (!pClassInfo->levelInfo) - pClassInfo->levelInfo = new PlayerClassLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)]; - - PlayerClassLevelInfo* pClassLevelInfo = &pClassInfo->levelInfo[current_level-1]; - - pClassLevelInfo->basehealth = fields[2].GetUInt16(); - pClassLevelInfo->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) - { - sLog->outError(LOG_FILTER_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) - { - sLog->outError(LOG_FILTER_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]; - } - } - } - - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u level health/mana definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); - } - // Loading levels data (class/race dependent) sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Player Create Level Stats Data..."); { @@ -3311,7 +3115,7 @@ void ObjectMgr::LoadPlayerInfo() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 level stats definitions. DB table `player_levelstats` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 level stats definitions. DB table `player_levelstats` is empty."); exit(1); } @@ -3428,7 +3232,7 @@ void ObjectMgr::LoadPlayerInfo() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 xp for level definitions. DB table `player_xp_for_level` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 xp for level definitions. DB table `player_xp_for_level` is empty."); exit(1); } @@ -3473,17 +3277,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) + { + sLog->outError(LOG_FILTER_GENERAL, "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 @@ -3595,38 +3407,42 @@ 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 - "RequiredSpellCast1, RequiredSpellCast2, RequiredSpellCast3, RequiredSpellCast4, Unknown0, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, " - // 126 127 128 129 130 131 132 133 134 135 + // 123 124 125 126 127 128 129 130 131 + "RequiredSpell, RequiredSpellCast1, RequiredSpellCast2, RequiredSpellCast3, RequiredSpellCast4, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, " + // 132 133 134 135 136 137 138 139 + "RewardCurrencyId1, RewardCurrencyId2, RewardCurrencyId3, RewardCurrencyId4, RewardCurrencyCount1, RewardCurrencyCount2, RewardCurrencyCount3, RewardCurrencyCount4, " + // 140 141 142 143 144 145 146 147 + "RequiredCurrencyId1, RequiredCurrencyId2, RequiredCurrencyId3, RequiredCurrencyId4, RequiredCurrencyCount1, RequiredCurrencyCount2, RequiredCurrencyCount3, RequiredCurrencyCount4, " + // 148 149 150 151 152 153 + "QuestGiverTextWindow, QuestGiverTargetName, QuestTurnTextWindow, QuestTurnTargetName, SoundAccept, SoundTurnIn, " + // 154 155 156 157 158 159 160 161 162 163 "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, EmoteOnIncomplete, EmoteOnComplete, " - // 136 137 138 139 140 141 142 143 + // 164 165 166 167 168 169 170 171 "OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4, " - // 144 145 146 + // 172 173 174 "StartScript, CompleteScript, WDBVerified" " FROM quest_template"); if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 quests definitions. DB table `quest_template` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 quests definitions. DB table `quest_template` is empty."); return; } @@ -3658,11 +3474,11 @@ void ObjectMgr::LoadQuests() if (qinfo->GetQuestMethod() >= 3) sLog->outError(LOG_FILTER_SQL, "Quest %u has `Method` = %u, expected values are 0, 1 or 2.", qinfo->GetQuestId(), qinfo->GetQuestMethod()); - if (qinfo->Flags & ~QUEST_TRINITY_FLAGS_DB_ALLOWED) + if (qinfo->SpecialFlags & ~QUEST_SPECIAL_FLAGS_DB_ALLOWED) { sLog->outError(LOG_FILTER_SQL, "Quest %u has `SpecialFlags` = %u > max allowed value. Correct `SpecialFlags` to value <= %u", - qinfo->GetQuestId(), qinfo->Flags >> 20, QUEST_TRINITY_FLAGS_DB_ALLOWED >> 20); - qinfo->Flags &= QUEST_TRINITY_FLAGS_DB_ALLOWED; + qinfo->GetQuestId(), qinfo->SpecialFlags, QUEST_SPECIAL_FLAGS_DB_ALLOWED); + qinfo->SpecialFlags &= QUEST_SPECIAL_FLAGS_DB_ALLOWED; } if (qinfo->Flags & QUEST_FLAGS_DAILY && qinfo->Flags & QUEST_FLAGS_WEEKLY) @@ -3673,19 +3489,19 @@ void ObjectMgr::LoadQuests() if (qinfo->Flags & QUEST_FLAGS_DAILY) { - if (!(qinfo->Flags & QUEST_TRINITY_FLAGS_REPEATABLE)) + if (!(qinfo->SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE)) { sLog->outError(LOG_FILTER_SQL, "Daily Quest %u not marked as repeatable in `SpecialFlags`, added.", qinfo->GetQuestId()); - qinfo->Flags |= QUEST_TRINITY_FLAGS_REPEATABLE; + qinfo->SpecialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE; } } if (qinfo->Flags & QUEST_FLAGS_WEEKLY) { - if (!(qinfo->Flags & QUEST_TRINITY_FLAGS_REPEATABLE)) + if (!(qinfo->SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE)) { sLog->outError(LOG_FILTER_SQL, "Weekly Quest %u not marked as repeatable in `SpecialFlags`, added.", qinfo->GetQuestId()); - qinfo->Flags |= QUEST_TRINITY_FLAGS_REPEATABLE; + qinfo->SpecialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE; } } @@ -3703,6 +3519,12 @@ void ObjectMgr::LoadQuests() } } + if (qinfo->MinLevel == uint32(-1) || qinfo->MinLevel > DEFAULT_MAX_LEVEL) + { + sLog->outError(LOG_FILTER_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) { @@ -3903,7 +3725,7 @@ void ObjectMgr::LoadQuests() // no changes, quest can't be done for this requirement } - qinfo->SetFlag(QUEST_TRINITY_FLAGS_DELIVER); + qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER); if (!sObjectMgr->GetItemTemplate(id)) { @@ -3912,7 +3734,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) { sLog->outError(LOG_FILTER_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]); @@ -3971,12 +3793,12 @@ void ObjectMgr::LoadQuests() if (found) { - if (!qinfo->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) + if (!qinfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT)) { - sLog->outError(LOG_FILTER_SQL, "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT for quest %u and RequiredNpcOrGo%d = 0, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags or RequiredNpcOrGo%d must be fixed, quest modified to enable objective.", spellInfo->Id, qinfo->Id, j+1, j+1); + sLog->outError(LOG_FILTER_SQL, "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT for quest %u and RequiredNpcOrGo%d = 0, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT. Quest flags or RequiredNpcOrGo%d must be fixed, quest modified to enable objective.", spellInfo->Id, qinfo->Id, j+1, j+1); // this will prevent quest completing without objective - const_cast<Quest*>(qinfo)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); + const_cast<Quest*>(qinfo)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT); } } else @@ -4010,7 +3832,7 @@ void ObjectMgr::LoadQuests() { // In fact SpeakTo and Kill are quite same: either you can speak to mob:SpeakTo or you can't:Kill/Cast - qinfo->SetFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO); + qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO); if (!qinfo->RequiredNpcOrGoCount[j]) { @@ -4190,26 +4012,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) + { + sLog->outError(LOG_FILTER_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])) + { + sLog->outError(LOG_FILTER_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) + { + sLog->outError(LOG_FILTER_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) + { + sLog->outError(LOG_FILTER_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])) + { + sLog->outError(LOG_FILTER_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) + { + sLog->outError(LOG_FILTER_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)) + { + sLog->outError(LOG_FILTER_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)) + { + sLog->outError(LOG_FILTER_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) + { + sLog->outError(LOG_FILTER_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)) + { + sLog->outError(LOG_FILTER_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)) + { + sLog->outError(LOG_FILTER_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)) + { + sLog->outError(LOG_FILTER_SQL, "Quest %u has `RewardSkillId` = %u but this skill does not exist", + qinfo->GetQuestId(), qinfo->RewardSkillId); + } + if (!qinfo->RewardSkillPoints) + { + sLog->outError(LOG_FILTER_SQL, "Quest %u has `RewardSkillId` = %u but `RewardSkillPoints` is 0", + qinfo->GetQuestId(), qinfo->RewardSkillId); + } + } + + if (qinfo->RewardSkillPoints) + { + if (qinfo->RewardSkillPoints > sWorld->GetConfigMaxSkillValue()) + { + sLog->outError(LOG_FILTER_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) + { + sLog->outError(LOG_FILTER_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()) - { sLog->outError(LOG_FILTER_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()) - { sLog->outError(LOG_FILTER_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()); @@ -4220,12 +4165,12 @@ void ObjectMgr::LoadQuests() if (qinfo->ExclusiveGroup) mExclusiveQuestGroups.insert(std::pair<int32, uint32>(qinfo->ExclusiveGroup, qinfo->GetQuestId())); if (qinfo->LimitTime) - qinfo->SetFlag(QUEST_TRINITY_FLAGS_TIMED); + qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED); if (qinfo->RequiredPlayerKills) - qinfo->SetFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL); + qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL); } - // check QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE + // check QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i); @@ -4245,12 +4190,12 @@ void ObjectMgr::LoadQuests() if (!quest) continue; - if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) + if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT)) { - sLog->outError(LOG_FILTER_SQL, "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE for quest %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags must be fixed, quest modified to enable objective.", spellInfo->Id, quest_id); + sLog->outError(LOG_FILTER_SQL, "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE for quest %u, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT. Quest flags must be fixed, quest modified to enable objective.", spellInfo->Id, quest_id); // this will prevent quest completing without objective - const_cast<Quest*>(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); + const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT); } } } @@ -4265,14 +4210,14 @@ void ObjectMgr::LoadQuestLocales() _questLocaleStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT entry, " - "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) @@ -4290,16 +4235,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()); @@ -4421,13 +4371,13 @@ void ObjectMgr::LoadScripts(ScriptsType type) continue; } - if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) + if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT)) { - sLog->outError(LOG_FILTER_SQL, "Table `%s` has quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT in quest flags. Script command or quest flags wrong. Quest modified to require objective.", + sLog->outError(LOG_FILTER_SQL, "Table `%s` has quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT in quest flags. Script command or quest flags wrong. Quest modified to require objective.", tableName.c_str(), tmp.QuestExplored.QuestID, tmp.id); // this will prevent quest completing without objective - const_cast<Quest*>(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); + const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT); // continue; - quest objective requirement set and command can be allowed } @@ -5006,7 +4956,7 @@ void ObjectMgr::LoadInstanceEncounters() QueryResult result = WorldDatabase.Query("SELECT entry, creditType, creditEntry, lastEncounterDungeon FROM instance_encounters"); if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 instance encounters, table is empty!"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 instance encounters, table is empty!"); return; } @@ -5029,7 +4979,7 @@ void ObjectMgr::LoadInstanceEncounters() if (lastEncounterDungeon && !sLFGDungeonStore.LookupEntry(lastEncounterDungeon)) { - sLog->outError(LOG_FILTER_SQL, "Table `instance_encounters` has an encounter %u (%s) marked as final for invalid dungeon id %u, skipped!", entry, dungeonEncounter->encounterName[0], lastEncounterDungeon); + sLog->outError(LOG_FILTER_SQL, "Table `instance_encounters` has an encounter %u (%s) marked as final for invalid dungeon id %u, skipped!", entry, dungeonEncounter->encounterName, lastEncounterDungeon); continue; } @@ -5038,7 +4988,7 @@ void ObjectMgr::LoadInstanceEncounters() { if (itr != dungeonLastBosses.end()) { - sLog->outError(LOG_FILTER_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]); + sLog->outError(LOG_FILTER_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; } @@ -5052,7 +5002,7 @@ void ObjectMgr::LoadInstanceEncounters() CreatureTemplate const* creatureInfo = GetCreatureTemplate(creditEntry); if (!creatureInfo) { - sLog->outError(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid creature (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName[0]); + sLog->outError(LOG_FILTER_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; @@ -5061,12 +5011,12 @@ void ObjectMgr::LoadInstanceEncounters() case ENCOUNTER_CREDIT_CAST_SPELL: if (!sSpellMgr->GetSpellInfo(creditEntry)) { - sLog->outError(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid spell (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName[0]); + sLog->outError(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid spell (entry %u) linked to the encounter %u (%s), skipped!", creditEntry, entry, dungeonEncounter->encounterName); continue; } break; default: - sLog->outError(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid credit type (%u) for encounter %u (%s), skipped!", creditType, entry, dungeonEncounter->encounterName[0]); + sLog->outError(LOG_FILTER_SQL, "Table `instance_encounters` has an invalid credit type (%u) for encounter %u (%s), skipped!", creditType, entry, dungeonEncounter->encounterName); continue; } @@ -5234,7 +5184,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(); @@ -5347,12 +5297,12 @@ void ObjectMgr::LoadQuestAreaTriggers() continue; } - if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) + if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT)) { - sLog->outError(LOG_FILTER_SQL, "Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective.", trigger_ID, quest_ID); + sLog->outError(LOG_FILTER_SQL, "Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective.", trigger_ID, quest_ID); // this will prevent quest completing without objective - const_cast<Quest*>(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); + const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT); // continue; - quest modified to required objective and trigger can be allowed. } @@ -5450,8 +5400,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) @@ -6087,6 +6037,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() @@ -6273,8 +6227,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) @@ -6308,10 +6264,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 @@ -6459,7 +6416,7 @@ void ObjectMgr::LoadExplorationBaseXP() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 BaseXP definitions. DB table `exploration_basexp` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 BaseXP definitions. DB table `exploration_basexp` is empty."); return; } @@ -6544,7 +6501,7 @@ std::string ObjectMgr::GeneratePetName(uint32 entry) if (list0.empty() || list1.empty()) { CreatureTemplate const* cinfo = GetCreatureTemplate(entry); - char* petname = GetPetName(cinfo->family, sWorld->GetDefaultDbcLocale()); + const char* petname = GetPetName(cinfo->family, sWorld->GetDefaultDbcLocale()); if (!petname) return cinfo->Name; @@ -6559,8 +6516,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)); @@ -6575,7 +6540,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) { sLog->outError(LOG_FILTER_GENERAL, "Corpse (guid: %u) have wrong corpse type (%u), not loading.", guid, type); @@ -6676,7 +6641,7 @@ void ObjectMgr::LoadReputationOnKill() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 creature award reputation definitions. DB table `creature_onkill_reputation` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 creature award reputation definitions. DB table `creature_onkill_reputation` is empty."); return; } @@ -6738,8 +6703,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) { @@ -6767,6 +6732,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); @@ -6832,6 +6800,12 @@ void ObjectMgr::LoadReputationSpilloverTemplate() sLog->outError(LOG_FILTER_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) + { + sLog->outError(LOG_FILTER_SQL, "Faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template`", repTemplate.faction[4]); + continue; + } _repSpilloverTemplateStore[factionId] = repTemplate; @@ -6855,7 +6829,7 @@ void ObjectMgr::LoadPointsOfInterest() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 Points of Interest definitions. DB table `points_of_interest` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 Points of Interest definitions. DB table `points_of_interest` is empty."); return; } @@ -6901,7 +6875,7 @@ void ObjectMgr::LoadQuestPOI() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 quest POI definitions. DB table `quest_poi` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 quest POI definitions. DB table `quest_poi` is empty."); return; } @@ -6969,7 +6943,7 @@ void ObjectMgr::LoadNPCSpellClickSpells() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 spellclick spells. DB table `npc_spellclick_spells` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 spellclick spells. DB table `npc_spellclick_spells` is empty."); return; } @@ -7072,7 +7046,7 @@ void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map, std::string table, if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 quest relations from `%s`, table is empty.", table.c_str()); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 quest relations from `%s`, table is empty.", table.c_str()); return; } @@ -7443,7 +7417,7 @@ bool ObjectMgr::LoadTrinityStrings(const char* table, int32 min_value, int32 max if (!result) { if (min_value == MIN_TRINITY_STRING_ID) // error only in case internal strings - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 trinity strings. DB table `%s` is empty. Cannot continue.", table); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 trinity strings. DB table `%s` is empty. Cannot continue.", table); else sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 string templates. DB table `%s` is empty.", table); @@ -7519,7 +7493,7 @@ void ObjectMgr::LoadFishingBaseSkillLevel() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 areas for fishing base skill level. DB table `skill_fishing_base_level` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 areas for fishing base skill level. DB table `skill_fishing_base_level` is empty."); return; } @@ -7627,7 +7601,7 @@ void ObjectMgr::LoadGameTele() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 GameTeleports. DB table `game_tele` is empty!"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 GameTeleports. DB table `game_tele` is empty!"); return; } @@ -7767,7 +7741,7 @@ void ObjectMgr::LoadMailLevelRewards() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 level dependent mail rewards. DB table `mail_level_reward` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 level dependent mail rewards. DB table `mail_level_reward` is empty."); return; } @@ -7909,7 +7883,7 @@ void ObjectMgr::LoadTrainerSpell() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 Trainers. DB table `npc_trainer` is empty!"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 Trainers. DB table `npc_trainer` is empty!"); return; } @@ -7936,11 +7910,12 @@ void ObjectMgr::LoadTrainerSpell() sLog->outInfo(LOG_FILTER_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) @@ -7955,19 +7930,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()); @@ -7986,11 +7962,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) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 Vendors. DB table `npc_vendor` is empty!"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 Vendors. DB table `npc_vendor` is empty!"); return; } @@ -8005,19 +7981,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; } } @@ -8036,7 +8013,7 @@ void ObjectMgr::LoadGossipMenu() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 gossip_menu entries. DB table `gossip_menu` is empty!"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 gossip_menu entries. DB table `gossip_menu` is empty!"); return; } @@ -8082,7 +8059,7 @@ void ObjectMgr::LoadGossipMenuItems() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 gossip_menu_option entries. DB table `gossip_menu_option` is empty!"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 gossip_menu_option entries. DB table `gossip_menu_option` is empty!"); return; } @@ -8130,32 +8107,33 @@ void ObjectMgr::LoadGossipMenuItems() sLog->outInfo(LOG_FILTER_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) { - PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_NPC_VENODR); + PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_NPC_VENDOR); stmt->setUInt32(0, entry); stmt->setUInt32(1, item); 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) @@ -8164,6 +8142,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); } @@ -8171,7 +8150,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) @@ -8198,12 +8177,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).PSendSysMessage(LANG_ITEM_NOT_FOUND, item_id); + ChatHandler(player).PSendSysMessage(LANG_ITEM_NOT_FOUND, id, type); else - sLog->outError(LOG_FILTER_SQL, "Table `(game_event_)npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u), ignore", vendor_entry, item_id); + sLog->outError(LOG_FILTER_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; } @@ -8212,41 +8192,44 @@ bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 max if (player) ChatHandler(player).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST, ExtendedCost); else - sLog->outError(LOG_FILTER_SQL, "Table `(game_event_)npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore", item_id, ExtendedCost, vendor_entry); + sLog->outError(LOG_FILTER_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).PSendSysMessage("MaxCount != 0 (%u) but IncrTime == 0", maxcount); - else - sLog->outError(LOG_FILTER_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).PSendSysMessage("MaxCount == 0 but IncrTime<>= 0"); - else - sLog->outError(LOG_FILTER_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).PSendSysMessage("MaxCount != 0 (%u) but IncrTime == 0", maxcount); + else + sLog->outError(LOG_FILTER_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).PSendSysMessage("MaxCount == 0 but IncrTime<>= 0"); + else + sLog->outError(LOG_FILTER_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).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id, ExtendedCost); + ChatHandler(player).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, id, ExtendedCost, type); else - sLog->outError(LOG_FILTER_SQL, "Table `npc_vendor` has duplicate items %u (with extended cost %u) for vendor (Entry: %u), ignoring", item_id, ExtendedCost, vendor_entry); + sLog->outError(LOG_FILTER_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 (vItems->GetItemCount() >= MAX_VENDOR_ITEMS) + if (vItems->GetItemCount() >= MAX_VENDOR_ITEMS) // FIXME: GetItemCount range 0...255 MAX_VENDOR_ITEMS = 300 { if (player) ChatHandler(player).SendSysMessage(LANG_COMMAND_ADDVENDORITEMITEMS); @@ -8272,7 +8255,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 " @@ -8404,7 +8387,7 @@ void ObjectMgr::LoadCreatureClassLevelStats() { uint32 oldMSTime = getMSTime(); - QueryResult result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basemana, basearmor FROM creature_classlevelstats"); + QueryResult result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basehp3, basemana, basearmor FROM creature_classlevelstats"); if (!result) { @@ -8423,10 +8406,10 @@ void ObjectMgr::LoadCreatureClassLevelStats() CreatureBaseStats stats; for (uint8 i = 0; i < MAX_CREATURE_BASE_HP; ++i) - stats.BaseHealth[i] = fields[i + 2].GetInt16(); + stats.BaseHealth[i] = fields[i + 2].GetUInt32(); - stats.BaseMana = fields[5].GetInt16(); - stats.BaseArmor = fields[6].GetInt16(); + stats.BaseMana = fields[5].GetUInt32(); + stats.BaseArmor = fields[6].GetUInt32(); if (!Class || ((1 << (Class - 1)) & CLASSMASK_ALL_CREATURES) == 0) sLog->outError(LOG_FILTER_SQL, "Creature base stats for level %u has invalid class %u", Level, Class); @@ -8467,7 +8450,7 @@ void ObjectMgr::LoadFactionChangeAchievements() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 faction change achievement pairs. DB table `player_factionchange_achievement` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 faction change achievement pairs. DB table `player_factionchange_achievement` is empty."); return; } @@ -8538,7 +8521,7 @@ void ObjectMgr::LoadFactionChangeSpells() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 faction change spell pairs. DB table `player_factionchange_spells` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 faction change spell pairs. DB table `player_factionchange_spells` is empty."); return; } @@ -8601,6 +8584,38 @@ void ObjectMgr::LoadFactionChangeReputations() sLog->outInfo(LOG_FILTER_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) + { + sLog->outInfo(LOG_FILTER_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()); + + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u hotfix info entries 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 da0d37cf27a..c176cf42e1a 100755 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -389,7 +389,6 @@ typedef UNORDERED_MAP<uint32, GameObjectData> GameObjectDataContainer; typedef UNORDERED_MAP<uint32, CreatureLocale> CreatureLocaleContainer; typedef UNORDERED_MAP<uint32, GameObjectLocale> GameObjectLocaleContainer; typedef UNORDERED_MAP<uint32, ItemLocale> ItemLocaleContainer; -typedef UNORDERED_MAP<uint32, ItemSetNameLocale> ItemSetNameLocaleContainer; typedef UNORDERED_MAP<uint32, QuestLocale> QuestLocaleContainer; typedef UNORDERED_MAP<uint32, NpcTextLocale> NpcTextLocaleContainer; typedef UNORDERED_MAP<uint32, PageTextLocale> PageTextLocaleContainer; @@ -578,6 +577,15 @@ struct DungeonEncounter typedef std::list<DungeonEncounter const*> DungeonEncounterList; typedef UNORDERED_MAP<uint32, DungeonEncounterList> DungeonEncounterContainer; +struct HotfixInfo +{ + uint32 Type; + uint32 Timestamp; + uint32 Entry; +}; + +typedef std::vector<HotfixInfo> HotfixData; + class PlayerDumpReader; class ObjectMgr @@ -614,7 +622,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); @@ -631,25 +639,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 { @@ -858,9 +852,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(); @@ -930,6 +924,7 @@ class ObjectMgr uint64 GenerateEquipmentSetGuid(); uint32 GenerateMailID(); uint32 GeneratePetNumber(); + uint64 GenerateVoidStorageItemId(); typedef std::multimap<int32, uint32> ExclusiveQuestGroups; ExclusiveQuestGroups mExclusiveQuestGroups; @@ -984,12 +979,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); @@ -1086,15 +1075,15 @@ class ObjectMgr VendorItemData const* GetNpcVendorItemList(uint32 entry) const { - CacheVendorItemContainer::const_iterator iter = _cacheVendorItemStore.find(entry); + CacheVendorItemContainer::const_iterator iter = _cacheVendorItemStore.find(entry); if (iter == _cacheVendorItemStore.end()) return NULL; 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; + 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; } @@ -1145,6 +1134,19 @@ class ObjectMgr void LoadFactionChangeSpells(); void LoadFactionChangeReputations(); + 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 (itr->Timestamp > ret) + ret = itr->Timestamp; + + return ret ? ret : time(NULL); + } + private: // first free id for selected id type uint32 _auctionId; @@ -1152,6 +1154,7 @@ class ObjectMgr uint32 _itemTextId; uint32 _mailId; uint32 _hiPetNumber; + uint64 _voidItemId; // first free low guid for selected guid type uint32 _hiCharGuid; @@ -1229,8 +1232,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]; @@ -1248,9 +1249,6 @@ class ObjectMgr HalfNameContainer _petHalfName0; HalfNameContainer _petHalfName1; - typedef UNORDERED_MAP<uint32, ItemSetNameEntry> ItemSetNameContainer; - ItemSetNameContainer _itemSetNameStore; - MapObjectGuids _mapObjectGuidsStore; CreatureDataContainer _creatureDataStore; CreatureTemplateContainer _creatureTemplateStore; @@ -1266,7 +1264,6 @@ class ObjectMgr ItemTemplateContainer _itemTemplateStore; ItemLocaleContainer _itemLocaleStore; - ItemSetNameLocaleContainer _itemSetNameLocaleStore; QuestLocaleContainer _questLocaleStore; NpcTextLocaleContainer _npcTextLocaleStore; PageTextLocaleContainer _pageTextLocaleStore; @@ -1287,6 +1284,7 @@ class ObjectMgr GO_TO_GO, GO_TO_CREATURE, // GO is dependant on creature }; + HotfixData _hotfixData; }; #define sObjectMgr ACE_Singleton<ObjectMgr, ACE_Null_Mutex>::instance() diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 072db578220..75df3e67c5a 100755 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -44,7 +44,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); }; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index fda04effbf5..b9ede2ec985 100755 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -269,6 +269,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()) @@ -442,7 +473,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 @@ -453,7 +484,7 @@ bool Group::AddMember(Player* player) if (Player* member = itr->getSource()) { - if (player->HaveAtClient(member)) + if (player->HaveAtClient(member)) // must be on the same map, or shit will break { member->SetFieldNotifyFlag(UF_FLAG_PARTY_MEMBER); member->BuildValuesUpdateBlockForPlayer(&groupData, player); @@ -462,7 +493,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()) @@ -773,7 +804,7 @@ void Group::Disband(bool hideDestroy /* = false */) /*** LOOT SYSTEM ***/ /*********************************************************/ -void Group::SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r) +void Group::SendLootStartRoll(uint32 countDown, uint32 mapid, const Roll &r) { WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4+4+1)); data << uint64(r.itemGUID); // guid of rolled item @@ -783,8 +814,9 @@ void Group::SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r) data << uint32(r.itemRandomSuffix); // randomSuffix data << uint32(r.itemRandomPropId); // item random property ID data << uint32(r.itemCount); // items in stack - data << uint32(CountDown); // the countdown time to choose "need" or "greed" + 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) @@ -917,7 +950,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject) item = sObjectMgr->GetItemTemplate(i->itemid); if (!item) { - //sLog->outDebug("Group::GroupLoot: missing item prototype for item with id: %d", i->itemid); + //sLog->outDebug(LOG_FILTER_GENERAL, "Group::GroupLoot: missing item prototype for item with id: %d", i->itemid); continue; } @@ -1004,7 +1037,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject) item = sObjectMgr->GetItemTemplate(i->itemid); if (!item) { - //sLog->outDebug("Group::GroupLoot: missing item prototype for item with id: %d", i->itemid); + //sLog->outDebug(LOG_FILTER_GENERAL, "Group::GroupLoot: missing item prototype for item with id: %d", i->itemid); continue; } @@ -1201,11 +1234,11 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) void Group::MasterLoot(Loot* /*loot*/, WorldObject* pLootedObject) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Group::MasterLoot (SMSG_LOOT_MASTER_LIST, 330)"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "Group::MasterLoot (SMSG_LOOT_MASTER_LIST)"); uint32 real_count = 0; - WorldPacket data(SMSG_LOOT_MASTER_LIST, 330); + WorldPacket data(SMSG_LOOT_MASTER_LIST, GetMembersCount()*8); data << (uint8)GetMembersCount(); for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) @@ -1326,7 +1359,7 @@ void Group::CountTheRoll(Rolls::iterator rollI) if (player && player->GetSession()) { - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT, roll->itemid, maxresul); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT, roll->itemid, maxresul); ItemPosCountVec dest; LootItem* item = &(roll->itemSlot >= roll->getLoot()->items.size() ? roll->getLoot()->quest_items[roll->itemSlot - roll->getLoot()->items.size()] : roll->getLoot()->items[roll->itemSlot]); @@ -1376,7 +1409,7 @@ void Group::CountTheRoll(Rolls::iterator rollI) if (player && player->GetSession()) { - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT, roll->itemid, maxresul); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT, roll->itemid, maxresul); LootItem* item = &(roll->itemSlot >= roll->getLoot()->items.size() ? roll->getLoot()->quest_items[roll->itemSlot - roll->getLoot()->items.size()] : roll->getLoot()->items[roll->itemSlot]); @@ -1498,6 +1531,7 @@ void Group::SendUpdateToPlayer(uint64 playerGUID, MemberSlot* slot) { data << uint8(sLFGMgr->GetState(m_guid) == 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); @@ -1510,7 +1544,7 @@ void Group::SendUpdateToPlayer(uint64 playerGUID, MemberSlot* slot) Player* member = ObjectAccessor::FindPlayer(citr->guid); - uint8 onlineState = (member) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE; + uint8 onlineState = member ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE; onlineState = onlineState | ((isBGGroup() || isBFGroup()) ? MEMBER_STATUS_PVP : 0); data << citr->name; @@ -1530,7 +1564,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(0); // 3.3 } player->GetSession()->SendPacket(&data); @@ -1553,6 +1586,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()) diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index de622a16301..5d3bcdd48a3 100755 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -96,34 +96,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 (length), if length > 0, string (size 2*length), else cstring + + 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 | /* unk100 */ GROUP_UPDATE_FLAG_POSITION | + GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_PET | GROUP_UPDATE_FLAG_VEHICLE_SEAT | GROUP_UPDATE_FLAG_PHASE, // all known flags }; -#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); @@ -269,7 +274,8 @@ class Group void SendUpdateToPlayer(uint64 playerGUID, MemberSlot* slot = NULL); 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 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 4df77f874f3..595ad77feeb 100755..100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -219,17 +219,6 @@ void Guild::RankInfo::SaveToDB(SQLTransaction& trans) const CharacterDatabase.ExecuteOrAppend(trans, stmt); } -void Guild::RankInfo::WritePacket(WorldPacket& data) const -{ - data << uint32(m_rights); - data << uint32(m_bankMoneyPerDay); // In game set in gold, in packet set in bronze. - for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i) - { - data << uint32(m_bankTabRightsAndSlots[i].rights); - data << uint32(m_bankTabRightsAndSlots[i].slots); - } -} - void Guild::RankInfo::SetName(const std::string& name) { if (m_name == name) @@ -381,48 +370,6 @@ void Guild::BankTab::Delete(SQLTransaction& trans, bool removeItemsFromDB) } } -inline void Guild::BankTab::WritePacket(WorldPacket& data) const -{ - data << uint8(GUILD_BANK_MAX_SLOTS); - for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId) - WriteSlotPacket(data, slotId); -} - -// Writes information about contents of specified slot into packet. -void Guild::BankTab::WriteSlotPacket(WorldPacket& data, uint8 slotId) const -{ - Item* pItem = GetItem(slotId); - uint32 itemEntry = pItem ? pItem->GetEntry() : 0; - - data << uint8(slotId); - data << uint32(itemEntry); - if (itemEntry) - { - data << uint32(0); // 3.3.0 (0x00018020, 0x00018000) - data << uint32(pItem->GetItemRandomPropertyId()); // Random item property id - - if (pItem->GetItemRandomPropertyId()) - data << uint32(pItem->GetItemSuffixFactor()); // SuffixFactor - - 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); - } -} - void Guild::BankTab::SetInfo(const std::string& name, const std::string& icon) { if (m_name == name && m_icon == icon) @@ -586,12 +533,12 @@ bool Guild::Member::LoadFromDB(Field* fields) m_bankRemaining[i].value = fields[8 + i * 2].GetUInt32(); } - SetStats(fields[19].GetString(), - fields[20].GetUInt8(), // characters.level - fields[21].GetUInt8(), // characters.class - fields[22].GetUInt16(), // characters.zone - fields[23].GetUInt32()); // characters.account - m_logoutTime = fields[24].GetUInt32(); // characters.logout_time + SetStats(fields[23].GetString(), + fields[24].GetUInt8(), // characters.level + fields[25].GetUInt8(), // characters.class + fields[26].GetUInt16(), // characters.zone + fields[27].GetUInt32()); // characters.account + m_logoutTime = fields[28].GetUInt32(); // characters.logout_time if (!CheckStats()) return false; @@ -620,35 +567,6 @@ bool Guild::Member::CheckStats() const return true; } -void Guild::Member::WritePacket(WorldPacket& data) const -{ - if (Player* player = FindPlayer()) - { - data << uint64(player->GetGUID()); - data << uint8(1); - data << player->GetName(); - data << uint32(m_rankId); - data << uint8(player->getLevel()); - data << uint8(player->getClass()); - data << uint8(0); // new 2.4.0 - data << uint32(player->GetZoneId()); - } - else - { - data << m_guid; - data << uint8(0); - data << m_name; - data << uint32(m_rankId); - data << uint8(m_level); - data << uint8(m_class); - data << uint8(0); // new 2.4.0 - data << uint32(m_zoneId); - data << float(float(::time(NULL) - m_logoutTime) / DAY); - } - data << m_publicNote; - data << m_officerNote; -} - // 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. @@ -804,13 +722,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; } } @@ -1029,11 +947,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) @@ -1044,7 +962,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; @@ -1069,7 +987,7 @@ InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap) /////////////////////////////////////////////////////////////////////////////// // Guild -Guild::Guild() : m_id(0), m_leaderGuid(0), m_createdDate(0), m_accountsNumber(0), m_bankMoney(0), m_eventLog(NULL) +Guild::Guild() : m_id(0), m_leaderGuid(0), m_createdDate(0), m_accountsNumber(0), m_bankMoney(0), m_eventLog(NULL), m_achievementMgr(this), m_level(1) { memset(&m_bankEventLog, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(LogHolder*)); } @@ -1107,6 +1025,7 @@ bool Guild::Create(Player* pLeader, const std::string& name) m_motd = "No message set."; m_bankMoney = 0; m_createdDate = ::time(NULL); + m_level = 1; _CreateLogHolders(); sLog->outDebug(LOG_FILTER_GUILD, "GUILD: creating guild [%s] for leader %s (%u)", @@ -1144,6 +1063,8 @@ bool Guild::Create(Player* pLeader, const std::string& name) // Call scripts on successful create sScriptMgr->OnGuildCreate(this, pLeader, name); + _BroadcastEvent(GE_FOUNDER, m_leaderGuid); + return ret; } @@ -1198,22 +1119,108 @@ void Guild::Disband() sGuildMgr->RemoveGuild(m_id); } +void Guild::SaveToDB() +{ + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + m_achievementMgr.SaveToDB(trans); + + CharacterDatabase.CommitTransaction(trans); +} + /////////////////////////////////////////////////////////////////////////////// // HANDLE CLIENT COMMANDS void Guild::HandleRoster(WorldSession* session /*= NULL*/) { + 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); + { + Member* member = itr->second; + Player* player = member->FindPlayer(); + 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]); + + uint8 flags = GUILDMEMBER_STATUS_NONE; + if (player) + { + flags |= GUILDMEMBER_STATUS_ONLINE; + if (player->isAFK()) + flags |= GUILDMEMBER_STATUS_AFK; + if (player->isDND()) + flags |= GUILDMEMBER_STATUS_DND; + } + + memberData << uint8(member->GetClass()); + memberData << int32(0); // unk + memberData.WriteByteSeq(guid[0]); + memberData << uint64(0); // weekly activity + memberData << uint32(member->GetRankId()); + memberData << uint32(0); // player->GetAchievementMgr().GetCompletedAchievementsAmount() + + // for (2 professions) + memberData << uint32(0) << uint32(0) << uint32(0); + memberData << uint32(0) << uint32(0) << uint32(0); + + memberData.WriteByteSeq(guid[2]); + memberData << uint8(flags); + memberData << uint32(player ? player->GetZoneId() : member->GetZone()); + memberData << uint64(0); // Total activity + memberData.WriteByteSeq(guid[7]); + memberData << uint32(member->GetRemainingWeeklyReputation());// Remaining guild week Rep + + if (pubNoteLength) + memberData.WriteString(member->GetPublicNote()); + + memberData.WriteByteSeq(guid[3]); + memberData << uint8(player ? player->getLevel() : member->GetLevel()); + memberData << int32(0); // unk + memberData.WriteByteSeq(guid[5]); + memberData.WriteByteSeq(guid[4]); + memberData << uint8(0); // unk + memberData.WriteByteSeq(guid[1]); + memberData << float(player ? 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(GUILD_REPUTATION_WEEKLY_CAP); + data << uint32(secsToTimeBitFields(m_createdDate)); + data << uint32(0); if (session) session->SendPacket(&data); @@ -1225,9 +1232,11 @@ void Guild::HandleRoster(WorldSession* session /*= NULL*/) 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 for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i) // Always show 10 ranks { if (i < _GetRanksSize()) @@ -1236,13 +1245,71 @@ 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()); // Amount of ranks + + data << uint32(_GetRanksSize()); // Number of ranks used + session->SendPacket(&data); sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)"); } +void Guild::HandleGuildRanks(WorldSession* session) const +{ + // perhaps move to guild.cpp..... + 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(i); + + 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(rankInfo->GetId()); + } + + data.FlushBits(); + data.append(rankData); + session->SendPacket(&data); +} + void Guild::HandleSetMOTD(WorldSession* session, const std::string& motd) { if (m_motd == motd) @@ -1293,12 +1360,12 @@ void Guild::HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo) if (!_IsLeader(player)) // "Only guild leaders can create emblems." SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTGUILDMASTER); - else if (!player->HasEnoughMoney(EMBLEM_PRICE)) + else if (!player->HasEnoughMoney(uint64(EMBLEM_PRICE))) // "You can't afford to do that." SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTENOUGHMONEY); else { - player->ModifyMoney(-int32(EMBLEM_PRICE)); + player->ModifyMoney(-int64(EMBLEM_PRICE)); m_emblemInfo = emblemInfo; m_emblemInfo.SaveToDB(m_id); @@ -1336,28 +1403,26 @@ void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, const std:: if (BankTab* pTab = GetBankTab(tabId)) { pTab->SetInfo(name, icon); - SendBankTabsInfo(session); - _SendBankContent(session, tabId); + SendBankList(session, tabId, true, true); } } -void Guild::HandleSetMemberNote(WorldSession* session, const std::string& name, const std::string& note, bool officer) +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(), officer ? GR_RIGHT_EOFFNOTE : GR_RIGHT_EPNOTE)) + if (!_HasRankRight(session->GetPlayer(), isPublic ? GR_RIGHT_EPNOTE : GR_RIGHT_EOFFNOTE)) SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); - // Noted player must be a member of guild - else if (Member* member = GetMember(session, name)) + else if (Member* member = GetMember(guid)) { - if (officer) - member->SetOfficerNote(note); - else + if (isPublic) member->SetPublicNote(note); + else + member->SetOfficerNote(note); HandleRoster(session); } } -void Guild::HandleSetRankInfo(WorldSession* session, uint8 rankId, const std::string& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots) +void Guild::HandleSetRankInfo(WorldSession* session, uint32 rankId, const std::string& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots) { // Only leader can modify ranks if (!_IsLeader(session->GetPlayer())) @@ -1389,17 +1454,17 @@ void Guild::HandleBuyBankTab(WorldSession* session, uint8 tabId) return; Player* player = session->GetPlayer(); - if (!player->HasEnoughMoney(tabCost)) // Should not happen, this is checked by client + if (!player->HasEnoughMoney(uint64(tabCost))) // Should not happen, this is checked by client return; if (!_CreateNewBankTab()) return; - player->ModifyMoney(-int32(tabCost)); + player->ModifyMoney(-int64(tabCost)); _SetRankBankMoneyPerDay(player->GetRank(), uint32(GUILD_WITHDRAW_MONEY_UNLIMITED)); _SetRankBankTabRightsAndSlots(player->GetRank(), tabId, GuildBankRightsAndSlots(GUILD_BANK_RIGHT_FULL, uint32(GUILD_WITHDRAW_SLOT_UNLIMITED))); HandleRoster(); // Broadcast for tab rights update - SendBankTabsInfo(session); + SendBankList(session, tabId, false, true); } void Guild::HandleInviteMember(WorldSession* session, const std::string& name) @@ -1421,11 +1486,11 @@ void Guild::HandleInviteMember(WorldSession* session, const std::string& name) return; } // Invited player cannot be in another guild - if (pInvitee->GetGuildId()) + /*if (pInvitee->GetGuildId()) { - SendCommandResult(session, GUILD_INVITE_S, ERR_ALREADY_IN_GUILD_S, name); + SendCommandResult(session, GUILD_INVITE, ERR_ALREADY_IN_GUILD_S, name); return; - } + }*/ // Invited player cannot be invited if (pInvitee->GetGuildIdInvited()) { @@ -1444,9 +1509,65 @@ void Guild::HandleInviteMember(WorldSession* session, const std::string& 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(strlen(player->GetName()), 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); sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_INVITE)"); @@ -1490,41 +1611,49 @@ void Guild::HandleLeaveMember(WorldSession* session) } } -void Guild::HandleRemoveMember(WorldSession* session, const std::string& name) +void Guild::HandleRemoveMember(WorldSession* session, uint64 guid) { Player* player = session->GetPlayer(); + Player* removedPlayer = ObjectAccessor::FindPlayer(guid); + Member* member = GetMember(guid); + // Player must have rights to remove members if (!_HasRankRight(player, GR_RIGHT_REMOVE)) SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); - // Removed player must be a member of guild - else if (Member* member = GetMember(session, name)) + // Removed player must be a member of the guild + else if (member && removedPlayer) { - // Leader cannot be removed + // Guild masters cannot be removed if (member->IsRank(GR_GUILDMASTER)) SendCommandResult(session, GUILD_QUIT_S, ERR_GUILD_LEADER_LEAVE); // Do not allow to remove player with the same rank or higher else if (member->IsRankNotLower(player->GetRank())) - SendCommandResult(session, GUILD_QUIT_S, ERR_GUILD_RANK_TOO_HIGH_S, name); + SendCommandResult(session, GUILD_QUIT_S, ERR_GUILD_RANK_TOO_HIGH_S, removedPlayer->GetName()); 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()); + _BroadcastEvent(GE_REMOVED, 0, removedPlayer->GetName(), player->GetName()); } } + else if (removedPlayer) + SendCommandResult(session, GUILD_QUIT_S, ERR_PLAYER_NO_MORE_IN_GUILD, removedPlayer->GetName()); } -void Guild::HandleUpdateMemberRank(WorldSession* session, const std::string& name, bool demote) +void Guild::HandleUpdateMemberRank(WorldSession* session, uint64 targetGuid, bool demote) { Player* player = session->GetPlayer(); - // Player must have rights to promote - if (!_HasRankRight(player, demote ? GR_RIGHT_DEMOTE : GR_RIGHT_PROMOTE)) - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); + // Promoted player must be a member of guild - else if (Member* member = GetMember(session, name)) + if (Member* member = GetMember(targetGuid)) { + if (!_HasRankRight(player, demote ? GR_RIGHT_DEMOTE : GR_RIGHT_PROMOTE)) + { + SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); + return; + } + // Player cannot promote himself if (member->IsSamePlayer(player->GetGUID())) { @@ -1537,13 +1666,13 @@ void Guild::HandleUpdateMemberRank(WorldSession* session, const std::string& nam // Player can demote only lower rank members if (member->IsRankNotLower(player->GetRank())) { - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_HIGH_S, name); + SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_HIGH_S, member->GetName()); return; } // Lowest rank cannot be demoted if (member->GetRankId() >= _GetLowestRankId()) { - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_LOW_S, name); + SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_LOW_S, member->GetName()); return; } } @@ -1553,20 +1682,43 @@ void Guild::HandleUpdateMemberRank(WorldSession* session, const std::string& nam // member->GetRank() + 1 is the highest rank that current player can promote to if (member->IsRankNotLower(player->GetRank() + 1)) { - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_HIGH_S, name); + SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_HIGH_S, member->GetName()); return; } } - // When promoting player, rank is decreased, when demoting - increased uint32 newRankId = member->GetRankId() + (demote ? 1 : -1); member->ChangeRank(newRankId); _LogEvent(demote ? GUILD_EVENT_LOG_DEMOTE_PLAYER : GUILD_EVENT_LOG_PROMOTE_PLAYER, player->GetGUIDLow(), GUID_LOPART(member->GetGUID()), newRankId); - _BroadcastEvent(demote ? GE_DEMOTION : GE_PROMOTION, 0, player->GetName(), name.c_str(), _GetRankName(newRankId).c_str()); + _BroadcastEvent(demote ? GE_DEMOTION : GE_PROMOTION, 0, player->GetName(), member->GetName().c_str(), _GetRankName(newRankId).c_str()); + } +} + +void Guild::HandleSetMemberRank(WorldSession* session, uint64 targetGuid, uint64 setterGuid, uint32 rank) +{ + Player* player = session->GetPlayer(); + + // Promoted player must be a member of guild + if (Member* member = GetMember(targetGuid)) + { + if (!_HasRankRight(player, rank > member->GetRankId() ? GR_RIGHT_DEMOTE : GR_RIGHT_PROMOTE)) + { + SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); + return; + } + + // Player cannot promote himself + if (member->IsSamePlayer(player->GetGUID())) + { + SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_NAME_INVALID); + return; + } + + SendGuildRanksUpdate(setterGuid, targetGuid, rank); } } -void Guild::HandleAddNewRank(WorldSession* session, const std::string& name) +void Guild::HandleAddNewRank(WorldSession* session, std::string const& name) //, uint32 rankId) { if (_GetRanksSize() >= GUILD_RANKS_MAX_COUNT) return; @@ -1582,7 +1734,7 @@ void Guild::HandleAddNewRank(WorldSession* session, const std::string& name) } } -void Guild::HandleRemoveLowestRank(WorldSession* session) +void Guild::HandleRemoveRank(WorldSession* session, uint32 rankId) { // Cannot remove rank if total count is minimum allowed by the client if (_GetRanksSize() <= GUILD_RANKS_MIN_COUNT) @@ -1593,19 +1745,18 @@ void Guild::HandleRemoveLowestRank(WorldSession* session) SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); else { - uint8 rankId = _GetLowestRankId(); // Delete bank rights for rank PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_RIGHTS_FOR_RANK); stmt->setUInt32(0, m_id); - stmt->setUInt8 (1, 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); + stmt->setUInt8(1, rankId); CharacterDatabase.Execute(stmt); - m_ranks.pop_back(); + m_ranks.erase(m_ranks.begin() + rankId-1); HandleQuery(session); HandleRoster(); // Broadcast for tab rights update @@ -1623,7 +1774,7 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount) // Add money to bank _ModifyBankMoney(trans, amount, true); // Remove money from player - player->ModifyMoney(-int32(amount)); + player->ModifyMoney(-int64(amount)); player->SaveGoldToDB(trans); // Log GM action (TODO: move to scripts) if (!AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) @@ -1637,9 +1788,7 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount) CharacterDatabase.CommitTransaction(trans); - SendBankTabsInfo(session); - _SendBankContent(session, 0); - _SendBankMoneyUpdate(session); + SendBankList(session, 0, false, false); } bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair) @@ -1680,11 +1829,7 @@ bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool SendMoneyInfo(session); if (!repair) - { - SendBankTabsInfo(session); - _SendBankContent(session, 0); - _SendBankMoneyUpdate(session); - } + SendBankList(session, 0, false, false); return true; } @@ -1697,6 +1842,8 @@ void Guild::HandleMemberLogout(WorldSession* session) member->UpdateLogoutTime(); } _BroadcastEvent(GE_SIGNED_OFF, player->GetGUID(), player->GetName()); + + SaveToDB(); } void Guild::HandleDisband(WorldSession* session) @@ -1711,20 +1858,28 @@ 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 << secsToTimeBitFields(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(0); // 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); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_INFO)"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_GUILD_PARTY_STATE_RESPONSE)"); } +/////////////////////////////////////////////////////////////////////////////// +// Send data to client void Guild::SendEventLog(WorldSession* session) const { WorldPacket data(MSG_GUILD_EVENT_LOG_QUERY, 1 + m_eventLog->GetSize() * (1 + 8 + 4)); @@ -1747,29 +1902,86 @@ void Guild::SendBankLog(WorldSession* session, uint8 tabId) const } } -void Guild::SendBankTabData(WorldSession* session, uint8 tabId) const +void Guild::SendBankList(WorldSession* session, uint8 tabId, bool withContent, bool withTabInfo) const { - if (tabId < _GetPurchasedTabsSize()) + ByteBuffer tabData; + WorldPacket data(SMSG_GUILD_BANK_LIST, 500); + 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 (Item* tabItem = 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 (withTabInfo) { - SendMoneyInfo(session); - _SendBankContent(session, tabId); + for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i) + { + data.WriteBits(m_bankTabs[i]->GetIcon().length(), 9); + data.WriteBits(m_bankTabs[i]->GetName().length(), 7); + } } -} -void Guild::SendBankTabsInfo(WorldSession* session) const -{ - WorldPacket data(SMSG_GUILD_BANK_LIST, 500); + data.FlushBits(); + + if (withTabInfo) + { + for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i) + { + data.WriteString(m_bankTabs[i]->GetIcon()); + data << uint32(i); + data.WriteString(m_bankTabs[i]->GetName()); + } + } data << uint64(m_bankMoney); - data << uint8(0); // TabInfo packet must be for tabId 0 - data << uint32(_GetMemberRemainingSlots(session->GetPlayer()->GetGUID(), 0)); - data << uint8(1); // Tell client that this packet includes tab info + if (!tabData.empty()) + data.append(tabData); - data << uint8(_GetPurchasedTabsSize()); // Number of tabs - for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i) - m_bankTabs[i]->WriteInfoPacket(data); + data << uint32(tabId); + data << uint32(_GetMemberRemainingSlots(session->GetPlayer()->GetGUID(), 0)); - data << uint8(0); // Do not send tab content session->SendPacket(&data); sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_BANK_LIST)"); @@ -1784,33 +1996,44 @@ void Guild::SendBankTabText(WorldSession* session, uint8 tabId) const void Guild::SendPermissions(WorldSession* session) const { uint64 guid = session->GetPlayer()->GetGUID(); - uint8 rankId = session->GetPlayer()->GetRank(); - - WorldPacket data(MSG_GUILD_PERMISSIONS, 4 * 15 + 1); + uint32 rankId = session->GetPlayer()->GetRank(); + WorldPacket data(SMSG_GUILD_PERMISSIONS_QUERY_RESULTS, 4 * 15 + 1); data << uint32(rankId); + data << uint32(_GetPurchasedTabsSize()); data << uint32(_GetRankRights(rankId)); data << uint32(_GetMemberRemainingMoney(guid)); - data << uint8 (_GetPurchasedTabsSize()); - // Why sending all info when not all tabs are purchased??? + data.WriteBits(GUILD_BANK_MAX_TABS, 23); for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId) { data << uint32(_GetRankBankTabRights(rankId, tabId)); data << uint32(_GetMemberRemainingSlots(guid, tabId)); } + session->SendPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (MSG_GUILD_PERMISSIONS)"); + sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_PERMISSIONS_QUERY_RESULTS)"); } void Guild::SendMoneyInfo(WorldSession* session) const { - WorldPacket data(MSG_GUILD_BANK_MONEY_WITHDRAWN, 4); - data << uint32(_GetMemberRemainingMoney(session->GetPlayer()->GetGUID())); + WorldPacket data(SMSG_GUILD_BANK_MONEY_WITHDRAWN, 4); + data << uint64(_GetMemberRemainingMoney(session->GetPlayer()->GetGUID())); session->SendPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent MSG_GUILD_BANK_MONEY_WITHDRAWN"); + sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent SMSG_GUILD_BANK_MONEY_WITHDRAWN"); } void Guild::SendLoginInfo(WorldSession* session) const { + /* + 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); @@ -1818,9 +2041,39 @@ void Guild::SendLoginInfo(WorldSession* session) const session->SendPacket(&data); sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent guild MOTD (SMSG_GUILD_EVENT)"); - SendBankTabsInfo(session); + HandleGuildRanks(session); _BroadcastEvent(GE_SIGNED_ON, session->GetPlayer()->GetGUID(), session->GetPlayer()->GetName()); + + // Send to self separately, player is not in world yet and is not found by _BroadcastEvent + data.Initialize(SMSG_GUILD_EVENT, 1 + 1 + strlen(session->GetPlayer()->GetName()) + 8); + data << uint8(GE_SIGNED_ON); + data << uint8(1); + data << session->GetPlayer()->GetName(); + data << uint64(session->GetPlayer()->GetGUID()); + session->SendPacket(&data); + + for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i) + if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i)) + if (entry->Level >= GetLevel()) + session->GetPlayer()->learnSpell(entry->SpellId, false); + + SendGuildReputationWeeklyCap(session); + + GetAchievementMgr().SendAllAchievementData(session->GetPlayer()); + + data.Initialize(SMSG_GUILD_MEMBER_DAILY_RESET, 0); // tells the client to request bank withdrawal limit + session->SendPacket(&data); +} + +void Guild::SendGuildReputationWeeklyCap(WorldSession* session) const +{ + if (Member const* member = GetMember(session->GetPlayer()->GetGUID())) + { + WorldPacket data(SMSG_GUILD_REPUTATION_WEEKLY_CAP, 4); + data << uint32(member->GetRemainingWeeklyReputation()); + session->SendPacket(&data); + } } /////////////////////////////////////////////////////////////////////////////// @@ -2040,6 +2293,21 @@ void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, const std: } } +void Guild::BroadcastAddonToGuild(WorldSession* session, bool officerOnly, const std::string& msg, const std::string& prefix) const +{ + if (session && session->GetPlayer() && _HasRankRight(session->GetPlayer(), officerOnly ? GR_RIGHT_OFFCHATSPEAK : GR_RIGHT_GCHATSPEAK)) + { + WorldPacket data; + ChatHandler::FillMessageData(&data, session, officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, CHAT_MSG_ADDON, NULL, 0, msg.c_str(), NULL, prefix.c_str()); + 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) @@ -2075,7 +2343,7 @@ bool Guild::AddMember(uint64 guid, uint8 rankId) uint32 lowguid = GUID_LOPART(guid); - // If rank was not passed, assing lowest possible rank + // If rank was not passed, assign lowest possible rank if (rankId == GUILD_RANK_NONE) rankId = _GetLowestRankId(); @@ -2115,6 +2383,7 @@ bool Guild::AddMember(uint64 guid, uint8 rankId) { player->SetInGuild(m_id); player->SetRank(rankId); + player->SetGuildLevel(m_level); player->SetGuildIdInvited(0); } @@ -2193,6 +2462,12 @@ bool Guild::ChangeMemberRank(uint64 guid, uint8 newRank) return false; } +bool Guild::IsMember(uint64 guid) +{ + 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) @@ -2292,7 +2567,7 @@ void Guild::_CreateRank(const std::string& name, uint32 rights) return; // Ranks represent sequence 0, 1, 2, ... where 0 means guildmaster - uint8 newRankId = _GetRanksSize(); + uint32 newRankId = _GetRanksSize(); RankInfo info(m_id, newRankId, name, rights, 0); m_ranks.push_back(info); @@ -2379,7 +2654,7 @@ void Guild::_SetLeaderGUID(Member* pLeader) CharacterDatabase.Execute(stmt); } -void Guild::_SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay) +void Guild::_SetRankBankMoneyPerDay(uint32 rankId, uint32 moneyPerDay) { if (RankInfo* rankInfo = GetRankInfo(rankId)) { @@ -2391,7 +2666,7 @@ void Guild::_SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay) } } -void Guild::_SetRankBankTabRightsAndSlots(uint8 rankId, uint8 tabId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB) +void Guild::_SetRankBankTabRightsAndSlots(uint32 rankId, uint8 tabId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB) { if (tabId >= _GetPurchasedTabsSize()) return; @@ -2406,28 +2681,28 @@ void Guild::_SetRankBankTabRightsAndSlots(uint8 rankId, uint8 tabId, GuildBankRi } } -inline std::string Guild::_GetRankName(uint8 rankId) const +inline std::string Guild::_GetRankName(uint32 rankId) const { if (const RankInfo* rankInfo = GetRankInfo(rankId)) return rankInfo->GetName(); return "<unknown>"; } -inline uint32 Guild::_GetRankRights(uint8 rankId) const +inline uint32 Guild::_GetRankRights(uint32 rankId) const { if (const RankInfo* rankInfo = GetRankInfo(rankId)) return rankInfo->GetRights(); return 0; } -inline uint32 Guild::_GetRankBankMoneyPerDay(uint8 rankId) const +inline uint32 Guild::_GetRankBankMoneyPerDay(uint32 rankId) const { if (const RankInfo* rankInfo = GetRankInfo(rankId)) return rankInfo->GetBankMoneyPerDay(); return 0; } -inline uint32 Guild::_GetRankBankTabSlotsPerDay(uint8 rankId, uint8 tabId) const +inline uint32 Guild::_GetRankBankTabSlotsPerDay(uint32 rankId, uint8 tabId) const { if (tabId < _GetPurchasedTabsSize()) if (const RankInfo* rankInfo = GetRankInfo(rankId)) @@ -2435,7 +2710,7 @@ inline uint32 Guild::_GetRankBankTabSlotsPerDay(uint8 rankId, uint8 tabId) const return 0; } -inline uint8 Guild::_GetRankBankTabRights(uint8 rankId, uint8 tabId) const +inline uint32 Guild::_GetRankBankTabRights(uint32 rankId, uint8 tabId) const { if (const RankInfo* rankInfo = GetRankInfo(rankId)) return rankInfo->GetBankTabRights(tabId); @@ -2624,41 +2899,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)) - if (const BankTab* pTab = GetBankTab(tabId)) - { - WorldPacket data(SMSG_GUILD_BANK_LIST, 1200); - - data << uint64(m_bankMoney); - data << uint8(tabId); - data << uint32(_GetMemberRemainingSlots(guid, tabId)); - data << uint8(0); // Tell client that there's no tab info in this packet - - pTab->WritePacket(data); - - session->SendPacket(&data); - - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_BANK_LIST)"); - } -} - -void Guild::_SendBankMoneyUpdate(WorldSession* session) const -{ - WorldPacket data(SMSG_GUILD_BANK_LIST, 8 + 1 + 4 + 1 + 1); - - data << uint64(m_bankMoney); - data << uint8(0); // tabId, default 0 - data << uint32(_GetMemberRemainingSlots(session->GetPlayer()->GetGUID(), 0)); - data << uint8(0); // Tell that there's no tab info in this packet - data << uint8(0); // No items - BroadcastPacket(&data); - - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_BANK_LIST)"); -} - void Guild::_SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) const { ASSERT(pSrc->IsBank() || pDest->IsBank()); @@ -2687,26 +2927,63 @@ void Guild::_SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) cons tabId = pDest->GetContainer(); pDest->CopySlots(slots); } + _SendBankContentUpdate(tabId, slots); } void Guild::_SendBankContentUpdate(uint8 tabId, SlotIds slots) const { - if (const BankTab* pTab = GetBankTab(tabId)) + 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); - data << uint8(tabId); + if (!tabData.empty()) + data.append(tabData); + + data << uint32(tabId); size_t rempos = data.wpos(); data << uint32(0); // Item withdraw amount, will be filled later - data << uint8(0); // Tell client that there's no tab info in this packet - - data << uint8(slots.size()); - for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId) - if (slots.find(slotId) != slots.end()) - pTab->WriteSlotPacket(data, slotId); for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) if (_MemberHasTabRights(itr->second->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB)) @@ -2742,3 +3019,56 @@ void Guild::_BroadcastEvent(GuildEvents guildEvent, uint64 guid, const char* par sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent SMSG_GUILD_EVENT"); } + +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); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_GUILD_RANKS_UPDATE"); +} diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index e18e62e51b7..565420052ec 100755 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -29,7 +29,7 @@ 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, @@ -72,7 +72,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 @@ -87,54 +87,68 @@ enum GuildCommandType enum GuildCommandError { - ERR_PLAYER_NO_MORE_IN_GUILD = 0x00, - ERR_GUILD_INTERNAL = 0x01, - ERR_ALREADY_IN_GUILD = 0x02, - ERR_ALREADY_IN_GUILD_S = 0x03, - ERR_INVITED_TO_GUILD = 0x04, - ERR_ALREADY_INVITED_TO_GUILD_S = 0x05, - ERR_GUILD_NAME_INVALID = 0x06, - ERR_GUILD_NAME_EXISTS_S = 0x07, - ERR_GUILD_LEADER_LEAVE = 0x08, - ERR_GUILD_PERMISSIONS = 0x08, - ERR_GUILD_PLAYER_NOT_IN_GUILD = 0x09, - ERR_GUILD_PLAYER_NOT_IN_GUILD_S = 0x0A, - ERR_GUILD_PLAYER_NOT_FOUND_S = 0x0B, - ERR_GUILD_NOT_ALLIED = 0x0C, - ERR_GUILD_RANK_TOO_HIGH_S = 0x0D, - ERR_GUILD_RANK_TOO_LOW_S = 0x0E, - ERR_GUILD_RANKS_LOCKED = 0x11, - ERR_GUILD_RANK_IN_USE = 0x12, - ERR_GUILD_IGNORING_YOU_S = 0x13, - ERR_GUILD_UNK1 = 0x14, - ERR_GUILD_WITHDRAW_LIMIT = 0x19, - ERR_GUILD_NOT_ENOUGH_MONEY = 0x1A, - ERR_GUILD_BANK_FULL = 0x1C, - ERR_GUILD_ITEM_NOT_FOUND = 0x1D + ERR_PLAYER_NO_MORE_IN_GUILD = 0x00, + ERR_GUILD_INTERNAL = 0x01, + ERR_ALREADY_IN_GUILD = 0x02, + ERR_ALREADY_IN_GUILD_S = 0x03, + ERR_INVITED_TO_GUILD = 0x04, + ERR_ALREADY_INVITED_TO_GUILD_S = 0x05, + ERR_GUILD_NAME_INVALID = 0x06, + ERR_GUILD_NAME_EXISTS_S = 0x07, + ERR_GUILD_LEADER_LEAVE = 0x08, + ERR_GUILD_PERMISSIONS = 0x08, + ERR_GUILD_PLAYER_NOT_IN_GUILD = 0x09, + ERR_GUILD_PLAYER_NOT_IN_GUILD_S = 0x0A, + ERR_GUILD_PLAYER_NOT_FOUND_S = 0x0B, + ERR_GUILD_NOT_ALLIED = 0x0C, + ERR_GUILD_RANK_TOO_HIGH_S = 0x0D, + ERR_GUILD_RANK_TOO_LOW_S = 0x0E, + ERR_GUILD_RANKS_LOCKED = 0x11, + ERR_GUILD_RANK_IN_USE = 0x12, + ERR_GUILD_IGNORING_YOU_S = 0x13, + ERR_GUILD_UNK1 = 0x14, + ERR_GUILD_WITHDRAW_LIMIT = 0x19, + ERR_GUILD_NOT_ENOUGH_MONEY = 0x1A, + ERR_GUILD_BANK_FULL = 0x1C, + ERR_GUILD_ITEM_NOT_FOUND = 0x1D, + ERR_GUILD_TOO_MUCH_MONEY = 0x1F, + ERR_GUILD_BANK_WRONG_TAB = 0x20, + ERR_RANK_REQUIRES_AUTHENTICATOR = 0x22, + ERR_GUILD_BANK_VOUCHER_FAILED = 0x23, + ERR_GUILD_TRIAL_ACCOUNT = 0x24, + ERR_GUILD_UNDELETABLE_DUE_TO_LEVEL = 0x25, + ERR_GUILD_MOVE_STARTING = 0x26, + ERR_GUILD_REP_TOO_LOW = 0x27, }; enum GuildEvents { - GE_PROMOTION = 0x00, - GE_DEMOTION = 0x01, - GE_MOTD = 0x02, - GE_JOINED = 0x03, - GE_LEFT = 0x04, - GE_REMOVED = 0x05, - GE_LEADER_IS = 0x06, - GE_LEADER_CHANGED = 0x07, - GE_DISBANDED = 0x08, - GE_TABARDCHANGE = 0x09, - GE_UNK1 = 0x0A, // string, string EVENT_GUILD_ROSTER_UPDATE tab content change? - GE_UNK2 = 0x0B, // EVENT_GUILD_ROSTER_UPDATE - GE_SIGNED_ON = 0x0C, // ERR_FRIEND_ONLINE_SS - GE_SIGNED_OFF = 0x0D, // ERR_FRIEND_OFFLINE_S - GE_GUILDBANK_BAGSLOTS_CHANGED = 0x0E, // EVENT_GUILDBANK_BAGSLOTS_CHANGED - GE_GUILDBANK_TAB_PURCHASED = 0x0F, // EVENT_GUILDBANK_UPDATE_TABS - GE_UNK5 = 0x10, // EVENT_GUILDBANK_UPDATE_TABS - GE_GUILDBANK_MONEY_UPDATE = 0x11, // EVENT_GUILDBANK_UPDATE_MONEY, string 0000000000002710 is 1 gold - GE_GUILDBANK_MONEY_WITHDRAWN = 0x12, // MSG_GUILD_BANK_MONEY_WITHDRAWN - GE_GUILDBANK_TEXT_CHANGED = 0x13 // EVENT_GUILDBANK_TEXT_CHANGED + 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, // At guild creation - Set founder + 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_UPDATED = 21, + GE_BANK_MONEY_WITHDRAWN = 22, + GE_BANK_TEXT_CHANGED = 23, + // 24 - error 795 + GE_SIGNED_ON_MOBILE = 25, + GE_SIGNED_Off_MOBILE = 26, }; enum PetitionTurns @@ -142,15 +156,20 @@ enum PetitionTurns PETITION_TURN_OK = 0, PETITION_TURN_ALREADY_IN_GUILD = 2, PETITION_TURN_NEED_MORE_SIGNATURES = 4, + PETITION_TURN_GUILD_PERMISSIONS = 11, + PETITION_TURN_GUILD_NAME_INVALID = 12, }; enum PetitionSigns { - PETITION_SIGN_OK = 0, - PETITION_SIGN_ALREADY_SIGNED = 1, - PETITION_SIGN_ALREADY_IN_GUILD = 2, - PETITION_SIGN_CANT_SIGN_OWN = 3, - PETITION_SIGN_NOT_SERVER = 4, + PETITION_SIGN_OK = 0, + PETITION_SIGN_ALREADY_SIGNED = 1, + PETITION_SIGN_ALREADY_IN_GUILD = 2, + PETITION_SIGN_CANT_SIGN_OWN = 3, + PETITION_SIGN_NOT_SERVER = 4, + PETITION_SIGN_FULL = 5, + PETITION_SIGN_ALREADY_SIGNED_OTHER = 6, + PETITION_SIGN_RESTRICTED_ACCOUNT = 7, }; enum GuildBankRights @@ -173,7 +192,7 @@ enum GuildBankEventLogTypes GUILD_BANK_LOG_REPAIR_MONEY = 6, GUILD_BANK_LOG_MOVE_ITEM2 = 7, GUILD_BANK_LOG_UNK1 = 8, - GUILD_BANK_LOG_UNK2 = 9, + GUILD_BANK_LOG_BUY_SLOT = 9, }; enum GuildEventLogTypes @@ -196,6 +215,17 @@ enum GuildEmblemError ERR_GUILDEMBLEM_INVALIDVENDOR = 5 }; +enum GuildMemberFlags +{ + GUILDMEMBER_STATUS_NONE = 0x0000, + GUILDMEMBER_STATUS_ONLINE = 0x0001, + GUILDMEMBER_STATUS_AFK = 0x0002, + GUILDMEMBER_STATUS_DND = 0x0004, + GUILDMEMBER_STATUS_MOBILE = 0x0008, // remote chat from mobile app +}; + +#define GUILD_REPUTATION_WEEKLY_CAP 4375 + //////////////////////////////////////////////////////////////////////////////////////////// // Emblem info class EmblemInfo @@ -226,7 +256,7 @@ private: struct GuildBankRightsAndSlots { GuildBankRightsAndSlots() : rights(0), slots(0) { } - GuildBankRightsAndSlots(uint8 _rights, uint32 _slots) : rights(_rights), slots(_slots) { } + GuildBankRightsAndSlots(uint32 _rights, uint32 _slots) : rights(_rights), slots(_slots) { } inline bool IsEqual(GuildBankRightsAndSlots const& rhs) const { return rights == rhs.rights && slots == rhs.slots; } void SetGuildMasterValues() @@ -235,7 +265,7 @@ struct GuildBankRightsAndSlots slots = uint32(GUILD_WITHDRAW_SLOT_UNLIMITED); } - uint8 rights; + uint32 rights; uint32 slots; }; typedef std::vector <GuildBankRightsAndSlots> GuildBankRightsAndSlotsVec; @@ -257,7 +287,7 @@ private: }; public: - Member(uint32 guildId, uint64 guid, uint8 rankId) : m_guildId(guildId), m_guid(guid), m_logoutTime(::time(NULL)), m_rankId(rankId) { } + Member(uint32 guildId, uint64 guid, uint32 rankId) : m_guildId(guildId), m_guid(guid), m_logoutTime(::time(NULL)), m_rankId(rankId) { } void SetStats(Player* player); void SetStats(const std::string& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId); @@ -266,14 +296,20 @@ private: void SetPublicNote(const std::string& publicNote); void SetOfficerNote(const std::string& officerNote); + std::string GetPublicNote() { return m_publicNote; }; + std::string GetOfficerNote() { return m_officerNote; }; + bool LoadFromDB(Field* fields); void SaveToDB(SQLTransaction& trans) const; - void WritePacket(WorldPacket& data) const; uint64 GetGUID() const { return m_guid; } std::string GetName() const { return m_name; } uint32 GetAccountId() const { return m_accountId; } - uint8 GetRankId() const { return m_rankId; } + uint32 GetRankId() const { return m_rankId; } + uint8 GetClass() const { return m_class; } + uint8 GetLevel() const { return m_level; } + uint8 GetZone() const { return m_zoneId; } + uint64 GetLogoutTime() const { return m_logoutTime; } void ChangeRank(uint8 newRank); @@ -290,6 +326,8 @@ private: inline Player* FindPlayer() const { return ObjectAccessor::FindPlayer(m_guid); } + uint32 GetRemainingWeeklyReputation() const { return 0; } + private: uint32 m_guildId; // Fields from characters table @@ -301,7 +339,7 @@ private: uint64 m_logoutTime; uint32 m_accountId; // Fields from guild_member table - uint8 m_rankId; + uint32 m_rankId; std::string m_publicNote; std::string m_officerNote; @@ -409,19 +447,18 @@ private: uint32 m_nextGUID; }; - // Class incapsulating guild rank data + // Class encapsulating guild rank data class RankInfo { public: RankInfo(uint32 guildId) : m_guildId(guildId), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { } - RankInfo(uint32 guildId, uint8 rankId, const std::string& name, uint32 rights, uint32 money) : + RankInfo(uint32 guildId, uint32 rankId, const std::string& name, uint32 rights, uint32 money) : m_guildId(guildId), m_rankId(rankId), m_name(name), m_rights(rights), m_bankMoneyPerDay(money) { } void LoadFromDB(Field* fields); void SaveToDB(SQLTransaction& trans) const; - void WritePacket(WorldPacket& data) const; - uint8 GetId() const { return m_rankId; } + uint32 GetId() const { return m_rankId; } std::string GetName() const { return m_name; } void SetName(const std::string& name); @@ -429,10 +466,13 @@ private: uint32 GetRights() const { return m_rights; } void SetRights(uint32 rights); + bool operator < (const RankInfo& rank) const { return m_rights > rank.GetRights(); } + bool operator == (const RankInfo& rank) const { return m_rights == rank.GetRights(); } + uint32 GetBankMoneyPerDay() const { return m_rankId == GR_GUILDMASTER ? GUILD_WITHDRAW_MONEY_UNLIMITED : m_bankMoneyPerDay; } void SetBankMoneyPerDay(uint32 money); - inline uint8 GetBankTabRights(uint8 tabId) const { return tabId < GUILD_BANK_MAX_TABS ? m_bankTabRightsAndSlots[tabId].rights : 0; } + inline uint32 GetBankTabRights(uint8 tabId) const { return tabId < GUILD_BANK_MAX_TABS ? m_bankTabRightsAndSlots[tabId].rights : 0; } inline uint32 GetBankTabSlotsPerDay(uint8 tabId) const { if (tabId < GUILD_BANK_MAX_TABS) @@ -443,8 +483,7 @@ private: private: uint32 m_guildId; - - uint8 m_rankId; + uint32 m_rankId; std::string m_name; uint32 m_rights; uint32 m_bankMoneyPerDay; @@ -463,18 +502,14 @@ private: bool LoadItemFromDB(Field* fields); void Delete(SQLTransaction& trans, bool removeItemsFromDB = false); - void WritePacket(WorldPacket& data) const; - void WriteSlotPacket(WorldPacket& data, uint8 slotId) const; - void WriteInfoPacket(WorldPacket& data) const - { - data << m_name; - data << m_icon; - } - void SetInfo(const std::string& name, const std::string& icon); void SetText(const std::string& text); void SendText(const Guild* 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); @@ -588,8 +623,11 @@ public: bool Create(Player* pLeader, const std::string& 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; } const std::string& GetName() const { return m_name; } const std::string& GetMOTD() const { return m_motd; } @@ -598,36 +636,38 @@ public: // Handle client commands void HandleRoster(WorldSession* session = NULL); // NULL = broadcast void HandleQuery(WorldSession* session); + void HandleGuildRanks(WorldSession* session) const; void HandleSetMOTD(WorldSession* session, const std::string& motd); void HandleSetInfo(WorldSession* session, const std::string& info); void HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo); void HandleSetLeader(WorldSession* session, const std::string& name); void HandleSetBankTabInfo(WorldSession* session, uint8 tabId, const std::string& name, const std::string& icon); - void HandleSetMemberNote(WorldSession* session, const std::string& name, const std::string& note, bool officer); - void HandleSetRankInfo(WorldSession* session, uint8 rankId, const std::string& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots); + void HandleSetMemberNote(WorldSession* session, std::string const& note, uint64 guid, bool isPublic); + void HandleSetRankInfo(WorldSession* session, uint32 rankId, const std::string& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots); void HandleBuyBankTab(WorldSession* session, uint8 tabId); void HandleInviteMember(WorldSession* session, const std::string& name); void HandleAcceptMember(WorldSession* session); void HandleLeaveMember(WorldSession* session); - void HandleRemoveMember(WorldSession* session, const std::string& name); - void HandleUpdateMemberRank(WorldSession* session, const std::string& name, bool demote); + void HandleRemoveMember(WorldSession* session, uint64 guid); + void HandleUpdateMemberRank(WorldSession* session, uint64 targetGuid, bool demote); + void HandleSetMemberRank(WorldSession* session, uint64 targetGuid, uint64 setterGuid, uint32 rank); void HandleAddNewRank(WorldSession* session, const std::string& name); - void HandleRemoveLowestRank(WorldSession* session); + void HandleRemoveRank(WorldSession* session, uint32 rankId); void HandleMemberDepositMoney(WorldSession* session, uint32 amount); bool HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair = false); void HandleMemberLogout(WorldSession* session); void HandleDisband(WorldSession* session); + void HandleGuildPartyRequest(WorldSession* session); // Send info to client - void SendInfo(WorldSession* session) const; void SendEventLog(WorldSession* session) const; void SendBankLog(WorldSession* session, uint8 tabId) const; - void SendBankTabsInfo(WorldSession* session) const; - void SendBankTabData(WorldSession* session, uint8 tabId) const; + void SendBankList(WorldSession* session, uint8 tabId, bool withContent, bool withTabInfo) const; void SendBankTabText(WorldSession* session, uint8 tabId) const; void SendPermissions(WorldSession* session) const; void SendMoneyInfo(WorldSession* session) const; void SendLoginInfo(WorldSession* session) const; + void SendGuildReputationWeeklyCap(WorldSession* session) const; // Load from DB bool LoadFromDB(Field* fields); @@ -642,6 +682,7 @@ public: // Broadcasts void BroadcastToGuild(WorldSession* session, bool officerOnly, const std::string& msg, uint32 language = LANG_UNIVERSAL) const; + void BroadcastAddonToGuild(WorldSession* session, bool officerOnly, const std::string& msg, const std::string& prefix) const; void BroadcastPacketToRank(WorldPacket* packet, uint8 rankId) const; void BroadcastPacket(WorldPacket* packet) const; @@ -659,6 +700,7 @@ public: bool AddMember(uint64 guid, uint8 rankId = GUILD_RANK_NONE); void DeleteMember(uint64 guid, bool isDisbanding = false, bool isKicked = false); bool ChangeMemberRank(uint64 guid, uint8 newRank); + bool IsMember(uint64 guid); // Bank void SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount); @@ -667,6 +709,11 @@ public: // Bank tabs void SetBankTabText(uint8 tabId, const std::string& text); + AchievementMgr<Guild>& GetAchievementMgr() { return m_achievementMgr; } + AchievementMgr<Guild> const& GetAchievementMgr() const { return m_achievementMgr; } + + uint32 GetLevel() const { return m_level; } + protected: uint32 m_id; std::string m_name; @@ -687,12 +734,16 @@ protected: LogHolder* m_eventLog; LogHolder* m_bankEventLog[GUILD_BANK_MAX_TABS + 1]; + AchievementMgr<Guild> m_achievementMgr; + + uint32 m_level; + 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 uint32 _GetRanksSize() const { return uint32(m_ranks.size()); } + inline const RankInfo* GetRankInfo(uint32 rankId) const { return rankId < _GetRanksSize() ? &m_ranks[rankId] : NULL; } + inline RankInfo* GetRankInfo(uint32 rankId) { return rankId < _GetRanksSize() ? &m_ranks[rankId] : NULL; } inline bool _HasRankRight(Player* player, uint32 right) const { return (_GetRankRights(player->GetRank()) & right) != GR_RIGHT_EMPTY; } - inline uint8 _GetLowestRankId() const { return uint8(m_ranks.size() - 1); } + inline uint32 _GetLowestRankId() const { return uint32(m_ranks.size() - 1); } inline uint8 _GetPurchasedTabsSize() const { return uint8(m_bankTabs.size()); } inline BankTab* GetBankTab(uint8 tabId) { return tabId < m_bankTabs.size() ? m_bankTabs[tabId] : NULL; } @@ -739,13 +790,13 @@ private: bool _ModifyBankMoney(SQLTransaction& trans, uint64 amount, bool add); void _SetLeaderGUID(Member* pLeader); - void _SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay); - void _SetRankBankTabRightsAndSlots(uint8 rankId, uint8 tabId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB = true); - uint8 _GetRankBankTabRights(uint8 rankId, uint8 tabId) const; - uint32 _GetRankRights(uint8 rankId) const; - uint32 _GetRankBankMoneyPerDay(uint8 rankId) const; - uint32 _GetRankBankTabSlotsPerDay(uint8 rankId, uint8 tabId) const; - std::string _GetRankName(uint8 rankId) const; + void _SetRankBankMoneyPerDay(uint32 rankId, uint32 moneyPerDay); + void _SetRankBankTabRightsAndSlots(uint32 rankId, uint8 tabId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB = true); + uint32 _GetRankBankTabRights(uint32 rankId, uint8 tabId) const; + uint32 _GetRankRights(uint32 rankId) const; + uint32 _GetRankBankMoneyPerDay(uint32 rankId) const; + uint32 _GetRankBankTabSlotsPerDay(uint32 rankId, uint8 tabId) const; + std::string _GetRankName(uint32 rankId) const; uint32 _GetMemberRemainingSlots(uint64 guid, uint8 tabId) const; uint32 _GetMemberRemainingMoney(uint64 guid) const; @@ -760,11 +811,11 @@ 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 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; }; #endif diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp index cebcf6040f9..04b0cfeaa39 100644 --- a/src/server/game/Guilds/GuildMgr.cpp +++ b/src/server/game/Guilds/GuildMgr.cpp @@ -39,6 +39,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) @@ -59,6 +65,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)) + if (uint32 guildId = GUID_LOPART(guid)) + return GetGuildById(guildId); + + return NULL; +} + Guild* GuildMgr::GetGuildByName(const std::string& guildName) const { std::string search = guildName; @@ -174,12 +191,14 @@ 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"); // 0 1 2 3 4 5 6 - QueryResult result = CharacterDatabase.Query("SELECT guildid, gm.guid, rank, pnote, offnote, BankResetTimeMoney, BankRemMoney, " + QueryResult result = CharacterDatabase.Query("SELECT gm.guildid, gm.guid, rank, pnote, offnote, BankResetTimeMoney, BankRemMoney, " // 7 8 9 10 11 12 "BankResetTimeTab0, BankRemSlotsTab0, BankResetTimeTab1, BankRemSlotsTab1, BankResetTimeTab2, BankRemSlotsTab2, " // 13 14 15 16 17 18 "BankResetTimeTab3, BankRemSlotsTab3, BankResetTimeTab4, BankRemSlotsTab4, BankResetTimeTab5, BankRemSlotsTab5, " - // 19 20 21 22 23 24 + // 19 20 21 22 + "BankResetTimeTab6, BankRemSlotsTab6, BankResetTimeTab7, BankRemSlotsTab7, " + // 23 24 25 26 27 28 "c.name, c.level, c.class, c.zone, c.account, c.logout_time " "FROM guild_member gm LEFT JOIN characters c ON c.guid = gm.guid ORDER BY guildid ASC"); @@ -378,8 +397,25 @@ void GuildMgr::LoadGuilds() } } - // 9. Validate loaded guild data - sLog->outInfo(LOG_FILTER_GUILD, "Validating data of loaded guilds..."); + // 9. 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); + } + } + + // 10. Validate loaded guild data + sLog->outInfo(LOG_FILTER_GENERAL, "Validating data of loaded guilds..."); { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/Guilds/GuildMgr.h b/src/server/game/Guilds/GuildMgr.h index 9654fced227..4b999c9231a 100644 --- a/src/server/game/Guilds/GuildMgr.h +++ b/src/server/game/Guilds/GuildMgr.h @@ -32,6 +32,7 @@ public: Guild* GetGuildByLeader(uint64 guid) const; Guild* GetGuildById(uint32 guildId) const; + Guild* GetGuildByGuid(uint64 guid) const; Guild* GetGuildByName(const std::string& guildName) const; std::string GetGuildNameById(uint32 guildId) const; @@ -39,6 +40,8 @@ public: void AddGuild(Guild* guild); void RemoveGuild(uint32 guildId); + void SaveGuilds(); + uint32 GenerateGuildId(); void SetNextGuildId(uint32 Id) { NextGuildId = Id; } diff --git a/src/server/game/Handlers/ArenaTeamHandler.cpp b/src/server/game/Handlers/ArenaTeamHandler.cpp index 8fb820713ce..27ec8433fe1 100755 --- a/src/server/game/Handlers/ArenaTeamHandler.cpp +++ b/src/server/game/Handlers/ArenaTeamHandler.cpp @@ -152,7 +152,7 @@ void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket & recvData) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_ARENA_TEAM_INVITE"); } -void WorldSession::HandleArenaTeamAcceptOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleArenaTeamAcceptOpcode(WorldPacket & /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ARENA_TEAM_ACCEPT"); // empty opcode @@ -185,7 +185,7 @@ void WorldSession::HandleArenaTeamAcceptOpcode(WorldPacket & /*recv_data*/) arenaTeam->BroadcastEvent(ERR_ARENA_TEAM_JOIN_SS, _player->GetGUID(), 2, _player->GetName(), arenaTeam->GetName(), ""); } -void WorldSession::HandleArenaTeamDeclineOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleArenaTeamDeclineOpcode(WorldPacket & /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ARENA_TEAM_DECLINE"); // empty opcode @@ -348,20 +348,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 2ebcbce0661..3e2d0e1310a 100755..100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -33,10 +33,10 @@ //post-incrementation is always slower than pre-incrementation ! //void called when player click on auctioneer npc -void WorldSession::HandleAuctionHelloOpcode(WorldPacket & recv_data) +void WorldSession::HandleAuctionHelloOpcode(WorldPacket& recvData) { uint64 guid; //NPC guid - recv_data >> guid; + recvData >> guid; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_AUCTIONEER); if (!unit) @@ -73,74 +73,98 @@ 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); } //this function sends notification, if bidder is online -void WorldSession::SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template) +void WorldSession::SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 itemEntry) { WorldPacket data(SMSG_AUCTION_BIDDER_NOTIFICATION, (8*4)); data << uint32(location); data << uint32(auctionId); data << uint64(bidder); - data << uint32(bidSum); - data << uint32(diff); - data << uint32(item_template); + 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 << uint32(auction->item_template); - data << uint32(0); //unk - data << float(0); //unk (time?) + data << uint64(auction->bid); + data << uint64(0); //unk + data << uint64(0); //unk + data << uint32(auction->itemEntry); + 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 & recv_data) +void WorldSession::HandleAuctionSellItem(WorldPacket & recvData) { - uint64 auctioneer; - uint32 itemsCount, etime, bid, buyout; - recv_data >> auctioneer; - recv_data >> itemsCount; + uint64 auctioneer, bid, buyout; + uint32 itemsCount, etime; + recvData >> auctioneer; + recvData >> itemsCount; uint64 itemGUIDs[MAX_AUCTION_ITEMS]; // 160 slot = 4x 36 slot bag + backpack 16 slot uint32 count[MAX_AUCTION_ITEMS]; if (itemsCount > MAX_AUCTION_ITEMS) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } for (uint32 i = 0; i < itemsCount; ++i) { - recv_data >> itemGUIDs[i]; - recv_data >> count[i]; + recvData >> itemGUIDs[i]; + recvData >> count[i]; if (!itemGUIDs[i] || !count[i] || count[i] > 1000 ) return; } - recv_data >> bid; - recv_data >> buyout; - recv_data >> etime; + recvData >> bid; + recvData >> buyout; + recvData >> etime; if (!bid || !etime) return; @@ -184,7 +208,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) if (!item) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); + SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_ITEM_NOT_FOUND); return; } @@ -192,7 +216,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) || item->GetCount() < count[i]) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } @@ -202,7 +226,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) if (!finalCount) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } @@ -212,7 +236,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) if (item->GetMaxStackCount() < finalCount) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } } @@ -225,9 +249,9 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) 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, AUCTION_NOT_ENOUGHT_MONEY); + SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_NOT_ENOUGHT_MONEY); return; } @@ -250,8 +274,8 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) GetPlayerName().c_str(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount()); } - AH->item_guidlow = item->GetGUIDLow(); - AH->item_template = item->GetEntry(); + AH->itemGUIDLow = item->GetGUIDLow(); + AH->itemEntry = item->GetEntry(); AH->itemCount = item->GetCount(); AH->owner = _player->GetGUIDLow(); AH->startbid = bid; @@ -275,9 +299,9 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) _player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); - SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); + SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK); - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); + GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); return; } else // Required stack size of auction does not match to current item stack size, clone item and set correct stack size @@ -286,7 +310,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) if (!newItem) { sLog->outError(LOG_FILTER_NETWORKIO, "CMSG_AUCTION_SELL_ITEM: Could not create clone of item %u", item->GetEntry()); - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } @@ -296,8 +320,8 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) GetPlayerName().c_str(), GetAccountId(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetCount()); } - AH->item_guidlow = newItem->GetGUIDLow(); - AH->item_template = newItem->GetEntry(); + AH->itemGUIDLow = newItem->GetGUIDLow(); + AH->itemEntry = newItem->GetEntry(); AH->itemCount = newItem->GetCount(); AH->owner = _player->GetGUIDLow(); AH->startbid = bid; @@ -345,27 +369,28 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) _player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); - SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); + SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK); - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); + GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); return; } } } -//this function is called when client bids or buys out auction -void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) +// this function is called when client bids or buys out auction +void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_PLACE_BID"); uint64 auctioneer; uint32 auctionId; - uint32 price; - recv_data >> auctioneer; - recv_data >> auctionId >> price; + uint64 price; + recvData >> auctioneer; + 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) @@ -386,18 +411,18 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) if (!auction || auction->owner == player->GetGUIDLow()) { //you cannot bid your own auction: - SendAuctionCommandResult(0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR); + 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, CANNOT_BID_YOUR_AUCTION_ERROR); + SendAuctionCommandResult(NULL, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN); return; - } + }*/ // cheating if (price <= auction->bid || price < auction->startbid) @@ -407,14 +432,15 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) 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; } @@ -425,20 +451,20 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) 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; - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); + GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_AUCTION_BID); stmt->setUInt32(0, auction->bidder); @@ -446,50 +472,49 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) stmt->setUInt32(2, auction->Id); trans->Append(stmt); - SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, 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); } auction->bidder = player->GetGUIDLow(); auction->bid = auction->buyout; - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); + GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); //- Mails must be under transaction control too to prevent data loss sAuctionMgr->SendAuctionSalePendingMail(auction, trans); sAuctionMgr->SendAuctionSuccessfulMail(auction, trans); sAuctionMgr->SendAuctionWonMail(auction, trans); - SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); + SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_OK); auction->DeleteFromDB(trans); - uint32 item_template = auction->item_template; - sAuctionMgr->RemoveAItem(auction->item_guidlow); - auctionHouse->RemoveAuction(auction, item_template); + uint32 itemEntry = auction->itemEntry; + sAuctionMgr->RemoveAItem(auction->itemGUIDLow); + auctionHouse->RemoveAuction(auction, itemEntry); } player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); } //this void is called when auction_owner cancels his auction -void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) +void WorldSession::HandleAuctionRemoveItem(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_REMOVE_ITEM"); uint64 auctioneer; uint32 auctionId; - recv_data >> auctioneer; - recv_data >> auctionId; - //sLog->outDebug("Cancel AUCTION AuctionID: %u", auctionId); + recvData >> auctioneer; + recvData >> auctionId; Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) @@ -510,17 +535,16 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (auction && auction->owner == player->GetGUIDLow()) { - Item* pItem = sAuctionMgr->GetAItem(auction->item_guidlow); + Item* pItem = sAuctionMgr->GetAItem(auction->itemGUIDLow); if (pItem) { 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 @@ -530,21 +554,21 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) } else { - sLog->outError(LOG_FILTER_NETWORKIO, "Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->item_guidlow); - SendAuctionCommandResult(0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR); + sLog->outError(LOG_FILTER_NETWORKIO, "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, AUCTION_INTERNAL_ERROR); + SendAuctionCommandResult(NULL, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR); //this code isn't possible ... maybe there should be assert - sLog->outError(LOG_FILTER_NETWORKIO, "CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", player->GetGUIDLow(), auctionId); + sLog->outError(LOG_FILTER_NETWORKIO, "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, AUCTION_OK); + SendAuctionCommandResult(auction, AUCTION_CANCEL, ERR_AUCTION_OK); // Now remove the auction @@ -552,13 +576,13 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) auction->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); - uint32 item_template = auction->item_template; - sAuctionMgr->RemoveAItem(auction->item_guidlow); - auctionHouse->RemoveAuction(auction, item_template); + uint32 itemEntry = auction->itemEntry; + sAuctionMgr->RemoveAItem(auction->itemGUIDLow); + auctionHouse->RemoveAuction(auction, itemEntry); } //called when player lists his bids -void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data) +void WorldSession::HandleAuctionListBidderItems(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_BIDDER_ITEMS"); @@ -566,12 +590,12 @@ void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data) uint32 listfrom; //page of auctions uint32 outbiddedCount; //count of outbidded auctions - recv_data >> guid; - recv_data >> listfrom; // not used in fact (this list not have page control in client) - recv_data >> outbiddedCount; - if (recv_data.size() != (16 + outbiddedCount * 4)) + recvData >> guid; + recvData >> listfrom; // not used in fact (this list not have page control in client) + recvData >> outbiddedCount; + if (recvData.size() != (16 + outbiddedCount * 4)) { - sLog->outError(LOG_FILTER_NETWORKIO, "Client sent bad opcode!!! with count: %u and size : %lu (must be: %u)", outbiddedCount, (unsigned long)recv_data.size(), (16 + outbiddedCount * 4)); + sLog->outError(LOG_FILTER_NETWORKIO, "Client sent bad opcode!!! with count: %u and size : %lu (must be: %u)", outbiddedCount, (unsigned long)recvData.size(), (16 + outbiddedCount * 4)); outbiddedCount = 0; } @@ -579,7 +603,7 @@ void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data) if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionListBidderItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - recv_data.rfinish(); + recvData.rfinish(); return; } @@ -591,14 +615,14 @@ void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data) 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 { --outbiddedCount; uint32 outbiddedAuctionId; - recv_data >> outbiddedAuctionId; + recvData >> outbiddedAuctionId; AuctionEntry* auction = auctionHouse->GetAuction(outbiddedAuctionId); if (auction && auction->BuildAuctionInfo(data)) { @@ -610,20 +634,20 @@ void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data) 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); } //this void sends player info about his auctions -void WorldSession::HandleAuctionListOwnerItems(WorldPacket & recv_data) +void WorldSession::HandleAuctionListOwnerItems(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_OWNER_ITEMS"); uint32 listfrom; uint64 guid; - recv_data >> guid; - recv_data >> listfrom; // not used in fact (this list not have page control in client) + recvData >> guid; + recvData >> listfrom; // not used in fact (this list not have page control in client) Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) @@ -639,20 +663,20 @@ void WorldSession::HandleAuctionListOwnerItems(WorldPacket & recv_data) 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); } //this void is called when player clicks on search button -void WorldSession::HandleAuctionListItems(WorldPacket & recv_data) +void WorldSession::HandleAuctionListItems(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_ITEMS"); @@ -661,24 +685,20 @@ void WorldSession::HandleAuctionListItems(WorldPacket & recv_data) uint32 listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality; uint64 guid; - recv_data >> guid; - recv_data >> listfrom; // start, used for page control listing by 50 elements - recv_data >> searchedname; + recvData >> guid; + recvData >> listfrom; // start, used for page control listing by 50 elements + recvData >> searchedname; - recv_data >> levelmin >> levelmax; - recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory; - recv_data >> quality >> usable; + recvData >> levelmin >> levelmax; + recvData >> auctionSlotID >> auctionMainCategory >> auctionSubCategory; + recvData >> quality >> usable; - recv_data.read_skip<uint8>(); // unk + recvData.read_skip<uint8>(); // unk + recvData.read_skip<uint8>(); // unk // this block looks like it uses some lame byte packing or similar... - uint8 unkCnt; - recv_data >> unkCnt; - for (uint8 i = 0; i < unkCnt; i++) - { - recv_data.read_skip<uint8>(); - recv_data.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) @@ -693,13 +713,13 @@ void WorldSession::HandleAuctionListItems(WorldPacket & recv_data) AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); - //sLog->outDebug("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", + //sLog->outDebug(LOG_FILTER_GENERAL, "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; @@ -714,16 +734,16 @@ void WorldSession::HandleAuctionListItems(WorldPacket & recv_data) 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); } -void WorldSession::HandleAuctionListPendingSales(WorldPacket & recv_data) +void WorldSession::HandleAuctionListPendingSales(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_PENDING_SALES"); - recv_data.read_skip<uint64>(); + recvData.read_skip<uint64>(); uint32 count = 0; @@ -733,7 +753,7 @@ void WorldSession::HandleAuctionListPendingSales(WorldPacket & recv_data) { 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 49027bdf497..5085bb15584 100755 --- 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 475c1c42fca..d1da504008e 100755 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -35,10 +35,10 @@ #include "DisableMgr.h" #include "Group.h" -void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket & recv_data) +void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket & recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid))); Creature* unit = GetPlayer()->GetMap()->GetCreature(guid); @@ -66,11 +66,11 @@ void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket & recv_data) 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 & recv_data) +void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket & recvData) { uint64 guid; uint32 bgTypeId_; @@ -79,10 +79,10 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket & recv_data) bool isPremade = false; Group* grp = NULL; - recv_data >> guid; // battlemaster guid - recv_data >> bgTypeId_; // battleground type id (DBC id) - recv_data >> instanceId; // instance id, 0 if First Available selected - recv_data >> joinAsGroup; // join as group + 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 if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { @@ -244,7 +244,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket & recv_data) sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); } -void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket & /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message"); @@ -290,7 +290,7 @@ void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket & /*recv_ SendPacket(&data); } -void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd MSG_PVP_LOG_DATA Message"); @@ -309,18 +309,12 @@ void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recv_data*/) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent MSG_PVP_LOG_DATA Message"); } -void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recv_data) +void WorldSession::HandleBattlefieldListOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEFIELD_LIST Message"); uint32 bgTypeId; - recv_data >> bgTypeId; // id from DBC - - uint8 fromWhere; - recv_data >> fromWhere; // 0 - battlemaster (lua: ShowBattlefieldList), 1 - UI (lua: RequestBattlegroundInstanceInfo) - - uint8 unk1; - recv_data >> unk1; // Unknown 3.2.2 + recvData >> bgTypeId; // id from DBC BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); if (!bl) @@ -330,11 +324,11 @@ void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recv_data) } WorldPacket data; - sBattlegroundMgr->BuildBattlegroundListPacket(&data, 0, _player, BattlegroundTypeId(bgTypeId), fromWhere); + sBattlegroundMgr->BuildBattlegroundListPacket(&data, 0, _player, BattlegroundTypeId(bgTypeId)); SendPacket(&data); } -void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recv_data) +void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); @@ -344,7 +338,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recv_data) uint16 unk; // 0x1F90 constant? uint8 action; // enter battle 0x1, leave queue 0x0 - recv_data >> type >> unk2 >> bgTypeId_ >> unk >> action; + recvData >> type >> unk2 >> bgTypeId_ >> unk >> action; if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { @@ -483,14 +477,14 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recv_data) } } -void WorldSession::HandleLeaveBattlefieldOpcode(WorldPacket& recv_data) +void WorldSession::HandleLeaveBattlefieldOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message"); - recv_data.read_skip<uint8>(); // unk1 - recv_data.read_skip<uint8>(); // unk2 - recv_data.read_skip<uint32>(); // BattlegroundTypeId - recv_data.read_skip<uint16>(); // unk3 + recvData.read_skip<uint8>(); // unk1 + recvData.read_skip<uint8>(); // unk2 + recvData.read_skip<uint32>(); // BattlegroundTypeId + recvData.read_skip<uint16>(); // unk3 // not allow leave battleground in combat if (_player->isInCombat()) @@ -501,7 +495,7 @@ void WorldSession::HandleLeaveBattlefieldOpcode(WorldPacket& recv_data) _player->LeaveBattleground(); } -void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/) { // empty opcode sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Battleground status"); @@ -565,7 +559,7 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recv_data*/) } } -void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recv_data) +void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); @@ -575,7 +569,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recv_data) uint8 isRated; // isRated Group* grp = NULL; - recv_data >> guid >> arenaslot >> asGroup >> isRated; + recvData >> guid >> arenaslot >> asGroup >> isRated; // ignore if we already in BG or BG queue if (_player->InBattleground()) @@ -733,10 +727,10 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recv_data) sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); } -void WorldSession::HandleReportPvPAFK(WorldPacket & recv_data) +void WorldSession::HandleReportPvPAFK(WorldPacket & recvData) { uint64 playerGuid; - recv_data >> playerGuid; + recvData >> playerGuid; Player* reportedPlayer = ObjectAccessor::FindPlayer(playerGuid); if (!reportedPlayer) diff --git a/src/server/game/Handlers/ChannelHandler.cpp b/src/server/game/Handlers/ChannelHandler.cpp index 9b749fa8005..1fb0f8a2f32 100755 --- a/src/server/game/Handlers/ChannelHandler.cpp +++ b/src/server/game/Handlers/ChannelHandler.cpp @@ -23,18 +23,21 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - uint32 channel_id; - uint8 unknown1, unknown2; - std::string channelname, pass; - - recvPacket >> channel_id; - recvPacket >> unknown1 >> unknown2; - recvPacket >> channelname; - recvPacket >> pass; - - if (channel_id) + uint32 channelId; + uint32 channelLength, passLength; + std::string channelName, pass; + + recvPacket >> channelId; + recvPacket.ReadBit(); // unknowns + recvPacket.ReadBit(); + channelLength = recvPacket.ReadBits(8); + passLength = recvPacket.ReadBits(8); + channelName = recvPacket.ReadString(channelLength); + pass = recvPacket.ReadString(passLength); + + if (channelId) { - ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(channel_id); + ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(channelId); if (!channel) return; @@ -46,13 +49,13 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) return; } - if (channelname.empty()) + if (channelName.empty()) return; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) { cMgr->team = _player->GetTeam(); - if (Channel* chn = cMgr->GetJoinChannel(channelname, channel_id)) + if (Channel* chn = cMgr->GetJoinChannel(channelName, channelId)) chn->Join(_player->GetGUID(), pass.c_str()); } } @@ -64,7 +67,8 @@ void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket) uint32 unk; std::string channelname; recvPacket >> unk; // channel id? - recvPacket >> channelname; + uint32 length = recvPacket.ReadBits(8); + channelname = recvPacket.ReadString(length); if (channelname.empty()) return; @@ -80,8 +84,9 @@ void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket) void WorldSession::HandleChannelList(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname; - recvPacket >> channelname; + + uint32 length = recvPacket.ReadBits(8); + std::string channelname = recvPacket.ReadString(length); if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channelname, _player)) @@ -91,10 +96,11 @@ void WorldSession::HandleChannelList(WorldPacket& recvPacket) void WorldSession::HandleChannelPassword(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, pass; - recvPacket >> channelname; + uint32 nameLength = recvPacket.ReadBits(8); + uint32 passLength = recvPacket.ReadBits(7); - recvPacket >> pass; + std::string channelname = recvPacket.ReadString(nameLength); + std::string pass = recvPacket.ReadString(passLength); if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channelname, _player)) @@ -104,10 +110,12 @@ void WorldSession::HandleChannelPassword(WorldPacket& recvPacket) void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, newp; - recvPacket >> channelname; - recvPacket >> newp; + uint32 channelLength = recvPacket.ReadBits(8); + uint32 nameLength = recvPacket.ReadBits(7); + + std::string newp = recvPacket.ReadString(nameLength); + std::string channelname = recvPacket.ReadString(channelLength); if (!normalizePlayerName(newp)) return; @@ -120,8 +128,9 @@ void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket) void WorldSession::HandleChannelOwner(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname; - recvPacket >> channelname; + uint32 length = recvPacket.ReadBits(8); + std::string channelname = recvPacket.ReadString(length); + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channelname, _player)) chn->SendWhoOwner(_player->GetGUID()); @@ -130,10 +139,12 @@ void WorldSession::HandleChannelOwner(WorldPacket& recvPacket) void WorldSession::HandleChannelModerator(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; - recvPacket >> otp; + uint32 channelLength = recvPacket.ReadBits(8); + uint32 nameLength = recvPacket.ReadBits(7); + + std::string otp = recvPacket.ReadString(nameLength); + std::string channelname = recvPacket.ReadString(channelLength); if (!normalizePlayerName(otp)) return; @@ -146,10 +157,12 @@ void WorldSession::HandleChannelModerator(WorldPacket& recvPacket) void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; - recvPacket >> otp; + uint32 nameLength = recvPacket.ReadBits(7); + uint32 channelLength = recvPacket.ReadBits(8); + + std::string channelname = recvPacket.ReadString(channelLength); + std::string otp = recvPacket.ReadString(nameLength); if (!normalizePlayerName(otp)) return; @@ -162,10 +175,11 @@ void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket) void WorldSession::HandleChannelMute(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; + uint32 channelLength = recvPacket.ReadBits(8); + uint32 nameLength = recvPacket.ReadBits(7); - recvPacket >> otp; + std::string channelname = recvPacket.ReadString(channelLength); + std::string otp = recvPacket.ReadString(nameLength); if (!normalizePlayerName(otp)) return; @@ -179,10 +193,11 @@ void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; + uint32 nameLength = recvPacket.ReadBits(8); + uint32 channelLength = recvPacket.ReadBits(7); - recvPacket >> otp; + std::string otp = recvPacket.ReadString(nameLength); + std::string channelname = recvPacket.ReadString(channelLength); if (!normalizePlayerName(otp)) return; @@ -195,10 +210,11 @@ void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket) void WorldSession::HandleChannelInvite(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; + uint32 nameLength = recvPacket.ReadBits(7); + uint32 channelLength = recvPacket.ReadBits(8); - recvPacket >> otp; + std::string otp = recvPacket.ReadString(nameLength); + std::string channelname = recvPacket.ReadString(channelLength); if (!normalizePlayerName(otp)) return; @@ -211,10 +227,12 @@ void WorldSession::HandleChannelInvite(WorldPacket& recvPacket) void WorldSession::HandleChannelKick(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; + uint32 channelLength = recvPacket.ReadBits(8); + uint32 nameLength = recvPacket.ReadBits(7); + + std::string channelname = recvPacket.ReadString(channelLength); + std::string otp = recvPacket.ReadString(nameLength); - recvPacket >> otp; if (!normalizePlayerName(otp)) return; @@ -226,10 +244,14 @@ void WorldSession::HandleChannelKick(WorldPacket& recvPacket) void WorldSession::HandleChannelBan(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); + uint32 channelLength, nameLength; std::string channelname, otp; - recvPacket >> channelname; - recvPacket >> otp; + channelLength = recvPacket.ReadBits(8); + nameLength = recvPacket.ReadBits(7); + + otp = recvPacket.ReadString(nameLength); + channelname = recvPacket.ReadString(channelLength); if (!normalizePlayerName(otp)) return; @@ -243,10 +265,11 @@ void WorldSession::HandleChannelUnban(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; + uint32 channelLength = recvPacket.ReadBits(7); + uint32 nameLength = recvPacket.ReadBits(8); - recvPacket >> otp; + std::string otp = recvPacket.ReadString(nameLength); + std::string channelname = recvPacket.ReadString(channelLength); if (!normalizePlayerName(otp)) return; @@ -259,8 +282,10 @@ void WorldSession::HandleChannelUnban(WorldPacket& recvPacket) void WorldSession::HandleChannelAnnouncements(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname; - recvPacket >> channelname; + + uint32 length = recvPacket.ReadBits(8); + std::string channelname = recvPacket.ReadString(length); + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channelname, _player)) chn->Announce(_player->GetGUID()); @@ -290,13 +315,13 @@ void WorldSession::HandleGetChannelMemberCount(WorldPacket &recvPacket) } } -void WorldSession::HandleSetChannelWatch(WorldPacket &recvPacket) +void WorldSession::HandleSetChannelWatch(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); std::string channelname; recvPacket >> channelname; /*if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) + if (Channel* chn = cMgr->GetChannel(channelName, _player)) chn->JoinNotify(_player->GetGUID());*/ } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 8544266840f..649f09ad212 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -26,7 +26,6 @@ #include "WorldPacket.h" #include "WorldSession.h" #include "DatabaseEnv.h" - #include "ArenaTeam.h" #include "Chat.h" #include "Group.h" @@ -43,6 +42,7 @@ #include "ScriptMgr.h" #include "Battleground.h" #include "AccountMgr.h" +#include "DBCStores.h" #include "LFGMgr.h" class LoginQueryHolder : public SQLQueryHolder @@ -110,6 +110,10 @@ bool LoginQueryHolder::Initialize() stmt->setUInt32(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADINVENTORY, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_VOID_STORAGE); + stmt->setUInt32(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADVOIDSTORAGE, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS); stmt->setUInt32(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADACTIONS, stmt); @@ -203,34 +207,47 @@ bool LoginQueryHolder::Initialize() 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; - - _allowedCharsToLogin.clear(); + bitBuffer.WriteBits(0, 23); + bitBuffer.WriteBit(1); if (result) { + _allowedCharsToLogin.clear(); + + charCount = uint32(result->GetRowCount()); + bitBuffer.reserve(24 * charCount / 8); + dataBuffer.reserve(charCount * 381); + + bitBuffer.WriteBits(charCount, 17); + do { - uint32 guidlow = (*result)[0].GetUInt32(); - sLog->outInfo(LOG_FILTER_NETWORKIO, "Loading char guid %u from account %u.", guidlow, GetAccountId()); - if (Player::BuildEnumData(result, &data)) - { - _allowedCharsToLogin.insert(guidlow); - ++num; - } - } - while (result->NextRow()); + uint32 guidLow = (*result)[0].GetUInt32(); + + sLog->outInfo(LOG_FILTER_NETWORKIO, "Loading char guid %u from account %u.", guidLow, GetAccountId()); + + Player::BuildEnumData(result, &dataBuffer, &bitBuffer); + + _allowedCharsToLogin.insert(guidLow); + } 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); } -void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recvData*/) { // remove expired bans PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EXPIRED_BANS); @@ -249,20 +266,20 @@ void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/) _charEnumCallback = CharacterDatabase.AsyncQuery(stmt); } -void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data) +void WorldSession::HandleCharCreateOpcode(WorldPacket & recvData) { std::string name; uint8 race_, class_; - recv_data >> name; + recvData >> name; - recv_data >> race_; - recv_data >> class_; + recvData >> race_; + recvData >> class_; // extract other data required for player creating uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; - recv_data >> gender >> skin >> face; - recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; + recvData >> gender >> skin >> face; + recvData >> hairStyle >> hairColor >> facialHair >> outfitId; WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases @@ -387,7 +404,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data) } delete _charCreateCallback.GetParam(); // Delete existing if any, to make the callback chain reset to stage 0 - _charCreateCallback.SetParam(new CharacterCreateInfo(name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId, recv_data)); + _charCreateCallback.SetParam(new CharacterCreateInfo(name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId, recvData)); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); stmt->setString(0, name); _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); @@ -670,10 +687,10 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte } } -void WorldSession::HandleCharDeleteOpcode(WorldPacket & recv_data) +void WorldSession::HandleCharDeleteOpcode(WorldPacket & recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; // can't delete loaded character if (ObjectAccessor::FindPlayer(guid)) @@ -737,20 +754,37 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket & recv_data) SendPacket(&data); } -void WorldSession::HandlePlayerLoginOpcode(WorldPacket & recv_data) +void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData) { if (PlayerLoading() || GetPlayer() != NULL) { - sLog->outError(LOG_FILTER_NETWORKIO, "Player tryes to login again, AccountId = %d", GetAccountId()); + sLog->outError(LOG_FILTER_NETWORKIO, "Player tries to login again, AccountId = %d", GetAccountId()); return; } m_playerLoading = true; - uint64 playerGuid = 0; + ObjectGuid playerGuid; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd Player Logon Message"); - - recv_data >> 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]); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "Character (Guid: %u) logging in", GUID_LOPART(playerGuid)); if (!CharCanLogin(GUID_LOPART(playerGuid))) { @@ -770,6 +804,17 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket & recv_data) _charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder); } +void WorldSession::HandleLoadScreenOpcode(WorldPacket& recvPacket) +{ + sLog->outInfo(LOG_FILTER_GENERAL, "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(); @@ -804,9 +849,34 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) LoadAccountData(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA), 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 @@ -853,6 +923,8 @@ 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->SetUInt32Value(PLAYER_GUILDLEVEL, guild->GetLevel()); } else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership { @@ -860,21 +932,20 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) pCurrChar->SetRank(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 - sLog->outError(LOG_FILTER_NETWORKIO, "Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName(), 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(); @@ -918,20 +989,28 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) } sObjectAccessor->AddObject(pCurrChar); - //sLog->outDebug("Player %s added to Map.", pCurrChar->GetName()); + //sLog->outDebug(LOG_FILTER_GENERAL, "Player %s added to Map.", pCurrChar->GetName()); + + if (pCurrChar->GetGuildId() != 0) + { + if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId())) + guild->SendLoginInfo(this); + else + { + // remove wrong guild data + sLog->outError(LOG_FILTER_GENERAL, "Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName(), 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()); @@ -958,7 +1037,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) - pCurrChar->SetMovement(MOVE_WATER_WALK); + pCurrChar->SendMovementSetWaterWalking(true); } pCurrChar->ContinueTaxiFlight(); @@ -986,7 +1065,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { - pCurrChar->resetTalents(true); + pCurrChar->ResetTalents(true); pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state SendNotification(LANG_RESET_TALENTS); } @@ -1017,30 +1096,30 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) delete holder; } -void WorldSession::HandleSetFactionAtWar(WorldPacket & recv_data) +void WorldSession::HandleSetFactionAtWar(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SET_FACTION_ATWAR"); uint32 repListID; uint8 flag; - recv_data >> repListID; - recv_data >> flag; + recvData >> repListID; + recvData >> flag; GetPlayer()->GetReputationMgr().SetAtWar(repListID, flag); } //I think this function is never used :/ I dunno, but i guess this opcode not exists -void WorldSession::HandleSetFactionCheat(WorldPacket & /*recv_data*/) +void WorldSession::HandleSetFactionCheat(WorldPacket & /*recvData*/) { sLog->outError(LOG_FILTER_NETWORKIO, "WORLD SESSION: HandleSetFactionCheat, not expected call, please report."); GetPlayer()->GetReputationMgr().SendStates(); } -void WorldSession::HandleTutorialFlag(WorldPacket & recv_data) +void WorldSession::HandleTutorialFlag(WorldPacket & recvData) { uint32 data; - recv_data >> data; + recvData >> data; uint8 index = uint8(data / 32); if (index >= MAX_ACCOUNT_TUTORIAL_VALUES) @@ -1053,57 +1132,57 @@ void WorldSession::HandleTutorialFlag(WorldPacket & recv_data) SetTutorialInt(index, flag); } -void WorldSession::HandleTutorialClear(WorldPacket & /*recv_data*/) +void WorldSession::HandleTutorialClear(WorldPacket& /*recvData*/) { for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i) SetTutorialInt(i, 0xFFFFFFFF); } -void WorldSession::HandleTutorialReset(WorldPacket & /*recv_data*/) +void WorldSession::HandleTutorialReset(WorldPacket& /*recvData*/) { for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i) SetTutorialInt(i, 0x00000000); } -void WorldSession::HandleSetWatchedFactionOpcode(WorldPacket & recv_data) +void WorldSession::HandleSetWatchedFactionOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SET_WATCHED_FACTION"); uint32 fact; - recv_data >> fact; + recvData >> fact; GetPlayer()->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fact); } -void WorldSession::HandleSetFactionInactiveOpcode(WorldPacket & recv_data) +void WorldSession::HandleSetFactionInactiveOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SET_FACTION_INACTIVE"); uint32 replistid; uint8 inactive; - recv_data >> replistid >> inactive; + recvData >> replistid >> inactive; _player->GetReputationMgr().SetInactive(replistid, inactive); } -void WorldSession::HandleShowingHelmOpcode(WorldPacket& recv_data) +void WorldSession::HandleShowingHelmOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SHOWING_HELM for %s", _player->GetName()); - recv_data.read_skip<uint8>(); // unknown, bool? + recvData.read_skip<uint8>(); // unknown, bool? _player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM); } -void WorldSession::HandleShowingCloakOpcode(WorldPacket& recv_data) +void WorldSession::HandleShowingCloakOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SHOWING_CLOAK for %s", _player->GetName()); - recv_data.read_skip<uint8>(); // unknown, bool? + recvData.read_skip<uint8>(); // unknown, bool? _player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK); } -void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data) +void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData) { uint64 guid; std::string newName; - recv_data >> guid; - recv_data >> newName; + recvData >> guid; + recvData >> newName; // prevent character rename to invalid name if (!normalizePlayerName(newName)) @@ -1193,11 +1272,11 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult resu sWorld->UpdateCharacterNameData(guidLow, newName); } -void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) +void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; // not accept declined names for unsupported languages std::string name; @@ -1232,7 +1311,7 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) std::string name2; DeclinedName declinedname; - recv_data >> name2; + recvData >> name2; if (name2 != name) // character have different name { @@ -1245,7 +1324,7 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { - recv_data >> declinedname.name[i]; + recvData >> declinedname.name[i]; if (!normalizePlayerName(declinedname.name[i])) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); @@ -1290,12 +1369,12 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) SendPacket(&data); } -void WorldSession::HandleAlterAppearance(WorldPacket & recv_data) +void WorldSession::HandleAlterAppearance(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ALTER_APPEARANCE"); uint32 Hair, Color, FacialHair, SkinColor; - recv_data >> Hair >> Color >> FacialHair >> SkinColor; + recvData >> Hair >> Color >> FacialHair >> SkinColor; BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair); @@ -1312,12 +1391,12 @@ void WorldSession::HandleAlterAppearance(WorldPacket & recv_data) if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->getGender())) return; - uint32 Cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id, bs_skinColor); + uint32 cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id, bs_skinColor); // 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 @@ -1331,8 +1410,8 @@ void WorldSession::HandleAlterAppearance(WorldPacket & recv_data) SendPacket(&data); } - _player->ModifyMoney(-int32(Cost)); // it isn't free - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, Cost); + _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)); _player->SetByteValue(PLAYER_BYTES, 3, uint8(Color)); @@ -1340,15 +1419,15 @@ void WorldSession::HandleAlterAppearance(WorldPacket & recv_data) if (bs_skinColor) _player->SetByteValue(PLAYER_BYTES, 0, uint8(bs_skinColor->hair_id)); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); _player->SetStandState(0); // stand up } -void WorldSession::HandleRemoveGlyph(WorldPacket & recv_data) +void WorldSession::HandleRemoveGlyph(WorldPacket & recvData) { uint32 slot; - recv_data >> slot; + recvData >> slot; if (slot >= MAX_GLYPH_SLOT_INDEX) { @@ -1356,7 +1435,7 @@ void WorldSession::HandleRemoveGlyph(WorldPacket & recv_data) return; } - if (uint32 glyph = _player->GetGlyph(slot)) + if (uint32 glyph = _player->GetGlyph(_player->GetActiveSpec(), slot)) { if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph)) { @@ -1367,21 +1446,19 @@ void WorldSession::HandleRemoveGlyph(WorldPacket & recv_data) } } -void WorldSession::HandleCharCustomize(WorldPacket& recv_data) +void WorldSession::HandleCharCustomize(WorldPacket& recvData) { uint64 guid; std::string newName; - recv_data >> guid; - recv_data >> newName; + recvData >> guid; + recvData >> newName; uint8 gender, skin, face, hairStyle, hairColor, facialHair; - recv_data >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face; + recvData >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AT_LOGIN); - stmt->setUInt32(0, GUID_LOPART(guid)); - PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) @@ -1483,23 +1560,23 @@ void WorldSession::HandleCharCustomize(WorldPacket& recv_data) SendPacket(&data); } -void WorldSession::HandleEquipmentSetSave(WorldPacket &recv_data) +void WorldSession::HandleEquipmentSetSave(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_EQUIPMENT_SET_SAVE"); uint64 setGuid; - recv_data.readPackGUID(setGuid); + recvData.readPackGUID(setGuid); uint32 index; - recv_data >> index; + recvData >> index; if (index >= MAX_EQUIPMENT_SET_INDEX) // client set slots amount return; std::string name; - recv_data >> name; + recvData >> name; std::string iconName; - recv_data >> iconName; + recvData >> iconName; EquipmentSet eqSet; @@ -1511,7 +1588,7 @@ void WorldSession::HandleEquipmentSetSave(WorldPacket &recv_data) for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) { uint64 itemGuid; - recv_data.readPackGUID(itemGuid); + recvData.readPackGUID(itemGuid); // equipment manager sends "1" (as raw GUID) for slots set to "ignore" (don't touch slot at equip set) if (itemGuid == 1) @@ -1535,17 +1612,17 @@ void WorldSession::HandleEquipmentSetSave(WorldPacket &recv_data) _player->SetEquipmentSet(index, eqSet); } -void WorldSession::HandleEquipmentSetDelete(WorldPacket &recv_data) +void WorldSession::HandleEquipmentSetDelete(WorldPacket &recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_EQUIPMENT_SET_DELETE"); uint64 setGuid; - recv_data.readPackGUID(setGuid); + recvData.readPackGUID(setGuid); _player->DeleteEquipmentSet(setGuid); } -void WorldSession::HandleEquipmentSetUse(WorldPacket &recv_data) +void WorldSession::HandleEquipmentSetUse(WorldPacket& recvData) { if (_player->isInCombat()) return; @@ -1555,10 +1632,10 @@ void WorldSession::HandleEquipmentSetUse(WorldPacket &recv_data) for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) { uint64 itemGuid; - recv_data.readPackGUID(itemGuid); + recvData.readPackGUID(itemGuid); uint8 srcbag, srcslot; - recv_data >> srcbag >> srcslot; + recvData >> srcbag >> srcslot; sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "Item " UI64FMTD ": srcbag %u, srcslot %u", itemGuid, srcbag, srcslot); @@ -1600,15 +1677,15 @@ void WorldSession::HandleEquipmentSetUse(WorldPacket &recv_data) SendPacket(&data); } -void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) +void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) { // TODO: Move queries to prepared statements uint64 guid; std::string newname; uint8 gender, skin, face, hairStyle, hairColor, facialHair, race; - recv_data >> guid; - recv_data >> newname; - recv_data >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face >> race; + recvData >> guid; + recvData >> newname; + recvData >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face >> race; uint32 lowGuid = GUID_LOPART(guid); @@ -1630,7 +1707,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) uint32 playerClass = uint32(fields[0].GetUInt8()); uint32 level = uint32(fields[1].GetUInt8()); uint32 at_loginFlags = fields[2].GetUInt16(); - uint32 used_loginFlag = ((recv_data.GetOpcode() == CMSG_CHAR_RACE_CHANGE) ? AT_LOGIN_CHANGE_RACE : AT_LOGIN_CHANGE_FACTION); + uint32 used_loginFlag = ((recvData.GetOpcode() == CMSG_CHAR_RACE_CHANGE) ? AT_LOGIN_CHANGE_RACE : AT_LOGIN_CHANGE_FACTION); if (!sObjectMgr->GetPlayerInfo(race, playerClass)) { @@ -1722,6 +1799,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) switch (race) { case RACE_ORC: + case RACE_GOBLIN: case RACE_TAUREN: case RACE_UNDEAD_PLAYER: case RACE_TROLL: @@ -1770,6 +1848,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) 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; @@ -1782,12 +1863,15 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) case RACE_BLOODELF: stmt->setUInt16(1, 137); break; + case RACE_GOBLIN: + stmt->setUInt16(1, 792); + break; } trans->Append(stmt); } - if (recv_data.GetOpcode() == CMSG_CHAR_FACTION_CHANGE) + if (recvData.GetOpcode() == CMSG_CHAR_FACTION_CHANGE) { // Delete all Flypaths PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXI_PATH); @@ -2021,3 +2105,73 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) data << uint8(race); SendPacket(&data); } + +void WorldSession::HandleRandomizeCharNameOpcode(WorldPacket& recvData) +{ + uint8 gender, race; + + recvData >> race; + recvData >> gender; + + if (!Player::IsValidRace(race)) + { + sLog->outError(LOG_FILTER_GENERAL, "Invalid race (%u) sent by accountId: %u", race, GetAccountId()); + return; + } + + if (!Player::IsValidGender(gender)) + { + sLog->outError(LOG_FILTER_GENERAL, "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); +} diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index 880f2df86f7..2ab2831c0d0 100755..100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -63,131 +63,180 @@ bool WorldSession::processChatmessageFurtherAfterSecurityChecks(std::string& msg return true; } -void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) +void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) { - uint32 type; + uint32 type = 0; uint32 lang; - recv_data >> type; - recv_data >> lang; + switch(recvData.GetOpcode()) + { + 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: + sLog->outError(LOG_FILTER_NETWORKIO, "HandleMessagechatOpcode : Unknown chat opcode (%u)", recvData.GetOpcode()); + recvData.hexlike(); + return; + } if (type >= MAX_CHAT_MSG_TYPE) { sLog->outError(LOG_FILTER_NETWORKIO, "CHAT: Wrong message type received: %u", type); - recv_data.rfinish(); + recvData.rfinish(); return; } Player* sender = GetPlayer(); - //sLog->outDebug("CHAT: packet received. type %u, lang %u", type, lang); + //sLog->outDebug(LOG_FILTER_GENERAL, "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); - recv_data.rfinish(); - return; - } - 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) + recvData >> lang; + + // prevent talking at unknown language (cheating) + LanguageDesc const* langDesc = GetLanguageDescByID(lang); + if (!langDesc) { - if ((*i)->GetMiscValue() == int32(lang)) - { - foundAura = true; - break; - } + SendNotification(LANG_UNKNOWN_LANGUAGE); + recvData.rfinish(); + return; } - if (!foundAura) + if (langDesc->skill_id != 0 && !sender->HasSkill(langDesc->skill_id)) { - SendNotification(LANG_NOT_LEARNED_LANGUAGE); - recv_data.rfinish(); - return; + // 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)) + { + foundAura = true; + break; + } + } + if (!foundAura) + { + SendNotification(LANG_NOT_LEARNED_LANGUAGE); + recvData.rfinish(); + return; + } } - } - if (lang == LANG_ADDON) - { - if (sWorld->getBoolConfig(CONFIG_CHATLOG_ADDON)) + if (lang == LANG_ADDON) { - std::string msg = ""; - recv_data >> msg; + if (sWorld->getBoolConfig(CONFIG_CHATLOG_ADDON)) + { + std::string msg = ""; + recvData >> msg; - if (msg.empty()) - return; + if (msg.empty()) + return; - sScriptMgr->OnPlayerChat(sender, uint32(CHAT_MSG_ADDON), lang, msg); - } + sScriptMgr->OnPlayerChat(sender, uint32(CHAT_MSG_ADDON), lang, msg); + } - // Disabled addon channel? - if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL)) - 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; + // Disabled addon channel? + if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL)) + return; + } + // LANG_ADDON should not be changed nor be affected by flood control else { - // send in universal language in two side iteration allowed mode - if (sWorld->getBoolConfig(CONFIG_ALLOW_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 (sWorld->getBoolConfig(CONFIG_ALLOW_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(); - } + // 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()); - recv_data.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) { - std::string msg=""; - recv_data >> msg; - + recvData.rfinish(); SendNotification(GetTrinityString(LANG_GM_SILENCE), sender->GetName()); return; } + uint32 textLength = 0; + uint32 receiverLength = 0; std::string to, channel, msg; bool ignoreChecks = false; switch (type) @@ -196,27 +245,30 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) 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: - recv_data >> msg; + textLength = recvData.ReadBits(9); + msg = recvData.ReadString(textLength); break; case CHAT_MSG_WHISPER: - recv_data >> to; - recv_data >> msg; + receiverLength = recvData.ReadBits(10); + textLength = recvData.ReadBits(9); + to = recvData.ReadString(receiverLength); + msg = recvData.ReadString(textLength); break; case CHAT_MSG_CHANNEL: - recv_data >> channel; - recv_data >> 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: - recv_data >> msg; + textLength = recvData.ReadBits(9); + msg = recvData.ReadString(textLength); ignoreChecks = true; break; } @@ -309,8 +361,8 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) return; } - if (type == CHAT_MSG_PARTY_LEADER && !group->IsLeader(_player->GetGUID())) - return; + if (group->IsLeader(GetPlayer()->GetGUID())) + type = CHAT_MSG_PARTY_LEADER; sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); @@ -343,6 +395,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) } } 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(); @@ -353,27 +406,13 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) return; } - sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(), NULL); - 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(_player->GetGUID())) - return; - } + if (group->IsLeader(GetPlayer()->GetGUID())) + type = CHAT_MSG_RAID_LEADER; sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(), NULL); + ChatHandler::FillMessageData(&data, this, uint8(type), lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_RAID_WARNING: @@ -390,29 +429,20 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) group->BroadcastPacket(&data, false); } 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::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(), NULL); - 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::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(), NULL); + ChatHandler::FillMessageData(&data, this, uint8(type), lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_CHANNEL: @@ -479,13 +509,151 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleEmoteOpcode(WorldPacket & recv_data) +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: + sLog->outError(LOG_FILTER_NETWORKIO, "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; + } + + // Logging enabled? + if (sWorld->getBoolConfig(CONFIG_CHATLOG_ADDON)) + { + if (message.empty()) + return; + + // Weird way to log stuff... + sScriptMgr->OnPlayerChat(sender, CHAT_MSG_ADDON, LANG_ADDON, message); + } + + // Disabled addon channel? + if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL)) + return; + + switch (type) + { + case CHAT_MSG_BATTLEGROUND: + { + Group* group = sender->GetGroup(); + if (!group || !group->isBGGroup()) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, type, LANG_ADDON, "", 0, message.c_str(), NULL); + 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.c_str()); + 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::FillMessageData(&data, this, type, LANG_ADDON, "", 0, message.c_str(), NULL, prefix.c_str()); + group->BroadcastAddonMessagePacket(&data, prefix, true, -1, group->GetMemberGroup(sender->GetGUID())); + break; + } + default: + { + sLog->outError(LOG_FILTER_GENERAL, "HandleAddonMessagechatOpcode: unknown addon message type %u", type); + break; + } + } +} + +void WorldSession::HandleEmoteOpcode(WorldPacket & recvData) { if (!GetPlayer()->isAlive() || GetPlayer()->HasUnitState(UNIT_STATE_DIED)) return; uint32 emote; - recv_data >> emote; + recvData >> emote; sScriptMgr->OnPlayerEmote(GetPlayer(), emote); GetPlayer()->HandleEmoteCommand(emote); } @@ -522,7 +690,7 @@ namespace Trinity }; } // namespace Trinity -void WorldSession::HandleTextEmoteOpcode(WorldPacket & recv_data) +void WorldSession::HandleTextEmoteOpcode(WorldPacket & recvData) { if (!GetPlayer()->isAlive()) return; @@ -537,9 +705,9 @@ void WorldSession::HandleTextEmoteOpcode(WorldPacket & recv_data) uint32 text_emote, emoteNum; uint64 guid; - recv_data >> text_emote; - recv_data >> emoteNum; - recv_data >> guid; + recvData >> text_emote; + recvData >> emoteNum; + recvData >> guid; sScriptMgr->OnPlayerTextEmote(GetPlayer(), text_emote, emoteNum, guid); @@ -577,21 +745,21 @@ void WorldSession::HandleTextEmoteOpcode(WorldPacket & recv_data) 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()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); + GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); //Send scripted event call if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI()) ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(), text_emote); } -void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data) +void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recvData) { uint64 iguid; uint8 unk; //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: Received CMSG_CHAT_IGNORED"); - recv_data >> iguid; - recv_data >> unk; // probably related to spam reporting + recvData >> iguid; + recvData >> unk; // probably related to spam reporting Player* player = ObjectAccessor::FindPlayer(iguid); if (!player || !player->GetSession()) diff --git a/src/server/game/Handlers/CombatHandler.cpp b/src/server/game/Handlers/CombatHandler.cpp index 78547d2d0f3..1cd86afc6d2 100755 --- a/src/server/game/Handlers/CombatHandler.cpp +++ b/src/server/game/Handlers/CombatHandler.cpp @@ -26,10 +26,10 @@ #include "Vehicle.h" #include "VehicleDefines.h" -void WorldSession::HandleAttackSwingOpcode(WorldPacket& recv_data) +void WorldSession::HandleAttackSwingOpcode(WorldPacket& recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_ATTACKSWING Message guidlow:%u guidhigh:%u", GUID_LOPART(guid), GUID_HIPART(guid)); @@ -66,15 +66,15 @@ void WorldSession::HandleAttackSwingOpcode(WorldPacket& recv_data) _player->Attack(pEnemy, true); } -void WorldSession::HandleAttackStopOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleAttackStopOpcode(WorldPacket & /*recvData*/) { GetPlayer()->AttackStop(); } -void WorldSession::HandleSetSheathedOpcode(WorldPacket& recv_data) +void WorldSession::HandleSetSheathedOpcode(WorldPacket& recvData) { uint32 sheathed; - recv_data >> sheathed; + recvData >> sheathed; //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: Recvd CMSG_SETSHEATHED Message guidlow:%u value1:%u", GetPlayer()->GetGUIDLow(), sheathed); diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index c11a1cfc2aa..590cd5ff63f 100755..100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -31,6 +31,9 @@ #include "Util.h" #include "SpellAuras.h" #include "Vehicle.h" +#include "DB2Structure.h" +#include "DB2Stores.h" +#include "SpellAuraEffects.h" class Aura; @@ -47,72 +50,105 @@ 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); } -void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data) +void WorldSession::HandleGroupInviteOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_INVITE"); - std::string membername; - recv_data >> membername; - recv_data.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.c_str()); + Player* player = sObjectAccessor->FindPlayerByName(memberName.c_str()); // 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(); @@ -123,17 +159,63 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data) // 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(strlen(player->GetName()), 7); // Invited 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(player->GetName()); // invited name + + data << int32(0); + player->GetSession()->SendPacket(&data); } @@ -184,101 +266,145 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data) } // 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(strlen(player->GetName()), 7); // Invited 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(player->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& recv_data) +void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_ACCEPT"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_INVITE_RESPONSE"); + + bool accept = !recvData.ReadBit(); + if (!accept) + recvData.read_skip<uint32>(); // unk - recv_data.read_skip<uint32>(); Group* group = GetPlayer()->GetGroupInvite(); if (!group) return; - // Remove player from invitees in any case - group->RemoveInvite(GetPlayer()); - - if (group->GetLeaderGUID() == GetPlayer()->GetGUID()) + if (accept) { - sLog->outError(LOG_FILTER_NETWORKIO, "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); - return; - } - - // Group is full - if (group->IsFull()) - { - 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(); + sLog->outError(LOG_FILTER_NETWORKIO, "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName(), 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 & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "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 - std::string name = std::string(GetPlayer()->GetName()); - WorldPacket data(SMSG_GROUP_DECLINE, name.length()); - data << name.c_str(); - leader->GetSession()->SendPacket(&data); + // report + WorldPacket data(SMSG_GROUP_DECLINE, strlen(GetPlayer()->GetName())); + data << GetPlayer()->GetName(); + leader->GetSession()->SendPacket(&data); + } } -void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket & recv_data) +void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_UNINVITE_GUID"); uint64 guid; std::string reason; - recv_data >> guid; - recv_data >> reason; + recvData >> guid; + recvData >> reason; //can't uninvite yourself if (guid == GetPlayer()->GetGUID()) @@ -319,12 +445,12 @@ void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket & recv_data) SendPartyResult(PARTY_OP_UNINVITE, "", ERR_TARGET_NOT_IN_GROUP_S); } -void WorldSession::HandleGroupUninviteOpcode(WorldPacket & recv_data) +void WorldSession::HandleGroupUninviteOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_UNINVITE"); std::string membername; - recv_data >> membername; + recvData >> membername; // player not found if (!normalizePlayerName(membername)) @@ -363,12 +489,12 @@ void WorldSession::HandleGroupUninviteOpcode(WorldPacket & recv_data) SendPartyResult(PARTY_OP_UNINVITE, membername, ERR_TARGET_NOT_IN_GROUP_S); } -void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket & recv_data) +void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_SET_LEADER"); uint64 guid; - recv_data >> guid; + recvData >> guid; Player* player = ObjectAccessor::FindPlayer(guid); Group* group = GetPlayer()->GetGroup(); @@ -384,7 +510,7 @@ void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket & recv_data) group->SendUpdate(); } -void WorldSession::HandleGroupDisbandOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleGroupDisbandOpcode(WorldPacket& /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_DISBAND"); @@ -407,14 +533,14 @@ void WorldSession::HandleGroupDisbandOpcode(WorldPacket & /*recv_data*/) GetPlayer()->RemoveFromGroup(GROUP_REMOVEMETHOD_LEAVE); } -void WorldSession::HandleLootMethodOpcode(WorldPacket & recv_data) +void WorldSession::HandleLootMethodOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LOOT_METHOD"); uint32 lootMethod; uint64 lootMaster; uint32 lootThreshold; - recv_data >> lootMethod >> lootMaster >> lootThreshold; + recvData >> lootMethod >> lootMaster >> lootThreshold; Group* group = GetPlayer()->GetGroup(); if (!group) @@ -450,15 +576,15 @@ void WorldSession::HandleLootRoll(WorldPacket& recvData) switch (rollType) { case ROLL_NEED: - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1); + GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1); break; case ROLL_GREED: - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1); + GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1); break; } } -void WorldSession::HandleMinimapPingOpcode(WorldPacket& recv_data) +void WorldSession::HandleMinimapPingOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_MINIMAP_PING"); @@ -466,10 +592,10 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recv_data) return; float x, y; - recv_data >> x; - recv_data >> y; + recvData >> x; + recvData >> y; - //sLog->outDebug("Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y); + //sLog->outDebug(LOG_FILTER_GENERAL, "Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y); /** error handling **/ /********************/ @@ -482,13 +608,13 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recv_data) GetPlayer()->GetGroup()->BroadcastPacket(&data, true, -1, GetPlayer()->GetGUID()); } -void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data) +void WorldSession::HandleRandomRollOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_RANDOM_ROLL"); uint32 minimum, maximum, roll; - recv_data >> minimum; - recv_data >> maximum; + recvData >> minimum; + recvData >> maximum; /** error handling **/ if (minimum > maximum || maximum > 10000) // < 32768 for urand call @@ -498,7 +624,7 @@ void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data) // everything's fine, do it roll = urand(minimum, maximum); - //sLog->outDebug("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll); + //sLog->outDebug(LOG_FILTER_GENERAL, "ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll); WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8); data << uint32(minimum); @@ -511,7 +637,7 @@ void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data) SendPacket(&data); } -void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket & recv_data) +void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_RAID_TARGET_UPDATE"); @@ -519,29 +645,27 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket & recv_data) if (!group) return; - uint8 x; - recv_data >> x; + uint8 x; + recvData >> x; /** error handling **/ /********************/ // everything's fine, do it if (x == 0xFF) // target icon request - { group->SendTargetIconList(this); - } else // target icon update { if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) return; uint64 guid; - recv_data >> guid; + recvData >> guid; group->SetTargetIcon(x, _player->GetGUID(), guid); } } -void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_RAID_CONVERT"); @@ -552,17 +676,25 @@ void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recv_data*/) 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 & recv_data) +void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_CHANGE_SUB_GROUP"); @@ -573,8 +705,8 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket & recv_data) std::string name; uint8 groupNr; - recv_data >> name; - recv_data >> groupNr; + recvData >> name; + recvData >> groupNr; if (groupNr >= MAX_RAID_SUBGROUPS) return; @@ -588,10 +720,9 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket & recv_data) Player* movedPlayer = sObjectAccessor->FindPlayerByName(name.c_str()); uint64 guid; + if (movedPlayer) - { guid = movedPlayer->GetGUID(); - } else { CharacterDatabase.EscapeString(name); @@ -601,7 +732,17 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket & recv_data) group->ChangeMembersGroup(guid, groupNr); } -void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket & recv_data) +void WorldSession::HandleGroupSwapSubGroupOpcode(WorldPacket& recvData) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_SWAP_SUB_GROUP"); + std::string unk1; + std::string unk2; + + recvData >> unk1; + recvData >> unk2; +} + +void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_ASSISTANT_LEADER"); @@ -614,15 +755,15 @@ void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket & recv_data) uint64 guid; bool apply; - recv_data >> guid; - recv_data >> apply; + recvData >> guid; + recvData >> apply; group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_ASSISTANT); group->SendUpdate(); } -void WorldSession::HandlePartyAssignmentOpcode(WorldPacket & recv_data) +void WorldSession::HandlePartyAssignmentOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_PARTY_ASSIGNMENT"); @@ -637,8 +778,8 @@ void WorldSession::HandlePartyAssignmentOpcode(WorldPacket & recv_data) uint8 assignment; bool apply; uint64 guid; - recv_data >> assignment >> apply; - recv_data >> guid; + recvData >> assignment >> apply; + recvData >> guid; switch (assignment) { @@ -656,7 +797,7 @@ void WorldSession::HandlePartyAssignmentOpcode(WorldPacket & recv_data) group->SendUpdate(); } -void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket & recv_data) +void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_RAID_READY_CHECK"); @@ -664,7 +805,7 @@ void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket & recv_data) if (!group) return; - if (recv_data.empty()) // request + if (recvData.empty()) // request { /** error handling **/ if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) @@ -681,7 +822,7 @@ void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket & recv_data) else // answer { uint8 state; - recv_data >> state; + recvData >> state; // everything's fine, do it WorldPacket data(MSG_RAID_READY_CHECK_CONFIRM, 9); @@ -691,7 +832,7 @@ void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket& /*recvData*/) { //Group* group = GetPlayer()->GetGroup(); //if (!group) @@ -716,12 +857,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke 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; @@ -760,20 +896,39 @@ 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() << (uint16) player->GetPositionY(); + *data << (uint16) player->GetPositionX() << (uint16) player->GetPositionY() << (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) + continue; // mhmm... + + *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); + } + } } } } @@ -853,29 +1008,52 @@ 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(1); + if (!aurApp) + continue; // mhmm... + + *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 << (uint64) 0; } + + if (mask & GROUP_UPDATE_FLAG_PHASE) + { + *data << uint32(8); // either 0 or 8, same unk found in SMSG_PHASESHIFT + *data << uint32(0); // count + // for (count) *data << uint16(phaseId) + } } /*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ -void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data) +void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); uint64 Guid; - recv_data >> Guid; + recvData >> Guid; Player* player = HashMapHolder<Player>::Find(Guid); if (!player) @@ -895,9 +1073,14 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data) data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.append(player->GetPackGUID()); - uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF + uint32 mask1 = 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_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_AURAS | + GROUP_UPDATE_FLAG_PHASE; + if (pet) - mask1 = 0x7FFFFFFF; // for hunters and other classes with pets + mask1 = 0x7FEFFEFF; // full mask & ~(GROUP_UPDATE_FLAG_VEHICLE_SEAT | GROUP_UPDATE_FLAG_UNK) (for hunters and other classes with pets) Powers powerType = player->getPowerType(); data << (uint32) mask1; // group update mask @@ -911,17 +1094,34 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data) 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; size_t maskPos = data.wpos(); - data << (uint64) auramask; // placeholder + data << (uint8) 1; + data << (uint64) auramask; // placeholder + data << (uint32) MAX_AURAS; // count for (uint8 i = 0; i < MAX_AURAS; ++i) { - if (AuraApplication * aurApp = player->GetVisibleAura(i)) + if (auramask & (uint64(1) << i)) { - auramask |= (uint64(1) << i); - data << (uint32) aurApp->GetBase()->GetId(); - data << (uint8) 1; + AuraApplication const* aurApp = player->GetVisibleAura(i); + if (!aurApp) + continue; // mhmm... + + 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); + } + } } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS @@ -940,14 +1140,30 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data) uint64 petauramask = 0; size_t petMaskPos = data.wpos(); + data << (uint8) 1; data << (uint64) petauramask; // placeholder + data << (uint32) MAX_AURAS; // count for (uint8 i = 0; i < MAX_AURAS; ++i) { - if (AuraApplication * auraApp = pet->GetVisibleAura(i)) + if (auramask & (uint64(1) << i)) { - petauramask |= (uint64(1) << i); - data << (uint32) auraApp->GetBase()->GetId(); - data << (uint8) 1; + AuraApplication const* aurApp = pet->GetVisibleAura(i); + if (!aurApp) + continue; // mhmm... + + 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); + } + } } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS @@ -955,34 +1171,41 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data) else { data << (uint8) 0; // GROUP_UPDATE_FLAG_PET_NAME + data << (uint8) 0; // GROUP_UPDATE_FLAG_PET_AURAS data << (uint64) 0; // GROUP_UPDATE_FLAG_PET_AURAS + data << (uint32) 0; // GROUP_UPDATE_FLAG_PET_AURAS } + // GROUP_UPDATE_FLAG_PHASE + data << uint32(8); // either 0 or 8, same unk found in SMSG_PHASESHIFT + data << uint32(0); // count + // for (count) *data << uint16(phaseId) + SendPacket(&data); } -/*!*/void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket & /*recv_data*/) +/*!*/void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket & /*recvData*/) { // every time the player checks the character screen _player->SendRaidInfo(); } -/*void WorldSession::HandleGroupCancelOpcode(WorldPacket & recv_data) +/*void WorldSession::HandleGroupCancelOpcode(WorldPacket & recvData) { - sLog->outDebug("WORLD: got CMSG_GROUP_CANCEL."); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: got CMSG_GROUP_CANCEL."); }*/ -void WorldSession::HandleOptOutOfLootOpcode(WorldPacket & recv_data) +void WorldSession::HandleOptOutOfLootOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_OPT_OUT_OF_LOOT"); - uint32 passOnLoot; - recv_data >> passOnLoot; // 1 always pass, 0 do not pass + 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) sLog->outError(LOG_FILTER_NETWORKIO, "CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!"); return; } diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp index ccd1c931f51..778ecc2659f 100755 --- a/src/server/game/Handlers/GuildHandler.cpp +++ b/src/server/game/Handlers/GuildHandler.cpp @@ -44,38 +44,26 @@ void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_QUERY"); - uint32 guildId; - recvPacket >> guildId; - // Use received guild id to access guild method (not player's guild id) - if (Guild* guild = sGuildMgr->GetGuildById(guildId)) - guild->HandleQuery(this); - else - Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_PLAYER_NOT_IN_GUILD); -} - -void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_CREATE"); + uint64 guildGuid, playerGuid; + recvPacket >> guildGuid >> playerGuid; - std::string name; - recvPacket >> name; + // If guild doesn't exist or player is not part of the guild send error + if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid)) + if (guild->IsMember(playerGuid)) + { + guild->HandleQuery(this); + return; + } - if (!GetPlayer()->GetGuildId()) // Player cannot be in guild - { - Guild* guild = new Guild(); - if (guild->Create(GetPlayer(), name)) - sGuildMgr->AddGuild(guild); - else - delete guild; - } + Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_PLAYER_NOT_IN_GUILD); } void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_INVITE"); - std::string invitedName; - recvPacket >> invitedName; + uint32 nameLength = recvPacket.ReadBits(7); + std::string invitedName = recvPacket.ReadString(nameLength); if (normalizePlayerName(invitedName)) if (Guild* guild = _GetPlayerGuild(this, true)) @@ -86,12 +74,28 @@ void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_REMOVE"); - std::string playerName; - recvPacket >> playerName; + ObjectGuid playerGuid; + + 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(); + + 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]); - if (normalizePlayerName(playerName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleRemoveMember(this, playerName); + if (Guild* guild = _GetPlayerGuild(this, true)) + guild->HandleRemoveMember(this, playerGuid); } void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/) @@ -112,19 +116,13 @@ void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/) GetPlayer()->SetInGuild(0); } -void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_INFO"); - - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->SendInfo(this); -} - -void WorldSession::HandleGuildRosterOpcode(WorldPacket& /*recvPacket*/) +void WorldSession::HandleGuildRosterOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_ROSTER"); - if (Guild* guild = _GetPlayerGuild(this)) + recvPacket.rfinish(); + + if (Guild* guild = _GetPlayerGuild(this, true)) guild->HandleRoster(this); } @@ -132,24 +130,104 @@ void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_PROMOTE"); - std::string playerName; - recvPacket >> playerName; + ObjectGuid targetGuid; + + 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(); + + 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]); - if (normalizePlayerName(playerName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleUpdateMemberRank(this, playerName, false); + if (Guild* guild = _GetPlayerGuild(this, true)) + guild->HandleUpdateMemberRank(this, targetGuid, false); } void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_DEMOTE"); - std::string playerName; - recvPacket >> playerName; + ObjectGuid targetGuid; + + 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(); + + 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]); - if (normalizePlayerName(playerName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleUpdateMemberRank(this, playerName, true); + if (Guild* guild = _GetPlayerGuild(this, true)) + guild->HandleUpdateMemberRank(this, targetGuid, true); +} + +void WorldSession::HandleGuildAssignRankOpcode(WorldPacket& recvPacket) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_ASSIGN_MEMBER_RANK"); + + 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]); + + if (Guild* guild = _GetPlayerGuild(this, true)) + guild->HandleSetMemberRank(this, targetGuid, setterGuid, rankId); } void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/) @@ -184,107 +262,104 @@ void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_MOTD"); - std::string motd; // Empty by default - if (!recvPacket.empty()) - recvPacket >> motd; + uint32 motdLength = recvPacket.ReadBits(11); + std::string motd = recvPacket.ReadString(motdLength); if (Guild* guild = _GetPlayerGuild(this, true)) guild->HandleSetMOTD(this, motd); } -void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket) +void WorldSession::HandleGuildSetNoteOpcode(WorldPacket& recvPacket) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_SET_PUBLIC_NOTE"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_SET_NOTE"); - std::string playerName; - recvPacket >> playerName; + ObjectGuid playerGuid; - std::string publicNote; - recvPacket >> publicNote; + 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 type = recvPacket.ReadBit(); // 0 == Officer, 1 == Public + playerGuid[6] = recvPacket.ReadBit(); + uint32 noteLength = recvPacket.ReadBits(8); + playerGuid[2] = recvPacket.ReadBit(); - if (normalizePlayerName(playerName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleSetMemberNote(this, playerName, publicNote, false); -} + 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]); -void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_SET_OFFICER_NOTE"); - - std::string playerName; - recvPacket >> playerName; - - std::string officerNote; - recvPacket >> officerNote; - - if (normalizePlayerName(playerName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleSetMemberNote(this, playerName, officerNote, true); + if (Guild* guild = _GetPlayerGuild(this, true)) + guild->HandleSetMemberNote(this, note, playerGuid, type); } -void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket) +void WorldSession::HandleGuildQueryRanksOpcode(WorldPacket& recvData) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_RANK"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_QUERY_RANKS"); - Guild* guild = _GetPlayerGuild(this, true); - if (!guild) - { - recvPacket.rpos(recvPacket.wpos()); - return; - } - - uint32 rankId; - recvPacket >> rankId; - - uint32 rights; - recvPacket >> rights; - - std::string rankName; - recvPacket >> rankName; - - uint32 money; - recvPacket >> money; - - GuildBankRightsAndSlotsVec rightsAndSlots(GUILD_BANK_MAX_TABS); - for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId) - { - uint32 bankRights; - uint32 slots; + ObjectGuid guildGuid; - recvPacket >> bankRights; - recvPacket >> slots; + guildGuid[2] = recvData.ReadBit(); + guildGuid[3] = recvData.ReadBit(); + guildGuid[0] = recvData.ReadBit(); + guildGuid[6] = recvData.ReadBit(); + guildGuid[4] = recvData.ReadBit(); + guildGuid[7] = recvData.ReadBit(); + guildGuid[5] = recvData.ReadBit(); + guildGuid[1] = recvData.ReadBit(); - rightsAndSlots[tabId] = GuildBankRightsAndSlots(uint8(bankRights), slots); - } + recvData.ReadByteSeq(guildGuid[3]); + recvData.ReadByteSeq(guildGuid[4]); + recvData.ReadByteSeq(guildGuid[5]); + recvData.ReadByteSeq(guildGuid[7]); + recvData.ReadByteSeq(guildGuid[1]); + recvData.ReadByteSeq(guildGuid[0]); + recvData.ReadByteSeq(guildGuid[6]); + recvData.ReadByteSeq(guildGuid[2]); - guild->HandleSetRankInfo(this, rankId, rankName, rights, money, rightsAndSlots); + if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid)) + if (guild->IsMember(_player->GetGUID())) + guild->HandleGuildRanks(this); } void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_ADD_RANK"); - std::string rankName; - recvPacket >> rankName; + uint32 rankId; + recvPacket >> rankId; + + uint32 length = recvPacket.ReadBits(7); + std::string rankName = recvPacket.ReadString(length); if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleAddNewRank(this, rankName); + guild->HandleAddNewRank(this, rankName); //, rankId); } -void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/) +void WorldSession::HandleGuildDelRankOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_DEL_RANK"); + uint32 rankId; + recvPacket >> rankId; + if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleRemoveLowestRank(this); + guild->HandleRemoveRank(this, rankId); } void WorldSession::HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_INFO_TEXT"); - std::string info; - recvPacket >> info; + uint32 length = recvPacket.ReadBits(12); + std::string info = recvPacket.ReadString(length); if (Guild* guild = _GetPlayerGuild(this, true)) guild->HandleSetInfo(this, info); @@ -328,86 +403,86 @@ void WorldSession::HandleGuildEventLogQueryOpcode(WorldPacket& /* recvPacket */) guild->SendEventLog(this); } -void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPacket & /* recv_data */) +void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPacket & /* recvData */) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (MSG_GUILD_BANK_MONEY_WITHDRAWN)"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_MONEY_WITHDRAWN_QUERY)"); if (Guild* guild = _GetPlayerGuild(this)) guild->SendMoneyInfo(this); } -void WorldSession::HandleGuildPermissions(WorldPacket& /* recv_data */) +void WorldSession::HandleGuildPermissions(WorldPacket& /* recvData */) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (MSG_GUILD_PERMISSIONS)"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_PERMISSIONS)"); if (Guild* guild = _GetPlayerGuild(this)) guild->SendPermissions(this); } // Called when clicking on Guild bank gameobject -void WorldSession::HandleGuildBankerActivate(WorldPacket & recv_data) +void WorldSession::HandleGuildBankerActivate(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANKER_ACTIVATE)"); uint64 GoGuid; - recv_data >> GoGuid; + recvData >> GoGuid; uint8 fullSlotList; - recv_data >> fullSlotList; // 0 = only slots updated in last operation are shown. 1 = all slots updated + recvData >> fullSlotList; // 0 = only slots updated in last operation are shown. 1 = all slots updated if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) { if (Guild* guild = _GetPlayerGuild(this)) - guild->SendBankTabsInfo(this); + guild->SendBankList(this, 0, true, true); else Guild::SendCommandResult(this, GUILD_UNK1, ERR_GUILD_PLAYER_NOT_IN_GUILD); } } // Called when opening guild bank tab only (first one) -void WorldSession::HandleGuildBankQueryTab(WorldPacket & recv_data) +void WorldSession::HandleGuildBankQueryTab(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_QUERY_TAB)"); uint64 GoGuid; - recv_data >> GoGuid; + recvData >> GoGuid; uint8 tabId; - recv_data >> tabId; + recvData >> tabId; uint8 fullSlotList; - recv_data >> fullSlotList; // 0 = only slots updated in last operation are shown. 1 = all slots updated + recvData >> fullSlotList; // 0 = only slots updated in last operation are shown. 1 = all slots updated if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) if (Guild* guild = _GetPlayerGuild(this)) - guild->SendBankTabData(this, tabId); + guild->SendBankList(this, tabId, true, false); } -void WorldSession::HandleGuildBankDepositMoney(WorldPacket & recv_data) +void WorldSession::HandleGuildBankDepositMoney(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_DEPOSIT_MONEY)"); - uint64 GoGuid; - recv_data >> GoGuid; + uint64 goGuid; + recvData >> goGuid; - uint32 money; - recv_data >> money; + uint64 money; + recvData >> money; - if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + if (GetPlayer()->GetGameObjectIfCanInteractWith(goGuid, GAMEOBJECT_TYPE_GUILD_BANK)) if (money && GetPlayer()->HasEnoughMoney(money)) if (Guild* guild = _GetPlayerGuild(this)) guild->HandleMemberDepositMoney(this, money); } -void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket & recv_data) +void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_WITHDRAW_MONEY)"); uint64 GoGuid; - recv_data >> GoGuid; + recvData >> GoGuid; uint32 money; - recv_data >> money; + recvData >> money; if (money) if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) @@ -415,28 +490,28 @@ void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket & recv_data) guild->HandleMemberWithdrawMoney(this, money); } -void WorldSession::HandleGuildBankSwapItems(WorldPacket & recv_data) +void WorldSession::HandleGuildBankSwapItems(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_SWAP_ITEMS)"); uint64 GoGuid; - recv_data >> GoGuid; + recvData >> GoGuid; if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) { - recv_data.rfinish(); // Prevent additional spam at rejected packet + recvData.rfinish(); // Prevent additional spam at rejected packet return; } Guild* guild = _GetPlayerGuild(this); if (!guild) { - recv_data.rfinish(); // Prevent additional spam at rejected packet + recvData.rfinish(); // Prevent additional spam at rejected packet return; } uint8 bankToBank; - recv_data >> bankToBank; + recvData >> bankToBank; uint8 tabId; uint8 slotId; @@ -446,18 +521,19 @@ void WorldSession::HandleGuildBankSwapItems(WorldPacket & recv_data) if (bankToBank) { uint8 destTabId; - recv_data >> destTabId; + recvData >> destTabId; uint8 destSlotId; - recv_data >> destSlotId; - recv_data.read_skip<uint32>(); // Always 0 + recvData >> destSlotId; - recv_data >> tabId; - recv_data >> slotId; - recv_data >> itemEntry; - recv_data.read_skip<uint8>(); // Always 0 + uint32 destItemEntry; + recvData >> destItemEntry; - recv_data >> splitedAmount; + recvData >> tabId; + recvData >> slotId; + recvData >> itemEntry; + recvData.read_skip<uint8>(); // Always 0 + recvData >> splitedAmount; guild->SwapItems(GetPlayer(), tabId, slotId, destTabId, destSlotId, splitedAmount); } @@ -467,65 +543,65 @@ void WorldSession::HandleGuildBankSwapItems(WorldPacket & recv_data) uint8 playerSlotId = NULL_SLOT; uint8 toChar = 1; - recv_data >> tabId; - recv_data >> slotId; - recv_data >> itemEntry; + recvData >> tabId; + recvData >> slotId; + recvData >> itemEntry; uint8 autoStore; - recv_data >> autoStore; + recvData >> autoStore; if (autoStore) { - recv_data.read_skip<uint32>(); // autoStoreCount - recv_data.read_skip<uint8>(); // ToChar (?), always and expected to be 1 (autostore only triggered in Bank -> Char) - recv_data.read_skip<uint32>(); // Always 0 + 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 } else { - recv_data >> playerBag; - recv_data >> playerSlotId; - recv_data >> toChar; - recv_data >> splitedAmount; + recvData >> playerBag; + recvData >> playerSlotId; + recvData >> toChar; + recvData >> 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, tabId, slotId, playerBag, playerSlotId, splitedAmount); } } -void WorldSession::HandleGuildBankBuyTab(WorldPacket & recv_data) +void WorldSession::HandleGuildBankBuyTab(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_BUY_TAB)"); uint64 GoGuid; - recv_data >> GoGuid; + recvData >> GoGuid; uint8 tabId; - recv_data >> tabId; + recvData >> tabId; - if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + if (!GoGuid || GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) if (Guild* guild = _GetPlayerGuild(this)) guild->HandleBuyBankTab(this, tabId); } -void WorldSession::HandleGuildBankUpdateTab(WorldPacket & recv_data) +void WorldSession::HandleGuildBankUpdateTab(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_UPDATE_TAB)"); uint64 GoGuid; - recv_data >> GoGuid; + recvData >> GoGuid; uint8 tabId; - recv_data >> tabId; + recvData >> tabId; std::string name; - recv_data >> name; + recvData >> name; std::string icon; - recv_data >> icon; + recvData >> icon; if (!name.empty() && !icon.empty()) if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) @@ -533,38 +609,135 @@ void WorldSession::HandleGuildBankUpdateTab(WorldPacket & recv_data) guild->HandleSetBankTabInfo(this, tabId, name, icon); } -void WorldSession::HandleGuildBankLogQuery(WorldPacket & recv_data) +void WorldSession::HandleGuildBankLogQuery(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (MSG_GUILD_BANK_LOG_QUERY)"); uint8 tabId; - recv_data >> tabId; + recvData >> tabId; if (Guild* guild = _GetPlayerGuild(this)) guild->SendBankLog(this, tabId); } -void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recv_data) +void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_QUERY_GUILD_BANK_TEXT"); uint8 tabId; - recv_data >> tabId; + recvData >> tabId; if (Guild* guild = _GetPlayerGuild(this)) guild->SendBankTabText(this, tabId); } -void WorldSession::HandleSetGuildBankTabText(WorldPacket &recv_data) +void WorldSession::HandleSetGuildBankTabText(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SET_GUILD_BANK_TEXT"); uint8 tabId; - recv_data >> tabId; + recvData >> tabId; std::string text; - recv_data >> text; + recvData >> text; if (Guild* guild = _GetPlayerGuild(this)) guild->SetBankTabText(tabId, text); } + +void WorldSession::HandleGuildQueryXPOpcode(WorldPacket& recvData) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUERY_GUILD_XP"); + + ObjectGuid guildGuid; + + guildGuid[2] = recvData.ReadBit(); + guildGuid[1] = recvData.ReadBit(); + guildGuid[0] = recvData.ReadBit(); + guildGuid[5] = recvData.ReadBit(); + guildGuid[4] = recvData.ReadBit(); + guildGuid[7] = recvData.ReadBit(); + guildGuid[6] = recvData.ReadBit(); + guildGuid[3] = recvData.ReadBit(); + + recvData.ReadByteSeq(guildGuid[7]); + recvData.ReadByteSeq(guildGuid[2]); + recvData.ReadByteSeq(guildGuid[3]); + recvData.ReadByteSeq(guildGuid[6]); + recvData.ReadByteSeq(guildGuid[1]); + recvData.ReadByteSeq(guildGuid[5]); + recvData.ReadByteSeq(guildGuid[0]); + recvData.ReadByteSeq(guildGuid[4]); + + //if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid)) + // guild->Send SMSG_GUILD_XP +} + +void WorldSession::HandleGuildSetRankPermissionsOpcode(WorldPacket& recvPacket) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_SET_RANK_PERMISSIONS"); + + Guild* guild = _GetPlayerGuild(this, true); + if (!guild) + { + recvPacket.rfinish(); + return; + } + + uint32 unk; + uint32 rankId; + uint32 oldRights; + uint32 newRights; + uint32 moneyPerDay; + + recvPacket >> unk; + 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(uint8(bankRights), slots); + } + + recvPacket >> moneyPerDay; + recvPacket >> rankId; + uint32 nameLength = recvPacket.ReadBits(7); + std::string rankName = recvPacket.ReadString(nameLength); + + guild->HandleSetRankInfo(this, rankId, rankName, newRights, moneyPerDay, rightsAndSlots); +} + +void WorldSession::HandleGuildRequestPartyState(WorldPacket& recvData) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_REQUEST_PARTY_STATE"); + + ObjectGuid guildGuid; + + guildGuid[0] = recvData.ReadBit(); + guildGuid[6] = recvData.ReadBit(); + guildGuid[7] = recvData.ReadBit(); + guildGuid[3] = recvData.ReadBit(); + guildGuid[5] = recvData.ReadBit(); + guildGuid[1] = recvData.ReadBit(); + guildGuid[2] = recvData.ReadBit(); + guildGuid[4] = recvData.ReadBit(); + + recvData.ReadByteSeq(guildGuid[6]); + recvData.ReadByteSeq(guildGuid[3]); + recvData.ReadByteSeq(guildGuid[2]); + recvData.ReadByteSeq(guildGuid[1]); + recvData.ReadByteSeq(guildGuid[5]); + recvData.ReadByteSeq(guildGuid[0]); + recvData.ReadByteSeq(guildGuid[7]); + recvData.ReadByteSeq(guildGuid[4]); + + if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid)) + guild->HandleGuildPartyRequest(this); +} diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index 260220bb8d5..ad8846ab071 100755..100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -27,14 +27,15 @@ #include "UpdateData.h" #include "ObjectAccessor.h" #include "SpellInfo.h" +#include <vector> -void WorldSession::HandleSplitItemOpcode(WorldPacket & recv_data) +void WorldSession::HandleSplitItemOpcode(WorldPacket& recvData) { //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_SPLIT_ITEM"); uint8 srcbag, srcslot, dstbag, dstslot; uint32 count; - recv_data >> srcbag >> srcslot >> dstbag >> dstslot >> count; + recvData >> srcbag >> srcslot >> dstbag >> dstslot >> count; //sLog->outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count); uint16 src = ((srcbag << 8) | srcslot); @@ -54,19 +55,19 @@ void WorldSession::HandleSplitItemOpcode(WorldPacket & recv_data) 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; } _player->SplitItem(src, dst, count); } -void WorldSession::HandleSwapInvItemOpcode(WorldPacket & recv_data) +void WorldSession::HandleSwapInvItemOpcode(WorldPacket & recvData) { //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_SWAP_INV_ITEM"); uint8 srcslot, dstslot; - recv_data >> dstslot >> srcslot; + recvData >> dstslot >> srcslot; //sLog->outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot); // prevent attempt swap same item to current position generated by client at special checting sequence @@ -81,7 +82,7 @@ void WorldSession::HandleSwapInvItemOpcode(WorldPacket & recv_data) 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; } @@ -91,11 +92,11 @@ void WorldSession::HandleSwapInvItemOpcode(WorldPacket & recv_data) _player->SwapItem(src, dst); } -void WorldSession::HandleAutoEquipItemSlotOpcode(WorldPacket & recv_data) +void WorldSession::HandleAutoEquipItemSlotOpcode(WorldPacket& recvData) { uint64 itemguid; uint8 dstslot; - recv_data >> itemguid >> dstslot; + recvData >> itemguid >> dstslot; // cheating attempt, client should never send opcode in that case if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, dstslot)) @@ -110,12 +111,12 @@ void WorldSession::HandleAutoEquipItemSlotOpcode(WorldPacket & recv_data) _player->SwapItem(item->GetPos(), dstpos); } -void WorldSession::HandleSwapItem(WorldPacket & recv_data) +void WorldSession::HandleSwapItem(WorldPacket& recvData) { //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_SWAP_ITEM"); uint8 dstbag, dstslot, srcbag, srcslot; - recv_data >> dstbag >> dstslot >> srcbag >> srcslot; + recvData >> dstbag >> dstslot >> srcbag >> srcslot; //sLog->outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u", srcbag, srcslot, dstbag, dstslot); uint16 src = ((srcbag << 8) | srcslot); @@ -133,19 +134,19 @@ void WorldSession::HandleSwapItem(WorldPacket & recv_data) 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; } _player->SwapItem(src, dst); } -void WorldSession::HandleAutoEquipItemOpcode(WorldPacket & recv_data) +void WorldSession::HandleAutoEquipItemOpcode(WorldPacket & recvData) { //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_AUTOEQUIP_ITEM"); uint8 srcbag, srcslot; - recv_data >> srcbag >> srcslot; + recvData >> srcbag >> srcslot; //sLog->outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); Item* pSrcItem = _player->GetItemByPos(srcbag, srcslot); @@ -234,12 +235,12 @@ void WorldSession::HandleAutoEquipItemOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleDestroyItemOpcode(WorldPacket & recv_data) +void WorldSession::HandleDestroyItemOpcode(WorldPacket & recvData) { - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_DESTROYITEM"); + //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_DESTROY_ITEM"); uint8 bag, slot, count, data1, data2, data3; - recv_data >> bag >> slot >> count >> data1 >> data2 >> data3; + recvData >> bag >> slot >> count >> data1 >> data2 >> data3; //sLog->outDebug("STORAGE: receive bag = %u, slot = %u, count = %u", bag, slot, count); uint16 pos = (bag << 8) | slot; @@ -264,7 +265,7 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket & recv_data) 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; } @@ -277,174 +278,176 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket & recv_data) _player->DestroyItem(bag, slot, true); } -// Only _static_ data send in this packet !!! -void WorldSession::HandleItemQuerySingleOpcode(WorldPacket & recv_data) +void WorldSession::SendItemDb2Reply(uint32 entry) { - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_ITEM_QUERY_SINGLE"); - uint32 item; - recv_data >> item; - - sLog->outInfo(LOG_FILTER_NETWORKIO, "STORAGE: Item Query = %u", item); - - ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item); - if (pProto) + WorldPacket data(SMSG_DB_REPLY, 44); + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(entry); + if (!proto) { - 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 << int32(pProto->Unk0); // new 2.0.3, not exist in wdb cache? - data << Name; - data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name... - data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00); - 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; - } + data << uint32(-1); // entry + data << uint32(DB2_REPLY_ITEM); + data << uint32(time(NULL)); // hotfix date + data << uint32(0); // size of next block + return; + } - // resistances (7) - data << pProto->Armor; - data << pProto->HolyRes; - data << pProto->FireRes; - data << pProto->NatureRes; - data << pProto->FrostRes; - data << pProto->ShadowRes; - data << pProto->ArcaneRes; + data << uint32(entry); + data << uint32(DB2_REPLY_ITEM); + data << uint32(sObjectMgr->GetHotfixDate(entry, DB2_REPLY_ITEM)); - data << pProto->Delay; - data << pProto->AmmoType; - data << pProto->RangedModRange; + ByteBuffer buff; + buff << uint32(entry); + buff << uint32(proto->Class); + buff << uint32(proto->SubClass); + buff << int32(proto->Unk0); + buff << uint32(proto->Material); + buff << uint32(proto->DisplayInfoID); + buff << uint32(proto->InventoryType); + buff << uint32(proto->Sheath); - 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 << uint32(buff.size()); + data.append(buff); - data << pProto->Spells[s].SpellId; - data << pProto->Spells[s].SpellTrigger; - data << uint32(-abs(pProto->Spells[s].SpellCharges)); + SendPacket(&data); +} - 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->Category); - 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 +void WorldSession::SendItemSparseDb2Reply(uint32 entry) +{ + WorldPacket data(SMSG_DB_REPLY, 526); + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(entry); + if (!proto) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "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); + data << uint32(-1); // entry + data << uint32(DB2_REPLY_SPARSE); + data << uint32(time(NULL)); // hotfix date + data << uint32(0); // size of next block + return; } + + data << uint32(entry); + data << uint32(DB2_REPLY_SPARSE); + data << uint32(sObjectMgr->GetHotfixDate(entry, DB2_REPLY_SPARSE)); + + ByteBuffer buff; + buff << uint32(entry); + buff << uint32(proto->Quality); + buff << uint32(proto->Flags); + buff << uint32(proto->Flags2); + buff << float(proto->Unk430_1); + buff << float(proto->Unk430_2); + buff << uint32(proto->BuyCount); + buff << int32(proto->BuyPrice); + buff << uint32(proto->SellPrice); + buff << uint32(proto->InventoryType); + buff << int32(proto->AllowableClass); + buff << int32(proto->AllowableRace); + buff << uint32(proto->ItemLevel); + buff << uint32(proto->RequiredLevel); + buff << uint32(proto->RequiredSkill); + buff << uint32(proto->RequiredSkillRank); + buff << uint32(proto->RequiredSpell); + buff << uint32(proto->RequiredHonorRank); + buff << uint32(proto->RequiredCityRank); + buff << uint32(proto->RequiredReputationFaction); + buff << uint32(proto->RequiredReputationRank); + buff << int32(proto->MaxCount); + buff << int32(proto->Stackable); + buff << uint32(proto->ContainerSlots); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) + buff << uint32(proto->ItemStat[x].ItemStatType); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) + buff << int32(proto->ItemStat[x].ItemStatValue); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) + buff << int32(proto->ItemStat[x].ItemStatUnk1); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) + buff << int32(proto->ItemStat[x].ItemStatUnk2); + + buff << uint32(proto->ScalingStatDistribution); + buff << uint32(proto->DamageType); + buff << uint32(proto->Delay); + buff << float(proto->RangedModRange); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) + buff << int32(proto->Spells[x].SpellId); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) + buff << uint32(proto->Spells[x].SpellTrigger); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) + buff << int32(proto->Spells[x].SpellCharges); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) + buff << int32(proto->Spells[x].SpellCooldown); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) + buff << uint32(proto->Spells[x].SpellCategory); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) + buff << int32(proto->Spells[x].SpellCategoryCooldown); + + buff << uint32(proto->Bonding); + + // item name + std::string name = proto->Name1; + buff << uint16(name.length()); + if (name.length()) + buff << name; + + for (uint32 i = 0; i < 3; ++i) // other 3 names + buff << uint16(0); + + std::string desc = proto->Description; + buff << uint16(desc.length()); + if (desc.length()) + buff << desc; + + buff << uint32(proto->PageText); + buff << uint32(proto->LanguageID); + buff << uint32(proto->PageMaterial); + buff << uint32(proto->StartQuest); + buff << uint32(proto->LockID); + buff << int32(proto->Material); + buff << uint32(proto->Sheath); + buff << int32(proto->RandomProperty); + buff << int32(proto->RandomSuffix); + buff << uint32(proto->ItemSet); + + buff << uint32(proto->Area); + buff << uint32(proto->Map); + buff << uint32(proto->BagFamily); + buff << uint32(proto->TotemCategory); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x) + buff << uint32(proto->Socket[x].Color); + + for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x) + buff << uint32(proto->Socket[x].Content); + + buff << uint32(proto->socketBonus); + buff << uint32(proto->GemProperties); + buff << float(proto->ArmorDamageModifier); + buff << int32(proto->Duration); + buff << uint32(proto->ItemLimitCategory); + buff << uint32(proto->HolidayId); + buff << float(proto->StatScalingFactor); // StatScalingFactor + buff << uint32(proto->CurrencySubstitutionId); + buff << uint32(proto->CurrencySubstitutionCount); + + data << uint32(buff.size()); + data.append(buff); + + SendPacket(&data); } -void WorldSession::HandleReadItem(WorldPacket & recv_data) +void WorldSession::HandleReadItem(WorldPacket& recvData) { - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_READ_ITEM"); - uint8 bag, slot; - recv_data >> bag >> slot; + recvData >> bag >> slot; - //sLog->outInfo(LOG_FILTER_NETWORKIO, "STORAGE: Read bag = %u, slot = %u", bag, slot); Item* pItem = _player->GetItemByPos(bag, slot); if (pItem && pItem->GetTemplate()->PageText) @@ -454,7 +457,7 @@ void WorldSession::HandleReadItem(WorldPacket & recv_data) InventoryResult msg = _player->CanUseItem(pItem); if (msg == EQUIP_ERR_OK) { - data.Initialize (SMSG_READ_ITEM_OK, 8); + data.Initialize(SMSG_READ_ITEM_OK, 8); sLog->outInfo(LOG_FILTER_NETWORKIO, "STORAGE: Item page sent"); } else @@ -470,26 +473,13 @@ void WorldSession::HandleReadItem(WorldPacket & recv_data) _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); } -void WorldSession::HandlePageQuerySkippedOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PAGE_TEXT_QUERY"); - - uint32 itemid; - uint64 guid; - - recv_data >> itemid >> guid; - - sLog->outInfo(LOG_FILTER_NETWORKIO, "Packet Info: itemid: %u guidlow: %u guidentry: %u guidhigh: %u", - itemid, GUID_LOPART(guid), GUID_ENPART(guid), GUID_HIPART(guid)); -} - -void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) +void WorldSession::HandleSellItemOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SELL_ITEM"); uint64 vendorguid, itemguid; uint32 count; - recv_data >> vendorguid >> itemguid >> count; + recvData >> vendorguid >> itemguid >> count; if (!itemguid) return; @@ -498,7 +488,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "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; } @@ -512,21 +502,21 @@ void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) // 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; } @@ -546,7 +536,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) // 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; } } @@ -562,7 +552,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) if (!pNewItem) { sLog->outError(LOG_FILTER_NETWORKIO, "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; } @@ -586,30 +576,30 @@ void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) uint32 money = pProto->SellPrice * count; _player->ModifyMoney(money); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money); + _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; } -void WorldSession::HandleBuybackItem(WorldPacket & recv_data) +void WorldSession::HandleBuybackItem(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUYBACK_ITEM"); uint64 vendorguid; uint32 slot; - recv_data >> vendorguid >> slot; + recvData >> vendorguid >> slot; Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR); if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "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; } @@ -621,7 +611,7 @@ void WorldSession::HandleBuybackItem(WorldPacket & recv_data) 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; @@ -634,7 +624,7 @@ void WorldSession::HandleBuybackItem(WorldPacket & recv_data) _player->ModifyMoney(-(int32)price); _player->RemoveItemFromBuyBackSlot(slot, false); _player->ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount()); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount()); + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount()); _player->StoreItem(dest, pItem, true); } else @@ -645,14 +635,14 @@ void WorldSession::HandleBuybackItem(WorldPacket & recv_data) _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, 0, 0); } -void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket & recv_data) +void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUY_ITEM_IN_SLOT"); uint64 vendorguid, bagguid; uint32 item, slot, count; uint8 bagslot; - recv_data >> vendorguid >> item >> slot >> bagguid >> bagslot >> count; + recvData >> vendorguid >> item >> slot >> bagguid >> bagslot >> count; // client expects count starting at 1, and we send vendorslot+1 to client already if (slot > 0) @@ -661,24 +651,15 @@ void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket & recv_data) 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) @@ -687,14 +668,15 @@ void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket & recv_data) GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, bag, bagslot); } -void WorldSession::HandleBuyItemOpcode(WorldPacket & recv_data) +void WorldSession::HandleBuyItemOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUY_ITEM"); - uint64 vendorguid; + uint64 vendorguid, bagGuid; uint32 item, slot, count; - uint8 unk1; + uint8 itemType; // 1 = item, 2 = currency + uint8 bagSlot; - recv_data >> 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) @@ -702,14 +684,27 @@ void WorldSession::HandleBuyItemOpcode(WorldPacket & recv_data) 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(); + + GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, bag, bagSlot); + } + else if (itemType == ITEM_VENDOR_TYPE_CURRENCY) + GetPlayer()->BuyCurrencyFromVendorSlot(vendorguid, slot, item, count); + else + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: received wrong itemType (%u) in HandleBuyItemOpcode", itemType); } -void WorldSession::HandleListInventoryOpcode(WorldPacket & recv_data) +void WorldSession::HandleListInventoryOpcode(WorldPacket & recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; if (!GetPlayer()->isAlive()) return; @@ -727,7 +722,7 @@ void WorldSession::SendListInventory(uint64 vendorGuid) if (!vendor) { sLog->outDebug(LOG_FILTER_NETWORKIO, "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; } @@ -739,80 +734,149 @@ 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; - - WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + itemCount * 8 * 4); - data << uint64(vendorGuid); + VendorItemData const* vendorItems = vendor->GetVendorItems(); + uint8 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0; - size_t countPos = data.wpos(); - data << uint8(count); + //if (rawItemCount > 300), + // rawItemCount = 300; // client cap but uint8 max value is 255 - float discountMod = _player->GetReputationPriceDiscount(vendor); + ByteBuffer itemsData(32 * rawItemCount); + std::vector<bool> enablers; + enablers.reserve(2 * rawItemCount); - for (uint8 slot = 0; slot < itemCount; ++slot) + const float discountMod = _player->GetReputationPriceDiscount(vendor); + uint8 count = 0; + for (uint8 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; + + 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())) 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))) + + // Do not sell BOP items + if (itemTemplate->Bonding == BIND_WHEN_PICKED_UP) + continue; + + // 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) + uint32 leftInStock = !vendorItem->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(vendorItem); + if (leftInStock == 0) continue; + } - ++count; + int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0; + uint32 leftInStock = !vendorItem->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(vendorItem); - // reputation discount - int32 price = item->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0; + itemsData << uint32(count++ + 1); // client expects counting to start at 1 + itemsData << uint32(itemTemplate->MaxDurability); - 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 (vendorItem->ExtendedCost != 0) + { + enablers.push_back(0); + itemsData << uint32(vendorItem->ExtendedCost); } + else + enablers.push_back(1); + enablers.push_back(1); // unk bit + + 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); } - } + else if (vendorItem->Type == ITEM_VENDOR_TYPE_CURRENCY) + { + CurrencyTypesEntry const* currencyTemplate = sCurrencyTypesStore.LookupEntry(vendorItem->item); - if (count == 0) - { - data << uint8(0); - SendPacket(&data); - return; + if (!currencyTemplate) continue; + + if (vendorItem->ExtendedCost == 0) continue; // there's no price defined for currencies, only extendedcost is used + + uint32 precision = (currencyTemplate->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? 100 : 1; + + itemsData << uint32(count++ + 1); // client expects counting to start at 1 + itemsData << uint32(0); // max durability + + if (vendorItem->ExtendedCost != 0) + { + enablers.push_back(0); + itemsData << uint32(vendorItem->ExtendedCost); + } + else + enablers.push_back(1); + enablers.push_back(1); // unk bit + + 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 * precision); + } + // else error } - data.put<uint8>(countPos, count); + uint8* guidBytes = (uint8*)&vendorGuid; + + WorldPacket data(SMSG_LIST_INVENTORY, 12 + itemsData.size()); + + data.WriteBit(guidBytes[1]); + data.WriteBit(guidBytes[0]); + + data.WriteBits(count, 21); // item count + + data.WriteBit(guidBytes[3]); + data.WriteBit(guidBytes[6]); + data.WriteBit(guidBytes[5]); + data.WriteBit(guidBytes[2]); + data.WriteBit(guidBytes[7]); + + for (std::vector<bool>::const_iterator itr = enablers.begin(); itr != enablers.end(); ++itr) + data.WriteBit(*itr); + + data.WriteBit(guidBytes[4]); + + data.FlushBits(); + data.append(itemsData); + + data.WriteByteSeq(guidBytes[5]); + data.WriteByteSeq(guidBytes[4]); + data.WriteByteSeq(guidBytes[1]); + data.WriteByteSeq(guidBytes[0]); + data.WriteByteSeq(guidBytes[6]); + + data << uint8(count == 0); // unk byte, item count 0: 1, item count != 0: 0 or some "random" value below 300 + + data.WriteByteSeq(guidBytes[2]); + data.WriteByteSeq(guidBytes[3]); + data.WriteByteSeq(guidBytes[7]); + SendPacket(&data); } -void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket & recv_data) +void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket& recvData) { //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_AUTOSTORE_BAG_ITEM"); uint8 srcbag, srcslot, dstbag; - recv_data >> srcbag >> srcslot >> dstbag; + recvData >> srcbag >> srcslot >> dstbag; //sLog->outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag); Item* pItem = _player->GetItemByPos(srcbag, srcslot); @@ -821,7 +885,7 @@ void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket & recv_data) 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; } @@ -850,7 +914,7 @@ void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket & recv_data) 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; } @@ -895,7 +959,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); @@ -903,12 +967,12 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket) } _player->SetBankBagSlotCount(slot); - _player->ModifyMoney(-int32(price)); + _player->ModifyMoney(-int64(price)); data << uint32(ERR_BANKSLOT_OK); SendPacket(&data); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT); + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT); } void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket) @@ -933,7 +997,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; } @@ -983,33 +1047,13 @@ void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket) } } -void WorldSession::HandleSetAmmoOpcode(WorldPacket & recv_data) -{ - if (!GetPlayer()->isAlive()) - { - GetPlayer()->SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL); - return; - } - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SET_AMMO"); - uint32 item; - - recv_data >> item; - - if (!item) - GetPlayer()->RemoveAmmo(); - else - GetPlayer()->SetAmmo(item); -} - void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster, uint32 ItemID, uint32 SpellID) { - WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10 - data << uint64(Target); - data << uint64(Caster); + WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 4.3.4 + data.appendPackGUID(Target); + data.appendPackGUID(Caster); data << uint32(ItemID); data << uint32(SpellID); - data << uint8(0); SendPacket(&data); } @@ -1024,38 +1068,14 @@ void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid, SendPacket(&data); } -void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data) -{ - uint32 itemid; - recv_data >> itemid; - recv_data.read_skip<uint64>(); // guid - - sLog->outDebug(LOG_FILTER_NETWORKIO, "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& recv_data) +void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_WRAP_ITEM"); uint8 gift_bag, gift_slot, item_bag, item_slot; - recv_data >> gift_bag >> gift_slot; // paper - recv_data >> item_bag >> item_slot; // item + recvData >> gift_bag >> gift_slot; // paper + recvData >> item_bag >> item_slot; // item sLog->outDebug(LOG_FILTER_NETWORKIO, "WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag, gift_slot, item_bag, item_slot); @@ -1082,44 +1102,44 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data) 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; } @@ -1159,19 +1179,19 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data) _player->DestroyItemCount(gift, count, true); } -void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) +void WorldSession::HandleSocketOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SOCKET_GEMS"); uint64 item_guid; uint64 gem_guids[MAX_GEM_SOCKETS]; - recv_data >> item_guid; + recvData >> item_guid; if (!item_guid) return; for (int i = 0; i < MAX_GEM_SOCKETS; ++i) - recv_data >> gem_guids[i]; + recvData >> gem_guids[i]; //cheat -> tried to socket same gem multiple times if ((gem_guids[0] && (gem_guids[0] == gem_guids[1] || gem_guids[0] == gem_guids[2])) || @@ -1223,6 +1243,14 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) // 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]; @@ -1329,9 +1357,10 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) { if (GemEnchants[i]) { + uint32 gemCount = 1; itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i], 0, 0); if (Item* guidItem = _player->GetItemByGuid(gem_guids[i])) - _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true); + _player->DestroyItemCount(guidItem, gemCount, true); } } @@ -1353,19 +1382,19 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) itemTarget->ClearSoulboundTradeable(_player); // clear tradeable flag } -void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data) +void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT"); - uint32 eslot; + uint32 slot; - recv_data >> 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; @@ -1377,12 +1406,12 @@ void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data) item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT); } -void WorldSession::HandleItemRefundInfoRequest(WorldPacket& recv_data) +void WorldSession::HandleItemRefundInfoRequest(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_ITEM_REFUND_INFO"); uint64 guid; - recv_data >> guid; // item guid + recvData >> guid; // item guid Item* item = _player->GetItemByGuid(guid); if (!item) @@ -1394,11 +1423,11 @@ void WorldSession::HandleItemRefundInfoRequest(WorldPacket& recv_data) GetPlayer()->SendRefundInfo(item); } -void WorldSession::HandleItemRefund(WorldPacket &recv_data) +void WorldSession::HandleItemRefund(WorldPacket &recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_ITEM_REFUND"); uint64 guid; - recv_data >> guid; // item guid + recvData >> guid; // item guid Item* item = _player->GetItemByGuid(guid); if (!item) @@ -1415,14 +1444,14 @@ void WorldSession::HandleItemRefund(WorldPacket &recv_data) * * This function is called when player clicks on item which has some flag set */ -void WorldSession::HandleItemTextQuery(WorldPacket & recv_data ) +void WorldSession::HandleItemTextQuery(WorldPacket & recvData ) { uint64 itemGuid; - recv_data >> itemGuid; + recvData >> itemGuid; sLog->outDebug(LOG_FILTER_NETWORKIO, "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)) { @@ -1437,3 +1466,263 @@ void WorldSession::HandleItemTextQuery(WorldPacket & recv_data ) SendPacket(&data); } + +void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_TRANSMOGRIFY_ITEMS"); + Player* player = GetPlayer(); + + // Read data + uint32 count = recvData.ReadBits(22); + + if (count < EQUIPMENT_SLOT_START || count >= EQUIPMENT_SLOT_END) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) sent a wrong count (%u) when transmogrifying items.", player->GetGUIDLow(), player->GetName(), 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)) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "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_START || slots[i] >= EQUIPMENT_SLOT_END) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "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(), 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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify to an invalid item (entry: %u).", player->GetGUIDLow(), player->GetName(), 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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify with an invalid item (lowguid: %u).", player->GetGUIDLow(), player->GetName(), GUID_LOPART(itemGuids[i])); + return; + } + } + + // transmogrified item + Item* itemTransmogrified = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slots[i]); + if (!itemTransmogrified) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify an invalid item in a valid slot (slot: %u).", player->GetGUIDLow(), player->GetName(), slots[i]); + return; + } + + // uint16 tempDest; + //// has to be able to equip item transmogrified item + //if (!player->CanEquipItem(slots[i], tempDest, itemTransmogrified, true, true)) + //{ + // sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) can't equip the item to be transmogrified (slot: %u, entry: %u).", player->GetGUIDLow(), player->GetName(), slots[i], itemTransmogrified->GetEntry()); + // return; + //} + // + //// has to be able to equip item transmogrifier item + //if (!player->CanEquipItem(slots[i], tempDest, itemTransmogrifier, true, true)) + //{ + // sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) can't equip the transmogrifier item (slot: %u, entry: %u).", player->GetGUIDLow(), player->GetName(), slots[i], itemTransmogrifier->GetEntry()); + // return; + //} + + if (!newEntries[i]) // reset look + { + itemTransmogrified->ClearEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT); + player->SetVisibleItemSlot(slots[i], itemTransmogrified); + } + else + { + if (!Item::CanTransmogrifyItemWithItem(itemTransmogrified, itemTransmogrifier)) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) failed CanTransmogrifyItemWithItem (%u with %u).", player->GetGUIDLow(), player->GetName(), 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); + + 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)) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to reforge an invalid/non-existant item.", player->GetGUIDLow(), player->GetName()); + SendReforgeResult(false); + return; + } + + if (!reforgeEntry) + { + // Reset the item + if (item->IsEquipped()) + player->ApplyReforgeEnchantment(item, false); + item->ClearEnchantment(REFORGE_ENCHANTMENT_SLOT); + SendReforgeResult(true); + return; + } + + ItemReforgeEntry const* stats = sItemReforgeStore.LookupEntry(reforgeEntry); + if (!stats) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to reforge an item with invalid reforge entry (%u).", player->GetGUIDLow(), player->GetName(), 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); +} diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index aa6d208ad3a..b4f74735568 100755 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -32,6 +32,8 @@ void BuildPlayerLockDungeonBlock(WorldPacket& data, const LfgLockMap& lock) { data << uint32(it->first); // Dungeon entry (id + type) data << uint32(it->second); // Lock status + data << uint32(0); // Unknown 4.2.2 + data << uint32(0); // Unknown 4.2.2 } } @@ -45,13 +47,13 @@ void BuildPartyLockDungeonBlock(WorldPacket& data, const LfgLockPartyMap& lockMa } } -void WorldSession::HandleLfgJoinOpcode(WorldPacket& recv_data) +void WorldSession::HandleLfgJoinOpcode(WorldPacket& recvData) { if (!sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE) || (GetPlayer()->GetGroup() && GetPlayer()->GetGroup()->GetLeaderGUID() != GetPlayer()->GetGUID() && (GetPlayer()->GetGroup()->GetMembersCount() == MAXGROUPSIZE || !GetPlayer()->GetGroup()->isLFGGroup()))) { - recv_data.rfinish(); + recvData.rfinish(); return; } @@ -59,32 +61,32 @@ void WorldSession::HandleLfgJoinOpcode(WorldPacket& recv_data) uint32 dungeon; uint32 roles; - recv_data >> roles; - recv_data.read_skip<uint16>(); // uint8 (always 0) - uint8 (always 0) - recv_data >> numDungeons; + recvData >> roles; + recvData.read_skip<uint16>(); // uint8 (always 0) - uint8 (always 0) + recvData >> numDungeons; if (!numDungeons) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_JOIN [" UI64FMTD "] no dungeons selected", GetPlayer()->GetGUID()); - recv_data.rfinish(); + recvData.rfinish(); return; } LfgDungeonSet newDungeons; for (int8 i = 0; i < numDungeons; ++i) { - recv_data >> dungeon; + recvData >> dungeon; newDungeons.insert((dungeon & 0x00FFFFFF)); // remove the type from the dungeon entry } - recv_data.read_skip<uint32>(); // for 0..uint8 (always 3) { uint8 (always 0) } + recvData.read_skip<uint32>(); // for 0..uint8 (always 3) { uint8 (always 0) } std::string comment; - recv_data >> comment; + recvData >> comment; sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_JOIN [" UI64FMTD "] roles: %u, Dungeons: %u, Comment: %s", GetPlayer()->GetGUID(), roles, uint8(newDungeons.size()), comment.c_str()); sLFGMgr->Join(GetPlayer(), uint8(roles), newDungeons, comment); } -void WorldSession::HandleLfgLeaveOpcode(WorldPacket& /*recv_data*/) +void WorldSession::HandleLfgLeaveOpcode(WorldPacket& /*recvData*/) { Group* grp = GetPlayer()->GetGroup(); @@ -95,21 +97,21 @@ void WorldSession::HandleLfgLeaveOpcode(WorldPacket& /*recv_data*/) sLFGMgr->Leave(GetPlayer(), grp); } -void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recv_data) +void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recvData) { uint32 lfgGroupID; // Internal lfgGroupID bool accept; // Accept to join? - recv_data >> lfgGroupID; - recv_data >> accept; + recvData >> lfgGroupID; + recvData >> accept; sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_PROPOSAL_RESULT [" UI64FMTD "] proposal: %u accept: %u", GetPlayer()->GetGUID(), lfgGroupID, accept ? 1 : 0); sLFGMgr->UpdateProposal(lfgGroupID, GetPlayer()->GetGUID(), accept); } -void WorldSession::HandleLfgSetRolesOpcode(WorldPacket& recv_data) +void WorldSession::HandleLfgSetRolesOpcode(WorldPacket& recvData) { uint8 roles; - recv_data >> roles; // Player Group Roles + recvData >> roles; // Player Group Roles uint64 guid = GetPlayer()->GetGUID(); Group* grp = GetPlayer()->GetGroup(); if (!grp) @@ -122,35 +124,35 @@ void WorldSession::HandleLfgSetRolesOpcode(WorldPacket& recv_data) sLFGMgr->UpdateRoleCheck(gguid, guid, roles); } -void WorldSession::HandleLfgSetCommentOpcode(WorldPacket& recv_data) +void WorldSession::HandleLfgSetCommentOpcode(WorldPacket& recvData) { std::string comment; - recv_data >> comment; + recvData >> comment; uint64 guid = GetPlayer()->GetGUID(); sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SET_LFG_COMMENT [" UI64FMTD "] comment: %s", guid, comment.c_str()); sLFGMgr->SetComment(guid, comment); } -void WorldSession::HandleLfgSetBootVoteOpcode(WorldPacket& recv_data) +void WorldSession::HandleLfgSetBootVoteOpcode(WorldPacket& recvData) { bool agree; // Agree to kick player - recv_data >> agree; + recvData >> agree; sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_BOOT_VOTE [" UI64FMTD "] agree: %u", GetPlayer()->GetGUID(), agree ? 1 : 0); sLFGMgr->UpdateBoot(GetPlayer(), agree); } -void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recv_data) +void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recvData) { bool out; - recv_data >> out; + recvData >> out; sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_TELEPORT [" UI64FMTD "] out: %u", GetPlayer()->GetGUID(), out ? 1 : 0); sLFGMgr->TeleportPlayer(GetPlayer(), out, true); } -void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data*/) +void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recvData*/) { uint64 guid = GetPlayer()->GetGUID(); sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST [" UI64FMTD "]", guid); @@ -231,7 +233,7 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data SendPacket(&data); } -void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recv_data*/) +void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recvData*/) { uint64 guid = GetPlayer()->GetGUID(); sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFD_PARTY_LOCK_INFO_REQUEST [" UI64FMTD "]", guid); @@ -257,7 +259,7 @@ void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recv_data uint32 size = 0; for (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); sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PARTY_INFO [" UI64FMTD "]", guid); WorldPacket data(SMSG_LFG_PARTY_INFO, 1 + size); @@ -265,18 +267,18 @@ void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recv_data SendPacket(&data); } -void WorldSession::HandleLfrSearchOpcode(WorldPacket& recv_data) +void WorldSession::HandleLfrSearchOpcode(WorldPacket& recvData) { uint32 entry; // Raid id to search - recv_data >> entry; + recvData >> entry; sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SEARCH_LFG_JOIN [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), entry); //SendLfrUpdateListOpcode(entry); } -void WorldSession::HandleLfrLeaveOpcode(WorldPacket& recv_data) +void WorldSession::HandleLfrLeaveOpcode(WorldPacket& recvData) { uint32 dungeonId; // Raid id queue to leave - recv_data >> dungeonId; + recvData >> dungeonId; sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SEARCH_LFG_LEAVE [" UI64FMTD "] dungeonId: %u", GetPlayer()->GetGUID(), dungeonId); //sLFGMgr->LeaveLfr(GetPlayer(), dungeonId); } @@ -444,7 +446,7 @@ void WorldSession::SendLfgJoinResult(const LfgJoinResultData& joinData) { uint32 size = 0; for (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); sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_JOIN_RESULT [" UI64FMTD "] checkResult: %u checkValue: %u", GetPlayer()->GetGUID(), joinData.result, joinData.state); WorldPacket data(SMSG_LFG_JOIN_RESULT, 4 + 4 + size); @@ -531,6 +533,7 @@ void WorldSession::SendLfgBootPlayer(const LfgPlayerBoot* pBoot) data << uint8(pBoot->inProgress); // Vote in progress data << uint8(playerVote != LFG_ANSWER_PENDING); // Did Vote data << uint8(playerVote == LFG_ANSWER_AGREE); // Agree + data << uint8(0); // Unknown 4.2.2 data << uint64(pBoot->victim); // Victim GUID data << uint32(votesNum); // Total Votes data << uint32(agreeNum); // Agree Count @@ -657,8 +660,8 @@ void WorldSession::SendLfgTeleportError(uint8 err) /* void WorldSession::SendLfrUpdateListOpcode(uint32 dungeonEntry) { - sLog->outDebug(LOG_FILTER_PACKETIO, "SMSG_UPDATE_LFG_LIST [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), dungeonEntry); - WorldPacket data(SMSG_UPDATE_LFG_LIST); + sLog->outDebug(LOG_FILTER_PACKETIO, "SMSG_LFG_UPDATE_LIST [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), dungeonEntry); + WorldPacket data(SMSG_LFG_UPDATE_LIST); SendPacket(&data); } */ diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index 8259d0c4e9b..aa4b7b85023 100755 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -30,7 +30,7 @@ #include "World.h" #include "Util.h" -void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) +void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player* player = GetPlayer(); @@ -38,7 +38,7 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) Loot* loot = NULL; uint8 lootSlot = 0; - recv_data >> lootSlot; + recvData >> lootSlot; if (IS_GAMEOBJECT_GUID(lguid)) { @@ -94,7 +94,7 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) player->StoreLootItem(lootSlot, loot); } -void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_LOOT_MONEY"); @@ -179,7 +179,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(goldPerPlayer); - (*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer); + (*i)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(goldPerPlayer); @@ -190,7 +190,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) else { player->ModifyMoney(loot->gold); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(loot->gold); @@ -202,12 +202,12 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) } } -void WorldSession::HandleLootOpcode(WorldPacket & recv_data) +void WorldSession::HandleLootOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_LOOT"); uint64 guid; - recv_data >> guid; + recvData >> guid; // Check possible cheat if (!_player->isAlive()) @@ -428,12 +428,12 @@ void WorldSession::DoLootRelease(uint64 lguid) loot->RemoveLooter(player->GetGUID()); } -void WorldSession::HandleLootMasterGiveOpcode(WorldPacket & recv_data) +void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData) { uint8 slotid; uint64 lootguid, target_playerguid; - recv_data >> lootguid >> slotid >> target_playerguid; + recvData >> lootguid >> slotid >> target_playerguid; if (!_player->GetGroup() || _player->GetGroup()->GetLooterGuid() != _player->GetGUID()) { @@ -483,7 +483,7 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket & recv_data) 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); @@ -498,9 +498,9 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket & recv_data) // not move item from loot to target inventory Item* newitem = target->StoreNewItem(dest, item.itemid, true, item.randomPropertyId, looters); target->SendNewItem(newitem, uint32(item.count), false, false, true); - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count); - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, loot->loot_type, item.count); - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item.itemid, item.count); + 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_EPIC_ITEM, item.itemid, item.count); // mark as looted item.count=0; diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index ae04444a118..f89fa2ab25e 100755..100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -29,43 +29,84 @@ #include "Item.h" #include "AccountMgr.h" -void WorldSession::HandleSendMail(WorldPacket & recv_data) +void WorldSession::HandleSendMail(WorldPacket& recvData) { - uint64 mailbox, unk3; + ObjectGuid mailbox; + uint64 money, COD; std::string receiver, subject, body; - uint32 unk1, unk2, money, COD; - uint8 unk4; - recv_data >> mailbox; - recv_data >> receiver; + uint32 bodyLength, subjectLength, receiverLength; + uint32 unk1, unk2; - recv_data >> subject; + recvData >> unk1; + recvData >> unk2; // Stationery? - recv_data >> body; + recvData >> money >> COD; // money and cod + bodyLength = recvData.ReadBits(12); + subjectLength = recvData.ReadBits(9); - recv_data >> unk1; // stationery? - recv_data >> unk2; // 0x00000000 - - uint8 items_count; - recv_data >> items_count; // attached items count + uint8 items_count = recvData.ReadBits(5); // attached items count if (items_count > MAX_MAIL_ITEMS) // client limit { GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS); - recv_data.rfinish(); // set to end to avoid warnings spam + recvData.rfinish(); // set to end to avoid warnings spam return; } - uint64 itemGUIDs[MAX_MAIL_ITEMS]; + mailbox[0] = recvData.ReadBit(); + + ObjectGuid itemGUIDs[MAX_MAIL_ITEMS]; + + for (uint8 i = 0; i < items_count; ++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(); + } + + 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) { - recv_data.read_skip<uint8>(); // item slot in mail, not used - recv_data >> itemGUIDs[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]); } - recv_data >> money >> COD; // money and cod - recv_data >> unk3; // const 0 - recv_data >> unk4; // const 0 + recvData.ReadByteSeq(mailbox[7]); + recvData.ReadByteSeq(mailbox[3]); + recvData.ReadByteSeq(mailbox[6]); + recvData.ReadByteSeq(mailbox[5]); + + subject = recvData.ReadString(subjectLength); + receiver = 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 @@ -89,13 +130,13 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) if (!rc) { - sLog->outInfo(LOG_FILTER_NETWORKIO, "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", + sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } - sLog->outInfo(LOG_FILTER_NETWORKIO, "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", player->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); + sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); if (player->GetGUID() == rc) { @@ -105,7 +146,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client - uint32 reqmoney = cost + money; + uint64 reqmoney = cost + money; if (!player->HasEnoughMoney(reqmoney) && !player->isGameMaster()) { @@ -218,7 +259,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != rc_account) { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS); + player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_NOT_SAME_ACCOUNT); return; } @@ -236,7 +277,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) 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; } @@ -245,8 +286,8 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) player->SendMailResult(0, MAIL_SEND, MAIL_OK); - player->ModifyMoney(-int32(reqmoney)); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); + player->ModifyMoney(-int64(reqmoney)); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); bool needItemDelay = false; @@ -283,7 +324,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) if (money > 0 && !AccountMgr::IsPlayerAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail money: %u to player: %s (Account: %u)", + sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail money: " UI64FMTD " to player: %s (Account: %u)", GetPlayerName().c_str(), GetAccountId(), money, receiver.c_str(), rc_account); } } @@ -302,12 +343,12 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) } //called when mail is read -void WorldSession::HandleMailMarkAsRead(WorldPacket & recv_data) +void WorldSession::HandleMailMarkAsRead(WorldPacket & recvData) { uint64 mailbox; uint32 mailId; - recv_data >> mailbox; - recv_data >> mailId; + recvData >> mailbox; + recvData >> mailId; if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; @@ -325,13 +366,13 @@ void WorldSession::HandleMailMarkAsRead(WorldPacket & recv_data) } //called when client deletes mail -void WorldSession::HandleMailDelete(WorldPacket & recv_data) +void WorldSession::HandleMailDelete(WorldPacket & recvData) { uint64 mailbox; uint32 mailId; - recv_data >> mailbox; - recv_data >> mailId; - recv_data.read_skip<uint32>(); // mailTemplateId + recvData >> mailbox; + recvData >> mailId; + recvData.read_skip<uint32>(); // mailTemplateId if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; @@ -353,13 +394,13 @@ void WorldSession::HandleMailDelete(WorldPacket & recv_data) player->SendMailResult(mailId, MAIL_DELETED, MAIL_OK); } -void WorldSession::HandleMailReturnToSender(WorldPacket & recv_data) +void WorldSession::HandleMailReturnToSender(WorldPacket & recvData) { uint64 mailbox; uint32 mailId; - recv_data >> mailbox; - recv_data >> mailId; - recv_data.read_skip<uint64>(); // original sender GUID for return to, not used + recvData >> mailbox; + recvData >> mailId; + recvData.read_skip<uint64>(); // original sender GUID for return to, not used if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; @@ -417,14 +458,14 @@ void WorldSession::HandleMailReturnToSender(WorldPacket & recv_data) } //called when player takes item attached in mail -void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) +void WorldSession::HandleMailTakeItem(WorldPacket& recvData) { uint64 mailbox; uint32 mailId; uint32 itemId; - recv_data >> mailbox; - recv_data >> mailId; - recv_data >> itemId; // item guid low + recvData >> mailbox; + recvData >> mailId; + recvData >> itemId; // item guid low if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; @@ -439,7 +480,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) } // 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; @@ -478,7 +519,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) if (!sObjectMgr->GetPlayerNameByGUID(sender_guid, sender_name)) sender_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN); } - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receive mail item: %s (Entry: %u Count: %u) and send COD money: %u to player: %s (Account: %u)", + sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receive 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 (!receive) @@ -512,12 +553,15 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_EQUIP_ERROR, msg); } -void WorldSession::HandleMailTakeMoney(WorldPacket & recv_data) +void WorldSession::HandleMailTakeMoney(WorldPacket& recvData) { uint64 mailbox; + uint64 money; uint32 mailId; - recv_data >> mailbox; - recv_data >> mailId; + + recvData >> mailbox; + recvData >> mailId; + recvData >> money; if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; @@ -525,7 +569,8 @@ void WorldSession::HandleMailTakeMoney(WorldPacket & recv_data) 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; @@ -533,7 +578,7 @@ void WorldSession::HandleMailTakeMoney(WorldPacket & recv_data) player->SendMailResult(mailId, MAIL_MONEY_TAKEN, MAIL_OK); - player->ModifyMoney(m->money); + player->ModifyMoney(money); m->money = 0; m->state = MAIL_STATE_CHANGED; player->m_mailsUpdated = true; @@ -546,10 +591,10 @@ void WorldSession::HandleMailTakeMoney(WorldPacket & recv_data) } //called when player lists his received mails -void WorldSession::HandleGetMailList(WorldPacket & recv_data) +void WorldSession::HandleGetMailList(WorldPacket& recvData) { uint64 mailbox; - recv_data >> mailbox; + recvData >> mailbox; if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; @@ -566,7 +611,7 @@ void WorldSession::HandleGetMailList(WorldPacket & recv_data) 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); @@ -613,10 +658,10 @@ void WorldSession::HandleGetMailList(WorldPacket & recv_data) 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(((*itr)->expire_time-time(NULL))/DAY); // Time data << uint32((*itr)->mailTemplateId); // mail template (MailTemplate.dbc) @@ -668,13 +713,13 @@ void WorldSession::HandleGetMailList(WorldPacket & recv_data) } //used when player copies mail body to his inventory -void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data) +void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData) { uint64 mailbox; uint32 mailId; - recv_data >> mailbox; - recv_data >> mailId; + recvData >> mailbox; + recvData >> mailId; if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; @@ -705,7 +750,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data) return; } - bodyItem->SetText(mailTemplateEntry->content[GetSessionDbcLocale()]); + bodyItem->SetText(mailTemplateEntry->content); } else bodyItem->SetText(m->body); @@ -734,7 +779,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data) } //TODO Fix me! ... this void has probably bad condition, but good data are sent -void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recv_data*/) +void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recvData*/) { WorldPacket data(MSG_QUERY_NEXT_MAIL_TIME, 8); diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 80caee7d896..677b3cccf82 100755..100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -56,11 +56,11 @@ #include "Battlefield.h" #include "BattlefieldMgr.h" -void WorldSession::HandleRepopRequestOpcode(WorldPacket & recv_data) +void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_REPOP_REQUEST Message"); - recv_data.read_skip<uint8>(); + recvData.read_skip<uint8>(); // FromLua ? if (GetPlayer()->isAlive() || GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) return; @@ -85,7 +85,7 @@ void WorldSession::HandleRepopRequestOpcode(WorldPacket & recv_data) GetPlayer()->RepopAtGraveyard(); } -void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) +void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GOSSIP_SELECT_OPTION"); @@ -94,10 +94,10 @@ void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) uint64 guid; std::string code = ""; - recv_data >> guid >> menuId >> gossipListId; + recvData >> guid >> menuId >> gossipListId; if (_player->PlayerTalkClass->IsGossipOptionCoded(gossipListId)) - recv_data >> code; + recvData >> code; Creature* unit = NULL; GameObject* go = NULL; @@ -170,7 +170,7 @@ void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleWhoOpcode(WorldPacket & recv_data) +void WorldSession::HandleWhoOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_WHO Message"); @@ -185,15 +185,15 @@ void WorldSession::HandleWhoOpcode(WorldPacket & recv_data) uint32 zoneids[10]; // 10 is client limit std::string player_name, guild_name; - recv_data >> level_min; // maximal player level, default 0 - recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL) - recv_data >> player_name; // player name, case sensitive... + recvData >> level_min; // maximal player level, default 0 + recvData >> level_max; // minimal player level, default 100 (MAX_LEVEL) + recvData >> player_name; // player name, case sensitive... - recv_data >> guild_name; // guild name, case sensitive... + recvData >> guild_name; // guild name, case sensitive... - recv_data >> racemask; // race mask - recv_data >> classmask; // class mask - recv_data >> zones_count; // zones count, client limit = 10 (2.0.10) + recvData >> racemask; // race mask + recvData >> classmask; // class mask + recvData >> zones_count; // zones count, client limit = 10 (2.0.10) if (zones_count > 10) return; // can't be received from real client or broken packet @@ -201,12 +201,12 @@ void WorldSession::HandleWhoOpcode(WorldPacket & recv_data) for (uint32 i = 0; i < zones_count; ++i) { uint32 temp; - recv_data >> temp; // zone id, 0 if zone is unknown... + recvData >> temp; // zone id, 0 if zone is unknown... zoneids[i] = temp; sLog->outDebug(LOG_FILTER_NETWORKIO, "Zone %u: %u", i, zoneids[i]); } - recv_data >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10) + recvData >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10) if (str_count > 4) return; // can't be received from real client or broken packet @@ -217,7 +217,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket & recv_data) for (uint32 i = 0; i < str_count; ++i) { std::string temp; - recv_data >> temp; // user entered string, it used as universal search pattern(guild+player name)? + recvData >> temp; // user entered string, it used as universal search pattern(guild+player name)? if (!Utf8toWStr(temp, str[i])) continue; @@ -367,14 +367,14 @@ void WorldSession::HandleWhoOpcode(WorldPacket & recv_data) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Send SMSG_WHO Message"); } -void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_LOGOUT_REQUEST Message, security - %u", GetSecurity()); if (uint64 lguid = GetPlayer()->GetLootGUID()) DoLootRelease(lguid); - uint8 reason = 0; + uint32 reason = 0; if (GetPlayer()->isInCombat()) reason = 1; @@ -386,8 +386,8 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/) if (reason) { WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); - data << uint8(reason); - data << uint32(0); + data << uint32(reason); + data << uint8(0); SendPacket(&data); LogoutRequest(0); return; @@ -398,8 +398,8 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/) GetSecurity() >= AccountTypes(sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT))) { WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); - data << uint8(0); - data << uint32(16777216); + data << uint32(reason); + data << uint8(1); // instant logout SendPacket(&data); LogoutPlayer(true); return; @@ -409,27 +409,23 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/) 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); } WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); - data << uint8(0); data << uint32(0); + data << uint8(0); SendPacket(&data); LogoutRequest(time(NULL)); } -void WorldSession::HandlePlayerLogoutOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandlePlayerLogoutOpcode(WorldPacket & /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_PLAYER_LOGOUT Message"); } -void WorldSession::HandleLogoutCancelOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleLogoutCancelOpcode(WorldPacket & /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_LOGOUT_CANCEL Message"); @@ -446,10 +442,7 @@ void WorldSession::HandleLogoutCancelOpcode(WorldPacket & /*recv_data*/) 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); @@ -461,13 +454,13 @@ void WorldSession::HandleLogoutCancelOpcode(WorldPacket & /*recv_data*/) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_LOGOUT_CANCEL_ACK Message"); } -void WorldSession::HandleTogglePvP(WorldPacket & recv_data) +void WorldSession::HandleTogglePvP(WorldPacket& recvData) { // this opcode can be used in two ways: Either set explicit new status or toggle old status - if (recv_data.size() == 1) + if (recvData.size() == 1) { bool newPvPStatus; - recv_data >> newPvPStatus; + recvData >> newPvPStatus; GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP, newPvPStatus); GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER, !newPvPStatus); } @@ -492,10 +485,10 @@ void WorldSession::HandleTogglePvP(WorldPacket & recv_data) // pvp->HandlePlayerActivityChanged(_player); } -void WorldSession::HandleZoneUpdateOpcode(WorldPacket & recv_data) +void WorldSession::HandleZoneUpdateOpcode(WorldPacket & recvData) { uint32 newZone; - recv_data >> newZone; + recvData >> newZone; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd ZONE_UPDATE: %u", newZone); @@ -506,41 +499,47 @@ void WorldSession::HandleZoneUpdateOpcode(WorldPacket & recv_data) //GetPlayer()->SendInitWorldStates(true, newZone); } -void WorldSession::HandleSetSelectionOpcode(WorldPacket & recv_data) +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; - recv_data >> guid; + recvData >> guid; _player->SetSelection(guid); } -void WorldSession::HandleStandStateChangeOpcode(WorldPacket & recv_data) +void WorldSession::HandleStandStateChangeOpcode(WorldPacket & recvData) { // sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: Received CMSG_STANDSTATECHANGE"); -- too many spam in log at lags/debug stop uint32 animstate; - recv_data >> animstate; + recvData >> animstate; _player->SetStandState(animstate); } -void WorldSession::HandleContactListOpcode(WorldPacket & recv_data) +void WorldSession::HandleContactListOpcode(WorldPacket& recvData) { - uint32 unk; - recv_data >> unk; - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_CONTACT_LIST - Unk: %d", unk); + recvData.read_skip<uint32>(); // always 1 + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_CONTACT_LIST"); _player->GetSocial()->SendSocialList(_player); } -void WorldSession::HandleAddFriendOpcode(WorldPacket & recv_data) +void WorldSession::HandleAddFriendOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ADD_FRIEND"); std::string friendName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN); std::string friendNote; - recv_data >> friendName; + recvData >> friendName; - recv_data >> friendNote; + recvData >> friendNote; if (!normalizePlayerName(friendName)) return; @@ -609,13 +608,13 @@ void WorldSession::HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_FRIEND_STATUS)"); } -void WorldSession::HandleDelFriendOpcode(WorldPacket & recv_data) +void WorldSession::HandleDelFriendOpcode(WorldPacket& recvData) { uint64 FriendGUID; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_DEL_FRIEND"); - recv_data >> FriendGUID; + recvData >> FriendGUID; _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(FriendGUID), false); @@ -624,13 +623,13 @@ void WorldSession::HandleDelFriendOpcode(WorldPacket & recv_data) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent motd (SMSG_FRIEND_STATUS)"); } -void WorldSession::HandleAddIgnoreOpcode(WorldPacket & recv_data) +void WorldSession::HandleAddIgnoreOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ADD_IGNORE"); std::string ignoreName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN); - recv_data >> ignoreName; + recvData >> ignoreName; if (!normalizePlayerName(ignoreName)) return; @@ -682,13 +681,13 @@ void WorldSession::HandleAddIgnoreOpcodeCallBack(PreparedQueryResult result) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_FRIEND_STATUS)"); } -void WorldSession::HandleDelIgnoreOpcode(WorldPacket & recv_data) +void WorldSession::HandleDelIgnoreOpcode(WorldPacket & recvData) { uint64 IgnoreGUID; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_DEL_IGNORE"); - recv_data >> IgnoreGUID; + recvData >> IgnoreGUID; _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(IgnoreGUID), true); @@ -697,23 +696,23 @@ void WorldSession::HandleDelIgnoreOpcode(WorldPacket & recv_data) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent motd (SMSG_FRIEND_STATUS)"); } -void WorldSession::HandleSetContactNotesOpcode(WorldPacket & recv_data) +void WorldSession::HandleSetContactNotesOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SET_CONTACT_NOTES"); uint64 guid; std::string note; - recv_data >> guid >> note; + recvData >> guid >> note; _player->GetSocial()->SetFriendNote(GUID_LOPART(guid), note); } -void WorldSession::HandleBugOpcode(WorldPacket & recv_data) +void WorldSession::HandleBugOpcode(WorldPacket & recvData) { uint32 suggestion, contentlen, typelen; std::string content, type; - recv_data >> suggestion >> contentlen >> content; + recvData >> suggestion >> contentlen >> content; - recv_data >> typelen >> type; + recvData >> typelen >> type; if (suggestion == 0) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUG [Bug Report]"); @@ -731,12 +730,12 @@ void WorldSession::HandleBugOpcode(WorldPacket & recv_data) CharacterDatabase.Execute(stmt); } -void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) +void WorldSession::HandleReclaimCorpseOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_RECLAIM_CORPSE"); uint64 guid; - recv_data >> guid; + recvData >> guid; if (GetPlayer()->isAlive()) return; @@ -768,14 +767,14 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) GetPlayer()->SpawnCorpseBones(); } -void WorldSession::HandleResurrectResponseOpcode(WorldPacket & recv_data) +void WorldSession::HandleResurrectResponseOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_RESURRECT_RESPONSE"); uint64 guid; uint8 status; - recv_data >> guid; - recv_data >> status; + recvData >> guid; + recvData >> status; if (GetPlayer()->isAlive()) return; @@ -809,10 +808,10 @@ void WorldSession::SendAreaTriggerMessage(const char* Text, ...) SendPacket(&data); } -void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data) +void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData) { uint32 triggerId; - recv_data >> triggerId; + recvData >> triggerId; sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_AREATRIGGER. Trigger ID: %u", triggerId); @@ -939,12 +938,12 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data) player->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, at->target_Orientation, TELE_TO_NOT_LEAVE_TRANSPORT); } -void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) +void WorldSession::HandleUpdateAccountData(WorldPacket &recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); uint32 type, timestamp, decompressedSize; - recv_data >> type >> timestamp >> decompressedSize; + recvData >> type >> timestamp >> decompressedSize; sLog->outDebug(LOG_FILTER_NETWORKIO, "UAD: type %u, time %u, decompressedSize %u", type, timestamp, decompressedSize); @@ -965,7 +964,7 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) if (decompressedSize > 0xFFFF) { - recv_data.rfinish(); // unnneded warning spam in this case + recvData.rfinish(); // unnneded warning spam in this case sLog->outError(LOG_FILTER_NETWORKIO, "UAD: Account data packet too big, size %u", decompressedSize); return; } @@ -974,14 +973,14 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) dest.resize(decompressedSize); uLongf realSize = decompressedSize; - if (uncompress(const_cast<uint8*>(dest.contents()), &realSize, const_cast<uint8*>(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK) + if (uncompress(const_cast<uint8*>(dest.contents()), &realSize, const_cast<uint8*>(recvData.contents() + recvData.rpos()), recvData.size() - recvData.rpos()) != Z_OK) { - recv_data.rfinish(); // unnneded warning spam in this case + recvData.rfinish(); // unnneded warning spam in this case sLog->outError(LOG_FILTER_NETWORKIO, "UAD: Failed to decompress account data"); return; } - recv_data.rfinish(); // uncompress read (recv_data.size() - recv_data.rpos()) + recvData.rfinish(); // uncompress read (recvData.size() - recvData.rpos()) std::string adata; dest >> adata; @@ -994,12 +993,12 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) SendPacket(&data); } -void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) +void WorldSession::HandleRequestAccountData(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); uint32 type; - recv_data >> type; + recvData >> type; sLog->outDebug(LOG_FILTER_NETWORKIO, "RAD: type %u", type); @@ -1032,12 +1031,19 @@ void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) SendPacket(&data); } -void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_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) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SET_ACTION_BUTTON"); uint8 button; uint32 packetData; - recv_data >> button >> packetData; + recvData >> button >> packetData; uint32 action = ACTION_BUTTON_ACTION(packetData); uint8 type = ACTION_BUTTON_TYPE(packetData); @@ -1073,29 +1079,49 @@ void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) } } -void WorldSession::HandleCompleteCinematic(WorldPacket & /*recv_data*/) +void WorldSession::HandleCompleteCinematic(WorldPacket& /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_COMPLETE_CINEMATIC"); } -void WorldSession::HandleNextCinematicCamera(WorldPacket & /*recv_data*/) +void WorldSession::HandleNextCinematicCamera(WorldPacket & /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_NEXT_CINEMATIC_CAMERA"); } -void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) +void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recvData) { - /* WorldSession::Update(getMSTime());*/ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_MOVE_TIME_SKIPPED"); - uint64 guid; - recv_data.readPackGUID(guid); - recv_data.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; - recv_data >> guid; - recv_data >> time_skipped; + recvData >> guid; + recvData >> time_skipped; sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_MOVE_TIME_SKIPPED"); /// TODO @@ -1106,84 +1132,84 @@ void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) */ } -void WorldSession::HandleFeatherFallAck(WorldPacket &recv_data) +void WorldSession::HandleFeatherFallAck(WorldPacket &recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); // no used - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam } -void WorldSession::HandleMoveUnRootAck(WorldPacket& recv_data) +void WorldSession::HandleMoveUnRootAck(WorldPacket& recvData) { // no used - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam /* uint64 guid; - recv_data >> guid; + recvData >> guid; // now can skip not our packet if (_player->GetGUID() != guid) { - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam return; } sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_FORCE_MOVE_UNROOT_ACK"); - recv_data.read_skip<uint32>(); // unk + recvData.read_skip<uint32>(); // unk MovementInfo movementInfo; movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); - recv_data.read_skip<float>(); // unk2 + ReadMovementInfo(recvData, &movementInfo); + recvData.read_skip<float>(); // unk2 */ } -void WorldSession::HandleMoveRootAck(WorldPacket& recv_data) +void WorldSession::HandleMoveRootAck(WorldPacket& recvData) { // no used - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam /* uint64 guid; - recv_data >> guid; + recvData >> guid; // now can skip not our packet if (_player->GetGUID() != guid) { - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam return; } sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_FORCE_MOVE_ROOT_ACK"); - recv_data.read_skip<uint32>(); // unk + recvData.read_skip<uint32>(); // unk MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); + ReadMovementInfo(recvData, &movementInfo); */ } -void WorldSession::HandleSetActionBarToggles(WorldPacket& recv_data) +void WorldSession::HandleSetActionBarToggles(WorldPacket& recvPacket) { - uint8 ActionBar; + uint8 actionBar; - recv_data >> ActionBar; + recvPacket >> actionBar; if (!GetPlayer()) // ignore until not logged (check needed because STATUS_AUTHED) { - if (ActionBar != 0) - sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetActionBarToggles in not logged state with value: %u, ignored", uint32(ActionBar)); + if (actionBar != 0) + sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetActionBarToggles in not logged state with value: %u, ignored", uint32(actionBar)); return; } - GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, 2, ActionBar); + GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, 2, actionBar); } -void WorldSession::HandlePlayedTime(WorldPacket& recv_data) +void WorldSession::HandlePlayedTime(WorldPacket& recvData) { uint8 unk1; - recv_data >> unk1; // 0 or 1 expected + recvData >> unk1; // 0 or 1 expected WorldPacket data(SMSG_PLAYED_TIME, 4 + 4 + 1); data << uint32(_player->GetTotalPlayedTime()); @@ -1192,10 +1218,10 @@ void WorldSession::HandlePlayedTime(WorldPacket& recv_data) SendPacket(&data); } -void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) +void WorldSession::HandleInspectOpcode(WorldPacket& recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_INSPECT"); @@ -1208,15 +1234,12 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) 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); - } else { data << uint32(0); // unspentTalentPoints @@ -1225,13 +1248,20 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) } player->BuildEnchantmentsInfoData(&data); + if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId())) + { + data << uint64(guild->GetGUID()); + data << uint32(guild->GetLevel()); + data << uint64(0/*guild->GetXP()*/); + data << uint32(0/*guild->GetMembersCount()*/); // number of members + } SendPacket(&data); } -void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) +void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; Player* player = ObjectAccessor::FindPlayer(guid); @@ -1241,17 +1271,15 @@ void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) return; } - WorldPacket data(MSG_INSPECT_HONOR_STATS, 8+1+4*4); - data << uint64(player->GetGUID()); - data << uint8(player->GetHonorPoints()); + WorldPacket data(SMSG_INSPECT_HONOR_STATS, 4+1+4+8); data << uint32(player->GetUInt32Value(PLAYER_FIELD_KILLS)); - data << uint32(player->GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); - data << uint32(player->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); + data << uint8(0); // rank data << uint32(player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS)); + data << uint64(player->GetGUID()); SendPacket(&data); } -void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) +void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recvData) { uint32 time; uint32 mapid; @@ -1260,12 +1288,12 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) float PositionZ; float Orientation; - recv_data >> time; // time in m.sec. - recv_data >> mapid; - recv_data >> PositionX; - recv_data >> PositionY; - recv_data >> PositionZ; - recv_data >> Orientation; // o (3.141593 = 180 degrees) + recvData >> time; // time in m.sec. + recvData >> mapid; + recvData >> PositionX; + recvData >> PositionY; + recvData >> PositionZ; + recvData >> Orientation; // o (3.141593 = 180 degrees) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_WORLD_TELEPORT"); @@ -1283,11 +1311,11 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); } -void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) +void WorldSession::HandleWhoisOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_WHOIS"); std::string charname; - recv_data >> charname; + recvData >> charname; if (!AccountMgr::IsAdminAccount(GetSecurity())) { @@ -1343,7 +1371,7 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) sLog->outDebug(LOG_FILTER_NETWORKIO, "Received whois command from player %s for character %s", GetPlayer()->GetName(), charname.c_str()); } -void WorldSession::HandleComplainOpcode(WorldPacket & recv_data) +void WorldSession::HandleComplainOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_COMPLAIN"); @@ -1354,21 +1382,21 @@ void WorldSession::HandleComplainOpcode(WorldPacket & recv_data) uint32 unk3 = 0; uint32 unk4 = 0; std::string description = ""; - recv_data >> spam_type; // unk 0x01 const, may be spam type (mail/chat) - recv_data >> spammer_guid; // player guid + recvData >> spam_type; // unk 0x01 const, may be spam type (mail/chat) + recvData >> spammer_guid; // player guid switch (spam_type) { case 0: - recv_data >> unk1; // const 0 - recv_data >> unk2; // probably mail id - recv_data >> unk3; // const 0 + recvData >> unk1; // const 0 + recvData >> unk2; // probably mail id + recvData >> unk3; // const 0 break; case 1: - recv_data >> unk1; // probably language - recv_data >> unk2; // message type? - recv_data >> unk3; // probably channel id - recv_data >> unk4; // unk random value - recv_data >> description; // spam description string (messagetype, channel name, player name, message) + recvData >> unk1; // probably language + recvData >> unk2; // message type? + recvData >> unk3; // probably channel id + recvData >> unk4; // unk random value + recvData >> description; // spam description string (messagetype, channel name, player name, message) break; } @@ -1376,20 +1404,21 @@ void WorldSession::HandleComplainOpcode(WorldPacket & recv_data) // 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); sLog->outDebug(LOG_FILTER_NETWORKIO, "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()); } -void WorldSession::HandleRealmSplitOpcode(WorldPacket & recv_data) +void WorldSession::HandleRealmSplitOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_REALM_SPLIT"); uint32 unk; std::string split_date = "01/01/01"; - recv_data >> unk; + recvData >> unk; WorldPacket data(SMSG_REALM_SPLIT, 4+4+split_date.size()+1); data << unk; @@ -1403,12 +1432,12 @@ void WorldSession::HandleRealmSplitOpcode(WorldPacket & recv_data) //sLog->outDebug("response sent %u", unk); } -void WorldSession::HandleFarSightOpcode(WorldPacket & recv_data) +void WorldSession::HandleFarSightOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_FAR_SIGHT"); uint8 apply; - recv_data >> apply; + recvData >> apply; switch (apply) { @@ -1431,12 +1460,12 @@ void WorldSession::HandleFarSightOpcode(WorldPacket & recv_data) GetPlayer()->UpdateVisibilityForPlayer(); } -void WorldSession::HandleSetTitleOpcode(WorldPacket & recv_data) +void WorldSession::HandleSetTitleOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SET_TITLE"); int32 title; - recv_data >> title; + recvData >> title; // -1 at none if (title > 0 && title < MAX_TITLE_INDEX) @@ -1450,12 +1479,12 @@ void WorldSession::HandleSetTitleOpcode(WorldPacket & recv_data) GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title); } -void WorldSession::HandleTimeSyncResp(WorldPacket & recv_data) +void WorldSession::HandleTimeSyncResp(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_TIME_SYNC_RESP"); uint32 counter, clientTicks; - recv_data >> counter >> clientTicks; + recvData >> clientTicks >> counter; if (counter != _player->m_timeSyncCounter - 1) sLog->outDebug(LOG_FILTER_NETWORKIO, "Wrong time sync counter from player %s (cheater?)", _player->GetName()); @@ -1470,7 +1499,7 @@ void WorldSession::HandleTimeSyncResp(WorldPacket & recv_data) _player->m_timeSyncClient = clientTicks; } -void WorldSession::HandleResetInstancesOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleResetInstancesOpcode(WorldPacket& /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_RESET_INSTANCES"); @@ -1483,12 +1512,12 @@ void WorldSession::HandleResetInstancesOpcode(WorldPacket & /*recv_data*/) _player->ResetInstances(INSTANCE_RESET_ALL, false); } -void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket & recv_data) +void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_SET_DUNGEON_DIFFICULTY"); uint32 mode; - recv_data >> mode; + recvData >> mode; if (mode >= MAX_DUNGEON_DIFFICULTY) { @@ -1540,12 +1569,12 @@ void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket & recv_data) +void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_SET_RAID_DIFFICULTY"); uint32 mode; - recv_data >> mode; + recvData >> mode; if (mode >= MAX_RAID_DIFFICULTY) { @@ -1597,7 +1626,7 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleCancelMountAuraOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleCancelMountAuraOpcode(WorldPacket & /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CANCEL_MOUNT_AURA"); @@ -1618,54 +1647,63 @@ void WorldSession::HandleCancelMountAuraOpcode(WorldPacket & /*recv_data*/) _player->RemoveAurasByType(SPELL_AURA_MOUNTED); } -void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket & recv_data) +void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket & recvData) { // fly mode on/off sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK"); uint64 guid; // guid - unused - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); - recv_data.read_skip<uint32>(); // unk + recvData.read_skip<uint32>(); // unk MovementInfo movementInfo; movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); + ReadMovementInfo(recvData, &movementInfo); - recv_data.read_skip<float>(); // unk2 + recvData.read_skip<float>(); // unk2 _player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags(); } -void WorldSession::HandleRequestPetInfoOpcode(WorldPacket & /*recv_data */) +void WorldSession::HandleRequestPetInfoOpcode(WorldPacket& /*recvData */) { /* sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_REQUEST_PET_INFO"); - recv_data.hexlike(); + recvData.hexlike(); */ } -void WorldSession::HandleSetTaxiBenchmarkOpcode(WorldPacket & recv_data) +void WorldSession::HandleSetTaxiBenchmarkOpcode(WorldPacket& recvData) { uint8 mode; - recv_data >> mode; + recvData >> mode; sLog->outDebug(LOG_FILTER_NETWORKIO, "Client used \"/timetest %d\" command", mode); } -void WorldSession::HandleQueryInspectAchievements(WorldPacket & recv_data) +void WorldSession::HandleQueryInspectAchievements(WorldPacket& recvData) { uint64 guid; - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); Player* player = ObjectAccessor::FindPlayer(guid); if (!player) return; - player->GetAchievementMgr().SendRespondInspectAchievements(_player); + player->GetAchievementMgr().SendAchievementInfo(_player); } -void WorldSession::HandleWorldStateUITimerUpdate(WorldPacket& /*recv_data*/) +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 sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_WORLD_STATE_UI_TIMER_UPDATE"); @@ -1675,7 +1713,7 @@ void WorldSession::HandleWorldStateUITimerUpdate(WorldPacket& /*recv_data*/) SendPacket(&data); } -void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recv_data*/) +void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recvData*/) { // empty opcode sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_READY_FOR_ACCOUNT_DATA_TIMES"); @@ -1689,6 +1727,7 @@ void WorldSession::SendSetPhaseShift(uint32 PhaseShift) data << uint32(PhaseShift); SendPacket(&data); } + // Battlefield and Battleground void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPacket & recv_data) { @@ -1736,7 +1775,7 @@ void WorldSession::HandleAreaSpiritHealerQueueOpcode(WorldPacket & recv_data) bf->AddPlayerToResurrectQueue(guid, _player->GetGUID()); } -void WorldSession::HandleHearthAndResurrect(WorldPacket& /*recv_data*/) +void WorldSession::HandleHearthAndResurrect(WorldPacket& /*recvData*/) { if (_player->isInFlight()) return; @@ -1775,6 +1814,57 @@ void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket) _player->SetPendingBind(0, 0); } +void WorldSession::HandleRequestHotfix(WorldPacket& recvPacket) +{ + uint32 type, count; + recvPacket >> type; + + 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]); + + switch (type) + { + case DB2_REPLY_ITEM: + SendItemDb2Reply(entry); + break; + case DB2_REPLY_SPARSE: + SendItemSparseDb2Reply(entry); + break; + default: + sLog->outError(LOG_FILTER_NETWORKIO, "CMSG_REQUEST_HOTFIX: Received unknown hotfix type: %u", type); + recvPacket.rfinish(); + break; + } + } + + delete[] guids; +} + void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_UPDATE_MISSILE_TRAJECTORY"); @@ -1814,7 +1904,39 @@ 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); + sLog->outError(LOG_FILTER_NETWORKIO, "Object update failed for object "UI64FMTD" (%s) for player %s (%u)", uint64(guid), obj ? obj->GetName() : "object-not-found", GetPlayerName().c_str(), GetGuidLow()); + } diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 27b1f2eca3f..0cc9263bfbd 100755..100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -30,8 +30,9 @@ #include "WaypointMovementGenerator.h" #include "InstanceSaveMgr.h" #include "ObjectMgr.h" +#include "MovementStructures.h" -void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket& /*recvPacket*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: got MSG_MOVE_WORLDPORT_ACK."); HandleMoveWorldportAckOpcode(); @@ -187,16 +188,33 @@ void WorldSession::HandleMoveWorldportAckOpcode() GetPlayer()->ProcessDelayedOperations(); } -void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data) +void WorldSession::HandleMoveTeleportAck(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_MOVE_TELEPORT_ACK"); - uint64 guid; - - recv_data.readPackGUID(guid); + ObjectGuid guid; uint32 flags, time; - recv_data >> flags >> time; - sLog->outDebug(LOG_FILTER_NETWORKIO, "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]); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "Guid " UI64FMTD, uint64(guid)); sLog->outDebug(LOG_FILTER_NETWORKIO, "Flags %u, time %u", flags, time/IN_MILLISECONDS); Player* plMover = _player->m_mover->ToPlayer(); @@ -238,9 +256,9 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data) 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; @@ -251,46 +269,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 + ReadMovementInfo(recvPacket, &movementInfo); // prevent tampered movement data - if (guid != mover->GetGUID()) + if (movementInfo.guid != mover->GetGUID()) + { + sLog->outError(LOG_FILTER_NETWORKIO, "HandleMovementOpcodes: guid error"); return; - + } if (!movementInfo.pos.IsPositionValid()) { - recvData.rfinish(); // prevent warnings spam + sLog->outError(LOG_FILTER_NETWORKIO, "HandleMovementOpcodes: Invalid Position"); return; } /* handle special cases */ - if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) + if (movementInfo.t_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.t_pos.GetPositionX() > 50 || movementInfo.t_pos.GetPositionY() > 50 || movementInfo.t_pos.GetPositionZ() > 50) { - recvData.rfinish(); // prevent warnings spam + recvPacket.rfinish(); // prevent warnings spam return; } if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.t_pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.t_pos.GetPositionY(), movementInfo.pos.GetPositionZ() + movementInfo.t_pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.t_pos.GetOrientation())) { - recvData.rfinish(); // prevent warnings spam + recvPacket.rfinish(); // prevent warnings spam return; } @@ -339,7 +352,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recvData) { GameObject* go = mover->GetMap()->GetGameObject(movementInfo.t_guid); if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) - movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; + movementInfo.t_guid = 0; } } else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave @@ -364,10 +377,10 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recvData) /*----------------------*/ /* process position-change */ - WorldPacket data(opcode, recvData.size()); + WorldPacket data(SMSG_PLAYER_MOVE, recvPacket.size()); movementInfo.time = getMSTime(); movementInfo.guid = mover->GetGUID(); - WriteMovementInfo(&data, &movementInfo); + WriteMovementInfo(data, &movementInfo); mover->SendMessageToSet(&data, _player); mover->m_movementInfo = movementInfo; @@ -406,34 +419,33 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recvData) } } -void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) +void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData) { - uint32 opcode = recv_data.GetOpcode(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); + uint32 opcode = recvData.GetOpcode(); /* extract packet */ uint64 guid; uint32 unk1; float newspeed; - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); // now can skip not our packet if (_player->GetGUID() != guid) { - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam return; } // continue parse packet - recv_data >> unk1; // counter or moveEvent + recvData >> unk1; // counter or moveEvent MovementInfo movementInfo; movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); + ReadMovementInfo(recvData, &movementInfo); - recv_data >> newspeed; + recvData >> newspeed; /*----------------*/ // client ACK send one packet for mounted/run case and need skip all except last from its @@ -445,15 +457,15 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) 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; force_move_type = MOVE_WALK; break; + //case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break; + //case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break; + //case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break; + //case CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break; + //case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break; + //case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break; + //case CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break; + //case CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break; default: sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode); return; @@ -485,36 +497,53 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) } } -void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data) +void WorldSession::HandleSetActiveMoverOpcode(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_SET_ACTIVE_MOVER"); - uint64 guid; - recv_data >> 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) - sLog->outError(LOG_FILTER_NETWORKIO, "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " (%s - Entry: %u) and should be " UI64FMTD, guid, GetLogNameForGuid(guid), GUID_ENPART(guid), _player->m_mover->GetGUID()); + sLog->outError(LOG_FILTER_NETWORKIO, "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()); } } -void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data) +void WorldSession::HandleMoveNotActiveMover(WorldPacket &recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER"); uint64 old_mover_guid; - recv_data.readPackGUID(old_mover_guid); + recvData.readPackGUID(old_mover_guid); MovementInfo mi; - ReadMovementInfo(recv_data, &mi); + ReadMovementInfo(recvData, &mi); mi.guid = old_mover_guid; _player->m_movementInfo = mi; } -void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recv_data*/) +void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvData*/) { WorldPacket data(SMSG_MOUNTSPECIAL_ANIM, 8); data << uint64(GetPlayer()->GetGUID()); @@ -522,24 +551,24 @@ void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recv_data*/) GetPlayer()->SendMessageToSet(&data, false); } -void WorldSession::HandleMoveKnockBackAck(WorldPacket & recv_data) +void WorldSession::HandleMoveKnockBackAck(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_MOVE_KNOCK_BACK_ACK"); uint64 guid; - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); if (_player->m_mover->GetGUID() != guid) return; - recv_data.read_skip<uint32>(); // unk + recvData.read_skip<uint32>(); // unk MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); + ReadMovementInfo(recvData, &movementInfo); _player->m_movementInfo = movementInfo; - WorldPacket data(MSG_MOVE_KNOCK_BACK, 66); + WorldPacket data(SMSG_MOVE_UPDATE_KNOCK_BACK, 66); data.appendPackGUID(guid); _player->BuildMovementPacket(&data); @@ -552,45 +581,518 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket & recv_data) _player->SendMessageToSet(&data, false); } -void WorldSession::HandleMoveHoverAck(WorldPacket& recv_data) +void WorldSession::HandleMoveHoverAck(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_MOVE_HOVER_ACK"); uint64 guid; // guid - unused - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); - recv_data.read_skip<uint32>(); // unk + recvData.read_skip<uint32>(); // unk MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); + ReadMovementInfo(recvData, &movementInfo); - recv_data.read_skip<uint32>(); // unk2 + recvData.read_skip<uint32>(); // unk2 } -void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recv_data) +void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_MOVE_WATER_WALK_ACK"); uint64 guid; // guid - unused - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); - recv_data.read_skip<uint32>(); // unk + recvData.read_skip<uint32>(); // unk MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); + ReadMovementInfo(recvData, &movementInfo); - recv_data.read_skip<uint32>(); // unk2 + recvData.read_skip<uint32>(); // unk2 } -void WorldSession::HandleSummonResponseOpcode(WorldPacket& recv_data) +void WorldSession::HandleSummonResponseOpcode(WorldPacket& recvData) { if (!_player->isAlive() || _player->isInCombat()) return; - uint64 summoner_guid; + uint64 summonerGuid; bool agree; - recv_data >> summoner_guid; - recv_data >> agree; + recvData >> summonerGuid; + recvData >> agree; _player->SummonIfPossible(agree); } + +void WorldSession::ReadMovementInfo(WorldPacket& data, MovementInfo* mi) +{ + 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; + bool hasSpline = false; + + MovementStatusElements* sequence = GetMovementStatusElementsSequence(data.GetOpcode()); + if (sequence == NULL) + { + sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::ReadMovementInfo: No movement sequence found for opcode 0x%04X", uint32(data.GetOpcode())); + return; + } + + ObjectGuid guid; + ObjectGuid tguid; + + for (uint32 i = 0; i < MSE_COUNT; ++i) + { + MovementStatusElements element = sequence[i]; + if (element == MSEEnd) + break; + + if (element >= MSEHasGuidByte0 && element <= MSEHasGuidByte7) + { + guid[element - MSEHasGuidByte0] = data.ReadBit(); + continue; + } + + if (element >= MSEHasTransportGuidByte0 && + element <= MSEHasTransportGuidByte7) + { + if (hasTransportData) + tguid[element - MSEHasTransportGuidByte0] = data.ReadBit(); + continue; + } + + if (element >= MSEGuidByte0 && element <= MSEGuidByte7) + { + data.ReadByteSeq(guid[element - MSEGuidByte0]); + continue; + } + + if (element >= MSETransportGuidByte0 && + element <= MSETransportGuidByte7) + { + if (hasTransportData) + data.ReadByteSeq(tguid[element - MSETransportGuidByte0]); + continue; + } + + switch (element) + { + 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: + hasSpline = 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->t_pos.m_positionX; + break; + case MSETransportPositionY: + if (hasTransportData) + data >> mi->t_pos.m_positionY; + break; + case MSETransportPositionZ: + if (hasTransportData) + data >> mi->t_pos.m_positionZ; + break; + case MSETransportOrientation: + if (hasTransportData) + mi->pos.SetOrientation(data.read<float>()); + break; + case MSETransportSeat: + if (hasTransportData) + data >> mi->t_seat; + break; + case MSETransportTime: + if (hasTransportData) + data >> mi->t_time; + break; + case MSETransportTime2: + if (hasTransportData && hasTransportTime2) + data >> mi->t_time2; + break; + case MSETransportTime3: + if (hasTransportData && hasTransportTime3) + data >> mi->t_time3; + break; + case MSEPitch: + if (hasPitch) + data >> mi->pitch; + break; + case MSEFallTime: + if (hasFallData) + data >> mi->fallTime; + break; + case MSEFallVerticalSpeed: + if (hasFallData) + data >> mi->j_zspeed; + break; + case MSEFallCosAngle: + if (hasFallData && hasFallDirection) + data >> mi->j_cosAngle; + break; + case MSEFallSinAngle: + if (hasFallData && hasFallDirection) + data >> mi->j_sinAngle; + break; + case MSEFallHorizontalSpeed: + if (hasFallData && hasFallDirection) + data >> mi->j_xyspeed; + break; + case MSESplineElevation: + if (hasSplineElevation) + data >> mi->splineElevation; + break; + case MSEZeroBit: + case MSEOneBit: + data.ReadBit(); + break; + default: + ASSERT(false && "Incorrect sequence element detected at ReadMovementInfo"); + break; + } + } + + mi->guid = guid; + mi->t_guid = tguid; + + if (hasTransportData && mi->pos.m_positionX != mi->t_pos.m_positionX) + if (GetPlayer()->GetTransport()) + GetPlayer()->GetTransport()->UpdatePosition(mi); + + //! 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) \ + { \ + sLog->outDebug(LOG_FILTER_UNITS, "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); + + #undef REMOVE_VIOLATING_FLAGS +} + +void WorldSession::WriteMovementInfo(WorldPacket &data, MovementInfo* mi) +{ + bool hasMovementFlags = mi->GetMovementFlags() != 0; + bool hasMovementFlags2 = mi->GetExtraMovementFlags() != 0; + bool hasTimestamp = mi->time != 0; + bool hasOrientation = !G3D::fuzzyEq(mi->pos.GetOrientation(), 0.0f); + bool hasTransportData = mi->t_guid != 0; + bool hasTransportTime2 = mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT); + bool hasTransportTime3 = false; + bool hasPitch = mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || mi->HasExtraMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING); + bool hasFallData = mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_TURNING); + bool hasFallDirection = mi->HasMovementFlag(MOVEMENTFLAG_FALLING); + bool hasSplineElevation = mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION); + bool hasSpline = false; + + MovementStatusElements* sequence = GetMovementStatusElementsSequence(data.GetOpcode()); + if (!sequence) + { + sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::WriteMovementInfo: No movement sequence found for opcode 0x%04X", uint32(data.GetOpcode())); + return; + } + + ObjectGuid guid = mi->guid; + ObjectGuid tguid = mi->t_guid; + + for(uint32 i = 0; i < MSE_COUNT; ++i) + { + MovementStatusElements element = sequence[i]; + if (element == MSEEnd) + break; + + if (element >= MSEHasGuidByte0 && element <= MSEHasGuidByte7) + { + data.WriteBit(guid[element - MSEHasGuidByte0]); + continue; + } + + if (element >= MSEHasTransportGuidByte0 && + element <= MSEHasTransportGuidByte7) + { + if (hasTransportData) + data.WriteBit(tguid[element - MSEHasTransportGuidByte0]); + continue; + } + + if (element >= MSEGuidByte0 && element <= MSEGuidByte7) + { + data.WriteByteSeq(guid[element - MSEGuidByte0]); + continue; + } + + if (element >= MSETransportGuidByte0 && + element <= MSETransportGuidByte7) + { + if (hasTransportData) + data.WriteByteSeq(tguid[element - MSETransportGuidByte0]); + continue; + } + + switch (element) + { + 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(mi->flags, 30); + break; + case MSEMovementFlags2: + if (hasMovementFlags2) + data.WriteBits(mi->flags2, 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) + data << mi->pos.GetOrientation(); + break; + case MSETransportPositionX: + if (hasTransportData) + data << mi->t_pos.m_positionX; + break; + case MSETransportPositionY: + if (hasTransportData) + data << mi->t_pos.m_positionY; + break; + case MSETransportPositionZ: + if (hasTransportData) + data << mi->t_pos.m_positionZ; + break; + case MSETransportOrientation: + if (hasTransportData) + data << mi->t_pos.GetOrientation(); + break; + case MSETransportSeat: + if (hasTransportData) + data << mi->t_seat; + break; + case MSETransportTime: + if (hasTransportData) + data << mi->t_time; + break; + case MSETransportTime2: + if (hasTransportData && hasTransportTime2) + data << mi->t_time2; + break; + case MSETransportTime3: + if (hasTransportData && hasTransportTime3) + data << mi->t_time3; + break; + case MSEPitch: + if (hasPitch) + data << mi->pitch; + break; + case MSEFallTime: + if (hasFallData) + data << mi->fallTime; + break; + case MSEFallVerticalSpeed: + if (hasFallData) + data << mi->j_zspeed; + break; + case MSEFallCosAngle: + if (hasFallData && hasFallDirection) + data << mi->j_cosAngle; + break; + case MSEFallSinAngle: + if (hasFallData && hasFallDirection) + data << mi->j_sinAngle; + break; + case MSEFallHorizontalSpeed: + if (hasFallData && hasFallDirection) + data << mi->j_xyspeed; + break; + case MSESplineElevation: + if (hasSplineElevation) + data << mi->splineElevation; + break; + case MSEZeroBit: + data.WriteBit(0); + break; + case MSEOneBit: + data.WriteBit(1); + break; + default: + ASSERT(false && "Incorrect sequence element detected at ReadMovementInfo"); + break; + } + } +} diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index f0c3093aa25..32636d51f49 100755 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -47,10 +47,10 @@ enum StableResultCode STABLE_ERR_EXOTIC = 0x0C, // "you are unable to control exotic creatures" }; -void WorldSession::HandleTabardVendorActivateOpcode(WorldPacket & recv_data) +void WorldSession::HandleTabardVendorActivateOpcode(WorldPacket & recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TABARDDESIGNER); if (!unit) @@ -73,13 +73,13 @@ void WorldSession::SendTabardVendorActivate(uint64 guid) SendPacket(&data); } -void WorldSession::HandleBankerActivateOpcode(WorldPacket & recv_data) +void WorldSession::HandleBankerActivateOpcode(WorldPacket& recvData) { uint64 guid; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BANKER_ACTIVATE"); - recv_data >> guid; + recvData >> guid; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER); if (!unit) @@ -102,11 +102,11 @@ void WorldSession::SendShowBank(uint64 guid) SendPacket(&data); } -void WorldSession::HandleTrainerListOpcode(WorldPacket & recv_data) +void WorldSession::HandleTrainerListOpcode(WorldPacket & recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; SendTrainerList(guid); } @@ -154,6 +154,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()); @@ -191,9 +192,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); @@ -208,7 +206,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) @@ -216,15 +214,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; } @@ -234,12 +236,13 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle) SendPacket(&data); } -void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket & recv_data) +void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket & recvData) { uint64 guid; uint32 spellId = 0; + int32 unkInt; - recv_data >> guid >> spellId; + recvData >> guid >> unkInt >> spellId; sLog->outDebug(LOG_FILTER_NETWORKIO, "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); @@ -274,10 +277,10 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket & recv_data) uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit))); // check money requirement - if (!_player->HasEnoughMoney(nSpellCost)) + if (!_player->HasEnoughMoney(uint64(nSpellCost))) return; - _player->ModifyMoney(-int32(nSpellCost)); + _player->ModifyMoney(-int64(nSpellCost)); unit->SendPlaySpellVisual(179); // 53 SpellCastDirected unit->SendPlaySpellImpact(_player->GetGUID(), 362); // 113 EmoteSalute @@ -291,15 +294,16 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket & recv_data) WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12); data << uint64(guid); data << uint32(spellId); // should be same as in packet from client + data << uint32(0); // "Trainer service", 1 = "Not enough money for trainer service <TS>". 0 = "Trainer service <TS> unavailable" SendPacket(&data); } -void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data) +void WorldSession::HandleGossipHelloOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GOSSIP_HELLO"); uint64 guid; - recv_data >> guid; + recvData >> guid; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!unit) @@ -318,9 +322,7 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data) // 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()) @@ -343,7 +345,7 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data) unit->AI()->sGossipHello(_player); } -/*void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) +/*void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_GOSSIP_SELECT_OPTION"); @@ -352,12 +354,12 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data) uint64 guid; std::string code = ""; - recv_data >> guid >> unk >> option; + recvData >> guid >> unk >> option; if (_player->PlayerTalkClass->GossipOptionCoded(option)) { sLog->outDebug(LOG_FILTER_PACKETIO, "reading string"); - recv_data >> code; + recvData >> code; sLog->outDebug(LOG_FILTER_PACKETIO, "string read: %s", code.c_str()); } @@ -384,13 +386,13 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data) } }*/ -void WorldSession::HandleSpiritHealerActivateOpcode(WorldPacket & recv_data) +void WorldSession::HandleSpiritHealerActivateOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SPIRIT_HEALER_ACTIVATE"); uint64 guid; - recv_data >> guid; + recvData >> guid; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_SPIRITHEALER); if (!unit) @@ -439,10 +441,10 @@ void WorldSession::SendSpiritResurrect() _player->UpdateObjectVisibility(); } -void WorldSession::HandleBinderActivateOpcode(WorldPacket & recv_data) +void WorldSession::HandleBinderActivateOpcode(WorldPacket& recvData) { uint64 npcGUID; - recv_data >> npcGUID; + recvData >> npcGUID; if (!GetPlayer()->IsInWorld() || !GetPlayer()->isAlive()) return; @@ -491,17 +493,18 @@ void WorldSession::SendBindPoint(Creature* npc) WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, (8+4)); data << uint64(npc->GetGUID()); data << uint32(bindspell); + data << uint32(0); // "Trainer service", 1 = "Not enough money for trainer service <TS>". 0 = "Trainer service <TS> unavailable" SendPacket(&data); _player->PlayerTalkClass->SendCloseGossip(); } -void WorldSession::HandleListStabledPetsOpcode(WorldPacket & recv_data) +void WorldSession::HandleListStabledPetsOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv MSG_LIST_STABLED_PETS"); uint64 npcGUID; - recv_data >> npcGUID; + recvData >> npcGUID; if (!CheckStableMaster(npcGUID)) return; @@ -552,6 +555,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(0); // 4.x unknown, some kind of order? data << uint32(pet->GetCharmInfo()->GetPetNumber()); data << uint32(pet->GetEntry()); data << uint32(pet->getLevel()); @@ -589,12 +593,12 @@ void WorldSession::SendStableResult(uint8 res) SendPacket(&data); } -void WorldSession::HandleStablePet(WorldPacket & recv_data) +void WorldSession::HandleStablePet(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_STABLE_PET"); uint64 npcGUID; - recv_data >> npcGUID; + recvData >> npcGUID; if (!GetPlayer()->isAlive()) { @@ -664,13 +668,13 @@ void WorldSession::HandleStablePetCallback(PreparedQueryResult result) SendStableResult(STABLE_ERR_STABLE); } -void WorldSession::HandleUnstablePet(WorldPacket & recv_data) +void WorldSession::HandleUnstablePet(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_UNSTABLE_PET."); uint64 npcGUID; uint32 petnumber; - recv_data >> npcGUID >> petnumber; + recvData >> npcGUID >> petnumber; if (!CheckStableMaster(npcGUID)) { @@ -745,12 +749,12 @@ void WorldSession::HandleUnstablePetCallback(PreparedQueryResult result, uint32 SendStableResult(STABLE_SUCCESS_UNSTABLE); } -void WorldSession::HandleBuyStableSlot(WorldPacket & recv_data) +void WorldSession::HandleBuyStableSlot(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_BUY_STABLE_SLOT."); uint64 npcGUID; - recv_data >> npcGUID; + recvData >> npcGUID; if (!CheckStableMaster(npcGUID)) { @@ -764,7 +768,7 @@ void WorldSession::HandleBuyStableSlot(WorldPacket & recv_data) 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; @@ -772,24 +776,24 @@ void WorldSession::HandleBuyStableSlot(WorldPacket & recv_data) SendStableResult(STABLE_SUCCESS_BUY_SLOT); } else - SendStableResult(STABLE_ERR_MONEY); + SendStableResult(STABLE_ERR_MONEY);*/ } else SendStableResult(STABLE_ERR_STABLE); } -void WorldSession::HandleStableRevivePet(WorldPacket &/* recv_data */) +void WorldSession::HandleStableRevivePet(WorldPacket &/* recvData */) { sLog->outDebug(LOG_FILTER_NETWORKIO, "HandleStableRevivePet: Not implemented"); } -void WorldSession::HandleStableSwapPet(WorldPacket & recv_data) +void WorldSession::HandleStableSwapPet(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_STABLE_SWAP_PET."); uint64 npcGUID; uint32 petId; - recv_data >> npcGUID >> petId; + recvData >> npcGUID >> petId; if (!CheckStableMaster(npcGUID)) { @@ -875,14 +879,14 @@ void WorldSession::HandleStableSwapPetCallback(PreparedQueryResult result, uint3 SendStableResult(STABLE_SUCCESS_UNSTABLE); } -void WorldSession::HandleRepairItemOpcode(WorldPacket & recv_data) +void WorldSession::HandleRepairItemOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_REPAIR_ITEM"); uint64 npcGUID, itemGUID; uint8 guildBank; // new in 2.3.2, bool that means from guild bank money - recv_data >> npcGUID >> itemGUID >> guildBank; + recvData >> npcGUID >> itemGUID >> guildBank; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_REPAIR); if (!unit) diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 3501b3bc068..c0345e17fcd 100755..100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -32,10 +32,10 @@ #include "Group.h" #include "SpellInfo.h" -void WorldSession::HandleDismissCritter(WorldPacket &recv_data) +void WorldSession::HandleDismissCritter(WorldPacket &recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_DISMISS_CRITTER for GUID " UI64FMTD, guid); @@ -55,14 +55,19 @@ void WorldSession::HandleDismissCritter(WorldPacket &recv_data) } } -void WorldSession::HandlePetAction(WorldPacket & recv_data) +void WorldSession::HandlePetAction(WorldPacket & recvData) { uint64 guid1; uint32 data; uint64 guid2; - recv_data >> guid1; //pet guid - recv_data >> data; - recv_data >> guid2; //tag guid + 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 @@ -110,10 +115,10 @@ void WorldSession::HandlePetAction(WorldPacket & recv_data) } } -void WorldSession::HandlePetStopAttack(WorldPacket &recv_data) +void WorldSession::HandlePetStopAttack(WorldPacket &recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PET_STOP_ATTACK for GUID " UI64FMTD "", guid); @@ -401,15 +406,15 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid } } -void WorldSession::HandlePetNameQuery(WorldPacket & recv_data) +void WorldSession::HandlePetNameQuery(WorldPacket & recvData) { sLog->outInfo(LOG_FILTER_NETWORKIO, "HandlePetNameQuery. CMSG_PET_NAME_QUERY"); uint32 petnumber; uint64 petguid; - recv_data >> petnumber; - recv_data >> petguid; + recvData >> petnumber; + recvData >> petguid; SendPetNameQuery(petguid, petnumber); } @@ -470,14 +475,14 @@ bool WorldSession::CheckStableMaster(uint64 guid) return true; } -void WorldSession::HandlePetSetAction(WorldPacket & recv_data) +void WorldSession::HandlePetSetAction(WorldPacket & recvData) { sLog->outInfo(LOG_FILTER_NETWORKIO, "HandlePetSetAction. CMSG_PET_SET_ACTION"); uint64 petguid; uint8 count; - recv_data >> petguid; + recvData >> petguid; Unit* pet = ObjectAccessor::GetUnit(*_player, petguid); @@ -494,7 +499,7 @@ void WorldSession::HandlePetSetAction(WorldPacket & recv_data) return; } - count = (recv_data.size() == 24) ? 2 : 1; + count = (recvData.size() == 24) ? 2 : 1; uint32 position[2]; uint32 data[2]; @@ -502,8 +507,8 @@ void WorldSession::HandlePetSetAction(WorldPacket & recv_data) for (uint8 i = 0; i < count; ++i) { - recv_data >> position[i]; - recv_data >> data[i]; + recvData >> position[i]; + recvData >> data[i]; uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); @@ -586,7 +591,7 @@ void WorldSession::HandlePetSetAction(WorldPacket & recv_data) } } -void WorldSession::HandlePetRename(WorldPacket & recv_data) +void WorldSession::HandlePetRename(WorldPacket & recvData) { sLog->outInfo(LOG_FILTER_NETWORKIO, "HandlePetRename. CMSG_PET_RENAME"); @@ -596,9 +601,9 @@ void WorldSession::HandlePetRename(WorldPacket & recv_data) std::string name; DeclinedName declinedname; - recv_data >> petguid; - recv_data >> name; - recv_data >> isdeclined; + recvData >> petguid; + recvData >> name; + recvData >> isdeclined; Pet* pet = ObjectAccessor::FindPet(petguid); // check it! @@ -632,7 +637,7 @@ void WorldSession::HandlePetRename(WorldPacket & recv_data) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { - recv_data >> declinedname.name[i]; + recvData >> declinedname.name[i]; } std::wstring wname; @@ -671,10 +676,10 @@ void WorldSession::HandlePetRename(WorldPacket & recv_data) pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped } -void WorldSession::HandlePetAbandon(WorldPacket & recv_data) +void WorldSession::HandlePetAbandon(WorldPacket & recvData) { uint64 guid; - recv_data >> guid; //pet guid + recvData >> guid; //pet guid sLog->outInfo(LOG_FILTER_NETWORKIO, "HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid)); if (!_player->IsInWorld()) @@ -685,15 +690,7 @@ void WorldSession::HandlePetAbandon(WorldPacket & recv_data) 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(); } @@ -855,33 +852,33 @@ void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, Dec SendPacket(&data); } -void WorldSession::HandlePetLearnTalent(WorldPacket & recv_data) +void WorldSession::HandlePetLearnTalent(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_PET_LEARN_TALENT"); uint64 guid; - uint32 talent_id, requested_rank; - recv_data >> guid >> talent_id >> requested_rank; + uint32 talentId, requestedRank; + recvData >> guid >> talentId >> requestedRank; - _player->LearnPetTalent(guid, talent_id, requested_rank); + _player->LearnPetTalent(guid, talentId, requestedRank); _player->SendTalentsInfoData(true); } -void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket & recv_data) +void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LEARN_PREVIEW_TALENTS_PET"); uint64 guid; - recv_data >> guid; + recvData >> guid; uint32 talentsCount; - recv_data >> talentsCount; + recvData >> talentsCount; uint32 talentId, talentRank; for (uint32 i = 0; i < talentsCount; ++i) { - recv_data >> talentId >> talentRank; + recvData >> talentId >> talentRank; _player->LearnPetTalent(guid, talentId, talentRank); } diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index 90af03113bf..263aa8846ee 100755 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -56,7 +56,7 @@ enum CharterCosts ARENA_TEAM_CHARTER_5v5_COST = 2000000 }; -void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) +void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_BUY"); @@ -64,28 +64,28 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) uint32 clientIndex; // 1 for guild and arenaslot+1 for arenas in client std::string name; - recv_data >> guidNPC; // NPC GUID - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint64>(); // 0 - recv_data >> name; // name - recv_data.read_skip<std::string>(); // some string - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint16>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 + recvData >> guidNPC; // NPC GUID + recvData.read_skip<uint32>(); // 0 + recvData.read_skip<uint64>(); // 0 + recvData >> name; // name + recvData.read_skip<std::string>(); // some string + recvData.read_skip<uint32>(); // 0 + recvData.read_skip<uint32>(); // 0 + recvData.read_skip<uint32>(); // 0 + recvData.read_skip<uint32>(); // 0 + recvData.read_skip<uint32>(); // 0 + recvData.read_skip<uint32>(); // 0 + recvData.read_skip<uint32>(); // 0 + recvData.read_skip<uint16>(); // 0 + recvData.read_skip<uint32>(); // 0 + recvData.read_skip<uint32>(); // 0 + recvData.read_skip<uint32>(); // 0 for (int i = 0; i < 10; ++i) - recv_data.read_skip<std::string>(); + recvData.read_skip<std::string>(); - recv_data >> clientIndex; // index - recv_data.read_skip<uint32>(); // 0 + recvData >> clientIndex; // index + recvData.read_skip<uint32>(); // 0 sLog->outDebug(LOG_FILTER_NETWORKIO, "Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str()); @@ -187,7 +187,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) 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; @@ -250,13 +250,13 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) CharacterDatabase.CommitTransaction(trans); } -void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recv_data) +void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_SHOW_SIGNATURES"); uint8 signs = 0; uint64 petitionguid; - recv_data >> petitionguid; // petition guid + recvData >> petitionguid; // petition guid // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?) uint32 petitionGuidLow = GUID_LOPART(petitionguid); @@ -310,14 +310,14 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recv_data) SendPacket(&data); } -void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recv_data) +void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_QUERY"); // ok uint32 guildguid; uint64 petitionguid; - recv_data >> guildguid; // in Trinity always same as GUID_LOPART(petitionguid) - recv_data >> petitionguid; // petition guid + recvData >> guildguid; // in Trinity always same as GUID_LOPART(petitionguid) + recvData >> petitionguid; // petition guid sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_PETITION_QUERY Petition GUID %u Guild GUID %u", GUID_LOPART(petitionguid), guildguid); SendPetitionQueryOpcode(petitionguid); @@ -355,8 +355,8 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) data << uint8(0); // some string if (type == GUILD_CHARTER_TYPE) { - data << uint32(9); - data << uint32(9); + data << uint32(4); + data << uint32(4); data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition } else @@ -387,16 +387,16 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) SendPacket(&data); } -void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) +void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recvData) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode MSG_PETITION_RENAME"); // ok + sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode MSG_PETITION_RENAME"); uint64 petitionGuid; uint32 type; std::string newName; - recv_data >> petitionGuid; // guid - recv_data >> newName; // new name + recvData >> petitionGuid; // guid + recvData >> newName; // new name Item* item = _player->GetItemByGuid(petitionGuid); if (!item) @@ -460,15 +460,15 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) SendPacket(&data); } -void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) +void WorldSession::HandlePetitionSignOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_SIGN"); // ok Field* fields; uint64 petitionGuid; uint8 unk; - recv_data >> petitionGuid; // petition guid - recv_data >> unk; + recvData >> petitionGuid; // petition guid + recvData >> unk; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURES); @@ -557,14 +557,10 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) 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; } @@ -597,13 +593,13 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) owner->GetSession()->SendPacket(&data); } -void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data) +void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode MSG_PETITION_DECLINE"); // ok uint64 petitionguid; uint64 ownerguid; - recv_data >> petitionguid; // petition guid + recvData >> petitionguid; // petition guid sLog->outDebug(LOG_FILTER_NETWORKIO, "Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_OWNER_BY_GUID); @@ -627,7 +623,7 @@ void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) +void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_OFFER_PETITION"); // ok @@ -635,9 +631,9 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) uint64 petitionguid, plguid; uint32 type, junk; Player* player; - recv_data >> junk; // this is not petition type! - recv_data >> petitionguid; // petition guid - recv_data >> plguid; // player guid + recvData >> junk; // this is not petition type! + recvData >> petitionguid; // petition guid + recvData >> plguid; // player guid player = ObjectAccessor::FindPlayer(plguid); if (!player) @@ -736,7 +732,7 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) player->GetSession()->SendPacket(&data); } -void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) +void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_TURN_IN_PETITION"); @@ -744,7 +740,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) WorldPacket data; uint64 petitionGuid; - recv_data >> petitionGuid; + recvData >> petitionGuid; // Check if player really has the required petition charter Item* item = _player->GetItemByGuid(petitionGuid); @@ -878,7 +874,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) { // Receive the rest of the packet in arena team creation case uint32 background, icon, iconcolor, border, bordercolor; - recv_data >> background >> icon >> iconcolor >> border >> bordercolor; + recvData >> background >> icon >> iconcolor >> border >> bordercolor; // Create arena team ArenaTeam* arenaTeam = new ArenaTeam(); @@ -924,12 +920,12 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) SendPacket(&data); } -void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data) +void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received CMSG_PETITION_SHOWLIST"); uint64 guid; - recv_data >> guid; + recvData >> guid; SendPetitionShowList(guid); } @@ -954,7 +950,7 @@ void WorldSession::SendPetitionShowList(uint64 guid) data << uint32(CHARTER_DISPLAY_ID); // charter display id data << uint32(GUILD_CHARTER_COST); // charter cost data << uint32(0); // unknown - data << uint32(9); // required signs? + data << uint32(4); // required signs? } else { diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index d3f51867831..6ee11e4936d 100755 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -64,10 +64,10 @@ void WorldSession::SendNameQueryOpcode(uint64 guid) SendPacket(&data); } -void WorldSession::HandleNameQueryOpcode(WorldPacket& recv_data) +void WorldSession::HandleNameQueryOpcode(WorldPacket& recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; // This is disable by default to prevent lots of console spam // sLog->outInfo(LOG_FILTER_NETWORKIO, "HandleNameQueryOpcode %u", guid); @@ -75,7 +75,7 @@ void WorldSession::HandleNameQueryOpcode(WorldPacket& recv_data) SendNameQueryOpcode(guid); } -void WorldSession::HandleQueryTimeOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleQueryTimeOpcode(WorldPacket & /*recvData*/) { SendQueryTimeResponse(); } @@ -89,12 +89,12 @@ void WorldSession::SendQueryTimeResponse() } /// Only _static_ data is sent in this packet !!! -void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recv_data) +void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recvData) { uint32 entry; - recv_data >> entry; + recvData >> entry; uint64 guid; - recv_data >> guid; + recvData >> guid; CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(entry); if (ci) @@ -118,10 +118,14 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recv_data) 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 + + for (int i = 0; i < 7; i++) + data << uint8(0); // name2, ..., name8 + data << SubName; data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0 data << uint32(ci->type_flags); // flags + data << uint32(ci->type_flags2); // unknown meaning data << uint32(ci->type); // CreatureType.dbc data << uint32(ci->family); // CreatureFamily.dbc data << uint32(ci->rank); // Creature Rank (elite, boss, etc) @@ -137,6 +141,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recv_data) 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 + data << uint32(ci->expansionUnknown); // unknown meaning SendPacket(&data); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE"); } @@ -152,12 +157,12 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recv_data) } /// Only _static_ data is sent in this packet !!! -void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) +void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recvData) { uint32 entry; - recv_data >> entry; + recvData >> entry; uint64 guid; - recv_data >> guid; + recvData >> guid; const GameObjectTemplate* info = sObjectMgr->GetGameObjectTemplate(entry); if (info) @@ -189,10 +194,11 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) data << IconName; // 2.0.3, string. Icon name to use instead of default icon for go's (ex: "Attack" makes sword) data << CastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting") data << info->unk1; // 2.0.3, string - data.append(info->raw.data, 24); + 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); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); } @@ -207,7 +213,7 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleCorpseQueryOpcode(WorldPacket& /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_CORPSE_QUERY"); @@ -258,15 +264,15 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) SendPacket(&data); } -void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) +void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recvData) { uint32 textID; uint64 guid; - recv_data >> textID; + recvData >> textID; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); - recv_data >> guid; + recvData >> guid; GetPlayer()->SetSelection(guid); GossipText const* pGossip = sObjectMgr->GetGossipText(textID); @@ -342,13 +348,13 @@ void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) } /// Only _static_ data is sent in this packet !!! -void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data) +void WorldSession::HandlePageTextQueryOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PAGE_TEXT_QUERY"); uint32 pageID; - recv_data >> pageID; - recv_data.read_skip<uint64>(); // guid + recvData >> pageID; + recvData.read_skip<uint64>(); // guid while (pageID) { @@ -382,12 +388,12 @@ void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleCorpseMapPositionQuery(WorldPacket & recv_data) +void WorldSession::HandleCorpseMapPositionQuery(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_CORPSE_MAP_POSITION_QUERY"); uint32 unk; - recv_data >> unk; + recvData >> unk; WorldPacket data(SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE, 4+4+4+4); data << float(0); @@ -397,14 +403,14 @@ void WorldSession::HandleCorpseMapPositionQuery(WorldPacket & recv_data) SendPacket(&data); } -void WorldSession::HandleQuestPOIQuery(WorldPacket& recv_data) +void WorldSession::HandleQuestPOIQuery(WorldPacket& recvData) { uint32 count; - recv_data >> count; // quest count, max=25 + recvData >> count; // quest count, max=25 if (count >= MAX_QUEST_LOG_SIZE) { - recv_data.rfinish(); + recvData.rfinish(); return; } @@ -414,7 +420,7 @@ void WorldSession::HandleQuestPOIQuery(WorldPacket& recv_data) for (uint32 i = 0; i < count; ++i) { uint32 questId; - recv_data >> questId; // quest id + recvData >> questId; // quest id bool questOk = false; diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index db18f2a01c9..2f5c031e336 100755..100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -33,12 +33,12 @@ #include "ScriptMgr.h" #include "GameObjectAI.h" -void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket & recv_data) +void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket & recvData) { uint64 guid; - recv_data >> guid; - uint8 questStatus = DIALOG_STATUS_NONE; - uint8 defstatus = DIALOG_STATUS_NONE; + recvData >> guid; + uint32 questStatus = DIALOG_STATUS_NONE; + uint32 defstatus = DIALOG_STATUS_NONE; Object* questgiver = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); if (!questgiver) @@ -79,10 +79,10 @@ void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket & recv_data) _player->PlayerTalkClass->SendQuestGiverStatus(questStatus, guid); } -void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket & recv_data) +void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket& recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u", GUID_LOPART(guid)); @@ -109,12 +109,12 @@ void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket & recv_data) creature->AI()->sGossipHello(_player); } -void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket & recv_data) +void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvData) { uint64 guid; uint32 questId; uint32 unk1; - recv_data >> guid >> questId >> unk1; + recvData >> guid >> questId >> unk1; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST npc = %u, quest = %u, unk1 = %u", uint32(GUID_LOPART(guid)), questId, unk1); @@ -230,12 +230,12 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket & recv_data) _player->PlayerTalkClass->SendCloseGossip(); } -void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPacket & recv_data) +void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPacket& recvData) { uint64 guid; uint32 questId; uint8 unk1; - recv_data >> guid >> questId >> unk1; + recvData >> guid >> questId >> unk1; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_QUERY_QUEST npc = %u, quest = %u, unk1 = %u", uint32(GUID_LOPART(guid)), questId, unk1); // Verify that the guid is valid and is a questgiver or involved in the requested quest @@ -268,24 +268,24 @@ void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleQuestQueryOpcode(WorldPacket & recv_data) +void WorldSession::HandleQuestQueryOpcode(WorldPacket & recvData) { if (!_player) return; uint32 questId; - recv_data >> questId; + recvData >> questId; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUEST_QUERY quest = %u", questId); if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) _player->PlayerTalkClass->SendQuestQueryResponse(quest); } -void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket & recv_data) +void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData) { uint32 questId, reward; uint64 guid; - recv_data >> guid >> questId >> reward; + recvData >> guid >> questId >> reward; if (reward >= QUEST_REWARD_CHOICES_COUNT) { @@ -365,11 +365,11 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket & recv_data) } } -void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPacket & recv_data) +void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPacket & recvData) { uint32 questId; uint64 guid; - recv_data >> guid >> questId; + recvData >> guid >> questId; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_REQUEST_REWARD npc = %u, quest = %u", uint32(GUID_LOPART(guid)), questId); @@ -391,17 +391,17 @@ void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPacket & recv_data) _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true); } -void WorldSession::HandleQuestgiverCancel(WorldPacket& /*recv_data*/) +void WorldSession::HandleQuestgiverCancel(WorldPacket& /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_CANCEL"); _player->PlayerTalkClass->SendCloseGossip(); } -void WorldSession::HandleQuestLogSwapQuest(WorldPacket& recv_data) +void WorldSession::HandleQuestLogSwapQuest(WorldPacket& recvData) { uint8 slot1, slot2; - recv_data >> slot1 >> slot2; + recvData >> slot1 >> slot2; if (slot1 == slot2 || slot1 >= MAX_QUEST_LOG_SIZE || slot2 >= MAX_QUEST_LOG_SIZE) return; @@ -411,10 +411,10 @@ void WorldSession::HandleQuestLogSwapQuest(WorldPacket& recv_data) GetPlayer()->SwapQuestSlot(slot1, slot2); } -void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data) +void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recvData) { uint8 slot; - recv_data >> slot; + recvData >> slot; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTLOG_REMOVE_QUEST slot = %u", slot); @@ -427,7 +427,7 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data) if (const Quest *quest = sObjectMgr->GetQuestTemplate(questId)) { - if (quest->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED)) _player->RemoveTimedQuest(questId); } @@ -440,16 +440,16 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data) _player->SetQuestSlot(slot, 0); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED, 1); + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED, 1); } } -void WorldSession::HandleQuestConfirmAccept(WorldPacket& recv_data) +void WorldSession::HandleQuestConfirmAccept(WorldPacket& recvData) { uint32 questId; - recv_data >> questId; + recvData >> questId; - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT quest = %u", questId); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT questId = %u", questId); if (const Quest* quest = sObjectMgr->GetQuestTemplate(questId)) { @@ -479,16 +479,16 @@ void WorldSession::HandleQuestConfirmAccept(WorldPacket& recv_data) } } -void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recv_data) +void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData) { uint32 questId; - uint64 guid; - - recv_data >> guid >> questId; + uint64 playerGuid; + int8 unkByte; + recvData >> playerGuid >> questId >> unkByte; - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, quest = %u", uint32(GUID_LOPART(guid)), questId); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, questId = %u", uint32(GUID_LOPART(playerGuid)), questId); - Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, playerGuid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); if (!object || !object->hasInvolvedQuest(questId)) return; @@ -500,7 +500,7 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recv_data) { if (!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) { - sLog->outError(LOG_FILTER_NETWORKIO, "Possible hacking attempt: Player %s [guid: %u] tried to complete quest [entry: %u] without being in possession of the quest!", + sLog->outError(LOG_FILTER_NETWORKIO, "Possible hacking attempt: Player %s [playerGuid: %u] tried to complete questId [entry: %u] without being in possession of the questId!", _player->GetName(), _player->GetGUIDLow(), questId); return; } @@ -513,16 +513,16 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recv_data) if (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE) { if (quest->IsRepeatable()) - _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanCompleteRepeatableQuest(quest), false); + _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanCompleteRepeatableQuest(quest), false); else - _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanRewardQuest(quest, false), false); + _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanRewardQuest(quest, false), false); } else { if (quest->GetReqItemsCount()) // some items required - _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanRewardQuest(quest, false), false); + _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanRewardQuest(quest, false), false); else // no items required - _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true); + _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, playerGuid, true); } } } @@ -537,7 +537,7 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) uint32 questId; recvPacket >> questId; - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PUSHQUESTTOPARTY quest = %u", questId); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PUSHQUESTTOPARTY questId = %u", questId); if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { @@ -715,13 +715,13 @@ 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) { - uint8 questStatus = DIALOG_STATUS_NONE; - uint8 defstatus = DIALOG_STATUS_NONE; + uint32 questStatus = DIALOG_STATUS_NONE; + uint32 defstatus = DIALOG_STATUS_NONE; if (IS_CRE_OR_VEH_OR_PET_GUID(*itr)) { @@ -736,7 +736,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket questStatus = getDialogStatus(_player, questgiver, defstatus); data << uint64(questgiver->GetGUID()); - data << uint8(questStatus); + data << uint32(questStatus); ++count; } else if (IS_GAMEOBJECT_GUID(*itr)) @@ -751,7 +751,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket questStatus = getDialogStatus(_player, questgiver, defstatus); data << uint64(questgiver->GetGUID()); - data << uint8(questStatus); + data << uint32(questStatus); ++count; } } @@ -760,7 +760,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket SendPacket(&data); } -void WorldSession::HandleQueryQuestsCompleted(WorldPacket & /*recv_data*/) +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 58d425ddf98..90fbe068984 100644 --- a/src/server/game/Handlers/ReferAFriendHandler.cpp +++ b/src/server/game/Handlers/ReferAFriendHandler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2012 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 @@ -21,12 +21,12 @@ #include "Opcodes.h" #include "Log.h" -void WorldSession::HandleGrantLevel(WorldPacket& recv_data) +void WorldSession::HandleGrantLevel(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GRANT_LEVEL"); uint64 guid; - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); Player* target = ObjectAccessor::GetObjectInWorld(guid, _player); @@ -63,12 +63,12 @@ void WorldSession::HandleGrantLevel(WorldPacket& recv_data) target->GetSession()->SendPacket(&data2); } -void WorldSession::HandleAcceptGrantLevel(WorldPacket& recv_data) +void WorldSession::HandleAcceptGrantLevel(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_ACCEPT_LEVEL_GRANT"); uint64 guid; - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); Player* other = ObjectAccessor::GetObjectInWorld(guid, _player); if (!(other && other->GetSession())) diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index f9731ba85db..f2199e26055 100755 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -26,20 +26,36 @@ #include "ObjectAccessor.h" #include "UpdateMask.h" -void WorldSession::HandleLearnTalentOpcode(WorldPacket & recv_data) +void WorldSession::HandleLearnTalentOpcode(WorldPacket & recvData) { - uint32 talent_id, requested_rank; - recv_data >> 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) { sLog->outDebug(LOG_FILTER_NETWORKIO, "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; @@ -48,17 +64,21 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) { recvPacket >> talentId >> talentRank; - _player->LearnTalent(talentId, talentRank); + if (!_player->LearnTalent(talentId, talentRank)) + { + recvPacket.rfinish(); + break; + } } _player->SendTalentsInfoData(false); } -void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket & recv_data) +void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_TALENT_WIPE_CONFIRM"); uint64 guid; - recv_data >> guid; + recvData >> guid; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!unit) @@ -71,7 +91,7 @@ void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket & recv_data) 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); @@ -84,9 +104,9 @@ void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket & recv_data) unit->CastSpell(_player, 14867, true); //spell: "Untalent Visual Effect" } -void WorldSession::HandleUnlearnSkillOpcode(WorldPacket & recv_data) +void WorldSession::HandleUnlearnSkillOpcode(WorldPacket& recvData) { - uint32 skill_id; - recv_data >> skill_id; - GetPlayer()->SetSkill(skill_id, 0, 0, 0); + uint32 skillId; + recvData >> skillId; + GetPlayer()->SetSkill(skillId, 0, 0, 0); } diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index d7bb10e8ba3..6aeb61b222b 100755 --- 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" @@ -61,6 +62,27 @@ void WorldSession::HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlag ReadMovementInfo(recvPacket, &movementInfo);*/ } } + 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; + } + } + } } void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) @@ -206,7 +228,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); sLog->outError(LOG_FILTER_NETWORKIO, "Possible hacking attempt: Player %s [guid: %u] tried to open item [guid: %u, entry: %u] which is not openable!", pUser->GetName(), pUser->GetGUIDLow(), item->GetGUIDLow(), proto->ItemId); return; @@ -269,11 +291,11 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) pUser->SendLoot(item->GetGUID(), LOOT_CORPSE); } -void WorldSession::HandleGameObjectUseOpcode(WorldPacket & recv_data) +void WorldSession::HandleGameObjectUseOpcode(WorldPacket & recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", GUID_LOPART(guid)); @@ -305,14 +327,18 @@ void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket) go->AI()->GossipHello(_player); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry()); + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry()); } 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; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: got cast spell packet, castCount: %u, spellId: %u, castFlags: %u, data length = %u", castCount, spellId, castFlags, (uint32)recvPacket.size()); @@ -324,8 +350,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) return; } - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) { sLog->outError(LOG_FILTER_NETWORKIO, "WORLD: unknown spell id %u", spellId); @@ -336,7 +362,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) if (mover->GetTypeId() == TYPEID_PLAYER) { // not have spell in spellbook or spell passive and not casted by client - if (!mover->ToPlayer()->HasActiveSpell (spellId) || spellInfo->IsPassive()) + if (!mover->ToPlayer()->HasActiveSpell(spellId) || spellInfo->IsPassive()) { //cheater? kick? ban? recvPacket.rfinish(); // prevent spam at ignore packet @@ -354,6 +380,27 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) } } + 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 casted during shoot rotation // Skip it to prevent "interrupt" message if (spellInfo->IsAutoRepeatRangedSpell() && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) @@ -387,6 +434,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) Spell* spell = new Spell(mover, spellInfo, TRIGGERED_NONE, 0, false); spell->m_cast_count = castCount; // set count of casts + spell->m_glyphIndex = glyphIndex; spell->prepare(&targets); } @@ -484,9 +532,9 @@ void WorldSession::HandleCancelAutoRepeatSpellOpcode(WorldPacket& /*recvPacket*/ _player->InterruptSpell(CURRENT_AUTOREPEAT_SPELL); } -void WorldSession::HandleCancelChanneling(WorldPacket & recv_data) +void WorldSession::HandleCancelChanneling(WorldPacket & recvData) { - recv_data.read_skip<uint32>(); // spellid, not used + recvData.read_skip<uint32>(); // spellid, not used // ignore for remote control state (for player case) Unit* mover = _player->m_mover; @@ -519,7 +567,7 @@ void WorldSession::HandleTotemDestroyed(WorldPacket& recvPacket) totem->ToTotem()->UnSummon(); } -void WorldSession::HandleSelfResOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleSelfResOpcode(WorldPacket& /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SELF_RES"); // empty opcode @@ -536,10 +584,10 @@ void WorldSession::HandleSelfResOpcode(WorldPacket & /*recv_data*/) } } -void WorldSession::HandleSpellClick(WorldPacket& recv_data) +void WorldSession::HandleSpellClick(WorldPacket& recvData) { uint64 guid; - recv_data >> guid; + recvData >> guid; // this will get something not in world. crash Creature* unit = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); @@ -554,11 +602,12 @@ void WorldSession::HandleSpellClick(WorldPacket& recv_data) unit->HandleSpellClick(_player); } -void WorldSession::HandleMirrorImageDataRequest(WorldPacket & recv_data) +void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GET_MIRRORIMAGE_DATA"); uint64 guid; - recv_data >> guid; + recvData >> guid; + recvData.read_skip<uint32>(); // DisplayId ? // Get unit for which data is needed by client Unit* unit = ObjectAccessor::GetObjectInWorld(guid, (Unit*)NULL); @@ -583,12 +632,17 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket & recv_data) 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[] = { diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp index b774fbcba70..a3e7959cdeb 100755 --- a/src/server/game/Handlers/TaxiHandler.cpp +++ b/src/server/game/Handlers/TaxiHandler.cpp @@ -28,13 +28,13 @@ #include "Path.h" #include "WaypointMovementGenerator.h" -void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket & recv_data) +void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_TAXINODE_STATUS_QUERY"); uint64 guid; - recv_data >> guid; + recvData >> guid; SendTaxiStatus(guid); } @@ -63,12 +63,12 @@ void WorldSession::SendTaxiStatus(uint64 guid) sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_TAXINODE_STATUS"); } -void WorldSession::HandleTaxiQueryAvailableNodes(WorldPacket & recv_data) +void WorldSession::HandleTaxiQueryAvailableNodes(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_TAXIQUERYAVAILABLENODES"); uint64 guid; - recv_data >> guid; + recvData >> guid; // cheating checks Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); @@ -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. sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_TAXINODE_STATUS_QUERY %u ", curloc); @@ -163,14 +163,14 @@ void WorldSession::SendDiscoverNewTaxiNode(uint32 nodeid) } } -void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket & recv_data) +void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ACTIVATETAXIEXPRESS"); uint64 guid; uint32 node_count; - recv_data >> guid >> node_count; + recvData >> guid >> node_count; Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); if (!npc) @@ -183,7 +183,7 @@ void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket & recv_data) for (uint32 i = 0; i < node_count; ++i) { uint32 node; - recv_data >> node; + recvData >> node; nodes.push_back(node); } @@ -195,17 +195,14 @@ void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket & recv_data) GetPlayer()->ActivateTaxiPathTo(nodes, npc); } -void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data) +void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_MOVE_SPLINE_DONE"); - uint64 guid; // used only for proper packet read - recv_data.readPackGUID(guid); + recvData.read_skip<uint32>(); // unk MovementInfo movementInfo; // used only for proper packet read - ReadMovementInfo(recv_data, &movementInfo); - - recv_data.read_skip<uint32>(); // unk + ReadMovementInfo(recvData, &movementInfo); // in taxi flight packet received in 2 case: // 1) end taxi path in far (multi-node) flight @@ -273,7 +270,7 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data) GetPlayer()->CastSpell(GetPlayer(), 2479, true); } -void WorldSession::HandleActivateTaxiOpcode(WorldPacket & recv_data) +void WorldSession::HandleActivateTaxiOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ACTIVATETAXI"); @@ -281,7 +278,7 @@ void WorldSession::HandleActivateTaxiOpcode(WorldPacket & recv_data) std::vector<uint32> nodes; nodes.resize(2); - recv_data >> guid >> nodes[0] >> nodes[1]; + recvData >> guid >> nodes[0] >> nodes[1]; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ACTIVATETAXI from %d to %d", nodes[0], nodes[1]); Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); if (!npc) diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp index d6675188f6e..e5618420ac5 100755 --- a/src/server/game/Handlers/TicketHandler.cpp +++ b/src/server/game/Handlers/TicketHandler.cpp @@ -26,7 +26,7 @@ #include "WorldSession.h" #include "Util.h" -void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data) +void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recvData) { // Don't accept tickets if the ticket queue is disabled. (Ticket UI is greyed out but not fully dependable) if (sTicketMgr->GetStatus() == GMTICKET_QUEUE_STATUS_DISABLED) @@ -42,7 +42,7 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data) // Player must not have ticket if (!sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID())) { - GmTicket* ticket = new GmTicket(GetPlayer(), recv_data); + GmTicket* ticket = new GmTicket(GetPlayer(), recvData); sTicketMgr->AddTicket(ticket); sTicketMgr->UpdateLastChange(); @@ -56,10 +56,10 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data) SendPacket(&data); } -void WorldSession::HandleGMTicketUpdateOpcode(WorldPacket & recv_data) +void WorldSession::HandleGMTicketUpdateOpcode(WorldPacket & recvData) { std::string message; - recv_data >> message; + recvData >> message; GMTicketResponse response = GMTICKET_RESPONSE_UPDATE_ERROR; if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID())) @@ -78,7 +78,7 @@ void WorldSession::HandleGMTicketUpdateOpcode(WorldPacket & recv_data) SendPacket(&data); } -void WorldSession::HandleGMTicketDeleteOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleGMTicketDeleteOpcode(WorldPacket & /*recvData*/) { if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID())) { @@ -93,7 +93,7 @@ void WorldSession::HandleGMTicketDeleteOpcode(WorldPacket & /*recv_data*/) } } -void WorldSession::HandleGMTicketGetTicketOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleGMTicketGetTicketOpcode(WorldPacket & /*recvData*/) { SendQueryTimeResponse(); @@ -108,7 +108,7 @@ void WorldSession::HandleGMTicketGetTicketOpcode(WorldPacket & /*recv_data*/) sTicketMgr->SendTicket(this, NULL); } -void WorldSession::HandleGMTicketSystemStatusOpcode(WorldPacket & /*recv_data*/) +void WorldSession::HandleGMTicketSystemStatusOpcode(WorldPacket & /*recvData*/) { // Note: This only disables the ticket UI at client side and is not fully reliable // are we sure this is a uint32? Should ask Zor @@ -117,25 +117,25 @@ void WorldSession::HandleGMTicketSystemStatusOpcode(WorldPacket & /*recv_data*/) SendPacket(&data); } -void WorldSession::HandleGMSurveySubmit(WorldPacket& recv_data) +void WorldSession::HandleGMSurveySubmit(WorldPacket& recvData) { uint32 nextSurveyID = sTicketMgr->GetNextSurveyID(); // just put the survey into the database uint32 mainSurvey; // GMSurveyCurrentSurvey.dbc, column 1 (all 9) ref to GMSurveySurveys.dbc - recv_data >> mainSurvey; + recvData >> mainSurvey; // 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++) { uint32 subSurveyId; // ref to i'th GMSurveySurveys.dbc field (all fields in that dbc point to fields in GMSurveyQuestions.dbc) - recv_data >> subSurveyId; + recvData >> subSurveyId; if (!subSurveyId) break; uint8 rank; // probably some sort of ref to GMSurveyAnswers.dbc - recv_data >> rank; + recvData >> rank; std::string comment; // comment ("Usage: GMSurveyAnswerSubmit(question, rank, comment)") - recv_data >> comment; + recvData >> comment; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GM_SUBSURVEY); stmt->setUInt32(0, nextSurveyID); @@ -146,7 +146,7 @@ void WorldSession::HandleGMSurveySubmit(WorldPacket& recv_data) } std::string comment; // just a guess - recv_data >> comment; + recvData >> comment; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GM_SURVEY); stmt->setUInt32(0, GUID_LOPART(GetPlayer()->GetGUID())); @@ -157,17 +157,17 @@ void WorldSession::HandleGMSurveySubmit(WorldPacket& recv_data) CharacterDatabase.Execute(stmt); } -void WorldSession::HandleReportLag(WorldPacket& recv_data) +void WorldSession::HandleReportLag(WorldPacket& recvData) { // just put the lag report into the database... // can't think of anything else to do with it uint32 lagType, mapId; - recv_data >> lagType; - recv_data >> mapId; + recvData >> lagType; + recvData >> mapId; float x, y, z; - recv_data >> x; - recv_data >> y; - recv_data >> z; + recvData >> x; + recvData >> y; + recvData >> z; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_LAG_REPORT); stmt->setUInt32(0, GUID_LOPART(GetPlayer()->GetGUID())); diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index f50b9ebd311..13cddaff7ea 100755 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -34,34 +34,38 @@ void WorldSession::SendTradeStatus(TradeStatus status) { WorldPacket data; + data.Initialize(SMSG_TRADE_STATUS, 1+4+4); + data.WriteBit(0); // unk bit, usually 0 + 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); // zero 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); // unk 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); // unk + data.FlushBits(); + data << uint32(0); // unk + data << uint32(0); // unk break; case TRADE_STATUS_ONLY_CONJURED: case TRADE_STATUS_NOT_ELIGIBLE: - data.Initialize(SMSG_TRADE_STATUS, 4+1); - data << uint32(status); - data << uint8(0); + data.FlushBits(); + data << uint8(0); // unk break; + case TRADE_STATUS_CURRENCY: // Not implemented + case TRADE_STATUS_CURRENCY_NOT_TRADABLE: // Not implemented + data.FlushBits(); + data << uint32(0); // unk + data << uint32(0); // unk default: - data.Initialize(SMSG_TRADE_STATUS, 4); - data << uint32(status); + data.FlushBits(); break; } @@ -71,60 +75,117 @@ void WorldSession::SendTradeStatus(TradeStatus status) void WorldSession::HandleIgnoreTradeOpcode(WorldPacket& /*recvPacket*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Ignore Trade %u", _player->GetGUIDLow()); - // recvPacket.print_storage(); } void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "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 casted 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(0); // reforge id, FIXME: not implemented + 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); } @@ -462,14 +523,14 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) { if (!AccountMgr::IsPlayerAccount(_player->GetSession()->GetSecurity()) && 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(), _player->GetSession()->GetAccountId(), my_trade->GetMoney(), trader->GetName(), trader->GetSession()->GetAccountId()); } if (!AccountMgr::IsPlayerAccount(trader->GetSession()->GetSecurity()) && 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(), trader->GetSession()->GetAccountId(), his_trade->GetMoney(), _player->GetName(), _player->GetSession()->GetAccountId()); @@ -477,9 +538,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) @@ -539,15 +600,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; @@ -582,7 +660,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) return; } - Player* pOther = ObjectAccessor::FindPlayer(ID); + Player* pOther = ObjectAccessor::FindPlayer(guid); if (!pOther) { @@ -648,15 +726,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(); @@ -674,9 +773,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) diff --git a/src/server/game/Handlers/VehicleHandler.cpp b/src/server/game/Handlers/VehicleHandler.cpp index f0ccfc44e60..b9603cc7822 100644 --- a/src/server/game/Handlers/VehicleHandler.cpp +++ b/src/server/game/Handlers/VehicleHandler.cpp @@ -23,7 +23,7 @@ #include "Log.h" #include "ObjectAccessor.h" -void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data) +void WorldSession::HandleDismissControlledVehicle(WorldPacket &recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE"); @@ -31,44 +31,44 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data) if (!vehicleGUID) // something wrong here... { - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam return; } uint64 guid; - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); MovementInfo mi; mi.guid = guid; - ReadMovementInfo(recv_data, &mi); + ReadMovementInfo(recvData, &mi); _player->m_movementInfo = mi; _player->ExitVehicle(); } -void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data) +void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE"); Unit* vehicle_base = GetPlayer()->GetVehicleBase(); if (!vehicle_base) { - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam return; } VehicleSeatEntry const* seat = GetPlayer()->GetVehicle()->GetSeatForPassenger(GetPlayer()); if (!seat->CanSwitchFromSeat()) { - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam sLog->outError(LOG_FILTER_NETWORKIO, "HandleChangeSeatsOnControlledVehicle, Opcode: %u, Player %u tried to switch seats but current seatflags %u don't permit that.", - recv_data.GetOpcode(), GetPlayer()->GetGUIDLow(), seat->m_flags); + recvData.GetOpcode(), GetPlayer()->GetGUIDLow(), seat->m_flags); return; } - switch (recv_data.GetOpcode()) + switch (recvData.GetOpcode()) { case CMSG_REQUEST_VEHICLE_PREV_SEAT: GetPlayer()->ChangeSeat(-1, false); @@ -76,20 +76,20 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data) case CMSG_REQUEST_VEHICLE_NEXT_SEAT: GetPlayer()->ChangeSeat(-1, true); break; - case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: + /*case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: { uint64 guid; // current vehicle guid - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); + ReadMovementInfo(recvData, &movementInfo); vehicle_base->m_movementInfo = movementInfo; uint64 accessory; // accessory guid - recv_data.readPackGUID(accessory); + recvData.readPackGUID(accessory); int8 seatId; - recv_data >> seatId; + recvData >> seatId; if (vehicle_base->GetGUID() != guid) return; @@ -103,14 +103,14 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data) vehUnit->HandleSpellClick(GetPlayer(), seatId); } break; - } + }*/ case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: { uint64 guid; // current vehicle guid - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); int8 seatId; - recv_data >> seatId; + recvData >> seatId; if (vehicle_base->GetGUID() == guid) GetPlayer()->ChangeSeat(seatId); @@ -125,7 +125,7 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data) } } -void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data) +void WorldSession::HandleEnterPlayerVehicle(WorldPacket& data) { // Read guid uint64 guid; @@ -144,7 +144,7 @@ void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data) } } -void WorldSession::HandleEjectPassenger(WorldPacket &data) +void WorldSession::HandleEjectPassenger(WorldPacket& data) { Vehicle* vehicle = _player->GetVehicleKit(); if (!vehicle) @@ -209,7 +209,7 @@ void WorldSession::HandleEjectPassenger(WorldPacket &data) sLog->outError(LOG_FILTER_NETWORKIO, "HandleEjectPassenger: Player %u tried to eject invalid GUID "UI64FMTD, GetPlayer()->GetGUIDLow(), guid); } -void WorldSession::HandleRequestVehicleExit(WorldPacket& /*recv_data*/) +void WorldSession::HandleRequestVehicleExit(WorldPacket& /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_REQUEST_VEHICLE_EXIT"); diff --git a/src/server/game/Handlers/VoiceChatHandler.cpp b/src/server/game/Handlers/VoiceChatHandler.cpp index 34ad5ac3eae..92e6b45d225 100755 --- a/src/server/game/Handlers/VoiceChatHandler.cpp +++ b/src/server/game/Handlers/VoiceChatHandler.cpp @@ -22,24 +22,28 @@ #include "Opcodes.h" #include "Log.h" -void WorldSession::HandleVoiceSessionEnableOpcode(WorldPacket& recv_data) +void WorldSession::HandleVoiceSessionEnableOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_VOICE_SESSION_ENABLE"); // uint8 isVoiceEnabled, uint8 isMicrophoneEnabled - recv_data.read_skip<uint8>(); - recv_data.read_skip<uint8>(); + recvData.read_skip<uint8>(); + recvData.read_skip<uint8>(); } -void WorldSession::HandleChannelVoiceOnOpcode(WorldPacket& /*recv_data*/) +void WorldSession::HandleChannelVoiceOnOpcode(WorldPacket& /*recvData*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CHANNEL_VOICE_ON"); // Enable Voice button in channel context menu + /* structure: + 8 bits -> channel name length + string -> channel name + */ } -void WorldSession::HandleSetActiveVoiceChannel(WorldPacket& recv_data) +void WorldSession::HandleSetActiveVoiceChannel(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SET_ACTIVE_VOICE_CHANNEL"); - recv_data.read_skip<uint32>(); - recv_data.read_skip<char*>(); + recvData.read_skip<uint32>(); + recvData.read_skip<char*>(); } diff --git a/src/server/game/Handlers/VoidStorageHandler.cpp b/src/server/game/Handlers/VoidStorageHandler.cpp new file mode 100644 index 00000000000..8171a30cc3a --- /dev/null +++ b/src/server/game/Handlers/VoidStorageHandler.cpp @@ -0,0 +1,620 @@ +/* + * Copyright (C) 2008-2012 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) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageUnlock - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); + return; + } + + if (player->IsVoidStorageUnlocked()) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageUnlock - Player (GUID: %u, name: %s) tried to unlock void storage a 2nd time.", player->GetGUIDLow(), player->GetName()); + return; + } + + player->ModifyMoney(-int64(VOID_STORAGE_UNLOCK)); + player->UnlockVoidStorage(); +} + +void WorldSession::HandleVoidStorageQuery(WorldPacket& recvData) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageQuery - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); + return; + } + + if (!player->IsVoidStorageUnlocked()) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageQuery - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName()); + 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 << 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) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit more than 9 items (%u).", player->GetGUIDLow(), player->GetName(), 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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to withdraw more than 9 items (%u).", player->GetGUIDLow(), player->GetName(), 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(); + + recvData.FlushBits(); + + 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][1]); + recvData.ReadByteSeq(itemIds[i][0]); + 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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); + return; + } + + if (!player->IsVoidStorageUnlocked()) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName()); + 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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit an invalid item (item guid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName(), 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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) tried to withdraw an invalid item (id: " UI64FMTD ")", player->GetGUIDLow(), player->GetName(), 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); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) couldn't withdraw item id " UI64FMTD " because inventory was full.", player->GetGUIDLow(), player->GetName(), 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) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "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) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); + return; + } + + if (!player->IsVoidStorageUnlocked()) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName()); + return; + } + + uint8 oldSlot; + if (!player->GetVoidStorageItem(itemId, oldSlot)) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Player (GUID: %u, name: %s) requested swapping an invalid item (slot: %u, itemid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName(), 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/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index be9ee67b341..6888f77916a 100755 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -400,12 +400,15 @@ void InstanceScript::SendEncounterUnit(uint32 type, Unit* unit /*= NULL*/, uint8 case ENCOUNTER_FRAME_ENGAGE: case ENCOUNTER_FRAME_DISENGAGE: case ENCOUNTER_FRAME_UPDATE_PRIORITY: + if (!unit) + return; data.append(unit->GetPackGUID()); data << uint8(param1); break; 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: @@ -413,6 +416,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; } @@ -431,7 +436,7 @@ void InstanceScript::UpdateEncounterState(EncounterCreditType type, uint32 credi if ((*itr)->creditType == type && (*itr)->creditEntry == creditEntry) { completedEncounters |= 1 << (*itr)->dbcEntry->encounterIndex; - sLog->outDebug(LOG_FILTER_TSCR, "Instance %s (instanceId %u) completed encounter %s", instance->GetMapName(), instance->GetInstanceId(), (*itr)->dbcEntry->encounterName[0]); + sLog->outDebug(LOG_FILTER_TSCR, "Instance %s (instanceId %u) completed encounter %s", instance->GetMapName(), instance->GetInstanceId(), (*itr)->dbcEntry->encounterName); if (uint32 dungeonId = (*itr)->lastEncounterDungeon) { Map::PlayerList const& players = instance->GetPlayers(); diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index ba6d327e631..130e06b67c0 100755 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -42,14 +42,17 @@ typedef std::set<Creature*> 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 diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 72636a5d2aa..186b54fd9e0 100755 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -794,20 +794,23 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) { if (lv.permission == NONE_PERMISSION) { - b << uint32(0); //gold + b << uint32(0); // gold b << uint8(0); // item count - return b; // nothing output more + b << uint8(0); // currency count + return b; } Loot &l = lv.loot; uint8 itemsShown = 0; + uint8 currenciesShown = 0; - //gold - b << uint32(l.gold); + 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) { @@ -887,7 +890,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) break; } default: - return b; // nothing output more + return b; } LootSlotType slotType = lv.permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT; @@ -985,8 +988,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; } @@ -1479,7 +1483,7 @@ void LoadLootTemplates_Creature() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u creature loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 creature loot templates. DB table `creature_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 creature loot templates. DB table `creature_loot_template` is empty"); } void LoadLootTemplates_Disenchant() @@ -1491,16 +1495,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) @@ -1512,7 +1517,7 @@ void LoadLootTemplates_Disenchant() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u disenchanting loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 disenchanting loot templates. DB table `disenchant_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 disenchanting loot templates. DB table `disenchant_loot_template` is empty"); } void LoadLootTemplates_Fishing() @@ -1536,7 +1541,7 @@ void LoadLootTemplates_Fishing() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u fishing loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 fishing loot templates. DB table `fishing_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 fishing loot templates. DB table `fishing_loot_template` is empty"); } void LoadLootTemplates_Gameobject() @@ -1570,7 +1575,7 @@ void LoadLootTemplates_Gameobject() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u gameobject loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 gameobject loot templates. DB table `gameobject_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 gameobject loot templates. DB table `gameobject_loot_template` is empty"); } void LoadLootTemplates_Item() @@ -1594,7 +1599,7 @@ void LoadLootTemplates_Item() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u item loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 item loot templates. DB table `item_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 item loot templates. DB table `item_loot_template` is empty"); } void LoadLootTemplates_Milling() @@ -1623,7 +1628,7 @@ void LoadLootTemplates_Milling() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u milling loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 milling loot templates. DB table `milling_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 milling loot templates. DB table `milling_loot_template` is empty"); } void LoadLootTemplates_Pickpocketing() @@ -1657,7 +1662,7 @@ void LoadLootTemplates_Pickpocketing() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u pickpocketing loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 pickpocketing loot templates. DB table `pickpocketing_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 pickpocketing loot templates. DB table `pickpocketing_loot_template` is empty"); } void LoadLootTemplates_Prospecting() @@ -1686,7 +1691,7 @@ void LoadLootTemplates_Prospecting() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u prospecting loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 prospecting loot templates. DB table `prospecting_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 prospecting loot templates. DB table `prospecting_loot_template` is empty"); } void LoadLootTemplates_Mail() @@ -1710,7 +1715,7 @@ void LoadLootTemplates_Mail() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u mail loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 mail loot templates. DB table `mail_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 mail loot templates. DB table `mail_loot_template` is empty"); } void LoadLootTemplates_Skinning() @@ -1744,7 +1749,7 @@ void LoadLootTemplates_Skinning() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u skinning loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 skinning loot templates. DB table `skinning_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 skinning loot templates. DB table `skinning_loot_template` is empty"); } void LoadLootTemplates_Spell() @@ -1786,7 +1791,7 @@ void LoadLootTemplates_Spell() if (count) sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u spell loot templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); else - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 spell loot templates. DB table `spell_loot_template` is empty"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 spell loot templates. DB table `spell_loot_template` is empty"); } void LoadLootTemplates_Reference() diff --git a/src/server/game/Mails/Mail.h b/src/server/game/Mails/Mail.h index 8efb33bda9a..7ae8f659788 100755 --- a/src/server/game/Mails/Mail.h +++ b/src/server/game/Mails/Mail.h @@ -124,13 +124,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 @@ -148,8 +148,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 @@ -165,7 +165,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; @@ -173,8 +173,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 53b2f9cf437..c1510bef543 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -1960,7 +1960,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) @@ -1989,7 +1989,7 @@ void Map::SendInitSelf(Player* player) { sLog->outInfo(LOG_FILTER_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()) @@ -2026,7 +2026,7 @@ void Map::SendInitTransports(Player* player) if (tmap.find(player->GetMapId()) == tmap.end()) return; - UpdateData transData; + UpdateData transData(player->GetMapId()); MapManager::TransportSet& tset = tmap[player->GetMapId()]; @@ -2053,7 +2053,7 @@ void Map::SendRemoveTransports(Player* player) if (tmap.find(player->GetMapId()) == tmap.end()) return; - UpdateData transData; + UpdateData transData(player->GetMapId()); MapManager::TransportSet& tset = tmap[player->GetMapId()]; @@ -2446,10 +2446,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); } diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 0743c4e545f..53588c527e3 100755 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -444,6 +444,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 */ diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index b49d7db0a27..4c272430266 100755 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -181,7 +181,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/MapManager.h b/src/server/game/Maps/MapManager.h index aa07eef2204..8f5c3799161 100755 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -104,21 +104,6 @@ class MapManager return IsValidMapCoord(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation()); } - // modulos a radian orientation to the range of 0..2PI - static float NormalizeOrientation(float o) - { - // fmod only supports positive numbers. Thus we have - // to emulate negative numbers - if (o < 0) - { - float mod = o *-1; - mod = fmod(mod, 2.0f * static_cast<float>(M_PI)); - mod = -mod + 2.0f * static_cast<float>(M_PI); - return mod; - } - return fmod(o, 2.0f * static_cast<float>(M_PI)); - } - void DoDelayedMovesAndRemoves(); void LoadTransports(); diff --git a/src/server/game/Miscellaneous/Formulas.h b/src/server/game/Miscellaneous/Formulas.h index dac5b1ef9a2..212c391d186 100755 --- a/src/server/game/Miscellaneous/Formulas.h +++ b/src/server/game/Miscellaneous/Formulas.h @@ -126,6 +126,9 @@ namespace Trinity case CONTENT_71_80: nBaseExp = 580; break; + case CONTENT_81_85: + nBaseExp = 1878; + break; default: sLog->outError(LOG_FILTER_GENERAL, "BaseGain: Unsupported content level %u", content); nBaseExp = 45; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index f74d6c44be7..fc656f2e88b 100755 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -22,6 +22,8 @@ #include "Define.h" #include <cassert> +#define MAX_CREATURE_BASE_HP 4 + enum SpellEffIndex { EFFECT_0 = 0, @@ -33,14 +35,15 @@ enum SpellEffIndex #define EFFECT_FIRST_FOUND 254 #define EFFECT_ALL 255 + // loot modes for creatures and gameobjects, bitmask! enum LootModes { - LOOT_MODE_DEFAULT = 1, - LOOT_MODE_HARD_MODE_1 = 2, - LOOT_MODE_HARD_MODE_2 = 4, - LOOT_MODE_HARD_MODE_3 = 8, - LOOT_MODE_HARD_MODE_4 = 16 + LOOT_MODE_DEFAULT = 0x1, + LOOT_MODE_HARD_MODE_1 = 0x2, + LOOT_MODE_HARD_MODE_2 = 0x4, + LOOT_MODE_HARD_MODE_3 = 0x8, + LOOT_MODE_HARD_MODE_4 = 0x10 }; enum Gender @@ -53,42 +56,44 @@ enum Gender // Race value is index in ChrRaces.dbc enum Races { - RACE_NONE = 0, - RACE_HUMAN = 1, - RACE_ORC = 2, - RACE_DWARF = 3, - RACE_NIGHTELF = 4, - RACE_UNDEAD_PLAYER = 5, - RACE_TAUREN = 6, - RACE_GNOME = 7, - RACE_TROLL = 8, - //RACE_GOBLIN = 9, - RACE_BLOODELF = 10, - RACE_DRAENEI = 11 - //RACE_FEL_ORC = 12, - //RACE_NAGA = 13, - //RACE_BROKEN = 14, - //RACE_SKELETON = 15, - //RACE_VRYKUL = 16, - //RACE_TUSKARR = 17, - //RACE_FOREST_TROLL = 18, - //RACE_TAUNKA = 19, + RACE_NONE = 0, + RACE_HUMAN = 1, + RACE_ORC = 2, + RACE_DWARF = 3, + RACE_NIGHTELF = 4, + RACE_UNDEAD_PLAYER = 5, + RACE_TAUREN = 6, + RACE_GNOME = 7, + RACE_TROLL = 8, + RACE_GOBLIN = 9, + RACE_BLOODELF = 10, + RACE_DRAENEI = 11, + //RACE_FEL_ORC = 12, + //RACE_NAGA = 13, + //RACE_BROKEN = 14, + //RACE_SKELETON = 15, + //RACE_VRYKUL = 16, + //RACE_TUSKARR = 17, + //RACE_FOREST_TROLL = 18, + //RACE_TAUNKA = 19, //RACE_NORTHREND_SKELETON = 20, - //RACE_ICE_TROLL = 21 + //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_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_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 @@ -148,7 +153,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 { @@ -174,14 +179,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_STORED_POWERS 5 + enum SpellSchools { SPELL_SCHOOL_NORMAL = 0, @@ -426,7 +437,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? @@ -552,11 +563,120 @@ enum SpellAttr7 SPELL_ATTR7_UNK31 = 0x80000000 // 31 only 70769 }; +enum SpellAttr8 +{ + SPELL_ATTR8_UNK0 = 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_UNK8 = 0x00000100, // 8 + 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_UNK10 = 0x00000400, // 10 + 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_UNK15 = 0x00008000, // 15 + SPELL_ATTR8_UNK16 = 0x00010000, // 16 + SPELL_ATTR8_UNK17 = 0x00020000, // 17 + SPELL_ATTR8_UNK18 = 0x00040000, // 18 + SPELL_ATTR8_UNK19 = 0x00080000, // 19 + SPELL_ATTR8_ARMOR_SPECIALIZATION = 0x00100000, // 20 + SPELL_ATTR8_UNK21 = 0x00200000, // 21 + SPELL_ATTR8_UNK22 = 0x00400000, // 22 + SPELL_ATTR8_UNK23 = 0x00800000, // 23 + SPELL_ATTR8_UNK24 = 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_GUILD_PERKS = 0x10000000, // 28 + SPELL_ATTR8_MASTERY = 0x20000000, // 29 + SPELL_ATTR8_UNK30 = 0x40000000, // 30 + SPELL_ATTR8_UNK31 = 0x80000000 // 31 +}; + +enum SpellAttr9 +{ + SPELL_ATTR9_UNK0 = 0x00000001, // 0 + SPELL_ATTR9_UNK1 = 0x00000002, // 1 + SPELL_ATTR9_UNK2 = 0x00000004, // 2 + SPELL_ATTR9_UNK3 = 0x00000008, // 3 + SPELL_ATTR9_UNK4 = 0x00000010, // 4 + SPELL_ATTR9_UNK5 = 0x00000020, // 5 + SPELL_ATTR9_UNK6 = 0x00000040, // 6 + SPELL_ATTR9_UNK7 = 0x00000080, // 7 + SPELL_ATTR9_UNK8 = 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_UNK13 = 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_UNK4 = 0x00000010, // 4 + SPELL_ATTR10_UNK5 = 0x00000020, // 5 + SPELL_ATTR10_UNK6 = 0x00000040, // 6 + SPELL_ATTR10_UNK7 = 0x00000080, // 7 + SPELL_ATTR10_UNK8 = 0x00000100, // 8 + SPELL_ATTR10_UNK9 = 0x00000200, // 9 + SPELL_ATTR10_UNK10 = 0x00000400, // 10 + SPELL_ATTR10_UNK11 = 0x00000800, // 11 + 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 @@ -633,10 +753,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 { @@ -662,7 +784,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, @@ -671,9 +793,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, @@ -709,8 +831,8 @@ enum SpellEffects 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, @@ -780,7 +902,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, @@ -821,203 +943,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_165 = 165, + SPELL_EFFECT_166 = 166, + SPELL_EFFECT_167 = 167, + SPELL_EFFECT_168 = 168, + SPELL_EFFECT_169 = 169, + SPELL_EFFECT_170 = 170, + SPELL_EFFECT_171 = 171, // Summons gamebject + SPELL_EFFECT_172 = 172, // Aoe ressurection + 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_179 = 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 @@ -1090,38 +1245,60 @@ 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_RESSURECT = 98, // Frostmourne has rendered you unable to ressurect. 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 = 105, // You must be above the Enslaved Pearl Miner. + SPELL_CUSTOM_ERROR_MUST_TARGET_CORPSE_SPECIAL_1 = 106, // You must target the corpse of a Seabrush Terrapin, Scourgut Remora, or Spinescale Hammerhead. + SPELL_CUSTOM_ERROR_SLAGHAMMER_ALREADY_PRISONER = 107, // Ambassador Slaghammer is already your prisoner. + SPELL_CUSTOM_ERROR_REQUIRE_ATTUNED_LOCATION_1 = 108, // Requires a location that is attuned with the Naz'jar Battlemaiden. + SPELL_CUSTOM_ERROR_NEED_TO_FREE_DRAKE_FIRST = 109, // Free the Drake from the net first! + SPELL_CUSTOM_ERROR_DRAGONMAW_ALLIES_ALREADY_FOLLOW = 110, // You already have three Dragonmaw allies following you. + SPELL_CUSTOM_ERROR_REQUIRE_OPPOSABLE_THUMBS = 111, // Requires Opposable Thumbs. + SPELL_CUSTOM_ERROR_NOT_ENOUGH_HEALTH_2 = 112, // Not enough health + SPELL_CUSTOM_ERROR_ENOUGH_FORSAKEN_TROOPERS = 113, // You already have enough Forsaken Troopers. + SPELL_CUSTOM_ERROR_CANNOT_JUMP_TO_BOULDER = 114, // You cannot jump to another boulder yet. + SPELL_CUSTOM_ERROR_SKILL_TOO_HIGH = 115, // Skill too high. + SPELL_CUSTOM_ERROR_ALREADY_6_SURVIVORS_RESCUED = 116, // You have already rescued 6 Survivors. + SPELL_CUSTOM_ERROR_MUST_FACE_SHIPS_FROM_BALLOON = 117, // You need to be facing the ships from the rescue balloon. + SPELL_CUSTOM_ERROR_CANNOT_SUPERVISE_MORE_CULTISTS = 118, // You cannot supervise more than 5 Arrested Cultists at a time. + SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_85 = 119, // You must reach level 85 to use this portal. + SPELL_CUSTOM_ERROR_MUST_BE_BELOW_35_HEALTH = 120, // Your target must be below 35% health. + SPELL_CUSTOM_ERROR_MUST_SELECT_TALENT_SPECIAL = 121, // You must select a talent specialization first. }; enum StealthType @@ -1232,7 +1409,8 @@ enum Mechanics MECHANIC_DISCOVERY = 28, MECHANIC_IMMUNE_SHIELD = 29, // Divine (Blessing) Shield/Protection and Ice Block MECHANIC_SAPPED = 30, - MECHANIC_ENRAGED = 31 + MECHANIC_ENRAGED = 31, + MECHANIC_WOUNDED = 32, }; // Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967ca6) @@ -1388,6 +1566,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 }; @@ -1473,7 +1668,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 { @@ -2519,47 +2714,58 @@ uint32 const CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL = (1 << (CREATURE_TYPE_ME // CreatureFamily.dbc enum CreatureFamily { - CREATURE_FAMILY_WOLF = 1, - CREATURE_FAMILY_CAT = 2, - CREATURE_FAMILY_SPIDER = 3, - CREATURE_FAMILY_BEAR = 4, - CREATURE_FAMILY_BOAR = 5, - CREATURE_FAMILY_CROCOLISK = 6, - CREATURE_FAMILY_CARRION_BIRD = 7, - CREATURE_FAMILY_CRAB = 8, - CREATURE_FAMILY_GORILLA = 9, - CREATURE_FAMILY_HORSE_CUSTOM = 10, // not exist in DBC but used for horse like beasts in DB - CREATURE_FAMILY_RAPTOR = 11, - CREATURE_FAMILY_TALLSTRIDER = 12, - CREATURE_FAMILY_FELHUNTER = 15, - CREATURE_FAMILY_VOIDWALKER = 16, - CREATURE_FAMILY_SUCCUBUS = 17, - CREATURE_FAMILY_DOOMGUARD = 19, - CREATURE_FAMILY_SCORPID = 20, - CREATURE_FAMILY_TURTLE = 21, - CREATURE_FAMILY_IMP = 23, - CREATURE_FAMILY_BAT = 24, - CREATURE_FAMILY_HYENA = 25, - CREATURE_FAMILY_BIRD_OF_PREY = 26, - CREATURE_FAMILY_WIND_SERPENT = 27, - CREATURE_FAMILY_REMOTE_CONTROL = 28, - CREATURE_FAMILY_FELGUARD = 29, - CREATURE_FAMILY_DRAGONHAWK = 30, - CREATURE_FAMILY_RAVAGER = 31, - CREATURE_FAMILY_WARP_STALKER = 32, - CREATURE_FAMILY_SPOREBAT = 33, - CREATURE_FAMILY_NETHER_RAY = 34, - CREATURE_FAMILY_SERPENT = 35, - CREATURE_FAMILY_MOTH = 37, - CREATURE_FAMILY_CHIMAERA = 38, - CREATURE_FAMILY_DEVILSAUR = 39, - CREATURE_FAMILY_GHOUL = 40, - CREATURE_FAMILY_SILITHID = 41, - CREATURE_FAMILY_WORM = 42, - CREATURE_FAMILY_RHINO = 43, - CREATURE_FAMILY_WASP = 44, - CREATURE_FAMILY_CORE_HOUND = 45, - CREATURE_FAMILY_SPIRIT_BEAST = 46 + CREATURE_FAMILY_WOLF = 1, + CREATURE_FAMILY_CAT = 2, + CREATURE_FAMILY_SPIDER = 3, + CREATURE_FAMILY_BEAR = 4, + CREATURE_FAMILY_BOAR = 5, + CREATURE_FAMILY_CROCOLISK = 6, + CREATURE_FAMILY_CARRION_BIRD = 7, + CREATURE_FAMILY_CRAB = 8, + CREATURE_FAMILY_GORILLA = 9, + CREATURE_FAMILY_HORSE_CUSTOM = 10, // Does not exist in DBC but used for horse like beasts in DB + CREATURE_FAMILY_RAPTOR = 11, + CREATURE_FAMILY_TALLSTRIDER = 12, + CREATURE_FAMILY_FELHUNTER = 15, + CREATURE_FAMILY_VOIDWALKER = 16, + CREATURE_FAMILY_SUCCUBUS = 17, + CREATURE_FAMILY_DOOMGUARD = 19, + CREATURE_FAMILY_SCORPID = 20, + CREATURE_FAMILY_TURTLE = 21, + CREATURE_FAMILY_IMP = 23, + CREATURE_FAMILY_BAT = 24, + CREATURE_FAMILY_HYENA = 25, + CREATURE_FAMILY_BIRD_OF_PREY = 26, + CREATURE_FAMILY_WIND_SERPENT = 27, + CREATURE_FAMILY_REMOTE_CONTROL = 28, + CREATURE_FAMILY_FELGUARD = 29, + CREATURE_FAMILY_DRAGONHAWK = 30, + CREATURE_FAMILY_RAVAGER = 31, + CREATURE_FAMILY_WARP_STALKER = 32, + CREATURE_FAMILY_SPOREBAT = 33, + CREATURE_FAMILY_NETHER_RAY = 34, + CREATURE_FAMILY_SERPENT = 35, + CREATURE_FAMILY_MOTH = 37, + CREATURE_FAMILY_CHIMAERA = 38, + CREATURE_FAMILY_DEVILSAUR = 39, + CREATURE_FAMILY_GHOUL = 40, + CREATURE_FAMILY_SILITHID = 41, + CREATURE_FAMILY_WORM = 42, + CREATURE_FAMILY_RHINO = 43, + CREATURE_FAMILY_WASP = 44, + CREATURE_FAMILY_CORE_HOUND = 45, + CREATURE_FAMILY_SPIRIT_BEAST = 46, + 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 @@ -2598,6 +2804,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, @@ -2638,7 +2856,12 @@ 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, }; // values based at QuestInfo.dbc @@ -2701,6 +2924,11 @@ enum QuestSort QUEST_SORT_NOBLEGARDEN = 374, QUEST_SORT_PILGRIMS_BOUNTY = 375, 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) @@ -2846,7 +3074,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, @@ -2874,10 +3102,34 @@ enum SkillType SKILL_PET_WASP = 785, SKILL_PET_EXOTIC_RHINO = 786, SKILL_PET_EXOTIC_CORE_HOUND = 787, - SKILL_PET_EXOTIC_SPIRIT_BEAST = 788 -}; - -#define MAX_SKILL_TYPE 789 + 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 825 inline SkillType SkillByLockType(LockType locktype) { @@ -2908,12 +3160,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, @@ -2957,7 +3211,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 @@ -2992,7 +3248,7 @@ enum WeatherType enum ChatMsg { - CHAT_MSG_ADDON = 0xFFFFFFFF, + CHAT_MSG_ADDON = 0xFFFFFFFF, // -1 CHAT_MSG_SYSTEM = 0x00, CHAT_MSG_SAY = 0x01, CHAT_MSG_PARTY = 0x02, @@ -3016,6 +3272,7 @@ enum ChatMsg CHAT_MSG_CHANNEL_LIST = 0x14, CHAT_MSG_CHANNEL_NOTICE = 0x15, CHAT_MSG_CHANNEL_NOTICE_USER = 0x16, + // CHAT_MSG_TARGETICONS CHAT_MSG_AFK = 0x17, CHAT_MSG_DND = 0x18, CHAT_MSG_IGNORED = 0x19, @@ -3044,7 +3301,7 @@ enum ChatMsg CHAT_MSG_ACHIEVEMENT = 0x30, CHAT_MSG_GUILD_ACHIEVEMENT = 0x31, CHAT_MSG_ARENA_POINTS = 0x32, - CHAT_MSG_PARTY_LEADER = 0x33 + CHAT_MSG_PARTY_LEADER = 0x33, }; #define MAX_CHAT_MSG_TYPE 0x34 @@ -3062,14 +3319,14 @@ enum ChatLinkColors // Values from ItemPetFood (power of (value-1) used for compare with CreatureFamilyEntry.petDietMask enum PetDiet { - PET_DIET_MEAT = 1, - PET_DIET_FISH = 2, - PET_DIET_CHEESE = 3, - PET_DIET_BREAD = 4, - PET_DIET_FUNGAS = 5, - PET_DIET_FRUIT = 6, - PET_DIET_RAW_MEAT = 7, - PET_DIET_RAW_FISH = 8 + PET_DIET_MEAT = 1, + PET_DIET_FISH = 2, + PET_DIET_CHEESE = 3, + PET_DIET_BREAD = 4, + PET_DIET_FUNGAS = 5, + PET_DIET_FRUIT = 6, + PET_DIET_RAW_MEAT = 7, + PET_DIET_RAW_FISH = 8 }; #define MAX_PET_DIET 9 @@ -3147,6 +3404,8 @@ enum SummonType SUMMON_TYPE_VEHICLE = 9, SUMMON_TYPE_VEHICLE2 = 10, SUMMON_TYPE_OBJECT = 11, + SUMMON_TYPE_UNK12 = 12, + SUMMON_TYPE_UNK13 = 13, }; enum EventId @@ -3156,121 +3415,121 @@ enum EventId enum ResponseCodes { - RESPONSE_SUCCESS = 0x00, - RESPONSE_FAILURE = 0x01, - RESPONSE_CANCELLED = 0x02, - RESPONSE_DISCONNECTED = 0x03, - RESPONSE_FAILED_TO_CONNECT = 0x04, - RESPONSE_CONNECTED = 0x05, - RESPONSE_VERSION_MISMATCH = 0x06, - - CSTATUS_CONNECTING = 0x07, - CSTATUS_NEGOTIATING_SECURITY = 0x08, - CSTATUS_NEGOTIATION_COMPLETE = 0x09, - CSTATUS_NEGOTIATION_FAILED = 0x0A, - CSTATUS_AUTHENTICATING = 0x0B, - - AUTH_OK = 0x0C, - AUTH_FAILED = 0x0D, - AUTH_REJECT = 0x0E, - AUTH_BAD_SERVER_PROOF = 0x0F, - AUTH_UNAVAILABLE = 0x10, - AUTH_SYSTEM_ERROR = 0x11, - AUTH_BILLING_ERROR = 0x12, - AUTH_BILLING_EXPIRED = 0x13, - AUTH_VERSION_MISMATCH = 0x14, - AUTH_UNKNOWN_ACCOUNT = 0x15, - AUTH_INCORRECT_PASSWORD = 0x16, - AUTH_SESSION_EXPIRED = 0x17, - AUTH_SERVER_SHUTTING_DOWN = 0x18, - AUTH_ALREADY_LOGGING_IN = 0x19, - AUTH_LOGIN_SERVER_NOT_FOUND = 0x1A, - AUTH_WAIT_QUEUE = 0x1B, - AUTH_BANNED = 0x1C, - AUTH_ALREADY_ONLINE = 0x1D, - AUTH_NO_TIME = 0x1E, - AUTH_DB_BUSY = 0x1F, - AUTH_SUSPENDED = 0x20, - AUTH_PARENTAL_CONTROL = 0x21, - AUTH_LOCKED_ENFORCED = 0x22, - - REALM_LIST_IN_PROGRESS = 0x23, - REALM_LIST_SUCCESS = 0x24, - REALM_LIST_FAILED = 0x25, - REALM_LIST_INVALID = 0x26, - REALM_LIST_REALM_NOT_FOUND = 0x27, - - ACCOUNT_CREATE_IN_PROGRESS = 0x28, - ACCOUNT_CREATE_SUCCESS = 0x29, - ACCOUNT_CREATE_FAILED = 0x2A, - - CHAR_LIST_RETRIEVING = 0x2B, - CHAR_LIST_RETRIEVED = 0x2C, - CHAR_LIST_FAILED = 0x2D, - - CHAR_CREATE_IN_PROGRESS = 0x2E, - CHAR_CREATE_SUCCESS = 0x2F, - CHAR_CREATE_ERROR = 0x30, - CHAR_CREATE_FAILED = 0x31, - CHAR_CREATE_NAME_IN_USE = 0x32, - CHAR_CREATE_DISABLED = 0x33, - CHAR_CREATE_PVP_TEAMS_VIOLATION = 0x34, - CHAR_CREATE_SERVER_LIMIT = 0x35, - CHAR_CREATE_ACCOUNT_LIMIT = 0x36, - CHAR_CREATE_SERVER_QUEUE = 0x37, - CHAR_CREATE_ONLY_EXISTING = 0x38, - CHAR_CREATE_EXPANSION = 0x39, - CHAR_CREATE_EXPANSION_CLASS = 0x3A, - CHAR_CREATE_LEVEL_REQUIREMENT = 0x3B, - CHAR_CREATE_UNIQUE_CLASS_LIMIT = 0x3C, - CHAR_CREATE_CHARACTER_IN_GUILD = 0x3D, - CHAR_CREATE_RESTRICTED_RACECLASS = 0x3E, - CHAR_CREATE_CHARACTER_CHOOSE_RACE = 0x3F, - CHAR_CREATE_CHARACTER_ARENA_LEADER = 0x40, - CHAR_CREATE_CHARACTER_DELETE_MAIL = 0x41, - CHAR_CREATE_CHARACTER_SWAP_FACTION = 0x42, - CHAR_CREATE_CHARACTER_RACE_ONLY = 0x43, - - CHAR_CREATE_CHARACTER_GOLD_LIMIT = 0x44, - - CHAR_CREATE_FORCE_LOGIN = 0x45, - - CHAR_DELETE_IN_PROGRESS = 0x46, - CHAR_DELETE_SUCCESS = 0x47, - CHAR_DELETE_FAILED = 0x48, - CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x49, - CHAR_DELETE_FAILED_GUILD_LEADER = 0x4A, - CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x4B, - - CHAR_LOGIN_IN_PROGRESS = 0x4C, - CHAR_LOGIN_SUCCESS = 0x4D, - CHAR_LOGIN_NO_WORLD = 0x4E, - CHAR_LOGIN_DUPLICATE_CHARACTER = 0x4F, - CHAR_LOGIN_NO_INSTANCES = 0x50, - CHAR_LOGIN_FAILED = 0x51, - CHAR_LOGIN_DISABLED = 0x52, - CHAR_LOGIN_NO_CHARACTER = 0x53, - CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x54, - CHAR_LOGIN_LOCKED_BY_BILLING = 0x55, - CHAR_LOGIN_LOCKED_BY_MOBILE_AH = 0x56, - - CHAR_NAME_SUCCESS = 0x57, - CHAR_NAME_FAILURE = 0x58, - CHAR_NAME_NO_NAME = 0x59, - CHAR_NAME_TOO_SHORT = 0x5A, - CHAR_NAME_TOO_LONG = 0x5B, - CHAR_NAME_INVALID_CHARACTER = 0x5C, - CHAR_NAME_MIXED_LANGUAGES = 0x5D, - CHAR_NAME_PROFANE = 0x5E, - CHAR_NAME_RESERVED = 0x5F, - CHAR_NAME_INVALID_APOSTROPHE = 0x60, - CHAR_NAME_MULTIPLE_APOSTROPHES = 0x61, - CHAR_NAME_THREE_CONSECUTIVE = 0x62, - CHAR_NAME_INVALID_SPACE = 0x63, - CHAR_NAME_CONSECUTIVE_SPACES = 0x64, - CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x65, - CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x66, - CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x67 + RESPONSE_SUCCESS = 0, + RESPONSE_FAILURE = 1, + RESPONSE_CANCELLED = 2, + RESPONSE_DISCONNECTED = 3, + RESPONSE_FAILED_TO_CONNECT = 4, + RESPONSE_CONNECTED = 5, + RESPONSE_VERSION_MISMATCH = 6, + + CSTATUS_CONNECTING = 7, + CSTATUS_NEGOTIATING_SECURITY = 8, + CSTATUS_NEGOTIATION_COMPLETE = 9, + CSTATUS_NEGOTIATION_FAILED = 10, + CSTATUS_AUTHENTICATING = 11, + + AUTH_OK = 12, + AUTH_FAILED = 13, + AUTH_REJECT = 14, + AUTH_BAD_SERVER_PROOF = 15, + AUTH_UNAVAILABLE = 16, + AUTH_SYSTEM_ERROR = 17, + AUTH_BILLING_ERROR = 18, + AUTH_BILLING_EXPIRED = 19, + AUTH_VERSION_MISMATCH = 20, + AUTH_UNKNOWN_ACCOUNT = 21, + AUTH_INCORRECT_PASSWORD = 22, + AUTH_SESSION_EXPIRED = 23, + AUTH_SERVER_SHUTTING_DOWN = 24, + AUTH_ALREADY_LOGGING_IN = 25, + AUTH_LOGIN_SERVER_NOT_FOUND = 26, + AUTH_WAIT_QUEUE = 27, + AUTH_BANNED = 28, + AUTH_ALREADY_ONLINE = 29, + AUTH_NO_TIME = 30, + AUTH_DB_BUSY = 31, + AUTH_SUSPENDED = 32, + AUTH_PARENTAL_CONTROL = 33, + AUTH_LOCKED_ENFORCED = 34, + + REALM_LIST_IN_PROGRESS = 35, + REALM_LIST_SUCCESS = 36, + REALM_LIST_FAILED = 37, + REALM_LIST_INVALID = 38, + REALM_LIST_REALM_NOT_FOUND = 39, + + ACCOUNT_CREATE_IN_PROGRESS = 40, + ACCOUNT_CREATE_SUCCESS = 41, + ACCOUNT_CREATE_FAILED = 42, + + CHAR_LIST_RETRIEVING = 43, + CHAR_LIST_RETRIEVED = 44, + CHAR_LIST_FAILED = 45, + + CHAR_CREATE_IN_PROGRESS = 46, + CHAR_CREATE_SUCCESS = 47, + CHAR_CREATE_ERROR = 48, + CHAR_CREATE_FAILED = 49, + CHAR_CREATE_NAME_IN_USE = 50, + CHAR_CREATE_DISABLED = 51, + CHAR_CREATE_PVP_TEAMS_VIOLATION = 52, + CHAR_CREATE_SERVER_LIMIT = 53, + CHAR_CREATE_ACCOUNT_LIMIT = 54, + CHAR_CREATE_SERVER_QUEUE = 55, + CHAR_CREATE_ONLY_EXISTING = 56, + CHAR_CREATE_EXPANSION = 57, + CHAR_CREATE_EXPANSION_CLASS = 58, + CHAR_CREATE_LEVEL_REQUIREMENT = 59, + CHAR_CREATE_UNIQUE_CLASS_LIMIT = 60, + CHAR_CREATE_CHARACTER_IN_GUILD = 61, + CHAR_CREATE_RESTRICTED_RACECLASS = 62, + CHAR_CREATE_CHARACTER_CHOOSE_RACE = 63, + CHAR_CREATE_CHARACTER_ARENA_LEADER = 64, + CHAR_CREATE_CHARACTER_DELETE_MAIL = 65, + CHAR_CREATE_CHARACTER_SWAP_FACTION = 66, + CHAR_CREATE_CHARACTER_RACE_ONLY = 67, + CHAR_CREATE_CHARACTER_GOLD_LIMIT = 68, + CHAR_CREATE_FORCE_LOGIN = 69, + + CHAR_DELETE_IN_PROGRESS = 70, + CHAR_DELETE_SUCCESS = 71, + CHAR_DELETE_FAILED = 72, + CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 73, + CHAR_DELETE_FAILED_GUILD_LEADER = 74, + CHAR_DELETE_FAILED_ARENA_CAPTAIN = 75, + 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 @@ -3292,23 +3551,31 @@ enum BanReturn // 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 -}; - -#define MAX_BATTLEGROUND_TYPE_ID 33 + 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 121 enum MailResponseType { @@ -3357,35 +3624,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 @@ -3522,4 +3798,24 @@ enum CalendarError // Calendar - end +#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, +}; + #endif diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 12b85b10922..6de76a1d9bc 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -237,6 +237,8 @@ void FlightPathMovementGenerator::Reset(Player & player) } init.SetFirstPointId(GetCurrentNode()); init.SetFly(); + init.SetSmooth(); + init.SetWalk(true); init.SetVelocity(PLAYER_FLIGHT_SPEED); init.Launch(); } diff --git a/src/server/game/Movement/MovementStructures.h b/src/server/game/Movement/MovementStructures.h new file mode 100644 index 00000000000..8f609e8d076 --- /dev/null +++ b/src/server/game/Movement/MovementStructures.h @@ -0,0 +1,1998 @@ +/* +* Copyright (C) 2008-2012 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 + +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, + + // Special + MSEZeroBit, // writes bit value 1 or skips read bit + MSEOneBit, // writes bit value 0 or skips read bit + MSEEnd, // marks end of parsing + MSE_COUNT +}; + +//4.3.4 +MovementStatusElements PlayerMoveSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallSinAngle, + 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, +}; + +//4.3.4 +MovementStatusElements MovementFallLandSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallSinAngle, + MSESplineElevation, + MSETimestamp, + MSEPitch, + MSEOrientation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementHeartBeatSequence[] = +{ + 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, + MSEFallSinAngle, + MSEFallCosAngle, + MSEPitch, + MSESplineElevation, + MSETimestamp, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementJumpSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallVerticalSpeed, + MSEFallTime, + MSESplineElevation, + MSEOrientation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementSetFacingSequence[] = +{ + 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, + MSEFallSinAngle, + MSEFallCosAngle, + MSEFallTime, + MSEFallVerticalSpeed, + MSESplineElevation, + MSEOrientation, + MSETimestamp, + MSEPitch, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementSetPitchSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallSinAngle, + MSEPitch, + MSESplineElevation, + MSETimestamp, + MSEOrientation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartBackwardSequence[] = +{ + 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, + MSEFallSinAngle, + MSEFallCosAngle, + MSEFallVerticalSpeed, + MSEFallTime, + MSEOrientation, + MSESplineElevation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartForwardSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallSinAngle, + MSEFallTime, + MSETransportGuidByte3, + MSETransportPositionY, + MSETransportPositionZ, + MSETransportGuidByte1, + MSETransportGuidByte4, + MSETransportGuidByte7, + MSETransportOrientation, + MSETransportGuidByte2, + MSETransportPositionX, + MSETransportGuidByte5, + MSETransportTime3, + MSETransportTime, + MSETransportGuidByte6, + MSETransportGuidByte0, + MSETransportSeat, + MSETransportTime2, + MSESplineElevation, + MSEPitch, + MSEOrientation, + MSETimestamp, + + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartStrafeLeftSequence[] = +{ + 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, + MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, + MSEFallTime, + MSEFallVerticalSpeed, + MSETransportSeat, + MSETransportGuidByte2, + MSETransportTime2, + MSETransportGuidByte3, + MSETransportPositionZ, + MSETransportTime3, + MSETransportGuidByte0, + MSETransportGuidByte7, + MSETransportPositionY, + MSETransportGuidByte5, + MSETransportGuidByte1, + MSETransportOrientation, + MSETransportTime, + MSETransportGuidByte6, + MSETransportGuidByte4, + MSETransportPositionX, + MSETimestamp, + MSEOrientation, + MSEPitch, + MSESplineElevation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartStrafeRightSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallTime, + MSEFallVerticalSpeed, + MSETimestamp, + MSESplineElevation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartTurnLeftSequence[] = +{ + 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, + MSEFallSinAngle, + MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallVerticalSpeed, + MSEFallTime, + MSETransportGuidByte0, + MSETransportPositionX, + MSETransportTime, + MSETransportSeat, + MSETransportPositionZ, + MSETransportGuidByte4, + MSETransportOrientation, + MSETransportGuidByte2, + MSETransportGuidByte6, + MSETransportGuidByte1, + MSETransportGuidByte3, + MSETransportPositionY, + MSETransportTime3, + MSETransportTime2, + MSETransportGuidByte5, + MSETransportGuidByte7, + MSETimestamp, + MSEPitch, + MSEOrientation, + MSESplineElevation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartTurnRightSequence[] = +{ + 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, + MSEFallSinAngle, + MSEFallCosAngle, + MSEFallTime, + MSEFallVerticalSpeed, + MSEPitch, + MSEOrientation, + MSESplineElevation, + MSETimestamp, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStopSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallVerticalSpeed, + MSEFallTime, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStopStrafeSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallSinAngle, + MSEFallTime, + MSEFallVerticalSpeed, + MSESplineElevation, + MSEOrientation, + MSEPitch, + MSETimestamp, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStopTurnSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallSinAngle, + MSEFallVerticalSpeed, + MSETimestamp, + MSEPitch, + MSEOrientation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartAscendSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallTime, + MSEFallVerticalSpeed, + MSEOrientation, + MSEPitch, + MSETimestamp, + MSESplineElevation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartDescendSequence[] = +{ + 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, + MSEFallSinAngle, + MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallVerticalSpeed, + MSETimestamp, + MSEOrientation, + MSESplineElevation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartSwimSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallSinAngle, + MSEFallVerticalSpeed, + MSEFallTime, + MSEOrientation, + MSETimestamp, + MSESplineElevation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStopSwimSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallSinAngle, + MSEFallTime, + MSETimestamp, + MSEPitch, + MSEOrientation, + MSESplineElevation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStopAscendSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEPitch, + MSESplineElevation, + MSETimestamp, + MSEOrientation, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStopPitchSequence[] = +{ + MSEPositionY, + MSEPositionX, + MSEPositionZ, + 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, + MSEFallSinAngle, + MSEFallCosAngle, + MSEFallVerticalSpeed, + MSEFallTime, + MSETransportGuidByte5, + MSETransportGuidByte2, + MSETransportTime2, + MSETransportPositionX, + MSETransportOrientation, + MSETransportGuidByte6, + MSETransportGuidByte3, + MSETransportGuidByte1, + MSETransportPositionZ, + MSETransportTime3, + MSETransportGuidByte0, + MSETransportGuidByte4, + MSETransportTime, + MSETransportPositionY, + MSETransportSeat, + MSETransportGuidByte7, + MSESplineElevation, + MSEOrientation, + MSEPitch, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartPitchDownSequence[] = +{ + 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, + MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, + MSEFallVerticalSpeed, + MSEFallTime, + MSEPitch, + MSEOrientation, + MSESplineElevation, + MSETimestamp, + MSEEnd, +}; + +//4.3.4 +MovementStatusElements MovementStartPitchUpSequence[] = +{ + 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, + MSEFallCosAngle, + MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallVerticalSpeed, + MSEOrientation, + MSESplineElevation, + MSEPitch, + MSETimestamp, + MSEEnd, +}; + +MovementStatusElements 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, + MSEFallCosAngle, + MSEFallSinAngle, + MSEFallVerticalSpeed, + + MSEOrientation, + MSEPitch, + MSESplineElevation, + MSETimestamp, + MSEEnd, +}; + +// 4.3.4 +MovementStatusElements 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, + MSEFallSinAngle, + MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallTime, + + MSEPitch, + MSEOrientation, + + MSETransportGuidByte1, + MSETransportTime3, + MSETransportGuidByte7, + MSETransportTime, + MSETransportPositionY, + MSETransportPositionX, + MSETransportPositionZ, + MSETransportSeat, + MSETransportOrientation, + MSETransportGuidByte0, + MSETransportTime2, + MSETransportGuidByte2, + MSETransportGuidByte3, + MSETransportGuidByte5, + MSETransportGuidByte6, + MSETransportGuidByte4, + + MSETimestamp, + MSESplineElevation, + MSEEnd, +}; + +MovementStatusElements* GetMovementStatusElementsSequence(Opcodes opcode) +{ + switch (opcode) + { + case MSG_MOVE_FALL_LAND: + return MovementFallLandSequence; + case MSG_MOVE_HEARTBEAT: + return MovementHeartBeatSequence; + case MSG_MOVE_JUMP: + return MovementJumpSequence; + case MSG_MOVE_SET_FACING: + return MovementSetFacingSequence; + case MSG_MOVE_SET_PITCH: + return MovementSetPitchSequence; + case MSG_MOVE_START_ASCEND: + return MovementStartAscendSequence; + case MSG_MOVE_START_BACKWARD: + return MovementStartBackwardSequence; + case MSG_MOVE_START_DESCEND: + return MovementStartDescendSequence; + case MSG_MOVE_START_FORWARD: + return MovementStartForwardSequence; + case MSG_MOVE_START_PITCH_DOWN: + return MovementStartPitchDownSequence; + case MSG_MOVE_START_PITCH_UP: + return MovementStartPitchUpSequence; + case MSG_MOVE_START_STRAFE_LEFT: + return MovementStartStrafeLeftSequence; + case MSG_MOVE_START_STRAFE_RIGHT: + return MovementStartStrafeRightSequence; + case MSG_MOVE_START_SWIM: + return MovementStartSwimSequence; + case MSG_MOVE_START_TURN_LEFT: + return MovementStartTurnLeftSequence; + case MSG_MOVE_START_TURN_RIGHT: + return MovementStartTurnRightSequence; + case MSG_MOVE_STOP: + return MovementStopSequence; + case MSG_MOVE_STOP_ASCEND: + return MovementStopAscendSequence; + case MSG_MOVE_STOP_PITCH: + return MovementStopPitchSequence; + case MSG_MOVE_STOP_STRAFE: + return MovementStopStrafeSequence; + case MSG_MOVE_STOP_SWIM: + return MovementStopSwimSequence; + case MSG_MOVE_STOP_TURN: + return MovementStopTurnSequence; + case SMSG_PLAYER_MOVE: + return PlayerMoveSequence; + case CMSG_MOVE_CHNG_TRANSPORT: + return MoveChngTransport; + case CMSG_MOVE_SPLINE_DONE: + return MoveSplineDone; + default: + break; + } + + return NULL; +} + +#endif diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp index 61bd3900b9d..164b65c067d 100644 --- a/src/server/game/Movement/Spline/MoveSpline.cpp +++ b/src/server/game/Movement/Spline/MoveSpline.cpp @@ -50,15 +50,15 @@ Location MoveSpline::ComputePosition() const if (splineflags.final_angle) c.orientation = facing.angle; else if (splineflags.final_point) - c.orientation = atan2(facing.f.y-c.y, facing.f.x-c.x); + c.orientation = atan2(facing.f.y - c.y, facing.f.x - c.x); //nothing to do for MoveSplineFlag::Final_Target flag } 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); + spline.evaluate_derivative(point_Idx, u, hermite); c.orientation = atan2(hermite.y, hermite.x); } @@ -171,6 +171,13 @@ void MoveSpline::Initialize(const MoveSplineInitArgs& args) vertical_acceleration = 0.f; effect_start_time = 0; + // Check if its a stop spline + if (args.flags.done) + { + spline.clear(); + return; + } + init_spline(args); // init parabolic / animation @@ -214,7 +221,7 @@ bool MoveSplineInitArgs::Validate() 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, @@ -264,7 +271,7 @@ MoveSpline::UpdateResult MoveSpline::_updateState(int32& ms_time_diff) { point_Idx = spline.first(); time_passed = time_passed % Duration(); - result = Result_NextSegment; + result = Result_NextCycle; } else { diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h index d4b19b21634..56f2670a04b 100644 --- a/src/server/game/Movement/Spline/MoveSpline.h +++ b/src/server/game/Movement/Spline/MoveSpline.h @@ -41,7 +41,8 @@ namespace Movement { public: typedef Spline<int32> MySpline; - enum UpdateResult{ + enum UpdateResult + { Result_None = 0x01, Result_Arrived = 0x02, Result_NextCycle = 0x04, @@ -70,27 +71,27 @@ namespace Movement void init_spline(const MoveSplineInitArgs& args); protected: - const MySpline::ControlArray& getPath() const { return spline.getPoints();} + const MySpline::ControlArray& getPath() const { return spline.getPoints(); } void computeParabolicElevation(float& el) const; void computeFallElevation(float& el) const; UpdateResult _updateState(int32& ms_time_diff); - int32 next_timestamp() const { return spline.length(point_Idx+1);} - int32 segment_time_elapsed() const { return next_timestamp()-time_passed;} - int32 Duration() const { return spline.length();} - int32 timeElapsed() const { return Duration() - time_passed;} - int32 timePassed() const { return time_passed;} + int32 next_timestamp() const { return spline.length(point_Idx+1); } + int32 segment_time_elapsed() const { return next_timestamp()-time_passed; } + int32 Duration() const { return spline.length(); } + int32 timeElapsed() const { return Duration() - time_passed; } + int32 timePassed() const { return time_passed; } public: - const MySpline& _Spline() const { return spline;} - int32 _currentSplineIdx() const { return point_Idx;} + const MySpline& _Spline() const { return spline; } + int32 _currentSplineIdx() const { return point_Idx; } void _Finalize(); void _Interrupt() { splineflags.done = true;} public: void Initialize(const MoveSplineInitArgs&); - bool Initialized() const { return !spline.empty();} + bool Initialized() const { return !spline.empty(); } explicit MoveSpline(); @@ -112,11 +113,11 @@ namespace Movement Location ComputePosition() const; - uint32 GetId() const { return m_Id;} + uint32 GetId() const { return m_Id; } bool Finalized() const { return splineflags.done; } - bool isCyclic() const { return splineflags.cyclic;} - const Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3();} - const Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx+1) : Vector3();} + bool isCyclic() const { return splineflags.cyclic; } + const Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3(); } + const Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx+1) : Vector3(); } int32 currentPathIdx() const; std::string ToString() const; diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h index cfc2fdee450..89e76faeea3 100644 --- a/src/server/game/Movement/Spline/MoveSplineFlag.h +++ b/src/server/game/Movement/Spline/MoveSplineFlag.h @@ -33,48 +33,52 @@ namespace Movement class MoveSplineFlag { public: - enum eFlags{ + 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;} - inline const uint32& raw() const { return (const uint32&)*this;} + inline uint32& raw() { return (uint32&)*this; } + inline const uint32& raw() const { return (const uint32&)*this; } MoveSplineFlag() { raw() = 0; } MoveSplineFlag(uint32 f) { raw() = f; } @@ -82,58 +86,62 @@ namespace Movement // Constant interface - bool isSmooth() const { return raw() & Mask_CatmullRom;} - bool isLinear() const { return !isSmooth();} - bool isFacing() const { return raw() & Mask_Final_Facing;} + bool isSmooth() const { return raw() & Catmullrom; } + bool isLinear() const { return !isSmooth(); } + bool isFacing() const { return raw() & Mask_Final_Facing; } - uint8 getAnimationId() const { return animId;} - bool hasAllFlags(uint32 f) const { return (raw() & f) == f;} - bool hasFlag(uint32 f) const { return (raw() & f) != 0;} - uint32 operator & (uint32 f) const { return (raw() & f);} - uint32 operator | (uint32 f) const { return (raw() | f);} + uint8 getAnimationId() const { return animId; } + bool hasAllFlags(uint32 f) const { return (raw() & f) == f; } + bool hasFlag(uint32 f) const { return (raw() & f) != 0; } + uint32 operator & (uint32 f) const { return (raw() & f); } + uint32 operator | (uint32 f) const { return (raw() | f); } std::string ToString() const; // Not constant interface - void operator &= (uint32 f) { raw() &= f;} - void operator |= (uint32 f) { raw() |= f;} + 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 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 EnableFalling() { raw() = (raw() & ~(Mask_Animations | Parabolic | Animation)) | Falling; } - void EnableFlying() { raw() = (raw() & ~Catmullrom) | Flying; } - void EnableCatmullRom() { raw() = (raw() & ~Flying) | Catmullrom; } + void EnableCatmullRom() { raw() = (raw() & ~SmoothGroundPath) | Catmullrom | UncompressedPath; } 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; - bool done : 1; - bool falling : 1; - bool no_spline : 1; - bool parabolic : 1; - bool walkmode : 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 unknown7 : 1; - bool unknown8 : 1; + uint8 animId : 3; + bool unknown0 : 1; + bool fallingSlow : 1; + bool done : 1; + bool falling : 1; + bool no_spline : 1; + bool unknown2 : 1; + bool flying : 1; + bool orientationFixed : 1; + bool catmullrom : 1; + bool cyclic : 1; + bool enter_cycle : 1; + bool frozen : 1; + bool transportEnter : 1; + bool transportExit : 1; + bool unknown3 : 1; + bool unknown4 : 1; bool orientationInversed : 1; - bool unknown10 : 1; - bool unknown11 : 1; - bool unknown12 : 1; - bool unknown13 : 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 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 c539dd3cc39..7d91e82096e 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -60,12 +60,10 @@ namespace Movement { MoveSpline& move_spline = *unit.movespline; - bool transport = false; Location real_position(unit.GetPositionX(), unit.GetPositionY(), unit.GetPositionZMinusOffset(), unit.GetOrientation()); // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes - if (unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit.GetTransGUID()) + if (unit.GetTransGUID()) { - transport = true; real_position.x = unit.GetTransOffsetX(); real_position.y = unit.GetTransOffsetY(); real_position.z = unit.GetTransOffsetZ(); @@ -81,7 +79,7 @@ namespace Movement if (args.path.empty()) return; - // corrent first vertex + // correct first vertex args.path[0] = real_position; args.initialOrientation = real_position.orientation; @@ -91,7 +89,7 @@ namespace Movement else moveFlags &= ~MOVEMENTFLAG_WALKING; - moveFlags |= (MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD); + moveFlags |= MOVEMENTFLAG_FORWARD; if (!args.HasVelocity) args.velocity = unit.GetSpeed(SelectSpeedType(moveFlags)); @@ -102,28 +100,57 @@ namespace Movement if (moveFlags & MOVEMENTFLAG_ROOT) moveFlags &= ~MOVEMENTFLAG_MASK_MOVING; - unit.m_movementInfo.SetMovementFlags((MovementFlags)moveFlags); + unit.m_movementInfo.SetMovementFlags(moveFlags); move_spline.Initialize(args); - WorldPacket data(!transport ? SMSG_MONSTER_MOVE : SMSG_MONSTER_MOVE_TRANSPORT, 64); + 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()); data << int8(unit.GetTransSeat()); } PacketBuilder::WriteMonsterMove(move_spline, data); - unit.SendMessageToSet(&data,true); + unit.SendMessageToSet(&data, true); + } + + void MoveSplineInit::Stop() + { + MoveSpline& move_spline = *unit.movespline; + + // No need to stop if we are not moving + if (move_spline.Finalized()) + return; + + Location loc = move_spline.ComputePosition(); + args.flags = MoveSplineFlag::Done; + unit.m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FORWARD); + move_spline.Initialize(args); + + WorldPacket data(SMSG_MONSTER_MOVE, 64); + data.append(unit.GetPackGUID()); + if (unit.GetTransGUID()) + { + data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT); + data.appendPackGUID(unit.GetTransGUID()); + data << int8(unit.GetTransSeat()); + } + + PacketBuilder::WriteStopMovement(loc, args.splineId, data); + unit.SendMessageToSet(&data, true); } MoveSplineInit::MoveSplineInit(Unit& m) : unit(m) { + 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(); // 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) @@ -154,6 +181,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 ef847809ac8..77e34c22b5b 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -58,6 +58,10 @@ namespace Movement */ void Launch(); + /* Final pass of initialization that stops movement. + */ + void Stop(); + /* Adds movement by parabolic trajectory * @param amplitude - the maximum height of parabola, value could be negative and positive * @param start_time - delay between movement starting time and beginning to move by parabolic trajectory @@ -102,6 +106,10 @@ namespace Movement void SetFly(); /* Enables walk mode. Disabled by default */ + void EnableTaxiFlight(); + /* Flags used in taxi + */ + void SetWalk(bool enable); /* Makes movement cyclic. Disabled by default */ @@ -140,16 +148,15 @@ namespace Movement Unit& unit; }; - 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::SetCyclic() { args.flags.cyclic = true;} - inline void MoveSplineInit::SetFall() { args.flags.EnableFalling();} + inline void MoveSplineInit::SetFly() { args.flags.flying = true; } + inline void MoveSplineInit::SetWalk(bool enable) { args.flags.walkmode = enable; } + inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom(); } + inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true; } 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(); } inline void MoveSplineInit::SetTransportExit() { args.flags.EnableTransportExit(); } - inline void MoveSplineInit::SetOrientationFixed(bool enable) { args.flags.orientationFixed = enable;} + inline void MoveSplineInit::SetOrientationFixed(bool enable) { args.flags.orientationFixed = enable; } inline void MoveSplineInit::MovebyPath(const PointsArray& controls, int32 path_offset) { diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp index 8aef671d2d1..027c85cef36 100644 --- a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp +++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008-2012 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 @@ -19,6 +20,7 @@ #include "MovementPacketBuilder.h" #include "MoveSpline.h" #include "WorldPacket.h" +#include "Object.h" namespace Movement { @@ -87,6 +89,14 @@ namespace Movement } } + void PacketBuilder::WriteStopMovement(Vector3 const& pos, uint32 splineId, ByteBuffer& data) + { + data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40) + data << pos; + data << splineId; + data << uint8(MonsterMoveStop); + } + void WriteLinearPath(const Spline<int32>& spline, ByteBuffer& data) { uint32 last_idx = spline.getPointCount() - 3; @@ -128,7 +138,7 @@ namespace Movement const Spline<int32>& spline = move_spline.spline; MoveSplineFlag splineflags = move_spline.splineflags; - if (splineflags & MoveSplineFlag::Mask_CatmullRom) + if (splineflags & MoveSplineFlag::UncompressedPath) { if (splineflags.cyclic) WriteCatmullRomCyclicPath(spline, data); @@ -139,44 +149,100 @@ namespace Movement WriteLinearPath(spline, data); } - void PacketBuilder::WriteCreate(const MoveSpline& move_spline, ByteBuffer& data) + void PacketBuilder::WriteCreateBits(MoveSpline const& moveSpline, ByteBuffer& data) + { + 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) { - //WriteClientStatus(mov,data); - //data.append<float>(&mov.m_float_values[SpeedWalk], SpeedMaxCount); - //if (mov.SplineEnabled()) + if (!moveSpline.Finalized()) { - MoveSplineFlag splineFlags = move_spline.splineflags; + MoveSplineFlag splineFlags = moveSpline.splineflags; + + if ((splineFlags & MoveSplineFlag::Parabolic) && moveSpline.effect_start_time < moveSpline.Duration()) + data << moveSpline.vertical_acceleration; // added in 3.1 - data << splineFlags.raw(); + 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 92a414e9b3b..24b355924c8 100644 --- a/src/server/game/Movement/Spline/MovementPacketBuilder.h +++ b/src/server/game/Movement/Spline/MovementPacketBuilder.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008-2012 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 @@ -19,6 +20,10 @@ #ifndef TRINITYSERVER_PACKET_BUILDER_H #define TRINITYSERVER_PACKET_BUILDER_H +#include "Define.h" // for uint32 +#include "G3D/Vector3.h" +using G3D::Vector3; + class ByteBuffer; class WorldPacket; @@ -31,7 +36,9 @@ namespace Movement public: static void WriteMonsterMove(const MoveSpline& mov, WorldPacket& data); - static void WriteCreate(const MoveSpline& mov, ByteBuffer& data); + static void WriteStopMovement(Vector3 const& loc, uint32 splineId, 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 01c8a5b7e7b..51679260ebb 100644 --- a/src/server/game/Movement/Spline/MovementTypedefs.h +++ b/src/server/game/Movement/Spline/MovementTypedefs.h @@ -54,7 +54,7 @@ namespace Movement class counter { public: - counter() { init();} + counter() { init(); } void Increase() { @@ -64,8 +64,8 @@ namespace Movement ++m_counter; } - T NewId() { Increase(); return m_counter;} - T getCurrent() const { return m_counter;} + T NewId() { Increase(); return m_counter; } + T getCurrent() const { return m_counter; } private: void init() { m_counter = 0; } @@ -76,6 +76,7 @@ namespace Movement extern double gravity; extern float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity); + extern UInt32Counter splineIdGen; } #endif // TRINITYSERVER_TYPEDEFS_H diff --git a/src/server/game/Movement/Spline/MovementUtil.cpp b/src/server/game/Movement/Spline/MovementUtil.cpp index f0ed01c4676..86fcd26fad7 100644 --- a/src/server/game/Movement/Spline/MovementUtil.cpp +++ b/src/server/game/Movement/Spline/MovementUtil.cpp @@ -23,34 +23,35 @@ namespace Movement { double gravity = 19.29110527038574; + UInt32Counter splineIdGen; /// Velocity bounds that makes fall speed limited float terminalVelocity = 60.148003f; - float terminalSavefallVelocity = 7.f; + float terminalSafefallVelocity = 7.f; - const float terminal_length = float(terminalVelocity * terminalVelocity) / (2.f * gravity); - const float terminal_savefall_length = (terminalSavefallVelocity * terminalSavefallVelocity) / (2.f * gravity); - const float terminalFallTime = float(terminalVelocity/gravity); // the time that needed to reach terminalVelocity + const float terminal_length = float(terminalVelocity * terminalVelocity) / (2.0f * gravity); + const float terminal_safefall_length = (terminalSafefallVelocity * terminalSafefallVelocity) / (2.0f * gravity); + const float terminalFallTime = float(terminalVelocity / gravity); // the time that needed to reach terminalVelocity float computeFallTime(float path_length, bool isSafeFall) { - if (path_length < 0.f) - return 0.f; + if (path_length < 0.0f) + return 0.0f; float time; - if ( isSafeFall ) + if (isSafeFall) { - if (path_length >= terminal_savefall_length) - time = (path_length - terminal_savefall_length)/terminalSavefallVelocity + terminalSavefallVelocity/gravity; + if (path_length >= terminal_safefall_length) + time = (path_length - terminal_safefall_length) / terminalSafefallVelocity + terminalSafefallVelocity / gravity; else - time = sqrtf(2.f * path_length/gravity); + time = sqrtf(2.0f * path_length / gravity); } else { if (path_length >= terminal_length) - time = (path_length - terminal_length)/terminalVelocity + terminalFallTime; + time = (path_length - terminal_length) / terminalVelocity + terminalFallTime; else - time = sqrtf(2.f * path_length/gravity); + time = sqrtf(2.0f * path_length / gravity); } return time; @@ -61,20 +62,21 @@ namespace Movement float termVel; float result; - if ( isSafeFall ) - termVel = terminalSavefallVelocity; + if (isSafeFall) + termVel = terminalSafefallVelocity; else termVel = terminalVelocity; - if ( start_velocity > termVel ) + if (start_velocity > termVel) start_velocity = termVel; float terminal_time = terminalFallTime - start_velocity / gravity; // the time that needed to reach terminalVelocity - if ( t_passed > terminal_time ) + if (t_passed > terminal_time) { - result = terminalVelocity*(t_passed - terminal_time) + - start_velocity*terminal_time + gravity*terminal_time*terminal_time*0.5f; + result = terminalVelocity * (t_passed - terminal_time) + + start_velocity * terminal_time + + gravity * terminal_time * terminal_time*0.5f; } else result = t_passed * (start_velocity + t_passed * gravity * 0.5f); @@ -100,7 +102,7 @@ namespace Movement #define STR(x) #x - const char * g_MovementFlag_names[]= + char const* g_MovementFlag_names[] = { STR(Forward ),// 0x00000001, STR(Backward ),// 0x00000002, @@ -112,89 +114,89 @@ namespace Movement 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(Levitation ),// 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 + 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(None8 ), + STR(None9 ), + STR(None10 ), }; - const char * g_SplineFlag_names[32]= + 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> - void print_flags(Flags t, const char* (&names)[N], std::string& str) + void print_flags(Flags t, char const* (&names)[N], std::string& str) { for (int i = 0; i < N; ++i) { - if ((t & (Flags)(1 << i)) && names[i] != NULL) + if ((t & Flags(1 << i)) && names[i] != NULL) str.append(" ").append(names[i]); } } @@ -202,7 +204,7 @@ namespace Movement std::string MoveSplineFlag::ToString() const { std::string str; - print_flags(raw(),g_SplineFlag_names,str); + print_flags(raw(), g_SplineFlag_names, str); return str; } } diff --git a/src/server/game/Movement/Waypoints/WaypointManager.cpp b/src/server/game/Movement/Waypoints/WaypointManager.cpp index a01e18347f6..a03db6bd9f0 100755 --- a/src/server/game/Movement/Waypoints/WaypointManager.cpp +++ b/src/server/game/Movement/Waypoints/WaypointManager.cpp @@ -48,7 +48,7 @@ void WaypointMgr::Load() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 waypoints. DB table `waypoint_data` is empty!"); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 waypoints. DB table `waypoint_data` is empty!"); return; } diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.h b/src/server/game/OutdoorPvP/OutdoorPvP.h index 6ea13d353c5..d2f1362dc82 100755 --- a/src/server/game/OutdoorPvP/OutdoorPvP.h +++ b/src/server/game/OutdoorPvP/OutdoorPvP.h @@ -31,10 +31,9 @@ enum OutdoorPvPTypes OUTDOOR_PVP_TF = 3, OUTDOOR_PVP_ZM = 4, OUTDOOR_PVP_SI = 5, - OUTDOOR_PVP_EP = 6, }; -#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 9221da53003..2a16756161b 100755 --- 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(); @@ -60,115 +61,150 @@ Quest::Quest(Field* questRecord) SourceItemIdCount = questRecord[35].GetUInt8(); SourceSpellid = questRecord[36].GetUInt32(); Flags = questRecord[37].GetUInt32(); - uint32 SpecialFlags = questRecord[38].GetUInt8(); - RewardTitleId = questRecord[39].GetUInt8(); - RequiredPlayerKills = questRecord[40].GetUInt8(); - RewardTalents = questRecord[41].GetUInt8(); - RewardArenaPoints = questRecord[42].GetUInt16(); + SpecialFlags = questRecord[38].GetUInt8(); + 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(); - for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - RequiredSpellCast[i] = questRecord[117+i].GetUInt32(); + RequiredSpell = questRecord[123].GetUInt32(); - // int8 Unknown0 = questRecord[121].GetUInt8(); + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) // To be removed + RequiredSpellCast[i] = questRecord[124+i].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ObjectiveText[i] = questRecord[122+i].GetString(); + ObjectiveText[i] = questRecord[128+i].GetString(); + + for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + RewardCurrencyId[i] = questRecord[132+i].GetUInt16(); + + for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + RewardCurrencyCount[i] = questRecord[136+i].GetUInt8(); + + for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) + RequiredCurrencyId[i] = questRecord[140+i].GetUInt16(); + + for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) + RequiredCurrencyCount[i] = questRecord[144+i].GetUInt8(); + + QuestGiverTextWindow = questRecord[148].GetString(); + QuestGiverTargetName = questRecord[149].GetString(); + QuestTurnTextWindow = questRecord[150].GetString(); + QuestTurnTargetName = questRecord[151].GetString(); + SoundAccept = questRecord[152].GetUInt16(); + SoundTurnIn = questRecord[153].GetUInt16(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - DetailsEmote[i] = questRecord[126+i].GetUInt16(); + DetailsEmote[i] = questRecord[154+i].GetUInt16(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - DetailsEmoteDelay[i] = questRecord[130+i].GetUInt32(); + DetailsEmoteDelay[i] = questRecord[158+i].GetUInt32(); - EmoteOnIncomplete = questRecord[134].GetUInt16(); - EmoteOnComplete = questRecord[135].GetUInt16(); + EmoteOnIncomplete = questRecord[162].GetUInt16(); + EmoteOnComplete = questRecord[163].GetUInt16(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - OfferRewardEmote[i] = questRecord[136+i].GetInt16(); + OfferRewardEmote[i] = questRecord[164+i].GetInt16(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - OfferRewardEmoteDelay[i] = questRecord[140+i].GetInt32(); + OfferRewardEmoteDelay[i] = questRecord[168+i].GetInt32(); - StartScript = questRecord[144].GetUInt32(); - CompleteScript = questRecord[145].GetUInt32(); + StartScript = questRecord[172].GetUInt32(); + CompleteScript = questRecord[173].GetUInt32(); - // int32 WDBVerified = questRecord[146].GetInt32(); + // int32 WDBVerified = questRecord[174].GetInt32(); - Flags |= SpecialFlags << 20; - if (Flags & QUEST_TRINITY_FLAGS_AUTO_ACCEPT) + if (SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT) Flags |= QUEST_FLAGS_AUTO_ACCEPT; - m_reqitemscount = 0; - m_reqCreatureOrGOcount = 0; - m_rewitemscount = 0; - m_rewchoiceitemscount = 0; + m_reqItemsCount = 0; + m_reqNpcOrGoCount = 0; + m_rewItemsCount = 0; + m_rewChoiceItemsCount = 0; + m_rewCurrencyCount = 0; + m_reqCurrencyCount = 0; - for (int i=0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) + for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) if (RequiredItemId[i]) - ++m_reqitemscount; + ++m_reqItemsCount; - for (int i=0; i < QUEST_OBJECTIVES_COUNT; ++i) + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) if (RequiredNpcOrGo[i]) - ++m_reqCreatureOrGOcount; + ++m_reqNpcOrGoCount; - for (int i=0; i < QUEST_REWARDS_COUNT; ++i) + for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) if (RewardItemId[i]) - ++m_rewitemscount; + ++m_rewItemsCount; - for (int i=0; i < QUEST_REWARD_CHOICES_COUNT; ++i) + for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) if (RewardChoiceItemId[i]) - ++m_rewchoiceitemscount; + ++m_rewChoiceItemsCount; + + for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + if (RewardCurrencyId[i]) + ++m_rewCurrencyCount; + + for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) + if (RequiredCurrencyId[i]) + ++m_reqCurrencyCount; + } uint32 Quest::XPValue(Player* player) const @@ -210,6 +246,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()); +} + bool Quest::IsAutoAccept() const { return sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT) ? false : (Flags & QUEST_FLAGS_AUTO_ACCEPT); @@ -235,7 +344,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-1); @@ -243,7 +352,7 @@ uint32 Quest::CalculateHonorGain(uint8 level) const return 0; honor = uint32(tc->value * GetRewHonorMultiplier() * 0.1000000014901161); honor += GetRewHonorAddition(); - } + }*/ return honor; } diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 7f22b441afe..2b4ad24e78f 100755 --- 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 <string> #include <vector> @@ -41,6 +42,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 QuestFailedReasons { @@ -107,17 +110,18 @@ 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 }; enum __QuestFlags @@ -145,20 +149,27 @@ enum __QuestFlags 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. + // ... 4.x added flags up to 0x80000000 - all unknown for now +}; + +enum __QuestSpecialFlags +{ + QUEST_SPECIAL_FLAGS_NONE = 0x000, // Trinity flags for set SpecialFlags in DB if required but used only at server - QUEST_TRINITY_FLAGS_REPEATABLE = 0x00100000, // Set by 1 in SpecialFlags from DB - QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT = 0x00200000, // Set by 2 in SpecialFlags from DB (if reequired area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script) - QUEST_TRINITY_FLAGS_AUTO_ACCEPT = 0x00400000, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted. - QUEST_TRINITY_FLAGS_DF_QUEST = 0x00800000, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder. - - QUEST_TRINITY_FLAGS_DB_ALLOWED = 0xFFFFF | QUEST_TRINITY_FLAGS_REPEATABLE | QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT | QUEST_TRINITY_FLAGS_AUTO_ACCEPT | QUEST_TRINITY_FLAGS_DF_QUEST, - - // Trinity flags for internal use only - QUEST_TRINITY_FLAGS_DELIVER = 0x04000000, // Internal flag computed only - QUEST_TRINITY_FLAGS_SPEAKTO = 0x08000000, // Internal flag computed only - QUEST_TRINITY_FLAGS_KILL_OR_CAST = 0x10000000, // Internal flag computed only - QUEST_TRINITY_FLAGS_TIMED = 0x20000000, // Internal flag computed only - QUEST_TRINITY_FLAGS_PLAYER_KILL = 0x40000000, // Internal flag computed only + QUEST_SPECIAL_FLAGS_REPEATABLE = 0x001, + QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT = 0x002, // if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script) + QUEST_SPECIAL_FLAGS_AUTO_ACCEPT = 0x004, // quest is to be auto-accepted. + QUEST_SPECIAL_FLAGS_DF_QUEST = 0x008, // quest is used by Dungeon Finder. + + // room for more custom flags + + QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT | QUEST_SPECIAL_FLAGS_DF_QUEST, + + QUEST_SPECIAL_FLAGS_DELIVER = 0x080, // Internal flag computed only + QUEST_SPECIAL_FLAGS_SPEAKTO = 0x100, // Internal flag computed only + QUEST_SPECIAL_FLAGS_KILL_OR_CAST = 0x200, // Internal flag computed only + QUEST_SPECIAL_FLAGS_TIMED = 0x400, // Internal flag computed only + QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x800, // Internal flag computed only }; struct QuestLocale @@ -173,6 +184,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, @@ -188,6 +204,9 @@ class Quest bool HasFlag(uint32 flag) const { return (Flags & flag) != 0; } void SetFlag(uint32 flag) { Flags |= flag; } + bool HasSpecialFlag(uint32 flag) const { return (SpecialFlags & flag) != 0; } + void SetSpecialFlag(uint32 flag) { SpecialFlags |= flag; } + // table data accessors: uint32 GetQuestId() const { return Id; } uint32 GetQuestMethod() const { return Method; } @@ -229,11 +248,14 @@ class Quest std::string GetRequestItemsText() const { return RequestItemsText; } std::string GetEndText() const { return EndText; } std::string GetCompletedText() const { return CompletedText; } + std::string GetQuestGiverTextWindow() const { return QuestGiverTextWindow; } + std::string GetQuestGiverTargetName() const { return QuestGiverTargetName; } + std::string GetQuestTurnTextWindow() const { return QuestTurnTextWindow; } + std::string GetQuestTurnTargetName() const { return QuestTurnTargetName; } int32 GetRewOrReqMoney() const; uint32 GetRewHonorAddition() const { return RewardHonor; } float GetRewHonorMultiplier() const { return RewardHonorMultiplier; } - uint32 GetRewMoneyMaxLevel() const { return RewardMoneyMaxLevel; } - // use in XP calculation at client + uint32 GetRewMoneyMaxLevel() const { return RewardMoneyMaxLevel; } // use in XP calculation at client uint32 GetRewSpell() const { return RewardSpell; } int32 GetRewSpellCast() const { return RewardSpellCast; } uint32 GetRewMailTemplateId() const { return RewardMailTemplateId; } @@ -242,21 +264,31 @@ 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; } uint32 GetQuestStartScript() const { return StartScript; } uint32 GetQuestCompleteScript() const { return CompleteScript; } - bool IsRepeatable() const { return Flags & QUEST_TRINITY_FLAGS_REPEATABLE; } + 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; } bool IsWeekly() const { return Flags & QUEST_FLAGS_WEEKLY; } bool IsSeasonal() const { return (ZoneOrSort == -QUEST_SORT_SEASONAL || ZoneOrSort == -QUEST_SORT_SPECIAL || ZoneOrSort == -QUEST_SORT_LUNAR_FESTIVAL || ZoneOrSort == -QUEST_SORT_MIDSUMMER || ZoneOrSort == -QUEST_SORT_BREWFEST || ZoneOrSort == -QUEST_SORT_LOVE_IS_IN_THE_AIR || ZoneOrSort == -QUEST_SORT_NOBLEGARDEN) && !IsRepeatable(); } bool IsDailyOrWeekly() const { return Flags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY); } bool IsRaidQuest() const { return Type == QUEST_TYPE_RAID || Type == QUEST_TYPE_RAID_10 || Type == QUEST_TYPE_RAID_25; } bool IsAllowedInRaid() const; - bool IsDFQuest() const { return Flags & QUEST_TRINITY_FLAGS_DF_QUEST; } + bool IsDFQuest() const { return SpecialFlags & QUEST_SPECIAL_FLAGS_DF_QUEST; } uint32 CalculateHonorGain(uint8 level) const; // multiple values @@ -279,11 +311,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 m_reqitemscount; } - uint32 GetReqCreatureOrGOcount() const { return m_reqCreatureOrGOcount; } - uint32 GetRewChoiceItemsCount() const { return m_rewchoiceitemscount; } - uint32 GetRewItemsCount() const { return m_rewitemscount; } + uint32 GetReqItemsCount() const { return m_reqItemsCount; } + uint32 GetReqCreatureOrGOcount() const { return m_reqNpcOrGoCount; } + uint32 GetRewChoiceItemsCount() const { return m_rewChoiceItemsCount; } + uint32 GetRewItemsCount() const { return m_rewItemsCount; } + uint32 GetRewCurrencyCount() const { return m_rewCurrencyCount; } + uint32 GetReqCurrencyCount() const { return m_reqCurrencyCount; } + + void BuildExtraQuestInfo(WorldPacket& data, Player* player) const; typedef std::vector<int32> PrevQuests; PrevQuests prevQuests; @@ -292,10 +333,12 @@ class Quest // cached data private: - uint32 m_reqitemscount; - uint32 m_reqCreatureOrGOcount; - uint32 m_rewchoiceitemscount; - uint32 m_rewitemscount; + uint32 m_reqItemsCount; + uint32 m_reqNpcOrGoCount; + uint32 m_rewChoiceItemsCount; + uint32 m_rewItemsCount; + uint32 m_rewCurrencyCount; + uint32 m_reqCurrencyCount; // table data protected: @@ -356,6 +399,22 @@ class Quest uint32 EmoteOnComplete; uint32 StartScript; uint32 CompleteScript; + // 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 }; struct QuestStatusData diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp index 05b224fb024..edb4c0c1cf4 100755 --- a/src/server/game/Reputation/ReputationMgr.cpp +++ b/src/server/game/Reputation/ReputationMgr.cpp @@ -197,23 +197,23 @@ void ReputationMgr::SendState(FactionState const* faction) void ReputationMgr::SendInitialReputations() { - WorldPacket data(SMSG_INITIALIZE_FACTIONS, (4+128*5)); - data << uint32 (0x00000080); + WorldPacket data(SMSG_INITIALIZE_FACTIONS, (4+256*5)); + data << uint32(256); // count RepListID a = 0; for (FactionStateList::iterator itr = _factions.begin(); itr != _factions.end(); ++itr) { // fill in absent fields - for (; a != itr->first; a++) + for (; a != itr->first; ++a) { - data << uint8 (0x00); - data << uint32 (0x00000000); + data << uint8(0); + data << uint32(0); } // fill in encountered data - data << uint8 (itr->second.Flags); - data << uint32 (itr->second.Standing); + data << uint8(itr->second.Flags); + data << uint32(itr->second.Standing); itr->second.needSend = false; @@ -221,7 +221,7 @@ void ReputationMgr::SendInitialReputations() } // fill in absent fields - for (; a != 128; a++) + for (; a != 256; ++a) { data << uint8 (0x00); data << uint32 (0x00000000); @@ -388,11 +388,11 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in UpdateRankCounters(old_rank, new_rank); _player->ReputationChanged(factionEntry); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION, factionEntry->ID); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION, factionEntry->ID); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION, factionEntry->ID); + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID); + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID); + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION, factionEntry->ID); + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION, factionEntry->ID); + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION, factionEntry->ID); return true; } diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 9d983542fea..e7d203c9bc1 100755 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -228,25 +228,19 @@ void AddSC_boss_nalorakk(); void AddSC_boss_zuljin(); 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(); -void AddSC_boss_kruul(); void AddSC_burning_steppes(); void AddSC_duskwood(); void AddSC_eastern_plaguelands(); @@ -335,7 +329,6 @@ 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(); @@ -600,7 +593,6 @@ void AddSC_zangarmarsh(); // battlegrounds // outdoor pvp -void AddSC_outdoorpvp_ep(); void AddSC_outdoorpvp_hp(); void AddSC_outdoorpvp_na(); void AddSC_outdoorpvp_si(); @@ -851,25 +843,20 @@ void AddEasternKingdomsScripts() AddSC_boss_zuljin(); 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(); AddSC_arathi_highlands(); AddSC_blasted_lands(); - AddSC_boss_kruul(); AddSC_burning_steppes(); AddSC_duskwood(); AddSC_eastern_plaguelands(); @@ -962,7 +949,6 @@ void AddKalimdorScripts() AddSC_azshara(); AddSC_azuremyst_isle(); AddSC_bloodmyst_isle(); - AddSC_boss_azuregos(); AddSC_darkshore(); AddSC_desolace(); AddSC_durotar(); @@ -1237,7 +1223,6 @@ void AddNorthrendScripts() void AddOutdoorPvPScripts() { #ifdef SCRIPTS - AddSC_outdoorpvp_ep(); AddSC_outdoorpvp_hp(); AddSC_outdoorpvp_na(); AddSC_outdoorpvp_si(); diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 47ce6c17b28..e3f550c5f48 100755 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -1226,7 +1226,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); } diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 270182509f9..0dc357c366d 100755 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -684,7 +684,7 @@ class PlayerScript : public ScriptObject 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*/) { } @@ -990,7 +990,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); diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index a229d3ed536..798dedfa755 100755..100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -16,1325 +16,1701 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/** \file - \ingroup u2w -*/ - #include "Opcodes.h" #include "WorldSession.h" +OpcodeHandler* opcodeTable[NUM_OPCODE_HANDLERS] = { }; + +template<bool isInValidRange, bool isNonZero> +inline void 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 ValidateAndSetOpcode<true, true>(uint16 opcode, char const* name, SessionStatus status, PacketProcessing processing, pOpcodeHandler handler) +{ + if (opcodeTable[opcode] != NULL) + { + sLog->outError(LOG_FILTER_NETWORKIO, "Tried to override handler of %s with %s (opcode %u)", opcodeTable[opcode]->name, name, opcode); + return; + } + + opcodeTable[opcode] = new OpcodeHandler(name, status, processing, handler); +} + +template<> +void ValidateAndSetOpcode<false, true>(uint16 opcode, char const* /*name*/, SessionStatus /*status*/, PacketProcessing /*processing*/, pOpcodeHandler /*handler*/) +{ + sLog->outError(LOG_FILTER_NETWORKIO, "Tried to set handler for an invalid opcode %d", opcode); +} + +template<> +void ValidateAndSetOpcode<true, false>(uint16 /*opcode*/, char const* name, SessionStatus /*status*/, PacketProcessing /*processing*/, pOpcodeHandler /*handler*/) +{ + sLog->outError(LOG_FILTER_NETWORKIO, "Opcode %s got value 0", name); +} + +#define DEFINE_OPCODE_HANDLER(opcode, status, processing, handler) \ + ValidateAndSetOpcode<(opcode < NUM_OPCODE_HANDLERS), (opcode != 0)>(opcode, #opcode, status, processing, handler); + /// Correspondence between opcodes and their names -OpcodeHandler opcodeTable[NUM_MSG_TYPES] = +void InitOpcodes() { - /*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_THREADSAFE, &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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL }, - /*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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL }, - /*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::HandleLeaveBattlefieldOpcode }, - /*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::HandleLfrSearchOpcode }, - /*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_AUTHED, 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_OPPONENT_UPDATE", 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_UPDATE_ITEM_ENCHANTMENTS", 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 }, + memset(opcodeTable, 0, sizeof(opcodeTable)); + + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_BANKER_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBankerActivateOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_LEAVE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldListOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_EXIT_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_PORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBattleFieldPortOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEFIELD_STATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldStatusOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEGROUND_PLAYER_POSITIONS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEMASTER_JOIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_BATTLEMASTER_JOIN_ARENA, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarAddEvent ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_ARENA_TEAM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarArenaTeam ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_COMPLAIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarComplain ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_COPY_EVENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarCopyEvent ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_INVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventInvite ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_MODERATOR_STATUS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventModeratorStatus); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_REMOVE_INVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventRemoveInvite ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_RSVP, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventRsvp ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_SIGNUP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_EVENT_STATUS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarEventStatus ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GET_CALENDAR, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGetCalendar ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GET_EVENT, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGuildFilter ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_REMOVE_EVENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarRemoveEvent ); + DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_UPDATE_EVENT, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAutoRepeatSpellOpcode); + DEFINE_OPCODE_HANDLER(CMSG_CANCEL_CAST, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCancelCastOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_CANCEL_CHANNELLING, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_VOICE_ON, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_DELETEEQUIPMENT_SET, 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_UNHANDLED, 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_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissControlledVehicle ); + DEFINE_OPCODE_HANDLER(CMSG_DISMISS_CRITTER, STATUS_UNHANDLED, 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_DUNGEON_FINDER_GET_SYSTEM_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_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_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveRootAck ); + DEFINE_OPCODE_HANDLER(CMSG_FORCE_MOVE_UNROOT_ACK, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGMSurveySubmit ); + DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_CREATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketCreateOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_DELETETICKET, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketDeleteOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_GETTICKET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketGetTicketOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_SYSTEMSTATUS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketSystemStatusOpcode); + DEFINE_OPCODE_HANDLER(CMSG_GMTICKET_UPDATETEXT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketUpdateOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_GM_REPORT_LAG, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_GUILD_BANK_SET_TAB_TEXT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, 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_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDisbandOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_GUILD_EVENT_LOG_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_LFG_JOIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_LFG_LEAVE, STATUS_UNHANDLED, 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_PROPOSAL_RESULT, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_BROWSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_DECLINE_RECRUIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_GET_APPLICATIONS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_GET_RECRUITS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_POST_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_REMOVE_RECRUIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_SET_GUILD_POST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleFeatherFallAck ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveKnockBackAck ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_NOT_ACTIVE_MOVER, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveNotActiveMover ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_CAN_FLY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_CAN_FLY_ACK, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_XP, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_REQUEST_CEMETERY_LIST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_REQUEST_HONOR_STATS, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_REQUEST_PVP_REWARDS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RAID_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRaidInfoOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RATED_BG_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_REQUEST_RATED_BG_STATS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_SET_SELECTION, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSetSelectionOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_SET_TAXI_BENCHMARK_MODE, STATUS_AUTHED, 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_UNHANDLED, 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_THREADSAFE, &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_NULL ); + DEFINE_OPCODE_HANDLER(MSG_CHANNEL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + 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_UNHANDLED, 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_NULL ); + 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_UPDATE_FLIGHT_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_RUN_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_TELEPORT, 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_UNHANDLED, 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_OPPONENT_UPDATE, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_EJECTED, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS2, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS3, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS4, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_BATTLEFIELD_STATUS_FAILED, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_LEFT, STATUS_UNHANDLED, 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_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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_CLEAR_PENDING_ACTION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_COMMAND_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_ALERT, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_REMOVED_ALERT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_STATUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_UPDATED_ALERT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_FILTER_GUILD, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_RAID_LOCKOUT_ADDED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_RAID_LOCKOUT_REMOVED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_RAID_LOCKOUT_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_SEND_CALENDAR, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_CALENDAR_SEND_EVENT, STATUS_UNHANDLED, 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_COOLDOWNS, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_GMRESPONSE_STATUS_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_CREATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_DELETETICKET, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_GMTICKET_UPDATETEXT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_GM_MESSAGECHAT, STATUS_UNHANDLED, 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_NEVER, 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_JOINED_BATTLEGROUND, STATUS_UNHANDLED, 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_UNHANDLED, 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_RESULTS, STATUS_UNHANDLED, 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_RESULTS, STATUS_UNHANDLED, 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, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP_GAIN, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_INSTANCE_LOCK_WARNING_QUERY, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LFG_DISABLED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LFG_JOIN_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LFG_OFFER_CONTINUE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LFG_PARTY_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LFG_PLAYER_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LFG_PLAYER_REWARD, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LFG_PROPOSAL_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LFG_QUEUE_STATUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LFG_ROLE_CHECK_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LFG_ROLE_CHOSEN, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_BROWSE_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_COMMAND_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_POST_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_RECRUIT_LIST_UPDATED, STATUS_UNHANDLED, 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_UNHANDLED, 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_COMPLETE, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_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_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_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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_PET_ACTION_SOUND, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_SOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_PLAY_SPELL_VISUAL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_PLAY_SPELL_VISUAL_KIT, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_PVP_OPTIONS_ENABLED, STATUS_UNHANDLED, 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_AUTHED, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_SET_PLAY_HOVER_ANIM, STATUS_UNHANDLED, 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_RATINGS, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, 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_FEATHER_FALL, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_NORMAL_FALL, STATUS_UNHANDLED, 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_START_SWIM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_STOP_SWIM, STATUS_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNSET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_WATER_WALK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_STABLE_RESULT, STATUS_UNHANDLED, 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_UNHANDLED, 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_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_TRAINER_BUY_SUCCEEDED, STATUS_UNHANDLED, 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_ITEM_ENCHANTMENTS, STATUS_UNHANDLED, 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_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_VOID_STORAGE_CONTENTS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_VOID_STORAGE_FAILED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_VOID_STORAGE_TRANSFER_CHANGES, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_VOID_TRANSFER_RESULT, STATUS_LOGGEDIN, 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_UNHANDLED, 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_EQUIPMENT_SET_DELETE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetDelete ); + //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_GUILD_LEADER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildLeaderOpcode ); + //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_LEAVE_BATTLEFIELD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLeaveBattlefieldOpcode ); + //DEFINE_OPCODE_HANDLER(CMSG_LEVEL_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(CMSG_LFD_PARTY_LOCK_INFO_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgPartyLockInfoRequestOpcode); + //DEFINE_OPCODE_HANDLER(CMSG_LFD_PLAYER_LOCK_INFO_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgPlayerLockInfoRequestOpcode); + //DEFINE_OPCODE_HANDLER(CMSG_LFG_GET_PLAYER_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(CMSG_LFG_PARTY_LOCK_INFO_REQUEST, 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(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_FLY, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); + //DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_RELATIVE_POSITION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_RUN_SPEED, 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_MOVE_TOGGLE_COLLISION_ACK, 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_QUEST_NPC_QUERY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //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::HandleLfrSearchOpcode ); + //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_GUILD_BANK_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetGuildBankTabText ); + //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_BATTLEGROUND_PLAYER_POSITIONS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlegroundPlayerPositionsOpcode); + //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_GUILD_BANK_LOG_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankLogQuery ); + //DEFINE_OPCODE_HANDLER(MSG_GUILD_EVENT_LOG_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildEventLogQueryOpcode ); + //DEFINE_OPCODE_HANDLER(MSG_INSPECT_HONOR_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectHonorStatsOpcode ); + //DEFINE_OPCODE_HANDLER(MSG_MOVE_FEATHER_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(MSG_MOVE_GRAVITY_CHNG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(MSG_MOVE_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(MSG_MOVE_ROOT, 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_COLLISION_HEIGHT, 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, 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_MOVE_UPDATE_CAN_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_MOUSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(MSG_MOVE_WATER_WALK, 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_QUERY_GUILD_BANK_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryGuildBankTabText ); + //DEFINE_OPCODE_HANDLER(MSG_START_MOVE_FORWARD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //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_BATTLEFIELD_STATUS1, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_POSITIONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_BINDZONEREPLY, 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_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_COOLDOWN, 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_COMPRESSED_ACHIEVEMENT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_CHAR_ENUM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_GUILD_ROSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_UNKNOWN_1310, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_UPDATE_OBJECT, 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_INSTANCE_DIFFICULTY, 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_LFG_UPDATE_PARTY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_PLAYER, 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_DISABLE_COLLISION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_MOVE_DISABLE_GRAVITY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_MOVE_ENABLE_COLLISION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_MOVE_ENABLE_GRAVITY, 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_MOVE_UPDATE_TELEPORT, 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_PLAY_SPELL_IMPACT, 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_SETUP_RESEARCH_HISTORY, 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_SHOW_MAILBOX, 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_SPLINE_MOVE_LAND_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_NORMAL_FALL, 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_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_FLIGHT_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_RUN_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_SWIM_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_SWIM_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_TURN_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_WALK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_TRAINER_BUY_RESULT, 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 d5b9dff4a89..07cfdf39bb1 100755 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -25,1327 +25,1384 @@ #include "Common.h" -// Note: this include need for be sure have full definition of class WorldSession -// if this class definition not complete then VS for x64 release use different size for -// struct OpcodeHandler in this header and Opcode.cpp and get totally wrong data from -// table opcodeTable in source when Opcode.h included but WorldSession.h not included -#include "WorldSession.h" - /// List of Opcodes enum Opcodes { - 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_OPPONENT_UPDATE = 0x4C7, // uint64 - 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_UPDATE_ITEM_ENCHANTMENTS = 0x50B, // some item update packet? - 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_DELETEEQUIPMENT_SET = 0x4D07, + CMSG_DEL_FRIEND = 0x6A15, + CMSG_DEL_IGNORE = 0x4727, + 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_DUNGEON_FINDER_GET_SYSTEM_INFO = 0x0412, + CMSG_EJECT_PASSENGER = 0x6927, + CMSG_EMOTE = 0x4C26, + CMSG_ENABLETAXI = 0x0C16, + CMSG_ENABLE_NAGLE = 0x4449, + CMSG_EQUIPMENT_SET_DELETE = 0x0000, + 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_SET_TAB_TEXT = 0x3023, + 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_LEADER = 0x0000, + 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_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_BATTLEFIELD = 0x0000, + CMSG_LEAVE_CHANNEL = 0x2D56, + CMSG_LFG_GET_PLAYER_INFO = 0x0000, + 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_PARTY_LOCK_INFO_REQUEST = 0x0000, + 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_JOIN = 0x0000, + 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_HONOR_STATS = 0x791E, + 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 = 0x0000, + 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_BATTLEGROUND_PLAYER_POSITIONS = 0x0000, + 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_GUILD_BANK_LOG_QUERY = 0x0000, + MSG_GUILD_EVENT_LOG_QUERY = 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_FEATHER_FALL = 0x0000, + MSG_MOVE_GRAVITY_CHNG = 0x0000, + MSG_MOVE_HEARTBEAT = 0x3914, + MSG_MOVE_HOVER = 0x0000, + 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_CAN_FLY = 0x0000, + MSG_MOVE_UPDATE_FLIGHT_SPEED = 0x30B1, + MSG_MOVE_UPDATE_MOUSE = 0x0000, + MSG_MOVE_UPDATE_RUN_SPEED = 0x14A6, + MSG_MOVE_UPDATE_TELEPORT = 0x50B2, + MSG_MOVE_WATER_WALK = 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_GUILD_BANK_TEXT = 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_OPPONENT_UPDATE = 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_STATUS1 = 0x0000, + SMSG_BATTLEFIELD_STATUS2 = 0x74A4, + SMSG_BATTLEFIELD_STATUS3 = 0x59A0, + SMSG_BATTLEFIELD_STATUS4 = 0x75A2, + SMSG_BATTLEFIELD_STATUS_FAILED = 0x71A7, + SMSG_BATTLEGROUND_INFO_THROTTLED = 0x34B2, + SMSG_BATTLEGROUND_PLAYER_JOINED = 0x50B0, + SMSG_BATTLEGROUND_PLAYER_LEFT = 0x59A6, + SMSG_BATTLEGROUND_PLAYER_POSITIONS = 0x0000, + SMSG_BINDER_CONFIRM = 0x2835, + SMSG_BINDPOINTUPDATE = 0x0527, + SMSG_BINDZONEREPLY = 0x0000, + SMSG_BREAK_TARGET = 0x0105, + SMSG_BUY_BANK_SLOT_RESULT = 0x0000, + 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 = 0x0000, + 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_ACHIEVEMENT_DATA = 0x0000, + SMSG_COMPRESSED_CHAR_ENUM = 0x0000, + SMSG_COMPRESSED_GUILD_ROSTER = 0x0000, + SMSG_COMPRESSED_MOVES = 0x0517, + SMSG_COMPRESSED_UPDATE_OBJECT = 0x0000, + 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 = 0x0627, + 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_JOINED_BATTLEGROUND = 0x35A1, + 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_RESULTS = 0x30B2, + SMSG_GUILD_BANK_MONEY_WITHDRAWN = 0x5DB4, + SMSG_GUILD_BANK_QUERY_TEXT_RESULTS = 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 = 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_DIFFICULTY = 0x0000, + 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_PARTY = 0x0000, + SMSG_LFG_UPDATE_PLAYER = 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_LF_GUILD_SEARCH_RESULT = 0x0000, + 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 = 0x2524, + 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_DISABLE_COLLISION = 0x0000, + SMSG_MOVE_DISABLE_GRAVITY = 0x0000, + SMSG_MOVE_ENABLE_COLLISION = 0x0000, + SMSG_MOVE_ENABLE_GRAVITY = 0x0000, + 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_KNOCK_BACK = 0x3DB2, + SMSG_MOVE_UPDATE_PITCH_RATE = 0x1DB5, + SMSG_MOVE_UPDATE_RUN_BACK_SPEED = 0x3DA6, + SMSG_MOVE_UPDATE_SWIM_BACK_SPEED = 0x30B5, + SMSG_MOVE_UPDATE_SWIM_SPEED = 0x59B5, + SMSG_MOVE_UPDATE_TELEPORT = 0x0000, + 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_SOUND = 0x2134, + SMSG_PLAY_SPELL_IMPACT = 0x0000, + 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_SETUP_RESEARCH_HISTORY = 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_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_RATINGS = 0x11B4, + 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_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 = 0x0000, + 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_RESULT = 0x0000, + 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_ITEM_ENCHANTMENTS = 0x6014, + 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 @@ -1367,30 +1424,48 @@ enum PacketProcessing }; class WorldPacket; +class WorldSession; + +typedef void(WorldSession::*pOpcodeHandler)(WorldPacket& recvPacket); struct OpcodeHandler { + OpcodeHandler() {} + OpcodeHandler(char const* _name, SessionStatus _status, PacketProcessing _processing, pOpcodeHandler _handler) + : name(_name), status(_status), packetProcessing(_processing), handler(_handler) {} + char const* name; SessionStatus status; PacketProcessing packetProcessing; - void (WorldSession::*handler)(WorldPacket& recvPacket); + pOpcodeHandler handler; }; -extern OpcodeHandler opcodeTable[NUM_MSG_TYPES]; +extern OpcodeHandler* opcodeTable[NUM_OPCODE_HANDLERS]; +void InitOpcodes(); /// 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; -} - -inline std::string GetOpcodeNameForLogging(uint16 opcode) +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 << ")]"; - return ss.str().c_str(); + ss << '['; + + if (id < UNKNOWN_OPCODE) + { + if (OpcodeHandler* 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(); } #endif diff --git a/src/server/game/Server/WorldPacket.cpp b/src/server/game/Server/WorldPacket.cpp new file mode 100644 index 00000000000..266f5e74e1d --- /dev/null +++ b/src/server/game/Server/WorldPacket.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2008-2012 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) + { + sLog->outError(LOG_FILTER_NETWORKIO, "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); + + sLog->outInfo(LOG_FILTER_NETWORKIO, "Successfully compressed opcode %u (len %u) to %u (len %u)", uncompressedOpcode, 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) + { + sLog->outError(LOG_FILTER_NETWORKIO, "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); + + sLog->outInfo(LOG_FILTER_NETWORKIO, "Successfully compressed opcode %u (len %u) to %u (len %u)", uncompressedOpcode, 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) + { + sLog->outError(LOG_FILTER_NETWORKIO, "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) + { + sLog->outError(LOG_FILTER_NETWORKIO, "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..c695c16ed3b --- /dev/null +++ b/src/server/game/Server/WorldPacket.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008-2012 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) + { + } + + WorldPacket(Opcodes opcode, size_t res = 200) : ByteBuffer(res), m_opcode(opcode) + { + } + // copy constructor + WorldPacket(WorldPacket const& packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) + { + } + + 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 6a2c7e64446..a2f2492b810 100755..100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -21,6 +21,7 @@ */ #include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it +#include <zlib.h> #include "Common.h" #include "DatabaseEnv.h" #include "Log.h" @@ -47,14 +48,15 @@ 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->packetProcessing == PROCESS_INPLACE) return true; //we do not process thread-unsafe packets - if (opHandle.packetProcessing == PROCESS_THREADUNSAFE) + if (opHandle->packetProcessing == PROCESS_THREADUNSAFE) return false; Player* player = m_pSession->GetPlayer(); @@ -69,13 +71,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->packetProcessing == PROCESS_INPLACE) return true; //thread-unsafe packets should be processed in World::UpdateSessions() - if (opHandle.packetProcessing == PROCESS_THREADUNSAFE) + if (opHandle->packetProcessing == PROCESS_THREADUNSAFE) return true; //no player attached? -> our client! ^^ @@ -99,6 +102,7 @@ m_latency(0), m_TutorialsChanged(false), recruiterId(recruiter), isRecruiter(isARecruiter), timeLastWhoCommand(0) { _warden = NULL; + _filterAddonMessages = false; if (sock) { @@ -109,6 +113,19 @@ isRecruiter(isARecruiter), timeLastWhoCommand(0) } 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) + { + sLog->outError(LOG_FILTER_NETWORKIO, "Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res)); + return; + } } /// WorldSession destructor @@ -135,6 +152,15 @@ 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 + { + sLog->outError(LOG_FILTER_NETWORKIO, "Can't close packet compression stream (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res)); + return; + } + + delete _compressionStream; } /// Get the player name @@ -169,11 +195,32 @@ uint32 WorldSession::GetGuidLow() const } /// Send a packet to the client -void WorldSession::SendPacket(WorldPacket const* packet) +void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/) { if (!m_Socket) return; + if (packet->GetOpcode() == NULL_OPCODE) + { + sLog->outError(LOG_FILTER_OPCODES, "Prevented sending of NULL_OPCODE to %s", GetPlayerName(false).c_str()); + return; + } + else if (packet->GetOpcode() == UNKNOWN_OPCODE) + { + sLog->outError(LOG_FILTER_OPCODES, "Prevented sending of UNKNOWN_OPCODE to %s", GetPlayerName(false).c_str()); + return; + } + + if (!forced) + { + OpcodeHandler* handler = opcodeTable[packet->GetOpcode()]; + if (!handler || handler->status == STATUS_UNHANDLED) + { + sLog->outError(LOG_FILTER_OPCODES, "Prevented sending disabled opcode %s to %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str(), GetPlayerName(false).c_str()); + return; + } + } + #ifdef TRINITY_DEBUG // Code for network use statistic static uint64 sendPacketCount = 0; @@ -260,108 +307,100 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater)) { - if (packet->GetOpcode() >= NUM_MSG_TYPES) - { - sLog->outError(LOG_FILTER_OPCODES, "Received non-existed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() - , GetPlayerName(false).c_str()); - sScriptMgr->OnUnknownPacketReceive(m_Socket, WorldPacket(*packet)); - } - else + const OpcodeHandler* 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 sLog->outDebug(LOG_FILTER_NETWORKIO, "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, WorldPacket(*packet)); - (this->*opHandle.handler)(*packet); - if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) - 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, WorldPacket(*packet)); - (this->*opHandle.handler)(*packet); - if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) - 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, WorldPacket(*packet)); - (this->*opHandle.handler)(*packet); - if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) - 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, WorldPacket(*packet)); + (this->*opHandle->handler)(*packet); + if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) + 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, WorldPacket(*packet)); - (this->*opHandle.handler)(*packet); + (this->*opHandle->handler)(*packet); if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) 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, WorldPacket(*packet)); + (this->*opHandle->handler)(*packet); + if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) + 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, WorldPacket(*packet)); + (this->*opHandle->handler)(*packet); + if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + break; + case STATUS_NEVER: sLog->outError(LOG_FILTER_OPCODES, "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() , GetPlayerName(false).c_str()); - break; - case STATUS_UNHANDLED: - sLog->outDebug(LOG_FILTER_OPCODES, "Received not handled opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() + break; + case STATUS_UNHANDLED: + sLog->outError(LOG_FILTER_OPCODES, "Received not handled opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() , GetPlayerName(false).c_str()); - break; - } - } - catch(ByteBufferException &) - { - sLog->outError(LOG_FILTER_GENERAL, "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 &) + { + sLog->outError(LOG_FILTER_NETWORKIO, "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; @@ -585,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); } } @@ -603,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); } } @@ -643,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); } } @@ -728,8 +779,8 @@ void WorldSession::SetAccountData(AccountDataType type, time_t tm, std::string d void WorldSession::SendAccountDataTimes(uint32 mask) { - WorldPacket data(SMSG_ACCOUNT_DATA_TIMES, 4 + 1 + 4 + 8 * 4); // changed in WotLK - data << uint32(time(NULL)); // unix time of something + WorldPacket data(SMSG_ACCOUNT_DATA_TIMES, 4+1+4+NUM_ACCOUNT_DATA_TYPES*4); + data << uint32(time(NULL)); // Server time data << uint8(1); data << uint32(mask); // type mask for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i) @@ -777,156 +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->t_guid); - - data >> mi->t_pos.PositionXYZOStream(); - data >> mi->t_time; - data >> mi->t_seat; - - if (mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT)) - data >> mi->t_time2; - - if (mi->pos.m_positionX != mi->t_pos.m_positionX) - if (GetPlayer()->GetTransport()) - GetPlayer()->GetTransport()->UpdatePosition(mi); - } - - 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->j_zspeed; - data >> mi->j_sinAngle; - data >> mi->j_cosAngle; - data >> mi->j_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) \ - { \ - sLog->outDebug(LOG_FILTER_UNITS, "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); - - #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->t_guid); - - *data << mi->t_pos.PositionXYZOStream(); - *data << mi->t_time; - *data << mi->t_seat; - - if (mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT)) - *data << mi->t_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->j_zspeed; - *data << mi->j_sinAngle; - *data << mi->j_cosAngle; - *data << mi->j_xyspeed; - } - - if (mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION)) - *data << mi->splineElevation; -} - void WorldSession::ReadAddonsInfo(WorldPacket &data) { if (data.rpos() + 4 > data.size()) @@ -1070,6 +971,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 +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_UNREGISTER_ALL_ADDON_PREFIXES"); + + _registeredAddonPrefixes.clear(); +} + +void WorldSession::HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "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; diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 0aa14eb78a8..ac8e48a0c04 100755 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -30,6 +30,7 @@ #include "World.h" #include "WorldPacket.h" #include "Cryptography/BigNumber.h" +#include "Opcodes.h" class CalendarEvent; class CalendarInvite; @@ -76,6 +77,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("") {} @@ -145,12 +148,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 @@ -161,6 +167,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; @@ -235,11 +242,12 @@ 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 WriteMovementInfo(WorldPacket &data, MovementInfo* mi); - void SendPacket(WorldPacket const* packet); + void SendPacket(WorldPacket const* packet, bool forced = false); void SendNotification(const char *format, ...) ATTR_PRINTF(2, 3); void SendNotification(uint32 string_id, ...); void SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName); @@ -248,7 +256,7 @@ class WorldSession void SendSetPhaseShift(uint32 phaseShift); void SendQueryTimeResponse(); - void SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos = 0); + void SendAuthResponse(uint8 code, bool queued, uint32 queuePos = 0); void SendClientCacheVersion(uint32 version); AccountTypes GetSecurity() const { return _security; } @@ -344,9 +352,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 SpellID); @@ -388,19 +397,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 @@ -413,9 +418,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& recv_data); + void HandleCharFactionOrRaceChange(WorldPacket& recvData); + void HandleRandomizeCharNameOpcode(WorldPacket& recvData); + void HandleReorderCharacters(WorldPacket& recvData); + // played time void HandlePlayedTime(WorldPacket& recvPacket); @@ -424,6 +433,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); @@ -432,15 +442,15 @@ class WorldSession void HandleInspectHonorStatsOpcode(WorldPacket& recvPacket); void HandleMoveWaterWalkAck(WorldPacket& recvPacket); - void HandleFeatherFallAck(WorldPacket& recv_data); + void HandleFeatherFallAck(WorldPacket& recvData); - void HandleMoveHoverAck(WorldPacket& recv_data); + void HandleMoveHoverAck(WorldPacket& recvData); void HandleMountSpecialAnimOpcode(WorldPacket& recvdata); // character view - void HandleShowingHelmOpcode(WorldPacket& recv_data); - void HandleShowingCloakOpcode(WorldPacket& recv_data); + void HandleShowingHelmOpcode(WorldPacket& recvData); + void HandleShowingCloakOpcode(WorldPacket& recvData); // repair void HandleRepairItemOpcode(WorldPacket& recvPacket); @@ -449,7 +459,7 @@ class WorldSession void HandleMoveKnockBackAck(WorldPacket& recvPacket); void HandleMoveTeleportAck(WorldPacket& recvPacket); - void HandleForceSpeedChangeAck(WorldPacket& recv_data); + void HandleForceSpeedChangeAck(WorldPacket& recvData); void HandlePingOpcode(WorldPacket& recvPacket); void HandleAuthSessionOpcode(WorldPacket& recvPacket); @@ -489,15 +499,13 @@ 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); - void HandleSetFactionAtWar(WorldPacket& recv_data); - void HandleSetFactionCheat(WorldPacket& recv_data); - void HandleSetWatchedFactionOpcode(WorldPacket& recv_data); - void HandleSetFactionInactiveOpcode(WorldPacket& recv_data); + void HandleSetFactionAtWar(WorldPacket& recvData); + void HandleSetFactionCheat(WorldPacket& recvData); + void HandleSetWatchedFactionOpcode(WorldPacket& recvData); + void HandleSetFactionInactiveOpcode(WorldPacket& recvData); void HandleUpdateAccountData(WorldPacket& recvPacket); void HandleRequestAccountData(WorldPacket& recvPacket); @@ -519,69 +527,69 @@ class WorldSession void HandleMoveWorldportAckOpcode(); // for server-side calls void HandleMovementOpcodes(WorldPacket& recvPacket); - void HandleSetActiveMoverOpcode(WorldPacket& recv_data); - void HandleMoveNotActiveMover(WorldPacket& recv_data); - void HandleDismissControlledVehicle(WorldPacket& recv_data); - void HandleRequestVehicleExit(WorldPacket& recv_data); - void HandleChangeSeatsOnControlledVehicle(WorldPacket& recv_data); - void HandleMoveTimeSkippedOpcode(WorldPacket& recv_data); + void HandleSetActiveMoverOpcode(WorldPacket& recvData); + void HandleMoveNotActiveMover(WorldPacket& recvData); + void HandleDismissControlledVehicle(WorldPacket& recvData); + void HandleRequestVehicleExit(WorldPacket& recvData); + void HandleChangeSeatsOnControlledVehicle(WorldPacket& recvData); + void HandleMoveTimeSkippedOpcode(WorldPacket& recvData); - void HandleRequestRaidInfoOpcode(WorldPacket& recv_data); + void HandleRequestRaidInfoOpcode(WorldPacket& recvData); - void HandleBattlefieldStatusOpcode(WorldPacket& recv_data); - void HandleBattleMasterHelloOpcode(WorldPacket& recv_data); + void HandleBattlefieldStatusOpcode(WorldPacket& recvData); + void HandleBattleMasterHelloOpcode(WorldPacket& recvData); 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 HandleGroupDisbandOpcode(WorldPacket& recvPacket); - void HandleOptOutOfLootOpcode(WorldPacket& recv_data); + void HandleOptOutOfLootOpcode(WorldPacket& recvData); void HandleLootMethodOpcode(WorldPacket& recvPacket); - void HandleLootRoll(WorldPacket& recv_data); - void HandleRequestPartyMemberStatsOpcode(WorldPacket& recv_data); - void HandleRaidTargetUpdateOpcode(WorldPacket& recv_data); - void HandleRaidReadyCheckOpcode(WorldPacket& recv_data); - void HandleRaidReadyCheckFinishedOpcode(WorldPacket& recv_data); - void HandleGroupRaidConvertOpcode(WorldPacket& recv_data); - void HandleGroupChangeSubGroupOpcode(WorldPacket& recv_data); - void HandleGroupAssistantLeaderOpcode(WorldPacket& recv_data); - void HandlePartyAssignmentOpcode(WorldPacket& recv_data); - - void HandlePetitionBuyOpcode(WorldPacket& recv_data); - void HandlePetitionShowSignOpcode(WorldPacket& recv_data); - void HandlePetitionQueryOpcode(WorldPacket& recv_data); - void HandlePetitionRenameOpcode(WorldPacket& recv_data); - void HandlePetitionSignOpcode(WorldPacket& recv_data); - void HandlePetitionDeclineOpcode(WorldPacket& recv_data); - void HandleOfferPetitionOpcode(WorldPacket& recv_data); - void HandleTurnInPetitionOpcode(WorldPacket& recv_data); + void HandleLootRoll(WorldPacket& recvData); + void HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData); + void HandleRaidTargetUpdateOpcode(WorldPacket& recvData); + void HandleRaidReadyCheckOpcode(WorldPacket& recvData); + void HandleRaidReadyCheckFinishedOpcode(WorldPacket& recvData); + void HandleGroupRaidConvertOpcode(WorldPacket& recvData); + void HandleGroupChangeSubGroupOpcode(WorldPacket& recvData); + void HandleGroupSwapSubGroupOpcode(WorldPacket& recvData); + void HandleGroupAssistantLeaderOpcode(WorldPacket& recvData); + void HandlePartyAssignmentOpcode(WorldPacket& recvData); + + void HandlePetitionBuyOpcode(WorldPacket& recvData); + void HandlePetitionShowSignOpcode(WorldPacket& recvData); + void HandlePetitionQueryOpcode(WorldPacket& recvData); + void HandlePetitionRenameOpcode(WorldPacket& recvData); + void HandlePetitionSignOpcode(WorldPacket& recvData); + void HandlePetitionDeclineOpcode(WorldPacket& recvData); + void HandleOfferPetitionOpcode(WorldPacket& recvData); + 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 HandleGuildPromoteOpcode(WorldPacket& recvPacket); void HandleGuildDemoteOpcode(WorldPacket& recvPacket); + void HandleGuildAssignRankOpcode(WorldPacket& recvPacket); void HandleGuildLeaveOpcode(WorldPacket& recvPacket); void HandleGuildDisbandOpcode(WorldPacket& recvPacket); void HandleGuildLeaderOpcode(WorldPacket& recvPacket); void HandleGuildMOTDOpcode(WorldPacket& recvPacket); - void HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket); - void HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket); - void HandleGuildRankOpcode(WorldPacket& recvPacket); + void HandleGuildSetNoteOpcode(WorldPacket& recvPacket); + void HandleGuildQueryRanksOpcode(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 HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket); void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket); @@ -626,32 +634,33 @@ class WorldSession void HandleUnacceptTradeOpcode(WorldPacket& recvPacket); void HandleAuctionHelloOpcode(WorldPacket& recvPacket); - void HandleAuctionListItems(WorldPacket& recv_data); - void HandleAuctionListBidderItems(WorldPacket& recv_data); - void HandleAuctionSellItem(WorldPacket& recv_data); - void HandleAuctionRemoveItem(WorldPacket& recv_data); - void HandleAuctionListOwnerItems(WorldPacket& recv_data); - void HandleAuctionPlaceBid(WorldPacket& recv_data); - void HandleAuctionListPendingSales(WorldPacket& recv_data); - - void HandleGetMailList(WorldPacket& recv_data); - void HandleSendMail(WorldPacket& recv_data); - void HandleMailTakeMoney(WorldPacket& recv_data); - void HandleMailTakeItem(WorldPacket& recv_data); - void HandleMailMarkAsRead(WorldPacket& recv_data); - void HandleMailReturnToSender(WorldPacket& recv_data); - void HandleMailDelete(WorldPacket& recv_data); - void HandleItemTextQuery(WorldPacket& recv_data); - void HandleMailCreateTextItem(WorldPacket& recv_data); - void HandleQueryNextMailTime(WorldPacket& recv_data); - void HandleCancelChanneling(WorldPacket& recv_data); + void HandleAuctionListItems(WorldPacket& recvData); + void HandleAuctionListBidderItems(WorldPacket& recvData); + void HandleAuctionSellItem(WorldPacket& recvData); + void HandleAuctionRemoveItem(WorldPacket& recvData); + void HandleAuctionListOwnerItems(WorldPacket& recvData); + void HandleAuctionPlaceBid(WorldPacket& recvData); + void HandleAuctionListPendingSales(WorldPacket& recvData); + + void HandleGetMailList(WorldPacket& recvData); + void HandleSendMail(WorldPacket& recvData); + void HandleMailTakeMoney(WorldPacket& recvData); + void HandleMailTakeItem(WorldPacket& recvData); + void HandleMailMarkAsRead(WorldPacket& recvData); + void HandleMailReturnToSender(WorldPacket& recvData); + void HandleMailDelete(WorldPacket& recvData); + void HandleItemTextQuery(WorldPacket& recvData); + void HandleMailCreateTextItem(WorldPacket& recvData); + void HandleQueryNextMailTime(WorldPacket& recvData); + void HandleCancelChanneling(WorldPacket& recvData); 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 SendItemDb2Reply(uint32 entry); + void SendItemSparseDb2Reply(uint32 entry); void HandleSellItemOpcode(WorldPacket& recvPacket); void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket); void HandleBuyItemOpcode(WorldPacket& recvPacket); @@ -690,17 +699,18 @@ class WorldSession void HandleQuestgiverChooseRewardOpcode(WorldPacket& recvPacket); void HandleQuestgiverRequestRewardOpcode(WorldPacket& recvPacket); void HandleQuestQueryOpcode(WorldPacket& recvPacket); - void HandleQuestgiverCancel(WorldPacket& recv_data); - void HandleQuestLogSwapQuest(WorldPacket& recv_data); - void HandleQuestLogRemoveQuest(WorldPacket& recv_data); - void HandleQuestConfirmAccept(WorldPacket& recv_data); - void HandleQuestgiverCompleteQuest(WorldPacket& recv_data); + void HandleQuestgiverCancel(WorldPacket& recvData); + void HandleQuestLogSwapQuest(WorldPacket& recvData); + void HandleQuestLogRemoveQuest(WorldPacket& recvData); + void HandleQuestConfirmAccept(WorldPacket& recvData); + void HandleQuestgiverCompleteQuest(WorldPacket& recvData); void HandleQuestgiverQuestAutoLaunch(WorldPacket& recvPacket); void HandlePushQuestToParty(WorldPacket& recvPacket); void HandleQuestPushResult(WorldPacket& recvPacket); bool processChatmessageFurtherAfterSecurityChecks(std::string&, uint32); void HandleMessagechatOpcode(WorldPacket& recvPacket); + void HandleAddonMessagechatOpcode(WorldPacket& recvPacket); void SendPlayerNotFoundNotice(std::string name); void SendPlayerAmbiguousNotice(std::string name); void SendWrongFactionNotice(); @@ -708,11 +718,14 @@ 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); void HandleResurrectResponseOpcode(WorldPacket& recvPacket); - void HandleSummonResponseOpcode(WorldPacket& recv_data); + void HandleSummonResponseOpcode(WorldPacket& recvData); void HandleJoinChannel(WorldPacket& recvPacket); void HandleLeaveChannel(WorldPacket& recvPacket); @@ -738,61 +751,60 @@ class WorldSession void HandleCompleteCinematic(WorldPacket& recvPacket); void HandleNextCinematicCamera(WorldPacket& recvPacket); - void HandlePageQuerySkippedOpcode(WorldPacket& recvPacket); void HandlePageTextQueryOpcode(WorldPacket& recvPacket); - void HandleTutorialFlag (WorldPacket& recv_data); - void HandleTutorialClear(WorldPacket& recv_data); - void HandleTutorialReset(WorldPacket& recv_data); + void HandleTutorialFlag (WorldPacket& recvData); + void HandleTutorialClear(WorldPacket& recvData); + void HandleTutorialReset(WorldPacket& recvData); //Pet - void HandlePetAction(WorldPacket& recv_data); - void HandlePetStopAttack(WorldPacket& recv_data); + void HandlePetAction(WorldPacket& recvData); + void HandlePetStopAttack(WorldPacket& recvData); void HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid, uint16 flag, uint64 guid2); - void HandlePetNameQuery(WorldPacket& recv_data); - void HandlePetSetAction(WorldPacket& recv_data); - void HandlePetAbandon(WorldPacket& recv_data); - void HandlePetRename(WorldPacket& recv_data); + void HandlePetNameQuery(WorldPacket& recvData); + void HandlePetSetAction(WorldPacket& recvData); + void HandlePetAbandon(WorldPacket& recvData); + void HandlePetRename(WorldPacket& recvData); void HandlePetCancelAuraOpcode(WorldPacket& recvPacket); void HandlePetSpellAutocastOpcode(WorldPacket& recvPacket); void HandlePetCastSpellOpcode(WorldPacket& recvPacket); void HandlePetLearnTalent(WorldPacket& recvPacket); void HandleLearnPreviewTalentsPet(WorldPacket& recvPacket); - void HandleSetActionBarToggles(WorldPacket& recv_data); + void HandleSetActionBarToggles(WorldPacket& recvData); - void HandleCharRenameOpcode(WorldPacket& recv_data); + void HandleCharRenameOpcode(WorldPacket& recvData); void HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, std::string newName); - void HandleSetPlayerDeclinedNames(WorldPacket& recv_data); + void HandleSetPlayerDeclinedNames(WorldPacket& recvData); - void HandleTotemDestroyed(WorldPacket& recv_data); - void HandleDismissCritter(WorldPacket& recv_data); + void HandleTotemDestroyed(WorldPacket& recvData); + void HandleDismissCritter(WorldPacket& recvData); //Battleground - void HandleBattlemasterHelloOpcode(WorldPacket& recv_data); - void HandleBattlemasterJoinOpcode(WorldPacket& recv_data); - void HandleBattlegroundPlayerPositionsOpcode(WorldPacket& recv_data); - void HandlePVPLogDataOpcode(WorldPacket& recv_data); - void HandleBattleFieldPortOpcode(WorldPacket& recv_data); - void HandleBattlefieldListOpcode(WorldPacket& recv_data); - void HandleLeaveBattlefieldOpcode(WorldPacket& recv_data); - void HandleBattlemasterJoinArena(WorldPacket& recv_data); - void HandleReportPvPAFK(WorldPacket& recv_data); - - void HandleWardenDataOpcode(WorldPacket& recv_data); - void HandleWorldTeleportOpcode(WorldPacket& recv_data); - void HandleMinimapPingOpcode(WorldPacket& recv_data); - void HandleRandomRollOpcode(WorldPacket& recv_data); - void HandleFarSightOpcode(WorldPacket& recv_data); - void HandleSetDungeonDifficultyOpcode(WorldPacket& recv_data); - void HandleSetRaidDifficultyOpcode(WorldPacket& recv_data); - void HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data); - void HandleSetTitleOpcode(WorldPacket& recv_data); - void HandleRealmSplitOpcode(WorldPacket& recv_data); - void HandleTimeSyncResp(WorldPacket& recv_data); - void HandleWhoisOpcode(WorldPacket& recv_data); - void HandleResetInstancesOpcode(WorldPacket& recv_data); - void HandleHearthAndResurrect(WorldPacket& recv_data); + void HandleBattlemasterHelloOpcode(WorldPacket& recvData); + void HandleBattlemasterJoinOpcode(WorldPacket& recvData); + void HandleBattlegroundPlayerPositionsOpcode(WorldPacket& recvData); + void HandlePVPLogDataOpcode(WorldPacket& recvData); + void HandleBattleFieldPortOpcode(WorldPacket& recvData); + void HandleBattlefieldListOpcode(WorldPacket& recvData); + void HandleLeaveBattlefieldOpcode(WorldPacket& recvData); + void HandleBattlemasterJoinArena(WorldPacket& recvData); + void HandleReportPvPAFK(WorldPacket& recvData); + + void HandleWardenDataOpcode(WorldPacket& recvData); + void HandleWorldTeleportOpcode(WorldPacket& recvData); + void HandleMinimapPingOpcode(WorldPacket& recvData); + void HandleRandomRollOpcode(WorldPacket& recvData); + void HandleFarSightOpcode(WorldPacket& recvData); + void HandleSetDungeonDifficultyOpcode(WorldPacket& recvData); + void HandleSetRaidDifficultyOpcode(WorldPacket& recvData); + void HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData); + void HandleSetTitleOpcode(WorldPacket& recvData); + void HandleRealmSplitOpcode(WorldPacket& recvData); + void HandleTimeSyncResp(WorldPacket& recvData); + void HandleWhoisOpcode(WorldPacket& recvData); + void HandleResetInstancesOpcode(WorldPacket& recvData); + void HandleHearthAndResurrect(WorldPacket& recvData); void HandleInstanceLockResponse(WorldPacket& recvPacket); // Battlefield @@ -806,17 +818,17 @@ class WorldSession void HandleBfExitRequest(WorldPacket &recv_data); // Looking for Dungeon/Raid - void HandleLfgSetCommentOpcode(WorldPacket& recv_data); - void HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& recv_data); - void HandleLfgPartyLockInfoRequestOpcode(WorldPacket& recv_data); - void HandleLfgJoinOpcode(WorldPacket& recv_data); - void HandleLfgLeaveOpcode(WorldPacket& recv_data); - void HandleLfgSetRolesOpcode(WorldPacket& recv_data); - void HandleLfgProposalResultOpcode(WorldPacket& recv_data); - void HandleLfgSetBootVoteOpcode(WorldPacket& recv_data); - void HandleLfgTeleportOpcode(WorldPacket& recv_data); - void HandleLfrSearchOpcode(WorldPacket& recv_data); - void HandleLfrLeaveOpcode(WorldPacket& recv_data); + void HandleLfgSetCommentOpcode(WorldPacket& recvData); + void HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& recvData); + void HandleLfgPartyLockInfoRequestOpcode(WorldPacket& recvData); + void HandleLfgJoinOpcode(WorldPacket& recvData); + void HandleLfgLeaveOpcode(WorldPacket& recvData); + void HandleLfgSetRolesOpcode(WorldPacket& recvData); + void HandleLfgProposalResultOpcode(WorldPacket& recvData); + void HandleLfgSetBootVoteOpcode(WorldPacket& recvData); + void HandleLfgTeleportOpcode(WorldPacket& recvData); + void HandleLfrSearchOpcode(WorldPacket& recvData); + void HandleLfrLeaveOpcode(WorldPacket& recvData); void SendLfgUpdatePlayer(const LfgUpdateData& updateData); void SendLfgUpdateParty(const LfgUpdateData& updateData); @@ -833,55 +845,56 @@ class WorldSession void SendLfgTeleportError(uint8 err); // Arena Team - void HandleInspectArenaTeamsOpcode(WorldPacket& recv_data); - void HandleArenaTeamQueryOpcode(WorldPacket& recv_data); - void HandleArenaTeamRosterOpcode(WorldPacket& recv_data); - void HandleArenaTeamInviteOpcode(WorldPacket& recv_data); - void HandleArenaTeamAcceptOpcode(WorldPacket& recv_data); - void HandleArenaTeamDeclineOpcode(WorldPacket& recv_data); - void HandleArenaTeamLeaveOpcode(WorldPacket& recv_data); - void HandleArenaTeamRemoveOpcode(WorldPacket& recv_data); - void HandleArenaTeamDisbandOpcode(WorldPacket& recv_data); - void HandleArenaTeamLeaderOpcode(WorldPacket& recv_data); - - void HandleAreaSpiritHealerQueryOpcode(WorldPacket& recv_data); - void HandleAreaSpiritHealerQueueOpcode(WorldPacket& recv_data); - void HandleCancelMountAuraOpcode(WorldPacket& recv_data); - void HandleSelfResOpcode(WorldPacket& recv_data); - void HandleComplainOpcode(WorldPacket& recv_data); - void HandleRequestPetInfoOpcode(WorldPacket& recv_data); + void HandleInspectArenaTeamsOpcode(WorldPacket& recvData); + void HandleArenaTeamQueryOpcode(WorldPacket& recvData); + void HandleArenaTeamRosterOpcode(WorldPacket& recvData); + void HandleArenaTeamInviteOpcode(WorldPacket& recvData); + void HandleArenaTeamAcceptOpcode(WorldPacket& recvData); + void HandleArenaTeamDeclineOpcode(WorldPacket& recvData); + void HandleArenaTeamLeaveOpcode(WorldPacket& recvData); + void HandleArenaTeamRemoveOpcode(WorldPacket& recvData); + void HandleArenaTeamDisbandOpcode(WorldPacket& recvData); + void HandleArenaTeamLeaderOpcode(WorldPacket& recvData); + + void HandleAreaSpiritHealerQueryOpcode(WorldPacket& recvData); + void HandleAreaSpiritHealerQueueOpcode(WorldPacket& recvData); + void HandleCancelMountAuraOpcode(WorldPacket& recvData); + void HandleSelfResOpcode(WorldPacket& recvData); + void HandleComplainOpcode(WorldPacket& recvData); + void HandleRequestPetInfoOpcode(WorldPacket& recvData); // Socket gem - void HandleSocketOpcode(WorldPacket& recv_data); + void HandleSocketOpcode(WorldPacket& recvData); - void HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data); + void HandleCancelTempEnchantmentOpcode(WorldPacket& recvData); - void HandleItemRefundInfoRequest(WorldPacket& recv_data); - void HandleItemRefund(WorldPacket& recv_data); + void HandleItemRefundInfoRequest(WorldPacket& recvData); + void HandleItemRefund(WorldPacket& recvData); - void HandleChannelVoiceOnOpcode(WorldPacket& recv_data); - void HandleVoiceSessionEnableOpcode(WorldPacket& recv_data); - void HandleSetActiveVoiceChannel(WorldPacket& recv_data); - void HandleSetTaxiBenchmarkOpcode(WorldPacket& recv_data); + void HandleChannelVoiceOnOpcode(WorldPacket& recvData); + void HandleVoiceSessionEnableOpcode(WorldPacket& recvData); + void HandleSetActiveVoiceChannel(WorldPacket& recvData); + void HandleSetTaxiBenchmarkOpcode(WorldPacket& recvData); // Guild Bank - void HandleGuildPermissions(WorldPacket& recv_data); - void HandleGuildBankMoneyWithdrawn(WorldPacket& recv_data); - void HandleGuildBankerActivate(WorldPacket& recv_data); - void HandleGuildBankQueryTab(WorldPacket& recv_data); - void HandleGuildBankLogQuery(WorldPacket& recv_data); - void HandleGuildBankDepositMoney(WorldPacket& recv_data); - void HandleGuildBankWithdrawMoney(WorldPacket& recv_data); - void HandleGuildBankSwapItems(WorldPacket& recv_data); - - void HandleGuildBankUpdateTab(WorldPacket& recv_data); - void HandleGuildBankBuyTab(WorldPacket& recv_data); - void HandleQueryGuildBankTabText(WorldPacket& recv_data); - void HandleSetGuildBankTabText(WorldPacket& recv_data); + void HandleGuildPermissions(WorldPacket& recvData); + void HandleGuildBankMoneyWithdrawn(WorldPacket& recvData); + void HandleGuildBankerActivate(WorldPacket& recvData); + void HandleGuildBankQueryTab(WorldPacket& recvData); + void HandleGuildBankLogQuery(WorldPacket& recvData); + void HandleGuildBankDepositMoney(WorldPacket& recvData); + void HandleGuildBankWithdrawMoney(WorldPacket& recvData); + void HandleGuildBankSwapItems(WorldPacket& recvData); + + void HandleGuildBankUpdateTab(WorldPacket& recvData); + void HandleGuildBankBuyTab(WorldPacket& recvData); + void HandleQueryGuildBankTabText(WorldPacket& recvData); + void HandleSetGuildBankTabText(WorldPacket& recvData); + void HandleGuildQueryXPOpcode(WorldPacket& recvData); // Refer-a-Friend - void HandleGrantLevel(WorldPacket& recv_data); - void HandleAcceptGrantLevel(WorldPacket& recv_data); + void HandleGrantLevel(WorldPacket& recvData); + void HandleAcceptGrantLevel(WorldPacket& recvData); // Calendar void HandleCalendarGetCalendar(WorldPacket& recvData); @@ -915,23 +928,43 @@ class WorldSession void SendCalendarRaidLockoutUpdated(InstanceSave const* save); void SendCalendarCommandResult(CalendarError err, char const* param = NULL); - void HandleSpellClick(WorldPacket& recv_data); - void HandleMirrorImageDataRequest(WorldPacket& recv_data); - void HandleAlterAppearance(WorldPacket& recv_data); - void HandleRemoveGlyph(WorldPacket& recv_data); - void HandleCharCustomize(WorldPacket& recv_data); - void HandleQueryInspectAchievements(WorldPacket& recv_data); - void HandleEquipmentSetSave(WorldPacket& recv_data); - void HandleEquipmentSetDelete(WorldPacket& recv_data); - void HandleEquipmentSetUse(WorldPacket& recv_data); - void HandleWorldStateUITimerUpdate(WorldPacket& recv_data); - void HandleReadyForAccountDataTimes(WorldPacket& recv_data); - void HandleQueryQuestsCompleted(WorldPacket& recv_data); - void HandleQuestPOIQuery(WorldPacket& recv_data); + // 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); + void HandleWorldStateUITimerUpdate(WorldPacket& recvData); + void HandleReadyForAccountDataTimes(WorldPacket& recvData); + void HandleQueryQuestsCompleted(WorldPacket& recvData); + void HandleQuestPOIQuery(WorldPacket& recvData); 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); + int32 HandleEnableNagleAlgorithm(); private: void InitializeQueryCallbackParameters(); @@ -993,10 +1026,13 @@ 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; ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue; time_t timeLastWhoCommand; + z_stream_s* _compressionStream; }; #endif /// @} diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 92455f8edfe..246b1424f23 100755..100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -159,24 +159,35 @@ int WorldSocket::SendPacket(WorldPacket const& pct) if (closing_) return -1; - // Dump outgoing packet. + // Dump outgoing packet if (sPacketLog->CanLogPacket()) sPacketLog->LogPacket(pct, SERVER_TO_CLIENT); - // Create a copy of the original packet; this is to avoid issues if a hook modifies it. - sScriptMgr->OnPacketSend(this, WorldPacket(pct)); + WorldPacket const* pkt = &pct; - ServerPktHeader header(pct.size()+2, pct.GetOpcode()); + // Empty buffer used in case packet should be compressed + WorldPacket buff; + if (m_Session && pkt->size() > 0x400) + { + buff.Compress(m_Session->GetCompressionStream(), pkt); + pkt = &buff; + } + + sLog->outInfo(LOG_FILTER_OPCODES, "S->C: %s", GetOpcodeNameForLogging(pkt->GetOpcode()).c_str()); + + sScriptMgr->OnPacketSend(this, *pkt); + + ServerPktHeader header(pkt->size()+2, pkt->GetOpcode()); m_Crypt.EncryptSend ((uint8*)header.header, header.getHeaderLength()); - if (m_OutBuffer->space() >= pct.size() + header.getHeaderLength() && msg_queue()->is_empty()) + if (m_OutBuffer->space() >= pkt->size() + header.getHeaderLength() && msg_queue()->is_empty()) { // Put the packet on the buffer. if (m_OutBuffer->copy((char*) header.header, header.getHeaderLength()) == -1) ACE_ASSERT (false); - if (!pct.empty()) - if (m_OutBuffer->copy((char*) pct.contents(), pct.size()) == -1) + if (!pkt->empty()) + if (m_OutBuffer->copy((char*) pkt->contents(), pkt->size()) == -1) ACE_ASSERT (false); } else @@ -184,12 +195,12 @@ int WorldSocket::SendPacket(WorldPacket const& pct) // Enqueue the packet. ACE_Message_Block* mb; - ACE_NEW_RETURN(mb, ACE_Message_Block(pct.size() + header.getHeaderLength()), -1); + ACE_NEW_RETURN(mb, ACE_Message_Block(pkt->size() + header.getHeaderLength()), -1); mb->copy((char*) header.header, header.getHeaderLength()); - if (!pct.empty()) - mb->copy((const char*)pct.contents(), pct.size()); + if (!pkt->empty()) + mb->copy((const char*)pkt->contents(), pkt->size()); if (msg_queue()->enqueue_tail(mb, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1) { @@ -242,18 +253,10 @@ int WorldSocket::open (void *a) m_Address = remote_addr.get_host_addr(); - // Send startup packet. - WorldPacket packet (SMSG_AUTH_CHALLENGE, 24); - packet << uint32(1); // 1...31 - packet << m_Seed; - - BigNumber seed1; - seed1.SetRand(16 * 8); - packet.append(seed1.AsByteArray(16), 16); // new encryption seeds - - BigNumber seed2; - seed2.SetRand(16 * 8); - packet.append(seed2.AsByteArray(16), 16); // new encryption seeds + // not an opcode. this packet sends raw string WORLD OF WARCRAFT CONNECTION - SERVER TO CLIENT" + // because of our implementation, bytes "WO" become the opcode + WorldPacket packet(MSG_VERIFY_CONNECTIVITY); + packet << "RLD OF WARCRAFT CONNECTION - SERVER TO CLIENT"; if (SendPacket(packet) == -1) return -1; @@ -458,7 +461,7 @@ int WorldSocket::Update (void) int ret; do - ret = handle_output (get_handle()); + ret = handle_output(get_handle()); while (ret > 0); return ret; @@ -466,18 +469,18 @@ int WorldSocket::Update (void) int WorldSocket::handle_input_header (void) { - ACE_ASSERT (m_RecvWPct == NULL); + ACE_ASSERT(m_RecvWPct == NULL); - ACE_ASSERT (m_Header.length() == sizeof(ClientPktHeader)); + ACE_ASSERT(m_Header.length() == sizeof(ClientPktHeader)); - m_Crypt.DecryptRecv ((uint8*) m_Header.rd_ptr(), sizeof(ClientPktHeader)); + m_Crypt.DecryptRecv ((uint8*)m_Header.rd_ptr(), sizeof(ClientPktHeader)); - ClientPktHeader& header = *((ClientPktHeader*) m_Header.rd_ptr()); + ClientPktHeader& header = *((ClientPktHeader*)m_Header.rd_ptr()); EndianConvertReverse(header.size); EndianConvert(header.cmd); - if ((header.size < 4) || (header.size > 10240) || (header.cmd > 10240)) + if ((header.size < 4) || (header.size > 10240) || (header.cmd > 0xFFFF && (header.cmd >> 16) != 0x4C52)) // LR (from MSG_VERIFY_CONNECTIVITY) { Player* _player = m_Session ? m_Session->GetPlayer() : NULL; sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::handle_input_header(): client (account: %u, char [GUID: %u, name: %s]) sent malformed packet (size: %d, cmd: %d)", @@ -492,11 +495,11 @@ int WorldSocket::handle_input_header (void) header.size -= 4; - ACE_NEW_RETURN (m_RecvWPct, WorldPacket ((uint16) header.cmd, header.size), -1); + ACE_NEW_RETURN(m_RecvWPct, WorldPacket (PacketFilter::DropHighBytes(Opcodes(header.cmd)), header.size), -1); if (header.size > 0) { - m_RecvWPct->resize (header.size); + m_RecvWPct->resize(header.size); m_RecvPct.base ((char*) m_RecvWPct->contents(), m_RecvWPct->size()); } else @@ -663,9 +666,9 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct) ACE_ASSERT (new_pct); // manage memory ;) - ACE_Auto_Ptr<WorldPacket> aptr (new_pct); + ACE_Auto_Ptr<WorldPacket> aptr(new_pct); - const ACE_UINT16 opcode = new_pct->GetOpcode(); + Opcodes opcode = PacketFilter::DropHighBytes(new_pct->GetOpcode()); if (closing_) return -1; @@ -674,12 +677,15 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct) if (sPacketLog->CanLogPacket()) sPacketLog->LogPacket(*new_pct, CLIENT_TO_SERVER); + std::string opcodeName = GetOpcodeNameForLogging(opcode); + sLog->outInfo(LOG_FILTER_OPCODES, "C->S: %s", opcodeName.c_str()); + try { switch (opcode) { case CMSG_PING: - return HandlePing (*new_pct); + return HandlePing(*new_pct); case CMSG_AUTH_SESSION: if (m_Session) { @@ -688,28 +694,57 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct) } sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct)); - return HandleAuthSession (*new_pct); + return HandleAuthSession(*new_pct); case CMSG_KEEP_ALIVE: sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", GetOpcodeNameForLogging(opcode).c_str()); sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct)); return 0; + case CMSG_LOG_DISCONNECT: + new_pct->rfinish(); // contains uint32 disconnectReason; + sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", opcodeName.c_str()); + sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct)); + return 0; + // 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: + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", opcodeName.c_str()); + sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct)); + std::string str; + *new_pct >> str; + if (str != "D OF WARCRAFT CONNECTION - CLIENT TO SERVER") + return -1; + return HandleSendAuthSession(); + } + case CMSG_ENABLE_NAGLE: + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", opcodeName.c_str()); + sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct)); + return m_Session ? m_Session->HandleEnableNagleAlgorithm() : -1; + } default: { - ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); - + ACE_GUARD_RETURN(LockType, Guard, m_SessionLock, -1); if (!m_Session) { - sLog->outError(LOG_FILTER_NETWORKIO, "ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); + sLog->outError(LOG_FILTER_OPCODES, "ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); return -1; } + OpcodeHandler* handler = opcodeTable[opcode]; + if (!handler || handler->status == STATUS_UNHANDLED) + { + sLog->outError(LOG_FILTER_OPCODES, "No defined handler for opcode %s sent by %s", GetOpcodeNameForLogging(new_pct->GetOpcode()).c_str(), m_Session->GetPlayerName(false).c_str()); + return 0; + } + // Our Idle timer will reset on any non PING opcodes. // Catches people idling on the login screen and any lingering ingame connections. m_Session->ResetTimeOutTime(); // OK, give the packet to WorldSession aptr.release(); - // WARNINIG here we call it with locks held. + // WARNING here we call it with locks held. // Its possible to cause deadlock if QueuePacket calls back m_Session->QueuePacket(new_pct); return 0; @@ -718,8 +753,8 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct) } catch (ByteBufferException &) { - sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet (opcode: %u) from client %s, accountid=%i. Disconnected client.", - opcode, GetRemoteAddress().c_str(), m_Session ? int32(m_Session->GetAccountId()) : -1); + sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet %s from client %s, accountid=%i. Disconnected client.", + opcodeName.c_str(), GetRemoteAddress().c_str(), m_Session ? int32(m_Session->GetAccountId()) : -1); new_pct->hexlike(); return -1; } @@ -727,27 +762,78 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct) ACE_NOTREACHED (return 0); } +int WorldSocket::HandleSendAuthSession() +{ + WorldPacket packet(SMSG_AUTH_CHALLENGE, 37); + BigNumber seed1; + seed1.SetRand(16 * 8); + packet.append(seed1.AsByteArray(16), 16); // new encryption seeds + + BigNumber seed2; + seed2.SetRand(16 * 8); + packet.append(seed2.AsByteArray(16), 16); // new encryption seeds + + packet << m_Seed; + packet << uint8(1); + return SendPacket(packet); +} + int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) { - // NOTE: ATM the socket is singlethread, have this in mind ... uint8 digest[20]; uint32 clientSeed; - uint32 unk2, unk3, unk5, unk6, unk7; - uint64 unk4; - uint32 BuiltNumberClient; - uint32 id, security; - //uint8 expansion = 0; + uint16 clientBuild, security; + uint32 id; + uint32 addonSize; LocaleConstant locale; std::string account; SHA1Hash sha; - BigNumber v, s, g, N; - WorldPacket packet, SendAddonPacked; - BigNumber k; + 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; + addonsData.resize(addonSize); + recvPacket.read((uint8*)addonsData.contents(), addonSize); + + recvPacket.ReadBit(); + uint32 accountNameLength = recvPacket.ReadBits(12); + account = recvPacket.ReadString(accountNameLength); if (sWorld->IsClosed()) { - packet.Initialize(SMSG_AUTH_RESPONSE, 1); + WorldPacket packet(SMSG_AUTH_RESPONSE, 1); + packet.WriteBit(0); // has queue info + packet.WriteBit(0); // has account info packet << uint8(AUTH_REJECT); SendPacket(packet); @@ -755,23 +841,6 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) return -1; } - // Read the content of the packet - recvPacket >> BuiltNumberClient; // for now no use - recvPacket >> unk2; - recvPacket >> account; - recvPacket >> unk3; - recvPacket >> clientSeed; - recvPacket >> unk5 >> unk6 >> unk7; - recvPacket >> unk4; - recvPacket.read(digest, 20); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, unk3 %u, clientseed %u", - BuiltNumberClient, - unk2, - account.c_str(), - unk3, - clientSeed); - // Get the account information from the realmd database PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME); @@ -782,8 +851,10 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) // Stop if the account is not found if (!result) { - packet.Initialize (SMSG_AUTH_RESPONSE, 1); - packet << uint8 (AUTH_UNKNOWN_ACCOUNT); + WorldPacket packet(SMSG_AUTH_RESPONSE, 1); + packet.WriteBit(0); // has queue info + packet.WriteBit(0); // has account info + packet << uint8(AUTH_UNKNOWN_ACCOUNT); SendPacket(packet); @@ -798,29 +869,19 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) if (expansion > world_expansion) expansion = world_expansion; - N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); - g.SetDword (7); - - v.SetHexStr(fields[4].GetCString()); - s.SetHexStr (fields[5].GetCString()); - - const char* sStr = s.AsHexStr(); //Must be freed by OPENSSL_free() - const char* vStr = v.AsHexStr(); //Must be freed by OPENSSL_free() - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: (s, v) check s: %s v: %s", - sStr, - vStr); - - OPENSSL_free ((void*) sStr); - OPENSSL_free ((void*) vStr); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s", + fields[5].GetCString(), + fields[4].GetCString()); ///- Re-check ip locking (same check as in realmd). if (fields[3].GetUInt8() == 1) // if ip is locked { if (strcmp (fields[2].GetCString(), GetRemoteAddress().c_str())) { - packet.Initialize (SMSG_AUTH_RESPONSE, 1); - packet << uint8 (AUTH_FAILED); + WorldPacket packet(SMSG_AUTH_RESPONSE, 1); + packet.WriteBit(0); // has queue info + packet.WriteBit(0); // has account info + packet << uint8(AUTH_FAILED); SendPacket(packet); sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); @@ -834,7 +895,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) security = SEC_ADMINISTRATOR; */ - k.SetHexStr (fields[1].GetCString()); + k.SetHexStr(fields[1].GetCString()); int64 mutetime = fields[7].GetInt64(); //! Negative mutetime indicates amount of seconds to be muted effective on next login - which is now. @@ -883,8 +944,10 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) if (banresult) // if account banned { - packet.Initialize (SMSG_AUTH_RESPONSE, 1); - packet << uint8 (AUTH_BANNED); + WorldPacket packet(SMSG_AUTH_RESPONSE, 1); + packet.WriteBit(0); // has queue info + packet.WriteBit(0); // has account info + packet << uint8(AUTH_BANNED); SendPacket(packet); sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); @@ -894,10 +957,12 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) // Check locked state for server AccountTypes allowedAccountType = sWorld->GetPlayerSecurityLimit(); sLog->outDebug(LOG_FILTER_NETWORKIO, "Allowed Level: %u Player Level %u", allowedAccountType, AccountTypes(security)); - if (AccountTypes(security) < allowedAccountType) + if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType) { - WorldPacket Packet (SMSG_AUTH_RESPONSE, 1); - Packet << uint8 (AUTH_UNAVAILABLE); + WorldPacket packet(SMSG_AUTH_RESPONSE, 1); + packet.WriteBit(0); // has queue info + packet.WriteBit(0); // has account info + packet << uint8(AUTH_UNAVAILABLE); SendPacket(packet); @@ -909,20 +974,21 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) uint32 t = 0; uint32 seed = m_Seed; - sha.UpdateData (account); - sha.UpdateData ((uint8 *) & t, 4); - sha.UpdateData ((uint8 *) & clientSeed, 4); - sha.UpdateData ((uint8 *) & seed, 4); - sha.UpdateBigNumbers (&k, NULL); + sha.UpdateData(account); + sha.UpdateData((uint8*)&t, 4); + sha.UpdateData((uint8*)&clientSeed, 4); + sha.UpdateData((uint8*)&seed, 4); + sha.UpdateBigNumbers(&k, NULL); sha.Finalize(); std::string address = GetRemoteAddress(); - if (memcmp (sha.GetDigest(), digest, 20)) + if (memcmp(sha.GetDigest(), digest, 20)) { - packet.Initialize (SMSG_AUTH_RESPONSE, 1); - packet << uint8 (AUTH_FAILED); - + WorldPacket packet(SMSG_AUTH_RESPONSE, 1); + packet.WriteBit(0); // has queue info + packet.WriteBit(0); // has account info + packet << uint8(AUTH_FAILED); SendPacket(packet); sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", id, account.c_str(), address.c_str()); @@ -930,8 +996,8 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) } sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", - account.c_str(), - address.c_str()); + account.c_str(), + address.c_str()); // Check if this user is by any chance a recruiter stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_RECRUITER); @@ -954,13 +1020,13 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) LoginDatabase.Execute(stmt); // NOTE ATM the socket is single-threaded, have this in mind ... - ACE_NEW_RETURN (m_Session, WorldSession (id, this, AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter), -1); + ACE_NEW_RETURN(m_Session, WorldSession(id, this, AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter), -1); m_Crypt.Init(&k); m_Session->LoadGlobalAccountData(); m_Session->LoadTutorialsData(); - m_Session->ReadAddonsInfo(recvPacket); + m_Session->ReadAddonsInfo(addonsData); // Initialize Warden system only if it is enabled by config if (sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED)) @@ -968,10 +1034,9 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) // Sleep this Network thread for uint32 sleepTime = sWorld->getIntConfig(CONFIG_SESSION_ADD_DELAY); - ACE_OS::sleep (ACE_Time_Value (0, sleepTime)); - - sWorld->AddSession (m_Session); + ACE_OS::sleep(ACE_Time_Value(0, sleepTime)); + sWorld->AddSession(m_Session); return 0; } @@ -981,8 +1046,8 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket) uint32 latency; // Get the ping packet content - recvPacket >> ping; recvPacket >> latency; + recvPacket >> ping; if (m_LastPingTime == ACE_Time_Value::zero) m_LastPingTime = ACE_OS::gettimeofday(); // for 1st ping @@ -1032,7 +1097,7 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket) } } - WorldPacket packet (SMSG_PONG, 4); + WorldPacket packet(SMSG_PONG, 4); packet << ping; return SendPacket(packet); } diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index b8080b128f2..3a256c07095 100755 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -161,6 +161,9 @@ class WorldSocket : public WorldHandler /// Called by ProcessIncoming() on CMSG_PING. int HandlePing (WorldPacket& recvPacket); + /// Called by CMSG_VERIFY_CONNECTIVITY_RESPONSE + int HandleSendAuthSession(); + private: /// Time in which the last ping was received ACE_Time_Value m_LastPingTime; diff --git a/src/server/game/Skills/SkillDiscovery.cpp b/src/server/game/Skills/SkillDiscovery.cpp index 3eac3d34fd2..55dc00c8524 100755 --- a/src/server/game/Skills/SkillDiscovery.cpp +++ b/src/server/game/Skills/SkillDiscovery.cpp @@ -55,7 +55,7 @@ void LoadSkillDiscoveryTable() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 skill discovery definitions. DB table `skill_discovery_template` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 skill discovery definitions. DB table `skill_discovery_template` is empty."); return; } diff --git a/src/server/game/Skills/SkillExtraItems.cpp b/src/server/game/Skills/SkillExtraItems.cpp index 9e2648dc943..0c094479262 100755 --- a/src/server/game/Skills/SkillExtraItems.cpp +++ b/src/server/game/Skills/SkillExtraItems.cpp @@ -60,7 +60,7 @@ void LoadSkillExtraItemTable() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 spell specialization definitions. DB table `skill_extra_item_template` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 spell specialization definitions. DB table `skill_extra_item_template` is empty."); return; } diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index ddb230d6773..1482136f52e 100755 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -59,324 +59,378 @@ enum DAMAGE_ABSORB_TYPE enum AuraType { - SPELL_AURA_NONE = 0, - SPELL_AURA_BIND_SIGHT = 1, - SPELL_AURA_MOD_POSSESS = 2, - SPELL_AURA_PERIODIC_DAMAGE = 3, - SPELL_AURA_DUMMY = 4, - SPELL_AURA_MOD_CONFUSE = 5, - SPELL_AURA_MOD_CHARM = 6, - SPELL_AURA_MOD_FEAR = 7, - SPELL_AURA_PERIODIC_HEAL = 8, - SPELL_AURA_MOD_ATTACKSPEED = 9, - SPELL_AURA_MOD_THREAT = 10, - SPELL_AURA_MOD_TAUNT = 11, - SPELL_AURA_MOD_STUN = 12, - SPELL_AURA_MOD_DAMAGE_DONE = 13, - SPELL_AURA_MOD_DAMAGE_TAKEN = 14, - SPELL_AURA_DAMAGE_SHIELD = 15, - SPELL_AURA_MOD_STEALTH = 16, - SPELL_AURA_MOD_STEALTH_DETECT = 17, - SPELL_AURA_MOD_INVISIBILITY = 18, - SPELL_AURA_MOD_INVISIBILITY_DETECT = 19, - SPELL_AURA_OBS_MOD_HEALTH = 20, //20, 21 unofficial - SPELL_AURA_OBS_MOD_POWER = 21, - SPELL_AURA_MOD_RESISTANCE = 22, - SPELL_AURA_PERIODIC_TRIGGER_SPELL = 23, - SPELL_AURA_PERIODIC_ENERGIZE = 24, - SPELL_AURA_MOD_PACIFY = 25, - SPELL_AURA_MOD_ROOT = 26, - SPELL_AURA_MOD_SILENCE = 27, - SPELL_AURA_REFLECT_SPELLS = 28, - SPELL_AURA_MOD_STAT = 29, - SPELL_AURA_MOD_SKILL = 30, - SPELL_AURA_MOD_INCREASE_SPEED = 31, - SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED = 32, - SPELL_AURA_MOD_DECREASE_SPEED = 33, - SPELL_AURA_MOD_INCREASE_HEALTH = 34, - SPELL_AURA_MOD_INCREASE_ENERGY = 35, - SPELL_AURA_MOD_SHAPESHIFT = 36, - SPELL_AURA_EFFECT_IMMUNITY = 37, - SPELL_AURA_STATE_IMMUNITY = 38, - SPELL_AURA_SCHOOL_IMMUNITY = 39, - SPELL_AURA_DAMAGE_IMMUNITY = 40, - SPELL_AURA_DISPEL_IMMUNITY = 41, - SPELL_AURA_PROC_TRIGGER_SPELL = 42, - SPELL_AURA_PROC_TRIGGER_DAMAGE = 43, - SPELL_AURA_TRACK_CREATURES = 44, - SPELL_AURA_TRACK_RESOURCES = 45, - SPELL_AURA_46 = 46, // Ignore all Gear test spells - SPELL_AURA_MOD_PARRY_PERCENT = 47, - SPELL_AURA_48 = 48, // One periodic spell - SPELL_AURA_MOD_DODGE_PERCENT = 49, - SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT = 50, - SPELL_AURA_MOD_BLOCK_PERCENT = 51, - SPELL_AURA_MOD_WEAPON_CRIT_PERCENT = 52, - SPELL_AURA_PERIODIC_LEECH = 53, - SPELL_AURA_MOD_HIT_CHANCE = 54, - SPELL_AURA_MOD_SPELL_HIT_CHANCE = 55, - SPELL_AURA_TRANSFORM = 56, - SPELL_AURA_MOD_SPELL_CRIT_CHANCE = 57, - SPELL_AURA_MOD_INCREASE_SWIM_SPEED = 58, - SPELL_AURA_MOD_DAMAGE_DONE_CREATURE = 59, - SPELL_AURA_MOD_PACIFY_SILENCE = 60, - SPELL_AURA_MOD_SCALE = 61, - SPELL_AURA_PERIODIC_HEALTH_FUNNEL = 62, - SPELL_AURA_63 = 63, // old SPELL_AURA_PERIODIC_MANA_FUNNEL - SPELL_AURA_PERIODIC_MANA_LEECH = 64, - SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK = 65, - SPELL_AURA_FEIGN_DEATH = 66, - SPELL_AURA_MOD_DISARM = 67, - SPELL_AURA_MOD_STALKED = 68, - SPELL_AURA_SCHOOL_ABSORB = 69, - SPELL_AURA_EXTRA_ATTACKS = 70, - SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL = 71, - SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT = 72, - SPELL_AURA_MOD_POWER_COST_SCHOOL = 73, - SPELL_AURA_REFLECT_SPELLS_SCHOOL = 74, - SPELL_AURA_MOD_LANGUAGE = 75, - SPELL_AURA_FAR_SIGHT = 76, - SPELL_AURA_MECHANIC_IMMUNITY = 77, - SPELL_AURA_MOUNTED = 78, - SPELL_AURA_MOD_DAMAGE_PERCENT_DONE = 79, - SPELL_AURA_MOD_PERCENT_STAT = 80, - SPELL_AURA_SPLIT_DAMAGE_PCT = 81, - SPELL_AURA_WATER_BREATHING = 82, - SPELL_AURA_MOD_BASE_RESISTANCE = 83, - SPELL_AURA_MOD_REGEN = 84, - SPELL_AURA_MOD_POWER_REGEN = 85, - SPELL_AURA_CHANNEL_DEATH_ITEM = 86, - SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN = 87, - SPELL_AURA_MOD_HEALTH_REGEN_PERCENT = 88, - SPELL_AURA_PERIODIC_DAMAGE_PERCENT = 89, - SPELL_AURA_90 = 90, // old SPELL_AURA_MOD_RESIST_CHANCE - SPELL_AURA_MOD_DETECT_RANGE = 91, - SPELL_AURA_PREVENTS_FLEEING = 92, - SPELL_AURA_MOD_UNATTACKABLE = 93, - SPELL_AURA_INTERRUPT_REGEN = 94, - SPELL_AURA_GHOST = 95, - SPELL_AURA_SPELL_MAGNET = 96, - SPELL_AURA_MANA_SHIELD = 97, - SPELL_AURA_MOD_SKILL_TALENT = 98, - SPELL_AURA_MOD_ATTACK_POWER = 99, - SPELL_AURA_AURAS_VISIBLE = 100, - SPELL_AURA_MOD_RESISTANCE_PCT = 101, - SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS = 102, - SPELL_AURA_MOD_TOTAL_THREAT = 103, - SPELL_AURA_WATER_WALK = 104, - SPELL_AURA_FEATHER_FALL = 105, - SPELL_AURA_HOVER = 106, - SPELL_AURA_ADD_FLAT_MODIFIER = 107, - SPELL_AURA_ADD_PCT_MODIFIER = 108, - SPELL_AURA_ADD_TARGET_TRIGGER = 109, - SPELL_AURA_MOD_POWER_REGEN_PERCENT = 110, - SPELL_AURA_ADD_CASTER_HIT_TRIGGER = 111, - SPELL_AURA_OVERRIDE_CLASS_SCRIPTS = 112, - SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN = 113, - SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT = 114, - SPELL_AURA_MOD_HEALING = 115, - SPELL_AURA_MOD_REGEN_DURING_COMBAT = 116, - SPELL_AURA_MOD_MECHANIC_RESISTANCE = 117, - SPELL_AURA_MOD_HEALING_PCT = 118, - SPELL_AURA_119 = 119, // old SPELL_AURA_SHARE_PET_TRACKING - SPELL_AURA_UNTRACKABLE = 120, - SPELL_AURA_EMPATHY = 121, - SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT = 122, - SPELL_AURA_MOD_TARGET_RESISTANCE = 123, - SPELL_AURA_MOD_RANGED_ATTACK_POWER = 124, - SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN = 125, - SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT = 126, - SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS = 127, - SPELL_AURA_MOD_POSSESS_PET = 128, - SPELL_AURA_MOD_SPEED_ALWAYS = 129, - SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS = 130, - SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS = 131, - SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT = 132, - SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT = 133, - SPELL_AURA_MOD_MANA_REGEN_INTERRUPT = 134, - SPELL_AURA_MOD_HEALING_DONE = 135, - SPELL_AURA_MOD_HEALING_DONE_PERCENT = 136, - SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE = 137, - 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_MOD_BASE_RESISTANCE_PCT = 142, - SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143, - SPELL_AURA_SAFE_FALL = 144, - SPELL_AURA_MOD_PET_TALENT_POINTS = 145, - SPELL_AURA_ALLOW_TAME_PET_TYPE = 146, - SPELL_AURA_MECHANIC_IMMUNITY_MASK = 147, - SPELL_AURA_RETAIN_COMBO_POINTS = 148, - SPELL_AURA_REDUCE_PUSHBACK = 149, // Reduce Pushback - SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT = 150, - SPELL_AURA_TRACK_STEALTHED = 151, // Track Stealthed - SPELL_AURA_MOD_DETECTED_RANGE = 152, // Mod Detected Range - SPELL_AURA_SPLIT_DAMAGE_FLAT = 153, // Split Damage Flat - 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_MOD_HEALTH_REGEN_IN_COMBAT = 161, - SPELL_AURA_POWER_BURN = 162, - SPELL_AURA_MOD_CRIT_DAMAGE_BONUS = 163, - SPELL_AURA_164 = 164, - SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS = 165, - 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_DETECT_AMORE = 170, - SPELL_AURA_MOD_SPEED_NOT_STACK = 171, - SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK = 172, - SPELL_AURA_173 = 173, // old SPELL_AURA_ALLOW_CHAMPION_SPELLS - SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT = 174, // by defeult intelect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT - 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_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 - SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT = 182, - SPELL_AURA_MOD_CRITICAL_THREAT = 183, - SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE = 184, - SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE= 185, - SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE = 186, - SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE = 187, - SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE = 188, - SPELL_AURA_MOD_RATING = 189, - SPELL_AURA_MOD_FACTION_REPUTATION_GAIN = 190, - SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED = 191, - SPELL_AURA_MOD_MELEE_RANGED_HASTE = 192, - SPELL_AURA_MELEE_SLOW = 193, - SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL = 194, - SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL = 195, - SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath - SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197, - SPELL_AURA_198 = 198, // old SPELL_AURA_MOD_ALL_WEAPON_SKILLS - SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT = 199, - SPELL_AURA_MOD_XP_PCT = 200, - SPELL_AURA_FLY = 201, - SPELL_AURA_IGNORE_COMBAT_RESULT = 202, - SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE = 203, - SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE = 204, - SPELL_AURA_MOD_SCHOOL_CRIT_DMG_TAKEN = 205, - SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED = 206, - SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED = 207, - SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED = 208, - 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_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_HASTE_RANGED = 218, - SPELL_AURA_MOD_MANA_REGEN_FROM_STAT = 219, - SPELL_AURA_MOD_RATING_FROM_STAT = 220, - SPELL_AURA_MOD_DETAUNT = 221, - SPELL_AURA_222 = 222, - SPELL_AURA_RAID_PROC_FROM_CHARGE = 223, - SPELL_AURA_224 = 224, - SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE = 225, - SPELL_AURA_PERIODIC_DUMMY = 226, - 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_PROC_TRIGGER_SPELL_WITH_VALUE = 231, - SPELL_AURA_MECHANIC_DURATION_MOD = 232, - SPELL_AURA_CHANGE_MODEL_FOR_ALL_HUMANOIDS = 233, // client-side only - SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK = 234, - SPELL_AURA_MOD_DISPEL_RESIST = 235, - SPELL_AURA_CONTROL_VEHICLE = 236, - SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER = 237, - SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER = 238, - SPELL_AURA_MOD_SCALE_2 = 239, - SPELL_AURA_MOD_EXPERTISE = 240, - SPELL_AURA_FORCE_MOVE_FORWARD = 241, - SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING = 242, - SPELL_AURA_MOD_FACTION = 243, - SPELL_AURA_COMPREHEND_LANGUAGE = 244, - SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL = 245, - SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK = 246, - SPELL_AURA_CLONE_CASTER = 247, - SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248, - SPELL_AURA_CONVERT_RUNE = 249, - SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250, - SPELL_AURA_MOD_ENEMY_DODGE = 251, - SPELL_AURA_MOD_SPEED_SLOW_ALL = 252, - SPELL_AURA_MOD_BLOCK_CRIT_CHANCE = 253, - SPELL_AURA_MOD_DISARM_OFFHAND = 254, - SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT = 255, - SPELL_AURA_NO_REAGENT_USE = 256, - SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS = 257, - SPELL_AURA_258 = 258, - SPELL_AURA_MOD_HOT_PCT = 259, - SPELL_AURA_SCREEN_EFFECT = 260, - SPELL_AURA_PHASE = 261, - SPELL_AURA_ABILITY_IGNORE_AURASTATE = 262, - SPELL_AURA_ALLOW_ONLY_ABILITY = 263, - SPELL_AURA_264 = 264, - SPELL_AURA_265 = 265, - SPELL_AURA_266 = 266, - SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267, - SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268, - SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 269, - SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive - SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271, - SPELL_AURA_IGNORE_MELEE_RESET = 272, - SPELL_AURA_X_RAY = 273, - SPELL_AURA_ABILITY_CONSUME_NO_AMMO = 274, - 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_DISARM_RANGED = 278, - SPELL_AURA_INITIALIZE_IMAGES = 279, - SPELL_AURA_MOD_ARMOR_PENETRATION_PCT = 280, - SPELL_AURA_MOD_HONOR_GAIN_PCT = 281, - SPELL_AURA_MOD_BASE_HEALTH_PCT = 282, - SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells - SPELL_AURA_LINKED = 284, - SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR = 285, - SPELL_AURA_ABILITY_PERIODIC_CRIT = 286, - SPELL_AURA_DEFLECT_SPELLS = 287, - SPELL_AURA_IGNORE_HIT_DIRECTION = 288, - SPELL_AURA_289 = 289, - SPELL_AURA_MOD_CRIT_PCT = 290, - SPELL_AURA_MOD_XP_QUEST_PCT = 291, - SPELL_AURA_OPEN_STABLE = 292, - SPELL_AURA_OVERRIDE_SPELLS = 293, - SPELL_AURA_PREVENT_REGENERATE_POWER = 294, - SPELL_AURA_295 = 295, - SPELL_AURA_SET_VEHICLE_ID = 296, - SPELL_AURA_BLOCK_SPELL_FAMILY = 297, - SPELL_AURA_STRANGULATE = 298, - SPELL_AURA_299 = 299, - SPELL_AURA_SHARE_DAMAGE_PCT = 300, - SPELL_AURA_SCHOOL_HEAL_ABSORB = 301, - SPELL_AURA_302 = 302, - SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE = 303, - SPELL_AURA_MOD_FAKE_INEBRIATE = 304, - 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_CREATURE_AOE_DAMAGE_AVOIDANCE = 310, - SPELL_AURA_311 = 311, - SPELL_AURA_312 = 312, - SPELL_AURA_313 = 313, - SPELL_AURA_PREVENT_RESURRECTION = 314, - SPELL_AURA_UNDERWATER_WALKING = 315, - SPELL_AURA_PERIODIC_HASTE = 316, - TOTAL_AURAS = 317 + SPELL_AURA_NONE = 0, + SPELL_AURA_BIND_SIGHT = 1, + SPELL_AURA_MOD_POSSESS = 2, + SPELL_AURA_PERIODIC_DAMAGE = 3, + SPELL_AURA_DUMMY = 4, + SPELL_AURA_MOD_CONFUSE = 5, + SPELL_AURA_MOD_CHARM = 6, + SPELL_AURA_MOD_FEAR = 7, + SPELL_AURA_PERIODIC_HEAL = 8, + SPELL_AURA_MOD_ATTACKSPEED = 9, + SPELL_AURA_MOD_THREAT = 10, + SPELL_AURA_MOD_TAUNT = 11, + SPELL_AURA_MOD_STUN = 12, + SPELL_AURA_MOD_DAMAGE_DONE = 13, + SPELL_AURA_MOD_DAMAGE_TAKEN = 14, + SPELL_AURA_DAMAGE_SHIELD = 15, + SPELL_AURA_MOD_STEALTH = 16, + SPELL_AURA_MOD_STEALTH_DETECT = 17, + SPELL_AURA_MOD_INVISIBILITY = 18, + SPELL_AURA_MOD_INVISIBILITY_DETECT = 19, + SPELL_AURA_OBS_MOD_HEALTH = 20, // 20, 21 unofficial + SPELL_AURA_OBS_MOD_POWER = 21, + SPELL_AURA_MOD_RESISTANCE = 22, + SPELL_AURA_PERIODIC_TRIGGER_SPELL = 23, + SPELL_AURA_PERIODIC_ENERGIZE = 24, + SPELL_AURA_MOD_PACIFY = 25, + SPELL_AURA_MOD_ROOT = 26, + SPELL_AURA_MOD_SILENCE = 27, + SPELL_AURA_REFLECT_SPELLS = 28, + SPELL_AURA_MOD_STAT = 29, + SPELL_AURA_MOD_SKILL = 30, + SPELL_AURA_MOD_INCREASE_SPEED = 31, + SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED = 32, + SPELL_AURA_MOD_DECREASE_SPEED = 33, + SPELL_AURA_MOD_INCREASE_HEALTH = 34, + SPELL_AURA_MOD_INCREASE_ENERGY = 35, + SPELL_AURA_MOD_SHAPESHIFT = 36, + SPELL_AURA_EFFECT_IMMUNITY = 37, + SPELL_AURA_STATE_IMMUNITY = 38, + SPELL_AURA_SCHOOL_IMMUNITY = 39, + SPELL_AURA_DAMAGE_IMMUNITY = 40, + SPELL_AURA_DISPEL_IMMUNITY = 41, + SPELL_AURA_PROC_TRIGGER_SPELL = 42, + SPELL_AURA_PROC_TRIGGER_DAMAGE = 43, + SPELL_AURA_TRACK_CREATURES = 44, + SPELL_AURA_TRACK_RESOURCES = 45, + SPELL_AURA_46 = 46, // Ignore all Gear test spells + SPELL_AURA_MOD_PARRY_PERCENT = 47, + SPELL_AURA_48 = 48, // One periodic spell + SPELL_AURA_MOD_DODGE_PERCENT = 49, + SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT = 50, + SPELL_AURA_MOD_BLOCK_PERCENT = 51, + SPELL_AURA_MOD_WEAPON_CRIT_PERCENT = 52, + SPELL_AURA_PERIODIC_LEECH = 53, + SPELL_AURA_MOD_HIT_CHANCE = 54, + SPELL_AURA_MOD_SPELL_HIT_CHANCE = 55, + SPELL_AURA_TRANSFORM = 56, + SPELL_AURA_MOD_SPELL_CRIT_CHANCE = 57, + SPELL_AURA_MOD_INCREASE_SWIM_SPEED = 58, + SPELL_AURA_MOD_DAMAGE_DONE_CREATURE = 59, + SPELL_AURA_MOD_PACIFY_SILENCE = 60, + SPELL_AURA_MOD_SCALE = 61, + SPELL_AURA_PERIODIC_HEALTH_FUNNEL = 62, + SPELL_AURA_63 = 63, // old SPELL_AURA_PERIODIC_MANA_FUNNEL + SPELL_AURA_PERIODIC_MANA_LEECH = 64, + SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK = 65, + SPELL_AURA_FEIGN_DEATH = 66, + SPELL_AURA_MOD_DISARM = 67, + SPELL_AURA_MOD_STALKED = 68, + SPELL_AURA_SCHOOL_ABSORB = 69, + SPELL_AURA_EXTRA_ATTACKS = 70, + SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL = 71, + SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT = 72, + SPELL_AURA_MOD_POWER_COST_SCHOOL = 73, + SPELL_AURA_REFLECT_SPELLS_SCHOOL = 74, + SPELL_AURA_MOD_LANGUAGE = 75, + SPELL_AURA_FAR_SIGHT = 76, + SPELL_AURA_MECHANIC_IMMUNITY = 77, + SPELL_AURA_MOUNTED = 78, + SPELL_AURA_MOD_DAMAGE_PERCENT_DONE = 79, + SPELL_AURA_MOD_PERCENT_STAT = 80, + SPELL_AURA_SPLIT_DAMAGE_PCT = 81, + SPELL_AURA_WATER_BREATHING = 82, + SPELL_AURA_MOD_BASE_RESISTANCE = 83, + SPELL_AURA_MOD_REGEN = 84, + SPELL_AURA_MOD_POWER_REGEN = 85, + SPELL_AURA_CHANNEL_DEATH_ITEM = 86, + SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN = 87, + SPELL_AURA_MOD_HEALTH_REGEN_PERCENT = 88, + SPELL_AURA_PERIODIC_DAMAGE_PERCENT = 89, + SPELL_AURA_90 = 90, // old SPELL_AURA_MOD_RESIST_CHANCE + SPELL_AURA_MOD_DETECT_RANGE = 91, + SPELL_AURA_PREVENTS_FLEEING = 92, + SPELL_AURA_MOD_UNATTACKABLE = 93, + SPELL_AURA_INTERRUPT_REGEN = 94, + SPELL_AURA_GHOST = 95, + SPELL_AURA_SPELL_MAGNET = 96, + SPELL_AURA_MANA_SHIELD = 97, + SPELL_AURA_MOD_SKILL_TALENT = 98, + SPELL_AURA_MOD_ATTACK_POWER = 99, + SPELL_AURA_AURAS_VISIBLE = 100, + SPELL_AURA_MOD_RESISTANCE_PCT = 101, + SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS = 102, + SPELL_AURA_MOD_TOTAL_THREAT = 103, + SPELL_AURA_WATER_WALK = 104, + SPELL_AURA_FEATHER_FALL = 105, + SPELL_AURA_HOVER = 106, + SPELL_AURA_ADD_FLAT_MODIFIER = 107, + SPELL_AURA_ADD_PCT_MODIFIER = 108, + SPELL_AURA_ADD_TARGET_TRIGGER = 109, + SPELL_AURA_MOD_POWER_REGEN_PERCENT = 110, + SPELL_AURA_ADD_CASTER_HIT_TRIGGER = 111, + SPELL_AURA_OVERRIDE_CLASS_SCRIPTS = 112, + SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN = 113, + SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT = 114, + SPELL_AURA_MOD_HEALING = 115, + SPELL_AURA_MOD_REGEN_DURING_COMBAT = 116, + SPELL_AURA_MOD_MECHANIC_RESISTANCE = 117, + SPELL_AURA_MOD_HEALING_PCT = 118, + SPELL_AURA_119 = 119, // old SPELL_AURA_SHARE_PET_TRACKING + SPELL_AURA_UNTRACKABLE = 120, + SPELL_AURA_EMPATHY = 121, + SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT = 122, + SPELL_AURA_MOD_TARGET_RESISTANCE = 123, + SPELL_AURA_MOD_RANGED_ATTACK_POWER = 124, + SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN = 125, + SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT = 126, + SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS = 127, + SPELL_AURA_MOD_POSSESS_PET = 128, + SPELL_AURA_MOD_SPEED_ALWAYS = 129, + SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS = 130, + SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS = 131, + SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT = 132, + SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT = 133, + SPELL_AURA_MOD_MANA_REGEN_INTERRUPT = 134, + SPELL_AURA_MOD_HEALING_DONE = 135, + SPELL_AURA_MOD_HEALING_DONE_PERCENT = 136, + SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE = 137, + SPELL_AURA_MOD_MELEE_HASTE = 138, + SPELL_AURA_FORCE_REACTION = 139, + SPELL_AURA_MOD_RANGED_HASTE = 140, + 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, + SPELL_AURA_MOD_PET_TALENT_POINTS = 145, + SPELL_AURA_ALLOW_TAME_PET_TYPE = 146, + SPELL_AURA_MECHANIC_IMMUNITY_MASK = 147, + SPELL_AURA_RETAIN_COMBO_POINTS = 148, + SPELL_AURA_REDUCE_PUSHBACK = 149, // Reduce Pushback + SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT = 150, + SPELL_AURA_TRACK_STEALTHED = 151, // Track Stealthed + SPELL_AURA_MOD_DETECTED_RANGE = 152, // Mod Detected Range + 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_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, + SPELL_AURA_164 = 164, + SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS = 165, + SPELL_AURA_MOD_ATTACK_POWER_PCT = 166, + SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT = 167, + SPELL_AURA_MOD_DAMAGE_DONE_VERSUS = 168, + 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, + SPELL_AURA_173 = 173, // old SPELL_AURA_ALLOW_CHAMPION_SPELLS + SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT = 174, // by defeult intelect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT + SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT = 175, + SPELL_AURA_SPIRIT_OF_REDEMPTION = 176, + SPELL_AURA_AOE_CHARM = 177, + 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 + SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT = 182, + SPELL_AURA_MOD_CRITICAL_THREAT = 183, + SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE = 184, + SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE = 185, + SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE = 186, + SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE = 187, + SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE = 188, + SPELL_AURA_MOD_RATING = 189, + SPELL_AURA_MOD_FACTION_REPUTATION_GAIN = 190, + SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED = 191, + SPELL_AURA_MOD_MELEE_RANGED_HASTE = 192, + SPELL_AURA_MELEE_SLOW = 193, + SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL = 194, + SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL = 195, + SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath + SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197, + SPELL_AURA_198 = 198, // old SPELL_AURA_MOD_ALL_WEAPON_SKILLS + 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, + SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE = 203, + SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE = 204, + SPELL_AURA_MOD_SCHOOL_CRIT_DMG_TAKEN = 205, + SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED = 206, + SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED = 207, + SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED = 208, + 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_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, + SPELL_AURA_HASTE_RANGED = 218, + SPELL_AURA_MOD_MANA_REGEN_FROM_STAT = 219, + SPELL_AURA_MOD_RATING_FROM_STAT = 220, + SPELL_AURA_MOD_DETAUNT = 221, + SPELL_AURA_222 = 222, + SPELL_AURA_RAID_PROC_FROM_CHARGE = 223, + SPELL_AURA_224 = 224, + SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE = 225, + SPELL_AURA_PERIODIC_DUMMY = 226, + 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_PROC_TRIGGER_SPELL_WITH_VALUE = 231, + SPELL_AURA_MECHANIC_DURATION_MOD = 232, + SPELL_AURA_CHANGE_MODEL_FOR_ALL_HUMANOIDS = 233, // client-side only + SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK = 234, + SPELL_AURA_MOD_DISPEL_RESIST = 235, + SPELL_AURA_CONTROL_VEHICLE = 236, + SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER = 237, + SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER = 238, + SPELL_AURA_MOD_SCALE_2 = 239, + SPELL_AURA_MOD_EXPERTISE = 240, + SPELL_AURA_FORCE_MOVE_FORWARD = 241, + SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING = 242, + SPELL_AURA_MOD_FACTION = 243, + SPELL_AURA_COMPREHEND_LANGUAGE = 244, + SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL = 245, + SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK = 246, + SPELL_AURA_CLONE_CASTER = 247, + SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248, + SPELL_AURA_CONVERT_RUNE = 249, + SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250, + SPELL_AURA_MOD_ENEMY_DODGE = 251, + SPELL_AURA_MOD_SPEED_SLOW_ALL = 252, + SPELL_AURA_MOD_BLOCK_CRIT_CHANCE = 253, + SPELL_AURA_MOD_DISARM_OFFHAND = 254, + SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT = 255, + SPELL_AURA_NO_REAGENT_USE = 256, + SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS = 257, + SPELL_AURA_258 = 258, + SPELL_AURA_259 = 259, // 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, + SPELL_AURA_ALLOW_ONLY_ABILITY = 263, + SPELL_AURA_264 = 264, + SPELL_AURA_265 = 265, + SPELL_AURA_266 = 266, + SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267, + SPELL_AURA_268 = 268, // old SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT. unused 4.3.4 + SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 269, + 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_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, + 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_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 + SPELL_AURA_LINKED = 284, + SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR = 285, + SPELL_AURA_ABILITY_PERIODIC_CRIT = 286, + SPELL_AURA_DEFLECT_SPELLS = 287, + SPELL_AURA_IGNORE_HIT_DIRECTION = 288, + SPELL_AURA_289 = 289, + SPELL_AURA_MOD_CRIT_PCT = 290, + SPELL_AURA_MOD_XP_QUEST_PCT = 291, + SPELL_AURA_OPEN_STABLE = 292, + SPELL_AURA_OVERRIDE_SPELLS = 293, + SPELL_AURA_PREVENT_REGENERATE_POWER = 294, + SPELL_AURA_295 = 295, + SPELL_AURA_SET_VEHICLE_ID = 296, + SPELL_AURA_BLOCK_SPELL_FAMILY = 297, + SPELL_AURA_STRANGULATE = 298, + SPELL_AURA_299 = 299, + SPELL_AURA_SHARE_DAMAGE_PCT = 300, + SPELL_AURA_SCHOOL_HEAL_ABSORB = 301, + SPELL_AURA_302 = 302, + SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE = 303, + SPELL_AURA_MOD_FAKE_INEBRIATE = 304, + SPELL_AURA_MOD_MINIMUM_SPEED = 305, + SPELL_AURA_306 = 306, + SPELL_AURA_HEAL_ABSORB_TEST = 307, + SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER = 308, + SPELL_AURA_309 = 309, + SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE = 310, + SPELL_AURA_311 = 311, + SPELL_AURA_312 = 312, // puts the caster in stealth? + SPELL_AURA_313 = 313, + SPELL_AURA_PREVENT_RESURRECTION = 314, + SPELL_AURA_UNDERWATER_WALKING = 315, + SPELL_AURA_316 = 316, // old SPELL_AURA_PERIODIC_HASTE. unused 4.3.4 + 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, + SPELL_AURA_324 = 324, // spell critical chance (probably by school mask) + SPELL_AURA_325 = 325, + SPELL_AURA_326 = 326, // phase related + SPELL_AURA_327 = 327, + SPELL_AURA_PROC_ON_POWER_AMOUNT = 328, + SPELL_AURA_MOD_RUNE_REGEN_SPEED = 329, // NYI + SPELL_AURA_CAST_WHILE_WALKING = 330, // NYI + SPELL_AURA_331 = 331, + SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS = 332, + SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2 = 333, + SPELL_AURA_334 = 334, + SPELL_AURA_335 = 335, + SPELL_AURA_MOD_FLYING_RESTRICTIONS = 336, // NYI + SPELL_AURA_MOD_VENDOR_ITEMS_PRICES = 337, // NYI + SPELL_AURA_MOD_DURABILITY_LOSS = 338, + SPELL_AURA_INCREASE_SKILL_GAIN_CHANCE = 339, // NYI + SPELL_AURA_340 = 340, + SPELL_AURA_341 = 341, // cooldown decrease + SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 = 342, + SPELL_AURA_343 = 343, + SPELL_AURA_MOD_AUTOATTACK_DAMAGE = 344, + SPELL_AURA_BYPASS_ARMOR_FOR_CASTER = 345, + SPELL_AURA_PROGRESS_BAR = 346, // NYI + SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE = 347, // NYI + SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT = 348, // NYI + SPELL_AURA_MOD_CURRENCY_GAIN = 349, // NYI + 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, + SPELL_AURA_355 = 355, + SPELL_AURA_356 = 356, + SPELL_AURA_357 = 357, + SPELL_AURA_358 = 358, + SPELL_AURA_359 = 359, + SPELL_AURA_360 = 360, + SPELL_AURA_361 = 361, + SPELL_AURA_362 = 362, + SPELL_AURA_363 = 363, + SPELL_AURA_364 = 364, + SPELL_AURA_365 = 365, + SPELL_AURA_366 = 366, + SPELL_AURA_367 = 367, + SPELL_AURA_368 = 368, + SPELL_AURA_369 = 369, + SPELL_AURA_370 = 370, + 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 b83e44d6a73..be18785e76e 100755..100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -118,7 +118,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::HandleNULL, // 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 @@ -145,7 +145,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::HandleNULL, // 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 @@ -174,7 +174,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::HandleNULL, //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 @@ -196,7 +196,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 @@ -208,14 +208,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 @@ -224,19 +224,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::HandleNULL, //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::HandleNULL, //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 @@ -253,8 +253,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::HandleNULL, //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 @@ -267,19 +267,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 @@ -314,28 +314,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 @@ -350,28 +350,82 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleAuraOpenStable, //292 SPELL_AURA_OPEN_STABLE &AuraEffect::HandleAuraOverrideSpells, //293 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::HandleNULL, //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::HandleNULL, //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::HandleNULL, //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::HandleNULL, //306 0 spells in 3.3.5 - &AuraEffect::HandleNULL, //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::HandleNULL, //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::HandleNULL, //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::HandleNULL, //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::HandleNULL, //326 SPELL_AURA_326 + &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::HandleNULL, //330 SPELL_AURA_CAST_WHILE_WALKING + &AuraEffect::HandleNULL, //331 SPELL_AURA_331 + &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_334 + &AuraEffect::HandleNULL, //335 SPELL_AURA_335 + &AuraEffect::HandleNULL, //336 SPELL_AURA_MOD_FLYING_RESTRICTIONS + &AuraEffect::HandleNULL, //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_340 + &AuraEffect::HandleNULL, //341 SPELL_AURA_341 + &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::HandleNULL, //345 SPELL_AURA_BYPASS_ARMOR_FOR_CASTER + &AuraEffect::HandleNULL, //346 SPELL_AURA_PROGRESS_BAR + &AuraEffect::HandleNULL, //347 SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE + &AuraEffect::HandleNULL, //348 SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT + &AuraEffect::HandleNULL, //349 SPELL_AURA_MOD_CURRENCY_GAIN + &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_357 + &AuraEffect::HandleNULL, //358 SPELL_AURA_358 + &AuraEffect::HandleNULL, //359 SPELL_AURA_359 + &AuraEffect::HandleNULL, //360 SPELL_AURA_360 + &AuraEffect::HandleNULL, //361 SPELL_AURA_361 + &AuraEffect::HandleUnused, //362 unused (4.3.4) + &AuraEffect::HandleNULL, //363 SPELL_AURA_363 + &AuraEffect::HandleUnused, //364 unused (4.3.4) + &AuraEffect::HandleNULL, //365 SPELL_AURA_365 + &AuraEffect::HandleNULL, //366 SPELL_AURA_366 + &AuraEffect::HandleNULL, //367 SPELL_AURA_367 + &AuraEffect::HandleUnused, //368 unused (4.3.4) + &AuraEffect::HandleNULL, //369 SPELL_AURA_369 + &AuraEffect::HandleNULL, //370 SPELL_AURA_370 }; AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* caster): @@ -417,7 +471,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster) { int32 amount; // default amount calculation - amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount, NULL); + amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit()); // check item enchant aura cast if (!amount && caster) @@ -469,9 +523,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) { AddPctN(amount, (*itr)->GetAmount()); @@ -491,28 +545,19 @@ int32 AuraEffect::CalculateAmount(Unit* caster) // Ice Barrier if (GetSpellInfo()->SpellFamilyFlags[1] & 0x1 && GetSpellInfo()->SpellFamilyFlags[2] & 0x8) { - // +80.68% from sp bonus - DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8068f; - // Glyph of Ice Barrier: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :) - // Glyph of Ice Barrier is only applied at the spell damage bonus because it was already applied to the base value in CalculateSpellDamage - DoneActualBenefit = caster->ApplyEffectModifiers(GetSpellInfo(), m_effIndex, DoneActualBenefit); + // +87% from sp bonus + DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.87f; } - // Fire Ward + // Mage Ward else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x8 && GetSpellInfo()->SpellFamilyFlags[2] & 0x8) { // +80.68% from sp bonus DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8068f; } - // Frost Ward - else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x100 && GetSpellInfo()->SpellFamilyFlags[2] & 0x8) - { - // +80.68% from sp bonus - DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8068f; - } break; case SPELLFAMILY_WARLOCK: // Shadow Ward - if (m_spellInfo->SpellFamilyFlags[2] & 0x40) + if (m_spellInfo->SpellFamilyFlags[2] & 0x80000000) { // +80.68% from sp bonus DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8068f; @@ -520,28 +565,18 @@ int32 AuraEffect::CalculateAmount(Unit* caster) break; case SPELLFAMILY_PRIEST: // Power Word: Shield - if (GetSpellInfo()->SpellFamilyFlags[0] & 0x1 && GetSpellInfo()->SpellFamilyFlags[2] & 0x400) + if (GetSpellInfo()->SpellFamilyFlags[0] & 0x1) { // +80.68% from sp bonus - float bonus = 0.8068f; - - // Borrowed Time - if (AuraEffect const* pAurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 2899, 1)) - bonus += CalculatePctN(1.0f, pAurEff->GetAmount()); - - DoneActualBenefit += caster->SpellBaseHealingBonusDone(m_spellInfo->GetSchoolMask()) * bonus; - // Improved PW: Shield: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :) - // Improved PW: Shield is only applied at the spell healing bonus because it was already applied to the base value in CalculateSpellDamage - DoneActualBenefit = caster->ApplyEffectModifiers(GetSpellInfo(), m_effIndex, DoneActualBenefit); + DoneActualBenefit += caster->SpellBaseHealingBonusDone(m_spellInfo->GetSchoolMask()) * 0.8068f; DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellInfo()); amount += int32(DoneActualBenefit); // Twin Disciplines - if (AuraEffect const* pAurEff = caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_PRIEST, 0x400000, 0, 0, caster->GetGUID())) + if (AuraEffect const* pAurEff = caster->GetAuraEffect(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, SPELLFAMILY_PRIEST, 2292, 0)) AddPctN(amount, pAurEff->GetAmount()); - // Focused Power // Reuse variable, not sure if this code below can be moved before Twin Disciplines DoneActualBenefit = float(amount); DoneActualBenefit *= caster->GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_DONE_PERCENT); @@ -550,30 +585,6 @@ int32 AuraEffect::CalculateAmount(Unit* caster) return amount; } break; - case SPELLFAMILY_PALADIN: - // Sacred Shield - if (m_spellInfo->SpellFamilyFlags[1] & 0x80000) - { - //+75.00% from sp bonus - float bonus = 0.75f; - - DoneActualBenefit += caster->SpellBaseHealingBonusDone(m_spellInfo->GetSchoolMask()) * bonus; - // Divine Guardian is only applied at the spell healing bonus because it was already applied to the base value in CalculateSpellDamage - DoneActualBenefit = caster->ApplyEffectModifiers(GetSpellInfo(), m_effIndex, DoneActualBenefit); - DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellInfo()); - - amount += (int32)DoneActualBenefit; - - // Arena - Dampening - AuraEffect const* pAurEff = caster->GetAuraEffect(74410, 0); - if (!pAurEff) - pAurEff = caster->GetAuraEffect(74411, 0); // Battleground - Dampening - if (pAurEff) - AddPctN(amount, pAurEff->GetAmount()); - - return amount; - } - break; default: break; } @@ -585,8 +596,8 @@ int32 AuraEffect::CalculateAmount(Unit* caster) // Mana Shield if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_MAGE && GetSpellInfo()->SpellFamilyFlags[0] & 0x8000 && m_spellInfo->SpellFamilyFlags[2] & 0x8) { - // +80.53% from +spd bonus - DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8053f; + // +80.7% from +spd bonus + DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.807f; } break; case SPELL_AURA_DUMMY: @@ -602,24 +613,8 @@ int32 AuraEffect::CalculateAmount(Unit* caster) case SPELL_AURA_PERIODIC_DAMAGE: if (!caster) break; - // Rupture - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellInfo->SpellFamilyFlags[0] & 0x100000) - { - m_canBeRecalculated = false; - if (caster->GetTypeId() != TYPEID_PLAYER) - break; - //1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs - //2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs - //3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs - //4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs - //5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs - float AP_per_combo[6] = {0.0f, 0.015f, 0.024f, 0.03f, 0.03428571f, 0.0375f}; - uint8 cp = caster->ToPlayer()->GetComboPoints(); - if (cp > 5) cp = 5; - amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]); - } // Rip - else if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[0] & 0x00800000 && GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE) + if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[0] & 0x00800000) { m_canBeRecalculated = false; // 0.01*$AP*cp @@ -641,20 +636,13 @@ int32 AuraEffect::CalculateAmount(Unit* caster) else if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARRIOR && GetSpellInfo()->SpellFamilyFlags[0] & 0x20) { m_canBeRecalculated = false; - // $0.2 * (($MWB + $mwb) / 2 + $AP / 14 * $MWS) bonus per tick + // ${0.25 * 6 * (($MWB + $mwb) / 2 + $AP / 14 * $MWS)} bonus per tick float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); int32 mws = caster->GetAttackTime(BASE_ATTACK); float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); - float mwb = ((mwb_min + mwb_max) / 2 + ap * mws / 14000) * 0.2f; + float mwb = ((mwb_min + mwb_max) / 2 + ap * mws / 14000) * 0.25f * 6.0f; amount += int32(caster->ApplyEffectModifiers(m_spellInfo, m_effIndex, mwb)); - // "If used while your target is above 75% health, Rend does 35% more damage." - // as for 3.1.3 only ranks above 9 (wrong tooltip?) - if (m_spellInfo->GetRank() >= 9) - { - if (GetBase()->GetUnitOwner()->HasAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, m_spellInfo, caster)) - AddPctN(amount, m_spellInfo->Effects[EFFECT_2].CalcValue(caster)); - } } // Unholy Blight damage over time effect else if (GetId() == 50536) @@ -668,7 +656,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster) switch (m_spellInfo->Id) { case 57669: // Replenishment (0.2% from max) - amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 0.002f; + amount = CalculatePctN(GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA), amount); break; case 61782: // Infinite Replenishment amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 0.0025f; @@ -695,39 +683,6 @@ int32 AuraEffect::CalculateAmount(Unit* caster) AddPctN(amount, modHealing->GetAmount()); } break; - case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: - if (!caster) - break; - // Icebound Fortitude - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00100000) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - { - int32 value = (-1 * amount) - 10; - uint32 defva = uint32(caster->ToPlayer()->GetSkillValue(SKILL_DEFENSE) + caster->ToPlayer()->GetRatingBonusValue(CR_DEFENSE_SKILL)); - - if (defva > 400) - value += int32((defva - 400) * 0.15); - - // Glyph of Icebound Fortitude - if (AuraEffect const* aurEff = caster->GetAuraEffect(58625, 0)) - { - int32 valMax = aurEff->GetAmount(); - if (value < valMax) - value = valMax; - } - amount = -value; - } - } - // Hand of Salvation - else if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_PALADIN && GetSpellInfo()->SpellFamilyFlags[0] & 0x00000100) - { - //Glyph of Salvation - if (caster->GetGUID() == GetBase()->GetUnitOwner()->GetGUID()) - if (AuraEffect const* aurEff = caster->GetAuraEffect(63225, 0)) - amount = -aurEff->GetAmount(); - } - break; case SPELL_AURA_MOD_THREAT: { uint8 level_diff = 0; @@ -759,6 +714,10 @@ int32 AuraEffect::CalculateAmount(Unit* caster) if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_DRUID && GetSpellInfo()->SpellFamilyFlags[2] & 0x00000008) amount = GetBase()->GetUnitOwner()->GetShapeshiftForm() == FORM_CAT ? amount : 0; break; + case SPELL_AURA_MOUNTED: + if (MountCapabilityEntry const* mountCapability = GetBase()->GetUnitOwner()->GetMountCapability(uint32(GetMiscValueB()))) + amount = mountCapability->Id; + break; default: break; } @@ -773,7 +732,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; @@ -824,8 +783,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)); } } @@ -843,9 +801,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; @@ -1203,7 +1158,7 @@ bool AuraEffect::IsPeriodicTickCrit(Unit* target, Unit const* caster) const Unit::AuraEffectList const& mPeriodicCritAuras= caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_PERIODIC_CRIT); for (Unit::AuraEffectList::const_iterator itr = mPeriodicCritAuras.begin(); itr != mPeriodicCritAuras.end(); ++itr) { - if ((*itr)->IsAffectedOnSpell(m_spellInfo) && caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask())) + if ((*itr)->IsAffectingSpell(m_spellInfo) && caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask())) return true; } @@ -1214,7 +1169,7 @@ bool AuraEffect::IsPeriodicTickCrit(Unit* target, Unit const* caster) const return false; } -bool AuraEffect::IsAffectedOnSpell(SpellInfo const* spell) const +bool AuraEffect::IsAffectingSpell(SpellInfo const* spell) const { if (!spell) return false; @@ -1358,11 +1313,6 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const spellId2 = 21178; HotWSpellId = 24899; break; - case FORM_DIREBEAR: - spellId = 9635; - spellId2 = 21178; - HotWSpellId = 24899; - break; case FORM_BATTLESTANCE: spellId = 21156; break; @@ -1428,7 +1378,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) @@ -1448,13 +1400,14 @@ 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))) target->CastSpell(target, glyph->SpellId, true, NULL, this); } @@ -1462,19 +1415,21 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const } // 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))) 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)) + if (plrTarget->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 @@ -1519,7 +1474,6 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const target->CastCustomSpell(target, 48420, &bp, NULL, NULL, true); } break; - case FORM_DIREBEAR: case FORM_BEAR: // Master Shapeshifter - Bear if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0)) @@ -1530,7 +1484,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const // Survival of the Fittest if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DRUID, 961, 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; @@ -1900,7 +1854,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 @@ -1950,7 +1903,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: @@ -1979,7 +1931,7 @@ 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); @@ -1988,10 +1940,9 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo { case FORM_CAT: case FORM_BEAR: - case FORM_DIREBEAR: { // get furor proc chance - uint32 FurorChance = 0; + int32 FurorChance = 0; if (AuraEffect const* dummy = target->GetDummyAuraEffect(SPELLFAMILY_DRUID, 238, 0)) FurorChance = std::max(dummy->GetAmount(), 0); @@ -1999,18 +1950,17 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo { case FORM_CAT: { - int32 basePoints = int32(std::min(oldPower, FurorChance)); + int32 basePoints = std::min<int32>(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) + if (irand(0, 99) < FurorChance) target->CastSpell(target, 17057, true); default: { - uint32 newEnergy = std::min(target->GetPower(POWER_ENERGY), FurorChance); + int32 newEnergy = std::min(target->GetPower(POWER_ENERGY), FurorChance); target->SetPower(POWER_ENERGY, newEnergy); } break; @@ -2049,7 +1999,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); @@ -2063,7 +2012,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) { @@ -2124,7 +2073,7 @@ 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); // 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) { @@ -2414,9 +2363,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); */ @@ -2462,9 +2409,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); */ // blizz like 2.0.x @@ -2769,17 +2714,17 @@ 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); + target->ModifySkillBonus(prot, (apply ? points : -points), GetAuraType() == SPELL_AURA_MOD_SKILL_TALENT); if (prot == SKILL_DEFENSE) - target->ToPlayer()->UpdateDefenseBonusesMod(); + target->UpdateDefenseBonusesMod(); } /****************************/ @@ -2817,7 +2762,7 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo if (target->GetTypeId() == TYPEID_PLAYER) team = target->ToPlayer()->GetTeam(); - uint32 displayID = sObjectMgr->ChooseDisplayId(team, ci); + uint32 displayID = ObjectMgr::ChooseDisplayId(team, ci); sObjectMgr->GetCreatureModelRandomGender(&displayID); //some spell has one aura of mount and one of vehicle @@ -2827,6 +2772,10 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo displayID = 0; target->Mount(displayID, ci->VehicleId, GetMiscValue()); + + // cast speed aura + if (MountCapabilityEntry const* mountCapability = target->GetMountCapability(uint32(GetMiscValueB()))) + target->CastSpell(target, mountCapability->SpeedModSpell, true); } else { @@ -2835,7 +2784,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 = target->GetMountCapability(uint32(GetMiscValueB()))) + target->RemoveAurasDueToSpell(mountCapability->SpeedModSpell, target->GetGUID()); + } } } @@ -4007,19 +3962,13 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 Unit* target = aurApp->GetTarget(); - if (GetMiscValue() < -1 || GetMiscValue() > 4) - { - sLog->outError(LOG_FILTER_SPELLS_AURAS, "WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); - return; - } - // save current health state float healthPct = target->GetHealthPct(); bool alive = target->isAlive(); 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 { target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetAmount()), apply); if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->isPet()) @@ -4029,7 +3978,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))); } @@ -4085,7 +4034,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 } @@ -4406,6 +4355,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); @@ -4442,6 +4392,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(); target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply); @@ -4453,24 +4404,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 ***/ /********************************/ @@ -4558,23 +4497,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))) @@ -4918,22 +4840,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); @@ -4959,10 +4865,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())) @@ -5585,7 +5487,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(); @@ -5598,6 +5500,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); @@ -6406,15 +6311,6 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const if (maxval) AddPctF(TakenTotalMod, maxval); - // Healing over time taken percent - float minval_hot = (float)target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT); - if (minval_hot) - AddPctF(TakenTotalMod, minval_hot); - - float maxval_hot = (float)target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT); - if (maxval_hot) - AddPctF(TakenTotalMod, maxval_hot); - TakenTotalMod = std::max(TakenTotalMod, 0.0f); damage = uint32(target->CountPctFromMaxHealth(damage)); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 64079918638..6d29035b9e3 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); } @@ -79,7 +79,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; @@ -242,7 +242,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; @@ -251,8 +250,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; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 9ee05b9a2a4..31129cf98d4 100755 --- 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,11 @@ 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)) // NULL if effect flag not set + data << int32(eff->GetAmount()); } void AuraApplication::ClientUpdate(bool remove) @@ -337,7 +345,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); @@ -672,7 +680,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; @@ -741,18 +749,35 @@ void Aura::RefreshDuration() { 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) @@ -766,14 +791,14 @@ void Aura::SetCharges(uint8 charges) uint8 Aura::CalcMaxCharges(Unit* caster) const { - uint8 maxProcCharges = m_spellInfo->ProcCharges; + uint32 maxProcCharges = m_spellInfo->ProcCharges; if (SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId())) maxProcCharges = procEntry->charges; if (caster) if (Player* modOwner = caster->GetSpellModOwner()) modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, maxProcCharges); - return maxProcCharges; + return uint8(maxProcCharges); } bool Aura::ModCharges(int32 num, AuraRemoveMode removeMode) @@ -913,6 +938,10 @@ bool Aura::CanBeSaved() const if (GetId() == 44413) return false; + // 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; @@ -1142,20 +1171,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) @@ -1187,18 +1204,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; } @@ -1210,7 +1215,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); @@ -1240,49 +1245,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: - sLog->outError(LOG_FILTER_SPELLS_AURAS, "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 @@ -1321,18 +1283,6 @@ 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; } @@ -1342,34 +1292,11 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[1] & 0x1) { // Shattered Barrier - if (AuraEffect * dummy = caster->GetDummyAuraEffect(SPELLFAMILY_MAGE, 2945, 0)) + if (AuraEffect * dummy = caster->GetDummyAuraEffect(SPELLFAMILY_MAGE, 3260, 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) break; @@ -1394,18 +1321,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)) @@ -1421,68 +1338,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(CalculatePctF(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(CalculatePctN(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(SMSG_SPELL_COOLDOWN, 8+1+4+4); - data << uint64(player->GetGUID()); - data << uint8(0x0); // flags (0x1, 0x2) - data << uint32(GetSpellInfo()->Id); - data << uint32(aurEff->GetAmount()*IN_MILLISECONDS); - player->SendDirectMessage(&data); - } - break; - } break; case SPELLFAMILY_ROGUE: // Remove Vanish on stealth remove @@ -1549,7 +1410,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00400000) { // Master of subtlety - if (AuraEffect const* aurEff = target->GetAuraEffectOfRankedSpell(31221, 0)) + if (AuraEffect const* aurEff = target->GetAuraEffect(31223, 0)) { if (!apply) target->CastSpell(target, 31666, true); @@ -1559,14 +1420,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b 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; @@ -1592,15 +1445,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b case SPELLFAMILY_PALADIN: switch (GetId()) { - case 19746: - // Improved concentration aura - linked aura - if (caster->HasAura(20254) || caster->HasAura(20255) || caster->HasAura(20256)) - { - if (apply) - target->CastSpell(target, 63510, true); - else - target->RemoveAura(63510); - } case 31821: // Aura Mastery Triggered Spell Handler // If apply Concentration Aura -> trigger -> apply Aura Mastery Immunity @@ -1618,7 +1462,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b else target->RemoveAurasDueToSpell(64364, GetCasterGUID()); break; - case 31842: // Divine Illumination + case 31842: // Divine Favor // Item - Paladin T10 Holy 2P Bonus if (target->HasAura(70755)) { @@ -1629,115 +1473,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b } break; } - if (GetSpellInfo()->GetSpellSpecific() == SPELL_SPECIFIC_AURA) - { - // Improved devotion aura - if (caster->HasAura(20140) || caster->HasAura(20138) || caster->HasAura(20139)) - { - if (apply) - caster->CastSpell(target, 63514, true); - else - target->RemoveAura(63514); - } - // 63531 - linked aura for both Sanctified Retribution and Swift Retribution talents - // Not allow for Retribution Aura (prevent stacking) - if ((GetSpellInfo()->SpellIconID != 555) && (caster->HasAura(53648) || caster->HasAura(53484) || caster->HasAura(53379) || caster->HasAura(31869))) - { - if (apply) - caster->CastSpell(target, 63531, true); - else - target->RemoveAura(63531); - } - } - break; - case SPELLFAMILY_DEATHKNIGHT: - if (GetSpellInfo()->GetSpellSpecific() == SPELL_SPECIFIC_PRESENCE) - { - AuraEffect* bloodPresenceAura=0; // healing by damage done - AuraEffect* frostPresenceAura=0; // increased health - AuraEffect* unholyPresenceAura=0; // increased movement speed, faster rune recovery - - // Improved Presences - Unit::AuraEffectList const& vDummyAuras = target->GetAuraEffectsByType(SPELL_AURA_DUMMY); - for (Unit::AuraEffectList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr) - { - switch ((*itr)->GetId()) - { - // Improved Blood Presence - case 50365: - case 50371: - { - bloodPresenceAura = (*itr); - break; - } - // Improved Frost Presence - case 50384: - case 50385: - { - frostPresenceAura = (*itr); - break; - } - // Improved Unholy Presence - case 50391: - case 50392: - { - unholyPresenceAura = (*itr); - break; - } - } - } - - uint32 presence = GetId(); - if (apply) - { - // Blood Presence bonus - if (presence == 48266) - target->CastSpell(target, 63611, true); - else if (bloodPresenceAura) - { - int32 basePoints1 = bloodPresenceAura->GetAmount(); - target->CastCustomSpell(target, 63611, NULL, &basePoints1, NULL, true, 0, bloodPresenceAura); - } - // Frost Presence bonus - if (presence == 48263) - target->CastSpell(target, 61261, true); - else if (frostPresenceAura) - { - int32 basePoints0 = frostPresenceAura->GetAmount(); - target->CastCustomSpell(target, 61261, &basePoints0, NULL, NULL, true, 0, frostPresenceAura); - } - // Unholy Presence bonus - if (presence == 48265) - { - if (unholyPresenceAura) - { - // Not listed as any effect, only base points set - int32 basePoints0 = unholyPresenceAura->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); - target->CastCustomSpell(target, 63622, &basePoints0, &basePoints0, &basePoints0, true, 0, unholyPresenceAura); - } - target->CastSpell(target, 49772, true); - } - else if (unholyPresenceAura) - { - int32 basePoints0 = unholyPresenceAura->GetAmount(); - target->CastCustomSpell(target, 49772, &basePoints0, NULL, NULL, true, 0, unholyPresenceAura); - } - } - else - { - // Remove passive auras - if (presence == 48266 || bloodPresenceAura) - target->RemoveAurasDueToSpell(63611); - if (presence == 48263 || frostPresenceAura) - target->RemoveAurasDueToSpell(61261); - if (presence == 48265 || unholyPresenceAura) - { - if (presence == 48265 && unholyPresenceAura) - target->RemoveAurasDueToSpell(63622); - target->RemoveAurasDueToSpell(49772); - } - } - } break; case SPELLFAMILY_WARLOCK: // Drain Soul - If the target is at or below 25% health, Drain Soul causes four times the normal damage @@ -2471,4 +2206,3 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster* } } } - diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 2f50d47a79b..36398bafa97 100755 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -166,7 +166,7 @@ class Aura void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 * amount); // helpers for aura effects - bool HasEffect(uint8 effIndex) const { return bool(GetEffect(effIndex)); } + bool HasEffect(uint8 effIndex) const { return GetEffect(effIndex) != NULL; } bool HasEffectType(AuraType type) const; AuraEffect* GetEffect(uint8 effIndex) const { ASSERT (effIndex < MAX_SPELL_EFFECTS); return m_effects[effIndex]; } uint8 GetEffectMask() const { uint8 effMask = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (m_effects[i]) effMask |= 1<<i; return effMask; } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 6376ff6e50b..98833c3eb41 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -53,6 +53,7 @@ #include "SpellScript.h" #include "InstanceScript.h" #include "SpellInfo.h" +#include "DB2Stores.h" #include "Battlefield.h" #include "BattlefieldMgr.h" @@ -533,7 +534,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; @@ -1061,14 +1062,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 compability with older code - add only unit and go targets // TODO: remove this @@ -1348,14 +1342,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(unitTargets, maxTargets); - } for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr) AddUnitTarget(*itr, effMask, false); @@ -1364,14 +1351,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge if (!gObjTargets.empty()) { 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(gObjTargets, maxTargets); - } for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr) AddGOTarget(*itr, effMask); @@ -2503,6 +2483,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) } + m_damage = damageInfo.damage; caster->DealSpellDamage(&damageInfo, true); @@ -2576,25 +2557,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; @@ -2605,14 +2570,14 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA if (unit->GetTypeId() == TYPEID_PLAYER) { unit->ToPlayer()->GetAchievementMgr().StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, m_spellInfo->Id); - unit->ToPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id, 0, m_caster); - unit->ToPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id); + unit->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id, 0, m_caster); + unit->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id); } if (m_caster->GetTypeId() == TYPEID_PLAYER) { m_caster->ToPlayer()->GetAchievementMgr().StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_CASTER, m_spellInfo->Id); - m_caster->ToPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit); + m_caster->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit); } if (m_caster != unit) @@ -2729,15 +2694,28 @@ 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()) + if (duration > 0) { - if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION) - m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this); + // Haste modifies duration of channeled spells + if (m_spellInfo->IsChanneled()) + { + if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION) + 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)); + } } - // 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 != m_spellAura->GetMaxDuration()) { @@ -3254,10 +3232,10 @@ void Spell::cast(bool skipCheck) if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_ITEM) && m_CastItem) { m_caster->ToPlayer()->GetAchievementMgr().StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_ITEM, m_CastItem->GetEntry()); - m_caster->ToPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry()); + m_caster->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry()); } - m_caster->ToPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id); + m_caster->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id); } if (!(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)) @@ -3368,7 +3346,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(); @@ -3684,7 +3662,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; @@ -3745,6 +3723,9 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas 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; @@ -3797,9 +3778,29 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas 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; @@ -3821,23 +3822,7 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas 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; } @@ -3851,19 +3836,17 @@ void Spell::SendSpellStart() //sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "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_UNKNOWN_19; WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); @@ -3876,22 +3859,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_PROJECTILE) + { + data << uint32(0); // Ammo display ID + data << uint32(0); // Inventory Type + } - if (castFlags & CAST_FLAG_UNKNOWN_23) + 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); } @@ -3909,9 +3928,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) @@ -3920,7 +3936,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) { castFlags |= CAST_FLAG_UNKNOWN_19; // same as in SMSG_SPELL_START castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list @@ -3946,6 +3962,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); @@ -3961,30 +3978,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) { @@ -3997,79 +4012,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) - { - Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK); - if (pItem) - { - 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 + if (m_targets.GetTargetMask() & TARGET_FLAG_EXTRA_TARGETS) { - for (uint8 i = 0; i < 3; ++i) + data << uint32(0); // Extra targets count + /* + for (uint8 i = 0; i < count; ++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); } void Spell::WriteSpellGoTargets(WorldPacket* data) @@ -4262,7 +4219,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; @@ -4283,12 +4258,12 @@ void Spell::SendResurrectRequest(Player* target) data << uint32(strlen(resurrectorName) + 1); data << resurrectorName; - data << uint8(0); // null terminator + data << uint8(0); // use timer according to client symbols 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); } @@ -4363,7 +4338,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) @@ -4379,7 +4354,7 @@ void Spell::TakePower() } } - if (powerType == POWER_RUNE) + if (powerType == POWER_RUNES) { TakeRunePower(hit); return; @@ -4435,14 +4410,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; if (m_caster->GetTypeId() != TYPEID_PLAYER) @@ -4663,8 +4636,7 @@ void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOT sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "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); @@ -4732,7 +4704,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; @@ -4758,7 +4730,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) @@ -4808,7 +4780,7 @@ SpellCastResult Spell::CheckCast(bool strict) SpellEffectInfo const* effInfo = &m_spellInfo->Effects[effIndex]; if (effInfo->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) { - SpellShapeshiftEntry const* shapeShiftEntry = sSpellShapeshiftStore.LookupEntry(effInfo->MiscValue); + SpellShapeshiftFormEntry const* shapeShiftEntry = sSpellShapeshiftFormStore.LookupEntry(effInfo->MiscValue); if (shapeShiftEntry && (shapeShiftEntry->flags1 & 1) == 0) // unk flag checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED; break; @@ -4917,14 +4889,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()) @@ -4987,6 +4959,7 @@ SpellCastResult Spell::CheckCast(bool strict) 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) @@ -5002,6 +4975,7 @@ SpellCastResult Spell::CheckCast(bool strict) hasNonDispelEffect = true; break; } + } if (!hasNonDispelEffect && !hasDispellableAura && dispelMask && !IsTriggered()) { @@ -5019,6 +4993,26 @@ SpellCastResult Spell::CheckCast(bool strict) // 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) @@ -5564,8 +5558,9 @@ SpellCastResult Spell::CheckCasterAuras() const bool usableInStun = m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_STUNNED; // 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. @@ -5661,6 +5656,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(); @@ -5781,8 +5807,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) @@ -5973,25 +5999,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 (int i= 0; i < 2; ++i) - { - if (m_spellInfo->TotemCategory[i] != 0) - { - if (p_caster->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 @@ -6031,7 +6039,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) @@ -6205,46 +6213,6 @@ SpellCastResult Spell::CheckItems() case ITEM_SUBCLASS_WEAPON_GUN: case ITEM_SUBCLASS_WEAPON_BOW: case ITEM_SUBCLASS_WEAPON_CROSSBOW: - { - uint32 ammo = m_caster->ToPlayer()->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 (!m_caster->ToPlayer()->HasItemCount(ammo, 1)) - { - m_caster->ToPlayer()->SetUInt32Value(PLAYER_AMMO_ID, 0); - return SPELL_FAILED_NO_AMMO; - } - }; break; case ITEM_SUBCLASS_WEAPON_WAND: break; default: @@ -6689,12 +6657,6 @@ void Spell::HandleLaunchPhase() multiplier[i] = m_spellInfo->Effects[i].CalcDamageMultiplier(m_originalCaster, this); bool usesAmmo = m_spellInfo->AttributesCu & SPELL_ATTR0_CU_DIRECT_DAMAGE; - 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) { @@ -7149,7 +7111,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 1376b0fbd40..ce8754cbff7 100755 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -39,11 +39,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, @@ -68,7 +68,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, }; @@ -396,6 +396,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]); } @@ -407,7 +408,6 @@ 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); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 11356e8b155..be5d4e3fa74 100755..100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -118,7 +118,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &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 +229,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::EffectNULL, //165 SPELL_EFFECT_165 + &Spell::EffectNULL, //166 SPELL_EFFECT_166 + &Spell::EffectNULL, //167 SPELL_EFFECT_167 + &Spell::EffectNULL, //168 SPELL_EFFECT_168 + &Spell::EffectNULL, //169 SPELL_EFFECT_169 + &Spell::EffectNULL, //170 SPELL_EFFECT_170 + &Spell::EffectNULL, //171 SPELL_EFFECT_171 + &Spell::EffectNULL, //172 SPELL_EFFECT_172 + &Spell::EffectNULL, //173 SPELL_EFFECT_173 + &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::EffectNULL, //179 SPELL_EFFECT_179 + &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*/) @@ -365,15 +383,8 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) } case SPELLFAMILY_WARRIOR: { - // Shield Slam - if (m_spellInfo->SpellFamilyFlags[1] & 0x200 && m_spellInfo->Category == 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->SpellFamilyFlags[1] & 0x100) ApplyPctF(damage, m_caster->GetTotalAttackPowerValue(BASE_ATTACK)); // Shockwave else if (m_spellInfo->Id == 46968) @@ -390,73 +401,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(CalculatePctU(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(CalculatePctU(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; @@ -487,20 +437,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(CalculatePctN(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)) - AddPctN(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 + AddPctN(damage, energy * 4); } break; } @@ -580,62 +520,6 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) 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) - { - // Add main hand dps * effect[2] amount - float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2; - 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 += CalculatePctN(block_value, m_spellInfo->Effects[EFFECT_1].CalcValue()); - break; - } break; } case SPELLFAMILY_DEATHKNIGHT: @@ -810,15 +694,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: { @@ -851,10 +726,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: { @@ -1529,22 +1400,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()) - AddPctN(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); @@ -1694,7 +1549,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 { @@ -1864,13 +1719,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(CalculatePctN(unitTarget->GetCreateMana(), damage)); break; - case 48542: // Revitalize - damage = int32(CalculatePctN(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()) @@ -1878,9 +1730,6 @@ void Spell::EffectEnergize(SpellEffIndex effIndex) AddPctN(damage, 25); break; } - case 71132: // Glyph of Shadow Word: Pain - damage = int32(CalculatePctN(unitTarget->GetCreateMana(), 1)); // set 1 as value, missing in dbc - break; default: break; } @@ -2221,9 +2070,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()) @@ -2563,7 +2412,7 @@ void Spell::EffectDispel(SpellEffIndex effIndex) // Devour Magic if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 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()) @@ -2753,7 +2602,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) Player* p_caster = (Player*)m_caster; // Handle vellums - if (itemTarget->IsWeaponVellum() || itemTarget->IsArmorVellum()) + if (itemTarget->IsVellum()) { // destroy one vellum from stack uint32 count = 1; @@ -2878,58 +2727,6 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex) Player* p_caster = (Player*)m_caster; - // 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: - sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW", damage); - return; - } - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id); - if (!spellInfo) - { - sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id); - return; - - } - - for (int j = BASE_ATTACK; j <= OFF_ATTACK; ++j) - { - if (Item* item = p_caster->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; @@ -3180,9 +2977,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()) { @@ -3262,74 +3056,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: @@ -3360,54 +3106,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)) - AddPctN(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)) AddPctF(bonusPct, aurEff->GetAmount()); AddPctF(totalDamagePercentMod, bonusPct); - - // Glyph of Blood Strike - if (m_caster->GetAuraEffect(59332, EFFECT_0)) - if (unitTarget->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED)) - AddPctN(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))) AddPctN(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)) AddPctF(bonusPct, aurEff->GetAmount()); @@ -3423,7 +3150,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)) AddPctF(bonusPct, aurEff->GetAmount()); @@ -4659,12 +4386,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); @@ -4686,7 +4417,7 @@ 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)) { @@ -5109,6 +4840,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(); } @@ -6258,7 +5990,7 @@ void Spell::EffectCastButtons(SpellEffIndex effIndex) if (!(spellInfo->AttributesEx7 & SPELL_ATTR7_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; @@ -6322,7 +6054,7 @@ void Spell::EffectBind(SpellEffIndex effIndex) loc.m_positionX = st->target_X; loc.m_positionY = st->target_Y; loc.m_positionZ = st->target_Z; - loc.m_orientation = st->target_Orientation; + loc.SetOrientation(st->target_Orientation); area_id = player->GetAreaId(); } else diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 7b3f9a1bef9..8fa008da823 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -319,29 +319,35 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_ SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex) { + SpellEffectEntry const* _effect = spellEntry->GetSpellEffect(effIndex); + 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]; + 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; + 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 @@ -361,7 +367,7 @@ bool SpellEffectInfo::IsAura() const bool SpellEffectInfo::IsAura(AuraType aura) const { - return IsAura() && ApplyAuraName == aura; + return IsAura() && AuraType(ApplyAuraName) == aura; } bool SpellEffectInfo::IsTargetingArea() const @@ -400,37 +406,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 = DeltaScalingMultiplier * ScalingMultiplier * multiplier * 0.5f; + preciseBasePoints += frand(-delta, delta); + } + + basePoints = int32(preciseBasePoints); - // roll in a range <1;EffectDieSides> as of patch 3.3.3 - switch (randomPoints) + 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); @@ -439,15 +481,14 @@ 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 - if (!basePointsPerLevel && (_spellInfo->Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION && _spellInfo->SpellLevel) && + 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 && @@ -496,8 +537,8 @@ float SpellEffectInfo::CalcRadius(Unit* caster, Spell* spell) const { if (!HasRadius()) return 0.0f; - - float radius = RadiusEntry->radiusMax; + //TODO: FIX radius value + float radius = RadiusEntry->ID; if (Player* modOwner = (caster ? caster->GetSpellModOwner() : NULL)) modOwner->ApplySpellMod(_spellInfo->Id, SPELLMOD_RADIUS, radius, spell); @@ -716,9 +757,6 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] = SpellInfo::SpellInfo(SpellEntry const* spellEntry) { Id = spellEntry->Id; - Category = spellEntry->Category; - Dispel = spellEntry->Dispel; - Mechanic = spellEntry->Mechanic; Attributes = spellEntry->Attributes; AttributesEx = spellEntry->AttributesEx; AttributesEx2 = spellEntry->AttributesEx2; @@ -727,75 +765,147 @@ 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); + + // 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(); + Category = _categorie ? _categorie->Category : 0; + 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; + ExplicitTargetMask = _GetExplicitTargetMask(); ChainEntry = NULL; } @@ -1230,6 +1340,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: @@ -1256,10 +1367,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) { sLog->outError(LOG_FILTER_SPELLS_AURAS, "GetErrorAtShapeshiftedCast: unknown shapeshift %u", form); @@ -1411,17 +1522,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; + } } } } @@ -1828,6 +1949,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; @@ -1959,11 +2084,20 @@ int32 SpellInfo::GetMaxDuration() const uint32 SpellInfo::CalcCastTime(Unit* caster, Spell* spell) const { + int32 castTime = 0; + // not all spells have cast time index and this is all is pasiive abilities - if (!CastTimeEntry) - return 0; + if (caster && CastTimeMax > 0) + { + castTime = CastTimeMax; + if (CastTimeMaxLevel > int32(caster->getLevel())) + castTime = CastTimeMin + int32(caster->getLevel() - 1) * (CastTimeMax - CastTimeMin) / (CastTimeMaxLevel - 1); + } + else if (CastTimeEntry) + castTime = CastTimeEntry->CastTime; - int32 castTime = CastTimeEntry->CastTime; + if (!castTime) + return 0; if (caster) caster->ModSpellCastTime(this, castTime, spell); @@ -2038,10 +2172,9 @@ uint32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) case POWER_RAGE: case POWER_FOCUS: case POWER_ENERGY: - case POWER_HAPPINESS: powerCost += int32(CalculatePctU(caster->GetMaxPower(Powers(PowerType)), ManaCostPercentage)); break; - case POWER_RUNE: + case POWER_RUNES: case POWER_RUNIC_POWER: sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "CalculateManaCost: Not implemented yet!"); break; @@ -2119,7 +2252,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; @@ -2482,6 +2616,86 @@ 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; +} + +SpellEffectEntry const* SpellEntry::GetSpellEffect(uint32 eff) const +{ + return GetSpellEffectEntry(Id, eff); +} + 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 54430cd7116..1161ac23aa3 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -60,7 +60,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,6 +166,8 @@ enum SpellSpecificType SPELL_SPECIFIC_WARRIOR_ENRAGE = 26, SPELL_SPECIFIC_PRIEST_DIVINE_SPIRIT = 27, SPELL_SPECIFIC_HAND = 28, + SPELL_SPECIFIC_PHASE = 29, + SPELL_SPECIFIC_BANE = 30, }; enum SpellCustomAttributes @@ -249,6 +251,10 @@ public: uint32 TriggerSpell; flag96 SpellClassMask; std::list<Condition*>* ImplicitTargetConditions; + // SpellScalingEntry + float ScalingMultiplier; + float DeltaScalingMultiplier; + float ComboScalingMultiplier; SpellEffectInfo() {} SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex); @@ -301,6 +307,9 @@ public: uint32 AttributesEx5; uint32 AttributesEx6; uint32 AttributesEx7; + uint32 AttributesEx8; + uint32 AttributesEx9; + uint32 AttributesEx10; uint32 AttributesCu; uint32 Stances; uint32 StancesNot; @@ -335,7 +344,6 @@ public: uint32 ManaCost; uint32 ManaCostPerlevel; uint32 ManaPerSecond; - uint32 ManaPerSecondPerLevel; uint32 ManaCostPercentage; uint32 RuneCostID; SpellRangeEntry const* RangeEntry; @@ -351,8 +359,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; @@ -361,10 +369,50 @@ 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; + // 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); ~SpellInfo(); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index b580c5e2282..c160673ae66 100755..100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1160,7 +1160,7 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32 // team that controls the workshop in the specified area uint32 team = bf->GetData(newArea); - + if (team == TEAM_HORDE) return spellId == 56618; else if (team == TEAM_ALLIANCE) @@ -2636,7 +2636,7 @@ void SpellMgr::LoadSpellInfoStore() mSpellInfoMap[i] = new SpellInfo(spellEntry); } - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded spell custom attributes in %u ms", GetMSTimeDiffToNow(oldMSTime)); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded spell info store in %u ms", GetMSTimeDiffToNow(oldMSTime)); } void SpellMgr::UnloadSpellInfoStore() @@ -2955,7 +2955,7 @@ void SpellMgr::LoadDbcDataCorrections() { uint32 oldMSTime = getMSTime(); - SpellEntry* spellInfo = NULL; + /*SpellEntry* spellInfo = NULL; for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i) { spellInfo = (SpellEntry*)sSpellStore.LookupEntry(i); @@ -3248,6 +3248,12 @@ void SpellMgr::LoadDbcDataCorrections() case 53246: // Marked for Death (Rank 5) spellInfo->EffectSpellClassMask[0] = flag96(0x00067801, 0x10820001, 0x00000801); break; + case 5176: // Wrath + case 2912: // Starfire + case 78674: // Starsurge + spellInfo->Effects[1].Effect = SPELL_EFFECT_DUMMY; + spellInfo->Effects[1].TargetA = TARGET_UNIT_CASTER; + break; case 70728: // Exploit Weakness (needs target selection script) case 70840: // Devious Minds (needs target selection script) spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_CASTER; @@ -3602,6 +3608,6 @@ void SpellMgr::LoadDbcDataCorrections() properties->Type = SUMMON_TYPE_TOTEM; properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(647)); // 52893 properties->Type = SUMMON_TYPE_TOTEM; - + */ sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loading spell dbc data corrections in %u ms", GetMSTimeDiffToNow(oldMSTime)); } diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp index 0a4682db759..220d348fba2 100755 --- a/src/server/game/Tickets/TicketMgr.cpp +++ b/src/server/game/Tickets/TicketMgr.cpp @@ -31,34 +31,34 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; } // GM ticket GmTicket::GmTicket() { } -GmTicket::GmTicket(Player* player, WorldPacket& recv_data) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED) +GmTicket::GmTicket(Player* player, WorldPacket& recvData) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED) { _id = sTicketMgr->GenerateTicketId(); _playerName = player->GetName(); _playerGuid = player->GetGUID(); uint32 mapId; - recv_data >> mapId; // Map is sent as UInt32! + recvData >> mapId; // Map is sent as UInt32! _mapId = mapId; - recv_data >> _posX; - recv_data >> _posY; - recv_data >> _posZ; - recv_data >> _message; + recvData >> _posX; + recvData >> _posY; + recvData >> _posZ; + recvData >> _message; uint32 needResponse; - recv_data >> needResponse; + recvData >> needResponse; _needResponse = (needResponse == 17); // Requires GM response. 17 = true, 1 = false (17 is default) uint8 unk1; - recv_data >> unk1; // Requests further GM interaction on a ticket to which a GM has already responded + recvData >> unk1; // Requests further GM interaction on a ticket to which a GM has already responded - recv_data.rfinish(); + recvData.rfinish(); /* - recv_data >> uint32(count); // text lines + recvData >> count; // text lines for (int i = 0; i < count; i++) - recv_data >> uint32(); + recvData >> uint32(); if (something) - recv_data >> uint32(); + recvData >> uint32(); else compressed uint32 + string; */ @@ -373,12 +373,12 @@ void TicketMgr::SendTicket(WorldSession* session, GmTicket* ticket) const status = GMTICKET_STATUS_HASTEXT; } - WorldPacket data(SMSG_GMTICKET_GETTICKET, (4 + 4 + (ticket ? message.length() + 1 + 4 + 4 + 4 + 1 + 1 : 0))); + WorldPacket data(SMSG_GMTICKET_GETTICKET, (4 + (ticket ? 4 + message.length() + 1 + 4 + 4 + 4 + 1 + 1 : 0))); data << uint32(status); // standard 0x0A, 0x06 if text present - data << uint32(ticket ? ticket->GetId() : 0); // ticketID if (ticket) { + data << uint32(ticket->GetId()); // ticketID data << message.c_str(); // ticket text data << uint8(0x7); // ticket category; why is this hardcoded? does it make a diff re: client? @@ -386,5 +386,6 @@ void TicketMgr::SendTicket(WorldSession* session, GmTicket* ticket) const // Now we need to go through the client logic for displaying various levels of ticket load ticket->WritePacket(data); } + session->SendPacket(&data); } diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h index be8b4063d84..0e78ac72692 100755 --- a/src/server/game/Tickets/TicketMgr.h +++ b/src/server/game/Tickets/TicketMgr.h @@ -82,7 +82,7 @@ class GmTicket { public: GmTicket(); - explicit GmTicket(Player* player, WorldPacket& recv_data); + explicit GmTicket(Player* player, WorldPacket& recvData); ~GmTicket(); bool IsClosed() const { return _closedBy; } diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index f6d0de28d28..2907292f5a6 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -320,7 +320,10 @@ bool PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl case DTT_CHARACTER: { if (result->GetFieldCount() <= 68) // avoid crashes on next check + { sLog->outFatal(LOG_FILTER_GENERAL, "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 return false; diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp index f6daba76c1a..6eca93dc4b5 100644 --- a/src/server/game/Warden/WardenCheckMgr.cpp +++ b/src/server/game/Warden/WardenCheckMgr.cpp @@ -52,7 +52,7 @@ void WardenCheckMgr::LoadWardenChecks() if (!result) { - sLog->outInfo(LOG_FILTER_WARDEN, ">> Loaded 0 Warden checks. DB table `warden_checks` is empty!"); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 Warden checks. DB table `warden_checks` is empty!"); return; } @@ -164,7 +164,7 @@ void WardenCheckMgr::LoadWardenOverrides() if (!result) { - sLog->outInfo(LOG_FILTER_WARDEN, ">> Loaded 0 Warden action overrides. DB table `warden_action` is empty!"); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 Warden action overrides. DB table `warden_action` is empty!"); return; } diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp index da62122d7a3..fce078a0a14 100755 --- a/src/server/game/Weather/WeatherMgr.cpp +++ b/src/server/game/Weather/WeatherMgr.cpp @@ -93,7 +93,7 @@ void LoadWeatherData() if (!result) { - sLog->outError(LOG_FILTER_SQL, ">> Loaded 0 weather definitions. DB table `game_weather` is empty."); + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 weather definitions. DB table `game_weather` is empty."); return; } diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 9814ddf57ad..0a9af095352 100755..100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -40,11 +40,11 @@ #include "ArenaTeamMgr.h" #include "GuildMgr.h" #include "TicketMgr.h" -#include "CreatureEventAIMgr.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" @@ -272,7 +272,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(); @@ -328,7 +328,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) @@ -770,14 +770,14 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_START_PLAYER_MONEY] = ConfigMgr::GetIntDefault("StartPlayerMoney", 0); if (int32(m_int_configs[CONFIG_START_PLAYER_MONEY]) < 0) { - sLog->outError(LOG_FILTER_SERVER_LOADING, "StartPlayerMoney (%i) must be in range 0..%u. Set to %u.", m_int_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, 0); - m_int_configs[CONFIG_START_PLAYER_MONEY] = 0; + sLog->outError(LOG_FILTER_SERVER_LOADING, "StartPlayerMoney (%i) must be in range 0.." UI64FMTD ". Set to %u.", m_int_configs[CONFIG_START_PLAYER_MONEY], 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) { sLog->outError(LOG_FILTER_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] = ConfigMgr::GetIntDefault("MaxHonorPoints", 75000); @@ -1197,6 +1197,9 @@ void World::LoadConfigSettings(bool reload) // MySQL ping time interval m_int_configs[CONFIG_DB_PING_INTERVAL] = ConfigMgr::GetIntDefault("MaxPingTime", 30); + // Guild save interval + m_int_configs[CONFIG_GUILD_SAVE_INTERVAL] = ConfigMgr::GetIntDefault("GuildSaveInterval", 15); + // misc m_bool_configs[CONFIG_PDUMP_NO_PATHS] = ConfigMgr::GetBoolDefault("PlayerDump.DisallowPaths", true); m_bool_configs[CONFIG_PDUMP_NO_OVERWRITE] = ConfigMgr::GetBoolDefault("PlayerDump.DisallowOverwrite", true); @@ -1209,7 +1212,7 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_WINTERGRASP_BATTLETIME] = ConfigMgr::GetIntDefault("Wintergrasp.BattleTimer", 30); m_int_configs[CONFIG_WINTERGRASP_NOBATTLETIME] = ConfigMgr::GetIntDefault("Wintergrasp.NoBattleTimer", 150); m_int_configs[CONFIG_WINTERGRASP_RESTART_AFTER_CRASH] = ConfigMgr::GetIntDefault("Wintergrasp.CrashRestartTimer", 10); - + if (reload) sScriptMgr->OnConfigLoad(reload); } @@ -1265,12 +1268,7 @@ void World::SetInitialWorldSettings() //No SQL injection as values are treated as integers // not send custom type REALM_FFA_PVP to realm list - uint32 server_type; - if (IsFFAPvPRealm()) - server_type = REALM_TYPE_PVP; - else - server_type = getIntConfig(CONFIG_GAME_TYPE); - + uint32 server_type = IsFFAPvPRealm() ? uint32(REALM_TYPE_PVP) : getIntConfig(CONFIG_GAME_TYPE); uint32 realm_zone = getIntConfig(CONFIG_REALM_ZONE); LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID); // One-time query @@ -1283,6 +1281,7 @@ void World::SetInitialWorldSettings() ///- Load the DBC files sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Initialize data stores..."); LoadDBCStores(m_dataPath); + LoadDB2Stores(m_dataPath); DetectDBCLang(); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading spell dbc data corrections..."); @@ -1315,7 +1314,6 @@ void World::SetInitialWorldSettings() sObjectMgr->LoadCreatureLocales(); sObjectMgr->LoadGameObjectLocales(); sObjectMgr->LoadItemLocales(); - sObjectMgr->LoadItemSetNameLocales(); sObjectMgr->LoadQuestLocales(); sObjectMgr->LoadNpcTextLocales(); sObjectMgr->LoadPageTextLocales(); @@ -1372,13 +1370,16 @@ void World::SetInitialWorldSettings() LoadRandomEnchantmentsTable(); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Disables"); - DisableMgr::LoadDisables(); // must be before loading quests and items + DisableMgr::LoadDisables(); // must be before loading quests and items sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Items..."); // must be after LoadRandomEnchantmentsTable and LoadPageTexts sObjectMgr->LoadItemTemplates(); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Item set names..."); // must be after LoadItemPrototypes - sObjectMgr->LoadItemSetNames(); + sObjectMgr->LoadItemTemplateAddon(); + + sLog->outInfo(LOG_FILTER_GENERAL, "Loading Item Scripts..."); // must be after LoadItemPrototypes + sObjectMgr->LoadItemScriptNames(); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Creature Model Based Info Data..."); sObjectMgr->LoadCreatureModelInfo(); @@ -1638,15 +1639,6 @@ void World::SetInitialWorldSettings() sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Scripts text locales..."); // must be after Load*Scripts calls sObjectMgr->LoadDbScriptStrings(); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading CreatureEventAI Texts..."); - sEventAIMgr->LoadCreatureEventAI_Texts(); - - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading CreatureEventAI Summons..."); - sEventAIMgr->LoadCreatureEventAI_Summons(); - - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading CreatureEventAI Scripts..."); - sEventAIMgr->LoadCreatureEventAI_Scripts(); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading spell script names..."); sObjectMgr->LoadSpellScriptNames(); @@ -1690,6 +1682,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) @@ -1733,7 +1727,7 @@ void World::SetInitialWorldSettings() ///- Initialize Battlefield sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Starting Battlefield System"); sBattlefieldMgr->InitBattlefield(); - + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Transports..."); sMapMgr->LoadTransports(); @@ -1761,6 +1755,12 @@ void World::SetInitialWorldSettings() LoadCharacterNameData(); + sLog->outInfo(LOG_FILTER_GENERAL, "Initializing Opcodes..."); + InitOpcodes(); + + sLog->outInfo(LOG_FILTER_GENERAL, "Loading hotfix info..."); + sObjectMgr->LoadHotfixData(); + uint32 startupDuration = GetMSTimeDiffToNow(startupBegin); sLog->outInfo(LOG_FILTER_WORLDSERVER, "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000)); @@ -1769,15 +1769,15 @@ void World::SetInitialWorldSettings() void World::DetectDBCLang() { - uint8 m_lang_confid = ConfigMgr::GetIntDefault("DBC.Locale", 255); + uint8 m_lang_confid = ConfigMgr::GetIntDefault("DBC.Locale", 0); - if (m_lang_confid != 255 && m_lang_confid >= TOTAL_LOCALES) + if (m_lang_confid >= TOTAL_LOCALES) { sLog->outError(LOG_FILTER_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); + /*ChrRacesEntry const* race = sChrRacesStore.LookupEntry(1); std::string availableLocalsStr; @@ -1803,12 +1803,11 @@ void World::DetectDBCLang() { sLog->outError(LOG_FILTER_SERVER_LOADING, "Unable to determine your DBC Locale! (corrupt DBC?)"); exit(1); - } + }*/ - m_defaultDbcLocale = LocaleConstant(default_locale); - - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Using %s DBC Locale as default. All available DBC locales: %s", localeNames[m_defaultDbcLocale], availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str()); + m_defaultDbcLocale = LocaleConstant(m_lang_confid); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Using %s DBC Locale", localeNames[m_defaultDbcLocale]); } void World::RecordTimeDiff(const char *text, ...) @@ -2041,6 +2040,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(); @@ -2610,8 +2615,10 @@ void World::SendAutoBroadcast() 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); } @@ -2619,8 +2626,10 @@ void World::SendAutoBroadcast() { 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); } @@ -2812,8 +2821,8 @@ void World::LoadDBVersion() if (result) { Field* fields = result->Fetch(); - m_DBVersion = fields[0].GetString(); + m_DBVersion = fields[0].GetString(); // will be overwrite by config values if different and non-0 m_int_configs[CONFIG_CLIENTCACHE_VERSION] = fields[1].GetUInt32(); } diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index a6cdd4742f6..b25444f4865 100755 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -45,11 +45,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 @@ -78,6 +86,7 @@ enum WorldTimers WUPDATE_MAILBOXQUEUE, WUPDATE_DELETECHARS, WUPDATE_PINGDB, + WUPDATE_GUILDSAVE, WUPDATE_COUNT }; @@ -218,8 +227,10 @@ enum WorldIntConfigs CONFIG_START_PLAYER_MONEY, CONFIG_MAX_HONOR_POINTS, CONFIG_START_HONOR_POINTS, - CONFIG_MAX_ARENA_POINTS, - CONFIG_START_ARENA_POINTS, + CONFIG_MAX_JUSTICE_POINTS, + CONFIG_START_JUSTICE_POINTS, + CONFIG_MAX_ARENA_POINTS,//todo: remove + CONFIG_START_ARENA_POINTS,//todo: remove CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL, CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE, CONFIG_INSTANCE_RESET_TIME_HOUR, @@ -325,6 +336,7 @@ enum WorldIntConfigs CONFIG_WINTERGRASP_BATTLETIME, CONFIG_WINTERGRASP_NOBATTLETIME, CONFIG_WINTERGRASP_RESTART_AFTER_CRASH, + CONFIG_GUILD_SAVE_INTERVAL, INT_CONFIG_VALUE_COUNT }; @@ -635,7 +647,7 @@ class World /// Get the maximum skill level a player can reach uint16 GetConfigMaxSkillValue() const { - uint8 lvl = getIntConfig(CONFIG_MAX_PLAYER_LEVEL); + uint8 lvl = uint8(getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); return lvl > 60 ? 300 + ((lvl - 60) * 75) / 10 : lvl*5; } |
