diff options
| author | Spp <spp@jorge.gr> | 2012-02-23 13:06:35 +0100 |
|---|---|---|
| committer | Spp <spp@jorge.gr> | 2012-02-23 13:06:35 +0100 |
| commit | 5cff9e071640bc47688b71bb264edd8267ba77c3 (patch) | |
| tree | c599d12dfb7870d7c34a07490a930b3102c3d8ac /src/server/game | |
| parent | f0ca875a216eaab3d213feae8ba75c07795c9304 (diff) | |
| parent | 9219625243bc9f63e5a152e6cda1043cfaade201 (diff) | |
Merge branch 'master' into 4.x
Conflicts:
sql/base/auth_database.sql
src/server/authserver/Server/AuthSocket.cpp
src/server/game/AI/CoreAI/CombatAI.cpp
src/server/game/AuctionHouse/AuctionHouseMgr.cpp
src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
src/server/game/DataStores/DBCStructure.h
src/server/game/DataStores/DBCfmt.h
src/server/game/Entities/Unit/Unit.cpp
src/server/game/Entities/Vehicle/Vehicle.cpp
src/server/game/Globals/ObjectMgr.cpp
src/server/game/Globals/ObjectMgr.h
src/server/game/Handlers/AuctionHouseHandler.cpp
src/server/game/Miscellaneous/SharedDefines.h
src/server/game/Movement/MotionMaster.cpp
src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
src/server/game/Quests/QuestDef.cpp
src/server/game/Server/Protocol/Opcodes.cpp
src/server/game/Server/WorldSocket.cpp
src/server/game/Spells/Spell.cpp
src/server/game/Spells/SpellEffects.cpp
src/server/game/Spells/SpellInfo.cpp
src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp
src/server/scripts/Spells/spell_quest.cpp
src/server/shared/Logging/Log.h
src/server/worldserver/worldserver.conf.dist
src/tools/vmap3_extractor/model.h
src/tools/vmap4_extractor/CMakeLists.txt
src/tools/vmap4_extractor/dbcfile.cpp
src/tools/vmap4_extractor/dbcfile.h
src/tools/vmap4_extractor/loadlib/loadlib.h
Diffstat (limited to 'src/server/game')
136 files changed, 9868 insertions, 5747 deletions
diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp index e178efc7eee..86f2c6a28b7 100755 --- a/src/server/game/AI/CoreAI/CombatAI.cpp +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -158,6 +158,12 @@ void CasterAI::UpdateAI(const uint32 diff) events.Update(diff); + if (me->getVictim()->HasBreakableByDamageCrowdControlAura(me)) + { + me->InterruptNonMeleeSpells(false); + return; + } + if (me->HasUnitState(UNIT_STATE_CASTING)) return; @@ -320,7 +326,7 @@ void VehicleAI::CheckConditions(const uint32 diff) { if (Player* player = passenger->ToPlayer()) { - if (!sConditionMgr->IsPlayerMeetToConditions(player, conditions)) + if (!sConditionMgr->IsObjectMeetToConditions(player, me, conditions)) { player->ExitVehicle(); return;//check other pessanger in next tick diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 83a89a966c5..30ebd06745f 100755 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -42,7 +42,6 @@ PetAI::PetAI(Creature* c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK) { m_AllySet.clear(); UpdateAllies(); - targetHasCC = false; } void PetAI::EnterEvadeMode() @@ -55,9 +54,6 @@ bool PetAI::_needToStop() if (me->isCharmed() && me->getVictim() == me->GetCharmer()) return true; - if (_CheckTargetCC(me->getVictim()) && !targetHasCC) - return true; - return !me->IsValidAttackTarget(me->getVictim()); } @@ -95,13 +91,19 @@ void PetAI::UpdateAI(const uint32 diff) // me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc. if (me->getVictim()) { + // is only necessary to stop casting, the pet must not exit combat + if (me->getVictim()->HasBreakableByDamageCrowdControlAura(me)) + { + me->InterruptNonMeleeSpells(false); + return; + } + if (_needToStop()) { sLog->outStaticDebug("Pet AI stopped attacking [guid=%u]", me->GetGUIDLow()); _stopAttack(); return; } - targetHasCC = _CheckTargetCC(me->getVictim()); DoMeleeAttackIfReady(); } @@ -293,8 +295,6 @@ void PetAI::AttackStart(Unit* target) if (!CanAttack(target)) return; - targetHasCC = _CheckTargetCC(target); - if (Unit* owner = me->GetOwner()) owner->SetInCombatWith(target); @@ -310,22 +310,21 @@ Unit* PetAI::SelectNextTarget() return NULL; Unit* target = me->getAttackerForHelper(); - targetHasCC = false; // Check pet's attackers first to prevent dragging mobs back to owner - if (target && !_CheckTargetCC(target)) + if (target && !target->HasBreakableByDamageCrowdControlAura()) return target; if (me->GetCharmerOrOwner()) { // Check owner's attackers if pet didn't have any target = me->GetCharmerOrOwner()->getAttackerForHelper(); - if (target && !_CheckTargetCC(target)) + if (target && !target->HasBreakableByDamageCrowdControlAura()) return target; // 3.0.2 - Pets now start attacking their owners target in defensive mode as soon as the hunter does target = me->GetCharmerOrOwner()->getVictim(); - if (target && !_CheckTargetCC(target)) + if (target && !target->HasBreakableByDamageCrowdControlAura()) return target; } @@ -467,11 +466,3 @@ bool PetAI::CanAttack(Unit* target) // default, though we shouldn't ever get here return false; } - -bool PetAI::_CheckTargetCC(Unit* target) -{ - if (me->GetCharmerOrOwnerGUID() && target->HasNegativeAuraWithAttribute(SPELL_ATTR0_BREAKABLE_BY_DAMAGE, me->GetCharmerOrOwnerGUID())) - return true; - - return false; -} diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h index 847b4140285..730ab12a3ca 100755 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -50,7 +50,6 @@ class PetAI : public CreatureAI TimeTracker i_tracker; bool inCombat; - bool targetHasCC; std::set<uint64> m_AllySet; uint32 m_updateAlliesTimer; @@ -58,7 +57,6 @@ class PetAI : public CreatureAI void HandleReturnMovement(); void DoAttack(Unit* target, bool chase); bool CanAttack(Unit* target); - bool _CheckTargetCC(Unit* target); }; #endif diff --git a/src/server/game/AI/EventAI/CreatureEventAI.cpp b/src/server/game/AI/EventAI/CreatureEventAI.cpp index ce46d51f579..bc1903257b7 100755 --- a/src/server/game/AI/EventAI/CreatureEventAI.cpp +++ b/src/server/game/AI/EventAI/CreatureEventAI.cpp @@ -1334,11 +1334,12 @@ void CreatureEventAI::ReceiveEmote(Player* player, uint32 textEmote) return; Condition cond; - cond.mConditionType = ConditionType((*itr).Event.receive_emote.condition); - cond.mConditionValue1 = (*itr).Event.receive_emote.conditionValue1; - cond.mConditionValue2 = (*itr).Event.receive_emote.conditionValue2; + cond.ConditionType = ConditionTypes((*itr).Event.receive_emote.condition); + cond.ConditionValue1 = (*itr).Event.receive_emote.conditionValue1; + cond.ConditionValue2 = (*itr).Event.receive_emote.conditionValue2; - if (cond.Meets(player)) + ConditionSourceInfo srcInfo = ConditionSourceInfo(player); + if (cond.Meets(srcInfo)) { sLog->outDebug(LOG_FILTER_DATABASE_AI, "CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing"); ProcessEvent(*itr, player); diff --git a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp index 8f2cf6b471f..add7b4db174 100755 --- a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp +++ b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp @@ -359,9 +359,9 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() if (temp.receive_emote.condition) { Condition cond; - cond.mConditionType = ConditionType(temp.receive_emote.condition); - cond.mConditionValue1 = temp.receive_emote.conditionValue1; - cond.mConditionValue2 = temp.receive_emote.conditionValue2; + cond.ConditionType = ConditionTypes(temp.receive_emote.condition); + cond.ConditionValue1 = temp.receive_emote.conditionValue1; + cond.ConditionValue2 = temp.receive_emote.conditionValue2; if (!sConditionMgr->isConditionTypeValid(&cond)) { sLog->outErrorDb("CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not valid.", temp.creature_id, i, temp.receive_emote.condition); diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index d4b2a9746be..7838e6891fe 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -68,6 +68,7 @@ SmartAI::SmartAI(Creature* c) : CreatureAI(c) mFollowCredit = 0; mFollowArrivedEntry = 0; mFollowCreditType = 0; + mInvinceabilityHpLevel = 0; } void SmartAI::UpdateDespawn(const uint32 diff) @@ -449,7 +450,7 @@ void SmartAI::EnterEvadeMode() return; RemoveAuras(); - + me->DeleteThreatList(); me->CombatStop(true); me->LoadCreaturesAddon(); @@ -479,15 +480,15 @@ void SmartAI::MoveInLineOfSight(Unit* who) { if (!who) return; - + GetScript()->OnMoveInLineOfSight(who); - + if (me->HasReactState(REACT_PASSIVE) || AssistPlayerInCombat(who)) return; if (!CanAIAttack(who)) return; - + if (!me->canStartAttack(who, false)) return; @@ -637,6 +638,8 @@ void SmartAI::SpellHitTarget(Unit* target, const SpellInfo* spellInfo) void SmartAI::DamageTaken(Unit* doneBy, uint32& damage) { GetScript()->ProcessEventsFor(SMART_EVENT_DAMAGED, doneBy, damage); + if ((me->GetHealth() - damage) <= mInvinceabilityHpLevel) + damage -= mInvinceabilityHpLevel; } void SmartAI::HealReceived(Unit* doneBy, uint32& addhealth) @@ -824,7 +827,7 @@ void SmartAI::SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker) GetScript()->mLastInvoker = invoker->GetGUID(); GetScript()->SetScript9(e, entry); } - + void SmartAI::sOnGameEvent(bool start, uint16 eventId) { GetScript()->ProcessEventsFor(start ? SMART_EVENT_GAME_EVENT_START : SMART_EVENT_GAME_EVENT_END, NULL, eventId); diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index 0576612a155..e82b35ec87a 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -175,6 +175,8 @@ class SmartAI : public CreatureAI void SetSwim(bool swim = true); + void SetInvinceabilityHpLevel(uint32 level) { mInvinceabilityHpLevel = level; } + void sGossipHello(Player* player); void sGossipSelect(Player* player, uint32 sender, uint32 action); void sGossipSelectCode(Player* player, uint32 sender, uint32 action, const char* code); @@ -193,7 +195,7 @@ class SmartAI : public CreatureAI mDespawnState = t ? 1 : 0; } void StartDespawn() { mDespawnState = 2; } - + void RemoveAuras(); private: @@ -222,6 +224,7 @@ class SmartAI : public CreatureAI bool mCanAutoAttack; bool mCanCombatMove; bool mForcedPaused; + uint32 mInvinceabilityHpLevel; bool AssistPlayerInCombat(Unit* who); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 04b1fa2b2e7..67d26ea06dd 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -39,7 +39,6 @@ SmartScript::SmartScript() go = NULL; me = NULL; mEventPhase = 0; - mInvinceabilityHpLevel = 0; mPathId = 0; mTargetStorage = new ObjectListMap(); mStoredEvents.clear(); @@ -86,15 +85,10 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3 if (eventType == e/* && (!(*i).event.event_phase_mask || IsInPhase((*i).event.event_phase_mask)) && !((*i).event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && (*i).runOnce)*/) { bool meets = true; - if (unit) - { - if (Player* player = unit->ToPlayer()) - { - ConditionList conds = sConditionMgr->GetConditionsForSmartEvent((*i).entryOrGuid, (*i).event_id, (*i).source_type); - meets = sConditionMgr->IsPlayerMeetToConditions(player, conds); - } - } - + ConditionList conds = sConditionMgr->GetConditionsForSmartEvent((*i).entryOrGuid, (*i).event_id, (*i).source_type); + ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject()); + meets = sConditionMgr->IsObjectMeetToConditions(info, conds); + if (meets) ProcessEvent(*i, unit, var0, var1, bvar, spell, gob); } @@ -485,7 +479,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) me->InterruptNonMeleeSpells(false); - me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false); + if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell)) + me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false); + else + sLog->outDebug(LOG_FILTER_DATABASE_AI, "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId())); sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_CAST:: Creature %u casts spell %u on target %u with castflags %u", me->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags); } @@ -511,7 +508,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) tempLastInvoker->InterruptNonMeleeSpells(false); - tempLastInvoker->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false); + if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell)) + tempLastInvoker->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false); + else + sLog->outDebug(LOG_FILTER_DATABASE_AI, "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId())); + sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_INVOKER_CAST: Invoker %u casts spell %u on target %u with castflags %u", tempLastInvoker->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags); } @@ -992,10 +993,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!me) break; + SmartAI* ai = CAST_AI(SmartAI, me->AI()); + + if (!ai) + break; + if (e.action.invincHP.percent) - mInvinceabilityHpLevel = me->CountPctFromMaxHealth(e.action.invincHP.percent); + ai->SetInvinceabilityHpLevel(me->CountPctFromMaxHealth(e.action.invincHP.percent)); else - mInvinceabilityHpLevel = e.action.invincHP.minHP; + ai->SetInvinceabilityHpLevel(e.action.invincHP.minHP); break; } case SMART_ACTION_SET_DATA: @@ -1564,8 +1570,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u (*itr)->ToUnit()->InterruptNonMeleeSpells(false); for (ObjectList::const_iterator it = targets->begin(); it != targets->end(); ++it) + { if (IsUnit(*it)) - (*itr)->ToUnit()->CastSpell((*it)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false); + { + if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*it)->ToUnit()->HasAura(e.action.cast.spell)) + (*itr)->ToUnit()->CastSpell((*it)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false); + else + sLog->outDebug(LOG_FILTER_DATABASE_AI, "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*it)->GetGUID(), (*it)->GetEntry(), uint32((*it)->GetTypeId())); + } + } } } @@ -2779,6 +2792,19 @@ void SmartScript::InstallEvents() } } +bool SmartScript::ConditionValid(Unit* u, int32 c, int32 v1, int32 v2, int32 v3) +{ + if (c == 0) return true; + if (!u || !u->ToPlayer()) return false; + Condition cond; + cond.ConditionType = ConditionTypes(uint32(c)); + cond.ConditionValue1 = uint32(v1); + cond.ConditionValue1 = uint32(v2); + cond.ConditionValue1 = uint32(v3); + ConditionSourceInfo srcInfo = ConditionSourceInfo(u->ToPlayer()); + return cond.Meets(srcInfo); +} + void SmartScript::OnUpdate(uint32 const diff) { if ((mScriptType == SMART_SCRIPT_TYPE_CREATURE || mScriptType == SMART_SCRIPT_TYPE_GAMEOBJECT) && !GetBaseObject()) diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index f55d91ed52f..f7524582ab7 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -84,17 +84,7 @@ class SmartScript return obj && obj->GetTypeId() == TYPEID_GAMEOBJECT; } - bool ConditionValid(Unit* u, int32 c, int32 v1, int32 v2, int32 v3) - { - if (c == 0) return true; - if (!u || !u->ToPlayer()) return false; - Condition cond; - cond.mConditionType = ConditionType(uint32(c)); - cond.mConditionValue1 = uint32(v1); - cond.mConditionValue1 = uint32(v2); - cond.mConditionValue1 = uint32(v3); - return cond.Meets(u->ToPlayer()); - } + bool ConditionValid(Unit* u, int32 c, int32 v1, int32 v2, int32 v3); void OnUpdate(const uint32 diff); void OnMoveInLineOfSight(Unit* who); @@ -236,7 +226,6 @@ class SmartScript SmartScriptType mScriptType; uint32 mEventPhase; - uint32 mInvinceabilityHpLevel; UNORDERED_MAP<int32, int32> mStoredDecimals; uint32 mPathId; SmartAIEventList mStoredEvents; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 9a23d9e1390..f99e317454c 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -260,7 +260,7 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e) } case SMART_TARGET_GAMEOBJECT_GUID: { - if (e.target.goGUID.entry && !IsGameObjectValid(e, e.target.goGUID.entry)) + if (e.target.goGUID.entry && !IsGameObjectValid(e, e.target.goGUID.entry)) return false; break; } diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 123275ccc55..7869a2e665f 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -155,7 +155,7 @@ enum SMART_EVENT SMART_EVENT_IS_BEHIND_TARGET = 67, //1 // cooldownMin, CooldownMax SMART_EVENT_GAME_EVENT_START = 68, //1 // game_event.Entry SMART_EVENT_GAME_EVENT_END = 69, //1 // game_event.Entry - SMART_EVENT_GO_STATE_CHANGED = 70, // go state + SMART_EVENT_GO_STATE_CHANGED = 70, // go state SMART_EVENT_END = 71, }; @@ -342,16 +342,16 @@ struct SmartEvent uint32 cooldownMax; } behindTarget; - struct + struct { uint32 gameEventId; } gameEvent; - + struct { uint32 state; } goStateChanged; - + struct { uint32 param1; @@ -873,7 +873,7 @@ struct SmartAction { uint32 goRespawnTime; } RespawnTarget; - + struct { uint32 gossipMenuId; @@ -884,12 +884,12 @@ struct SmartAction { uint32 state; } setGoLootState; - + struct { uint32 id; } sendTargetToTarget; - + struct { uint32 param1; @@ -1181,7 +1181,7 @@ enum SmartCastFlags //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 + SMARTCAST_AURA_NOT_PRESENT = 0x20, //Only casts the spell if the target does not have an aura from the spell }; // one line in DB is one event diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 79366f90395..d07a19c486a 100755 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -1080,10 +1080,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // speedup for non-login case if (miscValue1 && achievementCriteria->own_item.itemID != miscValue1) continue; - SetCriteriaProgress(achievementCriteria, GetPlayer()->GetItemCount(achievementCriteria->own_item.itemID, true)); + SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA: - // miscvalue1 contains the personal rating if (!miscValue1) // no update at login continue; diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index 4a725fada58..4f95413c49a 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -650,35 +650,35 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player //this function inserts to WorldPacket auction's data bool AuctionEntry::BuildAuctionInfo(WorldPacket& data) const { - Item* pItem = sAuctionMgr->GetAItem(item_guidlow); - if (!pItem) + Item* item = sAuctionMgr->GetAItem(item_guidlow); + if (!item) { - sLog->outError("auction to item, that doesn't exist !!!!"); + sLog->outError("AuctionEntry::BuildAuctionInfo: Auction %u has a non-existent item: %u", Id, item_guidlow); return false; } data << uint32(Id); - data << uint32(pItem->GetEntry()); + data << uint32(item->GetEntry()); for (uint8 i = 0; i < PROP_ENCHANTMENT_SLOT_2; ++i) // PROP_ENCHANTMENT_SLOT_2 = 9 { - data << uint32(pItem->GetEnchantmentId(EnchantmentSlot(i))); - data << uint32(pItem->GetEnchantmentDuration(EnchantmentSlot(i))); - data << uint32(pItem->GetEnchantmentCharges(EnchantmentSlot(i))); + data << uint32(item->GetEnchantmentId(EnchantmentSlot(i))); + data << uint32(item->GetEnchantmentDuration(EnchantmentSlot(i))); + data << uint32(item->GetEnchantmentCharges(EnchantmentSlot(i))); } - data << int32(pItem->GetItemRandomPropertyId()); // random item property id - data << uint32(pItem->GetItemSuffixFactor()); // SuffixFactor - data << uint32(pItem->GetCount()); // item->count - data << uint32(pItem->GetSpellCharges()); // item->charge FFFFFFF - data << uint32(0); // Unknown - data << uint64(owner); // Auction->owner - data << uint64(startbid); // Auction->startbid (not sure if useful) + data << int32(pItem->GetItemRandomPropertyId()); // random item property id + data << uint32(pItem->GetItemSuffixFactor()); // SuffixFactor + data << uint32(pItem->GetCount()); // item->count + data << uint32(pItem->GetSpellCharges()); // item->charge FFFFFFF + data << uint32(0); // Unknown + data << uint64(owner); // Auction->owner + data << uint64(startbid); // Auction->startbid (not sure if useful) data << uint64(bid ? GetAuctionOutBid() : 0); //minimal outbid - data << uint64(buyout); // auction->buyout - data << uint32((expire_time-time(NULL))*IN_MILLISECONDS); // time left - data << uint64(bidder); // auction->bidder current - data << uint64(bid); // current bid + data << uint64(buyout); // auction->buyout + data << uint32((expire_time - time(NULL)) * IN_MILLISECONDS); // time left + data << uint64(bidder); // auction->bidder current + data << uint64(bid); // current bid return true; } diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h index f81393be761..190fbcc5107 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.h +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h @@ -30,6 +30,7 @@ class Player; class WorldPacket; #define MIN_AUCTION_TIME (12*HOUR) +#define MAX_AUCTION_ITEMS 160 enum AuctionError { diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index 8e30743f107..02707261d13 100755 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -455,7 +455,7 @@ void ArenaTeam::Inspect(WorldSession* session, uint64 guid) session->SendPacket(&data); } -void ArenaTeamMember::ModifyPersonalRating(Player* player, int32 mod, uint32 slot) +void ArenaTeamMember::ModifyPersonalRating(Player* player, int32 mod, uint32 type) { if (int32(PersonalRating) + mod < 0) PersonalRating = 0; @@ -464,8 +464,8 @@ void ArenaTeamMember::ModifyPersonalRating(Player* player, int32 mod, uint32 slo if (player) { - player->SetArenaTeamInfoField(slot, ARENA_TEAM_PERSONAL_RATING, PersonalRating); - player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING, PersonalRating, slot); + player->SetArenaTeamInfoField(ArenaTeam::GetSlotByType(type), ARENA_TEAM_PERSONAL_RATING, PersonalRating); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING, PersonalRating, type); } } @@ -725,7 +725,7 @@ void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32 { // Update personal rating int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, false); - itr->ModifyPersonalRating(player, mod, GetSlot()); + itr->ModifyPersonalRating(player, mod, GetType()); // Update matchmaker rating itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot()); @@ -751,7 +751,7 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, i { // update personal rating int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, false); - itr->ModifyPersonalRating(NULL, mod, GetSlot()); + itr->ModifyPersonalRating(NULL, mod, GetType()); // update matchmaker rating itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot()); @@ -773,7 +773,7 @@ void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32 { // update personal rating int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, true); - itr->ModifyPersonalRating(player, mod, GetSlot()); + itr->ModifyPersonalRating(player, mod, GetType()); // update matchmaker rating itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot()); diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h index 03ddea1dd3a..d8ad2c09e59 100755 --- a/src/server/game/Battlegrounds/ArenaTeam.h +++ b/src/server/game/Battlegrounds/ArenaTeam.h @@ -97,7 +97,7 @@ struct ArenaTeamMember uint16 PersonalRating; uint16 MatchMakerRating; - void ModifyPersonalRating(Player* player, int32 mod, uint32 slot); + void ModifyPersonalRating(Player* player, int32 mod, uint32 type); void ModifyMatchmakerRating(int32 mod, uint32 slot); }; diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 159a986367c..191d2eaaeb6 100755 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -194,26 +194,26 @@ Battleground::Battleground() m_HonorMode = BG_NORMAL; - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_2M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_2M; + StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M; + StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S; + StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; //we must set to some default existing values - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; } Battleground::~Battleground() { // remove objects and creatures // (this is done automatically in mapmanager update, when the instance is reset after the reset time) - uint32 size = uint32(m_BgCreatures.size()); + uint32 size = uint32(BgCreatures.size()); for (uint32 i = 0; i < size; ++i) DelCreature(i); - size = uint32(m_BgObjects.size()); + size = uint32(BgObjects.size()); for (uint32 i = 0; i < size; ++i) DelObject(i); @@ -229,7 +229,7 @@ Battleground::~Battleground() // remove from bg free slot queue RemoveFromBGFreeSlotQueue(); - for (BattlegroundScoreMap::const_iterator itr = m_PlayerScores.begin(); itr != m_PlayerScores.end(); ++itr) + for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr) delete itr->second; } @@ -452,21 +452,21 @@ inline void Battleground::_ProcessJoin(uint32 diff) } StartingEventCloseDoors(); - SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FIRST]); + SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FIRST]); // First start warning - 2 or 1 minute - SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL); } // After 1 minute or 30 seconds, warning is signalled - else if (GetStartDelayTime() <= m_StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2)) + else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2)) { m_Events |= BG_STARTING_EVENT_2; - SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL); } // After 30 or 15 seconds, warning is signalled - else if (GetStartDelayTime() <= m_StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3)) + else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3)) { m_Events |= BG_STARTING_EVENT_3; - SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL); + SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL); } // Delay expired (atfer 2 or 1 minute) else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4)) @@ -475,9 +475,9 @@ inline void Battleground::_ProcessJoin(uint32 diff) StartingEventOpenDoors(); - SendWarningToAll(m_StartMessageIds[BG_STARTING_EVENT_FOURTH]); + SendWarningToAll(StartMessageIds[BG_STARTING_EVENT_FOURTH]); SetStatus(STATUS_IN_PROGRESS); - SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FOURTH]); + SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FOURTH]); // Remove preparation if (isArena()) @@ -824,7 +824,7 @@ void Battleground::EndBattleground(uint32 winner) // update achievement BEFORE personal rating update ArenaTeamMember* member = winner_arena_team->GetMember(player->GetGUID()); if (member) - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, member->PersonalRating); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, 1); winner_arena_team->MemberWon(player, loser_matchmaker_rating, winner_matchmaker_change); } @@ -922,11 +922,11 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac participant = true; } - BattlegroundScoreMap::iterator itr2 = m_PlayerScores.find(guid); - if (itr2 != m_PlayerScores.end()) + BattlegroundScoreMap::iterator itr2 = PlayerScores.find(guid); + if (itr2 != PlayerScores.end()) { delete itr2->second; // delete player's score - m_PlayerScores.erase(itr2); + PlayerScores.erase(itr2); } RemovePlayerFromResurrectQueue(guid); @@ -1060,9 +1060,9 @@ void Battleground::Reset() m_Players.clear(); - for (BattlegroundScoreMap::const_iterator itr = m_PlayerScores.begin(); itr != m_PlayerScores.end(); ++itr) + for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr) delete itr->second; - m_PlayerScores.clear(); + PlayerScores.clear(); ResetBGSubclass(); } @@ -1334,8 +1334,8 @@ bool Battleground::HasFreeSlots() const void Battleground::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) { //this procedure is called from virtual function implemented in bg subclass - BattlegroundScoreMap::const_iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... + BattlegroundScoreMap::const_iterator itr = PlayerScores.find(Source->GetGUID()); + if (itr == PlayerScores.end()) // player not found... return; switch (type) @@ -1404,8 +1404,8 @@ void Battleground::RemovePlayerFromResurrectQueue(uint64 player_guid) bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 /*respawnTime*/) { - // If the assert is called, means that m_BgObjects must be resized! - ASSERT(type < m_BgObjects.size()); + // If the assert is called, means that BgObjects must be resized! + ASSERT(type < BgObjects.size()); Map* map = FindBgMap(); if (!map) @@ -1452,7 +1452,7 @@ bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float delete go; return false; } - m_BgObjects[type] = go->GetGUID(); + BgObjects[type] = go->GetGUID(); return true; } @@ -1460,7 +1460,7 @@ bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float // It would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code void Battleground::DoorClose(uint32 type) { - if (GameObject* obj = GetBgMap()->GetGameObject(m_BgObjects[type])) + if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type])) { // If doors are open, close it if (obj->getLootState() == GO_ACTIVATED && obj->GetGoState() != GO_STATE_READY) @@ -1472,12 +1472,12 @@ void Battleground::DoorClose(uint32 type) } else sLog->outError("Battleground::DoorClose: door gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, GUID_LOPART(m_BgObjects[type]), m_MapId, m_InstanceID); + type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID); } void Battleground::DoorOpen(uint32 type) { - if (GameObject* obj = GetBgMap()->GetGameObject(m_BgObjects[type])) + if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type])) { // Change state to be sure they will be opened obj->SetLootState(GO_READY); @@ -1485,31 +1485,31 @@ void Battleground::DoorOpen(uint32 type) } else sLog->outError("Battleground::DoorOpen: door gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, GUID_LOPART(m_BgObjects[type]), m_MapId, m_InstanceID); + type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID); } GameObject* Battleground::GetBGObject(uint32 type) { - GameObject* obj = GetBgMap()->GetGameObject(m_BgObjects[type]); + GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]); if (!obj) sLog->outError("Battleground::GetBGObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, GUID_LOPART(m_BgObjects[type]), m_MapId, m_InstanceID); + type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID); return obj; } Creature* Battleground::GetBGCreature(uint32 type) { - Creature* creature = GetBgMap()->GetCreature(m_BgCreatures[type]); + Creature* creature = GetBgMap()->GetCreature(BgCreatures[type]); if (!creature) sLog->outError("Battleground::GetBGCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, GUID_LOPART(m_BgCreatures[type]), m_MapId, m_InstanceID); + type, GUID_LOPART(BgCreatures[type]), m_MapId, m_InstanceID); return creature; } void Battleground::SpawnBGObject(uint32 type, uint32 respawntime) { if (Map* map = FindBgMap()) - if (GameObject* obj = map->GetGameObject(m_BgObjects[type])) + if (GameObject* obj = map->GetGameObject(BgObjects[type])) { if (respawntime) obj->SetLootState(GO_JUST_DEACTIVATED); @@ -1524,8 +1524,8 @@ void Battleground::SpawnBGObject(uint32 type, uint32 respawntime) Creature* Battleground::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime) { - // If the assert is called, means that m_BgCreatures must be resized! - ASSERT(type < m_BgCreatures.size()); + // If the assert is called, means that BgCreatures must be resized! + ASSERT(type < BgCreatures.size()); Map* map = FindBgMap(); if (!map) @@ -1560,7 +1560,7 @@ Creature* Battleground::AddCreature(uint32 entry, uint32 type, uint32 teamval, f return NULL; } - m_BgCreatures[type] = creature->GetGUID(); + BgCreatures[type] = creature->GetGUID(); if (respawntime) creature->SetRespawnDelay(respawntime); @@ -1570,37 +1570,37 @@ Creature* Battleground::AddCreature(uint32 entry, uint32 type, uint32 teamval, f bool Battleground::DelCreature(uint32 type) { - if (!m_BgCreatures[type]) + if (!BgCreatures[type]) return true; - if (Creature* creature = GetBgMap()->GetCreature(m_BgCreatures[type])) + if (Creature* creature = GetBgMap()->GetCreature(BgCreatures[type])) { creature->AddObjectToRemoveList(); - m_BgCreatures[type] = 0; + BgCreatures[type] = 0; return true; } sLog->outError("Battleground::DelCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, GUID_LOPART(m_BgCreatures[type]), m_MapId, m_InstanceID); - m_BgCreatures[type] = 0; + type, GUID_LOPART(BgCreatures[type]), m_MapId, m_InstanceID); + BgCreatures[type] = 0; return false; } bool Battleground::DelObject(uint32 type) { - if (!m_BgObjects[type]) + if (!BgObjects[type]) return true; - if (GameObject* obj = GetBgMap()->GetGameObject(m_BgObjects[type])) + if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type])) { obj->SetRespawnTime(0); // not save respawn time obj->Delete(); - m_BgObjects[type] = 0; + BgObjects[type] = 0; return true; } sLog->outError("Battleground::DelObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!", - type, GUID_LOPART(m_BgObjects[type]), m_MapId, m_InstanceID); - m_BgObjects[type] = 0; + type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID); + BgObjects[type] = 0; return false; } @@ -1718,8 +1718,8 @@ void Battleground::HandleTriggerBuff(uint64 go_guid) return; // Change buff type, when buff is used: - int32 index = m_BgObjects.size() - 1; - while (index >= 0 && m_BgObjects[index] != go_guid) + int32 index = BgObjects.size() - 1; + while (index >= 0 && BgObjects[index] != go_guid) index--; if (index < 0) { @@ -1840,8 +1840,8 @@ void Battleground::SetHoliday(bool is_holiday) int32 Battleground::GetObjectType(uint64 guid) { - for (uint32 i = 0; i < m_BgObjects.size(); ++i) - if (m_BgObjects[i] == guid) + for (uint32 i = 0; i < BgObjects.size(); ++i) + if (BgObjects[i] == guid) return i; sLog->outError("Battleground::GetObjectType: player used gameobject (GUID: %u) which is not in internal data for BG (map: %u, instance id: %u), cheating?", GUID_LOPART(guid), m_MapId, m_InstanceID); diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 6eb64a2caba..32f6ebc92de 100755 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -411,9 +411,9 @@ class Battleground uint32 GetPlayersSize() const { return m_Players.size(); } typedef std::map<uint64, BattlegroundScore*> BattlegroundScoreMap; - BattlegroundScoreMap::const_iterator GetPlayerScoresBegin() const { return m_PlayerScores.begin(); } - BattlegroundScoreMap::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); } - uint32 GetPlayerScoresSize() const { return m_PlayerScores.size(); } + BattlegroundScoreMap::const_iterator GetPlayerScoresBegin() const { return PlayerScores.begin(); } + BattlegroundScoreMap::const_iterator GetPlayerScoresEnd() const { return PlayerScores.end(); } + uint32 GetPlayerScoresSize() const { return PlayerScores.size(); } uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); } @@ -539,8 +539,8 @@ class Battleground // TODO: make this protected: typedef std::vector<uint64> BGObjects; typedef std::vector<uint64> BGCreatures; - BGObjects m_BgObjects; - BGCreatures m_BgCreatures; + BGObjects BgObjects; + BGCreatures BgCreatures; void SpawnBGObject(uint32 type, uint32 respawntime); bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0); Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime = 0); @@ -589,7 +589,7 @@ class Battleground void _ProcessJoin(uint32 diff); // Scorekeeping - BattlegroundScoreMap m_PlayerScores; // Player scores + BattlegroundScoreMap PlayerScores; // Player scores // must be implemented in BG subclass virtual void RemovePlayer(Player* /*player*/, uint64 /*guid*/, uint32 /*team*/) {} @@ -600,9 +600,9 @@ class Battleground // these are important variables used for starting messages uint8 m_Events; - BattlegroundStartTimeIntervals m_StartDelayTimes[BG_STARTING_EVENT_COUNT]; + BattlegroundStartTimeIntervals StartDelayTimes[BG_STARTING_EVENT_COUNT]; // this must be filled in constructors! - uint32 m_StartMessageIds[BG_STARTING_EVENT_COUNT]; + uint32 StartMessageIds[BG_STARTING_EVENT_COUNT]; bool m_BuffChange; bool m_IsRandom; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAA.cpp index 61180ae88ea..e4c1b484d4d 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAA.cpp @@ -23,15 +23,15 @@ BattlegroundAA::BattlegroundAA() { - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattlegroundAA::~BattlegroundAA() @@ -53,7 +53,7 @@ void BattlegroundAA::AddPlayer(Player* player) //create score and add it to map, default values are set in constructor BattlegroundAAScore* sc = new BattlegroundAAScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; } void BattlegroundAA::RemovePlayer(Player* /*player*/, uint64 /*guid*/, uint32 /*team*/) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp index 5e529768c04..71f0ce29aec 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -28,27 +28,16 @@ #include "Player.h" #include "Util.h" -// these variables aren't used outside of this file, so declare them only here -uint32 BG_AB_HonorScoreTicks[BG_HONOR_MODE_NUM] = { - 330, // normal honor - 200 // holiday -}; - -uint32 BG_AB_ReputationScoreTicks[BG_HONOR_MODE_NUM] = { - 200, // normal honor - 150 // holiday -}; - BattlegroundAB::BattlegroundAB() { m_BuffChange = true; - m_BgObjects.resize(BG_AB_OBJECT_MAX); - m_BgCreatures.resize(BG_AB_ALL_NODES_COUNT + 5);//+5 for aura triggers + BgObjects.resize(BG_AB_OBJECT_MAX); + BgCreatures.resize(BG_AB_ALL_NODES_COUNT + 5);//+5 for aura triggers - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AB_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AB_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AB_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AB_HAS_BEGUN; } BattlegroundAB::~BattlegroundAB() @@ -213,7 +202,7 @@ void BattlegroundAB::AddPlayer(Player* player) //create score and add it to map, default values are set in the constructor BattlegroundABScore* sc = new BattlegroundABScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; } void BattlegroundAB::RemovePlayer(Player* /*player*/, uint64 /*guid*/, uint32 /*team*/) @@ -406,7 +395,7 @@ void BattlegroundAB::_NodeDeOccupied(uint8 node) DelCreature(node+7);//NULL checks are in DelCreature! 0-6 spirit guides // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard - std::vector<uint64> ghost_list = m_ReviveQueue[m_BgCreatures[node]]; + std::vector<uint64> ghost_list = m_ReviveQueue[BgCreatures[node]]; if (!ghost_list.empty()) { WorldSafeLocsEntry const* ClosestGrave = NULL; @@ -424,7 +413,7 @@ void BattlegroundAB::_NodeDeOccupied(uint8 node) } } - if (m_BgCreatures[node]) + if (BgCreatures[node]) DelCreature(node); // buff object isn't despawned @@ -437,11 +426,11 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* source, GameObject* /*targ return; uint8 node = BG_AB_NODE_STABLES; - GameObject* obj = GetBgMap()->GetGameObject(m_BgObjects[node*8+7]); + GameObject* obj = GetBgMap()->GetGameObject(BgObjects[node*8+7]); while ((node < BG_AB_DYNAMIC_NODES_COUNT) && ((!obj) || (!source->IsWithinDistInMap(obj, 10)))) { ++node; - obj = GetBgMap()->GetGameObject(m_BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]); + obj = GetBgMap()->GetGameObject(BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]); } if (node == BG_AB_DYNAMIC_NODES_COUNT) @@ -625,7 +614,7 @@ void BattlegroundAB::Reset() } for (uint8 i = 0; i < BG_AB_ALL_NODES_COUNT + 5; ++i)//+5 for aura triggers - if (m_BgCreatures[i]) + if (BgCreatures[i]) DelCreature(i); } @@ -684,8 +673,8 @@ WorldSafeLocsEntry const* BattlegroundAB::GetClosestGraveYard(Player* player) void BattlegroundAB::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) { - BattlegroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... + BattlegroundScoreMap::iterator itr = PlayerScores.find(Source->GetGUID()); + if (itr == PlayerScores.end()) // player not found... return; switch (type) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h index c86076f0250..50020a580b1 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h @@ -176,10 +176,10 @@ enum BG_AB_Objectives AB_OBJECTIVE_DEFEND_BASE = 123 }; -#define BG_AB_NotABBGWeekendHonorTicks 330 -#define BG_AB_ABBGWeekendHonorTicks 200 -#define BG_AB_NotABBGWeekendReputationTicks 200 -#define BG_AB_ABBGWeekendReputationTicks 150 +#define BG_AB_NotABBGWeekendHonorTicks 260 +#define BG_AB_ABBGWeekendHonorTicks 160 +#define BG_AB_NotABBGWeekendReputationTicks 160 +#define BG_AB_ABBGWeekendReputationTicks 120 #define AB_EVENT_START_BATTLE 9158 // Achievement: Let's Get This Done diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp index f2e8c2bf0af..801b522feab 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp @@ -29,13 +29,13 @@ BattlegroundAV::BattlegroundAV() { - m_BgObjects.resize(BG_AV_OBJECT_MAX); - m_BgCreatures.resize(AV_CPLACE_MAX+AV_STATICCPLACE_MAX); + BgObjects.resize(BG_AV_OBJECT_MAX); + BgCreatures.resize(AV_CPLACE_MAX+AV_STATICCPLACE_MAX); - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AV_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AV_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AV_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AV_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AV_START_TWO_MINUTES; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AV_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AV_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AV_HAS_BEGUN; } BattlegroundAV::~BattlegroundAV() @@ -430,7 +430,7 @@ void BattlegroundAV::AddPlayer(Player* player) Battleground::AddPlayer(player); //create score and add it to map, default values are set in constructor BattlegroundAVScore* sc = new BattlegroundAVScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; if (m_MaxLevel == 0) m_MaxLevel=(player->getLevel()%10 == 0)? player->getLevel() : (player->getLevel()-(player->getLevel()%10))+10; //TODO: just look at the code \^_^/ --but queue-info should provide this information.. @@ -532,8 +532,8 @@ void BattlegroundAV::HandleAreaTrigger(Player* Source, uint32 Trigger) void BattlegroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) { - BattlegroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... + BattlegroundScoreMap::iterator itr = PlayerScores.find(Source->GetGUID()); + if (itr == PlayerScores.end()) // player not found... return; switch (type) @@ -585,7 +585,7 @@ void BattlegroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node) { uint8 tmp = node-BG_AV_NODES_DUNBALDAR_SOUTH; //despawn marshal - if (m_BgCreatures[AV_CPLACE_A_MARSHAL_SOUTH + tmp]) + if (BgCreatures[AV_CPLACE_A_MARSHAL_SOUTH + tmp]) DelCreature(AV_CPLACE_A_MARSHAL_SOUTH + tmp); else sLog->outError("BG_AV: playerdestroyedpoint: marshal %i doesn't exist", AV_CPLACE_A_MARSHAL_SOUTH + tmp); @@ -649,10 +649,10 @@ void BattlegroundAV::ChangeMineOwner(uint8 mine, uint32 team, bool initial) sLog->outDebug(LOG_FILTER_BATTLEGROUND, "bg_av depopulating mine %i (0=north, 1=south)", mine); if (mine == AV_SOUTH_MINE) for (uint16 i=AV_CPLACE_MINE_S_S_MIN; i <= AV_CPLACE_MINE_S_S_MAX; i++) - if (m_BgCreatures[i]) + if (BgCreatures[i]) DelCreature(i); //TODO just set the respawntime to 999999 for (uint16 i=((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_1_MIN:AV_CPLACE_MINE_S_1_MIN); i <= ((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_3:AV_CPLACE_MINE_S_3); i++) - if (m_BgCreatures[i]) + if (BgCreatures[i]) DelCreature(i); //TODO here also } SendMineWorldStates(mine); @@ -750,7 +750,7 @@ void BattlegroundAV::PopulateNode(BG_AV_Nodes node) else creatureid = (owner == ALLIANCE)? AV_NPC_A_GRAVEDEFENSE3 : AV_NPC_H_GRAVEDEFENSE3; //spiritguide - if (m_BgCreatures[node]) + if (BgCreatures[node]) DelCreature(node); if (!AddSpiritGuide(node, BG_AV_CreaturePos[node][0], BG_AV_CreaturePos[node][1], BG_AV_CreaturePos[node][2], BG_AV_CreaturePos[node][3], owner)) sLog->outError("AV: couldn't spawn spiritguide at node %i", node); @@ -783,10 +783,10 @@ void BattlegroundAV::DePopulateNode(BG_AV_Nodes node) { uint32 c_place = AV_CPLACE_DEFENSE_STORM_AID + (4 * node); for (uint8 i=0; i<4; i++) - if (m_BgCreatures[c_place+i]) + if (BgCreatures[c_place+i]) DelCreature(c_place+i); //spiritguide - if (!IsTower(node) && m_BgCreatures[node]) + if (!IsTower(node) && BgCreatures[node]) DelCreature(node); //remove bonus honor aura trigger creature when node is lost @@ -1029,7 +1029,7 @@ void BattlegroundAV::EventPlayerAssaultsPoint(Player* player, uint32 object) SpawnBGObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+3*node, RESPAWN_IMMEDIATELY); //neutral aura spawn SpawnBGObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+GetTeamIndexByTeamId(owner)+3*node, RESPAWN_ONE_DAY); //teeamaura despawn // Those who are waiting to resurrect at this object are taken to the closest own object's graveyard - std::vector<uint64> ghost_list = m_ReviveQueue[m_BgCreatures[node]]; + std::vector<uint64> ghost_list = m_ReviveQueue[BgCreatures[node]]; if (!ghost_list.empty()) { Player* player; @@ -1044,7 +1044,7 @@ void BattlegroundAV::EventPlayerAssaultsPoint(Player* player, uint32 object) else player->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, player->GetOrientation()); } - m_ReviveQueue[m_BgCreatures[node]].clear(); + m_ReviveQueue[BgCreatures[node]].clear(); } } DePopulateNode(node); @@ -1490,7 +1490,7 @@ void BattlegroundAV::ResetBGSubclass() m_Mine_Timer=AV_MINE_TICK_TIMER; for (uint16 i = 0; i < AV_CPLACE_MAX+AV_STATICCPLACE_MAX; i++) - if (m_BgCreatures[i]) + if (BgCreatures[i]) DelCreature(i); } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp index 0e79296b6f4..c7eddbb67a9 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp @@ -26,17 +26,17 @@ BattlegroundBE::BattlegroundBE() { - m_BgObjects.resize(BG_BE_OBJECT_MAX); + BgObjects.resize(BG_BE_OBJECT_MAX); - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattlegroundBE::~BattlegroundBE() @@ -68,7 +68,7 @@ void BattlegroundBE::AddPlayer(Player* player) //create score and add it to map, default values are set in constructor BattlegroundBEScore* sc = new BattlegroundBEScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; UpdateArenaWorldState(); } @@ -116,10 +116,10 @@ void BattlegroundBE::HandleAreaTrigger(Player* Source, uint32 Trigger) switch (Trigger) { case 4538: // buff trigger? - //buff_guid = m_BgObjects[BG_BE_OBJECT_BUFF_1]; + //buff_guid = BgObjects[BG_BE_OBJECT_BUFF_1]; break; case 4539: // buff trigger? - //buff_guid = m_BgObjects[BG_BE_OBJECT_BUFF_2]; + //buff_guid = BgObjects[BG_BE_OBJECT_BUFF_2]; break; default: sLog->outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); @@ -164,8 +164,8 @@ bool BattlegroundBE::SetupBattleground() void BattlegroundBE::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) { - BattlegroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... + BattlegroundScoreMap::iterator itr = PlayerScores.find(Source->GetGUID()); + if (itr == PlayerScores.end()) // player not found... return; //there is nothing special in this score diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp index 87f4ca48378..d24058cdd8a 100755..100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp @@ -26,17 +26,17 @@ BattlegroundDS::BattlegroundDS() { - m_BgObjects.resize(BG_DS_OBJECT_MAX); + BgObjects.resize(BG_DS_OBJECT_MAX); - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattlegroundDS::~BattlegroundDS() @@ -46,21 +46,34 @@ BattlegroundDS::~BattlegroundDS() void BattlegroundDS::PostUpdateImpl(uint32 diff) { + if (GetStatus() != STATUS_IN_PROGRESS) + return; + if (getWaterFallTimer() < diff) { - if (isWaterFallActive()) + if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_OFF) // Add the water { - setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX)); - for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i) - SpawnBGObject(i, getWaterFallTimer()); - setWaterFallActive(false); + DoorClose(BG_DS_OBJECT_WATER_2); + setWaterFallTimer(BG_DS_WATERFALL_WARNING_DURATION); + setWaterFallStatus(BG_DS_WATERFALL_STATUS_WARNING); } - else + else if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_WARNING) // Active collision { + if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1])) + gob->SetGoState(GO_STATE_READY); + setWaterFallTimer(BG_DS_WATERFALL_DURATION); - for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - setWaterFallActive(true); + setWaterFallStatus(BG_DS_WATERFALL_STATUS_ON); + } + else //if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_ON) // Remove collision and water + { + // turn off collision + if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1])) + gob->SetGoState(GO_STATE_ACTIVE); + + DoorOpen(BG_DS_OBJECT_WATER_2); + setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX)); + setWaterFallStatus(BG_DS_WATERFALL_STATUS_OFF); } } else @@ -82,19 +95,23 @@ void BattlegroundDS::StartingEventOpenDoors() SpawnBGObject(i, 60); setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX)); - setWaterFallActive(false); + setWaterFallStatus(BG_DS_WATERFALL_STATUS_OFF); + + SpawnBGObject(BG_DS_OBJECT_WATER_2, RESPAWN_IMMEDIATELY); + DoorOpen(BG_DS_OBJECT_WATER_2); - for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i) - SpawnBGObject(i, getWaterFallTimer()); + // Turn off collision + if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1])) + gob->SetGoState(GO_STATE_ACTIVE); } void BattlegroundDS::AddPlayer(Player* player) { Battleground::AddPlayer(player); //create score and add it to map, default values are set in constructor - BattlegroundDSScore* sc = new BattlegroundDSScore; + BattlegroundDSScore* score = new BattlegroundDSScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = score; UpdateArenaWorldState(); } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h index f2ba2cea1e7..7efc6e1caa7 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h @@ -25,7 +25,7 @@ enum BattlegroundDSObjectTypes { BG_DS_OBJECT_DOOR_1 = 0, BG_DS_OBJECT_DOOR_2 = 1, - BG_DS_OBJECT_WATER_1 = 2, + BG_DS_OBJECT_WATER_1 = 2, // Collision BG_DS_OBJECT_WATER_2 = 3, BG_DS_OBJECT_BUFF_1 = 4, BG_DS_OBJECT_BUFF_2 = 5, @@ -36,7 +36,7 @@ enum BattlegroundDSObjects { BG_DS_OBJECT_TYPE_DOOR_1 = 192642, BG_DS_OBJECT_TYPE_DOOR_2 = 192643, - BG_DS_OBJECT_TYPE_WATER_1 = 194395, + BG_DS_OBJECT_TYPE_WATER_1 = 194395, // Collision BG_DS_OBJECT_TYPE_WATER_2 = 191877, BG_DS_OBJECT_TYPE_BUFF_1 = 184663, BG_DS_OBJECT_TYPE_BUFF_2 = 184664 @@ -46,7 +46,12 @@ enum BattlegroundDSData { // These values are NOT blizzlike... need the correct data! BG_DS_WATERFALL_TIMER_MIN = 30000, BG_DS_WATERFALL_TIMER_MAX = 60000, + BG_DS_WATERFALL_WARNING_DURATION = 7000, BG_DS_WATERFALL_DURATION = 10000, + + BG_DS_WATERFALL_STATUS_WARNING = 1, // Water starting to fall, but no LoS Blocking nor movement blocking + BG_DS_WATERFALL_STATUS_ON = 2, // LoS and Movement blocking active + BG_DS_WATERFALL_STATUS_OFF = 3, }; class BattlegroundDSScore : public BattlegroundScore @@ -76,14 +81,14 @@ class BattlegroundDS : public Battleground void HandleKillPlayer(Player* player, Player* killer); bool HandlePlayerUnderMap(Player* player); private: - uint32 m_waterTimer; - bool m_waterfallActive; + uint32 _waterfallTimer; + uint8 _waterfallStatus; virtual void PostUpdateImpl(uint32 diff); protected: - bool isWaterFallActive() { return m_waterfallActive; }; - void setWaterFallActive(bool active) { m_waterfallActive = active; }; - void setWaterFallTimer(uint32 timer) { m_waterTimer = timer; }; - uint32 getWaterFallTimer() { return m_waterTimer; }; + uint32 getWaterFallStatus() { return _waterfallStatus; }; + void setWaterFallStatus(uint32 status) { _waterfallStatus = status; }; + void setWaterFallTimer(uint32 timer) { _waterfallTimer = timer; }; + uint32 getWaterFallTimer() { return _waterfallTimer; }; }; #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index cbc3ec85055..344dc79fe79 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -30,24 +30,24 @@ // these variables aren't used outside of this file, so declare them only here uint32 BG_EY_HonorScoreTicks[BG_HONOR_MODE_NUM] = { - 330, // normal honor - 200 // holiday + 260, // normal honor + 160 // holiday }; BattlegroundEY::BattlegroundEY() { m_BuffChange = true; - m_BgObjects.resize(BG_EY_OBJECT_MAX); - m_BgCreatures.resize(BG_EY_CREATURES_MAX); + BgObjects.resize(BG_EY_OBJECT_MAX); + BgCreatures.resize(BG_EY_CREATURES_MAX); m_Points_Trigger[FEL_REAVER] = TR_FEL_REAVER_BUFF; m_Points_Trigger[BLOOD_ELF] = TR_BLOOD_ELF_BUFF; m_Points_Trigger[DRAENEI_RUINS] = TR_DRAENEI_RUINS_BUFF; m_Points_Trigger[MAGE_TOWER] = TR_MAGE_TOWER_BUFF; - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN; } BattlegroundEY::~BattlegroundEY() @@ -143,7 +143,7 @@ void BattlegroundEY::CheckSomeoneJoinedPoint() GameObject* obj = NULL; for (uint8 i = 0; i < EY_POINTS_MAX; ++i) { - obj = HashMapHolder<GameObject>::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]); + obj = HashMapHolder<GameObject>::Find(BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]); if (obj) { uint8 j = 0; @@ -183,7 +183,7 @@ void BattlegroundEY::CheckSomeoneLeftPoint() GameObject* obj = NULL; for (uint8 i = 0; i < EY_POINTS_MAX; ++i) { - obj = HashMapHolder<GameObject>::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]); + obj = HashMapHolder<GameObject>::Find(BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]); if (obj) { uint8 j = 0; @@ -340,7 +340,7 @@ void BattlegroundEY::AddPlayer(Player* player) m_PlayersNearPoint[EY_POINTS_MAX].push_back(player->GetGUID()); - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; } void BattlegroundEY::RemovePlayer(Player* player, uint64 guid, uint32 /*team*/) @@ -735,7 +735,7 @@ void BattlegroundEY::EventTeamCapturedPoint(Player* Source, uint32 Point) else SendMessageToAll(m_CapturingPointTypes[Point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE, Source); - if (m_BgCreatures[Point]) + if (BgCreatures[Point]) DelCreature(Point); WorldSafeLocsEntry const* sg = NULL; @@ -807,8 +807,8 @@ void BattlegroundEY::EventPlayerCapturedFlag(Player* Source, uint32 BgObjectType void BattlegroundEY::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) { - BattlegroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found + BattlegroundScoreMap::iterator itr = PlayerScores.find(Source->GetGUID()); + if (itr == PlayerScores.end()) // player not found return; switch (type) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h index baa9ca30cff..026fbccc320 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h @@ -217,8 +217,8 @@ enum EYBattlegroundObjectTypes BG_EY_OBJECT_MAX = 59 }; -#define BG_EY_NotEYWeekendHonorTicks 330 -#define BG_EY_EYWeekendHonorTicks 200 +#define BG_EY_NotEYWeekendHonorTicks 260 +#define BG_EY_EYWeekendHonorTicks 160 #define EY_EVENT_START_BATTLE 13180 // Achievement: Flurry diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index 90d5d7b9939..c72fcfdb3a7 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -28,13 +28,13 @@ BattlegroundIC::BattlegroundIC() { - m_BgObjects.resize(MAX_NORMAL_GAMEOBJECTS_SPAWNS + MAX_AIRSHIPS_SPAWNS + MAX_HANGAR_TELEPORTERS_SPAWNS + MAX_FORTRESS_TELEPORTERS_SPAWNS); - m_BgCreatures.resize(MAX_NORMAL_NPCS_SPAWNS + MAX_WORKSHOP_SPAWNS + MAX_DOCKS_SPAWNS + MAX_SPIRIT_GUIDES_SPAWNS); + BgObjects.resize(MAX_NORMAL_GAMEOBJECTS_SPAWNS + MAX_AIRSHIPS_SPAWNS + MAX_HANGAR_TELEPORTERS_SPAWNS + MAX_FORTRESS_TELEPORTERS_SPAWNS); + BgCreatures.resize(MAX_NORMAL_NPCS_SPAWNS + MAX_WORKSHOP_SPAWNS + MAX_DOCKS_SPAWNS + MAX_SPIRIT_GUIDES_SPAWNS); - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_IC_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_IC_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_IC_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_IC_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_IC_START_TWO_MINUTES; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_IC_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_IC_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_IC_HAS_BEGUN; for (uint8 i = 0; i < 2; i++) factionReinforcements[i] = MAX_REINFORCEMENTS; @@ -175,9 +175,9 @@ void BattlegroundIC::PostUpdateImpl(uint32 diff) { if (siege->isAlive()) { - if (siege->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_UNK_14|UNIT_FLAG_OOC_NOT_ATTACKABLE)) + if (siege->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_UNK_14|UNIT_FLAG_IMMUNE_TO_PC)) // following sniffs the vehicle always has UNIT_FLAG_UNK_14 - siege->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE); + siege->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_IMMUNE_TO_PC); else siege->SetHealth(siege->GetMaxHealth()); } @@ -298,7 +298,7 @@ void BattlegroundIC::AddPlayer(Player* player) //create score and add it to map, default values are set in constructor BattlegroundICScore* sc = new BattlegroundICScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; if (nodePoint[NODE_TYPE_QUARRY].nodeState == (player->GetTeamId() == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H)) player->CastSpell(player, SPELL_QUARRY, true); @@ -327,9 +327,9 @@ void BattlegroundIC::HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) void BattlegroundIC::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) { - std::map<uint64, BattlegroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID()); + std::map<uint64, BattlegroundScore*>::iterator itr = PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... + if (itr == PlayerScores.end()) // player not found... return; switch (type) @@ -476,7 +476,7 @@ void BattlegroundIC::EndBattleground(uint32 winner) void BattlegroundIC::RealocatePlayers(ICNodePointType nodeType) { // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard - std::vector<uint64> ghost_list = m_ReviveQueue[m_BgCreatures[BG_IC_NPC_SPIRIT_GUIDE_1+nodeType-2]]; + std::vector<uint64> ghost_list = m_ReviveQueue[BgCreatures[BG_IC_NPC_SPIRIT_GUIDE_1+nodeType-2]]; if (!ghost_list.empty()) { WorldSafeLocsEntry const* ClosestGrave = NULL; @@ -528,7 +528,7 @@ void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* target // if we are here means that the point has been lost, or it is the first capture if (nodePoint[i].nodeType != NODE_TYPE_REFINERY && nodePoint[i].nodeType != NODE_TYPE_QUARRY) - if (m_BgCreatures[BG_IC_NPC_SPIRIT_GUIDE_1+(nodePoint[i].nodeType)-2]) + if (BgCreatures[BG_IC_NPC_SPIRIT_GUIDE_1+(nodePoint[i].nodeType)-2]) DelCreature(BG_IC_NPC_SPIRIT_GUIDE_1+(nodePoint[i].nodeType)-2); UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); @@ -793,7 +793,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture) if (Creature* siegeEngine = GetBGCreature(siegeType)) { - siegeEngine->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_UNK_14|UNIT_FLAG_OOC_NOT_ATTACKABLE); + siegeEngine->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_UNK_14|UNIT_FLAG_IMMUNE_TO_PC); siegeEngine->setFaction(BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]); } } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp index cee8cb2b4da..0974c96a991 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp @@ -26,17 +26,17 @@ BattlegroundNA::BattlegroundNA() { - m_BgObjects.resize(BG_NA_OBJECT_MAX); + BgObjects.resize(BG_NA_OBJECT_MAX); - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattlegroundNA::~BattlegroundNA() @@ -65,7 +65,7 @@ void BattlegroundNA::AddPlayer(Player* player) //create score and add it to map, default values are set in constructor BattlegroundNAScore* sc = new BattlegroundNAScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; UpdateArenaWorldState(); } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRB.cpp index c304c194a71..98985b41b5a 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRB.cpp @@ -24,10 +24,10 @@ BattlegroundRB::BattlegroundRB() { //TODO FIX ME! - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = 0; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = 0; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; } BattlegroundRB::~BattlegroundRB() @@ -49,7 +49,7 @@ void BattlegroundRB::AddPlayer(Player* player) //create score and add it to map, default values are set in constructor BattlegroundRBScore* sc = new BattlegroundRBScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; } void BattlegroundRB::RemovePlayer(Player* /*player*/, uint64 /*guid*/, uint32 /*team*/) @@ -65,9 +65,9 @@ void BattlegroundRB::HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) void BattlegroundRB::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) { - std::map<uint64, BattlegroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID()); + std::map<uint64, BattlegroundScore*>::iterator itr = PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... + if (itr == PlayerScores.end()) // player not found... return; Battleground::UpdatePlayerScore(Source, type, value, doAddHonor); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp index f1602507cc1..6a626217a4e 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp @@ -26,17 +26,17 @@ BattlegroundRL::BattlegroundRL() { - m_BgObjects.resize(BG_RL_OBJECT_MAX); + BgObjects.resize(BG_RL_OBJECT_MAX); - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattlegroundRL::~BattlegroundRL() @@ -65,7 +65,7 @@ void BattlegroundRL::AddPlayer(Player* player) //create score and add it to map, default values are set in constructor BattlegroundRLScore* sc = new BattlegroundRLScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; UpdateArenaWorldState(); } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp index 539419d6c50..98bb704661e 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp @@ -26,17 +26,17 @@ BattlegroundRV::BattlegroundRV() { - m_BgObjects.resize(BG_RV_OBJECT_MAX); + BgObjects.resize(BG_RV_OBJECT_MAX); - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; } BattlegroundRV::~BattlegroundRV() @@ -63,6 +63,7 @@ void BattlegroundRV::PostUpdateImpl(uint32 diff) case BG_RV_STATE_OPEN_PILARS: for (uint8 i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_PULLEY_2; ++i) DoorOpen(i); + TogglePillarCollision(false); setTimer(BG_RV_PILAR_TO_FIRE_TIMER); setState(BG_RV_STATE_OPEN_FIRE); break; @@ -76,6 +77,7 @@ void BattlegroundRV::PostUpdateImpl(uint32 diff) case BG_RV_STATE_CLOSE_PILARS: for (uint8 i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_PULLEY_2; ++i) DoorOpen(i); + TogglePillarCollision(true); setTimer(BG_RV_PILAR_TO_FIRE_TIMER); setState(BG_RV_STATE_CLOSE_FIRE); break; @@ -100,6 +102,8 @@ void BattlegroundRV::StartingEventOpenDoors() setState(BG_RV_STATE_OPEN_FENCES); setTimer(BG_RV_FIRST_TIMER); + + TogglePillarCollision(true); } void BattlegroundRV::AddPlayer(Player* player) @@ -108,7 +112,7 @@ void BattlegroundRV::AddPlayer(Player* player) //create score and add it to map, default values are set in constructor BattlegroundRVScore* sc = new BattlegroundRVScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE)); UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE)); @@ -207,13 +211,13 @@ bool BattlegroundRV::SetupBattleground() || !AddObject(BG_RV_OBJECT_PILAR_2, BG_RV_OBJECT_TYPE_PILAR_2, 723.644287f, -284.493256f, 24.648525f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY) || !AddObject(BG_RV_OBJECT_PILAR_3, BG_RV_OBJECT_TYPE_PILAR_3, 763.611145f, -261.856750f, 25.909504f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY) || !AddObject(BG_RV_OBJECT_PILAR_4, BG_RV_OBJECT_TYPE_PILAR_4, 802.211609f, -284.493256f, 24.648525f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY) -/* - // Pilars Collision - Fixme: Use the collision pilars - should make u break LoS + + // Pilars Collision || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_1, BG_RV_OBJECT_TYPE_PILAR_COLLISION_1, 763.632385f, -306.162384f, 30.639660f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY) || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_2, BG_RV_OBJECT_TYPE_PILAR_COLLISION_2, 723.644287f, -284.493256f, 32.382710f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY) || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_3, BG_RV_OBJECT_TYPE_PILAR_COLLISION_3, 763.611145f, -261.856750f, 30.639660f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY) || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_4, BG_RV_OBJECT_TYPE_PILAR_COLLISION_4, 802.211609f, -284.493256f, 32.382710f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY) -*/ + ) { sLog->outErrorDb("BatteGroundRV: Failed to spawn some object!"); @@ -221,3 +225,28 @@ bool BattlegroundRV::SetupBattleground() } return true; } + + +void BattlegroundRV::TogglePillarCollision(bool apply) +{ + for (uint8 i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_PILAR_COLLISION_4; ++i) + { + if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[i])) + { + if (i >= BG_RV_OBJECT_PILAR_COLLISION_1) + { + uint32 _state = GO_STATE_READY; + if (gob->GetGOInfo()->door.startOpen) + _state = GO_STATE_ACTIVE; + gob->SetGoState(apply ? (GOState)_state : (GOState)(!_state)); + + if (gob->GetGOInfo()->door.startOpen) + gob->EnableCollision(!apply); // Forced collision toggle + } + + for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER))) + gob->SendUpdateToPlayer(player); + } + } +}
\ No newline at end of file diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRV.h b/src/server/game/Battlegrounds/Zones/BattlegroundRV.h index 4f99af268db..1dfd4825c8f 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRV.h @@ -38,12 +38,12 @@ enum BattlegroundRVObjectTypes BG_RV_OBJECT_PILAR_4, BG_RV_OBJECT_PULLEY_1, BG_RV_OBJECT_PULLEY_2, -/* + BG_RV_OBJECT_PILAR_COLLISION_1, BG_RV_OBJECT_PILAR_COLLISION_2, BG_RV_OBJECT_PILAR_COLLISION_3, BG_RV_OBJECT_PILAR_COLLISION_4, -*/ + BG_RV_OBJECT_ELEVATOR_1, BG_RV_OBJECT_ELEVATOR_2, BG_RV_OBJECT_MAX, @@ -64,12 +64,12 @@ enum BattlegroundRVObjects BG_RV_OBJECT_TYPE_GEAR_2 = 192394, BG_RV_OBJECT_TYPE_ELEVATOR_1 = 194582, BG_RV_OBJECT_TYPE_ELEVATOR_2 = 194586, -/* + BG_RV_OBJECT_TYPE_PILAR_COLLISION_1 = 194580, // axe BG_RV_OBJECT_TYPE_PILAR_COLLISION_2 = 194579, // arena BG_RV_OBJECT_TYPE_PILAR_COLLISION_3 = 194581, // lightning BG_RV_OBJECT_TYPE_PILAR_COLLISION_4 = 194578, // ivory -*/ + BG_RV_OBJECT_TYPE_PILAR_1 = 194583, // axe BG_RV_OBJECT_TYPE_PILAR_2 = 194584, // arena BG_RV_OBJECT_TYPE_PILAR_3 = 194585, // lightning @@ -129,5 +129,6 @@ class BattlegroundRV : public Battleground uint32 getState() { return State; }; void setState(uint32 state) { State = state; }; + void TogglePillarCollision(bool apply); }; #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp index ed51d843b46..b7792e10ae3 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp @@ -26,12 +26,12 @@ BattlegroundSA::BattlegroundSA() { - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_SA_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_SA_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_SA_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_SA_HAS_BEGUN; - m_BgObjects.resize(BG_SA_MAXOBJ); - m_BgCreatures.resize(BG_SA_MAXNPC + BG_SA_MAX_GY); + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_SA_START_TWO_MINUTES; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_SA_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_SA_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_SA_HAS_BEGUN; + BgObjects.resize(BG_SA_MAXOBJ); + BgCreatures.resize(BG_SA_MAXNPC + BG_SA_MAX_GY); TimerEnabled = false; UpdateWaitTimer = 0; SignaledRoundTwo = false; @@ -460,7 +460,7 @@ void BattlegroundSA::AddPlayer(Player* player) player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0); } SendTransportInit(player); - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; } void BattlegroundSA::RemovePlayer(Player* /*player*/, uint64 /*guid*/, uint32 /*team*/) @@ -476,8 +476,8 @@ void BattlegroundSA::HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) void BattlegroundSA::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) { - BattlegroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... + BattlegroundScoreMap::iterator itr = PlayerScores.find(Source->GetGUID()); + if (itr == PlayerScores.end()) // player not found... return; if (type == SCORE_DESTROYED_DEMOLISHER) @@ -563,7 +563,7 @@ void BattlegroundSA::HandleKillUnit(Creature* unit, Player* killer) */ void BattlegroundSA::OverrideGunFaction() { - if (!m_BgCreatures[0]) + if (!BgCreatures[0]) return; for (uint8 i = BG_SA_GUN_1; i <= BG_SA_GUN_10;i++) @@ -581,7 +581,7 @@ void BattlegroundSA::OverrideGunFaction() void BattlegroundSA::DemolisherStartState(bool start) { - if (!m_BgCreatures[0]) + if (!BgCreatures[0]) return; for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++) @@ -863,7 +863,7 @@ void BattlegroundSA::UpdateDemolisherSpawns() { for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++) { - if (m_BgCreatures[i]) + if (BgCreatures[i]) { if (Creature* Demolisher = GetBGCreature(i)) { @@ -898,12 +898,13 @@ void BattlegroundSA::UpdateDemolisherSpawns() void BattlegroundSA::SendTransportInit(Player* player) { - if (m_BgObjects[BG_SA_BOAT_ONE] || m_BgObjects[BG_SA_BOAT_TWO]) + if (BgObjects[BG_SA_BOAT_ONE] || BgObjects[BG_SA_BOAT_TWO]) { UpdateData transData(player->GetMapId()); - if (m_BgObjects[BG_SA_BOAT_ONE]) + if (BgObjects[BG_SA_BOAT_ONE]) + GetBGObject(BG_SA_BOAT_ONE)->BuildCreateUpdateBlockForPlayer(&transData, player); - if (m_BgObjects[BG_SA_BOAT_TWO]) + if (BgObjects[BG_SA_BOAT_TWO]) GetBGObject(BG_SA_BOAT_TWO)->BuildCreateUpdateBlockForPlayer(&transData, player); WorldPacket packet; transData.BuildPacket(&packet); @@ -913,12 +914,12 @@ void BattlegroundSA::SendTransportInit(Player* player) void BattlegroundSA::SendTransportsRemove(Player* player) { - if (m_BgObjects[BG_SA_BOAT_ONE] || m_BgObjects[BG_SA_BOAT_TWO]) + if (BgObjects[BG_SA_BOAT_ONE] || BgObjects[BG_SA_BOAT_TWO]) { UpdateData transData(player->GetMapId()); - if (m_BgObjects[BG_SA_BOAT_ONE]) + if (BgObjects[BG_SA_BOAT_ONE]) GetBGObject(BG_SA_BOAT_ONE)->BuildOutOfRangeUpdateBlock(&transData); - if (m_BgObjects[BG_SA_BOAT_TWO]) + if (BgObjects[BG_SA_BOAT_TWO]) GetBGObject(BG_SA_BOAT_TWO)->BuildOutOfRangeUpdateBlock(&transData); WorldPacket packet; transData.BuildPacket(&packet); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp index 226bf172a09..9650cf11a8c 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -42,20 +42,15 @@ uint32 BG_WSG_Honor[BG_HONOR_MODE_NUM][BG_WSG_REWARD_NUM] = { {60, 40, 80} // holiday }; -uint32 BG_WSG_Reputation[BG_HONOR_MODE_NUM][BG_WSG_REWARD_NUM] = { - {0, 35, 0}, // normal honor - {0, 45, 0} // holiday -}; - BattlegroundWS::BattlegroundWS() { - m_BgObjects.resize(BG_WS_OBJECT_MAX); - m_BgCreatures.resize(BG_CREATURES_MAX_WS); + BgObjects.resize(BG_WS_OBJECT_MAX); + BgCreatures.resize(BG_CREATURES_MAX_WS); - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; + StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; } BattlegroundWS::~BattlegroundWS() @@ -75,96 +70,93 @@ void BattlegroundWS::PostUpdateImpl(uint32 diff) else // Horde has more points and thus wins EndBattleground(HORDE); } - else if (GetTeamScore(HORDE) == 0) EndBattleground(ALLIANCE); // Alliance has > 0, Horde has 0, alliance wins - else if (GetTeamScore(HORDE) == GetTeamScore(ALLIANCE)) // Team score equal, winner is team that scored the last flag - EndBattleground(m_LastFlagCaptureTeam); - + EndBattleground(_lastFlagCaptureTeam); else if (GetTeamScore(HORDE) > GetTeamScore(ALLIANCE)) // Last but not least, check who has the higher score EndBattleground(HORDE); else EndBattleground(ALLIANCE); } - else if (GetStartTime() > uint32(m_minutesElapsed * MINUTE * IN_MILLISECONDS)) + else if (GetStartTime() > uint32(_minutesElapsed * MINUTE * IN_MILLISECONDS)) { - ++m_minutesElapsed; - UpdateWorldState(BG_WS_STATE_TIMER, 25 - m_minutesElapsed); + ++_minutesElapsed; + UpdateWorldState(BG_WS_STATE_TIMER, 25 - _minutesElapsed); } - if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) + if (_flagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) { - m_FlagsTimer[BG_TEAM_ALLIANCE] -= diff; + _flagsTimer[BG_TEAM_ALLIANCE] -= diff; - if (m_FlagsTimer[BG_TEAM_ALLIANCE] < 0) + if (_flagsTimer[BG_TEAM_ALLIANCE] < 0) { - m_FlagsTimer[BG_TEAM_ALLIANCE] = 0; + _flagsTimer[BG_TEAM_ALLIANCE] = 0; RespawnFlag(ALLIANCE, true); } } - if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND) + if (_flagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND) { - m_FlagsDropTimer[BG_TEAM_ALLIANCE] -= diff; + _flagsDropTimer[BG_TEAM_ALLIANCE] -= diff; - if (m_FlagsDropTimer[BG_TEAM_ALLIANCE] < 0) + if (_flagsDropTimer[BG_TEAM_ALLIANCE] < 0) { - m_FlagsDropTimer[BG_TEAM_ALLIANCE] = 0; + _flagsDropTimer[BG_TEAM_ALLIANCE] = 0; RespawnFlagAfterDrop(ALLIANCE); - m_BothFlagsKept = false; + _bothFlagsKept = false; } } - if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) + if (_flagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) { - m_FlagsTimer[BG_TEAM_HORDE] -= diff; + _flagsTimer[BG_TEAM_HORDE] -= diff; - if (m_FlagsTimer[BG_TEAM_HORDE] < 0) + if (_flagsTimer[BG_TEAM_HORDE] < 0) { - m_FlagsTimer[BG_TEAM_HORDE] = 0; + _flagsTimer[BG_TEAM_HORDE] = 0; RespawnFlag(HORDE, true); } } - if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND) + if (_flagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND) { - m_FlagsDropTimer[BG_TEAM_HORDE] -= diff; + _flagsDropTimer[BG_TEAM_HORDE] -= diff; - if (m_FlagsDropTimer[BG_TEAM_HORDE] < 0) + if (_flagsDropTimer[BG_TEAM_HORDE] < 0) { - m_FlagsDropTimer[BG_TEAM_HORDE] = 0; + _flagsDropTimer[BG_TEAM_HORDE] = 0; RespawnFlagAfterDrop(HORDE); - m_BothFlagsKept = false; + _bothFlagsKept = false; } } - if (m_BothFlagsKept) + if (_bothFlagsKept) { - m_FlagSpellForceTimer += diff; - if (m_FlagDebuffState == 0 && m_FlagSpellForceTimer >= 600000) //10 minutes - { - if (Player* player = ObjectAccessor::FindPlayer(m_FlagKeepers[0])) - player->CastSpell(player, WS_SPELL_FOCUSED_ASSAULT, true); - if (Player* player = ObjectAccessor::FindPlayer(m_FlagKeepers[1])) - player->CastSpell(player, WS_SPELL_FOCUSED_ASSAULT, true); - m_FlagDebuffState = 1; - } - else if (m_FlagDebuffState == 1 && m_FlagSpellForceTimer >= 900000) //15 minutes - { - if (Player* player = ObjectAccessor::FindPlayer(m_FlagKeepers[0])) + _flagSpellForceTimer += diff; + if (_flagDebuffState == 0 && _flagSpellForceTimer >= 10*MINUTE*IN_MILLISECONDS) //10 minutes { - player->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - player->CastSpell(player, WS_SPELL_BRUTAL_ASSAULT, true); + if (Player* player = ObjectAccessor::FindPlayer(m_FlagKeepers[0])) + player->CastSpell(player, WS_SPELL_FOCUSED_ASSAULT, true); + if (Player* player = ObjectAccessor::FindPlayer(m_FlagKeepers[1])) + player->CastSpell(player, WS_SPELL_FOCUSED_ASSAULT, true); + _flagDebuffState = 1; } - if (Player* player = ObjectAccessor::FindPlayer(m_FlagKeepers[1])) + else if (_flagDebuffState == 1 && _flagSpellForceTimer >= 900000) //15 minutes { - player->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - player->CastSpell(player, WS_SPELL_BRUTAL_ASSAULT, true); + if (Player* player = ObjectAccessor::FindPlayer(m_FlagKeepers[0])) + { + player->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); + player->CastSpell(player, WS_SPELL_BRUTAL_ASSAULT, true); + } + if (Player* player = ObjectAccessor::FindPlayer(m_FlagKeepers[1])) + { + player->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); + player->CastSpell(player, WS_SPELL_BRUTAL_ASSAULT, true); + } + _flagDebuffState = 2; } - m_FlagDebuffState = 2; - } } else { - m_FlagSpellForceTimer = 0; //reset timer. - m_FlagDebuffState = 0; + _flagSpellForceTimer = 0; //reset timer. + _flagDebuffState = 0; } } } @@ -208,7 +200,7 @@ void BattlegroundWS::AddPlayer(Player* player) //create score and add it to map, default values are set in constructor BattlegroundWGScore* sc = new BattlegroundWGScore; - m_PlayerScores[player->GetGUID()] = sc; + PlayerScores[player->GetGUID()] = sc; } void BattlegroundWS::RespawnFlag(uint32 Team, bool captured) @@ -216,12 +208,12 @@ void BattlegroundWS::RespawnFlag(uint32 Team, bool captured) if (Team == ALLIANCE) { sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Respawn Alliance flag"); - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; + _flagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; } else { sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Respawn Horde flag"); - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; + _flagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; } if (captured) @@ -232,7 +224,7 @@ void BattlegroundWS::RespawnFlag(uint32 Team, bool captured) SendMessageToAll(LANG_BG_WS_F_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL); PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); // flag respawned sound... } - m_BothFlagsKept = false; + _bothFlagsKept = false; } void BattlegroundWS::RespawnFlagAfterDrop(uint32 team) @@ -260,7 +252,7 @@ void BattlegroundWS::RespawnFlagAfterDrop(uint32 team) sLog->outError("unknown droped flag bg, guid: %u", GUID_LOPART(GetDroppedFlagGUID(team))); SetDroppedFlagGUID(0, team); - m_BothFlagsKept = false; + _bothFlagsKept = false; } void BattlegroundWS::EventPlayerCapturedFlag(Player* Source) @@ -277,12 +269,12 @@ void BattlegroundWS::EventPlayerCapturedFlag(Player* Source) return; SetHordeFlagPicker(0); // must be before aura remove to prevent 2 events (drop+capture) at the same time // horde flag in base (but not respawned yet) - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; + _flagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; // Drop Horde Flag from Player Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); - if (m_FlagDebuffState == 1) + if (_flagDebuffState == 1) Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - if (m_FlagDebuffState == 2) + if (_flagDebuffState == 2) Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); if (GetTeamScore(ALLIANCE) < BG_WS_MAX_TEAM_SCORE) AddPoint(ALLIANCE, 1); @@ -295,12 +287,12 @@ void BattlegroundWS::EventPlayerCapturedFlag(Player* Source) return; SetAllianceFlagPicker(0); // must be before aura remove to prevent 2 events (drop+capture) at the same time // alliance flag in base (but not respawned yet) - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; + _flagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; // Drop Alliance Flag from Player Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); - if (m_FlagDebuffState == 1) + if (_flagDebuffState == 1) Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - if (m_FlagDebuffState == 2) + if (_flagDebuffState == 2) Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); if (GetTeamScore(HORDE) < BG_WS_MAX_TEAM_SCORE) AddPoint(HORDE, 1); @@ -345,7 +337,7 @@ void BattlegroundWS::EventPlayerCapturedFlag(Player* Source) } else { - m_FlagsTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_RESPAWN_TIME; + _flagsTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_RESPAWN_TIME; } } @@ -388,11 +380,11 @@ void BattlegroundWS::EventPlayerDroppedFlag(Player* Source) { SetHordeFlagPicker(0); Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); - if (m_FlagDebuffState == 1) + if (_flagDebuffState == 1) Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - if (m_FlagDebuffState == 2) + if (_flagDebuffState == 2) Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_GROUND; + _flagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_GROUND; Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true); set = true; } @@ -405,11 +397,11 @@ void BattlegroundWS::EventPlayerDroppedFlag(Player* Source) { SetAllianceFlagPicker(0); Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); - if (m_FlagDebuffState == 1) + if (_flagDebuffState == 1) Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - if (m_FlagDebuffState == 2) + if (_flagDebuffState == 2) Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_GROUND; + _flagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_GROUND; Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true); set = true; } @@ -431,7 +423,7 @@ void BattlegroundWS::EventPlayerDroppedFlag(Player* Source) UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, uint32(-1)); } - m_FlagsDropTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_DROP_TIME; + _flagsDropTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_DROP_TIME; } } @@ -445,40 +437,40 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target //alliance flag picked up from base if (Source->GetTeam() == HORDE && this->GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE - && this->m_BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID()) + && this->BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID()) { message_id = LANG_BG_WS_PICKEDUP_AF; type = CHAT_MSG_BG_SYSTEM_HORDE; PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); SetAllianceFlagPicker(Source->GetGUID()); - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; + _flagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; //update world state to show correct flag carrier UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER); UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1); Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG, true); Source->GetAchievementMgr().StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_SILVERWING_FLAG_PICKED); - if (m_FlagState[1] == BG_WS_FLAG_STATE_ON_PLAYER) - m_BothFlagsKept = true; + if (_flagState[1] == BG_WS_FLAG_STATE_ON_PLAYER) + _bothFlagsKept = true; } //horde flag picked up from base if (Source->GetTeam() == ALLIANCE && this->GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE - && this->m_BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID()) + && this->BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID()) { message_id = LANG_BG_WS_PICKEDUP_HF; type = CHAT_MSG_BG_SYSTEM_ALLIANCE; PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); SetHordeFlagPicker(Source->GetGUID()); - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; + _flagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; //update world state to show correct flag carrier UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER); UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1); Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG, true); Source->GetAchievementMgr().StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_WARSONG_FLAG_PICKED); - if (m_FlagState[0] == BG_WS_FLAG_STATE_ON_PLAYER) - m_BothFlagsKept = true; + if (_flagState[0] == BG_WS_FLAG_STATE_ON_PLAYER) + _bothFlagsKept = true; } //Alliance flag on ground(not in base) (returned or picked up again from ground!) @@ -493,7 +485,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); UpdatePlayerScore(Source, SCORE_FLAG_RETURNS, 1); - m_BothFlagsKept = false; + _bothFlagsKept = false; } else { @@ -503,11 +495,11 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); SetAllianceFlagPicker(Source->GetGUID()); Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG, true); - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; + _flagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER); - if (m_FlagDebuffState == 1) + if (_flagDebuffState == 1) Source->CastSpell(Source, WS_SPELL_FOCUSED_ASSAULT, true); - if (m_FlagDebuffState == 2) + if (_flagDebuffState == 2) Source->CastSpell(Source, WS_SPELL_BRUTAL_ASSAULT, true); UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1); } @@ -527,7 +519,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); UpdatePlayerScore(Source, SCORE_FLAG_RETURNS, 1); - m_BothFlagsKept = false; + _bothFlagsKept = false; } else { @@ -537,11 +529,11 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); SetHordeFlagPicker(Source->GetGUID()); Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG, true); - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; + _flagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER); - if (m_FlagDebuffState == 1) + if (_flagDebuffState == 1) Source->CastSpell(Source, WS_SPELL_FOCUSED_ASSAULT, true); - if (m_FlagDebuffState == 2) + if (_flagDebuffState == 2) Source->CastSpell(Source, WS_SPELL_BRUTAL_ASSAULT, true); UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1); } @@ -610,30 +602,30 @@ void BattlegroundWS::HandleAreaTrigger(Player* Source, uint32 Trigger) switch (Trigger) { case 3686: // Alliance elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in Battleground::Update(). - //buff_guid = m_BgObjects[BG_WS_OBJECT_SPEEDBUFF_1]; + //buff_guid = BgObjects[BG_WS_OBJECT_SPEEDBUFF_1]; break; case 3687: // Horde elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in Battleground::Update(). - //buff_guid = m_BgObjects[BG_WS_OBJECT_SPEEDBUFF_2]; + //buff_guid = BgObjects[BG_WS_OBJECT_SPEEDBUFF_2]; break; case 3706: // Alliance elixir of regeneration spawn - //buff_guid = m_BgObjects[BG_WS_OBJECT_REGENBUFF_1]; + //buff_guid = BgObjects[BG_WS_OBJECT_REGENBUFF_1]; break; case 3708: // Horde elixir of regeneration spawn - //buff_guid = m_BgObjects[BG_WS_OBJECT_REGENBUFF_2]; + //buff_guid = BgObjects[BG_WS_OBJECT_REGENBUFF_2]; break; case 3707: // Alliance elixir of berserk spawn - //buff_guid = m_BgObjects[BG_WS_OBJECT_BERSERKBUFF_1]; + //buff_guid = BgObjects[BG_WS_OBJECT_BERSERKBUFF_1]; break; case 3709: // Horde elixir of berserk spawn - //buff_guid = m_BgObjects[BG_WS_OBJECT_BERSERKBUFF_2]; + //buff_guid = BgObjects[BG_WS_OBJECT_BERSERKBUFF_2]; break; case 3646: // Alliance Flag spawn - if (m_FlagState[BG_TEAM_HORDE] && !m_FlagState[BG_TEAM_ALLIANCE]) + if (_flagState[BG_TEAM_HORDE] && !_flagState[BG_TEAM_ALLIANCE]) if (GetFlagPickerGUID(BG_TEAM_HORDE) == Source->GetGUID()) EventPlayerCapturedFlag(Source); break; case 3647: // Horde Flag spawn - if (m_FlagState[BG_TEAM_ALLIANCE] && !m_FlagState[BG_TEAM_HORDE]) + if (_flagState[BG_TEAM_ALLIANCE] && !_flagState[BG_TEAM_HORDE]) if (GetFlagPickerGUID(BG_TEAM_ALLIANCE) == Source->GetGUID()) EventPlayerCapturedFlag(Source); break; @@ -710,8 +702,8 @@ void BattlegroundWS::Reset() m_FlagKeepers[BG_TEAM_HORDE] = 0; m_DroppedFlagGUID[BG_TEAM_ALLIANCE] = 0; m_DroppedFlagGUID[BG_TEAM_HORDE] = 0; - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; + _flagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; + _flagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; m_TeamScores[BG_TEAM_ALLIANCE] = 0; m_TeamScores[BG_TEAM_HORDE] = 0; bool isBGWeekend = sBattlegroundMgr->IsBGWeekend(GetTypeID()); @@ -719,13 +711,13 @@ void BattlegroundWS::Reset() m_HonorWinKills = (isBGWeekend) ? 3 : 1; m_HonorEndKills = (isBGWeekend) ? 4 : 2; // For WorldState - m_minutesElapsed = 0; - m_LastFlagCaptureTeam = 0; + _minutesElapsed = 0; + _lastFlagCaptureTeam = 0; /* Spirit nodes is static at this BG and then not required deleting at BG reset. - if (m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE]) + if (BgCreatures[WS_SPIRIT_MAIN_ALLIANCE]) DelCreature(WS_SPIRIT_MAIN_ALLIANCE); - if (m_BgCreatures[WS_SPIRIT_MAIN_HORDE]) + if (BgCreatures[WS_SPIRIT_MAIN_HORDE]) DelCreature(WS_SPIRIT_MAIN_HORDE); */ } @@ -757,8 +749,8 @@ void BattlegroundWS::HandleKillPlayer(Player* player, Player* killer) void BattlegroundWS::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) { - BattlegroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found + BattlegroundScoreMap::iterator itr = PlayerScores.find(Source->GetGUID()); + if (itr == PlayerScores.end()) // player not found return; switch (type) @@ -805,16 +797,16 @@ void BattlegroundWS::FillInitialWorldStates(WorldPacket& data) data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(ALLIANCE)); data << uint32(BG_WS_FLAG_CAPTURES_HORDE) << uint32(GetTeamScore(HORDE)); - if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND) + if (_flagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND) data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(-1); - else if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER) + else if (_flagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER) data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(1); else data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(0); - if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND) + if (_flagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND) data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(-1); - else if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER) + else if (_flagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER) data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(1); else data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(0); @@ -824,17 +816,17 @@ void BattlegroundWS::FillInitialWorldStates(WorldPacket& data) if (GetStatus() == STATUS_IN_PROGRESS) { data << uint32(BG_WS_STATE_TIMER_ACTIVE) << uint32(1); - data << uint32(BG_WS_STATE_TIMER) << uint32(25-m_minutesElapsed); + data << uint32(BG_WS_STATE_TIMER) << uint32(25-_minutesElapsed); } else data << uint32(BG_WS_STATE_TIMER_ACTIVE) << uint32(0); - if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER) + if (_flagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER) data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(2); else data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(1); - if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER) + if (_flagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER) data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(2); else data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(1); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h index 063d04253a5..a014840f273 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h @@ -180,7 +180,7 @@ class BattlegroundWS : public Battleground bool IsHordeFlagPickedup() const { return m_FlagKeepers[BG_TEAM_HORDE] != 0; } void RespawnFlag(uint32 Team, bool captured); void RespawnFlagAfterDrop(uint32 Team); - uint8 GetFlagState(uint32 team) { return m_FlagState[GetTeamIndexByTeamId(team)]; } + uint8 GetFlagState(uint32 team) { return _flagState[GetTeamIndexByTeamId(team)]; } /* Battleground Events */ virtual void EventPlayerDroppedFlag(Player* Source); @@ -196,7 +196,7 @@ class BattlegroundWS : public Battleground virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); void UpdateFlagState(uint32 team, uint32 value); - void SetLastFlagCapture(uint32 team) { m_LastFlagCaptureTeam = team; } + void SetLastFlagCapture(uint32 team) { _lastFlagCaptureTeam = team; } void UpdateTeamScore(uint32 team); void UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor = true); void SetDroppedFlagGUID(uint64 guid, uint32 TeamID) { m_DroppedFlagGUID[GetTeamIndexByTeamId(TeamID)] = guid;} @@ -211,18 +211,18 @@ class BattlegroundWS : public Battleground private: uint64 m_FlagKeepers[2]; // 0 - alliance, 1 - horde uint64 m_DroppedFlagGUID[2]; - uint8 m_FlagState[2]; // for checking flag state - int32 m_FlagsTimer[2]; - int32 m_FlagsDropTimer[2]; - uint32 m_LastFlagCaptureTeam; // Winner is based on this if score is equal + uint8 _flagState[2]; // for checking flag state + int32 _flagsTimer[2]; + int32 _flagsDropTimer[2]; + uint32 _lastFlagCaptureTeam; // Winner is based on this if score is equal uint32 m_ReputationCapture; uint32 m_HonorWinKills; uint32 m_HonorEndKills; - int32 m_FlagSpellForceTimer; - bool m_BothFlagsKept; - uint8 m_FlagDebuffState; // 0 - no debuffs, 1 - focused assault, 2 - brutal assault - uint8 m_minutesElapsed; + int32 _flagSpellForceTimer; + bool _bothFlagsKept; + uint8 _flagDebuffState; // 0 - no debuffs, 1 - focused assault, 2 - brutal assault + uint8 _minutesElapsed; virtual void PostUpdateImpl(uint32 diff); }; diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index 745e5962eb6..1f680f6e9b0 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -30,7 +30,7 @@ file(GLOB_RECURSE sources_Globals Globals/*.cpp Globals/*.h) file(GLOB_RECURSE sources_Grids Grids/*.cpp Grids/*.h) file(GLOB_RECURSE sources_Groups Groups/*.cpp Groups/*.h) file(GLOB_RECURSE sources_Guilds Guilds/*.cpp Guilds/*.h) -file(GLOB_RECURSE sources_Handlers Handlers/*.cpp Server/*.h) +file(GLOB_RECURSE sources_Handlers Handlers/*.cpp Handlers/*.h) file(GLOB_RECURSE sources_Instances Instances/*.cpp Instances/*.h) file(GLOB_RECURSE sources_Loot Loot/*.cpp Loot/*.h) file(GLOB_RECURSE sources_Mails Mails/*.cpp Mails/*.h) @@ -48,6 +48,7 @@ file(GLOB_RECURSE sources_Spells Spells/*.cpp Spells/*.h) file(GLOB_RECURSE sources_Texts Texts/*.cpp Texts/*.h) file(GLOB_RECURSE sources_Tools Tools/*.cpp Tools/*.h) file(GLOB_RECURSE sources_Tickets Tickets/*.cpp Tickets/*.h) +file(GLOB_RECURSE sources_Warden Warden/*.cpp Warden/*.h) file(GLOB_RECURSE sources_Weather Weather/*.cpp Weather/*.h) file(GLOB_RECURSE sources_World World/*.cpp World/*.h) @@ -98,6 +99,7 @@ set(game_STAT_SRCS ${sources_Texts} ${sources_Tools} ${sources_Tickets} + ${sources_Warden} ${sources_Weather} ${sources_World} ) @@ -110,6 +112,8 @@ include_directories( ${CMAKE_SOURCE_DIR}/dep/zlib ${CMAKE_SOURCE_DIR}/src/server/collision ${CMAKE_SOURCE_DIR}/src/server/collision/Management + ${CMAKE_SOURCE_DIR}/src/server/collision/Models + ${CMAKE_SOURCE_DIR}/src/server/collision/Maps ${CMAKE_SOURCE_DIR}/src/server/shared ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography @@ -189,6 +193,8 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Texts ${CMAKE_CURRENT_SOURCE_DIR}/Tools ${CMAKE_CURRENT_SOURCE_DIR}/Tickets + ${CMAKE_CURRENT_SOURCE_DIR}/Warden + ${CMAKE_CURRENT_SOURCE_DIR}/Warden/Modules ${CMAKE_CURRENT_SOURCE_DIR}/Weather ${CMAKE_CURRENT_SOURCE_DIR}/World ${CMAKE_SOURCE_DIR}/src/server/scripts/PrecompiledHeaders diff --git a/src/server/game/Chat/Commands/Level1.cpp b/src/server/game/Chat/Commands/Level1.cpp index 5c51d2b1bb5..2a57dce77a4 100755 --- a/src/server/game/Chat/Commands/Level1.cpp +++ b/src/server/game/Chat/Commands/Level1.cpp @@ -558,8 +558,8 @@ bool ChatHandler::HandleLookupTeleCommand(const char * args) uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); bool limitReached = false; - GameTeleMap const & teleMap = sObjectMgr->GetGameTeleMap(); - for (GameTeleMap::const_iterator itr = teleMap.begin(); itr != teleMap.end(); ++itr) + GameTeleContainer const & teleMap = sObjectMgr->GetGameTeleMap(); + for (GameTeleContainer::const_iterator itr = teleMap.begin(); itr != teleMap.end(); ++itr) { GameTele const* tele = &itr->second; diff --git a/src/server/game/Chat/Commands/TicketCommands.cpp b/src/server/game/Chat/Commands/TicketCommands.cpp index 138466f9623..177899efbf0 100755 --- a/src/server/game/Chat/Commands/TicketCommands.cpp +++ b/src/server/game/Chat/Commands/TicketCommands.cpp @@ -257,7 +257,7 @@ bool ChatHandler::HandleGMTicketUnAssignCommand(const char* args) ticket->SaveToDB(trans); sTicketMgr->UpdateLastChange(); - std::string msg = ticket->FormatMessageString(*this, NULL, ticket->GetAssignedToName().c_str(), + std::string msg = ticket->FormatMessageString(*this, NULL, ticket->GetAssignedToName().c_str(), m_session ? m_session->GetPlayer()->GetName() : "Console", NULL); SendGlobalGMSysMessage(msg.c_str()); return true; diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index a745c5a2f13..7d21f94f372 100755 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -26,209 +26,426 @@ #include "ConditionMgr.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "Spell.h" -// Checks if player meets the condition +// Checks if object meets the condition // Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI) -bool Condition::Meets(Player* player, Unit* invoker) +bool Condition::Meets(ConditionSourceInfo& sourceInfo) { - if (!player) + ASSERT(ConditionTarget < MAX_CONDITION_TARGETS); + WorldObject* object = sourceInfo.mConditionTargets[ConditionTarget]; + // object not present, return false + if (!object) { - sLog->outDebug(LOG_FILTER_CONDITIONSYS, "Condition player not found"); - return false; // player not present, return false + sLog->outDebug(LOG_FILTER_CONDITIONSYS, "Condition object not found for condition (Entry: %u Type: %u Group: %u)", SourceEntry, SourceType, SourceGroup); + return false; } - uint32 refId = mConditionValue3;//value 3 can be a 'quick' reference bool condMeets = false; - bool sendErrorMsg = false; - switch (mConditionType) + switch (ConditionType) { case CONDITION_NONE: condMeets = true; // empty condition, always met break; case CONDITION_AURA: - refId = 0; - if (!mConditionValue3) - condMeets = player->HasAuraEffect(mConditionValue1, mConditionValue2); - else if (Unit* target = player->GetSelectedUnit()) - condMeets = target->HasAuraEffect(mConditionValue1, mConditionValue2); + { + if (Unit* unit = object->ToUnit()) + condMeets = unit->HasAuraEffect(ConditionValue1, ConditionValue2); break; + } case CONDITION_ITEM: - condMeets = (mConditionValue2 && player->HasItemCount(mConditionValue1, mConditionValue2)) || (!mConditionValue2 && !player->HasItemCount(mConditionValue1, mConditionValue2));//HasItemCount returns false if 0 count is used + { + if (Player* player = object->ToPlayer()) + { + // don't allow 0 items (it's checked during table load) + ASSERT(ConditionValue2); + bool checkBank = ConditionValue3 ? true : false; + condMeets = player->HasItemCount(ConditionValue1, ConditionValue2, checkBank); + } break; + } case CONDITION_ITEM_EQUIPPED: - condMeets = player->HasItemOrGemWithIdEquipped(mConditionValue1, 1); + { + if (Player* player = object->ToPlayer()) + condMeets = player->HasItemOrGemWithIdEquipped(ConditionValue1, 1); break; + } case CONDITION_ZONEID: - condMeets = player->GetZoneId() == mConditionValue1; + condMeets = object->GetZoneId() == ConditionValue1; break; case CONDITION_REPUTATION_RANK: { - if (FactionEntry const* faction = sFactionStore.LookupEntry(mConditionValue1)) - condMeets = (mConditionValue2 & (1 << player->GetReputationMgr().GetRank(faction))); + if (Player* player = object->ToPlayer()) + { + if (FactionEntry const* faction = sFactionStore.LookupEntry(ConditionValue1)) + condMeets = (ConditionValue2 & (1 << player->GetReputationMgr().GetRank(faction))); + } break; } case CONDITION_ACHIEVEMENT: - condMeets = player->GetAchievementMgr().HasAchieved(mConditionValue1); + { + if (Player* player = object->ToPlayer()) + condMeets = player->GetAchievementMgr().HasAchieved(ConditionValue1); break; + } case CONDITION_TEAM: - condMeets = player->GetTeam() == mConditionValue1; + { + if (Player* player = object->ToPlayer()) + condMeets = player->GetTeam() == ConditionValue1; break; + } case CONDITION_CLASS: - condMeets = player->getClassMask() & mConditionValue1; + { + if (Unit* unit = object->ToUnit()) + condMeets = unit->getClassMask() & ConditionValue1; break; + } case CONDITION_RACE: - condMeets = player->getRaceMask() & mConditionValue1; + { + if (Unit* unit = object->ToUnit()) + condMeets = unit->getRaceMask() & ConditionValue1; break; + } case CONDITION_SKILL: - condMeets = player->HasSkill(mConditionValue1) && player->GetBaseSkillValue(mConditionValue1) >= mConditionValue2; + { + if (Player* player = object->ToPlayer()) + condMeets = player->HasSkill(ConditionValue1) && player->GetBaseSkillValue(ConditionValue1) >= ConditionValue2; break; + } case CONDITION_QUESTREWARDED: - condMeets = (player->GetQuestRewardStatus(mConditionValue1) == !mConditionValue2); + { + if (Player* player = object->ToPlayer()) + condMeets = (player->GetQuestRewardStatus(ConditionValue1) == !ConditionValue2); break; + } case CONDITION_QUESTTAKEN: { - QuestStatus status = player->GetQuestStatus(mConditionValue1); - condMeets = ((status == QUEST_STATUS_INCOMPLETE) == !mConditionValue2); + if (Player* player = object->ToPlayer()) + { + QuestStatus status = player->GetQuestStatus(ConditionValue1); + condMeets = ((status == QUEST_STATUS_INCOMPLETE) == !ConditionValue2); + } break; } case CONDITION_QUEST_COMPLETE: { - QuestStatus status = player->GetQuestStatus(mConditionValue1); - condMeets = ((status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(mConditionValue1)) == !mConditionValue2); + if (Player* player = object->ToPlayer()) + { + QuestStatus status = player->GetQuestStatus(ConditionValue1); + condMeets = ((status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(ConditionValue1)) == !ConditionValue2); + } break; } case CONDITION_QUEST_NONE: { - QuestStatus status = player->GetQuestStatus(mConditionValue1); - condMeets = ((status == QUEST_STATUS_NONE) == !mConditionValue2); + if (Player* player = object->ToPlayer()) + { + QuestStatus status = player->GetQuestStatus(ConditionValue1); + condMeets = ((status == QUEST_STATUS_NONE) == !ConditionValue2); + } break; } - case CONDITION_NO_AURA: - condMeets = !player->HasAuraEffect(mConditionValue1, mConditionValue2); - break; case CONDITION_ACTIVE_EVENT: - condMeets = sGameEventMgr->IsActiveEvent(mConditionValue1); + condMeets = sGameEventMgr->IsActiveEvent(ConditionValue1); break; case CONDITION_INSTANCE_DATA: { - Map* map = player->GetMap(); + Map* map = object->GetMap(); if (map && map->IsDungeon() && ((InstanceMap*)map)->GetInstanceScript()) - condMeets = ((InstanceMap*)map)->GetInstanceScript()->GetData(mConditionValue1) == mConditionValue2; + condMeets = ((InstanceMap*)map)->GetInstanceScript()->GetData(ConditionValue1) == ConditionValue2; break; } - case CONDITION_SPELL_SCRIPT_TARGET: - condMeets = true;//spell target condition is handled in spellsystem, here it is always true - refId = 0;//cant have references! use CONDITION_SOURCE_TYPE_SPELL for it + case CONDITION_MAPID: + condMeets = object->GetMapId() == ConditionValue1; break; - case CONDITION_CREATURE_TARGET: + case CONDITION_AREAID: + condMeets = object->GetAreaId() == ConditionValue1; + break; + case CONDITION_SPELL: { - Unit* target = player->GetSelectedUnit(); - if (target) - if (Creature* cTarget = target->ToCreature()) - if (cTarget->GetEntry() == mConditionValue1) - condMeets = true; + if (Player* player = object->ToPlayer()) + condMeets = player->HasSpell(ConditionValue1); break; } - case CONDITION_TARGET_HEALTH_BELOW_PCT: + case CONDITION_LEVEL: { - Unit* target = player->GetSelectedUnit(); - if (target) - condMeets = !target->HealthAbovePct(mConditionValue1); + if (Unit* unit = object->ToUnit()) + condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), static_cast<uint32>(unit->getLevel()), ConditionValue1); break; } - case CONDITION_TARGET_RANGE: + case CONDITION_DRUNKENSTATE: { - if (Unit* target = player->GetSelectedUnit()) - if (player->GetDistance(target) >= mConditionValue1 && (!mConditionValue2 || player->GetDistance(target) <= mConditionValue2)) - condMeets = true; + if (Player* player = object->ToPlayer()) + condMeets = (uint32)Player::GetDrunkenstateByValue(player->GetDrunkValue()) >= ConditionValue1; break; } - case CONDITION_MAPID: - condMeets = player->GetMapId() == mConditionValue1; + case CONDITION_NEAR_CREATURE: + { + condMeets = GetClosestCreatureWithEntry(object, ConditionValue1, (float)ConditionValue2) ? true : false; break; - case CONDITION_AREAID: - condMeets = player->GetAreaId() == mConditionValue1; + } + case CONDITION_NEAR_GAMEOBJECT: + { + condMeets = GetClosestGameObjectWithEntry(object, ConditionValue1, (float)ConditionValue2) ? true : false; break; - case CONDITION_ITEM_TARGET: + } + case CONDITION_OBJECT_ENTRY: { - condMeets = true;//handled in Item::IsTargetValidForItemUse - refId = 0;//cant have references for now + if (object->GetTypeId() == ConditionValue1) + condMeets = (!ConditionValue2) || (object->GetEntry() == ConditionValue2); break; } - case CONDITION_SPELL: - if (mConditionValue2 == 1) - condMeets = player->HasSpell(mConditionValue1); - else - condMeets = !player->HasSpell(mConditionValue1); + case CONDITION_TYPE_MASK: + { + condMeets = object->isType(ConditionValue1); break; - case CONDITION_NOITEM: - condMeets = !player->HasItemCount(mConditionValue1, 1, mConditionValue2 ? true : false); + } + case CONDITION_RELATION_TO: + { + if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1]) + { + Unit* toUnit = toObject->ToUnit(); + Unit* unit = object->ToUnit(); + if (toUnit && unit) + { + switch (ConditionValue2) + { + case RELATION_SELF: + condMeets = unit == toUnit; + break; + case RELATION_IN_PARTY: + condMeets = unit->IsInPartyWith(toUnit); + break; + case RELATION_IN_RAID_OR_PARTY: + condMeets = unit->IsInRaidWith(toUnit); + break; + case RELATION_OWNED_BY: + condMeets = unit->GetOwnerGUID() == toUnit->GetGUID(); + break; + case RELATION_PASSENGER_OF: + condMeets = unit->IsOnVehicle(toUnit); + break; + } + } + } break; - case CONDITION_LEVEL: + } + case CONDITION_REACTION_TO: { - switch (mConditionValue2) + if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1]) { - case LVL_COND_EQ: - condMeets = player->getLevel() == mConditionValue1; - break; - case LVL_COND_HIGH: - condMeets = player->getLevel() > mConditionValue1; - break; - case LVL_COND_LOW: - condMeets = player->getLevel() < mConditionValue1; - break; - case LVL_COND_HIGH_EQ: - condMeets = player->getLevel() >= mConditionValue1; - break; - case LVL_COND_LOW_EQ: - condMeets = player->getLevel() <= mConditionValue1; - break; + Unit* toUnit = toObject->ToUnit(); + Unit* unit = object->ToUnit(); + if (toUnit && unit) + condMeets = (1 << unit->GetReactionTo(toUnit)) & ConditionValue2; } break; } - case CONDITION_DRUNKENSTATE: + case CONDITION_DISTANCE_TO: { - condMeets = (uint32)Player::GetDrunkenstateByValue(player->GetDrunkValue()) >= mConditionValue1; + if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1]) + condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue3), object->GetDistance(toObject), static_cast<float>(ConditionValue2)); break; } - case CONDITION_NEAR_CREATURE: + case CONDITION_ALIVE: { - condMeets = GetClosestCreatureWithEntry(player, mConditionValue1, (float)mConditionValue2) ? true : false; + if (Unit* unit = object->ToUnit()) + condMeets = unit->isAlive(); break; } - case CONDITION_NEAR_GAMEOBJECT: + case CONDITION_HP_VAL: + { + if (Unit* unit = object->ToUnit()) + condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealth(), static_cast<uint32>(ConditionValue1)); + break; + } + case CONDITION_HP_PCT: { - condMeets = GetClosestGameObjectWithEntry(player, mConditionValue1, (float)mConditionValue2) ? true : false; + if (Unit* unit = object->ToUnit()) + condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealthPct(), static_cast<float>(ConditionValue1)); + break; + } + case CONDITION_WORLD_STATE: + { + condMeets = ConditionValue2 == sWorld->getWorldState(ConditionValue1); + break; + } + case CONDITION_PHASEMASK: + { + condMeets = object->GetPhaseMask() & ConditionValue1; break; } default: condMeets = false; - refId = 0; break; } - switch (mSourceType) + + if (NegativeCondition) + condMeets = !condMeets; + + if (!condMeets) + sourceInfo.mLastFailedCondition = this; + + bool script = sScriptMgr->OnConditionCheck(this, sourceInfo); // Returns true by default. + return condMeets && script; +} + +uint32 Condition::GetSearcherTypeMaskForCondition() +{ + // build mask of types for which condition can return true + // this is used for speeding up gridsearches + if (NegativeCondition) + return (GRID_MAP_TYPE_MASK_ALL); + uint32 mask = 0; + switch (ConditionType) { - case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET: - case CONDITION_SOURCE_TYPE_SPELL: - sendErrorMsg = true; + case CONDITION_NONE: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; + case CONDITION_AURA: + mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_ITEM: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_ITEM_EQUIPPED: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_ZONEID: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; + case CONDITION_REPUTATION_RANK: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_ACHIEVEMENT: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_TEAM: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_CLASS: + mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_RACE: + mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_SKILL: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_QUESTREWARDED: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_QUESTTAKEN: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_QUEST_COMPLETE: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_QUEST_NONE: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_ACTIVE_EVENT: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; + case CONDITION_INSTANCE_DATA: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; + case CONDITION_MAPID: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; + case CONDITION_AREAID: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; + case CONDITION_SPELL: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_LEVEL: + mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_DRUNKENSTATE: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_NEAR_CREATURE: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; + case CONDITION_NEAR_GAMEOBJECT: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; + case CONDITION_OBJECT_ENTRY: + switch (ConditionValue1) + { + case TYPEID_UNIT: + mask |= GRID_MAP_TYPE_MASK_CREATURE; + break; + case TYPEID_PLAYER: + mask |= GRID_MAP_TYPE_MASK_PLAYER; + break; + case TYPEID_GAMEOBJECT: + mask |= GRID_MAP_TYPE_MASK_GAMEOBJECT; + break; + case TYPEID_CORPSE: + mask |= GRID_MAP_TYPE_MASK_CORPSE; + break; + default: + break; + } + case CONDITION_TYPE_MASK: + if (ConditionValue1 & TYPEMASK_UNIT) + mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; + if (ConditionValue1 & TYPEMASK_PLAYER) + mask |= GRID_MAP_TYPE_MASK_PLAYER; + if (ConditionValue1 & TYPEMASK_GAMEOBJECT) + mask |= GRID_MAP_TYPE_MASK_GAMEOBJECT; + if (ConditionValue1 & TYPEMASK_CORPSE) + mask |= GRID_MAP_TYPE_MASK_CORPSE; + break; + case CONDITION_RELATION_TO: + mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_REACTION_TO: + mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_DISTANCE_TO: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; + case CONDITION_ALIVE: + mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_HP_VAL: + mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_HP_PCT: + mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER; + break; + case CONDITION_WORLD_STATE: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; + case CONDITION_PHASEMASK: + mask |= GRID_MAP_TYPE_MASK_ALL; break; default: + ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!"); break; } + return mask; +} - bool refMeets = false; - if (condMeets && refId)//only have to check references if 'this' is met +uint32 Condition::GetMaxAvailableConditionTargets() +{ + // returns number of targets which are available for given source type + switch(SourceType) { - ConditionList ref = sConditionMgr->GetConditionReferences(refId); - refMeets = sConditionMgr->IsPlayerMeetToConditions(player, ref); + case CONDITION_SOURCE_TYPE_SPELL: + case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET: + case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE: + case CONDITION_SOURCE_TYPE_VEHICLE_SPELL: + case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT: + case CONDITION_SOURCE_TYPE_GOSSIP_MENU: + case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION: + case CONDITION_SOURCE_TYPE_SMART_EVENT: + return 2; + default: + return 1; } - else - refMeets = true; - - if (sendErrorMsg && ErrorTextd && (!condMeets || !refMeets))//send special error from DB - player->m_ConditionErrorMsgId = ErrorTextd; - - bool script = sScriptMgr->OnConditionCheck(this, player, invoker); // Returns true by default. - return condMeets && refMeets && script; } ConditionMgr::ConditionMgr() @@ -249,39 +466,80 @@ ConditionList ConditionMgr::GetConditionReferences(uint32 refId) return conditions; } -bool ConditionMgr::IsPlayerMeetToConditionList(Player* player, ConditionList const& conditions, Unit* invoker /*= NULL*/) +uint32 ConditionMgr::GetSearcherTypeMaskForConditionList(ConditionList const& conditions) +{ + if (conditions.empty()) + return GRID_MAP_TYPE_MASK_ALL; + // groupId, typeMask + std::map<uint32, uint32> ElseGroupStore; + for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i) + { + // no point of having not loaded conditions in list + ASSERT((*i)->isLoaded() && "ConditionMgr::GetSearcherTypeMaskForConditionList - not yet loaded condition found in list"); + std::map<uint32, uint32>::const_iterator itr = ElseGroupStore.find((*i)->ElseGroup); + // group not filled yet, fill with widest mask possible + if (itr == ElseGroupStore.end()) + ElseGroupStore[(*i)->ElseGroup] = GRID_MAP_TYPE_MASK_ALL; + // no point of checking anymore, empty mask + else if (!(*itr).second) + continue; + + if ((*i)->ReferenceId) // handle reference + { + ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId); + ASSERT(ref != ConditionReferenceStore.end() && "ConditionMgr::GetSearcherTypeMaskForConditionList - incorrect reference"); + ElseGroupStore[(*i)->ElseGroup] &= GetSearcherTypeMaskForConditionList((*ref).second); + } + else // handle normal condition + { + // object will match conditions in one ElseGroupStore only when it matches all of them + // so, let's find a smallest possible mask which satisfies all conditions + ElseGroupStore[(*i)->ElseGroup] &= (*i)->GetSearcherTypeMaskForCondition(); + } + } + // object will match condition when one of the checks in ElseGroupStore is matching + // so, let's include all possible masks + uint32 mask = 0; + for (std::map<uint32, uint32>::const_iterator i = ElseGroupStore.begin(); i != ElseGroupStore.end(); ++i) + mask |= i->second; + + return mask; +} + +bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions) { + // groupId, groupCheckPassed std::map<uint32, bool> ElseGroupStore; for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i) { - sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsPlayerMeetToConditionList condType: %u val1: %u", (*i)->mConditionType, (*i)->mConditionValue1); + sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsPlayerMeetToConditionList condType: %u val1: %u", (*i)->ConditionType, (*i)->ConditionValue1); if ((*i)->isLoaded()) { - std::map<uint32, bool>::const_iterator itr = ElseGroupStore.find((*i)->mElseGroup); + std::map<uint32, bool>::const_iterator itr = ElseGroupStore.find((*i)->ElseGroup); if (itr == ElseGroupStore.end()) - ElseGroupStore[(*i)->mElseGroup] = true; + ElseGroupStore[(*i)->ElseGroup] = true; else if (!(*itr).second) continue; - if ((*i)->mReferenceId)//handle reference + if ((*i)->ReferenceId)//handle reference { - ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->mReferenceId); + ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId); if (ref != ConditionReferenceStore.end()) { - if (!IsPlayerMeetToConditionList(player, (*ref).second, invoker)) - ElseGroupStore[(*i)->mElseGroup] = false; + if (!IsObjectMeetToConditionList(sourceInfo, (*ref).second)) + ElseGroupStore[(*i)->ElseGroup] = false; } else { sLog->outDebug(LOG_FILTER_CONDITIONSYS, "IsPlayerMeetToConditionList: Reference template -%u not found", - (*i)->mReferenceId);//checked at loading, should never happen + (*i)->ReferenceId);//checked at loading, should never happen } } else //handle normal condition { - if (!(*i)->Meets(player, invoker)) - ElseGroupStore[(*i)->mElseGroup] = false; + if (!(*i)->Meets(sourceInfo)) + ElseGroupStore[(*i)->ElseGroup] = false; } } } @@ -292,21 +550,52 @@ bool ConditionMgr::IsPlayerMeetToConditionList(Player* player, ConditionList con return false; } -bool ConditionMgr::IsPlayerMeetToConditions(Player* player, ConditionList const& conditions, Unit* invoker /*= NULL*/) +bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions) +{ + ConditionSourceInfo srcInfo = ConditionSourceInfo(object); + return IsObjectMeetToConditions(srcInfo, conditions); +} + +bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions) +{ + ConditionSourceInfo srcInfo = ConditionSourceInfo(object1, object2); + return IsObjectMeetToConditions(srcInfo, conditions); +} + +bool ConditionMgr::IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions) { if (conditions.empty()) return true; - if (player) - player->m_ConditionErrorMsgId = 0; - - sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsPlayerMeetToConditions"); - bool result = IsPlayerMeetToConditionList(player, conditions, invoker); + sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsObjectMeetToConditions"); + return IsObjectMeetToConditionList(sourceInfo, conditions); +} - if (player && player->m_ConditionErrorMsgId && player->GetSession() && !result) - player->GetSession()->SendNotification(player->m_ConditionErrorMsgId); //m_ConditionErrorMsgId is set only if a condition was not met +bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const +{ + return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU || + sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION || + sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL || + sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET || + sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT || + sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT); +} - return result; +bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType) const +{ + return (sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT); } ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry) @@ -328,33 +617,50 @@ ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType return spellCond; } -ConditionList ConditionMgr::GetConditionsForVehicleSpell(uint32 creatureID, uint32 spellID) + +ConditionList ConditionMgr::GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId) { ConditionList cond; - VehicleSpellConditionContainer::const_iterator itr = VehicleSpellConditionStore.find(creatureID); + CreatureSpellConditionContainer::const_iterator itr = SpellClickEventConditionStore.find(creatureId); + if (itr != SpellClickEventConditionStore.end()) + { + ConditionTypeContainer::const_iterator i = (*itr).second.find(spellId); + if (i != (*itr).second.end()) + { + cond = (*i).second; + sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForSpellClickEvent: found conditions for Vehicle entry %u spell %u", creatureId, spellId); + } + } + return cond; +} + +ConditionList ConditionMgr::GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId) +{ + ConditionList cond; + CreatureSpellConditionContainer::const_iterator itr = VehicleSpellConditionStore.find(creatureId); if (itr != VehicleSpellConditionStore.end()) { - ConditionTypeContainer::const_iterator i = (*itr).second.find(spellID); + ConditionTypeContainer::const_iterator i = (*itr).second.find(spellId); if (i != (*itr).second.end()) { cond = (*i).second; - sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForVehicleSpell: found conditions for Vehicle entry %u spell %u", creatureID, spellID); + sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForVehicleSpell: found conditions for Vehicle entry %u spell %u", creatureId, spellId); } } return cond; } -ConditionList ConditionMgr::GetConditionsForSmartEvent(uint32 entry, uint32 eventId, uint32 sourceType) +ConditionList ConditionMgr::GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType) { ConditionList cond; - SmartEventConditionContainer::const_iterator itr = SmartEventConditionStore.find(std::make_pair(entry, sourceType)); + SmartEventConditionContainer::const_iterator itr = SmartEventConditionStore.find(std::make_pair(entryOrGuid, sourceType)); if (itr != SmartEventConditionStore.end()) { ConditionTypeContainer::const_iterator i = (*itr).second.find(eventId + 1); if (i != (*itr).second.end()) { cond = (*i).second; - sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForSmartEvent: found conditions for Smart Event entry %u event_id %u", entry, eventId); + sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForSmartEvent: found conditions for Smart Event entry or guid %d event_id %u", entryOrGuid, eventId); } } return cond; @@ -388,10 +694,11 @@ void ConditionMgr::LoadConditions(bool isReload) sLog->outString("Re-Loading `gossip_menu_option` Table for Conditions!"); sObjectMgr->LoadGossipMenuItems(); + sSpellMgr->UnloadSpellInfoImplicitTargetConditionLists(); } - QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, " - " ConditionValue1, ConditionValue2, ConditionValue3, ErrorTextId, ScriptName FROM conditions"); + QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, " + " ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorTextId, ScriptName FROM conditions"); if (!result) { @@ -409,19 +716,24 @@ void ConditionMgr::LoadConditions(bool isReload) Condition* cond = new Condition(); int32 iSourceTypeOrReferenceId = fields[0].GetInt32(); - cond->mSourceGroup = fields[1].GetUInt32(); - cond->mSourceEntry = fields[2].GetUInt32(); - cond->mSourceId = fields[3].GetUInt32(); - cond->mElseGroup = fields[4].GetUInt32(); + cond->SourceGroup = fields[1].GetUInt32(); + cond->SourceEntry = fields[2].GetInt32(); + cond->SourceId = fields[3].GetUInt32(); + cond->ElseGroup = fields[4].GetUInt32(); int32 iConditionTypeOrReference = fields[5].GetInt32(); - cond->mConditionValue1 = fields[6].GetUInt32(); - cond->mConditionValue2 = fields[7].GetUInt32(); - cond->mConditionValue3 = fields[8].GetUInt32(); - cond->ErrorTextd = fields[9].GetUInt32(); - cond->mScriptId = sObjectMgr->GetScriptId(fields[10].GetCString()); + cond->ConditionTarget = fields[6].GetUInt8(); + cond->ConditionValue1 = fields[7].GetUInt32(); + cond->ConditionValue2 = fields[8].GetUInt32(); + cond->ConditionValue3 = fields[9].GetUInt32(); + cond->NegativeCondition = fields[10].GetUInt8(); + cond->ErrorTextId = fields[11].GetUInt32(); + cond->ScriptId = sObjectMgr->GetScriptId(fields[12].GetCString()); if (iConditionTypeOrReference >= 0) - cond->mConditionType = ConditionType(iConditionTypeOrReference); + cond->ConditionType = ConditionTypes(iConditionTypeOrReference); + + if (iSourceTypeOrReferenceId >= 0) + cond->SourceType = ConditionSourceType(iSourceTypeOrReferenceId); if (iConditionTypeOrReference < 0)//it has a reference { @@ -431,22 +743,26 @@ void ConditionMgr::LoadConditions(bool isReload) delete cond; continue; } - cond->mReferenceId = uint32(abs(iConditionTypeOrReference)); + cond->ReferenceId = uint32(abs(iConditionTypeOrReference)); const char* rowType = "reference template"; if (iSourceTypeOrReferenceId >= 0) rowType = "reference"; //check for useless data - if (cond->mConditionValue1) - sLog->outErrorDb("Condition %s %i has useless data in value1 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue1); - if (cond->mConditionValue2) - sLog->outErrorDb("Condition %s %i has useless data in value2 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue2); - if (cond->mConditionValue3) - sLog->outErrorDb("Condition %s %i has useless data in value3 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue3); - if (cond->mSourceGroup && iSourceTypeOrReferenceId < 0) - sLog->outErrorDb("Condition %s %i has useless data in SourceGroup (%u)!", rowType, iSourceTypeOrReferenceId, cond->mSourceGroup); - if (cond->mSourceEntry && iSourceTypeOrReferenceId < 0) - sLog->outErrorDb("Condition %s %i has useless data in SourceEntry (%u)!", rowType, iSourceTypeOrReferenceId, cond->mSourceEntry); + if (cond->ConditionTarget) + sLog->outErrorDb("Condition %s %i has useless data in ConditionTarget (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionTarget); + if (cond->ConditionValue1) + sLog->outErrorDb("Condition %s %i has useless data in value1 (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue1); + if (cond->ConditionValue2) + sLog->outErrorDb("Condition %s %i has useless data in value2 (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Condition %s %i has useless data in value3 (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue3); + if (cond->NegativeCondition) + sLog->outErrorDb("Condition %s %i has useless data in NegativeCondition (%u)!", rowType, iSourceTypeOrReferenceId, cond->NegativeCondition); + if (cond->SourceGroup && iSourceTypeOrReferenceId < 0) + sLog->outErrorDb("Condition %s %i has useless data in SourceGroup (%u)!", rowType, iSourceTypeOrReferenceId, cond->SourceGroup); + if (cond->SourceEntry && iSourceTypeOrReferenceId < 0) + sLog->outErrorDb("Condition %s %i has useless data in SourceEntry (%u)!", rowType, iSourceTypeOrReferenceId, cond->SourceEntry); } else if (!isConditionTypeValid(cond))//doesn't have reference, validate ConditionType { @@ -467,8 +783,6 @@ void ConditionMgr::LoadConditions(bool isReload) continue; }//end of reference templates - cond->mSourceType = ConditionSourceType(iSourceTypeOrReferenceId); - //if not a reference and SourceType is invalid, skip if (iConditionTypeOrReference >= 0 && !isSourceTypeValid(cond)) { @@ -477,53 +791,60 @@ void ConditionMgr::LoadConditions(bool isReload) } //Grouping is only allowed for some types (loot templates, gossip menus, gossip items) - if (cond->mSourceGroup && !isGroupable(cond->mSourceType)) + if (cond->SourceGroup && !CanHaveSourceGroupSet(cond->SourceType)) { - sLog->outErrorDb("Condition type %u has not allowed grouping %u!", uint32(cond->mSourceType), cond->mSourceGroup); + sLog->outErrorDb("Condition type %u has not allowed value of SourceGroup = %u!", uint32(cond->SourceType), cond->SourceGroup); delete cond; continue; } - else if (cond->mSourceGroup) + if (cond->SourceId && !CanHaveSourceIdSet(cond->SourceType)) + { + sLog->outErrorDb("Condition type %u has not allowed value of SourceId = %u!", uint32(cond->SourceType), cond->SourceId); + delete cond; + continue; + } + + if (cond->SourceGroup) { bool valid = false; - //handle grouped conditions - switch (cond->mSourceType) + // handle grouped conditions + switch (cond->SourceType) { case CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Creature.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Creature.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Disenchant.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Disenchant.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Fishing.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Fishing.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Gameobject.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Gameobject.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Item.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Item.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Mail.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Mail.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Milling.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Milling.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Pickpocketing.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Pickpocketing.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Prospecting.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Prospecting.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Reference.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Reference.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Skinning.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Skinning.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE: - valid = addToLootTemplate(cond, LootTemplates_Spell.GetLootForConditionFill(cond->mSourceGroup)); + valid = addToLootTemplate(cond, LootTemplates_Spell.GetLootForConditionFill(cond->SourceGroup)); break; case CONDITION_SOURCE_TYPE_GOSSIP_MENU: valid = addToGossipMenus(cond); @@ -531,21 +852,44 @@ void ConditionMgr::LoadConditions(bool isReload) case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION: valid = addToGossipMenuItems(cond); break; + case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT: + { + //if no list for npc create one + if (SpellClickEventConditionStore.find(cond->SourceGroup) == SpellClickEventConditionStore.end()) + { + ConditionTypeContainer cmap; + SpellClickEventConditionStore[cond->SourceGroup] = cmap; + } + //if no list for spellclick spell create one + if (SpellClickEventConditionStore[cond->SourceGroup].find(cond->SourceEntry) == SpellClickEventConditionStore[cond->SourceGroup].end()) + { + ConditionList clist; + SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry] = clist; + } + SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond); + valid = true; + ++count; + continue; // do not add to m_AllocatedMemory to avoid double deleting + break; + } + case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET: + valid = addToSpellImplicitTargetConditions(cond); + break; case CONDITION_SOURCE_TYPE_VEHICLE_SPELL: { //if no list for vehicle create one - if (VehicleSpellConditionStore.find(cond->mSourceGroup) == VehicleSpellConditionStore.end()) + if (VehicleSpellConditionStore.find(cond->SourceGroup) == VehicleSpellConditionStore.end()) { ConditionTypeContainer cmap; - VehicleSpellConditionStore[cond->mSourceGroup] = cmap; + VehicleSpellConditionStore[cond->SourceGroup] = cmap; } //if no list for vehicle's spell create one - if (VehicleSpellConditionStore[cond->mSourceGroup].find(cond->mSourceEntry) == VehicleSpellConditionStore[cond->mSourceGroup].end()) + if (VehicleSpellConditionStore[cond->SourceGroup].find(cond->SourceEntry) == VehicleSpellConditionStore[cond->SourceGroup].end()) { ConditionList clist; - VehicleSpellConditionStore[cond->mSourceGroup][cond->mSourceEntry] = clist; + VehicleSpellConditionStore[cond->SourceGroup][cond->SourceEntry] = clist; } - VehicleSpellConditionStore[cond->mSourceGroup][cond->mSourceEntry].push_back(cond); + VehicleSpellConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond); valid = true; ++count; continue; // do not add to m_AllocatedMemory to avoid double deleting @@ -553,18 +897,18 @@ void ConditionMgr::LoadConditions(bool isReload) case CONDITION_SOURCE_TYPE_SMART_EVENT: { // If the entry does not exist, create a new list - std::pair<uint32, uint32> key = std::make_pair(cond->mSourceEntry, cond->mSourceId); + std::pair<int32, uint32> key = std::make_pair(cond->SourceEntry, cond->SourceId); if (SmartEventConditionStore.find(key) == SmartEventConditionStore.end()) { ConditionTypeContainer cmap; SmartEventConditionStore[key] = cmap; } - if (SmartEventConditionStore[key].find(cond->mSourceGroup) == SmartEventConditionStore[key].end()) + if (SmartEventConditionStore[key].find(cond->SourceGroup) == SmartEventConditionStore[key].end()) { ConditionList clist; - SmartEventConditionStore[key][cond->mSourceGroup] = clist; + SmartEventConditionStore[key][cond->SourceGroup] = clist; } - SmartEventConditionStore[key][cond->mSourceGroup].push_back(cond); + SmartEventConditionStore[key][cond->SourceGroup].push_back(cond); valid = true; ++count; continue; @@ -575,7 +919,7 @@ void ConditionMgr::LoadConditions(bool isReload) if (!valid) { - sLog->outErrorDb("Not handled grouped condition, SourceGroup %u", cond->mSourceGroup); + sLog->outErrorDb("Not handled grouped condition, SourceGroup %u", cond->SourceGroup); delete cond; } else @@ -588,21 +932,21 @@ void ConditionMgr::LoadConditions(bool isReload) //handle not grouped conditions //make sure we have a storage list for our SourceType - if (ConditionStore.find(cond->mSourceType) == ConditionStore.end()) + if (ConditionStore.find(cond->SourceType) == ConditionStore.end()) { ConditionTypeContainer mTypeMap; - ConditionStore[cond->mSourceType] = mTypeMap;//add new empty list for SourceType + ConditionStore[cond->SourceType] = mTypeMap;//add new empty list for SourceType } //make sure we have a condition list for our SourceType's entry - if (ConditionStore[cond->mSourceType].find(cond->mSourceEntry) == ConditionStore[cond->mSourceType].end()) + if (ConditionStore[cond->SourceType].find(cond->SourceEntry) == ConditionStore[cond->SourceType].end()) { ConditionList mCondList; - ConditionStore[cond->mSourceType][cond->mSourceEntry] = mCondList; + ConditionStore[cond->SourceType][cond->SourceEntry] = mCondList; } //add new Condition to storage based on Type/Entry - ConditionStore[cond->mSourceType][cond->mSourceEntry].push_back(cond); + ConditionStore[cond->SourceType][cond->SourceEntry].push_back(cond); ++count; } while (result->NextRow()); @@ -615,26 +959,26 @@ bool ConditionMgr::addToLootTemplate(Condition* cond, LootTemplate* loot) { if (!loot) { - sLog->outErrorDb("ConditionMgr: LootTemplate %u not found", cond->mSourceGroup); + sLog->outErrorDb("ConditionMgr: LootTemplate %u not found", cond->SourceGroup); return false; } if (loot->addConditionItem(cond)) return true; - sLog->outErrorDb("ConditionMgr: Item %u not found in LootTemplate %u", cond->mSourceEntry, cond->mSourceGroup); + sLog->outErrorDb("ConditionMgr: Item %u not found in LootTemplate %u", cond->SourceEntry, cond->SourceGroup); return false; } bool ConditionMgr::addToGossipMenus(Condition* cond) { - GossipMenusMapBoundsNonConst pMenuBounds = sObjectMgr->GetGossipMenusMapBoundsNonConst(cond->mSourceGroup); + GossipMenusMapBoundsNonConst pMenuBounds = sObjectMgr->GetGossipMenusMapBoundsNonConst(cond->SourceGroup); if (pMenuBounds.first != pMenuBounds.second) { - for (GossipMenusMap::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr) + for (GossipMenusContainer::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr) { - if ((*itr).second.entry == cond->mSourceGroup && (*itr).second.text_id == cond->mSourceEntry) + if ((*itr).second.entry == cond->SourceGroup && (*itr).second.text_id == uint32(cond->SourceEntry)) { (*itr).second.conditions.push_back(cond); return true; @@ -642,18 +986,18 @@ bool ConditionMgr::addToGossipMenus(Condition* cond) } } - sLog->outErrorDb("addToGossipMenus: GossipMenu %u not found", cond->mSourceGroup); + sLog->outErrorDb("addToGossipMenus: GossipMenu %u not found", cond->SourceGroup); return false; } bool ConditionMgr::addToGossipMenuItems(Condition* cond) { - GossipMenuItemsMapBoundsNonConst pMenuItemBounds = sObjectMgr->GetGossipMenuItemsMapBoundsNonConst(cond->mSourceGroup); + GossipMenuItemsMapBoundsNonConst pMenuItemBounds = sObjectMgr->GetGossipMenuItemsMapBoundsNonConst(cond->SourceGroup); if (pMenuItemBounds.first != pMenuItemBounds.second) { - for (GossipMenuItemsMap::iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr) + for (GossipMenuItemsContainer::iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr) { - if ((*itr).second.MenuId == cond->mSourceGroup && (*itr).second.OptionIndex == cond->mSourceEntry) + if ((*itr).second.MenuId == cond->SourceGroup && (*itr).second.OptionIndex == uint32(cond->SourceEntry)) { (*itr).second.Conditions.push_back(cond); return true; @@ -661,380 +1005,402 @@ bool ConditionMgr::addToGossipMenuItems(Condition* cond) } } - sLog->outErrorDb("addToGossipMenuItems: GossipMenuId %u Item %u not found", cond->mSourceGroup, cond->mSourceEntry); + sLog->outErrorDb("addToGossipMenuItems: GossipMenuId %u Item %u not found", cond->SourceGroup, cond->SourceEntry); return false; } +bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) +{ + uint32 conditionEffMask = cond->SourceGroup; + SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->GetSpellInfo(cond->SourceEntry)); + ASSERT(spellInfo); + std::list<uint32> sharedMasks; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + // check if effect is already a part of some shared mask + bool found = false; + for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr) + { + if ((1<<i) & *itr) + { + found = true; + break; + } + } + if (found) + continue; + + // build new shared mask with found effect + uint32 sharedMask = (1<<i); + ConditionList* cmp = spellInfo->Effects[i].ImplicitTargetConditions; + for (uint8 effIndex = i+1; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + { + if (spellInfo->Effects[effIndex].ImplicitTargetConditions == cmp) + sharedMask |= 1<<effIndex; + } + sharedMasks.push_back(sharedMask); + } + + for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr) + { + // some effect indexes should have same data + if (uint32 commonMask = *itr & conditionEffMask) + { + uint8 firstEffIndex = 0; + for (; firstEffIndex < MAX_SPELL_EFFECTS; ++firstEffIndex) + if ((1<<firstEffIndex) & *itr) + break; + + // get shared data + ConditionList* sharedList = spellInfo->Effects[firstEffIndex].ImplicitTargetConditions; + + // there's already data entry for that sharedMask + if (sharedList) + { + // we have overlapping masks in db + if (conditionEffMask != *itr) + { + sLog->outErrorDb("SourceEntry %u in `condition` table, has incorrect SourceGroup %u (spell effectMask) set - " + "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring.", cond->SourceEntry, cond->SourceGroup); + return false; + } + } + // no data for shared mask, we can create new submask + else + { + // add new list, create new shared mask + sharedList = new ConditionList(); + for (uint8 i = firstEffIndex; i < MAX_SPELL_EFFECTS; ++i) + if ((1<<i) & commonMask) + spellInfo->Effects[i].ImplicitTargetConditions = sharedList; + } + sharedList->push_back(cond); + break; + } + } + return true; +} + bool ConditionMgr::isSourceTypeValid(Condition* cond) { - if (cond->mSourceType == CONDITION_SOURCE_TYPE_NONE || cond->mSourceType >= CONDITION_SOURCE_TYPE_MAX) + if (cond->SourceType == CONDITION_SOURCE_TYPE_NONE || cond->SourceType >= CONDITION_SOURCE_TYPE_MAX) { - sLog->outErrorDb("Invalid ConditionSourceType %u in `condition` table, ignoring.", uint32(cond->mSourceType)); + sLog->outErrorDb("Invalid ConditionSourceType %u in `condition` table, ignoring.", uint32(cond->SourceType)); return false; } - switch (cond->mSourceType) + switch (cond->SourceType) { case CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE: { - if (!LootTemplates_Creature.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Creature.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Creature.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Creature.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE: { - if (!LootTemplates_Disenchant.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Disenchant.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Disenchant.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Disenchant.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE: { - if (!LootTemplates_Fishing.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Fishing.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Fishing.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Fishing.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE: { - if (!LootTemplates_Gameobject.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Gameobject.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Gameobject.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Gameobject.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE: { - if (!LootTemplates_Item.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Item.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Item.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Item.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE: { - if (!LootTemplates_Mail.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Mail.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Mail.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Mail.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE: { - if (!LootTemplates_Milling.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Milling.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Milling.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Milling.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE: { - if (!LootTemplates_Pickpocketing.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Pickpocketing.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Pickpocketing.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Pickpocketing.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE: { - if (!LootTemplates_Prospecting.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Prospecting.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Prospecting.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Prospecting.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE: { - if (!LootTemplates_Reference.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Reference.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Reference.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Reference.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE: { - if (!LootTemplates_Skinning.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Skinning.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Skinning.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Skinning.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE: { - if (!LootTemplates_Spell.HaveLootFor(cond->mSourceGroup)) + if (!LootTemplates_Spell.HaveLootFor(cond->SourceGroup)) { - sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->SourceGroup); return false; } - LootTemplate* loot = LootTemplates_Spell.GetLootForConditionFill(cond->mSourceGroup); - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + LootTemplate* loot = LootTemplates_Spell.GetLootForConditionFill(cond->SourceGroup); + ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); + if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); return false; } break; } - case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET: + case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET: { - if (cond->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry); + if (!spellInfo) { - sLog->outErrorDb("SourceEntry %u in `condition` table, has ConditionType %u. Only CONDITION_SPELL_SCRIPT_TARGET(18) is valid for CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET(14), ignoring.", cond->mSourceEntry, uint32(cond->mConditionType)); + sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry); return false; } - SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->mSourceEntry); - if (!spellProto) + if ((cond->SourceGroup > MAX_EFFECT_MASK) || !cond->SourceGroup) { - sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry); + sLog->outErrorDb("SourceEntry %u in `condition` table, has incorrect SourceGroup %u (spell effectMask) set , ignoring.", cond->SourceEntry, cond->SourceGroup); return false; } - bool targetfound = false; + uint32 origGroup = cond->SourceGroup; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if (spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENTRY || - spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_SRC_AREA_ENTRY || - spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENTRY || - spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ENTRY || - spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_NEARBY_ENTRY || - spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_NEARBY_ENTRY || - spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_NEARBY_ENTRY || - spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_NEARBY_ENTRY || - spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_SRC_AREA || - spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_SRC_AREA || - spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_DEST_AREA || - spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_DEST_AREA || - spellProto->Effects[i].TargetA.GetTarget() == TARGET_DEST_NEARBY_ENTRY || - spellProto->Effects[i].TargetB.GetTarget() == TARGET_DEST_NEARBY_ENTRY || - spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CONE_ENTRY || - spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_CONE_ENTRY) + if (!((1<<i) & cond->SourceGroup)) + continue; + + switch (spellInfo->Effects[i].TargetA.GetSelectionCategory()) { - targetfound = true; - //break; + case TARGET_SELECT_CATEGORY_NEARBY: + case TARGET_SELECT_CATEGORY_CONE: + case TARGET_SELECT_CATEGORY_AREA: + continue; + default: + break; } - else if (cond->mConditionValue3 & (1 << i)) + + switch (spellInfo->Effects[i].TargetB.GetSelectionCategory()) { - cond->mConditionValue3 &= ~(1 << i); - sLog->outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DEST_NEARBY_ENTRY (46)" - ", TARGET_UNIT_SRC_AREA_ENTRY(7), TARGET_UNIT_DEST_AREA_ENTRY(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)" - "TARGET_GAMEOBJECT_SRC_AREA(51), TARGET_GAMEOBJECT_DEST_AREA(52) in effect %u", cond->mSourceEntry, uint32(i)); + case TARGET_SELECT_CATEGORY_NEARBY: + case TARGET_SELECT_CATEGORY_CONE: + case TARGET_SELECT_CATEGORY_AREA: + continue; + default: + break; } + + sLog->outErrorDb("SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i)); + cond->SourceGroup &= ~(1<<i); } - if (!targetfound && !cond->mConditionValue3) // cond->mConditionValue3 already errored up there - { - sLog->outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DEST_NEARBY_ENTRY (46)" - ", TARGET_UNIT_SRC_AREA_ENTRY(7), TARGET_UNIT_DEST_AREA_ENTRY(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)" - "TARGET_GAMEOBJECT_SRC_AREA(51), TARGET_GAMEOBJECT_DEST_AREA(52)", cond->mSourceEntry); - return false; - } - if ((cond->mConditionValue1 == SPELL_TARGET_TYPE_DEAD) && !spellProto->IsAllowingDeadTarget()) - { - sLog->outErrorDb("SourceEntry %u in `condition` table does have SPELL_TARGET_TYPE_DEAD specified but spell does not have SPELL_ATTR2_CAN_TARGET_DEAD", cond->mSourceEntry); + // all effects were removed, no need to add the condition at all + if (!cond->SourceGroup) return false; - } break; } case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE: { - if (!sObjectMgr->GetCreatureTemplate(cond->mSourceEntry)) + if (!sObjectMgr->GetCreatureTemplate(cond->SourceEntry)) { - sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->mSourceEntry); + sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceEntry); return false; } break; } case CONDITION_SOURCE_TYPE_SPELL: { - SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->mSourceEntry); + SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry); if (!spellProto) { - sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry); + sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry); return false; } break; } - case CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET: - { - if (cond->mConditionType != CONDITION_ITEM_TARGET) + case CONDITION_SOURCE_TYPE_QUEST_ACCEPT: + if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry)) { - sLog->outErrorDb("SourceEntry %u in `condition` table, has ConditionType %u. Only CONDITION_ITEM_TARGET(24) is valid for CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET(18), ignoring.", cond->mSourceEntry, uint32(cond->mConditionType)); + sLog->outErrorDb("CONDITION_SOURCE_TYPE_QUEST_ACCEPT specifies non-existing quest (%u), skipped", cond->SourceEntry); return false; } - - ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry); - if (!pItemProto) + break; + case CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK: + if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry)) { - sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `item_tamplate`, ignoring.", cond->mSourceEntry); + sLog->outErrorDb("CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK specifies non-existing quest (%u), skipped", cond->SourceEntry); return false; } - - bool bIsItemSpellValid = false; - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - { - if (SpellInfo const* pSpellInfo = sSpellMgr->GetSpellInfo(pItemProto->Spells[i].SpellId)) - { - if (pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE || - pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) - { - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, pSpellInfo->Id);//script loading is done before item target loading - if (!conditions.empty()) - break; - - for (int j = 0; j < MAX_SPELL_EFFECTS; ++j) - { - if (pSpellInfo->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || - pSpellInfo->Effects[j].TargetB.GetTarget() == TARGET_UNIT_TARGET_ENEMY || - pSpellInfo->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ANY || - pSpellInfo->Effects[j].TargetB.GetTarget() == TARGET_UNIT_TARGET_ANY) - { - bIsItemSpellValid = true; - break; - } - } - - if (bIsItemSpellValid) - break; - } - } - } - - if (!bIsItemSpellValid) - { - sLog->outErrorDb("Conditions: CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET for item %u, which either doesn't have item spelltrigger or its spells don't have implicit target " - "TARGET_UNIT_TARGET_ENEMY(6), TARGET_UNIT_TARGET_ANY(25), or the spells are already listed in CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET conditions.", cond->mSourceEntry); - break; - } break; - } - case CONDITION_SOURCE_TYPE_QUEST_ACCEPT: - if (!sObjectMgr->GetQuestTemplate(cond->mSourceEntry)) + case CONDITION_SOURCE_TYPE_VEHICLE_SPELL: + if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup)) { - sLog->outErrorDb("CONDITION_SOURCE_TYPE_QUEST_ACCEPT specifies non-existing quest (%u), skipped", cond->mSourceEntry); + sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceGroup); return false; } - break; - case CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK: - if (!sObjectMgr->GetQuestTemplate(cond->mSourceEntry)) + + if (!sSpellMgr->GetSpellInfo(cond->SourceEntry)) { - sLog->outErrorDb("CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK specifies non-existing quest (%u), skipped", cond->mSourceEntry); + sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry); return false; } break; - case CONDITION_SOURCE_TYPE_VEHICLE_SPELL: - if (!sObjectMgr->GetCreatureTemplate(cond->mSourceGroup)) + case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT: + if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup)) { - sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->mSourceGroup); + sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceGroup); return false; } - if (!sSpellMgr->GetSpellInfo(cond->mSourceEntry)) + if (!sSpellMgr->GetSpellInfo(cond->SourceEntry)) { - sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry); + sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry); return false; } break; @@ -1050,113 +1416,131 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) } bool ConditionMgr::isConditionTypeValid(Condition* cond) { - if (cond->mConditionType == CONDITION_NONE || cond->mConditionType >= CONDITION_MAX) + if (cond->ConditionType == CONDITION_NONE || cond->ConditionType >= CONDITION_MAX) { - sLog->outErrorDb("Invalid ConditionType %u at SourceEntry %u in `condition` table, ignoring.", uint32(cond->mConditionType), cond->mSourceEntry); + sLog->outErrorDb("Invalid ConditionType %u at SourceEntry %u in `condition` table, ignoring.", uint32(cond->ConditionType), cond->SourceEntry); return false; } - switch (cond->mConditionType) + if (cond->ConditionTarget >= cond->GetMaxAvailableConditionTargets()) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->SourceType, cond->SourceEntry); + return false; + } + + switch (cond->ConditionType) { case CONDITION_AURA: { - if (!sSpellMgr->GetSpellInfo(cond->mConditionValue1)) + if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1)) { - sLog->outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->mConditionValue1); + sLog->outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->ConditionValue1); return false; } - if (cond->mConditionValue2 > 2) + if (cond->ConditionValue2 > EFFECT_2) { - sLog->outErrorDb("Aura condition has non existing effect index (%u) (must be 0..2), skipped", cond->mConditionValue2); + sLog->outErrorDb("Aura condition has non existing effect index (%u) (must be 0..2), skipped", cond->ConditionValue2); return false; } + if (cond->ConditionValue3) + sLog->outErrorDb("Aura condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_ITEM: { - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->mConditionValue1); + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1); if (!proto) { - sLog->outErrorDb("Item condition has non existing item (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("Item condition has non existing item (%u), skipped", cond->ConditionValue1); return false; } - if (!cond->mConditionValue2) + if (!cond->ConditionValue2) { - sLog->outErrorDb("Item condition has 0 set for item count in value2 (%u), skipped", cond->mConditionValue2); + sLog->outErrorDb("Item condition has 0 set for item count in value2 (%u), skipped", cond->ConditionValue2); return false; } break; } case CONDITION_ITEM_EQUIPPED: { - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->mConditionValue1); + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1); if (!proto) { - sLog->outErrorDb("ItemEquipped condition has non existing item (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("ItemEquipped condition has non existing item (%u), skipped", cond->ConditionValue1); return false; } - if (cond->mConditionValue2) - sLog->outErrorDb("ItemEquipped condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue2) + sLog->outErrorDb("ItemEquipped condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("ItemEquipped condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_ZONEID: { - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(cond->mConditionValue1); + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(cond->ConditionValue1); if (!areaEntry) { - sLog->outErrorDb("Zone condition has non existing area (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("ZoneID condition has non existing area (%u), skipped", cond->ConditionValue1); return false; } if (areaEntry->zone != 0) { - sLog->outErrorDb("Zone condition requires to be in area (%u) which is a subzone but zone expected, skipped", cond->mConditionValue1); + sLog->outErrorDb("ZoneID condition requires to be in area (%u) which is a subzone but zone expected, skipped", cond->ConditionValue1); return false; } - if (cond->mConditionValue2) - sLog->outErrorDb("Zone condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue2) + sLog->outErrorDb("ZoneID condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("ZoneID condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_REPUTATION_RANK: { - FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->mConditionValue1); + FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->ConditionValue1); if (!factionEntry) { - sLog->outErrorDb("Reputation condition has non existing faction (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("Reputation condition has non existing faction (%u), skipped", cond->ConditionValue1); return false; } + if (cond->ConditionValue3) + sLog->outErrorDb("Reputation condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_TEAM: { - if (cond->mConditionValue1 != ALLIANCE && cond->mConditionValue1 != HORDE) + if (cond->ConditionValue1 != ALLIANCE && cond->ConditionValue1 != HORDE) { - sLog->outErrorDb("Team condition specifies unknown team (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("Team condition specifies unknown team (%u), skipped", cond->ConditionValue1); return false; } - if (cond->mConditionValue2) - sLog->outErrorDb("Team condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue2) + sLog->outErrorDb("Team condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Team condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_SKILL: { - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(cond->mConditionValue1); + SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(cond->ConditionValue1); if (!pSkill) { - sLog->outErrorDb("Skill condition specifies non-existing skill (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("Skill condition specifies non-existing skill (%u), skipped", cond->ConditionValue1); return false; } - if (cond->mConditionValue2 < 1 || cond->mConditionValue2 > sWorld->GetConfigMaxSkillValue()) + if (cond->ConditionValue2 < 1 || cond->ConditionValue2 > sWorld->GetConfigMaxSkillValue()) { - sLog->outErrorDb("Skill condition specifies invalid skill value (%u), skipped", cond->mConditionValue2); + sLog->outErrorDb("Skill condition specifies invalid skill value (%u), skipped", cond->ConditionValue2); return false; } + if (cond->ConditionValue3) + sLog->outErrorDb("Skill condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_QUESTREWARDED: @@ -1164,246 +1548,331 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) case CONDITION_QUEST_NONE: case CONDITION_QUEST_COMPLETE: { - if (!sObjectMgr->GetQuestTemplate(cond->mConditionValue1)) + if (!sObjectMgr->GetQuestTemplate(cond->ConditionValue1)) { - sLog->outErrorDb("Quest condition specifies non-existing quest (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("Quest condition specifies non-existing quest (%u), skipped", cond->ConditionValue1); return false; } - if (cond->mConditionValue2 > 1) - sLog->outErrorDb("Quest condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_NO_AURA: - { - if (!sSpellMgr->GetSpellInfo(cond->mConditionValue1)) - { - sLog->outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->mConditionValue1); - return false; - } - - if (cond->mConditionValue2 > 2) - { - sLog->outErrorDb("Aura condition has non existing effect index (%u) in value2 (must be 0..2), skipped", cond->mConditionValue2); - return false; - } + if (cond->ConditionValue2 > 1) + sLog->outErrorDb("Quest condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Quest condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_ACTIVE_EVENT: { GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap(); - if (cond->mConditionValue1 >=events.size() || !events[cond->mConditionValue1].isValid()) + if (cond->ConditionValue1 >=events.size() || !events[cond->ConditionValue1].isValid()) { - sLog->outErrorDb("Active event condition has non existing event id (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("ActiveEvent condition has non existing event id (%u), skipped", cond->ConditionValue1); return false; } - if (cond->mConditionValue2) - sLog->outErrorDb("Active event condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue2) + sLog->outErrorDb("ActiveEvent condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("ActiveEvent condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_ACHIEVEMENT: { - AchievementEntry const* achievement = GetAchievementStore()->LookupEntry(cond->mConditionValue1); + AchievementEntry const* achievement = GetAchievementStore()->LookupEntry(cond->ConditionValue1); if (!achievement) { - sLog->outErrorDb("Achivemen condition has non existing achivement id (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("Achivement condition has non existing achivement id (%u), skipped", cond->ConditionValue1); return false; } - if (cond->mConditionValue2) - sLog->outErrorDb("Achivemen condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue2) + sLog->outErrorDb("Achivement condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Achivement condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_CLASS: { - if (!(cond->mConditionValue1 & CLASSMASK_ALL_PLAYABLE)) + if (!(cond->ConditionValue1 & CLASSMASK_ALL_PLAYABLE)) { - sLog->outErrorDb("Class condition has non existing classmask (%u), skipped", cond->mConditionValue1 & ~CLASSMASK_ALL_PLAYABLE); + sLog->outErrorDb("Class condition has non existing classmask (%u), skipped", cond->ConditionValue1 & ~CLASSMASK_ALL_PLAYABLE); return false; } - if (cond->mConditionValue2) - sLog->outErrorDb("Class condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue2) + sLog->outErrorDb("Class condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Class condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_RACE: { - if (!(cond->mConditionValue1 & RACEMASK_ALL_PLAYABLE)) + if (!(cond->ConditionValue1 & RACEMASK_ALL_PLAYABLE)) { - sLog->outErrorDb("Race condition has non existing racemask (%u), skipped", cond->mConditionValue1 & ~RACEMASK_ALL_PLAYABLE); + sLog->outErrorDb("Race condition has non existing racemask (%u), skipped", cond->ConditionValue1 & ~RACEMASK_ALL_PLAYABLE); return false; } - if (cond->mConditionValue2) - sLog->outErrorDb("Race condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue2) + sLog->outErrorDb("Race condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Race condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } - case CONDITION_SPELL_SCRIPT_TARGET: + case CONDITION_MAPID: { - if (cond->mConditionValue1 >= MAX_SPELL_TARGET_TYPE) + MapEntry const* me = sMapStore.LookupEntry(cond->ConditionValue1); + if (!me) { - sLog->outErrorDb("SpellTarget condition has non existing spell target type (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("Map condition has non existing map (%u), skipped", cond->ConditionValue1); return false; } - switch (cond->mConditionValue1) - { - case SPELL_TARGET_TYPE_GAMEOBJECT: - { - if (cond->mConditionValue2 && !sObjectMgr->GetGameObjectTemplate(cond->mConditionValue2)) - { - sLog->outErrorDb("SpellTarget condition has non existing gameobject (%u) as target, skipped", cond->mConditionValue2); - return false; - } - break; - } - case SPELL_TARGET_TYPE_CONTROLLED: - case SPELL_TARGET_TYPE_CREATURE: - case SPELL_TARGET_TYPE_DEAD: - { - if (cond->mConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->mConditionValue2)) - { - sLog->outErrorDb("SpellTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue2); - return false; - } - - const CreatureTemplate* cInfo = sObjectMgr->GetCreatureTemplate(cond->mConditionValue2); - if (cond->mSourceEntry == 30427 && !cInfo->SkinLootId) - { - sLog->outErrorDb("SpellTarget condition has creature entry %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!, skipped", cond->mConditionValue2); - return false; - } - break; - } - } + if (cond->ConditionValue2) + sLog->outErrorDb("Map condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Map condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } - case CONDITION_CREATURE_TARGET: + case CONDITION_SPELL: { - if (!cond->mConditionValue1 && !sObjectMgr->GetCreatureTemplate(cond->mConditionValue1)) + if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1)) { - sLog->outErrorDb("CreatureTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue1); + sLog->outErrorDb("Spell condition has non existing spell (Id: %d), skipped", cond->ConditionValue1); return false; } - if (cond->mConditionValue2) - sLog->outErrorDb("CreatureTarget condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue2) + sLog->outErrorDb("Spell condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Spell condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } - case CONDITION_TARGET_HEALTH_BELOW_PCT: + case CONDITION_LEVEL: { - if (cond->mConditionValue1 > 100) + if (cond->ConditionValue2 >= COMP_TYPE_MAX) { - sLog->outErrorDb("TargetHealthBelowPct condition has invalid data in value1 (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("Level condition has invalid option (%u), skipped", cond->ConditionValue2); return false; } - - if (cond->mConditionValue2) - sLog->outErrorDb("TargetHealthBelowPct condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Level condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } - case CONDITION_TARGET_RANGE: + case CONDITION_DRUNKENSTATE: { - if (cond->mConditionValue2 && cond->mConditionValue2 < cond->mConditionValue1)//maxDist can be 0 for infinit max range + if (cond->ConditionValue1 > DRUNKEN_SMASHED) + { + sLog->outErrorDb("DrunkState condition has invalid state (%u), skipped", cond->ConditionValue1); + return false; + } + if (cond->ConditionValue2) { - sLog->outErrorDb("TargetRange condition has max distance closer then min distance, skipped"); + sLog->outErrorDb("DrunkState condition has useless data in value2 (%u)!", cond->ConditionValue2); return false; } + if (cond->ConditionValue3) + sLog->outErrorDb("DrunkState condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } - case CONDITION_MAPID: + case CONDITION_NEAR_CREATURE: { - MapEntry const* me = sMapStore.LookupEntry(cond->mConditionValue1); - if (!me) + if (!sObjectMgr->GetCreatureTemplate(cond->ConditionValue1)) { - sLog->outErrorDb("Map condition has non existing map (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("NearCreature condition has non existing creature template entry (%u), skipped", cond->ConditionValue1); return false; } - - if (cond->mConditionValue2) - sLog->outErrorDb("Map condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("NearCreature condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } - case CONDITION_ITEM_TARGET: + case CONDITION_NEAR_GAMEOBJECT: { - if (!cond->mConditionValue1 || cond->mConditionValue1 > MAX_ITEM_REQ_TARGET_TYPE) + if (!sObjectMgr->GetGameObjectTemplate(cond->ConditionValue1)) { - sLog->outErrorDb("ItemTarget condition has incorrect target type (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("NearGameObject condition has non existing gameobject template entry (%u), skipped", cond->ConditionValue1); return false; } - - if (!cond->mConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->mConditionValue2)) + if (cond->ConditionValue3) + sLog->outErrorDb("NearGameObject condition has useless data in value3 (%u)!", cond->ConditionValue3); + break; + } + case CONDITION_OBJECT_ENTRY: + { + switch (cond->ConditionValue1) { - sLog->outErrorDb("ItemTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue2); - return false; + case TYPEID_UNIT: + if (cond->ConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->ConditionValue2)) + { + sLog->outErrorDb("ObjectEntry condition has non existing creature template entry (%u), skipped", cond->ConditionValue2); + return false; + } + break; + case TYPEID_GAMEOBJECT: + if (cond->ConditionValue2 && !sObjectMgr->GetGameObjectTemplate(cond->ConditionValue2)) + { + sLog->outErrorDb("ObjectEntry condition has non existing game object template entry (%u), skipped", cond->ConditionValue2); + return false; + } + break; + case TYPEID_PLAYER: + case TYPEID_CORPSE: + if (cond->ConditionValue2) + sLog->outErrorDb("ObjectEntry condition has useless data in value2 (%u)!", cond->ConditionValue2); + break; + default: + sLog->outErrorDb("ObjectEntry condition has wrong typeid set (%u), skipped", cond->ConditionValue1); + return false; } - - if (cond->mConditionValue3) - sLog->outErrorDb("ItemTarget condition has useless data in value3 (%u)!", cond->mConditionValue3); + if (cond->ConditionValue3) + sLog->outErrorDb("ObjectEntry condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } - case CONDITION_SPELL: + case CONDITION_TYPE_MASK: { - if (!sSpellMgr->GetSpellInfo(cond->mConditionValue1)) + if (!cond->ConditionValue1 || (cond->ConditionValue1 & ~(TYPEMASK_UNIT | TYPEMASK_PLAYER | TYPEMASK_GAMEOBJECT | TYPEMASK_CORPSE))) { - sLog->outErrorDb("Spell condition has non existing spell (Id: %d), skipped", cond->mConditionValue1); + sLog->outErrorDb("TypeMask condition has invalid typemask set (%u), skipped", cond->ConditionValue2); return false; } - - if (cond->mConditionValue2) - sLog->outErrorDb("Spell condition has useless data in value2 (%u)!", cond->mConditionValue2); + if (cond->ConditionValue2) + sLog->outErrorDb("TypeMask condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("TypeMask condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } - case CONDITION_NOITEM: + case CONDITION_RELATION_TO: { - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->mConditionValue1); - if (!proto) + if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets()) + { + sLog->outErrorDb("RelationTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1); + return false; + } + if (cond->ConditionValue1 == cond->ConditionTarget) + { + sLog->outErrorDb("RelationTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1); + return false; + } + if (cond->ConditionValue2 >= RELATION_MAX) { - sLog->outErrorDb("NoItem condition has non existing item (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("RelationTo condition has invalid ConditionValue2(RelationType) (%u), skipped", cond->ConditionValue2); return false; } + if (cond->ConditionValue3) + sLog->outErrorDb("RelationTo condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } - case CONDITION_LEVEL: + case CONDITION_REACTION_TO: { - if (cond->mConditionValue2 >= LVL_COND_MAX) + if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets()) + { + sLog->outErrorDb("ReactionTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1); + return false; + } + if (cond->ConditionValue1 == cond->ConditionTarget) + { + sLog->outErrorDb("ReactionTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1); + return false; + } + if (!cond->ConditionValue2) { - sLog->outErrorDb("Level condition has invalid option (%u), skipped", cond->mConditionValue2); + sLog->outErrorDb("mConditionValue2 condition has invalid ConditionValue2(rankMask) (%u), skipped", cond->ConditionValue2); return false; } break; } - case CONDITION_DRUNKENSTATE: + case CONDITION_DISTANCE_TO: { - if (cond->mConditionValue1 > DRUNKEN_SMASHED) + if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets()) + { + sLog->outErrorDb("DistanceTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1); + return false; + } + if (cond->ConditionValue1 == cond->ConditionTarget) + { + sLog->outErrorDb("DistanceTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1); + return false; + } + if (cond->ConditionValue3 >= COMP_TYPE_MAX) { - sLog->outErrorDb("DrunkState condition has invalid state (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("DistanceTo condition has invalid ComparisionType (%u), skipped", cond->ConditionValue3); return false; } break; } - case CONDITION_NEAR_CREATURE: + case CONDITION_ALIVE: + { + if (cond->ConditionValue1) + sLog->outErrorDb("Alive condition has useless data in value1 (%u)!", cond->ConditionValue1); + if (cond->ConditionValue2) + sLog->outErrorDb("Alive condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Alive condition has useless data in value3 (%u)!", cond->ConditionValue3); + break; + } + case CONDITION_HP_VAL: { - if (!sObjectMgr->GetCreatureTemplate(cond->mConditionValue1)) + if (cond->ConditionValue2 >= COMP_TYPE_MAX) { - sLog->outErrorDb("NearCreature condition has non existing creature template entry (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("HpVal condition has invalid ComparisionType (%u), skipped", cond->ConditionValue2); return false; } + if (cond->ConditionValue3) + sLog->outErrorDb("HpVal condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } - case CONDITION_NEAR_GAMEOBJECT: + case CONDITION_HP_PCT: { - if (!sObjectMgr->GetGameObjectTemplate(cond->mConditionValue1)) + if (cond->ConditionValue1 > 100) { - sLog->outErrorDb("NearGameObject condition has non existing gameobject template entry (%u), skipped", cond->mConditionValue1); + sLog->outErrorDb("HpPct condition has too big percent value (%u), skipped", cond->ConditionValue1); return false; } + if (cond->ConditionValue2 >= COMP_TYPE_MAX) + { + sLog->outErrorDb("HpPct condition has invalid ComparisionType (%u), skipped", cond->ConditionValue2); + return false; + } + if (cond->ConditionValue3) + sLog->outErrorDb("HpPct condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_AREAID: case CONDITION_INSTANCE_DATA: break; + case CONDITION_WORLD_STATE: + { + if (!sWorld->getWorldState(cond->ConditionValue1)) + { + sLog->outErrorDb("World state condition has non existing world state in value1 (%u), skipped", cond->ConditionValue1); + return false; + } + if (cond->ConditionValue3) + sLog->outErrorDb("World state condition has useless data in value3 (%u)!", cond->ConditionValue3); + break; + } + case CONDITION_PHASEMASK: + { + if (cond->ConditionValue2) + sLog->outErrorDb("Phasemask condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + sLog->outErrorDb("Phasemask condition has useless data in value3 (%u)!", cond->ConditionValue3); + break; + } + case CONDITION_UNUSED_18: + sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_18 in `conditions` table - ignoring"); + return false; + case CONDITION_UNUSED_19: + sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_19 in `conditions` table - ignoring"); + return false; + case CONDITION_UNUSED_20: + sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_20 in `conditions` table - ignoring"); + return false; + case CONDITION_UNUSED_21: + sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_21 in `conditions` table - ignoring"); + return false; + case CONDITION_UNUSED_24: + sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_24 in `conditions` table - ignoring"); + return false; default: break; } @@ -1434,7 +1903,7 @@ void ConditionMgr::Clean() ConditionStore.clear(); - for (VehicleSpellConditionContainer::iterator itr = VehicleSpellConditionStore.begin(); itr != VehicleSpellConditionStore.end(); ++itr) + for (CreatureSpellConditionContainer::iterator itr = VehicleSpellConditionStore.begin(); itr != VehicleSpellConditionStore.end(); ++itr) { for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it) { diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index a9bb97251da..5a5e2dd1c2e 100755 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -24,121 +24,165 @@ class Player; class Unit; +class WorldObject; class LootTemplate; +struct Condition; + +enum ConditionTypes +{ // value1 value2 value3 + CONDITION_NONE = 0, // 0 0 0 always true + CONDITION_AURA = 1, // spell_id effindex use target? true if player (or target, if value3) has aura of spell_id with effect effindex + CONDITION_ITEM = 2, // item_id count bank true if has #count of item_ids (if 'bank' is set it searches in bank slots too) + CONDITION_ITEM_EQUIPPED = 3, // item_id 0 0 true if has item_id equipped + CONDITION_ZONEID = 4, // zone_id 0 0 true if in zone_id + CONDITION_REPUTATION_RANK = 5, // faction_id rankMask 0 true if has min_rank for faction_id + CONDITION_TEAM = 6, // player_team 0, 0 469 - Alliance, 67 - Horde) + CONDITION_SKILL = 7, // skill_id skill_value 0 true if has skill_value for skill_id + CONDITION_QUESTREWARDED = 8, // quest_id 0 0 true if quest_id was rewarded before + CONDITION_QUESTTAKEN = 9, // quest_id 0, 0 true while quest active + CONDITION_DRUNKENSTATE = 10, // DrunkenState 0, 0 true if player is drunk enough + CONDITION_WORLD_STATE = 11, // index value 0 true if world has the value for the index + CONDITION_ACTIVE_EVENT = 12, // event_id 0 0 true if event is active + CONDITION_INSTANCE_DATA = 13, // entry data 0 true if data is set in current instance + CONDITION_QUEST_NONE = 14, // quest_id 0 0 true if doesn't have quest saved + CONDITION_CLASS = 15, // class 0 0 true if player's class is equal to class + CONDITION_RACE = 16, // race 0 0 true if player's race is equal to race + CONDITION_ACHIEVEMENT = 17, // achievement_id 0 0 true if achievement is complete + CONDITION_UNUSED_18 = 18, // + CONDITION_UNUSED_19 = 19, // + CONDITION_UNUSED_20 = 20, // + CONDITION_UNUSED_21 = 21, // + CONDITION_MAPID = 22, // map_id 0 0 true if in map_id + CONDITION_AREAID = 23, // area_id 0 0 true if in area_id + CONDITION_UNUSED_24 = 24, // + CONDITION_SPELL = 25, // spell_id 0 0 true if player has learned spell + CONDITION_PHASEMASK = 26, // phasemask 0 0 true if object is in phasemask + CONDITION_LEVEL = 27, // level ComparisonType 0 true if unit's level is equal to param1 (param2 can modify the statement) + CONDITION_QUEST_COMPLETE = 28, // quest_id 0 0 true if player has quest_id with all objectives complete, but not yet rewarded + CONDITION_NEAR_CREATURE = 29, // creature entry distance 0 true if there is a creature of entry in range + CONDITION_NEAR_GAMEOBJECT = 30, // gameobject entry distance 0 true if there is a gameobject of entry in range + CONDITION_OBJECT_ENTRY = 31, // TypeID entry 0 true if object is type TypeID and the entry is 0 or matches entry of the object + CONDITION_TYPE_MASK = 32, // TypeMask 0 0 true if object is type object's TypeMask matches provided TypeMask + CONDITION_RELATION_TO = 33, // ConditionTarget RelationType 0 true if object is in given relation with object specified by ConditionTarget + CONDITION_REACTION_TO = 34, // ConditionTarget rankMask 0 true if object's reaction matches rankMask object specified by ConditionTarget + CONDITION_DISTANCE_TO = 35, // ConditionTarget distance ComparisonType true if object and ConditionTarget are within distance given by parameters + CONDITION_ALIVE = 36, // 0 0 0 true if unit is alive + CONDITION_HP_VAL = 37, // hpVal ComparisonType 0 true if unit's hp matches given value + CONDITION_HP_PCT = 38, // hpPct ComparisonType 0 true if unit's hp matches given pct + CONDITION_MAX = 39 // MAX +}; -enum ConditionType -{ // value1 value2 value3 - CONDITION_NONE = 0, // 0 0 0 always true - CONDITION_AURA = 1, // spell_id effindex use target? true if player (or target, if value3) has aura of spell_id with effect effindex - CONDITION_ITEM = 2, // item_id count +referenceID true if has #count of item_ids - CONDITION_ITEM_EQUIPPED = 3, // item_id 0 +referenceID true if has item_id equipped - CONDITION_ZONEID = 4, // zone_id 0 +referenceID true if in zone_id - CONDITION_REPUTATION_RANK = 5, // faction_id min_rank +referenceID true if has min_rank for faction_id - CONDITION_TEAM = 6, // player_team 0, +referenceID 469 - Alliance, 67 - Horde) - CONDITION_SKILL = 7, // skill_id skill_value +referenceID true if has skill_value for skill_id - CONDITION_QUESTREWARDED = 8, // quest_id 0 +referenceID true if quest_id was rewarded before - CONDITION_QUESTTAKEN = 9, // quest_id 0, +referenceID true while quest active - CONDITION_DRUNKENSTATE = 10, // DrunkenState 0, +referenceID true if player is drunk enough - CONDITION_NO_AURA = 11, // spell_id effindex +referenceID true if does not have aura of spell_id with effect effindex - CONDITION_ACTIVE_EVENT = 12, // event_id 0 +referenceID true if event is active - CONDITION_INSTANCE_DATA = 13, // entry data +referenceID true if data is set in current instance - CONDITION_QUEST_NONE = 14, // quest_id 0 +referenceID true if doesn't have quest saved - CONDITION_CLASS = 15, // class 0 +referenceID true if player's class is equal to class - CONDITION_RACE = 16, // race 0 +referenceID true if player's race is equal to race - CONDITION_ACHIEVEMENT = 17, // achievement_id 0 +referenceID true if achievement is complete - CONDITION_SPELL_SCRIPT_TARGET = 18, // SpellScriptTargetType, TargetEntry, 0 - CONDITION_CREATURE_TARGET = 19, // creature entry 0 +referenceID true if current target is creature with value1 entry - CONDITION_TARGET_HEALTH_BELOW_PCT = 20, // 0-100 0 +referenceID true if target's health is below value1 percent, false if over or no target - CONDITION_TARGET_RANGE = 21, // minDistance maxDist +referenceID true if target is closer then minDist and further then maxDist or if max is 0 then max dist is infinit - CONDITION_MAPID = 22, // map_id 0 +referenceID true if in map_id - CONDITION_AREAID = 23, // area_id 0 +referenceID true if in area_id - CONDITION_ITEM_TARGET = 24, // ItemRequiredTargetType, TargetEntry, 0 - CONDITION_SPELL = 25, // spell_id bool +referenceID bool 1 for true 0 for false - CONDITION_NOITEM = 26, // item_id bank +referenceID true if player does not have any of the item (if 'bank' is set it searches in bank slots too) - CONDITION_LEVEL = 27, // level opt +referenceID true if player's level is equal to param1 (param2 can modify the statement) - CONDITION_QUEST_COMPLETE = 28, // quest_id 0 +referenceID true if player has quest_id with all objectives complete, but not yet rewarded - CONDITION_NEAR_CREATURE = 29, // creature entry distance +referenceID true if there is a creature of entry in range - CONDITION_NEAR_GAMEOBJECT = 30, // gameobject entry distance +referenceID true if there is a gameobject of entry in range - CONDITION_MAX = 31 // MAX +enum ConditionSourceType +{ + CONDITION_SOURCE_TYPE_NONE = 0, + CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE = 1, + CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE = 2, + CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE = 3, + CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE = 4, + CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE = 5, + CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE = 6, + CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE = 7, + CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE = 8, + CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE = 9, + CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE = 10, + CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE = 11, + CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE = 12, + CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET = 13, + CONDITION_SOURCE_TYPE_GOSSIP_MENU = 14, + CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION = 15, + CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16, + CONDITION_SOURCE_TYPE_SPELL = 17, + CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT = 18, + CONDITION_SOURCE_TYPE_QUEST_ACCEPT = 19, + CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK = 20, + CONDITION_SOURCE_TYPE_VEHICLE_SPELL = 21, + CONDITION_SOURCE_TYPE_SMART_EVENT = 22, + CONDITION_SOURCE_TYPE_MAX = 23 //MAX }; -enum LevelConditionType +enum ComparisionType { - LVL_COND_EQ, - LVL_COND_HIGH, - LVL_COND_LOW, - LVL_COND_HIGH_EQ, - LVL_COND_LOW_EQ, - LVL_COND_MAX + COMP_TYPE_EQ = 0, + COMP_TYPE_HIGH, + COMP_TYPE_LOW, + COMP_TYPE_HIGH_EQ, + COMP_TYPE_LOW_EQ, + COMP_TYPE_MAX }; -enum ConditionSourceType +enum RelationType { - CONDITION_SOURCE_TYPE_NONE = 0, //DONE - CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE = 1, //DONE - CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE = 2, //DONE - CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE = 3, //DONE - CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE = 4, //DONE - CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE = 5, //DONE - CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE = 6, //DONE - CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE = 7, //DONE - CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE = 8, //DONE - CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE = 9, //DONE - CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE = 10, //DONE - CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE = 11, //DONE - CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE = 12, //DONE - CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET = 13, //DONE - CONDITION_SOURCE_TYPE_GOSSIP_MENU = 14, //DONE - CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION = 15, //DONE - CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16, //DONE - CONDITION_SOURCE_TYPE_SPELL = 17, //DONE - CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET = 18, //DONE - CONDITION_SOURCE_TYPE_QUEST_ACCEPT = 19, //DONE - CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK = 20, //DONE - CONDITION_SOURCE_TYPE_VEHICLE_SPELL = 21, //DONE - CONDITION_SOURCE_TYPE_SMART_EVENT = 22, //DONE - CONDITION_SOURCE_TYPE_MAX = 23 //MAX + RELATION_SELF = 0, + RELATION_IN_PARTY, + RELATION_IN_RAID_OR_PARTY, + RELATION_OWNED_BY, + RELATION_PASSENGER_OF, + RELATION_MAX +}; + +enum +{ + MAX_CONDITION_TARGETS = 3, +}; + +struct ConditionSourceInfo +{ + WorldObject* mConditionTargets[MAX_CONDITION_TARGETS]; // an array of targets available for conditions + Condition* mLastFailedCondition; + ConditionSourceInfo(WorldObject* target0, WorldObject* target1 = NULL, WorldObject* target2 = NULL) + { + mConditionTargets[0] = target0; + mConditionTargets[1] = target1; + mConditionTargets[2] = target2; + mLastFailedCondition = NULL; + } }; struct Condition { - ConditionSourceType mSourceType; //SourceTypeOrReferenceId - uint32 mSourceGroup; - uint32 mSourceEntry; - uint32 mSourceId; // So far, only used in CONDITION_SOURCE_TYPE_SMART_EVENT - uint32 mElseGroup; - ConditionType mConditionType; //ConditionTypeOrReference - uint32 mConditionValue1; - uint32 mConditionValue2; - uint32 mConditionValue3; - uint32 ErrorTextd; - uint32 mReferenceId; - uint32 mScriptId; + ConditionSourceType SourceType; //SourceTypeOrReferenceId + uint32 SourceGroup; + int32 SourceEntry; + uint32 SourceId; // So far, only used in CONDITION_SOURCE_TYPE_SMART_EVENT + uint32 ElseGroup; + ConditionTypes ConditionType; //ConditionTypeOrReference + uint32 ConditionValue1; + uint32 ConditionValue2; + uint32 ConditionValue3; + uint32 ErrorTextId; + uint32 ReferenceId; + uint32 ScriptId; + uint8 ConditionTarget; + bool NegativeCondition; Condition() { - mSourceType = CONDITION_SOURCE_TYPE_NONE; - mSourceGroup = 0; - mSourceEntry = 0; - mElseGroup = 0; - mConditionType = CONDITION_NONE; - mConditionValue1 = 0; - mConditionValue2 = 0; - mConditionValue3 = 0; - mReferenceId = 0; - ErrorTextd = 0; - mScriptId = 0; + SourceType = CONDITION_SOURCE_TYPE_NONE; + SourceGroup = 0; + SourceEntry = 0; + ElseGroup = 0; + ConditionType = CONDITION_NONE; + ConditionTarget = 0; + ConditionValue1 = 0; + ConditionValue2 = 0; + ConditionValue3 = 0; + ReferenceId = 0; + ErrorTextId = 0; + ScriptId = 0; + NegativeCondition = false; } - bool Meets(Player* player, Unit* invoker = NULL); - bool isLoaded() const { return mConditionType > CONDITION_NONE || mReferenceId; } + bool Meets(ConditionSourceInfo& sourceInfo); + uint32 GetSearcherTypeMaskForCondition(); + bool isLoaded() const { return ConditionType > CONDITION_NONE || ReferenceId; } + uint32 GetMaxAvailableConditionTargets(); }; typedef std::list<Condition*> ConditionList; typedef std::map<uint32, ConditionList> ConditionTypeContainer; typedef std::map<ConditionSourceType, ConditionTypeContainer> ConditionContainer; -typedef std::map<uint32, ConditionTypeContainer> VehicleSpellConditionContainer; -typedef std::map<std::pair<uint32, uint32 /*SAI source_type*/>, ConditionTypeContainer> SmartEventConditionContainer; +typedef std::map<uint32, ConditionTypeContainer> CreatureSpellConditionContainer; +typedef std::map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionTypeContainer> SmartEventConditionContainer; typedef std::map<uint32, ConditionList> ConditionReferenceContainer;//only used for references @@ -155,47 +199,56 @@ class ConditionMgr bool isConditionTypeValid(Condition* cond); ConditionList GetConditionReferences(uint32 refId); - bool IsPlayerMeetToConditions(Player* player, ConditionList const& conditions, Unit* invoker = NULL); + uint32 GetSearcherTypeMaskForConditionList(ConditionList const& conditions); + bool IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions); + bool IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions); + bool IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions); + bool CanHaveSourceGroupSet(ConditionSourceType sourceType) const; + bool CanHaveSourceIdSet(ConditionSourceType sourceType) const; ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry); - ConditionList GetConditionsForSmartEvent(uint32 entry, uint32 eventId, uint32 sourceType); - ConditionList GetConditionsForVehicleSpell(uint32 creatureID, uint32 spellID); + ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId); + ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType); + ConditionList GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId); private: bool isSourceTypeValid(Condition* cond); bool addToLootTemplate(Condition* cond, LootTemplate* loot); bool addToGossipMenus(Condition* cond); bool addToGossipMenuItems(Condition* cond); - bool IsPlayerMeetToConditionList(Player* player, ConditionList const& conditions, Unit* invoker = NULL); - - bool isGroupable(ConditionSourceType sourceType) const - { - return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU || - sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION || - sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL || - sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT); - } + bool addToSpellImplicitTargetConditions(Condition* cond); + bool IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions); void Clean(); // free up resources std::list<Condition*> AllocatedMemoryStore; // some garbage collection :) ConditionContainer ConditionStore; ConditionReferenceContainer ConditionReferenceStore; - VehicleSpellConditionContainer VehicleSpellConditionStore; + CreatureSpellConditionContainer VehicleSpellConditionStore; + CreatureSpellConditionContainer SpellClickEventConditionStore; SmartEventConditionContainer SmartEventConditionStore; }; +template <class T> bool CompareValues(ComparisionType type, T val1, T val2) +{ + switch (type) + { + case COMP_TYPE_EQ: + return val1 == val2; + case COMP_TYPE_HIGH: + return val1 > val2; + case COMP_TYPE_LOW: + return val1 < val2; + case COMP_TYPE_HIGH_EQ: + return val1 >= val2; + case COMP_TYPE_LOW_EQ: + return val1 <= val2; + default: + // incorrect parameter + ASSERT(false); + return false; + } +} + #define sConditionMgr ACE_Singleton<ConditionMgr, ACE_Null_Mutex>::instance() #endif diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 98b21355504..6dbd1d847db 100755 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -682,10 +682,9 @@ void LoadDBCStores(const std::string& dataPath) if (node->map_id < 2 || i == 82 || i == 83 || i == 93 || i == 94) sOldContinentsNodesMask[field] |= submask; - // fix DK node at Ebon Hold - if (i == 315) { + // fix DK node at Ebon Hold and Shadow Vault flight master + if (i == 315 || i == 333) ((TaxiNodesEntry*)node)->MountCreatureID[1] = 32981; - } } } diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index eb25a6d8624..cc25a8f5495 100755 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -1015,7 +1015,7 @@ struct FactionTemplateEntry struct GameObjectDisplayInfoEntry { uint32 Displayid; // 0 m_ID - // char* filename; // 1 + char* filename; // 1 //uint32 unk1[10]; //2-11 float minX; float minY; diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 81f6e1a75a0..c0923b45400 100755 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -56,7 +56,7 @@ const char EmotesEntryfmt[]="nxxiiixx"; const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx"; const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixsxx"; const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii"; -const char GameObjectDisplayInfofmt[]="nxxxxxxxxxxxffffffxxx"; +const char GameObjectDisplayInfofmt[]="nsxxxxxxxxxxffffffxxx"; const char GemPropertiesEntryfmt[]="nixxix"; const char GlyphPropertiesfmt[]="niii"; diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index cccb780e412..e6039880b63 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -83,12 +83,12 @@ void LFGMgr::_LoadFromDB(Field* fields, uint64 guid) uint32 dungeon = fields[16].GetUInt32(); uint8 state = fields[17].GetUInt8(); - + if (!dungeon || !state) return; SetDungeon(guid, dungeon); - + switch (state) { case LFG_STATE_DUNGEON: @@ -104,19 +104,19 @@ void LFGMgr::_SaveToDB(uint64 guid, uint32 db_guid) { if (!IS_GROUP(guid)) return; - + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_LFG_DATA); stmt->setUInt32(0, db_guid); CharacterDatabase.Execute(stmt); - + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_LFG_DATA); stmt->setUInt32(0, db_guid); - + stmt->setUInt32(1, GetDungeon(guid)); stmt->setUInt32(2, GetState(guid)); - + CharacterDatabase.Execute(stmt); } @@ -999,7 +999,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) LfgQueueInfo* queue = itQueue->second; if (!queue) continue; - + for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) { if (*itPlayers == ObjectAccessor::FindPlayer(itPlayer->first)) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 82c5ce09d35..fc403ef1ff7 100755 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -141,11 +141,11 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapCreature(), lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLowGUID(0), -m_PlayerDamageReq(0), m_lootMoney(0), m_lootRecipient(0), m_lootRecipientGroup(0), m_corpseRemoveTime(0), m_respawnTime(0), +m_PlayerDamageReq(0), m_lootRecipient(0), m_lootRecipientGroup(0), m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), -m_creatureInfo(NULL), m_creatureData(NULL), m_formation(NULL), m_path_id(0) +m_creatureInfo(NULL), m_creatureData(NULL), m_path_id(0), m_formation(NULL) { m_regenTimer = CREATURE_REGEN_INTERVAL; m_valuesCount = UNIT_END; @@ -1289,7 +1289,7 @@ bool Creature::LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap) m_deathState = DEAD; if (canFly()) { - float tz = map->GetHeight(data->posX, data->posY, data->posZ, false); + float tz = map->GetHeight(GetPhaseMask(), data->posX, data->posY, data->posZ, false); if (data->posZ - tz > 0.1f) Relocate(data->posX, data->posY, tz); } @@ -1413,9 +1413,9 @@ bool Creature::canStartAttack(Unit const* who, bool force) const if (isCivilian()) return false; - if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)) + if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)) return false; - + // Do not attack non-combat pets if (who->GetTypeId() == TYPEID_UNIT && who->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET) return false; @@ -1565,7 +1565,7 @@ void Creature::Respawn(bool force) if (m_DBTableGuid) sObjectMgr->RemoveCreatureRespawnTime(m_DBTableGuid, GetInstanceId()); - sLog->outStaticDebug("Respawning..."); + sLog->outStaticDebug("Respawning creature %s (GuidLow: %u, Full GUID: " UI64FMTD " Entry: %u)", GetName(), GetGUIDLow(), GetGUID(), GetEntry()); m_respawnTime = 0; lootForPickPocketed = false; lootForBody = false; @@ -1907,7 +1907,7 @@ bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction / if (isCivilian()) return false; - if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PASSIVE)) + if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_NPC)) return false; // skip fighting creature diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index e890b6ac6fe..847f2aa6fd1 100755 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -211,7 +211,7 @@ struct CreatureBaseStats static CreatureBaseStats const* GetBaseStats(uint8 level, uint8 unitClass); }; -typedef UNORDERED_MAP<uint16, CreatureBaseStats> CreatureBaseStatsMap; +typedef UNORDERED_MAP<uint16, CreatureBaseStats> CreatureBaseStatsContainer; struct CreatureLocale { @@ -723,7 +723,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature static float _GetHealthMod(int32 Rank); - uint32 m_lootMoney; uint64 m_lootRecipient; uint32 m_lootRecipientGroup; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 64cc1bb325c..c04dd0b1941 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -30,7 +30,10 @@ #include "CreatureAISelector.h" #include "Group.h" -GameObject::GameObject() : WorldObject(false), m_goValue(new GameObjectValue), m_AI(NULL) +#include "GameObjectModel.h" +#include "DynamicTree.h" + +GameObject::GameObject() : WorldObject(false), m_model(NULL), m_goValue(new GameObjectValue), m_AI(NULL) { m_objectType |= TYPEMASK_GAMEOBJECT; m_objectTypeId = TYPEID_GAMEOBJECT; @@ -62,6 +65,7 @@ GameObject::~GameObject() { delete m_goValue; delete m_AI; + delete m_model; //if (m_uint32Values) // field array can be not exist if GameOBject not loaded // CleanupsBeforeDelete(); } @@ -127,6 +131,13 @@ void GameObject::AddToWorld() m_zoneScript->OnGameObjectCreate(this); sObjectAccessor->AddObject(this); + bool startOpen = (GetGoType() == GAMEOBJECT_TYPE_DOOR || GetGoType() == GAMEOBJECT_TYPE_BUTTON ? GetGOInfo()->door.startOpen : false); + bool toggledState = (GetGOData() ? GetGOData()->go_state == GO_STATE_ACTIVE : false); + if (m_model) + GetMap()->Insert(*m_model); + if ((startOpen && !toggledState) || (!startOpen && toggledState)) + EnableCollision(false); + WorldObject::AddToWorld(); } } @@ -140,6 +151,9 @@ void GameObject::RemoveFromWorld() m_zoneScript->OnGameObjectRemove(this); RemoveFromOwner(); + if (m_model) + if (GetMap()->Contains(*m_model)) + GetMap()->Remove(*m_model); WorldObject::RemoveFromWorld(); sObjectAccessor->RemoveObject(this); } @@ -199,15 +213,17 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa // set name for logs usage, doesn't affect anything ingame SetName(goinfo->name); - SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); + SetDisplayId(goinfo->displayId); + m_model = GameObjectModel::Create(*this); // GAMEOBJECT_BYTES_1, index at 0, 1, 2 and 3 - SetGoState(go_state); SetGoType(GameobjectTypes(goinfo->type)); + SetGoState(go_state); SetGoArtKit(0); // unknown what this is SetByteValue(GAMEOBJECT_BYTES_1, 2, artKit); + switch (goinfo->type) { case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING: @@ -228,13 +244,13 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa if (GetGOInfo()->trap.stealthed) { m_stealth.AddFlag(STEALTH_TRAP); - m_stealth.AddValue(STEALTH_TRAP, 300); + m_stealth.AddValue(STEALTH_TRAP, 70); } if (GetGOInfo()->trap.invisible) { m_invisibility.AddFlag(INVISIBILITY_TRAP); - m_invisibility.AddValue(INVISIBILITY_TRAP, 70); + m_invisibility.AddValue(INVISIBILITY_TRAP, 300); } break; @@ -850,6 +866,20 @@ bool GameObject::IsAlwaysVisibleFor(WorldObject const* seer) const if (IsTransport()) return true; + if (!seer) + return false; + + // Always seen by owner and friendly units + if (uint64 guid = GetOwnerGUID()) + { + if (seer->GetGUID() == guid) + return true; + + Unit* owner = GetOwner(); + if (owner && seer->isType(TYPEMASK_UNIT) && owner->IsFriendlyTo(((Unit*)seer))) + return true; + } + return false; } @@ -1779,7 +1809,7 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player* { case GO_DESTRUCTIBLE_INTACT: RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_DESTROYED); - SetUInt32Value(GAMEOBJECT_DISPLAYID, m_goInfo->displayId); + SetDisplayId(m_goInfo->displayId); if (setHealth) { m_goValue->Building.Health = m_goValue->Building.MaxHealth; @@ -1801,7 +1831,7 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player* if (DestructibleModelDataEntry const* modelData = sDestructibleModelDataStore.LookupEntry(m_goInfo->building.destructibleData)) if (modelData->DamagedDisplayId) modelId = modelData->DamagedDisplayId; - SetUInt32Value(GAMEOBJECT_DISPLAYID, modelId); + SetDisplayId(modelId); if (setHealth) { @@ -1834,7 +1864,7 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player* if (DestructibleModelDataEntry const* modelData = sDestructibleModelDataStore.LookupEntry(m_goInfo->building.destructibleData)) if (modelData->DestroyedDisplayId) modelId = modelData->DestroyedDisplayId; - SetUInt32Value(GAMEOBJECT_DISPLAYID, modelId); + SetDisplayId(modelId); if (setHealth) { @@ -1852,7 +1882,7 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player* if (DestructibleModelDataEntry const* modelData = sDestructibleModelDataStore.LookupEntry(m_goInfo->building.destructibleData)) if (modelData->RebuildingDisplayId) modelId = modelData->RebuildingDisplayId; - SetUInt32Value(GAMEOBJECT_DISPLAYID, modelId); + SetDisplayId(modelId); // restores to full health if (setHealth) @@ -1865,8 +1895,78 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player* } } -void GameObject::SetLootState(LootState s, Unit* unit) +void GameObject::SetLootState(LootState state, Unit* unit) { - m_lootState = s; - AI()->OnStateChanged(s, unit); + m_lootState = state; + AI()->OnStateChanged(state, unit); + if (m_model) + { + // startOpen determines whether we are going to add or remove the LoS on activation + bool startOpen = (GetGoType() == GAMEOBJECT_TYPE_DOOR || GetGoType() == GAMEOBJECT_TYPE_BUTTON ? GetGOInfo()->door.startOpen : false); + + if (GetGOData() && GetGOData()->go_state == GO_NOT_READY) + startOpen = !startOpen; + + if (state == GO_ACTIVATED || state == GO_JUST_DEACTIVATED) + EnableCollision(startOpen); + else if (state == GO_READY) + EnableCollision(!startOpen); + } +} + +void GameObject::SetGoState(GOState state) +{ + SetByteValue(GAMEOBJECT_BYTES_1, 0, state); + if (m_model) + { + if (!IsInWorld()) + return; + + // startOpen determines whether we are going to add or remove the LoS on activation + bool startOpen = (GetGoType() == GAMEOBJECT_TYPE_DOOR || GetGoType() == GAMEOBJECT_TYPE_BUTTON ? GetGOInfo()->door.startOpen : false); + + if (GetGOData() && GetGOData()->go_state == GO_NOT_READY) + startOpen = !startOpen; + + if (state == GO_STATE_ACTIVE || state == GO_STATE_ACTIVE_ALTERNATIVE) + EnableCollision(startOpen); + else if (state == GO_STATE_READY) + EnableCollision(!startOpen); + } +} + +void GameObject::SetDisplayId(uint32 displayid) +{ + SetUInt32Value(GAMEOBJECT_DISPLAYID, displayid); + UpdateModel(); +} + +void GameObject::SetPhaseMask(uint32 newPhaseMask, bool update) +{ + WorldObject::SetPhaseMask(newPhaseMask, update); + EnableCollision(true); +} + +void GameObject::EnableCollision(bool enable) +{ + if (!m_model) + return; + + /*if (enable && !GetMap()->Contains(*m_model)) + GetMap()->Insert(*m_model);*/ + + m_model->enable(enable ? GetPhaseMask() : 0); +} + +void GameObject::UpdateModel() +{ + if (!IsInWorld()) + return; + if (m_model) + if (GetMap()->Contains(*m_model)) + GetMap()->Remove(*m_model); + delete m_model; + m_model = GameObjectModel::Create(*this); + if (m_model) + GetMap()->Insert(*m_model); } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 2329ed10e49..2e40d45541c 100755 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -610,6 +610,7 @@ enum LootState }; class Unit; +class GameObjectModel; // 5 sec for bobber catch #define FISHING_BOBBER_READY_TIME 5 @@ -704,13 +705,16 @@ class GameObject : public WorldObject, public GridObject<GameObject> GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); } void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); } - void SetGoState(GOState state) { SetByteValue(GAMEOBJECT_BYTES_1, 0, state); } + void SetGoState(GOState state); uint8 GetGoArtKit() const { return GetByteValue(GAMEOBJECT_BYTES_1, 2); } void SetGoArtKit(uint8 artkit); uint8 GetGoAnimProgress() const { return GetByteValue(GAMEOBJECT_BYTES_1, 3); } void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); } static void SetGoArtKit(uint8 artkit, GameObject* go, uint32 lowguid = 0); + void SetPhaseMask(uint32 newPhaseMask, bool update); + void EnableCollision(bool enable); + void Use(Unit* user); LootState getLootState() const { return m_lootState; } @@ -791,6 +795,9 @@ class GameObject : public WorldObject, public GridObject<GameObject> GameObjectAI* AI() const { return m_AI; } std::string GetAIName() const; + void SetDisplayId(uint32 displayid); + + GameObjectModel * m_model; protected: bool AIM_Initialize(); uint32 m_spellId; @@ -820,6 +827,7 @@ class GameObject : public WorldObject, public GridObject<GameObject> private: void RemoveFromOwner(); void SwitchDoorOrButton(bool activate, bool alternative = false); + void UpdateModel(); // updates model in case displayId were changed //! Object distance/size - overridden from Object::_IsWithinDist. Needs to take in account proper GO size. bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool /*is3D*/) const diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 93068b4ed18..b5e39fe19af 100755 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -870,24 +870,6 @@ bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const return true; } -bool Item::IsTargetValidForItemUse(Unit* pUnitTarget) -{ - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET, GetTemplate()->ItemId); - if (conditions.empty()) - return true; - - if (!pUnitTarget) - return false; - - for (ConditionList::const_iterator itr = conditions.begin(); itr != conditions.end(); ++itr) - { - ItemRequiredTarget irt(ItemRequiredTargetType((*itr)->mConditionValue1), (*itr)->mConditionValue2); - if (irt.IsFitToRequirements(pUnitTarget)) - return true; - } - return false; -} - void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges) { // Better lost small time at check in comparison lost time at item save to DB. @@ -1092,25 +1074,6 @@ bool Item::IsBindedNotWith(Player const* player) const return true; } -bool ItemRequiredTarget::IsFitToRequirements(Unit* pUnitTarget) const -{ - if (pUnitTarget->GetTypeId() != TYPEID_UNIT) - return false; - - if (pUnitTarget->GetEntry() != m_uiTargetEntry) - return false; - - switch (m_uiType) - { - case ITEM_TARGET_TYPE_CREATURE: - return pUnitTarget->isAlive(); - case ITEM_TARGET_TYPE_DEAD: - return !pUnitTarget->isAlive(); - default: - return false; - } -} - void Item::BuildUpdate(UpdateDataMapType& data_map) { if (Player* owner = GetOwner()) diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index 41c13f78029..4887afc2b8a 100755 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -203,26 +203,8 @@ enum ItemUpdateState ITEM_REMOVED = 3 }; -enum ItemRequiredTargetType -{ - ITEM_TARGET_TYPE_CREATURE = 1, - ITEM_TARGET_TYPE_DEAD = 2 -}; - -#define MAX_ITEM_REQ_TARGET_TYPE 2 - #define MAX_ITEM_SPELLS 5 -struct ItemRequiredTarget -{ - ItemRequiredTarget(ItemRequiredTargetType uiType, uint32 uiTargetEntry) : m_uiType(uiType), m_uiTargetEntry(uiTargetEntry) {} - ItemRequiredTargetType m_uiType; - uint32 m_uiTargetEntry; - - // helpers - bool IsFitToRequirements(Unit* pUnitTarget) const; -}; - bool ItemCanGoIntoBag(ItemTemplate const* proto, ItemTemplate const* pBagProto); class Item : public Object @@ -270,7 +252,6 @@ class Item : public Object uint32 GetEnchantRequiredLevel() const; bool IsFitToSpellRequirements(SpellInfo const* spellInfo) const; - bool IsTargetValidForItemUse(Unit* pUnitTarget); bool IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const; bool GemsFitSockets() const; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 0332d0998b4..f1d0dd5a506 100755 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -46,6 +46,7 @@ #include "Totem.h" #include "OutdoorPvPMgr.h" #include "MovementPacketBuilder.h" +#include "DynamicTree.h" uint32 GuidHigh2TypeId(uint32 guid_hi) { @@ -1043,9 +1044,9 @@ bool Object::PrintIndexError(uint32 index, bool set) const return false; } -bool Position::HasInLine(Unit const* target, float distance, float width) const +bool Position::HasInLine(WorldObject const* target, float width) const { - if (!HasInArc(M_PI, target) || !target->IsWithinDist3d(m_positionX, m_positionY, m_positionZ, distance)) + if (!HasInArc(M_PI, target)) return false; width += target->GetObjectSize(); float angle = GetRelativeAngle(target); @@ -1259,15 +1260,19 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const float ox, oy, oz; obj->GetPosition(ox, oy, oz); - return(IsWithinLOS(ox, oy, oz)); + return IsWithinLOS(ox, oy, oz); } bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const { - float x, y, z; + /*float x, y, z; GetPosition(x, y, z); VMAP::IVMapManager* vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); - return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f); + return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f);*/ + if (IsInWorld()) + return GetMap()->isInLineOfSight(GetPositionX(), GetPositionY(), GetPositionZ()+2.f, ox, oy, oz+2.f, GetPhaseMask()); + + return true; } bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const @@ -1456,14 +1461,14 @@ bool WorldObject::IsInBetween(const WorldObject* obj1, const WorldObject* obj2, return (size * size) >= GetExactDist2dSq(obj1->GetPositionX() + cos(angle) * dist, obj1->GetPositionY() + sin(angle) * dist); } -bool WorldObject::isInFront(WorldObject const* target, float distance, float arc) const +bool WorldObject::isInFront(WorldObject const* target, float arc) const { - return IsWithinDist(target, distance) && HasInArc(arc, target); + return HasInArc(arc, target); } -bool WorldObject::isInBack(WorldObject const* target, float distance, float arc) const +bool WorldObject::isInBack(WorldObject const* target, float arc) const { - return IsWithinDist(target, distance) && !HasInArc(2 * M_PI - arc, target); + return !HasInArc(2 * M_PI - arc, target); } void WorldObject::GetRandomPoint(const Position &pos, float distance, float &rand_x, float &rand_y, float &rand_z) const @@ -1489,7 +1494,7 @@ void WorldObject::GetRandomPoint(const Position &pos, float distance, float &ran void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const { - float new_z = GetBaseMap()->GetHeight(x, y, z, true); + float new_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true); if (new_z > INVALID_HEIGHT) z = new_z+ 0.05f; // just to be sure that we are not a few pixel under the surface } @@ -1502,13 +1507,13 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const { // non fly unit don't must be in air // non swim unit must be at ground (mostly speedup, because it don't must be in water and water level check less fast - if (!((Creature const*)this)->canFly()) + if (!ToCreature()->canFly()) { - bool canSwim = ((Creature const*)this)->canSwim(); + bool canSwim = ToCreature()->canSwim(); float ground_z = z; float max_z = canSwim - ? GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK)) - : ((ground_z = GetBaseMap()->GetHeight(x, y, z, true))); + ? GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK)) + : ((ground_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true))); if (max_z > INVALID_HEIGHT) { if (z > max_z) @@ -1519,7 +1524,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const } else { - float ground_z = GetBaseMap()->GetHeight(x, y, z, true); + float ground_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true); if (z < ground_z) z = ground_z; } @@ -1528,10 +1533,10 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const case TYPEID_PLAYER: { // for server controlled moves playr work same as creature (but it can always swim) - if (!((Player const*)this)->canFly()) + if (!ToPlayer()->canFly()) { float ground_z = z; - float max_z = GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK)); + float max_z = GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK)); if (max_z > INVALID_HEIGHT) { if (z > max_z) @@ -1542,7 +1547,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const } else { - float ground_z = GetBaseMap()->GetHeight(x, y, z, true); + float ground_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true); if (z < ground_z) z = ground_z; } @@ -1550,7 +1555,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const } default: { - float ground_z = GetBaseMap()->GetHeight(x, y, z, true); + float ground_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true); if(ground_z > INVALID_HEIGHT) z = ground_z; break; @@ -1766,11 +1771,15 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const // Level difference: 5 point / level, starting from level 1. // There may be spells for this and the starting points too, but - // not in the DBCs of the client. + // not in the DBCs of the client. detectionValue += int32(getLevelForTarget(obj) - 1) * 5; // Apply modifiers detectionValue += m_stealthDetect.GetValue(StealthType(i)); + if (obj->isType(TYPEMASK_GAMEOBJECT)) + if (Unit* owner = ((GameObject*)obj)->GetOwner()) + detectionValue -= int32(owner->getLevelForTarget(this) - 1) * 5; + detectionValue -= obj->m_stealth.GetValue(StealthType(i)); // Calculate max distance @@ -2621,11 +2630,11 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float { angle += m_orientation; float destx, desty, destz, ground, floor; - + pos.m_positionZ += 2.0f; destx = pos.m_positionX + dist * cos(angle); desty = pos.m_positionY + dist * sin(angle); - ground = GetMap()->GetHeight(destx, desty, MAX_HEIGHT, true); - floor = GetMap()->GetHeight(destx, desty, pos.m_positionZ, true); + ground = GetMap()->GetHeight(GetPhaseMask(), destx, desty, MAX_HEIGHT, true); + floor = GetMap()->GetHeight(GetPhaseMask(), destx, desty, pos.m_positionZ, true); destz = fabs(ground - pos.m_positionZ) <= fabs(floor - pos.m_positionZ) ? ground : floor; bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(GetMapId(), pos.m_positionX, pos.m_positionY, pos.m_positionZ+0.5f, destx, desty, destz+0.5f, destx, desty, destz, -0.5f); @@ -2639,6 +2648,17 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float dist = sqrt((pos.m_positionX - destx)*(pos.m_positionX - destx) + (pos.m_positionY - desty)*(pos.m_positionY - desty)); } + // check dynamic collision + col = GetMap()->getObjectHitPos(GetPhaseMask(), pos.m_positionX, pos.m_positionY, pos.m_positionZ+0.5f, destx, desty, destz+0.5f, destx, desty, destz, -0.5f); + + // Collided with a gameobject + if (col) + { + destx -= CONTACT_DISTANCE * cos(angle); + desty -= CONTACT_DISTANCE * sin(angle); + dist = sqrt((pos.m_positionX - destx)*(pos.m_positionX - destx) + (pos.m_positionY - desty)*(pos.m_positionY - desty)); + } + float step = dist/10.0f; for (uint8 j = 0; j < 10; ++j) @@ -2648,8 +2668,8 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float { destx -= step * cos(angle); desty -= step * sin(angle); - ground = GetMap()->GetHeight(destx, desty, MAX_HEIGHT, true); - floor = GetMap()->GetHeight(destx, desty, pos.m_positionZ, true); + ground = GetMap()->GetHeight(GetPhaseMask(), destx, desty, MAX_HEIGHT, true); + floor = GetMap()->GetHeight(GetPhaseMask(), destx, desty, pos.m_positionZ, true); destz = fabs(ground - pos.m_positionZ) <= fabs(floor - pos.m_positionZ) ? ground : floor; } // we have correct destz now @@ -2662,7 +2682,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float Trinity::NormalizeMapCoord(pos.m_positionX); Trinity::NormalizeMapCoord(pos.m_positionY); - UpdateGroundPositionZ(pos.m_positionX, pos.m_positionY, pos.m_positionZ); + UpdateAllowedPositionZ(pos.m_positionX, pos.m_positionY, pos.m_positionZ); pos.m_orientation = m_orientation; } diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 666f71ffe68..54f64f8da38 100755 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -51,7 +51,7 @@ enum TypeMask TYPEMASK_OBJECT = 0x0001, TYPEMASK_ITEM = 0x0002, TYPEMASK_CONTAINER = 0x0006, // TYPEMASK_ITEM | 0x0004 - TYPEMASK_UNIT = 0x0008, //creature or player + TYPEMASK_UNIT = 0x0008, // creature TYPEMASK_PLAYER = 0x0010, TYPEMASK_GAMEOBJECT = 0x0020, TYPEMASK_DYNAMICOBJECT = 0x0040, @@ -450,7 +450,7 @@ struct Position bool IsInDist(const Position* pos, float dist) const { return GetExactDistSq(pos) < dist * dist; } bool HasInArc(float arcangle, const Position* pos) const; - bool HasInLine(Unit const* target, float distance, float width) const; + bool HasInLine(WorldObject const* target, float width) const; std::string ToString() const; }; ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); @@ -707,8 +707,8 @@ class WorldObject : public Object, public WorldLocation bool IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D = true) const; bool IsInRange2d(float x, float y, float minRange, float maxRange) const; bool IsInRange3d(float x, float y, float z, float minRange, float maxRange) const; - bool isInFront(WorldObject const* target, float distance, float arc = M_PI) const; - bool isInBack(WorldObject const* target, float distance, float arc = M_PI) const; + bool isInFront(WorldObject const* target, float arc = M_PI) const; + bool isInBack(WorldObject const* target, float arc = M_PI) const; bool IsInBetween(const WorldObject* obj1, const WorldObject* obj2, float size = 0) const; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 30f1c6e404b..088957ab0b3 100755 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -1107,6 +1107,9 @@ void Pet::_LoadAuras(uint32 timediff) int32 baseDamage[3]; Field* fields = result->Fetch(); uint64 caster_guid = fields[0].GetUInt64(); + // NULL guid stored - pet is the caster of the spell - see Pet::_SaveAuras + if (!caster_guid) + caster_guid = GetGUID(); uint32 spellid = fields[1].GetUInt32(); uint8 effmask = fields[2].GetUInt8(); uint8 recalculatemask = fields[3].GetUInt8(); @@ -1195,9 +1198,12 @@ void Pet::_SaveAuras(SQLTransaction& trans) } } + // don't save guid of caster in case we are caster of the spell - guid for pet is generated every pet load, so it won't match saved guid anyways + uint64 casterGUID = (itr->second->GetCasterGUID() == GetGUID()) ? 0 : itr->second->GetCasterGUID(); + trans->PAppend("INSERT INTO pet_aura (guid, caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges) " "VALUES ('%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u')", - m_charmInfo->GetPetNumber(), itr->second->GetCasterGUID(), itr->second->GetId(), effMask, recalculateMask, + m_charmInfo->GetPetNumber(), casterGUID, itr->second->GetId(), effMask, recalculateMask, itr->second->GetStackAmount(), damage[0], damage[1], damage[2], baseDamage[0], baseDamage[1], baseDamage[2], itr->second->GetMaxDuration(), itr->second->GetDuration(), itr->second->GetCharges()); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 21994640e63..2c9747312af 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -435,9 +435,9 @@ void TradeData::SetAccepted(bool state, bool crosssend /*= false*/) // 5. Credit instance encounter. KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) : // 1. Initialize internal variables to default values. - _killer(killer), _victim(victim), _isBattleGround(isBattleGround), - _isPvP(false), _group(killer->GetGroup()), _groupRate(1.0f), - _maxLevel(0), _maxNotGrayMember(NULL), _count(0), _sumLevel(0), _isFullXP(false), _xp(0) + _killer(killer), _victim(victim), _group(killer->GetGroup()), + _groupRate(1.0f), _maxNotGrayMember(NULL), _count(0), _sumLevel(0), _xp(0), + _isFullXP(false), _maxLevel(0), _isBattleGround(isBattleGround), _isPvP(false) { // mark the credit as pvp if victim is player if (victim->GetTypeId() == TYPEID_PLAYER) @@ -842,8 +842,6 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep for (uint8 i = 0; i < MAX_POWERS; ++i) m_powerFraction[i] = 0; - m_ConditionErrorMsgId = 0; - isDebugAreaTriggers = false; SetPendingBind(0, 0); @@ -1545,7 +1543,7 @@ void Player::Update(uint32 p_time) while (iter != m_timedquests.end()) { QuestStatusData& q_status = m_QuestStatus[*iter]; - if (q_status.m_timer <= p_time) + if (q_status.Timer <= p_time) { uint32 quest_id = *iter; ++iter; // current iter will be removed in FailQuest @@ -1553,7 +1551,7 @@ void Player::Update(uint32 p_time) } else { - q_status.m_timer -= p_time; + q_status.Timer -= p_time; m_QuestStatusSave[*iter] = true; ++iter; } @@ -2397,14 +2395,9 @@ bool Player::TeleportToBGEntryPoint() if (m_bgData.joinPos.m_mapId == MAPID_INVALID) return false; - Group* group = GetGroup(); - if (group && group->isLFGGroup() && group->GetMembersCount() == 1) - group->Disband(); - else - ScheduleDelayedOperation(DELAYED_BG_GROUP_RESTORE); - ScheduleDelayedOperation(DELAYED_BG_MOUNT_RESTORE); ScheduleDelayedOperation(DELAYED_BG_TAXI_RESTORE); + ScheduleDelayedOperation(DELAYED_BG_GROUP_RESTORE); return TeleportTo(m_bgData.joinPos); } @@ -3338,7 +3331,7 @@ void Player::InitStatsForLevel(bool reapplyMods) // cleanup unit flags (will be re-applied if need at aura load). RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_ATTACKABLE_1 | - UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE | UNIT_FLAG_LOOTING | + UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_LOOTING | UNIT_FLAG_PET_IN_COMBAT | UNIT_FLAG_SILENCED | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED | UNIT_FLAG_IN_COMBAT | UNIT_FLAG_DISARMED | UNIT_FLAG_CONFUSED | UNIT_FLAG_FLEEING | UNIT_FLAG_NOT_SELECTABLE | @@ -4522,11 +4515,14 @@ bool Player::ResetTalents(bool no_cost) // skip non-existant talent ranks if (talentInfo->RankID[rank] == 0) continue; + const SpellInfo* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->RankID[rank]); + if (!_spellEntry) + continue; removeSpell(talentInfo->RankID[rank], true); - if (const SpellInfo* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->RankID[rank])) - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) // search through the SpellInfo for valid trigger spells - if (_spellEntry->Effects[i].TriggerSpell > 0 && _spellEntry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL) - removeSpell(_spellEntry->Effects[i].TriggerSpell, true); // and remove any spells that the talent teaches + // search for spells that the talent teaches and unlearn them + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + 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 = GetTalentMap(GetActiveSpec())->find(talentInfo->RankID[rank]); if (plrTalent != GetTalentMap(GetActiveSpec())->end()) @@ -7048,38 +7044,38 @@ void Player::RewardReputation(Unit* pVictim, float rate) float favored_rep_mult = 0; if ((HasAura(32096) || HasAura(32098)) && (zone == 3483 || zone == 3562 || zone == 3836 || zone == 3713 || zone == 3714)) favored_rep_mult = 0.25; // Thrallmar's Favor and Honor Hold's Favor - else if (HasAura(30754) && (Rep->repfaction1 == 609 || Rep->repfaction2 == 609) && !ChampioningFaction) favored_rep_mult = 0.25; // Cenarion Favor + else if (HasAura(30754) && (Rep->RepFaction1 == 609 || Rep->RepFaction2 == 609) && !ChampioningFaction) favored_rep_mult = 0.25; // Cenarion Favor if (favored_rep_mult > 0) favored_rep_mult *= 2; // Multiplied by 2 because the reputation is divided by 2 for some reason (See "donerep1 / 2" and "donerep2 / 2") -- if you know why this is done, please update/explain :) // Favored reputation increase END bool recruitAFriend = GetsRecruitAFriendBonus(false); - if (Rep->repfaction1 && (!Rep->team_dependent || team == ALLIANCE)) + if (Rep->RepFaction1 && (!Rep->TeamDependent || team == ALLIANCE)) { - int32 donerep1 = CalculateReputationGain(pVictim->getLevel(), Rep->repvalue1, ChampioningFaction ? ChampioningFaction : Rep->repfaction1, false); + int32 donerep1 = CalculateReputationGain(pVictim->getLevel(), Rep->RepValue1, ChampioningFaction ? ChampioningFaction : Rep->RepFaction1, false); donerep1 = int32(donerep1*(rate + favored_rep_mult)); if (recruitAFriend) donerep1 = int32(donerep1 * (1 + sWorld->getRate(RATE_REPUTATION_RECRUIT_A_FRIEND_BONUS))); - FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->repfaction1); + FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->RepFaction1); uint32 current_reputation_rank1 = GetReputationMgr().GetRank(factionEntry1); - if (factionEntry1 && current_reputation_rank1 <= Rep->reputation_max_cap1) + if (factionEntry1 && current_reputation_rank1 <= Rep->ReputationMaxCap1) GetReputationMgr().ModifyReputation(factionEntry1, donerep1); } - if (Rep->repfaction2 && (!Rep->team_dependent || team == HORDE)) + if (Rep->RepFaction2 && (!Rep->TeamDependent || team == HORDE)) { - int32 donerep2 = CalculateReputationGain(pVictim->getLevel(), Rep->repvalue2, ChampioningFaction ? ChampioningFaction : Rep->repfaction2, false); + int32 donerep2 = CalculateReputationGain(pVictim->getLevel(), Rep->RepValue2, ChampioningFaction ? ChampioningFaction : Rep->RepFaction2, false); donerep2 = int32(donerep2*(rate + favored_rep_mult)); if (recruitAFriend) donerep2 = int32(donerep2 * (1 + sWorld->getRate(RATE_REPUTATION_RECRUIT_A_FRIEND_BONUS))); - FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->repfaction2); + FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->RepFaction2); uint32 current_reputation_rank2 = GetReputationMgr().GetRank(factionEntry2); - if (factionEntry2 && current_reputation_rank2 <= Rep->reputation_max_cap2) + if (factionEntry2 && current_reputation_rank2 <= Rep->ReputationMaxCap2) GetReputationMgr().ModifyReputation(factionEntry2, donerep2); } } @@ -11963,7 +11959,7 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje Map const* map = lootedObject->GetMap(); if (uint32 dungeonId = sLFGMgr->GetDungeon(GetGroup()->GetGUID(), true)) if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) - if (dungeon->map == map->GetId() && dungeon->difficulty == map->GetDifficulty()) + if (uint32(dungeon->map) == map->GetId() && dungeon->difficulty == map->GetDifficulty()) lootedObjectInDungeon = true; if (!lootedObjectInDungeon) @@ -12054,6 +12050,7 @@ Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update { ItemAddedQuestCheck(item, count); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, item, count); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, item, 1); if (randomPropertyId) pItem->SetItemRandomProperties(randomPropertyId); pItem = StoreItem(dest, pItem, update); @@ -12091,7 +12088,6 @@ Item* Player::StoreItem(ItemPosCountVec const& dest, Item* pItem, bool update) return NULL; Item* lastItem = pItem; - uint32 entry = pItem->GetEntry(); for (ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end();) { uint16 pos = itr->pos; @@ -12107,7 +12103,6 @@ Item* Player::StoreItem(ItemPosCountVec const& dest, Item* pItem, bool update) lastItem = _StoreItem(pos, pItem, count, true, update); } - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, entry); return lastItem; } @@ -14148,10 +14143,10 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool if (source->ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) PrepareQuestMenu(source->GetGUID()); - for (GossipMenuItemsMap::const_iterator itr = menuItemBounds.first; itr != menuItemBounds.second; ++itr) + for (GossipMenuItemsContainer::const_iterator itr = menuItemBounds.first; itr != menuItemBounds.second; ++itr) { bool canTalk = true; - if (!sConditionMgr->IsPlayerMeetToConditions(this, itr->second.Conditions)) + if (!sConditionMgr->IsObjectMeetToConditions(this, source, itr->second.Conditions)) continue; if (source->GetTypeId() == TYPEID_UNIT) @@ -14295,7 +14290,7 @@ void Player::SendPreparedGossip(WorldObject* source) uint32 textId = GetGossipTextId(source); if (uint32 menuId = PlayerTalkClass->GetGossipMenu().GetMenuId()) - textId = GetGossipTextId(menuId); + textId = GetGossipTextId(menuId, source); PlayerTalkClass->SendGossipMenu(textId, source->GetGUID()); } @@ -14386,7 +14381,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men break; case GOSSIP_OPTION_UNLEARNTALENTS: PlayerTalkClass->SendCloseGossip(); - source->ToCreature()->CastSpell(this, 46331, true); // Trainer: Untrain Talents + SendTalentWipeConfirm(guid); break; case GOSSIP_OPTION_UNLEARNPETTALENTS: PlayerTalkClass->SendCloseGossip(); @@ -14440,10 +14435,10 @@ uint32 Player::GetGossipTextId(WorldObject* source) if (!source) return DEFAULT_GOSSIP_MESSAGE; - return GetGossipTextId(GetDefaultGossipMenuForSource(source)); + return GetGossipTextId(GetDefaultGossipMenuForSource(source), source); } -uint32 Player::GetGossipTextId(uint32 menuId) +uint32 Player::GetGossipTextId(uint32 menuId, WorldObject* source) { uint32 textId = DEFAULT_GOSSIP_MESSAGE; @@ -14452,9 +14447,11 @@ uint32 Player::GetGossipTextId(uint32 menuId) GossipMenusMapBounds menuBounds = sObjectMgr->GetGossipMenusMapBounds(menuId); - for (GossipMenusMap::const_iterator itr = menuBounds.first; itr != menuBounds.second; ++itr) - if (sConditionMgr->IsPlayerMeetToConditions(this, itr->second.conditions)) + for (GossipMenusContainer::const_iterator itr = menuBounds.first; itr != menuBounds.second; ++itr) + { + if (sConditionMgr->IsObjectMeetToConditions(this, source, itr->second.conditions)) textId = itr->second.text_id; + } return textId; } @@ -14740,13 +14737,13 @@ bool Player::CanCompleteQuest(uint32 quest_id) QuestStatusData &q_status = itr->second; - if (q_status.m_status == QUEST_STATUS_INCOMPLETE) + if (q_status.Status == QUEST_STATUS_INCOMPLETE) { if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_DELIVER)) { for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++) { - if (qInfo->RequiredItemCount[i]!= 0 && q_status.m_itemcount[i] < qInfo->RequiredItemCount[i]) + if (qInfo->RequiredItemCount[i]!= 0 && q_status.ItemCount[i] < qInfo->RequiredItemCount[i]) return false; } } @@ -14758,19 +14755,19 @@ bool Player::CanCompleteQuest(uint32 quest_id) if (qInfo->RequiredNpcOrGo[i] == 0) continue; - if (qInfo->RequiredNpcOrGoCount[i] != 0 && q_status.m_creatureOrGOcount[i] < qInfo->RequiredNpcOrGoCount[i]) + if (qInfo->RequiredNpcOrGoCount[i] != 0 && q_status.CreatureOrGOCount[i] < qInfo->RequiredNpcOrGoCount[i]) return false; } } if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL)) - if (qInfo->GetPlayersSlain() != 0 && q_status.m_playercount < qInfo->GetPlayersSlain()) + if (qInfo->GetPlayersSlain() != 0 && q_status.PlayerCount < qInfo->GetPlayersSlain()) return false; - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT) && !q_status.m_explored) + if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT) && !q_status.Explored) return false; - if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_TIMED) && q_status.m_timer == 0) + if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_TIMED) && q_status.Timer == 0) return false; if (qInfo->GetRewOrReqMoney() < 0) @@ -14887,7 +14884,9 @@ bool Player::CanRewardQuest(Quest const* quest, uint32 reward, bool msg) void Player::AddQuest(Quest const* quest, Object* questGiver) { uint16 log_slot = FindQuestSlot(0); - ASSERT(log_slot < MAX_QUEST_LOG_SIZE); + + if (log_slot >= MAX_QUEST_LOG_SIZE) // Player does not have any free slot in the quest log + return; uint32 quest_id = quest->GetQuestId(); @@ -14895,23 +14894,23 @@ void Player::AddQuest(Quest const* quest, Object* questGiver) QuestStatusData& questStatusData = m_QuestStatus[quest_id]; // check for repeatable quests status reset - questStatusData.m_status = QUEST_STATUS_INCOMPLETE; - questStatusData.m_explored = false; + questStatusData.Status = QUEST_STATUS_INCOMPLETE; + questStatusData.Explored = false; if (quest->HasFlag(QUEST_TRINITY_FLAGS_DELIVER)) { for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) - questStatusData.m_itemcount[i] = 0; + questStatusData.ItemCount[i] = 0; } if (quest->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO)) { for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - questStatusData.m_creatureOrGOcount[i] = 0; + questStatusData.CreatureOrGOCount[i] = 0; } if (quest->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL)) - questStatusData.m_playercount = 0; + questStatusData.PlayerCount = 0; GiveQuestSourceItem(quest); AdjustQuestReqItemCount(quest, questStatusData); @@ -14931,14 +14930,14 @@ void Player::AddQuest(Quest const* quest, Object* questGiver) // shared timed quest if (questGiver && questGiver->GetTypeId() == TYPEID_PLAYER) - limittime = questGiver->ToPlayer()->getQuestStatusMap()[quest_id].m_timer / IN_MILLISECONDS; + limittime = questGiver->ToPlayer()->getQuestStatusMap()[quest_id].Timer / IN_MILLISECONDS; AddTimedQuest(quest_id); - questStatusData.m_timer = limittime * IN_MILLISECONDS; + questStatusData.Timer = limittime * IN_MILLISECONDS; qtime = static_cast<uint32>(time(NULL)) + limittime; } else - questStatusData.m_timer = 0; + questStatusData.Timer = 0; SetQuestSlot(log_slot, quest_id, qtime); @@ -15198,7 +15197,7 @@ void Player::FailQuest(uint32 questId) QuestStatusData& q_status = m_QuestStatus[questId]; RemoveTimedQuest(questId); - q_status.m_timer = 0; + q_status.Timer = 0; SendQuestTimerFailed(questId); } @@ -15436,7 +15435,7 @@ bool Player::SatisfyQuestStatus(Quest const* qInfo, bool msg) bool Player::SatisfyQuestConditions(Quest const* qInfo, bool msg) { ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_ACCEPT, qInfo->GetQuestId()); - if (!sConditionMgr->IsPlayerMeetToConditions(this, conditions)) + if (!sConditionMgr->IsObjectMeetToConditions(this, conditions)) { if (msg) SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); @@ -15528,7 +15527,7 @@ bool Player::SatisfyQuestPrevChain(Quest const* qInfo, bool msg) QuestStatusMap::const_iterator itr = m_QuestStatus.find(*iter); // If any of the previous quests in chain active, return false - if (itr != m_QuestStatus.end() && itr->second.m_status != QUEST_STATUS_NONE) + if (itr != m_QuestStatus.end() && itr->second.Status != QUEST_STATUS_NONE) { if (msg) SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); @@ -15594,8 +15593,8 @@ bool Player::SatisfyQuestSeasonal(Quest const* qInfo, bool /*msg*/) return true; uint16 eventId = sGameEventMgr->GetEventIdForQuest(qInfo); - if (m_seasonalquests.find(eventId) == m_seasonalquests.end()) - return false; + if (m_seasonalquests.find(eventId) == m_seasonalquests.end() || m_seasonalquests[eventId].empty()) + return true; // if not found in cooldown list return m_seasonalquests[eventId].find(qInfo->GetQuestId()) == m_seasonalquests[eventId].end(); @@ -15688,7 +15687,7 @@ QuestStatus Player::GetQuestStatus(uint32 quest_id) const { QuestStatusMap::const_iterator itr = m_QuestStatus.find(quest_id); if (itr != m_QuestStatus.end()) - return itr->second.m_status; + return itr->second.Status; if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id)) if (!qInfo->IsRepeatable() && m_RewardedQuests.find(quest_id) != m_RewardedQuests.end()) @@ -15704,7 +15703,7 @@ bool Player::CanShareQuest(uint32 quest_id) const { QuestStatusMap::const_iterator itr = m_QuestStatus.find(quest_id); if (itr != m_QuestStatus.end()) - return itr->second.m_status == QUEST_STATUS_INCOMPLETE; + return itr->second.Status == QUEST_STATUS_INCOMPLETE; } return false; } @@ -15713,7 +15712,7 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status) { if (sObjectMgr->GetQuestTemplate(quest_id)) { - m_QuestStatus[quest_id].m_status = status; + m_QuestStatus[quest_id].Status = status; m_QuestStatusSave[quest_id] = true; } @@ -15750,7 +15749,7 @@ uint16 Player::GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry) for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) if (qInfo->RequiredNpcOrGo[j] == entry) - return m_QuestStatus[quest_id].m_creatureOrGOcount[j]; + return m_QuestStatus[quest_id].CreatureOrGOCount[j]; return 0; } @@ -15766,7 +15765,7 @@ void Player::AdjustQuestReqItemCount(Quest const* quest, QuestStatusData& questS { uint32 curitemcount = GetItemCount(quest->RequiredItemId[i], true); - questStatusData.m_itemcount[i] = std::min(curitemcount, reqitemcount); + questStatusData.ItemCount[i] = std::min(curitemcount, reqitemcount); m_QuestStatusSave[quest->GetQuestId()] = true; } } @@ -15791,9 +15790,9 @@ void Player::AreaExploredOrEventHappens(uint32 questId) { QuestStatusData& q_status = m_QuestStatus[questId]; - if (!q_status.m_explored) + if (!q_status.Explored) { - q_status.m_explored = true; + q_status.Explored = true; m_QuestStatusSave[questId] = true; } } @@ -15830,7 +15829,7 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count) QuestStatusData& q_status = m_QuestStatus[questid]; - if (q_status.m_status != QUEST_STATUS_INCOMPLETE) + if (q_status.Status != QUEST_STATUS_INCOMPLETE) continue; Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid); @@ -15843,11 +15842,11 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count) if (reqitem == entry) { uint32 reqitemcount = qInfo->RequiredItemCount[j]; - uint16 curitemcount = q_status.m_itemcount[j]; + uint16 curitemcount = q_status.ItemCount[j]; if (curitemcount < reqitemcount) { uint16 additemcount = curitemcount + count <= reqitemcount ? count : reqitemcount - curitemcount; - q_status.m_itemcount[j] += additemcount; + q_status.ItemCount[j] += additemcount; m_QuestStatusSave[questid] = true; @@ -15884,14 +15883,14 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count) uint32 reqitemcount = qInfo->RequiredItemCount[j]; uint16 curitemcount; - if (q_status.m_status != QUEST_STATUS_COMPLETE) - curitemcount = q_status.m_itemcount[j]; + if (q_status.Status != QUEST_STATUS_COMPLETE) + curitemcount = q_status.ItemCount[j]; else curitemcount = GetItemCount(entry, true); if (curitemcount < reqitemcount + count) { uint16 remitemcount = curitemcount <= reqitemcount ? count : count + reqitemcount - curitemcount; - q_status.m_itemcount[j] = (curitemcount <= remitemcount) ? 0 : curitemcount - remitemcount; + q_status.ItemCount[j] = (curitemcount <= remitemcount) ? 0 : curitemcount - remitemcount; m_QuestStatusSave[questid] = true; @@ -15939,7 +15938,7 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid) continue; // just if !ingroup || !noraidgroup || raidgroup QuestStatusData& q_status = m_QuestStatus[questid]; - if (q_status.m_status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid())) + if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid())) { if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST)) { @@ -15958,10 +15957,10 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid) if (reqkill == real_entry) { uint32 reqkillcount = qInfo->RequiredNpcOrGoCount[j]; - uint16 curkillcount = q_status.m_creatureOrGOcount[j]; + uint16 curkillcount = q_status.CreatureOrGOCount[j]; if (curkillcount < reqkillcount) { - q_status.m_creatureOrGOcount[j] = curkillcount + addkillcount; + q_status.CreatureOrGOCount[j] = curkillcount + addkillcount; m_QuestStatusSave[questid] = true; @@ -15994,16 +15993,16 @@ void Player::KilledPlayerCredit() continue; // just if !ingroup || !noraidgroup || raidgroup QuestStatusData& q_status = m_QuestStatus[questid]; - if (q_status.m_status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid())) + if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid())) { if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_PLAYER_KILL)) { uint32 reqkill = qInfo->GetPlayersSlain(); - uint16 curkill = q_status.m_playercount; + uint16 curkill = q_status.PlayerCount; if (curkill < reqkill) { - q_status.m_playercount = curkill + addkillcount; + q_status.PlayerCount = curkill + addkillcount; m_QuestStatusSave[questid] = true; @@ -16036,7 +16035,7 @@ void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id) QuestStatusData& q_status = m_QuestStatus[questid]; - if (q_status.m_status == QUEST_STATUS_INCOMPLETE) + if (q_status.Status == QUEST_STATUS_INCOMPLETE) { if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST)) { @@ -16077,10 +16076,10 @@ void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id) continue; uint32 reqCastCount = qInfo->RequiredNpcOrGoCount[j]; - uint16 curCastCount = q_status.m_creatureOrGOcount[j]; + uint16 curCastCount = q_status.CreatureOrGOCount[j]; if (curCastCount < reqCastCount) { - q_status.m_creatureOrGOcount[j] = curCastCount + addCastCount; + q_status.CreatureOrGOCount[j] = curCastCount + addCastCount; m_QuestStatusSave[questid] = true; @@ -16113,7 +16112,7 @@ void Player::TalkedToCreature(uint32 entry, uint64 guid) QuestStatusData& q_status = m_QuestStatus[questid]; - if (q_status.m_status == QUEST_STATUS_INCOMPLETE) + if (q_status.Status == QUEST_STATUS_INCOMPLETE) { if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO)) { @@ -16134,10 +16133,10 @@ void Player::TalkedToCreature(uint32 entry, uint64 guid) if (reqTarget == entry) { uint32 reqTalkCount = qInfo->RequiredNpcOrGoCount[j]; - uint16 curTalkCount = q_status.m_creatureOrGOcount[j]; + uint16 curTalkCount = q_status.CreatureOrGOCount[j]; if (curTalkCount < reqTalkCount) { - q_status.m_creatureOrGOcount[j] = curTalkCount + addTalkCount; + q_status.CreatureOrGOCount[j] = curTalkCount + addTalkCount; m_QuestStatusSave[questid] = true; @@ -16168,7 +16167,7 @@ void Player::MoneyChanged(uint32 count) { QuestStatusData& q_status = m_QuestStatus[questid]; - if (q_status.m_status == QUEST_STATUS_INCOMPLETE) + if (q_status.Status == QUEST_STATUS_INCOMPLETE) { if (int32(count) >= -qInfo->GetRewOrReqMoney()) { @@ -16176,7 +16175,7 @@ void Player::MoneyChanged(uint32 count) CompleteQuest(questid); } } - else if (q_status.m_status == QUEST_STATUS_COMPLETE) + else if (q_status.Status == QUEST_STATUS_COMPLETE) { if (int32(count) < -qInfo->GetRewOrReqMoney()) IncompleteQuest(questid); @@ -16196,13 +16195,13 @@ void Player::ReputationChanged(FactionEntry const* factionEntry) if (qInfo->GetRepObjectiveFaction() == factionEntry->ID) { QuestStatusData& q_status = m_QuestStatus[questid]; - if (q_status.m_status == QUEST_STATUS_INCOMPLETE) + if (q_status.Status == QUEST_STATUS_INCOMPLETE) { if (GetReputationMgr().GetReputation(factionEntry) >= qInfo->GetRepObjectiveValue()) if (CanCompleteQuest(questid)) CompleteQuest(questid); } - else if (q_status.m_status == QUEST_STATUS_COMPLETE) + else if (q_status.Status == QUEST_STATUS_COMPLETE) { if (GetReputationMgr().GetReputation(factionEntry) < qInfo->GetRepObjectiveValue()) IncompleteQuest(questid); @@ -16224,13 +16223,13 @@ void Player::ReputationChanged2(FactionEntry const* factionEntry) if (qInfo->GetRepObjectiveFaction2() == factionEntry->ID) { QuestStatusData& q_status = m_QuestStatus[questid]; - if (q_status.m_status == QUEST_STATUS_INCOMPLETE) + if (q_status.Status == QUEST_STATUS_INCOMPLETE) { if (GetReputationMgr().GetReputation(factionEntry) >= qInfo->GetRepObjectiveValue2()) if (CanCompleteQuest(questid)) CompleteQuest(questid); } - else if (q_status.m_status == QUEST_STATUS_COMPLETE) + else if (q_status.Status == QUEST_STATUS_COMPLETE) { if (GetReputationMgr().GetReputation(factionEntry) < qInfo->GetRepObjectiveValue2()) IncompleteQuest(questid); @@ -16255,7 +16254,7 @@ bool Player::HasQuestForItem(uint32 itemid) const QuestStatusData const& q_status = qs_itr->second; - if (q_status.m_status == QUEST_STATUS_INCOMPLETE) + if (q_status.Status == QUEST_STATUS_INCOMPLETE) { Quest const* qinfo = sObjectMgr->GetQuestTemplate(questid); if (!qinfo) @@ -16270,7 +16269,7 @@ bool Player::HasQuestForItem(uint32 itemid) const // This part for ReqItem drop for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j) { - if (itemid == qinfo->RequiredItemId[j] && q_status.m_itemcount[j] < qinfo->RequiredItemCount[j]) + if (itemid == qinfo->RequiredItemId[j] && q_status.ItemCount[j] < qinfo->RequiredItemCount[j]) return true; } // This part - for ReqSource @@ -17888,14 +17887,14 @@ void Player::_LoadQuestStatus(PreparedQueryResult result) uint8 qstatus = fields[1].GetUInt8(); if (qstatus < MAX_QUEST_STATUS) - questStatusData.m_status = QuestStatus(qstatus); + questStatusData.Status = QuestStatus(qstatus); else { - questStatusData.m_status = QUEST_STATUS_INCOMPLETE; + questStatusData.Status = QUEST_STATUS_INCOMPLETE; sLog->outError("Player %s have invalid quest %d status (%u), replaced by QUEST_STATUS_INCOMPLETE(3).", GetName(), quest_id, qstatus); } - questStatusData.m_explored = (fields[2].GetUInt8() > 0); + questStatusData.Explored = (fields[2].GetUInt8() > 0); time_t quest_time = time_t(fields[3].GetUInt32()); @@ -17904,44 +17903,44 @@ void Player::_LoadQuestStatus(PreparedQueryResult result) AddTimedQuest(quest_id); if (quest_time <= sWorld->GetGameTime()) - questStatusData.m_timer = 1; + questStatusData.Timer = 1; else - questStatusData.m_timer = uint32((quest_time - sWorld->GetGameTime()) * IN_MILLISECONDS); + questStatusData.Timer = uint32((quest_time - sWorld->GetGameTime()) * IN_MILLISECONDS); } else quest_time = 0; - questStatusData.m_creatureOrGOcount[0] = fields[4].GetUInt16(); - questStatusData.m_creatureOrGOcount[1] = fields[5].GetUInt16(); - questStatusData.m_creatureOrGOcount[2] = fields[6].GetUInt16(); - questStatusData.m_creatureOrGOcount[3] = fields[7].GetUInt16(); - questStatusData.m_itemcount[0] = fields[8].GetUInt16(); - questStatusData.m_itemcount[1] = fields[9].GetUInt16(); - questStatusData.m_itemcount[2] = fields[10].GetUInt16(); - questStatusData.m_itemcount[3] = fields[11].GetUInt16(); - questStatusData.m_playercount = fields[12].GetUInt16(); + questStatusData.CreatureOrGOCount[0] = fields[4].GetUInt16(); + questStatusData.CreatureOrGOCount[1] = fields[5].GetUInt16(); + questStatusData.CreatureOrGOCount[2] = fields[6].GetUInt16(); + questStatusData.CreatureOrGOCount[3] = fields[7].GetUInt16(); + questStatusData.ItemCount[0] = fields[8].GetUInt16(); + questStatusData.ItemCount[1] = fields[9].GetUInt16(); + questStatusData.ItemCount[2] = fields[10].GetUInt16(); + questStatusData.ItemCount[3] = fields[11].GetUInt16(); + questStatusData.PlayerCount = fields[12].GetUInt16(); // add to quest log - if (slot < MAX_QUEST_LOG_SIZE && questStatusData.m_status != QUEST_STATUS_NONE) + if (slot < MAX_QUEST_LOG_SIZE && questStatusData.Status != QUEST_STATUS_NONE) { SetQuestSlot(slot, quest_id, uint32(quest_time)); // cast can't be helped - if (questStatusData.m_status == QUEST_STATUS_COMPLETE) + if (questStatusData.Status == QUEST_STATUS_COMPLETE) SetQuestSlotState(slot, QUEST_STATE_COMPLETE); - else if (questStatusData.m_status == QUEST_STATUS_FAILED) + else if (questStatusData.Status == QUEST_STATUS_FAILED) SetQuestSlotState(slot, QUEST_STATE_FAIL); for (uint8 idx = 0; idx < QUEST_OBJECTIVES_COUNT; ++idx) - if (questStatusData.m_creatureOrGOcount[idx]) - SetQuestSlotCounter(slot, idx, questStatusData.m_creatureOrGOcount[idx]); + if (questStatusData.CreatureOrGOCount[idx]) + SetQuestSlotCounter(slot, idx, questStatusData.CreatureOrGOCount[idx]); - if (questStatusData.m_playercount) - SetQuestSlotCounter(slot, QUEST_PVP_KILL_SLOT, questStatusData.m_playercount); + if (questStatusData.PlayerCount) + SetQuestSlotCounter(slot, QUEST_PVP_KILL_SLOT, questStatusData.PlayerCount); ++slot; } - sLog->outDebug(LOG_FILTER_PLAYER_LOADING, "Quest status is {%u} for quest {%u} for player (GUID: %u)", questStatusData.m_status, quest_id, GetGUIDLow()); + sLog->outDebug(LOG_FILTER_PLAYER_LOADING, "Quest status is {%u} for quest {%u} for player (GUID: %u)", questStatusData.Status, quest_id, GetGUIDLow()); } } while (result->NextRow()); @@ -19119,10 +19118,10 @@ void Player::_SaveQuestStatus(SQLTransaction& trans) if (saveItr->second) { statusItr = m_QuestStatus.find(saveItr->first); - if (statusItr != m_QuestStatus.end() && (keepAbandoned || statusItr->second.m_status != QUEST_STATUS_NONE)) + if (statusItr != m_QuestStatus.end() && (keepAbandoned || statusItr->second.Status != QUEST_STATUS_NONE)) trans->PAppend("REPLACE INTO character_queststatus (guid, quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, itemcount1, itemcount2, itemcount3, itemcount4, playercount) " "VALUES ('%u', '%u', '%u', '%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", - GetGUIDLow(), statusItr->first, statusItr->second.m_status, statusItr->second.m_explored, uint64(statusItr->second.m_timer / IN_MILLISECONDS+ sWorld->GetGameTime()), statusItr->second.m_creatureOrGOcount[0], statusItr->second.m_creatureOrGOcount[1], statusItr->second.m_creatureOrGOcount[2], statusItr->second.m_creatureOrGOcount[3], statusItr->second.m_itemcount[0], statusItr->second.m_itemcount[1], statusItr->second.m_itemcount[2], statusItr->second.m_itemcount[3], statusItr->second.m_playercount); + GetGUIDLow(), statusItr->first, statusItr->second.Status, statusItr->second.Explored, uint64(statusItr->second.Timer / IN_MILLISECONDS+ sWorld->GetGameTime()), statusItr->second.CreatureOrGOCount[0], statusItr->second.CreatureOrGOCount[1], statusItr->second.CreatureOrGOCount[2], statusItr->second.CreatureOrGOCount[3], statusItr->second.ItemCount[0], statusItr->second.ItemCount[1], statusItr->second.ItemCount[2], statusItr->second.ItemCount[3], statusItr->second.PlayerCount); } else trans->PAppend("DELETE FROM character_queststatus WHERE guid = %u AND quest = %u", GetGUIDLow(), saveItr->first); @@ -19977,7 +19976,7 @@ void Player::VehicleSpellInitialize() } ConditionList conditions = sConditionMgr->GetConditionsForVehicleSpell(veh->GetEntry(), spellId); - if (!sConditionMgr->IsPlayerMeetToConditions(this, conditions)) + if (!sConditionMgr->IsObjectMeetToConditions(this, veh, conditions)) { sLog->outDebug(LOG_FILTER_CONDITIONSYS, "VehicleSpellInitialize: conditions not met for Vehicle entry %u spell %u", veh->ToCreature()->GetEntry(), spellId); data << uint16(0) << uint8(0) << uint8(i+8); @@ -20387,9 +20386,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc // not let cheating with start flight in time of logout process || while in combat || has type state: stunned || has type state: root if (GetSession()->isLogingOut() || isInCombat() || HasUnitState(UNIT_STATE_STUNNED) || HasUnitState(UNIT_STATE_ROOT)) { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXIPLAYERBUSY); - GetSession()->SendPacket(&data); + GetSession()->SendActivateTaxiReply(ERR_TAXIPLAYERBUSY); return false; } @@ -20402,26 +20399,20 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc // not let cheating with start flight mounted if (IsMounted()) { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXIPLAYERALREADYMOUNTED); - GetSession()->SendPacket(&data); + GetSession()->SendActivateTaxiReply(ERR_TAXIPLAYERALREADYMOUNTED); return false; } if (IsInDisallowedMountForm()) { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXIPLAYERSHAPESHIFTED); - GetSession()->SendPacket(&data); + GetSession()->SendActivateTaxiReply(ERR_TAXIPLAYERSHAPESHIFTED); return false; } // not let cheating with start flight in time of logout process || if casting not finished || while in combat || if not use Spell's with EffectSendTaxi if (IsNonMeleeSpellCasted(false)) { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXIPLAYERBUSY); - GetSession()->SendPacket(&data); + GetSession()->SendActivateTaxiReply(ERR_TAXIPLAYERBUSY); return false; } } @@ -20450,9 +20441,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(sourcenode); if (!node) { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXINOSUCHPATH); - GetSession()->SendPacket(&data); + GetSession()->SendActivateTaxiReply(ERR_TAXINOSUCHPATH); return false; } @@ -20465,18 +20454,14 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc (node->z - GetPositionZ())*(node->z - GetPositionZ()) > (2*INTERACTION_DISTANCE)*(2*INTERACTION_DISTANCE)*(2*INTERACTION_DISTANCE)) { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXITOOFARAWAY); - GetSession()->SendPacket(&data); + GetSession()->SendActivateTaxiReply(ERR_TAXITOOFARAWAY); return false; } } // node must have pos if taxi master case (npc != NULL) else if (npc) { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXIUNSPECIFIEDSERVERERROR); - GetSession()->SendPacket(&data); + GetSession()->SendActivateTaxiReply(ERR_TAXIUNSPECIFIEDSERVERERROR); return false; } @@ -20539,9 +20524,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc // in spell case allow 0 model if ((mount_display_id == 0 && spellid == 0) || sourcepath == 0) { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXIUNSPECIFIEDSERVERERROR); - GetSession()->SendPacket(&data); + GetSession()->SendActivateTaxiReply(ERR_TAXIUNSPECIFIEDSERVERERROR); m_taxi.ClearTaxiDestinations(); return false; } @@ -20553,9 +20536,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc if (money < totalcost) { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXINOTENOUGHMONEY); - GetSession()->SendPacket(&data); + GetSession()->SendActivateTaxiReply(ERR_TAXINOTENOUGHMONEY); m_taxi.ClearTaxiDestinations(); return false; } @@ -20577,10 +20558,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc } else { - WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); - data << uint32(ERR_TAXIOK); - GetSession()->SendPacket(&data); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_ACTIVATETAXIREPLY"); + GetSession()->SendActivateTaxiReply(ERR_TAXIOK); GetSession()->SendDoFlight(mount_display_id, sourcepath); } return true; @@ -22434,7 +22412,7 @@ bool Player::HasQuestForGO(int32 GOId) const QuestStatusData const& qs = qs_itr->second; - if (qs.m_status == QUEST_STATUS_INCOMPLETE) + if (qs.Status == QUEST_STATUS_INCOMPLETE) { Quest const* qinfo = sObjectMgr->GetQuestTemplate(questid); if (!qinfo) @@ -22448,7 +22426,7 @@ bool Player::HasQuestForGO(int32 GOId) const if (qinfo->RequiredNpcOrGo[j] >= 0) //skip non GO case continue; - if ((-1)*GOId == qinfo->RequiredNpcOrGo[j] && qs.m_creatureOrGOcount[j] < qinfo->RequiredNpcOrGoCount[j]) + if ((-1)*GOId == qinfo->RequiredNpcOrGo[j] && qs.CreatureOrGOCount[j] < qinfo->RequiredNpcOrGoCount[j]) return true; } } @@ -22481,12 +22459,22 @@ void Player::UpdateForQuestWorldObjects() continue; SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry()); - for (SpellClickInfoMap::const_iterator _itr = clickPair.first; _itr != clickPair.second; ++_itr) - if (_itr->second.questStart || _itr->second.questEnd) + for (SpellClickInfoContainer::const_iterator _itr = clickPair.first; _itr != clickPair.second; ++_itr) + { + //! This code doesn't look right, but it was logically converted to condition system to do the exact + //! same thing it did before. It definitely needs to be overlooked for intended functionality. + ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(obj->GetEntry(), _itr->second.spellId); + bool buildUpdateBlock = false; + for (ConditionList::const_iterator jtr = conds.begin(); jtr != conds.end() && !buildUpdateBlock; ++jtr) + if ((*jtr)->ConditionType == CONDITION_QUESTREWARDED || (*jtr)->ConditionType == CONDITION_QUESTTAKEN) + buildUpdateBlock = true; + + if (buildUpdateBlock) { obj->BuildCreateUpdateBlockForPlayer(&udata, this); break; } + } } } udata.BuildPacket(&packet); @@ -24281,11 +24269,18 @@ bool Player::canSeeSpellClickOn(Creature const* c) const if (clickPair.first == clickPair.second) return true; - for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) - if (itr->second.IsFitToRequirements(this, c)) - return true; + for (SpellClickInfoContainer::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) + { + if (!itr->second.IsFitToRequirements(this, c)) + return false; - return false; + ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(c->GetEntry(), itr->second.spellId); + ConditionSourceInfo info = ConditionSourceInfo(const_cast<Player*>(this), const_cast<Creature*>(c)); + if (!sConditionMgr->IsObjectMeetToConditions(info, conds)) + return false; + } + + return true; } void Player::BuildPlayerTalentsInfoData(WorldPacket* data) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index ae2e0df2a63..c79cec42315 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -482,23 +482,6 @@ enum PlayerFieldByte2Flags PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW = 0x40 }; -enum ActivateTaxiReplies -{ - ERR_TAXIOK = 0, - ERR_TAXIUNSPECIFIEDSERVERERROR = 1, - ERR_TAXINOSUCHPATH = 2, - ERR_TAXINOTENOUGHMONEY = 3, - ERR_TAXITOOFARAWAY = 4, - ERR_TAXINOVENDORNEARBY = 5, - ERR_TAXINOTVISITED = 6, - ERR_TAXIPLAYERBUSY = 7, - ERR_TAXIPLAYERALREADYMOUNTED = 8, - ERR_TAXIPLAYERSHAPESHIFTED = 9, - ERR_TAXIPLAYERMOVING = 10, - ERR_TAXISAMENODE = 11, - ERR_TAXINOTSTANDING = 12 -}; - enum MirrorTimerType { FATIGUE_TIMER = 0, @@ -1074,19 +1057,16 @@ private: Player* _killer; Unit* _victim; - bool _isBattleGround; - - bool _isPvP; - Group* _group; float _groupRate; - uint8 _maxLevel; Player* _maxNotGrayMember; uint32 _count; uint32 _sumLevel; - bool _isFullXP; - uint32 _xp; + bool _isFullXP; + uint8 _maxLevel; + bool _isBattleGround; + bool _isPvP; }; struct PlayerTalentInfo @@ -1444,7 +1424,7 @@ class Player : public Unit, public GridObject<Player> void SendPreparedGossip(WorldObject* source); void OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 menuId); - uint32 GetGossipTextId(uint32 menuId); + uint32 GetGossipTextId(uint32 menuId, WorldObject* source); uint32 GetGossipTextId(WorldObject* source); static uint32 GetDefaultGossipMenuForSource(WorldObject* source); @@ -2401,8 +2381,6 @@ class Player : public Unit, public GridObject<Player> void SetHomebind(WorldLocation const& loc, uint32 area_id); - uint32 m_ConditionErrorMsgId; - // Homebind coordinates uint32 m_homebindMapId; uint16 m_homebindAreaId; diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index a2e59f855ba..f18b041ba88 100755 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -222,7 +222,7 @@ bool Transport::Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, floa SetUInt32Value(GAMEOBJECT_LEVEL, m_period); SetEntry(goinfo->entry); - SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); + SetDisplayId(goinfo->displayId); SetGoState(GO_STATE_READY); SetGoType(GameobjectTypes(goinfo->type)); @@ -496,7 +496,7 @@ void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) ResetMap(); Map* newMap = sMapMgr->CreateBaseMap(newMapid); SetMap(newMap); - ASSERT (GetMap()); + ASSERT(GetMap()); AddToWorld(); if (oldMap != newMap) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 1fda85c6c9c..01c1175f074 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -55,6 +55,7 @@ #include "SpellInfo.h" #include "MoveSplineInit.h" #include "MoveSpline.h" +#include "ConditionMgr.h" #include <math.h> @@ -146,9 +147,10 @@ _hitMask(hitMask), _spell(spell), _damageInfo(damageInfo), _healInfo(healInfo) #endif Unit::Unit(bool isWorldObject): WorldObject(isWorldObject), m_movedPlayer(NULL), m_lastSanctuaryTime(0), IsAIEnabled(false), NeedChangeAI(false), -m_ControlledByPlayer(false), i_AI(NULL), i_disabledAI(NULL), m_procDeep(0), -m_removedAurasCount(0), i_motionMaster(this), m_ThreatManager(this), m_vehicle(NULL), -m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this), movespline(new Movement::MoveSpline()) +m_ControlledByPlayer(false), movespline(new Movement::MoveSpline()), i_AI(NULL), +i_disabledAI(NULL), m_procDeep(0), m_removedAurasCount(0), i_motionMaster(this), +m_ThreatManager(this), m_vehicle(NULL), m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), +m_HostileRefManager(this) { #ifdef _MSC_VER #pragma warning(default:4355) @@ -279,7 +281,6 @@ Unit::~Unit() _DeleteRemovedAuras(); delete m_charmInfo; - delete m_vehicleKit; delete movespline; ASSERT(!m_duringRemoveFromWorld); @@ -516,6 +517,29 @@ bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint return false; } +bool Unit::HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura) const +{ + AuraEffectList const& auras = GetAuraEffectsByType(type); + for (AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + if ((!excludeAura || excludeAura != (*itr)->GetSpellInfo()->Id) && //Avoid self interrupt of channeled Crowd Control spells like Seduction + ((*itr)->GetSpellInfo()->Attributes & SPELL_ATTR0_BREAKABLE_BY_DAMAGE || (*itr)->GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_TAKE_DAMAGE)) + return true; + return false; +} + +bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) const +{ + uint32 excludeAura = 0; + if (Spell* currentChanneledSpell = excludeCasterChannel ? excludeCasterChannel->GetCurrentSpell(CURRENT_CHANNELED_SPELL) : NULL) + excludeAura = currentChanneledSpell->GetSpellInfo()->Id; //Avoid self interrupt of channeled Crowd Control spells like Seduction + + return ( HasBreakableByDamageAuraType(SPELL_AURA_MOD_CONFUSE, excludeAura) + || HasBreakableByDamageAuraType(SPELL_AURA_MOD_FEAR, excludeAura) + || HasBreakableByDamageAuraType(SPELL_AURA_MOD_STUN, excludeAura) + || HasBreakableByDamageAuraType(SPELL_AURA_MOD_ROOT, excludeAura) + || HasBreakableByDamageAuraType(SPELL_AURA_TRANSFORM, excludeAura)); +} + void Unit::DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb) { if (!victim || !victim->isAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())) @@ -775,7 +799,10 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam ASSERT(he->duel); - he->SetHealth(1); + if (duel_wasMounted) // In this case victim==mount + victim->SetHealth(1); + else + he->SetHealth(1); he->duel->opponent->CombatStopWithPets(true); he->CombatStopWithPets(true); @@ -1265,9 +1292,9 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) // Hmmmm dont like this emotes client must by self do all animations if (damageInfo->HitInfo & HITINFO_CRITICALHIT) - victim->HandleEmoteCommand(EMOTE_ONESHOT_WOUNDCRITICAL); + victim->HandleEmoteCommand(EMOTE_ONESHOT_WOUND_CRITICAL); if (damageInfo->blocked_amount && damageInfo->TargetState != VICTIMSTATE_BLOCKS) - victim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYSHIELD); + victim->HandleEmoteCommand(EMOTE_ONESHOT_PARRY_SHIELD); if (damageInfo->TargetState == VICTIMSTATE_PARRY) { @@ -1866,7 +1893,7 @@ void Unit::AttackerStateUpdate (Unit* victim, WeaponAttackType attType, bool ext else { // attack can be redirected to another target - victim = SelectMagnetTarget(victim); + victim = GetMeleeHitRedirectTarget(victim); CalcDamageInfo damageInfo; CalculateMeleeDamage(victim, 0, &damageInfo, attType); @@ -2418,7 +2445,7 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) // 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->IsAOE()) + if (spell->IsTargetingArea()) modHitChance -= victim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE); // Decrease hit chance from victim rating bonus @@ -3340,19 +3367,19 @@ void Unit::_RemoveNoStackAurasDueToAura(Aura* aura) return; bool remove = false; - for (AuraMap::iterator i = m_ownedAuras.begin(); i != m_ownedAuras.end(); ++i) + for (AuraApplicationMap::iterator i = m_appliedAuras.begin(); i != m_appliedAuras.end(); ++i) { if (remove) { remove = false; - i = m_ownedAuras.begin(); + i = m_appliedAuras.begin(); } - if (aura->CanStackWith(i->second)) + if (aura->CanStackWith(i->second->GetBase())) continue; - RemoveOwnedAura(i, AURA_REMOVE_BY_DEFAULT); - if (i == m_ownedAuras.end()) + RemoveAura(i, AURA_REMOVE_BY_DEFAULT); + if (i == m_appliedAuras.end()) break; remove = true; } @@ -3526,17 +3553,25 @@ void Unit::RemoveAuraFromStack(uint32 spellId, uint64 casterGUID, AuraRemoveMode } } -void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit* dispeller, uint8 chargesRemoved/*= 1*/) +void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId, uint64 casterGUID, Unit* dispeller, uint8 chargesRemoved/*= 1*/) { for (AuraMap::iterator iter = m_ownedAuras.lower_bound(spellId); iter != m_ownedAuras.upper_bound(spellId);) { Aura* aura = iter->second; if (aura->GetCasterGUID() == casterGUID) { + DispelInfo dispelInfo(dispeller, dispellerSpellId, chargesRemoved); + + // Call OnDispel hook on AuraScript + aura->CallScriptDispel(&dispelInfo); + if (aura->GetSpellInfo()->AttributesEx7 & SPELL_ATTR7_DISPEL_CHARGES) - aura->ModCharges(-chargesRemoved, AURA_REMOVE_BY_ENEMY_SPELL); + aura->ModCharges(-dispelInfo.GetRemovedCharges(), AURA_REMOVE_BY_ENEMY_SPELL); else - aura->ModStackAmount(-chargesRemoved, AURA_REMOVE_BY_ENEMY_SPELL); + aura->ModStackAmount(-dispelInfo.GetRemovedCharges(), AURA_REMOVE_BY_ENEMY_SPELL); + + // Call AfterDispel hook on AuraScript + aura->CallScriptAfterDispel(&dispelInfo); switch (aura->GetSpellInfo()->SpellFamilyName) { @@ -3566,7 +3601,7 @@ void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit { // final heal int32 healAmount = aurEff->GetAmount(); - int32 stack = chargesRemoved; + int32 stack = dispelInfo.GetRemovedCharges(); CastCustomSpell(this, 33778, &healAmount, &stack, NULL, true, NULL, NULL, aura->GetCasterGUID()); // mana @@ -4868,8 +4903,8 @@ bool Unit::HandleHasteAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere case 13877: case 33735: { - target = SelectNearbyTarget(); - if (!target || target == victim) + target = SelectNearbyTarget(victim); + if (!target) return false; basepoints0 = damage; triggered_spell_id = 22482; @@ -5016,7 +5051,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere case 18765: case 35429: { - target = SelectNearbyTarget(); + target = SelectNearbyTarget(victim); if (!target) return false; @@ -5736,7 +5771,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // Sweeping Strikes case 12328: { - target = SelectNearbyTarget(); + target = SelectNearbyTarget(victim); if (!target) return false; @@ -5812,12 +5847,12 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (!victim || !victim->isAlive() || !procSpell) return false; - target = SelectNearbyTarget(); - if (!target || target == victim) + target = SelectNearbyTarget(victim); + if (!target) return false; - CastSpell(target, 58567, true); - return true; + triggered_spell_id = 58567; + break; } break; } @@ -6985,8 +7020,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere WeaponAttackType attType = WeaponAttackType(player->GetAttackBySlot(castItem->GetSlot())); if ((attType != BASE_ATTACK && attType != OFF_ATTACK) - || attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK - || attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK) + || (attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK) + || (attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK)) return false; // Now compute real proc chance... @@ -7282,8 +7317,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere Player* player = ToPlayer(); WeaponAttackType attType = WeaponAttackType(player->GetAttackBySlot(castItem->GetSlot())); if ((attType != BASE_ATTACK && attType != OFF_ATTACK) - || attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK - || attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK) + || (attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK) + || (attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK)) return false; float fire_onhit = float(CalculatePctF(dummySpell->Effects[EFFECT_0]. CalcValue(), 1.0f)); @@ -9738,6 +9773,7 @@ void Unit::SetMinion(Minion *minion, bool apply) { // Send infinity cooldown - client does that automatically but after relog cooldown needs to be set again SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->GetUInt32Value(UNIT_CREATED_BY_SPELL)); + if (spellInfo && (spellInfo->Attributes & SPELL_ATTR0_DISABLED_WHILE_ACTIVE)) ToPlayer()->AddSpellAndCategoryCooldowns(spellInfo, 0, NULL, true); } @@ -9957,44 +9993,44 @@ int32 Unit::DealHeal(Unit* victim, uint32 addhealth) return gain; } -Unit* Unit::SelectMagnetTarget(Unit* victim, SpellInfo const* spellInfo) +Unit* Unit::GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo) { - if (!victim) - return NULL; + // Patch 1.2 notes: Spell Reflection no longer reflects abilities + if (spellInfo->Attributes & SPELL_ATTR0_ABILITY || spellInfo->AttributesEx & SPELL_ATTR1_CANT_BE_REDIRECTED || spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY) + return victim; - // Magic case - if (spellInfo && (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE || spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC)) + Unit::AuraEffectList const& magnetAuras = victim->GetAuraEffectsByType(SPELL_AURA_SPELL_MAGNET); + for (Unit::AuraEffectList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr) { - // Patch 1.2 notes: Spell Reflection no longer reflects abilities - if (spellInfo->Attributes & SPELL_ATTR0_ABILITY || spellInfo->AttributesEx & SPELL_ATTR1_CANT_BE_REDIRECTED || spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY) - return victim; - // I am not sure if this should be redirected. - if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE) - return victim; + if (Unit* magnet = (*itr)->GetBase()->GetUnitOwner()) + if (spellInfo->CheckExplicitTarget(this, magnet) == SPELL_CAST_OK + && spellInfo->CheckTarget(this, magnet, false) == SPELL_CAST_OK + && _IsValidAttackTarget(magnet, spellInfo) + && IsWithinLOSInMap(magnet)) + { + // TODO: handle this charge drop by proc in cast phase on explicit target + (*itr)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE); + return magnet; + } + } + return victim; +} - Unit::AuraEffectList const& magnetAuras = victim->GetAuraEffectsByType(SPELL_AURA_SPELL_MAGNET); - for (Unit::AuraEffectList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr) - if (Unit* magnet = (*itr)->GetBase()->GetUnitOwner()) - if (magnet->isAlive() && IsWithinLOSInMap(magnet)) +Unit* Unit::GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo) +{ + AuraEffectList const& hitTriggerAuras = victim->GetAuraEffectsByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER); + for (AuraEffectList::const_iterator i = hitTriggerAuras.begin(); i != hitTriggerAuras.end(); ++i) + { + if (Unit* magnet = (*i)->GetBase()->GetCaster()) + if (_IsValidAttackTarget(magnet, spellInfo) && magnet->IsWithinLOSInMap(this) + && (!spellInfo || (spellInfo->CheckExplicitTarget(this, magnet) == SPELL_CAST_OK + && spellInfo->CheckTarget(this, magnet, false) == SPELL_CAST_OK))) + if (roll_chance_i((*i)->GetAmount())) { - (*itr)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE); + (*i)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE); return magnet; } } - // Melee && ranged case - else - { - AuraEffectList const& hitTriggerAuras = victim->GetAuraEffectsByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER); - for (AuraEffectList::const_iterator i = hitTriggerAuras.begin(); i != hitTriggerAuras.end(); ++i) - if (Unit* magnet = (*i)->GetBase()->GetCaster()) - if (magnet->isAlive() && magnet->IsWithinLOSInMap(this)) - if (roll_chance_i((*i)->GetAmount())) - { - (*i)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE); - return magnet; - } - } - return victim; } @@ -12067,7 +12103,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy) if (IsAIEnabled) { creature->AI()->EnterCombat(enemy); - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); // always remove Out of Combat Non Attackable flag if we enter combat and AI is enabled + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); // unit has engaged in combat, remove immunity so players can fight back } if (creature->GetFormation()) creature->GetFormation()->MemberAttackStart(creature, enemy); @@ -12099,8 +12135,8 @@ void Unit::ClearInCombat() // Player's state will be cleared in Player::UpdateContestedPvP if (Creature* creature = ToCreature()) { - if (creature->GetCreatureInfo() && creature->GetCreatureInfo()->unit_flags & UNIT_FLAG_OOC_NOT_ATTACKABLE) - SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); // re-apply Out of Combat Non Attackable flag if we leave combat, can be overriden in scripts in EnterEvadeMode() + if (creature->GetCreatureInfo() && creature->GetCreatureInfo()->unit_flags & UNIT_FLAG_IMMUNE_TO_PC) + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); // set immunity state to the one from db on evade ClearUnitState(UNIT_STATE_ATTACK_PLAYER); if (HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TAPPED)) @@ -12128,7 +12164,7 @@ bool Unit::isTargetableForAttack(bool checkFakeDeath) const return false; if (HasFlag(UNIT_FIELD_FLAGS, - UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE)) + UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC)) return false; if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->isGameMaster()) @@ -12162,7 +12198,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) co return false; // can't attack invisible (ignore stealth for aoe spells) - if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target, bySpell && bySpell->IsAOE())) + if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target, bySpell && bySpell->IsAffectingArea())) return false; // can't attack dead @@ -12181,10 +12217,11 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) co } // check flags if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_TAXI_FLIGHT | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_UNK_16) - || (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)) - || (!target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)) - || (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) - || (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE))) + || (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)) + || (!target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)) + || (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)) + // check if this is a world trigger cast - GOs are using world triggers to cast their spells, so we need to ignore their immunity flag here, this is a temp workaround, needs removal when go cast is implemented properly + || (GetEntry() != WORLD_TRIGGER && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC))) return false; // CvC case - can attack each other only when one of them is hostile @@ -12197,6 +12234,26 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) co || target->GetReactionTo(this) > REP_NEUTRAL) return false; + // Not all neutral creatures can be attacked + if (GetReactionTo(target) == REP_NEUTRAL && + target->GetReactionTo(this) == REP_NEUTRAL) + { + if ( + !(target->GetTypeId() == TYPEID_PLAYER && GetTypeId() == TYPEID_PLAYER) && + !(target->GetTypeId() == TYPEID_UNIT && GetTypeId() == TYPEID_UNIT) + ) + { + Player const* player = target->GetTypeId() == TYPEID_PLAYER ? target->ToPlayer() : ToPlayer(); + Unit const* creature = target->GetTypeId() == TYPEID_UNIT ? target : this; + + if (FactionTemplateEntry const* factionTemplate = creature->getFactionTemplateEntry()) + if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->faction)) + if (FactionState const* repState = player->GetReputationMgr().GetState(factionEntry)) + if (!(repState->Flags & FACTION_FLAG_AT_WAR)) + return false; + } + } + Creature const* creatureAttacker = ToCreature(); if (creatureAttacker && creatureAttacker->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_UNK26) return false; @@ -12256,7 +12313,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co return false; // can't assist invisible - if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target, bySpell && bySpell->IsAOE())) + if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target, bySpell && bySpell->IsAffectingArea())) return false; // can't assist dead @@ -12272,12 +12329,12 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co { if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) { - if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) + if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)) return false; } else { - if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)) + if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)) return false; } } @@ -13035,7 +13092,6 @@ void Unit::setDeathState(DeathState s) { // death state needs to be updated before RemoveAllAurasOnDeath() calls HandleChannelDeathItem(..) so that // it can be used to check creation of death items (such as soul shards). - DeathState oldDeathState = m_deathState; m_deathState = s; if (s != ALIVE && s != JUST_ALIVED) @@ -13074,14 +13130,6 @@ void Unit::setDeathState(DeathState s) } else if (s == JUST_ALIVED) RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); // clear skinnable for creature and player (at battleground) - - if (oldDeathState != ALIVE && s == ALIVE) - { - // Reset display id on resurection - needed by corpse explosion to cleanup after display change - // TODO: fix this - if (!HasAuraType(SPELL_AURA_TRANSFORM)) - SetDisplayId(GetNativeDisplayId()); - } } /*######################################## @@ -14096,7 +14144,7 @@ void Unit::RemoveFromWorld() { m_duringRemoveFromWorld = true; if (IsVehicle()) - GetVehicleKit()->Uninstall(); + RemoveVehicleKit(); RemoveCharmAuras(); RemoveBindSightAuras(); @@ -14105,7 +14153,7 @@ void Unit::RemoveFromWorld() RemoveAllGameObjects(); RemoveAllDynObjects(); - ExitVehicle(); + ExitVehicle(); // Remove applied auras with SPELL_AURA_CONTROL_VEHICLE UnsummonAllTotems(); RemoveAllControlled(); @@ -15070,7 +15118,7 @@ void Unit::SendMovementFlagUpdate() { WorldPacket data; BuildHeartBeatMsg(&data); - SendMessageToSet(&data, true); + SendMessageToSet(&data, false); } bool Unit::IsSitState() const @@ -15230,7 +15278,7 @@ void Unit::UpdateReactives(uint32 p_time) } } -Unit* Unit::SelectNearbyTarget(float dist) const +Unit* Unit::SelectNearbyTarget(Unit* exclude, float dist) const { std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, this, dist); @@ -15241,6 +15289,9 @@ Unit* Unit::SelectNearbyTarget(float dist) const if (getVictim()) targets.remove(getVictim()); + if (exclude) + targets.remove(exclude); + // remove not LoS targets for (std::list<Unit*>::iterator tIter = targets.begin(); tIter != targets.end();) { @@ -15329,7 +15380,7 @@ uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectTyp break; } - if (spellProto->Effects[i].IsArea()) + if (spellProto->Effects[i].IsTargetingArea()) AreaEffect = true; } @@ -15739,14 +15790,6 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) if (!victim->GetHealth()) return; - // Inform pets (if any) when player kills target) - if (Player* player = ToPlayer()) - { - Pet* pet = player->GetPet(); - if (pet && pet->isAlive() && pet->isControlled()) - pet->AI()->KilledUnit(victim); - } - // find player: owner of controlled `this` or `this` itself maybe Player* player = GetCharmerOrOwnerPlayerOrPlayerItself(); Creature* creature = victim->ToCreature(); @@ -15875,6 +15918,16 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) victim->setDeathState(JUST_DIED); } + // Inform pets (if any) when player kills target) + // MUST come after victim->setDeathState(JUST_DIED); or pet next target + // selection will get stuck on same target and break pet react state + if (Player* player = ToPlayer()) + { + Pet* pet = player->GetPet(); + if (pet && pet->isAlive() && pet->isControlled()) + pet->AI()->KilledUnit(victim); + } + // 10% durability loss on death // clean InHateListOf if (Player* plrVictim = victim->ToPlayer()) @@ -15999,9 +16052,6 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) if (Player* killed = victim->ToPlayer()) sScriptMgr->OnPlayerKilledByCreature(killerCre, killed); } - - if (victim->GetVehicle()) - victim->ExitVehicle(); } void Unit::SetControlled(bool apply, UnitState state) @@ -16587,26 +16637,6 @@ bool Unit::IsInRaidWith(Unit const* unit) const return false; } -bool Unit::IsTargetMatchingCheck(Unit const* target, SpellTargetSelectionCheckTypes check) const -{ - switch (check) - { - case TARGET_SELECT_CHECK_ENEMY: - if (IsControlledByPlayer()) - return !IsFriendlyTo(target); - else - return IsHostileTo(target); - case TARGET_SELECT_CHECK_ALLY: - return IsFriendlyTo(target); - case TARGET_SELECT_CHECK_PARTY: - return IsInPartyWith(target); - case TARGET_SELECT_CHECK_RAID: - return IsInRaidWith(target); - default: - return true; - } -} - void Unit::GetRaidMember(std::list<Unit*> &nearMembers, float radius) { Player* owner = GetCharmerOrOwnerPlayerOrPlayerItself(); @@ -17321,57 +17351,61 @@ void Unit::JumpTo(WorldObject* obj, float speedZ) bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) { - bool success = false; uint32 spellClickEntry = GetVehicleKit() ? GetVehicleKit()->GetCreatureEntry() : GetEntry(); SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(spellClickEntry); - for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) + for (SpellClickInfoContainer::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) { - if (itr->second.IsFitToRequirements(clicker, this)) - { - Unit* caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_CLICKER) ? clicker : this; - Unit* target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_CLICKER) ? clicker : this; - uint64 origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? GetOwnerGUID() : clicker->GetGUID(); + //! First check simple relations from clicker to clickee + if (!itr->second.IsFitToRequirements(clicker, this)) + return false; - SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->second.spellId); - // if (!spellEntry) should be checked at npc_spellclick load + //! Check database conditions + ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(spellClickEntry, itr->second.spellId); + ConditionSourceInfo info = ConditionSourceInfo(clicker, this); + if (!sConditionMgr->IsObjectMeetToConditions(info, conds)) + return false; - if (seatId > -1) - { - uint8 i = 0; - bool valid = false; - while (i < MAX_SPELL_EFFECTS && !valid) - { - if (spellEntry->Effects[i].ApplyAuraName == SPELL_AURA_CONTROL_VEHICLE) - { - valid = true; - break; - } - ++i; - } + Unit* caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_CLICKER) ? clicker : this; + Unit* target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_CLICKER) ? clicker : this; + uint64 origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? GetOwnerGUID() : clicker->GetGUID(); - if (!valid) - { - sLog->outErrorDb("Spell %u specified in npc_spellclick_spells is not a valid vehicle enter aura!", itr->second.spellId); - return false; - } + SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->second.spellId); + // if (!spellEntry) should be checked at npc_spellclick load - if (IsInMap(caster)) - caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, true, NULL, NULL, origCasterGUID); - else // This can happen during Player::_LoadAuras + if (seatId > -1) + { + uint8 i = 0; + bool valid = false; + while (i < MAX_SPELL_EFFECTS && !valid) + { + if (spellEntry->Effects[i].ApplyAuraName == SPELL_AURA_CONTROL_VEHICLE) { - int32 bp0 = seatId; - Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, &bp0, NULL, origCasterGUID); + valid = true; + break; } + ++i; } - else + + if (!valid) { - if (IsInMap(caster)) - caster->CastSpell(target, spellEntry, true, NULL, NULL, origCasterGUID); - else - Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, NULL, NULL, origCasterGUID); + sLog->outErrorDb("Spell %u specified in npc_spellclick_spells is not a valid vehicle enter aura!", itr->second.spellId); + return false; } - success = true; + if (IsInMap(caster)) + caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, true, NULL, NULL, origCasterGUID); + else // This can happen during Player::_LoadAuras + { + int32 bp0 = seatId; + Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, &bp0, NULL, origCasterGUID); + } + } + else + { + if (IsInMap(caster)) + caster->CastSpell(target, spellEntry, true, NULL, NULL, origCasterGUID); + else + Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, NULL, NULL, origCasterGUID); } } @@ -17379,7 +17413,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) if (creature && creature->IsAIEnabled) creature->AI()->DoAction(EVENT_SPELLCLICK); - return success; + return true; } void Unit::EnterVehicle(Unit* base, int8 seatId) @@ -17465,12 +17499,21 @@ void Unit::ChangeSeat(int8 seatId, bool next) void Unit::ExitVehicle(Position const* exitPosition) { - // This function can be called at upper level code to initialize an exit from the passenger's side. + //! This function can be called at upper level code to initialize an exit from the passenger's side. if (!m_vehicle) return; GetVehicleBase()->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, GetGUID()); - _ExitVehicle(exitPosition); + //! The following call would not even be executed successfully as the + //! SPELL_AURA_CONTROL_VEHICLE unapply handler already calls _ExitVehicle without + //! specifying an exitposition. The subsequent call below would return on if (!m_vehicle). + /*_ExitVehicle(exitPosition);*/ + //! To do: + //! We need to allow SPELL_AURA_CONTROL_VEHICLE unapply handlers in spellscripts + //! to specify exit coordinates and either store those per passenger, or we need to + //! init spline movement based on those coordinates in unapply handlers, and + //! relocate exiting passengers based on Unit::moveSpline data. Either way, + //! Coming Soon™ } void Unit::_ExitVehicle(Position const* exitPosition) @@ -17513,9 +17556,7 @@ void Unit::_ExitVehicle(Position const* exitPosition) if (Player* player = ToPlayer()) player->ResummonPetTemporaryUnSummonedIfAny(); - WorldPacket data2; - BuildHeartBeatMsg(&data2); - SendMessageToSet(&data2, true); + SendMovementFlagUpdate(); if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION)) if (((Minion*)vehicle->GetBase())->GetOwner() == this) @@ -17894,7 +17935,11 @@ bool CharmInfo::IsCommandAttack() void CharmInfo::SaveStayPosition() { - m_unit->GetPosition(m_stayX, m_stayY, m_stayZ); + //! At this point a new spline destination is enabled because of Unit::StopMoving() + G3D::Vector3 const stayPos = m_unit->movespline->FinalDestination(); + m_stayX = stayPos.x; + m_stayY = stayPos.y; + m_stayZ = stayPos.z; } void CharmInfo::GetStayPosition(float &x, float &y, float &z) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index e65574bbfbc..e82c755ae41 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -589,8 +589,8 @@ enum UnitFlags UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR5_NO_REAGENT_WHILE_PREP UNIT_FLAG_UNK_6 = 0x00000040, UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE - UNIT_FLAG_OOC_NOT_ATTACKABLE = 0x00000100, // 2.0.8 - (OOC Out Of Combat) Can not be attacked when not in combat. Removed if unit for some reason enter combat. - UNIT_FLAG_PASSIVE = 0x00000200, // makes you unable to attack everything. Almost identical to our "civilian"-term. Will ignore it's surroundings and not engage in combat unless "called upon" or engaged by another unit. + UNIT_FLAG_IMMUNE_TO_PC = 0x00000100, // disables combat/assistance with PlayerCharacters (PC) - see Unit::_IsValidAttackTarget, Unit::_IsValidAssistTarget + UNIT_FLAG_IMMUNE_TO_NPC = 0x00000200, // disables combat/assistance with NonPlayerCharacters (NPC) - see Unit::_IsValidAttackTarget, Unit::_IsValidAssistTarget UNIT_FLAG_LOOTING = 0x00000400, // loot animation UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3 @@ -788,6 +788,25 @@ enum MeleeHitOutcome MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL }; +class DispelInfo +{ +private: + Unit* const m_dispeller; + uint32 const m_dispellerSpellId; + uint8 m_chargesRemoved; +public: + explicit DispelInfo(Unit* _dispeller, uint32 _dispellerSpellId, uint8 _chargesRemoved) : + m_dispeller(_dispeller), m_dispellerSpellId(_dispellerSpellId), m_chargesRemoved(_chargesRemoved) {} + + Unit* GetDispeller() { return m_dispeller; } + uint32 GetDispellerSpellId() { return m_dispellerSpellId; } + uint8 GetRemovedCharges() { return m_chargesRemoved; } + void SetRemovedCharges(uint8 amount) + { + m_chargesRemoved = amount; + } +}; + struct CleanDamage { CleanDamage(uint32 mitigated, uint32 absorbed, WeaponAttackType _attackType, MeleeHitOutcome _hitOutCome) : @@ -1280,7 +1299,7 @@ class Unit : public WorldObject void CombatStop(bool includingCast = false); void CombatStopWithPets(bool includingCast = false); void StopAttackFaction(uint32 faction_id); - Unit* SelectNearbyTarget(float dist = NOMINAL_MELEE_RANGE) const; + Unit* SelectNearbyTarget(Unit* exclude = NULL, float dist = NOMINAL_MELEE_RANGE) const; void SendMeleeAttackStop(Unit* victim = NULL); void SendMeleeAttackStart(Unit* pVictim); @@ -1377,7 +1396,6 @@ class Unit : public WorldObject bool IsNeutralToAll() const; bool IsInPartyWith(Unit const* unit) const; bool IsInRaidWith(Unit const* unit) const; - bool IsTargetMatchingCheck(Unit const* target, SpellTargetSelectionCheckTypes check) const; void GetPartyMemberInDist(std::list<Unit*> &units, float dist); void GetPartyMembers(std::list<Unit*> &units); void GetRaidMember(std::list<Unit*> &units, float dist); @@ -1539,6 +1557,8 @@ class Unit : public WorldObject bool HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint32 familyFlags) const; bool virtual HasSpell(uint32 /*spellID*/) const { return false; } + bool HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura = 0) const; + bool HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel = NULL) const; bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); } bool HasInvisibilityAura() const { return HasAuraType(SPELL_AURA_MOD_INVISIBILITY); } @@ -1747,7 +1767,7 @@ class Unit : public WorldObject void RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID = 0, uint8 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); void RemoveAuraFromStack(uint32 spellId, uint64 casterGUID = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); - void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit* dispeller, uint8 chargesRemoved = 1); + void RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId, uint64 casterGUID, Unit* dispeller, uint8 chargesRemoved = 1); void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit* stealer); void RemoveAurasDueToItemSpell(Item* castItem, uint32 spellId); void RemoveAurasByType(AuraType auraType, uint64 casterGUID = 0, Aura* except = NULL, bool negative = true, bool positive = true); @@ -1990,7 +2010,8 @@ class Unit : public WorldObject uint32 BuildAuraStateUpdateForTarget(Unit* target) const; bool HasAuraState(AuraStateType flag, SpellInfo const* spellProto = NULL, Unit const* Caster = NULL) const ; void UnsummonAllTotems(); - Unit* SelectMagnetTarget(Unit* victim, SpellInfo const* spellInfo = NULL); + Unit* GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo); + Unit* GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo = NULL); int32 SpellBaseDamageBonus(SpellSchoolMask schoolMask); int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask); int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit* pVictim); diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 0ff5d402242..e0d67e9ceef 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -363,9 +363,9 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) if (_me->IsInWorld()) { - unit->SendClearTarget(); // SMSG_BREAK_TARGET - unit->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_MOVE_SPLINE_ROOT here (for creatures) - // also adds MOVEMENTFLAG_ROOT + 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 unit->SendMonsterMoveTransport(_me); // SMSG_MONSTER_MOVE_TRANSPORT if (_me->GetTypeId() == TYPEID_UNIT) @@ -433,8 +433,7 @@ void Vehicle::RemovePassenger(Unit* unit) void Vehicle::RelocatePassengers(float x, float y, float z, float ang) { - Map* map = _me->GetMap(); - ASSERT(map != NULL); + ASSERT(_me->GetMap()); // not sure that absolute position calculation is correct, it must depend on vehicle orientation and pitch angle for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr) diff --git a/src/server/game/Entities/Vehicle/VehicleDefines.h b/src/server/game/Entities/Vehicle/VehicleDefines.h index 4ddfc0b2e81..fe7840c9878 100644 --- a/src/server/game/Entities/Vehicle/VehicleDefines.h +++ b/src/server/game/Entities/Vehicle/VehicleDefines.h @@ -85,16 +85,16 @@ struct VehicleSeat struct VehicleAccessory { VehicleAccessory(uint32 entry, int8 seatId, bool isMinion, uint8 summonType, uint32 summonTime) : - AccessoryEntry(entry), SeatId(seatId), IsMinion(isMinion), SummonedType(summonType), SummonTime(summonTime) {} + AccessoryEntry(entry), IsMinion(isMinion), SummonTime(summonTime), SeatId(seatId), SummonedType(summonType) {} uint32 AccessoryEntry; - int8 SeatId; uint32 IsMinion; - uint8 SummonedType; uint32 SummonTime; + int8 SeatId; + uint8 SummonedType; }; typedef std::vector<VehicleAccessory> VehicleAccessoryList; -typedef std::map<uint32, VehicleAccessoryList> VehicleAccessoryMap; +typedef std::map<uint32, VehicleAccessoryList> VehicleAccessoryContainer; typedef std::map<int8, VehicleSeat> SeatMap; #endif diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 7ed4af97a8b..d055707f68c 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -198,30 +198,8 @@ LanguageDesc const* GetLanguageDescByID(uint32 lang) bool SpellClickInfo::IsFitToRequirements(Unit const* clicker, Unit const* clickee) const { Player const* playerClicker = clicker->ToPlayer(); - if (playerClicker) - { - if (questStart) - { - // not in expected required quest state - if ((!questStartCanActive || !playerClicker->IsActiveQuest(questStart)) && !playerClicker->GetQuestRewardStatus(questStart)) - return false; - } - - if (questEnd) - { - // not in expected forbidden quest state - if (playerClicker->GetQuestRewardStatus(questEnd)) - return false; - } - } - - if (auraRequired) - if (!clicker->HasAura(auraRequired)) - return false; - - if (auraForbidden) - if (clicker->HasAura(auraForbidden)) - return false; + if (!playerClicker) + return true; Unit const* summoner = NULL; // Check summoners for party @@ -230,9 +208,6 @@ bool SpellClickInfo::IsFitToRequirements(Unit const* clicker, Unit const* clicke if (!summoner) summoner = clickee; - if (!playerClicker) - return true; - // This only applies to players switch (userType) { @@ -255,32 +230,32 @@ bool SpellClickInfo::IsFitToRequirements(Unit const* clicker, Unit const* clicke return true; } -ObjectMgr::ObjectMgr(): m_auctionid(1), m_equipmentSetGuid(1), - m_ItemTextId(1), m_mailid(1), m_hiPetNumber(1), m_hiCharGuid(1), - m_hiCreatureGuid(1), m_hiPetGuid(1), m_hiVehicleGuid(1), m_hiItemGuid(1), - m_hiGoGuid(1), m_hiDoGuid(1), m_hiCorpseGuid(1), m_hiMoTransGuid(1) +ObjectMgr::ObjectMgr(): _auctionId(1), _equipmentSetGuid(1), + _itemTextId(1), _mailId(1), _hiPetNumber(1), _hiCharGuid(1), + _hiCreatureGuid(1), _hiPetGuid(1), _hiVehicleGuid(1), _hiItemGuid(1), + _hiGoGuid(1), _hiDoGuid(1), _hiCorpseGuid(1), _hiMoTransGuid(1) {} ObjectMgr::~ObjectMgr() { - for (QuestMap::iterator i = mQuestTemplates.begin(); i != mQuestTemplates.end(); ++i) + for (QuestMap::iterator i = _questTemplates.begin(); i != _questTemplates.end(); ++i) delete i->second; - for (PetLevelInfoMap::iterator i = petInfo.begin(); i != petInfo.end(); ++i) + 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; + 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; + delete[] _playerInfo[race][class_].levelInfo; - for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) + for (CacheVendorItemContainer::iterator itr = _cacheVendorItemStore.begin(); itr != _cacheVendorItemStore.end(); ++itr) itr->second.Clear(); - m_mCacheTrainerSpellMap.clear(); + _cacheTrainerSpellStore.clear(); } void ObjectMgr::AddLocaleString(std::string const& s, LocaleConstant locale, StringVector& data) @@ -298,7 +273,7 @@ void ObjectMgr::LoadCreatureLocales() { uint32 oldMSTime = getMSTime(); - mCreatureLocaleMap.clear(); // need for reload case + _creatureLocaleStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT entry, name_loc1, subname_loc1, name_loc2, subname_loc2, name_loc3, subname_loc3, name_loc4, subname_loc4, name_loc5, subname_loc5, name_loc6, subname_loc6, name_loc7, subname_loc7, name_loc8, subname_loc8 FROM locales_creature"); @@ -311,7 +286,7 @@ void ObjectMgr::LoadCreatureLocales() uint32 entry = fields[0].GetUInt32(); - CreatureLocale& data = mCreatureLocaleMap[entry]; + CreatureLocale& data = _creatureLocaleStore[entry]; for (uint8 i = 1; i < TOTAL_LOCALES; ++i) { @@ -321,7 +296,7 @@ void ObjectMgr::LoadCreatureLocales() } } while (result->NextRow()); - sLog->outString(">> Loaded %lu creature locale strings in %u ms", (unsigned long)mCreatureLocaleMap.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu creature locale strings in %u ms", (unsigned long)_creatureLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -329,7 +304,7 @@ void ObjectMgr::LoadGossipMenuItemsLocales() { uint32 oldMSTime = getMSTime(); - mGossipMenuItemsLocaleMap.clear(); // need for reload case + _gossipMenuItemsLocaleStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT menu_id, id, " "option_text_loc1, box_text_loc1, option_text_loc2, box_text_loc2, " @@ -348,7 +323,7 @@ void ObjectMgr::LoadGossipMenuItemsLocales() uint16 menuId = fields[0].GetUInt16(); uint16 id = fields[1].GetUInt16(); - GossipMenuItemsLocale& data = mGossipMenuItemsLocaleMap[MAKE_PAIR32(menuId, id)]; + GossipMenuItemsLocale& data = _gossipMenuItemsLocaleStore[MAKE_PAIR32(menuId, id)]; for (uint8 i = 1; i < TOTAL_LOCALES; ++i) { @@ -358,7 +333,7 @@ void ObjectMgr::LoadGossipMenuItemsLocales() } } while (result->NextRow()); - sLog->outString(">> Loaded %lu gossip_menu_option locale strings in %u ms", (unsigned long)mGossipMenuItemsLocaleMap.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu gossip_menu_option locale strings in %u ms", (unsigned long)_gossipMenuItemsLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -366,7 +341,7 @@ void ObjectMgr::LoadPointOfInterestLocales() { uint32 oldMSTime = getMSTime(); - mPointOfInterestLocaleMap.clear(); // need for reload case + _pointOfInterestLocaleStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT entry, icon_name_loc1, icon_name_loc2, icon_name_loc3, icon_name_loc4, icon_name_loc5, icon_name_loc6, icon_name_loc7, icon_name_loc8 FROM locales_points_of_interest"); @@ -379,13 +354,13 @@ void ObjectMgr::LoadPointOfInterestLocales() uint32 entry = fields[0].GetUInt32(); - PointOfInterestLocale& data = mPointOfInterestLocaleMap[entry]; + PointOfInterestLocale& data = _pointOfInterestLocaleStore[entry]; for (uint8 i = 1; i < TOTAL_LOCALES; ++i) AddLocaleString(fields[i].GetString(), LocaleConstant(i), data.IconName); } while (result->NextRow()); - sLog->outString(">> Loaded %lu points_of_interest locale strings in %u ms", (unsigned long)mPointOfInterestLocaleMap.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu points_of_interest locale strings in %u ms", (unsigned long)_pointOfInterestLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -426,19 +401,15 @@ void ObjectMgr::LoadCreatureTemplates() uint32 entry = fields[0].GetUInt32(); - CreatureTemplate& creatureTemplate = CreatureTemplateStore[entry]; + CreatureTemplate& creatureTemplate = _creatureTemplateStore[entry]; creatureTemplate.Entry = entry; for (uint8 i = 0; i < MAX_DIFFICULTY - 1; ++i) - { creatureTemplate.DifficultyEntry[i] = fields[1 + i].GetUInt32(); - } for (uint8 i = 0; i < MAX_KILL_CREDIT; ++i) - { creatureTemplate.KillCredit[i] = fields[4 + i].GetUInt32(); - } creatureTemplate.Modelid1 = fields[6].GetUInt32(); creatureTemplate.Modelid2 = fields[7].GetUInt32(); @@ -517,10 +488,8 @@ void ObjectMgr::LoadCreatureTemplates() while (result->NextRow()); // Checking needs to be done after loading because of the difficulty self referencing - for (CreatureTemplateContainer::const_iterator itr = CreatureTemplateStore.begin(); itr != CreatureTemplateStore.end(); ++itr) - { + for (CreatureTemplateContainer::const_iterator itr = _creatureTemplateStore.begin(); itr != _creatureTemplateStore.end(); ++itr) CheckCreatureTemplate(&itr->second); - } sLog->outString(">> Loaded %u creature definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); @@ -553,7 +522,7 @@ void ObjectMgr::LoadCreatureTemplateAddons() continue; } - CreatureAddon& creatureAddon = CreatureTemplateAddonStore[entry]; + CreatureAddon& creatureAddon = _creatureTemplateAddonStore[entry]; creatureAddon.path_id = fields[1].GetUInt32(); creatureAddon.mount = fields[2].GetUInt32(); @@ -619,20 +588,20 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) for (uint32 diff2 = 0; diff2 < MAX_DIFFICULTY - 1 && ok2; ++diff2) { ok2 = false; - if (difficultyEntries[diff2].find(cInfo->Entry) != difficultyEntries[diff2].end()) + if (_difficultyEntries[diff2].find(cInfo->Entry) != _difficultyEntries[diff2].end()) { sLog->outErrorDb("Creature (Entry: %u) is listed as `difficulty_entry_%u` of another creature, but itself lists %u in `difficulty_entry_%u`.", cInfo->Entry, diff2 + 1, cInfo->DifficultyEntry[diff], diff + 1); continue; } - if (difficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != difficultyEntries[diff2].end()) + if (_difficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != _difficultyEntries[diff2].end()) { sLog->outErrorDb("Creature (Entry: %u) already listed as `difficulty_entry_%u` for another entry.", cInfo->DifficultyEntry[diff], diff2 + 1); continue; } - if (hasDifficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != hasDifficultyEntries[diff2].end()) + if (_hasDifficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != _hasDifficultyEntries[diff2].end()) { sLog->outErrorDb("Creature (Entry: %u) has `difficulty_entry_%u`=%u but creature entry %u has itself a value in `difficulty_entry_%u`.", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff], cInfo->DifficultyEntry[diff], diff2 + 1); @@ -694,8 +663,8 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) continue; } - hasDifficultyEntries[diff].insert(cInfo->Entry); - difficultyEntries[diff].insert(cInfo->DifficultyEntry[diff]); + _hasDifficultyEntries[diff].insert(cInfo->Entry); + _difficultyEntries[diff].insert(cInfo->DifficultyEntry[diff]); ok = true; } @@ -921,15 +890,22 @@ void ObjectMgr::LoadCreatureAddons() uint32 guid = fields[0].GetUInt32(); - if (mCreatureDataMap.find(guid) == mCreatureDataMap.end()) + CreatureData const* creData = GetCreatureData(guid); + if (!creData) { sLog->outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_addon`", guid); continue; } - CreatureAddon& creatureAddon = CreatureAddonStore[guid]; + CreatureAddon& creatureAddon = _creatureAddonStore[guid]; creatureAddon.path_id = fields[1].GetUInt32(); + if (creData->movementType == WAYPOINT_MOTION_TYPE && !creatureAddon.path_id) + { + const_cast<CreatureData*>(creData)->movementType = IDLE_MOTION_TYPE; + sLog->outErrorDb("Creature (GUID %u) has movement type set to WAYPOINT_MOTION_TYPE but no path assigned", guid); + } + creatureAddon.mount = fields[2].GetUInt32(); creatureAddon.bytes1 = fields[3].GetUInt32(); creatureAddon.bytes2 = fields[4].GetUInt32(); @@ -971,8 +947,8 @@ void ObjectMgr::LoadCreatureAddons() CreatureAddon const* ObjectMgr::GetCreatureAddon(uint32 lowguid) { - CreatureAddonContainer::const_iterator itr = CreatureAddonStore.find(lowguid); - if (itr != CreatureAddonStore.end()) + CreatureAddonContainer::const_iterator itr = _creatureAddonStore.find(lowguid); + if (itr != _creatureAddonStore.end()) return &(itr->second); return NULL; @@ -980,8 +956,8 @@ CreatureAddon const* ObjectMgr::GetCreatureAddon(uint32 lowguid) CreatureAddon const* ObjectMgr::GetCreatureTemplateAddon(uint32 entry) { - CreatureAddonContainer::const_iterator itr = CreatureTemplateAddonStore.find(entry); - if (itr != CreatureTemplateAddonStore.end()) + CreatureAddonContainer::const_iterator itr = _creatureTemplateAddonStore.find(entry); + if (itr != _creatureTemplateAddonStore.end()) return &(itr->second); return NULL; @@ -989,8 +965,8 @@ CreatureAddon const* ObjectMgr::GetCreatureTemplateAddon(uint32 entry) EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry) { - EquipmentInfoContainer::const_iterator itr = EquipmentInfoStore.find(entry); - if (itr != EquipmentInfoStore.end()) + EquipmentInfoContainer::const_iterator itr = _equipmentInfoStore.find(entry); + if (itr != _equipmentInfoStore.end()) return &(itr->second); return NULL; @@ -1016,7 +992,7 @@ void ObjectMgr::LoadEquipmentTemplates() uint16 entry = fields[0].GetUInt16(); - EquipmentInfo& equipmentInfo = EquipmentInfoStore[entry]; + EquipmentInfo& equipmentInfo = _equipmentInfoStore[entry]; equipmentInfo.ItemEntry[0] = fields[1].GetUInt32(); equipmentInfo.ItemEntry[1] = fields[2].GetUInt32(); @@ -1063,8 +1039,8 @@ void ObjectMgr::LoadEquipmentTemplates() CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelId) { - CreatureModelContainer::const_iterator itr = CreatureModelStore.find(modelId); - if (itr != CreatureModelStore.end()) + CreatureModelContainer::const_iterator itr = _creatureModelStore.find(modelId); + if (itr != _creatureModelStore.end()) return &(itr->second); return NULL; @@ -1148,7 +1124,7 @@ void ObjectMgr::LoadCreatureModelInfo() uint32 modelId = fields[0].GetUInt32(); - CreatureModelInfo& modelInfo = CreatureModelStore[modelId]; + CreatureModelInfo& modelInfo = _creatureModelStore[modelId]; modelInfo.bounding_radius = fields[1].GetFloat(); modelInfo.combat_reach = fields[2].GetFloat(); @@ -1189,7 +1165,7 @@ void ObjectMgr::LoadLinkedRespawn() { uint32 oldMSTime = getMSTime(); - mLinkedRespawnMap.clear(); + _linkedRespawnStore.clear(); QueryResult result = WorldDatabase.Query("SELECT guid, linkedGuid, linkType FROM linked_respawn ORDER BY guid ASC"); if (!result) @@ -1362,12 +1338,12 @@ void ObjectMgr::LoadLinkedRespawn() } if (!error) - mLinkedRespawnMap[guid] = linkedGuid; + _linkedRespawnStore[guid] = linkedGuid; } while (result->NextRow()); - sLog->outString(">> Loaded " UI64FMTD " linked respawns in %u ms", uint64(mLinkedRespawnMap.size()), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded " UI64FMTD " linked respawns in %u ms", uint64(_linkedRespawnStore.size()), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -1381,7 +1357,7 @@ bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guidLow, uint32 linkedGuidLow) if (!linkedGuidLow) // we're removing the linking { - mLinkedRespawnMap.erase(guid); + _linkedRespawnStore.erase(guid); PreparedStatement *stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CRELINKED_RESPAWN); stmt->setUInt32(0, guidLow); WorldDatabase.Execute(stmt); @@ -1405,7 +1381,7 @@ bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guidLow, uint32 linkedGuidLow) uint64 linkedGuid = MAKE_NEW_GUID(linkedGuidLow, slave->id, HIGHGUID_UNIT); - mLinkedRespawnMap[guid] = linkedGuid; + _linkedRespawnStore[guid] = linkedGuid; PreparedStatement *stmt = WorldDatabase.GetPreparedStatement(WORLD_REP_CREATURE_LINKED_RESPAWN); stmt->setUInt32(0, guidLow); stmt->setUInt32(1, linkedGuidLow); @@ -1432,15 +1408,6 @@ void ObjectMgr::LoadCreatures() return; } - // Build single time for check creature data - std::set<uint32> difficultyCreatures[MAX_DIFFICULTY - 1]; - - CreatureTemplateContainer const* ctc = sObjectMgr->GetCreatureTemplates(); - for (CreatureTemplateContainer::const_iterator itr = ctc->begin(); itr != ctc->end(); ++itr) - for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1; ++diff) - if (itr->second.DifficultyEntry[diff]) - difficultyCreatures[diff].insert(itr->second.DifficultyEntry[diff]); - // Build single time for check spawnmask std::map<uint32, uint32> spawnMasks; for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i) @@ -1464,7 +1431,7 @@ void ObjectMgr::LoadCreatures() continue; } - CreatureData& data = mCreatureDataMap[guid]; + CreatureData& data = _creatureDataStore[guid]; data.id = entry; data.mapid = fields[ 2].GetUInt32(); @@ -1501,7 +1468,7 @@ void ObjectMgr::LoadCreatures() bool ok = true; for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff) { - if (difficultyCreatures[diff].find(data.id) != difficultyCreatures[diff].end()) + if (_difficultyEntries[diff].find(data.id) != _difficultyEntries[diff].end()) { sLog->outErrorDb("Table `creature` have creature (GUID: %u) that listed as difficulty %u template (entry: %u) in `creature_template`, skipped.", guid, diff + 1, data.id); @@ -1575,7 +1542,7 @@ void ObjectMgr::AddCreatureToGrid(uint32 guid, CreatureData const* data) if (mask & 1) { CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; cell_guids.creatures.insert(guid); } } @@ -1589,7 +1556,7 @@ void ObjectMgr::RemoveCreatureFromGrid(uint32 guid, CreatureData const* data) if (mask & 1) { CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; cell_guids.creatures.erase(guid); } } @@ -1792,7 +1759,7 @@ void ObjectMgr::LoadGameobjects() continue; } - GameObjectData& data = mGameObjectDataMap[guid]; + GameObjectData& data = _gameObjectDataStore[guid]; data.id = entry; data.mapid = fields[ 2].GetUInt32(); @@ -1868,7 +1835,7 @@ void ObjectMgr::LoadGameobjects() } while (result->NextRow()); - sLog->outString(">> Loaded %lu gameobjects in %u ms", (unsigned long)mGameObjectDataMap.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu gameobjects in %u ms", (unsigned long)_gameObjectDataStore.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -1880,7 +1847,7 @@ void ObjectMgr::AddGameobjectToGrid(uint32 guid, GameObjectData const* data) if (mask & 1) { CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; cell_guids.gameobjects.insert(guid); } } @@ -1894,7 +1861,7 @@ void ObjectMgr::RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data if (mask & 1) { CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; cell_guids.gameobjects.erase(guid); } } @@ -1922,12 +1889,12 @@ void ObjectMgr::LoadCreatureRespawnTimes() uint32 respawn_time = fields[1].GetUInt32(); uint32 instance = fields[2].GetUInt32(); - mCreatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = time_t(respawn_time); + _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = time_t(respawn_time); ++count; } while (result->NextRow()); - sLog->outString(">> Loaded %lu creature respawn times in %u ms", (unsigned long)mCreatureRespawnTimes.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu creature respawn times in %u ms", (unsigned long)_creatureRespawnTimes.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -1956,13 +1923,13 @@ void ObjectMgr::LoadGameobjectRespawnTimes() uint32 respawn_time = fields[1].GetUInt32(); uint32 instance = fields[2].GetUInt32(); - mGORespawnTimes[MAKE_PAIR64(loguid, instance)] = time_t(respawn_time); + _goRespawnTimes[MAKE_PAIR64(loguid, instance)] = time_t(respawn_time); ++count; } while (result->NextRow()); sLog->outString(); - sLog->outString(">> Loaded %lu gameobject respawn times in %u ms", (unsigned long)mGORespawnTimes.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu gameobject respawn times in %u ms", (unsigned long)_goRespawnTimes.size(), GetMSTimeDiffToNow(oldMSTime)); } Player* ObjectMgr::GetPlayerByLowGUID(uint32 lowguid) const @@ -2059,7 +2026,7 @@ void ObjectMgr::LoadItemLocales() { uint32 oldMSTime = getMSTime(); - mItemLocaleMap.clear(); // need for reload case + _itemLocaleStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT entry, name_loc1, description_loc1, name_loc2, description_loc2, name_loc3, description_loc3, name_loc4, description_loc4, name_loc5, description_loc5, name_loc6, description_loc6, name_loc7, description_loc7, name_loc8, description_loc8 FROM locales_item"); @@ -2072,7 +2039,7 @@ void ObjectMgr::LoadItemLocales() uint32 entry = fields[0].GetUInt32(); - ItemLocale& data = mItemLocaleMap[entry]; + ItemLocale& data = _itemLocaleStore[entry]; for (uint8 i = 1; i < TOTAL_LOCALES; ++i) { @@ -2082,7 +2049,7 @@ void ObjectMgr::LoadItemLocales() } } while (result->NextRow()); - sLog->outString(">> Loaded %lu Item locale strings in %u ms", (unsigned long)mItemLocaleMap.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu Item locale strings in %u ms", (unsigned long)_itemLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -2593,8 +2560,8 @@ void ObjectMgr::LoadItemScriptNames() ItemTemplate const* ObjectMgr::GetItemTemplate(uint32 entry) { - ItemTemplateContainer::const_iterator itr = ItemTemplateStore.find(entry); - if (itr != ItemTemplateStore.end()) + ItemTemplateContainer::const_iterator itr = _itemTemplateStore.find(entry); + if (itr != _itemTemplateStore.end()) return &(itr->second); return NULL; @@ -2604,7 +2571,7 @@ void ObjectMgr::LoadItemSetNameLocales() { uint32 oldMSTime = getMSTime(); - mItemSetNameLocaleMap.clear(); // need for reload case + _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`"); @@ -2617,13 +2584,13 @@ void ObjectMgr::LoadItemSetNameLocales() uint32 entry = fields[0].GetUInt32(); - ItemSetNameLocale& data = mItemSetNameLocaleMap[entry]; + ItemSetNameLocale& data = _itemSetNameLocaleStore[entry]; for (uint8 i = 1; i < TOTAL_LOCALES; ++i) AddLocaleString(fields[i].GetString(), LocaleConstant(i), data.Name); } while (result->NextRow()); - sLog->outString(">> Loaded " UI64FMTD " Item set name locale strings in %u ms", uint64(mItemSetNameLocaleMap.size()), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded " UI64FMTD " Item set name locale strings in %u ms", uint64(_itemSetNameLocaleStore.size()), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -2631,7 +2598,7 @@ void ObjectMgr::LoadItemSetNames() { uint32 oldMSTime = getMSTime(); - mItemSetNameMap.clear(); // needed for reload case + _itemSetNameStore.clear(); // needed for reload case std::set<uint32> itemSetItems; @@ -2669,7 +2636,7 @@ void ObjectMgr::LoadItemSetNames() continue; } - ItemSetNameEntry &data = mItemSetNameMap[entry]; + ItemSetNameEntry &data = _itemSetNameStore[entry]; data.name = fields[1].GetString(); uint32 invType = fields[2].GetUInt32(); @@ -2695,7 +2662,7 @@ void ObjectMgr::LoadItemSetNames() if (pProto) { sLog->outErrorDb("Item set part (Entry: %u) does not have entry in `item_set_names`, adding data from `item_template`.", entry); - ItemSetNameEntry &data = mItemSetNameMap[entry]; + ItemSetNameEntry &data = _itemSetNameStore[entry]; data.name = pProto->Name1; data.InventoryType = pProto->InventoryType; ++count; @@ -2713,7 +2680,7 @@ void ObjectMgr::LoadVehicleTemplateAccessories() { uint32 oldMSTime = getMSTime(); - m_VehicleTemplateAccessoryMap.clear(); // needed for reload case + _vehicleTemplateAccessoryStore.clear(); // needed for reload case uint32 count = 0; @@ -2749,13 +2716,13 @@ void ObjectMgr::LoadVehicleTemplateAccessories() continue; } - if (mSpellClickInfoMap.find(uiEntry) == mSpellClickInfoMap.end()) + if (_spellClickInfoStore.find(uiEntry) == _spellClickInfoStore.end()) { sLog->outErrorDb("Table `vehicle_template_accessory`: creature template entry %u has no data in npc_spellclick_spells", uiEntry); continue; } - m_VehicleTemplateAccessoryMap[uiEntry].push_back(VehicleAccessory(uiAccessory, uiSeat, bMinion, uiSummonType, uiSummonTimer)); + _vehicleTemplateAccessoryStore[uiEntry].push_back(VehicleAccessory(uiAccessory, uiSeat, bMinion, uiSummonType, uiSummonTimer)); ++count; } @@ -2769,7 +2736,7 @@ void ObjectMgr::LoadVehicleAccessories() { uint32 oldMSTime = getMSTime(); - m_VehicleAccessoryMap.clear(); // needed for reload case + _vehicleAccessoryStore.clear(); // needed for reload case uint32 count = 0; @@ -2799,7 +2766,7 @@ void ObjectMgr::LoadVehicleAccessories() continue; } - m_VehicleAccessoryMap[uiGUID].push_back(VehicleAccessory(uiAccessory, uiSeat, bMinion, uiSummonType, uiSummonTimer)); + _vehicleAccessoryStore[uiGUID].push_back(VehicleAccessory(uiAccessory, uiSeat, bMinion, uiSummonType, uiSummonTimer)); ++count; } @@ -2854,7 +2821,7 @@ void ObjectMgr::LoadPetLevelInfo() continue; } - PetLevelInfo*& pInfoMapEntry = petInfo[creature_id]; + PetLevelInfo*& pInfoMapEntry = _petInfoStore[creature_id]; if (pInfoMapEntry == NULL) pInfoMapEntry = new PetLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)]; @@ -2876,7 +2843,7 @@ void ObjectMgr::LoadPetLevelInfo() while (result->NextRow()); // Fill gaps and check integrity - for (PetLevelInfoMap::iterator itr = petInfo.begin(); itr != petInfo.end(); ++itr) + for (PetLevelInfoContainer::iterator itr = _petInfoStore.begin(); itr != _petInfoStore.end(); ++itr) { PetLevelInfo* pInfo = itr->second; @@ -2907,8 +2874,8 @@ PetLevelInfo const* ObjectMgr::GetPetLevelInfo(uint32 creature_id, uint8 level) if (level > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) level = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); - PetLevelInfoMap::const_iterator itr = petInfo.find(creature_id); - if (itr == petInfo.end()) + PetLevelInfoContainer::const_iterator itr = _petInfoStore.find(creature_id); + if (itr == _petInfoStore.end()) return NULL; return &itr->second[level-1]; // data for level 1 stored in [0] array element, ... @@ -2917,7 +2884,7 @@ PetLevelInfo const* ObjectMgr::GetPetLevelInfo(uint32 creature_id, uint8 level) void ObjectMgr::PlayerCreateInfoAddItemHelper(uint32 race_, uint32 class_, uint32 itemId, int32 count) { if (count > 0) - playerInfo[race_][class_].item.push_back(PlayerCreateInfoItem(itemId, count)); + _playerInfo[race_][class_].item.push_back(PlayerCreateInfoItem(itemId, count)); else { if (count < -1) @@ -3024,7 +2991,7 @@ void ObjectMgr::LoadPlayerInfo() continue; } - PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + PlayerInfo* pInfo = &_playerInfo[current_race][current_class]; pInfo->mapId = mapId; pInfo->areaId = areaId; @@ -3163,10 +3130,10 @@ void ObjectMgr::LoadPlayerInfo() uint32 max_class = current_class ? current_class + 1 : MAX_CLASSES; for (uint32 r = min_race; r < max_race; ++r) for (uint32 c = min_class; c < max_class; ++c) - playerInfo[r][c].spell.push_back(fields[2].GetUInt32()); + _playerInfo[r][c].spell.push_back(fields[2].GetUInt32()); } else - playerInfo[current_race][current_class].spell.push_back(fields[2].GetUInt32()); + _playerInfo[current_race][current_class].spell.push_back(fields[2].GetUInt32()); ++count; } @@ -3212,7 +3179,7 @@ void ObjectMgr::LoadPlayerInfo() continue; } - PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + PlayerInfo* pInfo = &_playerInfo[current_race][current_class]; pInfo->action.push_back(PlayerCreateInfoAction(fields[2].GetUInt8(), fields[3].GetUInt32(), fields[4].GetUInt8())); ++count; @@ -3260,7 +3227,7 @@ void ObjectMgr::LoadPlayerInfo() continue; } - PlayerClassInfo* pClassInfo = &playerClassInfo[current_class]; + PlayerClassInfo* pClassInfo = &_playerClassInfo[current_class]; if (!pClassInfo->levelInfo) pClassInfo->levelInfo = new PlayerClassLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)]; @@ -3281,7 +3248,7 @@ void ObjectMgr::LoadPlayerInfo() if (!sChrClassesStore.LookupEntry(class_)) continue; - PlayerClassInfo* pClassInfo = &playerClassInfo[class_]; + PlayerClassInfo* pClassInfo = &_playerClassInfo[class_]; // fatal error if no level 1 data if (!pClassInfo->levelInfo || pClassInfo->levelInfo[0].basehealth == 0) @@ -3353,7 +3320,7 @@ void ObjectMgr::LoadPlayerInfo() continue; } - PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + PlayerInfo* pInfo = &_playerInfo[current_race][current_class]; if (!pInfo->levelInfo) pInfo->levelInfo = new PlayerLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)]; @@ -3382,7 +3349,7 @@ void ObjectMgr::LoadPlayerInfo() if (!sChrClassesStore.LookupEntry(class_)) continue; - PlayerInfo* pInfo = &playerInfo[race][class_]; + PlayerInfo* pInfo = &_playerInfo[race][class_]; // skip non loaded combinations if (!pInfo->displayId_m || !pInfo->displayId_f) @@ -3424,9 +3391,9 @@ void ObjectMgr::LoadPlayerInfo() { uint32 oldMSTime = getMSTime(); - mPlayerXPperLevel.resize(sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); + _playerXPperLevel.resize(sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); for (uint8 level = 0; level < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) - mPlayerXPperLevel[level] = 0; + _playerXPperLevel[level] = 0; // 0 1 QueryResult result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM player_xp_for_level"); @@ -3459,7 +3426,7 @@ void ObjectMgr::LoadPlayerInfo() continue; } //PlayerXPperLevel - mPlayerXPperLevel[current_level] = current_xp; + _playerXPperLevel[current_level] = current_xp; ++count; } while (result->NextRow()); @@ -3467,10 +3434,10 @@ void ObjectMgr::LoadPlayerInfo() // fill level gaps for (uint8 level = 1; level < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) { - if (mPlayerXPperLevel[level] == 0) + if (_playerXPperLevel[level] == 0) { sLog->outErrorDb("Level %i does not have XP for level data. Using data of level [%i] + 100.", level+1, level); - mPlayerXPperLevel[level] = mPlayerXPperLevel[level-1]+100; + _playerXPperLevel[level] = _playerXPperLevel[level-1]+100; } } @@ -3484,7 +3451,7 @@ void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint8 level, PlayerClassL if (level < 1 || class_ >= MAX_CLASSES) return; - PlayerClassInfo const* pInfo = &playerClassInfo[class_]; + PlayerClassInfo const* pInfo = &_playerClassInfo[class_]; if (level > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) level = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); @@ -3497,7 +3464,7 @@ void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, Play if (level < 1 || race >= MAX_RACES || class_ >= MAX_CLASSES) return; - PlayerInfo const* pInfo = &playerInfo[race][class_]; + PlayerInfo const* pInfo = &_playerInfo[race][class_]; if (pInfo->displayId_m == 0 || pInfo->displayId_f == 0) return; @@ -3510,7 +3477,7 @@ void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, Play void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, PlayerLevelInfo* info) const { // base data (last known level) - *info = playerInfo[race][_class].levelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)-1]; + *info = _playerInfo[race][_class].levelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)-1]; // if conversion from uint32 to uint8 causes unexpected behaviour, change lvl to uint32 for (uint8 lvl = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)-1; lvl < level; ++lvl) @@ -3588,9 +3555,9 @@ void ObjectMgr::LoadQuests() uint32 oldMSTime = getMSTime(); // For reload case - for (QuestMap::const_iterator itr=mQuestTemplates.begin(); itr != mQuestTemplates.end(); ++itr) + for (QuestMap::const_iterator itr=_questTemplates.begin(); itr != _questTemplates.end(); ++itr) delete itr->second; - mQuestTemplates.clear(); + _questTemplates.clear(); mExclusiveQuestGroups.clear(); @@ -3649,13 +3616,13 @@ void ObjectMgr::LoadQuests() Field* fields = result->Fetch(); Quest * newQuest = new Quest(fields); - mQuestTemplates[newQuest->GetQuestId()] = newQuest; + _questTemplates[newQuest->GetQuestId()] = newQuest; } while (result->NextRow()); std::map<uint32, uint32> usedMailTemplates; // Post processing - for (QuestMap::iterator iter = mQuestTemplates.begin(); iter != mQuestTemplates.end(); ++iter) + for (QuestMap::iterator iter = _questTemplates.begin(); iter != _questTemplates.end(); ++iter) { // skip post-loading checks for disabled quests if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, iter->first, NULL)) @@ -4191,8 +4158,8 @@ void ObjectMgr::LoadQuests() if (qinfo->NextQuestIdChain) { - QuestMap::iterator qNextItr = mQuestTemplates.find(qinfo->NextQuestIdChain); - if (qNextItr == mQuestTemplates.end()) + QuestMap::iterator qNextItr = _questTemplates.find(qinfo->NextQuestIdChain); + if (qNextItr == _questTemplates.end()) { sLog->outErrorDb("Quest %u has `NextQuestIdChain` = %u but quest %u does not exist, quest chain will not work.", qinfo->GetQuestId(), qinfo->NextQuestIdChain, qinfo->NextQuestIdChain); @@ -4360,7 +4327,7 @@ void ObjectMgr::LoadQuests() // fill additional data stores if (qinfo->PrevQuestId) { - if (mQuestTemplates.find(abs(qinfo->GetPrevQuestId())) == mQuestTemplates.end()) + if (_questTemplates.find(abs(qinfo->GetPrevQuestId())) == _questTemplates.end()) { sLog->outErrorDb("Quest %d has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId()); } @@ -4372,8 +4339,8 @@ void ObjectMgr::LoadQuests() if (qinfo->NextQuestId) { - QuestMap::iterator qNextItr = mQuestTemplates.find(abs(qinfo->GetNextQuestId())); - if (qNextItr == mQuestTemplates.end()) + QuestMap::iterator qNextItr = _questTemplates.find(abs(qinfo->GetNextQuestId())); + if (qNextItr == _questTemplates.end()) { sLog->outErrorDb("Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId()); } @@ -4422,7 +4389,7 @@ void ObjectMgr::LoadQuests() } } - sLog->outString(">> Loaded %lu quests definitions in %u ms", (unsigned long)mQuestTemplates.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu quests definitions in %u ms", (unsigned long)_questTemplates.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -4430,7 +4397,7 @@ void ObjectMgr::LoadQuestLocales() { uint32 oldMSTime = getMSTime(); - mQuestLocaleMap.clear(); // need for reload case + _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, QuestGiverTextWindow_loc1, QuestGiverTargetName_loc1, QuestTurnTextWindow_loc1, QuestTurnTargetName_loc1," @@ -4452,7 +4419,7 @@ void ObjectMgr::LoadQuestLocales() uint32 entry = fields[0].GetUInt32(); - QuestLocale& data = mQuestLocaleMap[entry]; + QuestLocale& data = _questLocaleStore[entry]; for (uint8 i = 1; i < TOTAL_LOCALES; ++i) { @@ -4475,7 +4442,7 @@ void ObjectMgr::LoadQuestLocales() } } while (result->NextRow()); - sLog->outString(">> Loaded %lu Quest locale strings in %u ms", (unsigned long)mQuestLocaleMap.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu Quest locale strings in %u ms", (unsigned long)_questLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -4935,7 +4902,7 @@ void ObjectMgr::LoadSpellScriptNames() { uint32 oldMSTime = getMSTime(); - mSpellScripts.clear(); // need for reload case + _spellScriptsStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT spell_id, ScriptName FROM spell_script_names"); @@ -4979,12 +4946,12 @@ void ObjectMgr::LoadSpellScriptNames() } while (spellInfo) { - mSpellScripts.insert(SpellScriptsMap::value_type(spellInfo->Id, GetScriptId(scriptName))); + _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, GetScriptId(scriptName))); spellInfo = sSpellMgr->GetSpellInfo(spellInfo->Id)->GetNextRankSpell(); } } else - mSpellScripts.insert(SpellScriptsMap::value_type(spellInfo->Id, GetScriptId(scriptName))); + _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, GetScriptId(scriptName))); ++count; } while (result->NextRow()); @@ -4997,7 +4964,7 @@ void ObjectMgr::ValidateSpellScripts() { uint32 oldMSTime = getMSTime(); - if (mSpellScripts.empty()) + if (_spellScriptsStore.empty()) { sLog->outString(">> Validated 0 scripts."); sLog->outString(); @@ -5006,14 +4973,14 @@ void ObjectMgr::ValidateSpellScripts() uint32 count = 0; - for (SpellScriptsMap::iterator itr = mSpellScripts.begin(); itr != mSpellScripts.end();) + for (SpellScriptsContainer::iterator itr = _spellScriptsStore.begin(); itr != _spellScriptsStore.end();) { SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->first); - std::vector<std::pair<SpellScriptLoader *, SpellScriptsMap::iterator> > SpellScriptLoaders; + std::vector<std::pair<SpellScriptLoader *, SpellScriptsContainer::iterator> > SpellScriptLoaders; sScriptMgr->CreateSpellScriptLoaders(itr->first, SpellScriptLoaders); - itr = mSpellScripts.upper_bound(itr->first); + itr = _spellScriptsStore.upper_bound(itr->first); - for (std::vector<std::pair<SpellScriptLoader *, SpellScriptsMap::iterator> >::iterator sitr = SpellScriptLoaders.begin(); sitr != SpellScriptLoaders.end(); ++sitr) + for (std::vector<std::pair<SpellScriptLoader *, SpellScriptsContainer::iterator> >::iterator sitr = SpellScriptLoaders.begin(); sitr != SpellScriptLoaders.end(); ++sitr) { SpellScript* spellScript = sitr->first->GetSpellScript(); AuraScript* auraScript = sitr->first->GetAuraScript(); @@ -5041,7 +5008,7 @@ void ObjectMgr::ValidateSpellScripts() } if (!valid) { - mSpellScripts.erase(sitr->second); + _spellScriptsStore.erase(sitr->second); } } ++count; @@ -5069,7 +5036,7 @@ void ObjectMgr::LoadPageTexts() { Field* fields = result->Fetch(); - PageText& pageText = PageTextStore[fields[0].GetUInt32()]; + PageText& pageText = _pageTextStore[fields[0].GetUInt32()]; pageText.Text = fields[1].GetString(); pageText.NextPage = fields[2].GetInt16(); @@ -5078,12 +5045,12 @@ void ObjectMgr::LoadPageTexts() } while (result->NextRow()); - for (PageTextContainer::const_iterator itr = PageTextStore.begin(); itr != PageTextStore.end(); ++itr) + for (PageTextContainer::const_iterator itr = _pageTextStore.begin(); itr != _pageTextStore.end(); ++itr) { if (itr->second.NextPage) { - PageTextContainer::const_iterator itr2 = PageTextStore.find(itr->second.NextPage); - if (itr2 == PageTextStore.end()) + PageTextContainer::const_iterator itr2 = _pageTextStore.find(itr->second.NextPage); + if (itr2 == _pageTextStore.end()) sLog->outErrorDb("Page text (Id: %u) has not existing next page (Id: %u)", itr->first, itr->second.NextPage); } @@ -5095,8 +5062,8 @@ void ObjectMgr::LoadPageTexts() PageText const* ObjectMgr::GetPageText(uint32 pageEntry) { - PageTextContainer::const_iterator itr = PageTextStore.find(pageEntry); - if (itr != PageTextStore.end()) + PageTextContainer::const_iterator itr = _pageTextStore.find(pageEntry); + if (itr != _pageTextStore.end()) return &(itr->second); return NULL; @@ -5106,7 +5073,7 @@ void ObjectMgr::LoadPageTextLocales() { uint32 oldMSTime = getMSTime(); - mPageTextLocaleMap.clear(); // need for reload case + _pageTextLocaleStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT entry, text_loc1, text_loc2, text_loc3, text_loc4, text_loc5, text_loc6, text_loc7, text_loc8 FROM locales_page_text"); @@ -5119,13 +5086,13 @@ void ObjectMgr::LoadPageTextLocales() uint32 entry = fields[0].GetUInt32(); - PageTextLocale& data = mPageTextLocaleMap[entry]; + PageTextLocale& data = _pageTextLocaleStore[entry]; for (uint8 i = 1; i < TOTAL_LOCALES; ++i) AddLocaleString(fields[i].GetString(), LocaleConstant(i), data.Text); } while (result->NextRow()); - sLog->outString(">> Loaded %lu PageText locale strings in %u ms", (unsigned long)mPageTextLocaleMap.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu PageText locale strings in %u ms", (unsigned long)_pageTextLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -5161,7 +5128,7 @@ void ObjectMgr::LoadInstanceTemplate() instanceTemplate.Parent = uint32(fields[1].GetUInt16()); instanceTemplate.ScriptId = sObjectMgr->GetScriptId(fields[2].GetCString()); - InstanceTemplateStore[mapID] = instanceTemplate; + _instanceTemplateStore[mapID] = instanceTemplate; ++count; } @@ -5173,8 +5140,8 @@ void ObjectMgr::LoadInstanceTemplate() InstanceTemplate const* ObjectMgr::GetInstanceTemplate(uint32 mapID) { - InstanceTemplateContainer::const_iterator itr = InstanceTemplateStore.find(uint16(mapID)); - if (itr != InstanceTemplateStore.end()) + InstanceTemplateContainer::const_iterator itr = _instanceTemplateStore.find(uint16(mapID)); + if (itr != _instanceTemplateStore.end()) return &(itr->second); return NULL; @@ -5251,7 +5218,7 @@ void ObjectMgr::LoadInstanceEncounters() continue; } - DungeonEncounterList& encounters = mDungeonEncounters[MAKE_PAIR32(dungeonEncounter->mapId, dungeonEncounter->difficulty)]; + DungeonEncounterList& encounters = _dungeonEncounterStore[MAKE_PAIR32(dungeonEncounter->mapId, dungeonEncounter->difficulty)]; encounters.push_back(new DungeonEncounter(dungeonEncounter, EncounterCreditType(creditType), creditEntry, lastEncounterDungeon)); ++count; } while (result->NextRow()); @@ -5262,8 +5229,8 @@ void ObjectMgr::LoadInstanceEncounters() GossipText const* ObjectMgr::GetGossipText(uint32 Text_ID) const { - GossipTextMap::const_iterator itr = mGossipText.find(Text_ID); - if (itr != mGossipText.end()) + GossipTextContainer::const_iterator itr = _gossipTextStore.find(Text_ID); + if (itr != _gossipTextStore.end()) return &itr->second; return NULL; } @@ -5299,7 +5266,7 @@ void ObjectMgr::LoadGossipText() continue; } - GossipText& gText = mGossipText[Text_ID]; + GossipText& gText = _gossipTextStore[Text_ID]; for (int i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; i++) { @@ -5325,7 +5292,7 @@ void ObjectMgr::LoadNpcTextLocales() { uint32 oldMSTime = getMSTime(); - mNpcTextLocaleMap.clear(); // need for reload case + _npcTextLocaleStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT entry, " "Text0_0_loc1, Text0_1_loc1, Text1_0_loc1, Text1_1_loc1, Text2_0_loc1, Text2_1_loc1, Text3_0_loc1, Text3_1_loc1, Text4_0_loc1, Text4_1_loc1, Text5_0_loc1, Text5_1_loc1, Text6_0_loc1, Text6_1_loc1, Text7_0_loc1, Text7_1_loc1, " @@ -5347,7 +5314,7 @@ void ObjectMgr::LoadNpcTextLocales() uint32 entry = fields[0].GetUInt32(); - NpcTextLocale& data = mNpcTextLocaleMap[entry]; + NpcTextLocale& data = _npcTextLocaleStore[entry]; for (uint8 i = 1; i < TOTAL_LOCALES; ++i) { @@ -5360,7 +5327,7 @@ void ObjectMgr::LoadNpcTextLocales() } } while (result->NextRow()); - sLog->outString(">> Loaded %lu NpcText locale strings in %u ms", (unsigned long)mNpcTextLocaleMap.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu NpcText locale strings in %u ms", (unsigned long)_npcTextLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -5499,7 +5466,7 @@ void ObjectMgr::LoadQuestAreaTriggers() { uint32 oldMSTime = getMSTime(); - mQuestAreaTriggerMap.clear(); // need for reload case + _questAreaTriggerStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT id, quest FROM areatrigger_involvedrelation"); @@ -5546,7 +5513,7 @@ void ObjectMgr::LoadQuestAreaTriggers() // continue; - quest modified to required objective and trigger can be allowed. } - mQuestAreaTriggerMap[trigger_ID] = quest_ID; + _questAreaTriggerStore[trigger_ID] = quest_ID; } while (result->NextRow()); @@ -5558,7 +5525,7 @@ void ObjectMgr::LoadTavernAreaTriggers() { uint32 oldMSTime = getMSTime(); - mTavernAreaTriggerSet.clear(); // need for reload case + _tavernAreaTriggerStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT id FROM areatrigger_tavern"); @@ -5586,7 +5553,7 @@ void ObjectMgr::LoadTavernAreaTriggers() continue; } - mTavernAreaTriggerSet.insert(Trigger_ID); + _tavernAreaTriggerStore.insert(Trigger_ID); } while (result->NextRow()); sLog->outString(">> Loaded %u tavern triggers in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); @@ -5597,7 +5564,7 @@ void ObjectMgr::LoadAreaTriggerScripts() { uint32 oldMSTime = getMSTime(); - mAreaTriggerScripts.clear(); // need for reload case + _areaTriggerScriptStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT entry, ScriptName FROM areatrigger_scripts"); if (!result) @@ -5624,7 +5591,7 @@ void ObjectMgr::LoadAreaTriggerScripts() sLog->outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.", Trigger_ID); continue; } - mAreaTriggerScripts[Trigger_ID] = GetScriptId(scriptName); + _areaTriggerScriptStore[Trigger_ID] = GetScriptId(scriptName); } while (result->NextRow()); sLog->outString(">> Loaded %u areatrigger scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); @@ -5739,7 +5706,7 @@ void ObjectMgr::LoadGraveyardZones() { uint32 oldMSTime = getMSTime(); - mGraveYardMap.clear(); // need for reload case + GraveYardStore.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT id, ghost_zone, faction FROM game_graveyard_zone"); @@ -5832,8 +5799,8 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float // then check faction // if mapId != graveyard.mapId (ghost in instance) and search any graveyard associated // then check faction - GraveYardMap::const_iterator graveLow = mGraveYardMap.lower_bound(zoneId); - GraveYardMap::const_iterator graveUp = mGraveYardMap.upper_bound(zoneId); + GraveYardContainer::const_iterator graveLow = GraveYardStore.lower_bound(zoneId); + GraveYardContainer::const_iterator graveUp = GraveYardStore.upper_bound(zoneId); MapEntry const* map = sMapStore.LookupEntry(MapId); // not need to check validity of map object; MapId _MUST_ be valid here @@ -5858,7 +5825,7 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float MapEntry const* mapEntry = sMapStore.LookupEntry(MapId); - for (GraveYardMap::const_iterator itr = graveLow; itr != graveUp; ++itr) + for (GraveYardContainer::const_iterator itr = graveLow; itr != graveUp; ++itr) { GraveYardData const& data = itr->second; @@ -5938,10 +5905,10 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float GraveYardData const* ObjectMgr::FindGraveYardData(uint32 id, uint32 zoneId) { - GraveYardMap::const_iterator graveLow = mGraveYardMap.lower_bound(zoneId); - GraveYardMap::const_iterator graveUp = mGraveYardMap.upper_bound(zoneId); + GraveYardContainer::const_iterator graveLow = GraveYardStore.lower_bound(zoneId); + GraveYardContainer::const_iterator graveUp = GraveYardStore.upper_bound(zoneId); - for (GraveYardMap::const_iterator itr = graveLow; itr != graveUp; ++itr) + for (GraveYardContainer::const_iterator itr = graveLow; itr != graveUp; ++itr) { if (itr->second.safeLocId == id) return &itr->second; @@ -5960,7 +5927,7 @@ bool ObjectMgr::AddGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool per data.safeLocId = id; data.team = team; - mGraveYardMap.insert(GraveYardMap::value_type(zoneId, data)); + GraveYardStore.insert(GraveYardContainer::value_type(zoneId, data)); // add link to DB if (persist) @@ -5979,8 +5946,8 @@ bool ObjectMgr::AddGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool per void ObjectMgr::RemoveGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool persist /*= false*/) { - GraveYardMap::iterator graveLow = mGraveYardMap.lower_bound(zoneId); - GraveYardMap::iterator graveUp = mGraveYardMap.upper_bound(zoneId); + GraveYardContainer::iterator graveLow = GraveYardStore.lower_bound(zoneId); + GraveYardContainer::iterator graveUp = GraveYardStore.upper_bound(zoneId); if (graveLow == graveUp) { //sLog->outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team); @@ -5989,7 +5956,7 @@ void ObjectMgr::RemoveGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool bool found = false; - GraveYardMap::iterator itr; + GraveYardContainer::iterator itr; for (itr = graveLow; itr != graveUp; ++itr) { @@ -6013,7 +5980,7 @@ void ObjectMgr::RemoveGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool return; // remove from links - mGraveYardMap.erase(itr); + GraveYardStore.erase(itr); // remove link from DB if (persist) @@ -6034,7 +6001,7 @@ void ObjectMgr::LoadAreaTriggerTeleports() { uint32 oldMSTime = getMSTime(); - mAreaTriggers.clear(); // need for reload case + _areaTriggerStore.clear(); // need for reload case // 0 1 2 3 4 5 QueryResult result = WorldDatabase.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport"); @@ -6083,7 +6050,7 @@ void ObjectMgr::LoadAreaTriggerTeleports() continue; } - mAreaTriggers[Trigger_ID] = at; + _areaTriggerStore[Trigger_ID] = at; } while (result->NextRow()); @@ -6095,7 +6062,7 @@ void ObjectMgr::LoadAccessRequirements() { uint32 oldMSTime = getMSTime(); - mAccessRequirements.clear(); // need for reload case + _accessRequirementStore.clear(); // need for reload case // 0 1 2 3 4 5 6 7 8 9 QueryResult result = WorldDatabase.Query("SELECT mapid, difficulty, level_min, level_max, item, item2, quest_done_A, quest_done_H, completed_achievement, quest_failed_text FROM access_requirement"); @@ -6176,7 +6143,7 @@ void ObjectMgr::LoadAccessRequirements() } } - mAccessRequirements[requirement_ID] = ar; + _accessRequirementStore[requirement_ID] = ar; } while (result->NextRow()); sLog->outString(">> Loaded %u access requirement definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); @@ -6206,7 +6173,7 @@ AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const } uint32 entrance_map = uint32(mapEntry->entrance_map); - for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); ++itr) + for (AreaTriggerContainer::const_iterator itr = _areaTriggerStore.begin(); itr != _areaTriggerStore.end(); ++itr) if ((!useParentDbValue && itr->second.target_mapId == entrance_map) || (useParentDbValue && itr->second.target_mapId == parentId)) { AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first); @@ -6221,7 +6188,7 @@ AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const */ AreaTrigger const* ObjectMgr::GetMapEntranceTrigger(uint32 Map) const { - for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); ++itr) + for (AreaTriggerContainer::const_iterator itr = _areaTriggerStore.begin(); itr != _areaTriggerStore.end(); ++itr) { if (itr->second.target_mapId == Map) { @@ -6237,41 +6204,41 @@ void ObjectMgr::SetHighestGuids() { QueryResult result = CharacterDatabase.Query("SELECT MAX(guid) FROM characters"); if (result) - m_hiCharGuid = (*result)[0].GetUInt32()+1; + _hiCharGuid = (*result)[0].GetUInt32()+1; result = WorldDatabase.Query("SELECT MAX(guid) FROM creature"); if (result) - m_hiCreatureGuid = (*result)[0].GetUInt32()+1; + _hiCreatureGuid = (*result)[0].GetUInt32()+1; result = CharacterDatabase.Query("SELECT MAX(guid) FROM item_instance"); if (result) - m_hiItemGuid = (*result)[0].GetUInt32()+1; + _hiItemGuid = (*result)[0].GetUInt32()+1; - // Cleanup other tables from not existed guids ( >= m_hiItemGuid) - CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item >= '%u'", m_hiItemGuid); // One-time query - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid >= '%u'", m_hiItemGuid); // One-time query - CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE itemguid >= '%u'", m_hiItemGuid); // One-time query - CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE item_guid >= '%u'", m_hiItemGuid); // One-time query + // Cleanup other tables from not existed guids ( >= _hiItemGuid) + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item >= '%u'", _hiItemGuid); // One-time query + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid >= '%u'", _hiItemGuid); // One-time query + CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE itemguid >= '%u'", _hiItemGuid); // One-time query + CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE item_guid >= '%u'", _hiItemGuid); // One-time query result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject"); if (result) - m_hiGoGuid = (*result)[0].GetUInt32()+1; + _hiGoGuid = (*result)[0].GetUInt32()+1; result = WorldDatabase.Query("SELECT MAX(guid) FROM transports"); if (result) - m_hiMoTransGuid = (*result)[0].GetUInt32()+1; + _hiMoTransGuid = (*result)[0].GetUInt32()+1; result = CharacterDatabase.Query("SELECT MAX(id) FROM auctionhouse"); if (result) - m_auctionid = (*result)[0].GetUInt32()+1; + _auctionId = (*result)[0].GetUInt32()+1; result = CharacterDatabase.Query("SELECT MAX(id) FROM mail"); if (result) - m_mailid = (*result)[0].GetUInt32()+1; + _mailId = (*result)[0].GetUInt32()+1; result = CharacterDatabase.Query("SELECT MAX(corpseGuid) FROM corpse"); if (result) - m_hiCorpseGuid = (*result)[0].GetUInt32()+1; + _hiCorpseGuid = (*result)[0].GetUInt32()+1; result = CharacterDatabase.Query("SELECT MAX(arenateamid) FROM arena_team"); if (result) @@ -6279,7 +6246,7 @@ void ObjectMgr::SetHighestGuids() result = CharacterDatabase.Query("SELECT MAX(setguid) FROM character_equipmentsets"); if (result) - m_equipmentSetGuid = (*result)[0].GetUInt64()+1; + _equipmentSetGuid = (*result)[0].GetUInt64()+1; result = CharacterDatabase.Query("SELECT MAX(guildId) FROM guild"); if (result) @@ -6292,32 +6259,32 @@ void ObjectMgr::SetHighestGuids() uint32 ObjectMgr::GenerateAuctionID() { - if (m_auctionid >= 0xFFFFFFFE) + if (_auctionId >= 0xFFFFFFFE) { sLog->outError("Auctions ids overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_auctionid++; + return _auctionId++; } uint64 ObjectMgr::GenerateEquipmentSetGuid() { - if (m_equipmentSetGuid >= uint64(0xFFFFFFFFFFFFFFFELL)) + if (_equipmentSetGuid >= uint64(0xFFFFFFFFFFFFFFFELL)) { sLog->outError("EquipmentSet guid overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_equipmentSetGuid++; + return _equipmentSetGuid++; } uint32 ObjectMgr::GenerateMailID() { - if (m_mailid >= 0xFFFFFFFE) + if (_mailId >= 0xFFFFFFFE) { sLog->outError("Mail ids overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_mailid++; + return _mailId++; } uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) @@ -6325,68 +6292,68 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) switch (guidhigh) { case HIGHGUID_ITEM: - if (m_hiItemGuid >= 0xFFFFFFFE) + if (_hiItemGuid >= 0xFFFFFFFE) { sLog->outError("Item guid overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_hiItemGuid++; + return _hiItemGuid++; case HIGHGUID_UNIT: - if (m_hiCreatureGuid >= 0x00FFFFFE) + if (_hiCreatureGuid >= 0x00FFFFFE) { sLog->outError("Creature guid overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_hiCreatureGuid++; + return _hiCreatureGuid++; case HIGHGUID_PET: - if (m_hiPetGuid >= 0x00FFFFFE) + if (_hiPetGuid >= 0x00FFFFFE) { sLog->outError("Pet guid overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_hiPetGuid++; + return _hiPetGuid++; case HIGHGUID_VEHICLE: - if (m_hiVehicleGuid >= 0x00FFFFFF) + if (_hiVehicleGuid >= 0x00FFFFFF) { sLog->outError("Vehicle guid overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_hiVehicleGuid++; + return _hiVehicleGuid++; case HIGHGUID_PLAYER: - if (m_hiCharGuid >= 0xFFFFFFFE) + if (_hiCharGuid >= 0xFFFFFFFE) { sLog->outError("Players guid overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_hiCharGuid++; + return _hiCharGuid++; case HIGHGUID_GAMEOBJECT: - if (m_hiGoGuid >= 0x00FFFFFE) + if (_hiGoGuid >= 0x00FFFFFE) { sLog->outError("Gameobject guid overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_hiGoGuid++; + return _hiGoGuid++; case HIGHGUID_CORPSE: - if (m_hiCorpseGuid >= 0xFFFFFFFE) + if (_hiCorpseGuid >= 0xFFFFFFFE) { sLog->outError("Corpse guid overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_hiCorpseGuid++; + return _hiCorpseGuid++; case HIGHGUID_DYNAMICOBJECT: - if (m_hiDoGuid >= 0xFFFFFFFE) + if (_hiDoGuid >= 0xFFFFFFFE) { sLog->outError("DynamicObject guid overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_hiDoGuid++; + return _hiDoGuid++; case HIGHGUID_MO_TRANSPORT: - if (m_hiMoTransGuid >= 0xFFFFFFFE) + if (_hiMoTransGuid >= 0xFFFFFFFE) { sLog->outError("MO Transport guid overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); } - return m_hiMoTransGuid++; + return _hiMoTransGuid++; default: ASSERT(0); } @@ -6399,7 +6366,7 @@ void ObjectMgr::LoadGameObjectLocales() { uint32 oldMSTime = getMSTime(); - mGameObjectLocaleMap.clear(); // need for reload case + _gameObjectLocaleStore.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, " @@ -6415,7 +6382,7 @@ void ObjectMgr::LoadGameObjectLocales() uint32 entry = fields[0].GetUInt32(); - GameObjectLocale& data = mGameObjectLocaleMap[entry]; + GameObjectLocale& data = _gameObjectLocaleStore[entry]; for (uint8 i = 1; i < TOTAL_LOCALES; ++i) AddLocaleString(fields[i].GetString(), LocaleConstant(i), data.Name); @@ -6424,7 +6391,7 @@ void ObjectMgr::LoadGameObjectLocales() AddLocaleString(fields[i + (TOTAL_LOCALES - 1)].GetString(), LocaleConstant(i), data.CastBarCaption); } while (result->NextRow()); - sLog->outString(">> Loaded %lu gameobject locale strings in %u ms", (unsigned long)mGameObjectLocaleMap.size(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %lu gameobject locale strings in %u ms", (unsigned long)_gameObjectLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -6515,7 +6482,7 @@ void ObjectMgr::LoadGameObjectTemplate() uint32 entry = fields[0].GetUInt32(); - GameObjectTemplate& got = GameObjectTemplateStore[entry]; + GameObjectTemplate& got = _gameObjectTemplateStore[entry]; got.entry = entry; got.type = uint32(fields[1].GetUInt8()); @@ -6698,7 +6665,7 @@ void ObjectMgr::LoadExplorationBaseXP() Field* fields = result->Fetch(); uint8 level = fields[0].GetUInt8(); uint32 basexp = fields[1].GetUInt32(); - mBaseXPTable[level] = basexp; + _baseXPTable[level] = basexp; ++count; } while (result->NextRow()); @@ -6709,13 +6676,13 @@ void ObjectMgr::LoadExplorationBaseXP() uint32 ObjectMgr::GetBaseXP(uint8 level) { - return mBaseXPTable[level] ? mBaseXPTable[level] : 0; + return _baseXPTable[level] ? _baseXPTable[level] : 0; } uint32 ObjectMgr::GetXPForLevel(uint8 level) { - if (level < mPlayerXPperLevel.size()) - return mPlayerXPperLevel[level]; + if (level < _playerXPperLevel.size()) + return _playerXPperLevel[level]; return 0; } @@ -6742,9 +6709,9 @@ void ObjectMgr::LoadPetNames() uint32 entry = fields[1].GetUInt32(); bool half = fields[2].GetBool(); if (half) - PetHalfName1[entry].push_back(word); + _petHalfName1[entry].push_back(word); else - PetHalfName0[entry].push_back(word); + _petHalfName0[entry].push_back(word); ++count; } while (result->NextRow()); @@ -6761,17 +6728,17 @@ void ObjectMgr::LoadPetNumber() if (result) { Field* fields = result->Fetch(); - m_hiPetNumber = fields[0].GetUInt32()+1; + _hiPetNumber = fields[0].GetUInt32()+1; } - sLog->outString(">> Loaded the max pet number: %d in %u ms", m_hiPetNumber-1, GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded the max pet number: %d in %u ms", _hiPetNumber-1, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } std::string ObjectMgr::GeneratePetName(uint32 entry) { - StringVector & list0 = PetHalfName0[entry]; - StringVector & list1 = PetHalfName1[entry]; + StringVector & list0 = _petHalfName0[entry]; + StringVector & list1 = _petHalfName1[entry]; if (list0.empty() || list1.empty()) { @@ -6788,7 +6755,7 @@ std::string ObjectMgr::GeneratePetName(uint32 entry) uint32 ObjectMgr::GeneratePetNumber() { - return ++m_hiPetNumber; + return ++_hiPetNumber; } void ObjectMgr::LoadCorpses() @@ -6801,7 +6768,7 @@ void ObjectMgr::LoadCorpses() PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES)); if (!result) { - sLog->outString(">> Loaded 0 corpses. DB table `pet_name_generation` is empty."); + sLog->outString(">> Loaded 0 corpses. DB table `corpse` is empty."); sLog->outString(); return; } @@ -6838,7 +6805,7 @@ void ObjectMgr::LoadReputationRewardRate() { uint32 oldMSTime = getMSTime(); - m_RepRewardRateMap.clear(); // for reload case + _repRewardRateStore.clear(); // for reload case uint32 count = 0; QueryResult result = WorldDatabase.Query("SELECT faction, quest_rate, creature_rate, spell_rate FROM reputation_reward_rate"); @@ -6888,7 +6855,7 @@ void ObjectMgr::LoadReputationRewardRate() continue; } - m_RepRewardRateMap[factionId] = repRate; + _repRewardRateStore[factionId] = repRate; ++count; } @@ -6903,7 +6870,7 @@ void ObjectMgr::LoadReputationOnKill() uint32 oldMSTime = getMSTime(); // For reload case - mRepOnKill.clear(); + _repOnKillStore.clear(); uint32 count = 0; @@ -6927,15 +6894,15 @@ void ObjectMgr::LoadReputationOnKill() uint32 creature_id = fields[0].GetUInt32(); ReputationOnKillEntry repOnKill; - repOnKill.repfaction1 = fields[1].GetUInt32(); - repOnKill.repfaction2 = fields[2].GetUInt32(); - repOnKill.is_teamaward1 = fields[3].GetBool(); - repOnKill.reputation_max_cap1 = fields[4].GetUInt32(); - repOnKill.repvalue1 = fields[5].GetInt32(); - repOnKill.is_teamaward2 = fields[6].GetBool(); - repOnKill.reputation_max_cap2 = fields[7].GetUInt32(); - repOnKill.repvalue2 = fields[8].GetInt32(); - repOnKill.team_dependent = fields[9].GetUInt8(); + repOnKill.RepFaction1 = fields[1].GetUInt32(); + repOnKill.RepFaction2 = fields[2].GetUInt32(); + repOnKill.IsTeamAward1 = fields[3].GetBool(); + repOnKill.ReputationMaxCap1 = fields[4].GetUInt32(); + repOnKill.RepValue1 = fields[5].GetInt32(); + repOnKill.IsTeamAward2 = fields[6].GetBool(); + repOnKill.ReputationMaxCap2 = fields[7].GetUInt32(); + repOnKill.RepValue2 = fields[8].GetInt32(); + repOnKill.TeamDependent = fields[9].GetUInt8(); if (!GetCreatureTemplate(creature_id)) { @@ -6943,27 +6910,27 @@ void ObjectMgr::LoadReputationOnKill() continue; } - if (repOnKill.repfaction1) + if (repOnKill.RepFaction1) { - FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(repOnKill.repfaction1); + FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(repOnKill.RepFaction1); if (!factionEntry1) { - sLog->outErrorDb("Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`", repOnKill.repfaction1); + sLog->outErrorDb("Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`", repOnKill.RepFaction1); continue; } } - if (repOnKill.repfaction2) + if (repOnKill.RepFaction2) { - FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(repOnKill.repfaction2); + FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(repOnKill.RepFaction2); if (!factionEntry2) { - sLog->outErrorDb("Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`", repOnKill.repfaction2); + sLog->outErrorDb("Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`", repOnKill.RepFaction2); continue; } } - mRepOnKill[creature_id] = repOnKill; + _repOnKillStore[creature_id] = repOnKill; ++count; } while (result->NextRow()); @@ -6976,7 +6943,7 @@ void ObjectMgr::LoadReputationSpilloverTemplate() { uint32 oldMSTime = getMSTime(); - m_RepSpilloverTemplateMap.clear(); // for reload case + _repSpilloverTemplateStore.clear(); // for reload case uint32 count = 0; 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"); @@ -7075,7 +7042,7 @@ void ObjectMgr::LoadReputationSpilloverTemplate() continue; } - m_RepSpilloverTemplateMap[factionId] = repTemplate; + _repSpilloverTemplateStore[factionId] = repTemplate; ++count; } @@ -7089,7 +7056,7 @@ void ObjectMgr::LoadPointsOfInterest() { uint32 oldMSTime = getMSTime(); - mPointsOfInterest.clear(); // need for reload case + _pointsOfInterestStore.clear(); // need for reload case uint32 count = 0; @@ -7123,7 +7090,7 @@ void ObjectMgr::LoadPointsOfInterest() continue; } - mPointsOfInterest[point_id] = POI; + _pointsOfInterestStore[point_id] = POI; ++count; } while (result->NextRow()); @@ -7136,7 +7103,7 @@ void ObjectMgr::LoadQuestPOI() { uint32 oldMSTime = getMSTime(); - mQuestPOIMap.clear(); // need for reload case + _questPOIStore.clear(); // need for reload case uint32 count = 0; @@ -7196,7 +7163,7 @@ void ObjectMgr::LoadQuestPOI() QuestPOI POI(id, objIndex, mapId, WorldMapAreaId, FloorId, unk3, unk4); POI.points = POIs[questId][id]; - mQuestPOIMap[questId].push_back(POI); + _questPOIStore[questId].push_back(POI); ++count; } while (result->NextRow()); @@ -7209,9 +7176,9 @@ void ObjectMgr::LoadNPCSpellClickSpells() { uint32 oldMSTime = getMSTime(); - mSpellClickInfoMap.clear(); - // 0 1 2 3 4 5 6 7 8 - QueryResult result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_start, quest_start_active, quest_end, cast_flags, aura_required, aura_forbidden, user_type FROM npc_spellclick_spells"); + _spellClickInfoStore.clear(); + // 0 1 2 3 + QueryResult result = WorldDatabase.Query("SELECT npc_entry, spell_id, cast_flags, user_type FROM npc_spellclick_spells"); if (!result) { @@ -7242,68 +7209,16 @@ void ObjectMgr::LoadNPCSpellClickSpells() continue; } - uint32 auraRequired = fields[6].GetUInt32(); - if (auraRequired) - { - SpellInfo const* aurReqInfo = sSpellMgr->GetSpellInfo(auraRequired); - if (!aurReqInfo) - { - sLog->outErrorDb("Table npc_spellclick_spells references unknown aura required %u. Skipping entry.", auraRequired); - continue; - } - } - - uint32 auraForbidden = fields[7].GetUInt32(); - if (auraForbidden) - { - SpellInfo const* aurForInfo = sSpellMgr->GetSpellInfo(auraForbidden); - if (!aurForInfo) - { - sLog->outErrorDb("Table npc_spellclick_spells references unknown aura forbidden %u. Skipping entry.", auraForbidden); - continue; - } - } - - uint32 quest_start = fields[2].GetUInt32(); - - // quest might be 0 to enable spellclick independent of any quest - if (quest_start) - { - if (mQuestTemplates.find(quest_start) == mQuestTemplates.end()) - { - sLog->outErrorDb("Table npc_spellclick_spells references unknown start quest %u. Skipping entry.", quest_start); - continue; - } - } - - bool quest_start_active = fields[3].GetBool(); - - uint32 quest_end = fields[4].GetUInt32(); - // quest might be 0 to enable spellclick active infinity after start quest - if (quest_end) - { - if (mQuestTemplates.find(quest_end) == mQuestTemplates.end()) - { - sLog->outErrorDb("Table npc_spellclick_spells references unknown end quest %u. Skipping entry.", quest_end); - continue; - } - } - - uint8 userType = fields[8].GetUInt8(); + uint8 userType = fields[3].GetUInt8(); if (userType >= SPELL_CLICK_USER_MAX) sLog->outErrorDb("Table npc_spellclick_spells references unknown user type %u. Skipping entry.", uint32(userType)); - uint8 castFlags = fields[5].GetUInt8(); + uint8 castFlags = fields[2].GetUInt8(); SpellClickInfo info; info.spellId = spellid; - info.questStart = quest_start; - info.questStartCanActive = quest_start_active; - info.questEnd = quest_end; info.castFlags = castFlags; - info.auraRequired = auraRequired; - info.auraForbidden = auraForbidden; info.userType = SpellClickUserTypes(userType); - mSpellClickInfoMap.insert(SpellClickInfoMap::value_type(npc_entry, info)); + _spellClickInfoStore.insert(SpellClickInfoContainer::value_type(npc_entry, info)); ++count; } @@ -7314,7 +7229,7 @@ void ObjectMgr::LoadNPCSpellClickSpells() CreatureTemplateContainer const* ctc = sObjectMgr->GetCreatureTemplates(); for (CreatureTemplateContainer::const_iterator itr = ctc->begin(); itr != ctc->end(); ++itr) { - if ((itr->second.npcflag & UNIT_NPC_FLAG_SPELLCLICK) && mSpellClickInfoMap.find(itr->second.Entry) == mSpellClickInfoMap.end()) + if ((itr->second.npcflag & UNIT_NPC_FLAG_SPELLCLICK) && _spellClickInfoStore.find(itr->second.Entry) == _spellClickInfoStore.end()) { sLog->outErrorDb("npc_spellclick_spells: Creature template %u has UNIT_NPC_FLAG_SPELLCLICK but no data in spellclick table! Removing flag", itr->second.Entry); const_cast<CreatureTemplate*>(&itr->second)->npcflag &= ~UNIT_NPC_FLAG_SPELLCLICK; @@ -7336,9 +7251,9 @@ void ObjectMgr::SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t // This function can be called from various map threads concurrently { - m_CreatureRespawnTimesMtx.acquire(); - mCreatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = t; - m_CreatureRespawnTimesMtx.release(); + _creatureRespawnTimesMutex.acquire(); + _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = t; + _creatureRespawnTimesMutex.release(); } PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CREATURE_RESPAWN); @@ -7352,9 +7267,9 @@ void ObjectMgr::RemoveCreatureRespawnTime(uint32 loguid, uint32 instance) { // This function can be called from various map threads concurrently { - m_CreatureRespawnTimesMtx.acquire(); - mCreatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = 0; - m_CreatureRespawnTimesMtx.release(); + _creatureRespawnTimesMutex.acquire(); + _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = 0; + _creatureRespawnTimesMutex.release(); } PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN); @@ -7370,7 +7285,7 @@ void ObjectMgr::DeleteCreatureData(uint32 guid) if (data) RemoveCreatureFromGrid(guid, data); - mCreatureDataMap.erase(guid); + _creatureDataStore.erase(guid); } void ObjectMgr::SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t) @@ -7384,9 +7299,9 @@ void ObjectMgr::SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t) // This function can be called from different map threads concurrently { - m_GORespawnTimesMtx.acquire(); - mGORespawnTimes[MAKE_PAIR64(loguid, instance)] = t; - m_GORespawnTimesMtx.release(); + _goRespawnTimesMutex.acquire(); + _goRespawnTimes[MAKE_PAIR64(loguid, instance)] = t; + _goRespawnTimesMutex.release(); } PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GO_RESPAWN); @@ -7400,9 +7315,9 @@ void ObjectMgr::RemoveGORespawnTime(uint32 loguid, uint32 instance) { // This function can be called from different map threads concurrently { - m_GORespawnTimesMtx.acquire(); - mGORespawnTimes[MAKE_PAIR64(loguid, instance)] = 0; - m_GORespawnTimesMtx.release(); + _goRespawnTimesMutex.acquire(); + _goRespawnTimes[MAKE_PAIR64(loguid, instance)] = 0; + _goRespawnTimesMutex.release(); } PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN); @@ -7417,28 +7332,28 @@ void ObjectMgr::DeleteRespawnTimeForInstance(uint32 instance) RespawnTimes::iterator next; { - m_GORespawnTimesMtx.acquire(); - for (RespawnTimes::iterator itr = mGORespawnTimes.begin(); itr != mGORespawnTimes.end(); itr = next) + _goRespawnTimesMutex.acquire(); + for (RespawnTimes::iterator itr = _goRespawnTimes.begin(); itr != _goRespawnTimes.end(); itr = next) { next = itr; ++next; if (GUID_HIPART(itr->first) == instance) - mGORespawnTimes.erase(itr); + _goRespawnTimes.erase(itr); } - m_GORespawnTimesMtx.release(); + _goRespawnTimesMutex.release(); } { - m_CreatureRespawnTimesMtx.acquire(); - for (RespawnTimes::iterator itr = mCreatureRespawnTimes.begin(); itr != mCreatureRespawnTimes.end(); itr = next) + _creatureRespawnTimesMutex.acquire(); + for (RespawnTimes::iterator itr = _creatureRespawnTimes.begin(); itr != _creatureRespawnTimes.end(); itr = next) { next = itr; ++next; if (GUID_HIPART(itr->first) == instance) - mCreatureRespawnTimes.erase(itr); + _creatureRespawnTimes.erase(itr); } - m_CreatureRespawnTimesMtx.release(); + _creatureRespawnTimesMutex.release(); } PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE); stmt->setUInt32(0, instance); @@ -7455,20 +7370,20 @@ void ObjectMgr::DeleteGOData(uint32 guid) if (data) RemoveGameobjectFromGrid(guid, data); - mGameObjectDataMap.erase(guid); + _gameObjectDataStore.erase(guid); } void ObjectMgr::AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance) { // corpses are always added to spawn mode 0 and they are spawned by their instance id - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(mapid, 0)][cellid]; + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(mapid, 0)][cellid]; cell_guids.corpses[player_guid] = instance; } void ObjectMgr::DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid) { // corpses are always added to spawn mode 0 and they are spawned by their instance id - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(mapid, 0)][cellid]; + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(mapid, 0)][cellid]; cell_guids.corpses.erase(player_guid); } @@ -7500,7 +7415,7 @@ void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map, std::string table, uint32 quest = result->Fetch()[1].GetUInt32(); uint32 poolId = result->Fetch()[2].GetUInt32(); - if (mQuestTemplates.find(quest) == mQuestTemplates.end()) + if (_questTemplates.find(quest) == _questTemplates.end()) { sLog->outErrorDb("Table `%s`: Quest %u listed for entry %u does not exist.", table.c_str(), quest, id); continue; @@ -7520,9 +7435,9 @@ void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map, std::string table, void ObjectMgr::LoadGameobjectQuestRelations() { - LoadQuestRelationsHelper(mGOQuestRelations, "gameobject_questrelation", true, true); + LoadQuestRelationsHelper(_goQuestRelations, "gameobject_questrelation", true, true); - for (QuestRelations::iterator itr = mGOQuestRelations.begin(); itr != mGOQuestRelations.end(); ++itr) + for (QuestRelations::iterator itr = _goQuestRelations.begin(); itr != _goQuestRelations.end(); ++itr) { GameObjectTemplate const* goInfo = GetGameObjectTemplate(itr->first); if (!goInfo) @@ -7534,9 +7449,9 @@ void ObjectMgr::LoadGameobjectQuestRelations() void ObjectMgr::LoadGameobjectInvolvedRelations() { - LoadQuestRelationsHelper(mGOQuestInvolvedRelations, "gameobject_involvedrelation", false, true); + LoadQuestRelationsHelper(_goQuestInvolvedRelations, "gameobject_involvedrelation", false, true); - for (QuestRelations::iterator itr = mGOQuestInvolvedRelations.begin(); itr != mGOQuestInvolvedRelations.end(); ++itr) + for (QuestRelations::iterator itr = _goQuestInvolvedRelations.begin(); itr != _goQuestInvolvedRelations.end(); ++itr) { GameObjectTemplate const* goInfo = GetGameObjectTemplate(itr->first); if (!goInfo) @@ -7548,9 +7463,9 @@ void ObjectMgr::LoadGameobjectInvolvedRelations() void ObjectMgr::LoadCreatureQuestRelations() { - LoadQuestRelationsHelper(mCreatureQuestRelations, "creature_questrelation", true, false); + LoadQuestRelationsHelper(_creatureQuestRelations, "creature_questrelation", true, false); - for (QuestRelations::iterator itr = mCreatureQuestRelations.begin(); itr != mCreatureQuestRelations.end(); ++itr) + for (QuestRelations::iterator itr = _creatureQuestRelations.begin(); itr != _creatureQuestRelations.end(); ++itr) { CreatureTemplate const* cInfo = GetCreatureTemplate(itr->first); if (!cInfo) @@ -7562,9 +7477,9 @@ void ObjectMgr::LoadCreatureQuestRelations() void ObjectMgr::LoadCreatureInvolvedRelations() { - LoadQuestRelationsHelper(mCreatureQuestInvolvedRelations, "creature_involvedrelation", false, false); + LoadQuestRelationsHelper(_creatureQuestInvolvedRelations, "creature_involvedrelation", false, false); - for (QuestRelations::iterator itr = mCreatureQuestInvolvedRelations.begin(); itr != mCreatureQuestInvolvedRelations.end(); ++itr) + for (QuestRelations::iterator itr = _creatureQuestInvolvedRelations.begin(); itr != _creatureQuestInvolvedRelations.end(); ++itr) { CreatureTemplate const* cInfo = GetCreatureTemplate(itr->first); if (!cInfo) @@ -7578,7 +7493,7 @@ void ObjectMgr::LoadReservedPlayersNames() { uint32 oldMSTime = getMSTime(); - m_ReservedNames.clear(); // need for reload case + _reservedNamesStore.clear(); // need for reload case QueryResult result = CharacterDatabase.Query("SELECT name FROM reserved_name"); @@ -7606,7 +7521,7 @@ void ObjectMgr::LoadReservedPlayersNames() wstrToLower(wstr); - m_ReservedNames.insert(wstr); + _reservedNamesStore.insert(wstr); ++count; } while (result->NextRow()); @@ -7623,7 +7538,7 @@ bool ObjectMgr::IsReservedName(const std::string& name) const wstrToLower(wstr); - return m_ReservedNames.find(wstr) != m_ReservedNames.end(); + return _reservedNamesStore.find(wstr) != _reservedNamesStore.end(); } enum LanguageType @@ -7761,7 +7676,7 @@ void ObjectMgr::LoadGameObjectForQuests() { uint32 oldMSTime = getMSTime(); - mGameObjectForQuestSet.clear(); // need for reload case + _gameObjectForQuestStore.clear(); // need for reload case if (sObjectMgr->GetGameObjectTemplates()->empty()) { @@ -7786,7 +7701,7 @@ void ObjectMgr::LoadGameObjectForQuests() // find quest loot for GO if (itr->second.chest.questId || LootTemplates_Gameobject.HaveQuestLootFor(loot_id)) { - mGameObjectForQuestSet.insert(itr->second.entry); + _gameObjectForQuestStore.insert(itr->second.entry); ++count; } break; @@ -7795,7 +7710,7 @@ void ObjectMgr::LoadGameObjectForQuests() { if (itr->second._generic.questID > 0) //quests objects { - mGameObjectForQuestSet.insert(itr->second.entry); + _gameObjectForQuestStore.insert(itr->second.entry); count++; } break; @@ -7804,7 +7719,7 @@ void ObjectMgr::LoadGameObjectForQuests() { if (itr->second.goober.questId > 0) //quests objects { - mGameObjectForQuestSet.insert(itr->second.entry); + _gameObjectForQuestStore.insert(itr->second.entry); count++; } break; @@ -7848,10 +7763,10 @@ bool ObjectMgr::LoadTrinityStrings(char const* table, int32 min_value, int32 max } // cleanup affected map part for reloading case - for (TrinityStringLocaleMap::iterator itr = mTrinityStringLocaleMap.begin(); itr != mTrinityStringLocaleMap.end();) + for (TrinityStringLocaleContainer::iterator itr = _trinityStringLocaleStore.begin(); itr != _trinityStringLocaleStore.end();) { if (itr->first >= start_value && itr->first < end_value) - mTrinityStringLocaleMap.erase(itr++); + _trinityStringLocaleStore.erase(itr++); else ++itr; } @@ -7888,7 +7803,7 @@ bool ObjectMgr::LoadTrinityStrings(char const* table, int32 min_value, int32 max continue; } - TrinityStringLocale& data = mTrinityStringLocaleMap[entry]; + TrinityStringLocale& data = _trinityStringLocaleStore[entry]; if (!data.Content.empty()) { @@ -7933,7 +7848,7 @@ void ObjectMgr::LoadFishingBaseSkillLevel() { uint32 oldMSTime = getMSTime(); - mFishingBaseForArea.clear(); // for reload case + _fishingBaseForAreaStore.clear(); // for reload case QueryResult result = WorldDatabase.Query("SELECT entry, skill FROM skill_fishing_base_level"); @@ -7960,7 +7875,7 @@ void ObjectMgr::LoadFishingBaseSkillLevel() continue; } - mFishingBaseForArea[entry] = skill; + _fishingBaseForAreaStore[entry] = skill; ++count; } while (result->NextRow()); @@ -7995,15 +7910,15 @@ bool ObjectMgr::CheckDeclinedNames(std::wstring w_ownname, DeclinedName const& n uint32 ObjectMgr::GetAreaTriggerScriptId(uint32 trigger_id) { - AreaTriggerScriptMap::const_iterator i = mAreaTriggerScripts.find(trigger_id); - if (i!= mAreaTriggerScripts.end()) + AreaTriggerScriptContainer::const_iterator i = _areaTriggerScriptStore.find(trigger_id); + if (i!= _areaTriggerScriptStore.end()) return i->second; return 0; } SpellScriptsBounds ObjectMgr::GetSpellScriptsBounds(uint32 spell_id) { - return SpellScriptsBounds(mSpellScripts.lower_bound(spell_id), mSpellScripts.upper_bound(spell_id)); + return SpellScriptsBounds(_spellScriptsStore.lower_bound(spell_id), _spellScriptsStore.upper_bound(spell_id)); } SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial) @@ -8042,7 +7957,7 @@ void ObjectMgr::LoadGameTele() { uint32 oldMSTime = getMSTime(); - m_GameTeleMap.clear(); // for reload case + _gameTeleStore.clear(); // for reload case QueryResult result = WorldDatabase.Query("SELECT id, position_x, position_y, position_z, orientation, map, name FROM game_tele"); @@ -8085,7 +8000,7 @@ void ObjectMgr::LoadGameTele() wstrToLower(gt.wnameLow); - m_GameTeleMap[id] = gt; + _gameTeleStore[id] = gt; ++count; } @@ -8107,7 +8022,7 @@ GameTele const* ObjectMgr::GetGameTele(const std::string& name) const // Alternative first GameTele what contains wnameLow as substring in case no GameTele location found const GameTele* alt = NULL; - for (GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) + for (GameTeleContainer::const_iterator itr = _gameTeleStore.begin(); itr != _gameTeleStore.end(); ++itr) { if (itr->second.wnameLow == wname) return &itr->second; @@ -8122,7 +8037,7 @@ bool ObjectMgr::AddGameTele(GameTele& tele) { // find max id uint32 new_id = 0; - for (GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) + for (GameTeleContainer::const_iterator itr = _gameTeleStore.begin(); itr != _gameTeleStore.end(); ++itr) if (itr->first > new_id) new_id = itr->first; @@ -8134,7 +8049,7 @@ bool ObjectMgr::AddGameTele(GameTele& tele) wstrToLower(tele.wnameLow); - m_GameTeleMap[new_id] = tele; + _gameTeleStore[new_id] = tele; PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_GAME_TELE); @@ -8161,7 +8076,7 @@ bool ObjectMgr::DeleteGameTele(const std::string& name) // converting string that we try to find to lower case wstrToLower(wname); - for (GameTeleMap::iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) + for (GameTeleContainer::iterator itr = _gameTeleStore.begin(); itr != _gameTeleStore.end(); ++itr) { if (itr->second.wnameLow == wname) { @@ -8171,7 +8086,7 @@ bool ObjectMgr::DeleteGameTele(const std::string& name) WorldDatabase.Execute(stmt); - m_GameTeleMap.erase(itr); + _gameTeleStore.erase(itr); return true; } } @@ -8183,7 +8098,7 @@ void ObjectMgr::LoadMailLevelRewards() { uint32 oldMSTime = getMSTime(); - m_mailLevelRewardMap.clear(); // for reload case + _mailLevelRewardStore.clear(); // for reload case QueryResult result = WorldDatabase.Query("SELECT level, raceMask, mailTemplateId, senderEntry FROM mail_level_reward"); @@ -8230,7 +8145,7 @@ void ObjectMgr::LoadMailLevelRewards() continue; } - m_mailLevelRewardMap[level].push_back(MailLevelReward(raceMask, mailTemplateId, senderEntry)); + _mailLevelRewardStore[level].push_back(MailLevelReward(raceMask, mailTemplateId, senderEntry)); ++count; } @@ -8277,7 +8192,7 @@ void ObjectMgr::AddSpellToTrainer(uint32 entry, uint32 spell, uint32 spellCost, return; } - TrainerSpellData& data = m_mCacheTrainerSpellMap[entry]; + TrainerSpellData& data = _cacheTrainerSpellStore[entry]; TrainerSpell& trainerSpell = data.spellList[spell]; trainerSpell.spell = spell; @@ -8323,7 +8238,7 @@ void ObjectMgr::LoadTrainerSpell() uint32 oldMSTime = getMSTime(); // For reload case - m_mCacheTrainerSpellMap.clear(); + _cacheTrainerSpellStore.clear(); std::set<uint32> skip_trainers; @@ -8389,7 +8304,7 @@ int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, std::set<uint32> *s if (!IsVendorItemValid(vendor, item_id, maxcount, incrtime, ExtendedCost, NULL, skip_vendors)) continue; - VendorItemData& vList = m_mCacheVendorItemMap[vendor]; + VendorItemData& vList = _cacheVendorItemStore[vendor]; vList.AddItem(item_id, maxcount, incrtime, ExtendedCost); ++count; @@ -8405,9 +8320,9 @@ void ObjectMgr::LoadVendors() uint32 oldMSTime = getMSTime(); // For reload case - for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) + for (CacheVendorItemContainer::iterator itr = _cacheVendorItemStore.begin(); itr != _cacheVendorItemStore.end(); ++itr) itr->second.Clear(); - m_mCacheVendorItemMap.clear(); + _cacheVendorItemStore.clear(); std::set<uint32> skip_vendors; @@ -8440,7 +8355,7 @@ void ObjectMgr::LoadVendors() if (!IsVendorItemValid(entry, item_id, maxcount, incrtime, ExtendedCost, NULL, &skip_vendors)) continue; - VendorItemData& vList = m_mCacheVendorItemMap[entry]; + VendorItemData& vList = _cacheVendorItemStore[entry]; vList.AddItem(item_id, maxcount, incrtime, ExtendedCost); ++count; @@ -8457,7 +8372,7 @@ void ObjectMgr::LoadGossipMenu() { uint32 oldMSTime = getMSTime(); - m_mGossipMenusMap.clear(); + _gossipMenusStore.clear(); QueryResult result = WorldDatabase.Query("SELECT entry, text_id FROM gossip_menu"); @@ -8486,7 +8401,7 @@ void ObjectMgr::LoadGossipMenu() continue; } - m_mGossipMenusMap.insert(GossipMenusMap::value_type(gMenu.entry, gMenu)); + _gossipMenusStore.insert(GossipMenusContainer::value_type(gMenu.entry, gMenu)); ++count; } @@ -8500,7 +8415,7 @@ void ObjectMgr::LoadGossipMenuItems() { uint32 oldMSTime = getMSTime(); - m_mGossipMenuItemsMap.clear(); + _gossipMenuItemsStore.clear(); QueryResult result = WorldDatabase.Query( "SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, " @@ -8549,7 +8464,7 @@ void ObjectMgr::LoadGossipMenuItems() gMenuItem.ActionPoiId = 0; } - m_mGossipMenuItemsMap.insert(GossipMenuItemsMap::value_type(gMenuItem.MenuId, gMenuItem)); + _gossipMenuItemsStore.insert(GossipMenuItemsContainer::value_type(gMenuItem.MenuId, gMenuItem)); ++count; } while (result->NextRow()); @@ -8560,7 +8475,7 @@ void ObjectMgr::LoadGossipMenuItems() void ObjectMgr::AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, bool persist /*= true*/) { - VendorItemData& vList = m_mCacheVendorItemMap[entry]; + VendorItemData& vList = _cacheVendorItemStore[entry]; vList.AddItem(item, maxcount, incrtime, extendedCost); if (persist) @@ -8579,8 +8494,8 @@ void ObjectMgr::AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, bool persist /*= true*/) { - CacheVendorItemMap::iterator iter = m_mCacheVendorItemMap.find(entry); - if (iter == m_mCacheVendorItemMap.end()) + CacheVendorItemContainer::iterator iter = _cacheVendorItemStore.find(entry); + if (iter == _cacheVendorItemStore.end()) return false; if (!iter->second.RemoveItem(item)) @@ -8690,7 +8605,7 @@ void ObjectMgr::LoadScriptNames() { uint32 oldMSTime = getMSTime(); - m_scriptNames.push_back(""); + _scriptNamesStore.push_back(""); QueryResult result = WorldDatabase.Query( "SELECT DISTINCT(ScriptName) FROM achievement_criteria_data WHERE ScriptName <> '' AND type = 11 " "UNION " @@ -8727,12 +8642,12 @@ void ObjectMgr::LoadScriptNames() do { - m_scriptNames.push_back((*result)[0].GetString()); + _scriptNamesStore.push_back((*result)[0].GetString()); ++count; } while (result->NextRow()); - std::sort(m_scriptNames.begin(), m_scriptNames.end()); + std::sort(_scriptNamesStore.begin(), _scriptNamesStore.end()); sLog->outString(">> Loaded %d Script Names in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -8742,10 +8657,10 @@ uint32 ObjectMgr::GetScriptId(const char *name) // use binary search to find the script name in the sorted vector // assume "" is the first element if (!name) return 0; - ScriptNameMap::const_iterator itr = - std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name); - if (itr == m_scriptNames.end() || *itr != name) return 0; - return uint32(itr - m_scriptNames.begin()); + ScriptNameContainer::const_iterator itr = + std::lower_bound(_scriptNamesStore.begin(), _scriptNamesStore.end(), name); + if (itr == _scriptNamesStore.end() || *itr != name) return 0; + return uint32(itr - _scriptNamesStore.begin()); } void ObjectMgr::CheckScripts(ScriptsType type, std::set<int32>& ids) @@ -8806,9 +8721,9 @@ bool LoadTrinityStrings(char const* table, int32 start_value, int32 end_value) CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unitClass) { - CreatureBaseStatsMap::const_iterator it = m_creatureBaseStatsMap.find(MAKE_PAIR16(level, unitClass)); + CreatureBaseStatsContainer::const_iterator it = _creatureBaseStatsStore.find(MAKE_PAIR16(level, unitClass)); - if (it != m_creatureBaseStatsMap.end()) + if (it != _creatureBaseStatsStore.end()) return &(it->second); struct DefaultCreatureBaseStats : public CreatureBaseStats @@ -8866,7 +8781,7 @@ void ObjectMgr::LoadCreatureClassLevelStats() } } - m_creatureBaseStatsMap[MAKE_PAIR16(Level, Class)] = stats; + _creatureBaseStatsStore[MAKE_PAIR16(Level, Class)] = stats; ++count; } @@ -8877,7 +8792,7 @@ void ObjectMgr::LoadCreatureClassLevelStats() { for (uint16 lvl = itr->second.minlevel; lvl <= itr->second.maxlevel; ++lvl) { - if (m_creatureBaseStatsMap.find(MAKE_PAIR16(lvl, itr->second.unit_class)) == m_creatureBaseStatsMap.end()) + if (_creatureBaseStatsStore.find(MAKE_PAIR16(lvl, itr->second.unit_class)) == _creatureBaseStatsStore.end()) sLog->outErrorDb("Missing base stats for creature class %u level %u", itr->second.unit_class, lvl); } } @@ -8913,7 +8828,7 @@ void ObjectMgr::LoadFactionChangeAchievements() else if (!sAchievementStore.LookupEntry(horde)) sLog->outErrorDb("Achievement %u referenced in `player_factionchange_achievement` does not exist, pair skipped!", horde); else - factionchange_achievements[alliance] = horde; + FactionChange_Achievements[alliance] = horde; ++count; } @@ -8950,7 +8865,7 @@ void ObjectMgr::LoadFactionChangeItems() else if (!GetItemTemplate(horde)) sLog->outErrorDb("Item %u referenced in `player_factionchange_items` does not exist, pair skipped!", horde); else - factionchange_items[alliance] = horde; + FactionChange_Items[alliance] = horde; ++count; } @@ -8987,7 +8902,7 @@ void ObjectMgr::LoadFactionChangeSpells() else if (!sSpellMgr->GetSpellInfo(horde)) sLog->outErrorDb("Spell %u referenced in `player_factionchange_spells` does not exist, pair skipped!", horde); else - factionchange_spells[alliance] = horde; + FactionChange_Spells[alliance] = horde; ++count; } @@ -9024,7 +8939,7 @@ void ObjectMgr::LoadFactionChangeReputations() else if (!sFactionStore.LookupEntry(horde)) sLog->outErrorDb("Reputation %u referenced in `player_factionchange_reputations` does not exist, pair skipped!", horde); else - factionchange_reputations[alliance] = horde; + FactionChange_Reputation[alliance] = horde; ++count; } @@ -9071,8 +8986,8 @@ void ObjectMgr::LoadHotfixData() GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry) { - GameObjectTemplateContainer::const_iterator itr = GameObjectTemplateStore.find(entry); - if (itr != GameObjectTemplateStore.end()) + GameObjectTemplateContainer::const_iterator itr = _gameObjectTemplateStore.find(entry); + if (itr != _gameObjectTemplateStore.end()) return &(itr->second); return NULL; @@ -9080,8 +8995,8 @@ GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry) CreatureTemplate const* ObjectMgr::GetCreatureTemplate(uint32 entry) { - CreatureTemplateContainer::const_iterator itr = CreatureTemplateStore.find(entry); - if (itr != CreatureTemplateStore.end()) + CreatureTemplateContainer::const_iterator itr = _creatureTemplateStore.find(entry); + if (itr != _creatureTemplateStore.end()) return &(itr->second); return NULL; @@ -9092,14 +9007,14 @@ VehicleAccessoryList const* ObjectMgr::GetVehicleAccessoryList(Vehicle* veh) con if (Creature* cre = veh->GetBase()->ToCreature()) { // Give preference to GUID-based accessories - VehicleAccessoryMap::const_iterator itr = m_VehicleAccessoryMap.find(cre->GetDBTableGUIDLow()); - if (itr != m_VehicleAccessoryMap.end()) + VehicleAccessoryContainer::const_iterator itr = _vehicleAccessoryStore.find(cre->GetDBTableGUIDLow()); + if (itr != _vehicleAccessoryStore.end()) return &itr->second; } // Otherwise return entry-based - VehicleAccessoryMap::const_iterator itr = m_VehicleTemplateAccessoryMap.find(veh->GetCreatureEntry()); - if (itr != m_VehicleTemplateAccessoryMap.end()) + VehicleAccessoryContainer::const_iterator itr = _vehicleTemplateAccessoryStore.find(veh->GetCreatureEntry()); + if (itr != _vehicleTemplateAccessoryStore.end()) return &itr->second; return NULL; } diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 023b28d0860..ae699a01da7 100755 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -82,7 +82,7 @@ struct GameTele std::wstring wnameLow; }; -typedef UNORDERED_MAP<uint32, GameTele > GameTeleMap; +typedef UNORDERED_MAP<uint32, GameTele > GameTeleContainer; enum ScriptsType { @@ -321,8 +321,8 @@ struct ScriptInfo typedef std::multimap<uint32, ScriptInfo> ScriptMap; typedef std::map<uint32, ScriptMap > ScriptMapMap; -typedef std::multimap<uint32, uint32> SpellScriptsMap; -typedef std::pair<SpellScriptsMap::iterator, SpellScriptsMap::iterator> SpellScriptsBounds; +typedef std::multimap<uint32, uint32> SpellScriptsContainer; +typedef std::pair<SpellScriptsContainer::iterator, SpellScriptsContainer::iterator> SpellScriptsBounds; extern ScriptMapMap sQuestEndScripts; extern ScriptMapMap sQuestStartScripts; extern ScriptMapMap sSpellScripts; @@ -337,20 +337,15 @@ std::string GetScriptCommandName(ScriptCommands command); struct SpellClickInfo { uint32 spellId; - uint32 questStart; // quest start (quest must be active or rewarded for spell apply) - uint32 questEnd; // quest end (quest must not be rewarded for spell apply) - bool questStartCanActive; // if true then quest start can be active (not only rewarded) uint8 castFlags; - uint32 auraRequired; - uint32 auraForbidden; SpellClickUserTypes userType; // helpers bool IsFitToRequirements(Unit const* clicker, Unit const* clickee) const; }; -typedef std::multimap<uint32, SpellClickInfo> SpellClickInfoMap; -typedef std::pair<SpellClickInfoMap::const_iterator, SpellClickInfoMap::const_iterator> SpellClickInfoMapBounds; +typedef std::multimap<uint32, SpellClickInfo> SpellClickInfoContainer; +typedef std::pair<SpellClickInfoContainer::const_iterator, SpellClickInfoContainer::const_iterator> SpellClickInfoMapBounds; struct AreaTrigger { @@ -390,24 +385,22 @@ struct TrinityStringLocale StringVector Content; }; -typedef std::map<uint64, uint64> LinkedRespawnMap; -typedef UNORDERED_MAP<uint32, CreatureData> CreatureDataMap; -typedef UNORDERED_MAP<uint32, GameObjectData> GameObjectDataMap; -typedef UNORDERED_MAP<uint32, CreatureLocale> CreatureLocaleMap; -typedef UNORDERED_MAP<uint32, GameObjectLocale> GameObjectLocaleMap; -typedef UNORDERED_MAP<uint32, ItemLocale> ItemLocaleMap; -typedef UNORDERED_MAP<uint32, ItemSetNameLocale> ItemSetNameLocaleMap; -typedef UNORDERED_MAP<uint32, QuestLocale> QuestLocaleMap; -typedef UNORDERED_MAP<uint32, NpcTextLocale> NpcTextLocaleMap; -typedef UNORDERED_MAP<uint32, PageTextLocale> PageTextLocaleMap; -typedef UNORDERED_MAP<int32, TrinityStringLocale> TrinityStringLocaleMap; -typedef UNORDERED_MAP<uint32, GossipMenuItemsLocale> GossipMenuItemsLocaleMap; -typedef UNORDERED_MAP<uint32, PointOfInterestLocale> PointOfInterestLocaleMap; +typedef std::map<uint64, uint64> LinkedRespawnContainer; +typedef UNORDERED_MAP<uint32, CreatureData> CreatureDataContainer; +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; +typedef UNORDERED_MAP<int32, TrinityStringLocale> TrinityStringLocaleContainer; +typedef UNORDERED_MAP<uint32, GossipMenuItemsLocale> GossipMenuItemsLocaleContainer; +typedef UNORDERED_MAP<uint32, PointOfInterestLocale> PointOfInterestLocaleContainer; typedef std::multimap<uint32, uint32> QuestRelations; typedef std::pair<QuestRelations::const_iterator, QuestRelations::const_iterator> QuestRelationBounds; -typedef std::multimap<uint32, ItemRequiredTarget> ItemRequiredTargetMap; -typedef std::pair<ItemRequiredTargetMap::const_iterator, ItemRequiredTargetMap::const_iterator> ItemRequiredTargetMapBounds; struct PetLevelInfo { @@ -430,7 +423,7 @@ struct MailLevelReward }; typedef std::list<MailLevelReward> MailLevelRewardList; -typedef UNORDERED_MAP<uint8, MailLevelRewardList> MailLevelRewardMap; +typedef UNORDERED_MAP<uint8, MailLevelRewardList> MailLevelRewardContainer; // We assume the rate is in general the same for all three types below, but chose to keep three for scalability and customization struct RepRewardRate @@ -442,15 +435,15 @@ struct RepRewardRate struct ReputationOnKillEntry { - uint32 repfaction1; - uint32 repfaction2; - bool is_teamaward1; - uint32 reputation_max_cap1; - int32 repvalue1; - bool is_teamaward2; - uint32 reputation_max_cap2; - int32 repvalue2; - bool team_dependent; + uint32 RepFaction1; + uint32 RepFaction2; + uint32 ReputationMaxCap1; + int32 RepValue1; + uint32 ReputationMaxCap2; + int32 RepValue2; + bool IsTeamAward1; + bool IsTeamAward2; + bool TeamDependent; }; struct RepSpilloverTemplate @@ -494,12 +487,12 @@ struct GossipMenus ConditionList conditions; }; -typedef std::multimap<uint32, GossipMenus> GossipMenusMap; -typedef std::pair<GossipMenusMap::const_iterator, GossipMenusMap::const_iterator> GossipMenusMapBounds; -typedef std::pair<GossipMenusMap::iterator, GossipMenusMap::iterator> GossipMenusMapBoundsNonConst; -typedef std::multimap<uint32, GossipMenuItems> GossipMenuItemsMap; -typedef std::pair<GossipMenuItemsMap::const_iterator, GossipMenuItemsMap::const_iterator> GossipMenuItemsMapBounds; -typedef std::pair<GossipMenuItemsMap::iterator, GossipMenuItemsMap::iterator> GossipMenuItemsMapBoundsNonConst; +typedef std::multimap<uint32, GossipMenus> GossipMenusContainer; +typedef std::pair<GossipMenusContainer::const_iterator, GossipMenusContainer::const_iterator> GossipMenusMapBounds; +typedef std::pair<GossipMenusContainer::iterator, GossipMenusContainer::iterator> GossipMenusMapBoundsNonConst; +typedef std::multimap<uint32, GossipMenuItems> GossipMenuItemsContainer; +typedef std::pair<GossipMenuItemsContainer::const_iterator, GossipMenuItemsContainer::const_iterator> GossipMenuItemsMapBounds; +typedef std::pair<GossipMenuItemsContainer::iterator, GossipMenuItemsContainer::iterator> GossipMenuItemsMapBoundsNonConst; struct QuestPOIPoint { @@ -526,17 +519,17 @@ struct QuestPOI }; typedef std::vector<QuestPOI> QuestPOIVector; -typedef UNORDERED_MAP<uint32, QuestPOIVector> QuestPOIMap; +typedef UNORDERED_MAP<uint32, QuestPOIVector> QuestPOIContainer; struct GraveYardData { uint32 safeLocId; uint32 team; }; -typedef std::multimap<uint32, GraveYardData> GraveYardMap; +typedef std::multimap<uint32, GraveYardData> GraveYardContainer; -typedef UNORDERED_MAP<uint32, VendorItemData> CacheVendorItemMap; -typedef UNORDERED_MAP<uint32, TrainerSpellData> CacheTrainerSpellMap; +typedef UNORDERED_MAP<uint32, VendorItemData> CacheVendorItemContainer; +typedef UNORDERED_MAP<uint32, TrainerSpellData> CacheTrainerSpellContainer; enum SkillRangeType { @@ -584,7 +577,7 @@ struct DungeonEncounter }; typedef std::list<DungeonEncounter const*> DungeonEncounterList; -typedef UNORDERED_MAP<uint32, DungeonEncounterList> DungeonEncounterMap; +typedef UNORDERED_MAP<uint32, DungeonEncounterList> DungeonEncounterContainer; struct HotfixInfo { @@ -611,33 +604,33 @@ class ObjectMgr typedef UNORDERED_MAP<uint32, Quest*> QuestMap; - typedef UNORDERED_MAP<uint32, AreaTrigger> AreaTriggerMap; + typedef UNORDERED_MAP<uint32, AreaTrigger> AreaTriggerContainer; - typedef UNORDERED_MAP<uint32, uint32> AreaTriggerScriptMap; + typedef UNORDERED_MAP<uint32, uint32> AreaTriggerScriptContainer; - typedef UNORDERED_MAP<uint32, AccessRequirement> AccessRequirementMap; + typedef UNORDERED_MAP<uint32, AccessRequirement> AccessRequirementContainer; - typedef UNORDERED_MAP<uint32, RepRewardRate > RepRewardRateMap; - typedef UNORDERED_MAP<uint32, ReputationOnKillEntry> RepOnKillMap; - typedef UNORDERED_MAP<uint32, RepSpilloverTemplate> RepSpilloverTemplateMap; + typedef UNORDERED_MAP<uint32, RepRewardRate > RepRewardRateContainer; + typedef UNORDERED_MAP<uint32, ReputationOnKillEntry> RepOnKillContainer; + typedef UNORDERED_MAP<uint32, RepSpilloverTemplate> RepSpilloverTemplateContainer; - typedef UNORDERED_MAP<uint32, PointOfInterest> PointOfInterestMap; + typedef UNORDERED_MAP<uint32, PointOfInterest> PointOfInterestContainer; - typedef std::vector<std::string> ScriptNameMap; + typedef std::vector<std::string> ScriptNameContainer; typedef std::map<uint32, uint32> CharacterConversionMap; Player* GetPlayerByLowGUID(uint32 lowguid) const; GameObjectTemplate const* GetGameObjectTemplate(uint32 entry); - GameObjectTemplateContainer const* GetGameObjectTemplates() { return &GameObjectTemplateStore; } + GameObjectTemplateContainer const* GetGameObjectTemplates() { return &_gameObjectTemplateStore; } int LoadReferenceVendor(int32 vendor, int32 item_id, std::set<uint32> *skip_vendors); void LoadGameObjectTemplate(); void AddGameobjectInfo(GameObjectTemplate* goinfo); CreatureTemplate const* GetCreatureTemplate(uint32 entry); - CreatureTemplateContainer const* GetCreatureTemplates() { return &CreatureTemplateStore; } + CreatureTemplateContainer const* GetCreatureTemplates() { return &_creatureTemplateStore; } CreatureModelInfo const* GetCreatureModelInfo(uint32 modelId); CreatureModelInfo const* GetCreatureModelRandomGender(uint32* displayID); static uint32 ChooseDisplayId(uint32 team, const CreatureTemplate* cinfo, const CreatureData* data = NULL); @@ -646,12 +639,12 @@ class ObjectMgr CreatureAddon const* GetCreatureAddon(uint32 lowguid); CreatureAddon const* GetCreatureTemplateAddon(uint32 entry); ItemTemplate const* GetItemTemplate(uint32 entry); - ItemTemplateContainer const* GetItemTemplateStore() { return &ItemTemplateStore; } + ItemTemplateContainer const* GetItemTemplateStore() { return &_itemTemplateStore; } ItemSetNameEntry const* GetItemSetNameEntry(uint32 itemId) { - ItemSetNameMap::iterator itr = mItemSetNameMap.find(itemId); - if (itr != mItemSetNameMap.end()) + ItemSetNameContainer::iterator itr = _itemSetNameStore.find(itemId); + if (itr != _itemSetNameStore.end()) return &itr->second; return NULL; } @@ -664,7 +657,7 @@ class ObjectMgr { if (class_ >= MAX_CLASSES) return NULL; - return &playerClassInfo[class_]; + return &_playerClassInfo[class_]; } void GetPlayerClassLevelInfo(uint32 class_, uint8 level, PlayerClassLevelInfo* info) const; @@ -674,7 +667,7 @@ class ObjectMgr return NULL; if (class_ >= MAX_CLASSES) return NULL; - PlayerInfo const* info = &playerInfo[race][class_]; + PlayerInfo const* info = &_playerInfo[race][class_]; if (info->displayId_m == 0 || info->displayId_f == 0) return NULL; return info; @@ -694,28 +687,28 @@ class ObjectMgr Quest const* GetQuestTemplate(uint32 quest_id) const { - QuestMap::const_iterator itr = mQuestTemplates.find(quest_id); - return itr != mQuestTemplates.end() ? itr->second : NULL; + QuestMap::const_iterator itr = _questTemplates.find(quest_id); + return itr != _questTemplates.end() ? itr->second : NULL; } - QuestMap const& GetQuestTemplates() const { return mQuestTemplates; } + QuestMap const& GetQuestTemplates() const { return _questTemplates; } uint32 GetQuestForAreaTrigger(uint32 Trigger_ID) const { - QuestAreaTriggerMap::const_iterator itr = mQuestAreaTriggerMap.find(Trigger_ID); - if (itr != mQuestAreaTriggerMap.end()) + QuestAreaTriggerContainer::const_iterator itr = _questAreaTriggerStore.find(Trigger_ID); + if (itr != _questAreaTriggerStore.end()) return itr->second; return 0; } bool IsTavernAreaTrigger(uint32 Trigger_ID) const { - return mTavernAreaTriggerSet.find(Trigger_ID) != mTavernAreaTriggerSet.end(); + return _tavernAreaTriggerStore.find(Trigger_ID) != _tavernAreaTriggerStore.end(); } bool IsGameObjectForQuests(uint32 entry) const { - return mGameObjectForQuestSet.find(entry) != mGameObjectForQuestSet.end(); + return _gameObjectForQuestStore.find(entry) != _gameObjectForQuestStore.end(); } GossipText const* GetGossipText(uint32 Text_ID) const; @@ -729,16 +722,16 @@ class ObjectMgr AreaTrigger const* GetAreaTrigger(uint32 trigger) const { - AreaTriggerMap::const_iterator itr = mAreaTriggers.find(trigger); - if (itr != mAreaTriggers.end()) + AreaTriggerContainer::const_iterator itr = _areaTriggerStore.find(trigger); + if (itr != _areaTriggerStore.end()) return &itr->second; return NULL; } AccessRequirement const* GetAccessRequirement(uint32 mapid, Difficulty difficulty) const { - AccessRequirementMap::const_iterator itr = mAccessRequirements.find(MAKE_PAIR32(mapid, difficulty)); - if (itr != mAccessRequirements.end()) + AccessRequirementContainer::const_iterator itr = _accessRequirementStore.find(MAKE_PAIR32(mapid, difficulty)); + if (itr != _accessRequirementStore.end()) return &itr->second; return NULL; } @@ -751,8 +744,8 @@ class ObjectMgr RepRewardRate const* GetRepRewardRate(uint32 factionId) const { - RepRewardRateMap::const_iterator itr = m_RepRewardRateMap.find(factionId); - if (itr != m_RepRewardRateMap.end()) + RepRewardRateContainer::const_iterator itr = _repRewardRateStore.find(factionId); + if (itr != _repRewardRateStore.end()) return &itr->second; return NULL; @@ -760,16 +753,16 @@ class ObjectMgr ReputationOnKillEntry const* GetReputationOnKilEntry(uint32 id) const { - RepOnKillMap::const_iterator itr = mRepOnKill.find(id); - if (itr != mRepOnKill.end()) + RepOnKillContainer::const_iterator itr = _repOnKillStore.find(id); + if (itr != _repOnKillStore.end()) return &itr->second; return NULL; } RepSpilloverTemplate const* GetRepSpilloverTemplate(uint32 factionId) const { - RepSpilloverTemplateMap::const_iterator itr = m_RepSpilloverTemplateMap.find(factionId); - if (itr != m_RepSpilloverTemplateMap.end()) + RepSpilloverTemplateContainer::const_iterator itr = _repSpilloverTemplateStore.find(factionId); + if (itr != _repSpilloverTemplateStore.end()) return &itr->second; return NULL; @@ -777,16 +770,16 @@ class ObjectMgr PointOfInterest const* GetPointOfInterest(uint32 id) const { - PointOfInterestMap::const_iterator itr = mPointsOfInterest.find(id); - if (itr != mPointsOfInterest.end()) + PointOfInterestContainer::const_iterator itr = _pointsOfInterestStore.find(id); + if (itr != _pointsOfInterestStore.end()) return &itr->second; return NULL; } QuestPOIVector const* GetQuestPOIVector(uint32 questId) { - QuestPOIMap::const_iterator itr = mQuestPOIMap.find(questId); - if (itr != mQuestPOIMap.end()) + QuestPOIContainer::const_iterator itr = _questPOIStore.find(questId); + if (itr != _questPOIStore.end()) return &itr->second; return NULL; } @@ -795,8 +788,8 @@ class ObjectMgr DungeonEncounterList const* GetDungeonEncounterList(uint32 mapId, Difficulty difficulty) { - UNORDERED_MAP<uint32, DungeonEncounterList>::const_iterator itr = mDungeonEncounters.find(MAKE_PAIR32(mapId, difficulty)); - if (itr != mDungeonEncounters.end()) + UNORDERED_MAP<uint32, DungeonEncounterList>::const_iterator itr = _dungeonEncounterStore.find(MAKE_PAIR32(mapId, difficulty)); + if (itr != _dungeonEncounterStore.end()) return &itr->second; return NULL; } @@ -820,32 +813,32 @@ class ObjectMgr QuestRelations* GetGOQuestRelationMap() { - return &mGOQuestRelations; + return &_goQuestRelations; } QuestRelationBounds GetGOQuestRelationBounds(uint32 go_entry) { - return mGOQuestRelations.equal_range(go_entry); + return _goQuestRelations.equal_range(go_entry); } QuestRelationBounds GetGOQuestInvolvedRelationBounds(uint32 go_entry) { - return mGOQuestInvolvedRelations.equal_range(go_entry); + return _goQuestInvolvedRelations.equal_range(go_entry); } QuestRelations* GetCreatureQuestRelationMap() { - return &mCreatureQuestRelations; + return &_creatureQuestRelations; } QuestRelationBounds GetCreatureQuestRelationBounds(uint32 creature_entry) { - return mCreatureQuestRelations.equal_range(creature_entry); + return _creatureQuestRelations.equal_range(creature_entry); } QuestRelationBounds GetCreatureQuestInvolvedRelationBounds(uint32 creature_entry) { - return mCreatureQuestInvolvedRelations.equal_range(creature_entry); + return _creatureQuestInvolvedRelations.equal_range(creature_entry); } void LoadGameObjectScripts(); @@ -937,8 +930,8 @@ class ObjectMgr int32 GetFishingBaseSkillLevel(uint32 entry) const { - FishingBaseSkillMap::const_iterator itr = mFishingBaseForArea.find(entry); - return itr != mFishingBaseForArea.end() ? itr->second : 0; + FishingBaseSkillContainer::const_iterator itr = _fishingBaseForAreaStore.find(entry); + return itr != _fishingBaseForAreaStore.end() ? itr->second : 0; } void ReturnOrDeleteOldMails(bool serverUp); @@ -957,8 +950,8 @@ class ObjectMgr MailLevelReward const* GetMailLevelReward(uint32 level, uint32 raceMask) { - MailLevelRewardMap::const_iterator map_itr = m_mailLevelRewardMap.find(level); - if (map_itr == m_mailLevelRewardMap.end()) + MailLevelRewardContainer::const_iterator map_itr = _mailLevelRewardStore.find(level); + if (map_itr == _mailLevelRewardStore.end()) return NULL; for (MailLevelRewardList::const_iterator set_itr = map_itr->second.begin(); set_itr != map_itr->second.end(); ++set_itr) @@ -970,81 +963,81 @@ class ObjectMgr CellObjectGuids const& GetCellObjectGuids(uint16 mapid, uint8 spawnMode, uint32 cell_id) { - return mMapObjectGuids[MAKE_PAIR32(mapid, spawnMode)][cell_id]; + return _mapObjectGuidsStore[MAKE_PAIR32(mapid, spawnMode)][cell_id]; } CreatureData const* GetCreatureData(uint32 guid) const { - CreatureDataMap::const_iterator itr = mCreatureDataMap.find(guid); - if (itr == mCreatureDataMap.end()) return NULL; + CreatureDataContainer::const_iterator itr = _creatureDataStore.find(guid); + if (itr == _creatureDataStore.end()) return NULL; return &itr->second; } - CreatureData& NewOrExistCreatureData(uint32 guid) { return mCreatureDataMap[guid]; } + CreatureData& NewOrExistCreatureData(uint32 guid) { return _creatureDataStore[guid]; } void DeleteCreatureData(uint32 guid); uint64 GetLinkedRespawnGuid(uint64 guid) const { - LinkedRespawnMap::const_iterator itr = mLinkedRespawnMap.find(guid); - if (itr == mLinkedRespawnMap.end()) return 0; + LinkedRespawnContainer::const_iterator itr = _linkedRespawnStore.find(guid); + if (itr == _linkedRespawnStore.end()) return 0; return itr->second; } CreatureLocale const* GetCreatureLocale(uint32 entry) const { - CreatureLocaleMap::const_iterator itr = mCreatureLocaleMap.find(entry); - if (itr == mCreatureLocaleMap.end()) return NULL; + CreatureLocaleContainer::const_iterator itr = _creatureLocaleStore.find(entry); + if (itr == _creatureLocaleStore.end()) return NULL; return &itr->second; } GameObjectLocale const* GetGameObjectLocale(uint32 entry) const { - GameObjectLocaleMap::const_iterator itr = mGameObjectLocaleMap.find(entry); - if (itr == mGameObjectLocaleMap.end()) return NULL; + GameObjectLocaleContainer::const_iterator itr = _gameObjectLocaleStore.find(entry); + if (itr == _gameObjectLocaleStore.end()) return NULL; return &itr->second; } ItemLocale const* GetItemLocale(uint32 entry) const { - ItemLocaleMap::const_iterator itr = mItemLocaleMap.find(entry); - if (itr == mItemLocaleMap.end()) return NULL; + ItemLocaleContainer::const_iterator itr = _itemLocaleStore.find(entry); + if (itr == _itemLocaleStore.end()) return NULL; return &itr->second; } ItemSetNameLocale const* GetItemSetNameLocale(uint32 entry) const { - ItemSetNameLocaleMap::const_iterator itr = mItemSetNameLocaleMap.find(entry); - if (itr == mItemSetNameLocaleMap.end())return NULL; + ItemSetNameLocaleContainer::const_iterator itr = _itemSetNameLocaleStore.find(entry); + if (itr == _itemSetNameLocaleStore.end())return NULL; return &itr->second; } QuestLocale const* GetQuestLocale(uint32 entry) const { - QuestLocaleMap::const_iterator itr = mQuestLocaleMap.find(entry); - if (itr == mQuestLocaleMap.end()) return NULL; + QuestLocaleContainer::const_iterator itr = _questLocaleStore.find(entry); + if (itr == _questLocaleStore.end()) return NULL; return &itr->second; } NpcTextLocale const* GetNpcTextLocale(uint32 entry) const { - NpcTextLocaleMap::const_iterator itr = mNpcTextLocaleMap.find(entry); - if (itr == mNpcTextLocaleMap.end()) return NULL; + NpcTextLocaleContainer::const_iterator itr = _npcTextLocaleStore.find(entry); + if (itr == _npcTextLocaleStore.end()) return NULL; return &itr->second; } PageTextLocale const* GetPageTextLocale(uint32 entry) const { - PageTextLocaleMap::const_iterator itr = mPageTextLocaleMap.find(entry); - if (itr == mPageTextLocaleMap.end()) return NULL; + PageTextLocaleContainer::const_iterator itr = _pageTextLocaleStore.find(entry); + if (itr == _pageTextLocaleStore.end()) return NULL; return &itr->second; } GossipMenuItemsLocale const* GetGossipMenuItemsLocale(uint32 entry) const { - GossipMenuItemsLocaleMap::const_iterator itr = mGossipMenuItemsLocaleMap.find(entry); - if (itr == mGossipMenuItemsLocaleMap.end()) return NULL; + GossipMenuItemsLocaleContainer::const_iterator itr = _gossipMenuItemsLocaleStore.find(entry); + if (itr == _gossipMenuItemsLocaleStore.end()) return NULL; return &itr->second; } PointOfInterestLocale const* GetPointOfInterestLocale(uint32 poi_id) const { - PointOfInterestLocaleMap::const_iterator itr = mPointOfInterestLocaleMap.find(poi_id); - if (itr == mPointOfInterestLocaleMap.end()) return NULL; + PointOfInterestLocaleContainer::const_iterator itr = _pointOfInterestLocaleStore.find(poi_id); + if (itr == _pointOfInterestLocaleStore.end()) return NULL; return &itr->second; } bool IsGoOfSpecificEntrySpawned(uint32 entry) const { - for (GameObjectDataMap::const_iterator it = mGameObjectDataMap.begin(); it != mGameObjectDataMap.end(); ++it) + for (GameObjectDataContainer::const_iterator it = _gameObjectDataStore.begin(); it != _gameObjectDataStore.end(); ++it) if (it->second.id == entry) return true; @@ -1053,17 +1046,17 @@ class ObjectMgr GameObjectData const* GetGOData(uint32 guid) const { - GameObjectDataMap::const_iterator itr = mGameObjectDataMap.find(guid); - if (itr == mGameObjectDataMap.end()) return NULL; + GameObjectDataContainer::const_iterator itr = _gameObjectDataStore.find(guid); + if (itr == _gameObjectDataStore.end()) return NULL; return &itr->second; } - GameObjectData& NewGOData(uint32 guid) { return mGameObjectDataMap[guid]; } + GameObjectData& NewGOData(uint32 guid) { return _gameObjectDataStore[guid]; } void DeleteGOData(uint32 guid); TrinityStringLocale const* GetTrinityStringLocale(int32 entry) const { - TrinityStringLocaleMap::const_iterator itr = mTrinityStringLocaleMap.find(entry); - if (itr == mTrinityStringLocaleMap.end()) return NULL; + TrinityStringLocaleContainer::const_iterator itr = _trinityStringLocaleStore.find(entry); + if (itr == _trinityStringLocaleStore.end()) return NULL; return &itr->second; } const char *GetTrinityString(int32 entry, LocaleConstant locale_idx) const; @@ -1090,15 +1083,15 @@ class ObjectMgr time_t GetCreatureRespawnTime(uint32 loguid, uint32 instance) { - TRINITY_GUARD(ACE_Thread_Mutex, m_CreatureRespawnTimesMtx); - return mCreatureRespawnTimes[MAKE_PAIR64(loguid, instance)]; + TRINITY_GUARD(ACE_Thread_Mutex, _creatureRespawnTimesMutex); + return _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)]; } void SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t); void RemoveCreatureRespawnTime(uint32 loguid, uint32 instance); time_t GetGORespawnTime(uint32 loguid, uint32 instance) { - TRINITY_GUARD(ACE_Thread_Mutex, m_GORespawnTimesMtx); - return mGORespawnTimes[MAKE_PAIR64(loguid, instance)]; + TRINITY_GUARD(ACE_Thread_Mutex, _goRespawnTimesMutex); + return _goRespawnTimes[MAKE_PAIR64(loguid, instance)]; } void SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t); void RemoveGORespawnTime(uint32 loguid, uint32 instance); @@ -1126,19 +1119,19 @@ class ObjectMgr GameTele const* GetGameTele(uint32 id) const { - GameTeleMap::const_iterator itr = m_GameTeleMap.find(id); - if (itr == m_GameTeleMap.end()) return NULL; + GameTeleContainer::const_iterator itr = _gameTeleStore.find(id); + if (itr == _gameTeleStore.end()) return NULL; return &itr->second; } GameTele const* GetGameTele(const std::string& name) const; - GameTeleMap const& GetGameTeleMap() const { return m_GameTeleMap; } + GameTeleContainer const& GetGameTeleMap() const { return _gameTeleStore; } bool AddGameTele(GameTele& data); bool DeleteGameTele(const std::string& name); TrainerSpellData const* GetNpcTrainerSpells(uint32 entry) const { - CacheTrainerSpellMap::const_iterator iter = m_mCacheTrainerSpellMap.find(entry); - if (iter == m_mCacheTrainerSpellMap.end()) + CacheTrainerSpellContainer::const_iterator iter = _cacheTrainerSpellStore.find(entry); + if (iter == _cacheTrainerSpellStore.end()) return NULL; return &iter->second; @@ -1146,8 +1139,8 @@ class ObjectMgr VendorItemData const* GetNpcVendorItemList(uint32 entry) const { - CacheVendorItemMap::const_iterator iter = m_mCacheVendorItemMap.find(entry); - if (iter == m_mCacheVendorItemMap.end()) + CacheVendorItemContainer::const_iterator iter = _cacheVendorItemStore.find(entry); + if (iter == _cacheVendorItemStore.end()) return NULL; return &iter->second; @@ -1157,36 +1150,36 @@ class ObjectMgr 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 LoadScriptNames(); - ScriptNameMap &GetScriptNames() { return m_scriptNames; } - const char * GetScriptName(uint32 id) { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; } + ScriptNameContainer &GetScriptNames() { return _scriptNamesStore; } + const char * GetScriptName(uint32 id) { return id < _scriptNamesStore.size() ? _scriptNamesStore[id].c_str() : ""; } uint32 GetScriptId(const char *name); SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const { - return SpellClickInfoMapBounds(mSpellClickInfoMap.lower_bound(creature_id), mSpellClickInfoMap.upper_bound(creature_id)); + return SpellClickInfoMapBounds(_spellClickInfoStore.lower_bound(creature_id), _spellClickInfoStore.upper_bound(creature_id)); } GossipMenusMapBounds GetGossipMenusMapBounds(uint32 uiMenuId) const { - return GossipMenusMapBounds(m_mGossipMenusMap.lower_bound(uiMenuId), m_mGossipMenusMap.upper_bound(uiMenuId)); + return GossipMenusMapBounds(_gossipMenusStore.lower_bound(uiMenuId), _gossipMenusStore.upper_bound(uiMenuId)); } GossipMenusMapBoundsNonConst GetGossipMenusMapBoundsNonConst(uint32 uiMenuId) { - return GossipMenusMapBoundsNonConst(m_mGossipMenusMap.lower_bound(uiMenuId), m_mGossipMenusMap.upper_bound(uiMenuId)); + return GossipMenusMapBoundsNonConst(_gossipMenusStore.lower_bound(uiMenuId), _gossipMenusStore.upper_bound(uiMenuId)); } GossipMenuItemsMapBounds GetGossipMenuItemsMapBounds(uint32 uiMenuId) const { - return GossipMenuItemsMapBounds(m_mGossipMenuItemsMap.lower_bound(uiMenuId), m_mGossipMenuItemsMap.upper_bound(uiMenuId)); + return GossipMenuItemsMapBounds(_gossipMenuItemsStore.lower_bound(uiMenuId), _gossipMenuItemsStore.upper_bound(uiMenuId)); } GossipMenuItemsMapBoundsNonConst GetGossipMenuItemsMapBoundsNonConst(uint32 uiMenuId) { - return GossipMenuItemsMapBoundsNonConst(m_mGossipMenuItemsMap.lower_bound(uiMenuId), m_mGossipMenuItemsMap.upper_bound(uiMenuId)); + return GossipMenuItemsMapBoundsNonConst(_gossipMenuItemsStore.lower_bound(uiMenuId), _gossipMenuItemsStore.upper_bound(uiMenuId)); } // for wintergrasp only - GraveYardMap mGraveYardMap; + GraveYardContainer GraveYardStore; static void AddLocaleString(const std::string& s, LocaleConstant locale, StringVector& data); static inline void GetLocaleString(const StringVector& data, int loc_idx, std::string& value) @@ -1195,10 +1188,10 @@ class ObjectMgr value = data[loc_idx]; } - CharacterConversionMap factionchange_achievements; - CharacterConversionMap factionchange_items; - CharacterConversionMap factionchange_spells; - CharacterConversionMap factionchange_reputations; + CharacterConversionMap FactionChange_Achievements; + CharacterConversionMap FactionChange_Items; + CharacterConversionMap FactionChange_Spells; + CharacterConversionMap FactionChange_Reputation; void LoadFactionChangeAchievements(); void LoadFactionChangeItems(); @@ -1210,80 +1203,73 @@ class ObjectMgr private: // first free id for selected id type - uint32 m_auctionid; - uint64 m_equipmentSetGuid; - uint32 m_ItemTextId; - uint32 m_mailid; - uint32 m_hiPetNumber; + uint32 _auctionId; + uint64 _equipmentSetGuid; + uint32 _itemTextId; + uint32 _mailId; + uint32 _hiPetNumber; // first free low guid for selected guid type - uint32 m_hiCharGuid; - uint32 m_hiCreatureGuid; - uint32 m_hiPetGuid; - uint32 m_hiVehicleGuid; - uint32 m_hiItemGuid; - uint32 m_hiGoGuid; - uint32 m_hiDoGuid; - uint32 m_hiCorpseGuid; - uint32 m_hiMoTransGuid; - - QuestMap mQuestTemplates; - - typedef UNORDERED_MAP<uint32, GossipText> GossipTextMap; - typedef UNORDERED_MAP<uint32, uint32> QuestAreaTriggerMap; - typedef std::set<uint32> TavernAreaTriggerSet; - typedef std::set<uint32> GameObjectForQuestSet; - - QuestAreaTriggerMap mQuestAreaTriggerMap; - TavernAreaTriggerSet mTavernAreaTriggerSet; - GameObjectForQuestSet mGameObjectForQuestSet; - GossipTextMap mGossipText; - AreaTriggerMap mAreaTriggers; - AreaTriggerScriptMap mAreaTriggerScripts; - AccessRequirementMap mAccessRequirements; - DungeonEncounterMap mDungeonEncounters; - - RepRewardRateMap m_RepRewardRateMap; - RepOnKillMap mRepOnKill; - RepSpilloverTemplateMap m_RepSpilloverTemplateMap; - - GossipMenusMap m_mGossipMenusMap; - GossipMenuItemsMap m_mGossipMenuItemsMap; - PointOfInterestMap mPointsOfInterest; - - QuestPOIMap mQuestPOIMap; - - QuestRelations mGOQuestRelations; - QuestRelations mGOQuestInvolvedRelations; - QuestRelations mCreatureQuestRelations; - QuestRelations mCreatureQuestInvolvedRelations; + uint32 _hiCharGuid; + uint32 _hiCreatureGuid; + uint32 _hiPetGuid; + uint32 _hiVehicleGuid; + uint32 _hiItemGuid; + uint32 _hiGoGuid; + uint32 _hiDoGuid; + uint32 _hiCorpseGuid; + uint32 _hiMoTransGuid; + + QuestMap _questTemplates; + + typedef UNORDERED_MAP<uint32, GossipText> GossipTextContainer; + typedef UNORDERED_MAP<uint32, uint32> QuestAreaTriggerContainer; + typedef std::set<uint32> TavernAreaTriggerContainer; + typedef std::set<uint32> GameObjectForQuestContainer; + + QuestAreaTriggerContainer _questAreaTriggerStore; + TavernAreaTriggerContainer _tavernAreaTriggerStore; + GameObjectForQuestContainer _gameObjectForQuestStore; + GossipTextContainer _gossipTextStore; + AreaTriggerContainer _areaTriggerStore; + AreaTriggerScriptContainer _areaTriggerScriptStore; + AccessRequirementContainer _accessRequirementStore; + DungeonEncounterContainer _dungeonEncounterStore; + + RepRewardRateContainer _repRewardRateStore; + RepOnKillContainer _repOnKillStore; + RepSpilloverTemplateContainer _repSpilloverTemplateStore; + + GossipMenusContainer _gossipMenusStore; + GossipMenuItemsContainer _gossipMenuItemsStore; + PointOfInterestContainer _pointsOfInterestStore; + + QuestPOIContainer _questPOIStore; + + QuestRelations _goQuestRelations; + QuestRelations _goQuestInvolvedRelations; + QuestRelations _creatureQuestRelations; + QuestRelations _creatureQuestInvolvedRelations; //character reserved names - typedef std::set<std::wstring> ReservedNamesMap; - ReservedNamesMap m_ReservedNames; + typedef std::set<std::wstring> ReservedNamesContainer; + ReservedNamesContainer _reservedNamesStore; -// GraveYardMap mGraveYardMap; + GameTeleContainer _gameTeleStore; - GameTeleMap m_GameTeleMap; + ScriptNameContainer _scriptNamesStore; - ScriptNameMap m_scriptNames; + SpellClickInfoContainer _spellClickInfoStore; - SpellClickInfoMap mSpellClickInfoMap; + SpellScriptsContainer _spellScriptsStore; - SpellScriptsMap mSpellScripts; - - ItemRequiredTargetMap m_ItemRequiredTarget; - - VehicleAccessoryMap m_VehicleTemplateAccessoryMap; - VehicleAccessoryMap m_VehicleAccessoryMap; - - typedef std::vector<LocaleConstant> LocalForIndex; - LocalForIndex m_LocalForIndex; + VehicleAccessoryContainer _vehicleTemplateAccessoryStore; + VehicleAccessoryContainer _vehicleAccessoryStore; LocaleConstant DBCLocaleIndex; - PageTextContainer PageTextStore; - InstanceTemplateContainer InstanceTemplateStore; + PageTextContainer _pageTextStore; + InstanceTemplateContainer _instanceTemplateStore; private: void LoadScripts(ScriptsType type); @@ -1291,67 +1277,68 @@ class ObjectMgr void LoadQuestRelationsHelper(QuestRelations& map, std::string table, bool starter, bool go); void PlayerCreateInfoAddItemHelper(uint32 race_, uint32 class_, uint32 itemId, int32 count); - MailLevelRewardMap m_mailLevelRewardMap; + MailLevelRewardContainer _mailLevelRewardStore; - CreatureBaseStatsMap m_creatureBaseStatsMap; + CreatureBaseStatsContainer _creatureBaseStatsStore; - typedef std::map<uint32, PetLevelInfo*> PetLevelInfoMap; - // PetLevelInfoMap[creature_id][level] - PetLevelInfoMap petInfo; // [creature_id][level] + typedef std::map<uint32, PetLevelInfo*> PetLevelInfoContainer; + // PetLevelInfoContainer[creature_id][level] + PetLevelInfoContainer _petInfoStore; // [creature_id][level] - PlayerClassInfo playerClassInfo[MAX_CLASSES]; + PlayerClassInfo _playerClassInfo[MAX_CLASSES]; void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const; - PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES]; + + PlayerInfo _playerInfo[MAX_RACES][MAX_CLASSES]; typedef std::vector<uint32> PlayerXPperLevel; // [level] - PlayerXPperLevel mPlayerXPperLevel; - - typedef std::map<uint32, uint32> BaseXPMap; // [area level][base xp] - BaseXPMap mBaseXPTable; - - typedef std::map<uint32, int32> FishingBaseSkillMap; // [areaId][base skill level] - FishingBaseSkillMap mFishingBaseForArea; - - typedef std::map<uint32, StringVector> HalfNameMap; - HalfNameMap PetHalfName0; - HalfNameMap PetHalfName1; - - typedef UNORDERED_MAP<uint32, ItemSetNameEntry> ItemSetNameMap; - ItemSetNameMap mItemSetNameMap; - - MapObjectGuids mMapObjectGuids; - CreatureDataMap mCreatureDataMap; - CreatureTemplateContainer CreatureTemplateStore; - CreatureModelContainer CreatureModelStore; - CreatureAddonContainer CreatureAddonStore; - CreatureAddonContainer CreatureTemplateAddonStore; - EquipmentInfoContainer EquipmentInfoStore; - LinkedRespawnMap mLinkedRespawnMap; - CreatureLocaleMap mCreatureLocaleMap; - GameObjectDataMap mGameObjectDataMap; - GameObjectLocaleMap mGameObjectLocaleMap; - GameObjectTemplateContainer GameObjectTemplateStore; - - ItemTemplateContainer ItemTemplateStore; - ItemLocaleMap mItemLocaleMap; - ItemSetNameLocaleMap mItemSetNameLocaleMap; - QuestLocaleMap mQuestLocaleMap; - NpcTextLocaleMap mNpcTextLocaleMap; - PageTextLocaleMap mPageTextLocaleMap; - TrinityStringLocaleMap mTrinityStringLocaleMap; - GossipMenuItemsLocaleMap mGossipMenuItemsLocaleMap; - PointOfInterestLocaleMap mPointOfInterestLocaleMap; - RespawnTimes mCreatureRespawnTimes; - ACE_Thread_Mutex m_CreatureRespawnTimesMtx; - RespawnTimes mGORespawnTimes; - ACE_Thread_Mutex m_GORespawnTimesMtx; - - CacheVendorItemMap m_mCacheVendorItemMap; - CacheTrainerSpellMap m_mCacheTrainerSpellMap; - - std::set<uint32> difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate - std::set<uint32> hasDifficultyEntries[MAX_DIFFICULTY - 1]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate + PlayerXPperLevel _playerXPperLevel; + + typedef std::map<uint32, uint32> BaseXPContainer; // [area level][base xp] + BaseXPContainer _baseXPTable; + + typedef std::map<uint32, int32> FishingBaseSkillContainer; // [areaId][base skill level] + FishingBaseSkillContainer _fishingBaseForAreaStore; + + typedef std::map<uint32, StringVector> HalfNameContainer; + HalfNameContainer _petHalfName0; + HalfNameContainer _petHalfName1; + + typedef UNORDERED_MAP<uint32, ItemSetNameEntry> ItemSetNameContainer; + ItemSetNameContainer _itemSetNameStore; + + MapObjectGuids _mapObjectGuidsStore; + CreatureDataContainer _creatureDataStore; + CreatureTemplateContainer _creatureTemplateStore; + CreatureModelContainer _creatureModelStore; + CreatureAddonContainer _creatureAddonStore; + CreatureAddonContainer _creatureTemplateAddonStore; + EquipmentInfoContainer _equipmentInfoStore; + LinkedRespawnContainer _linkedRespawnStore; + CreatureLocaleContainer _creatureLocaleStore; + GameObjectDataContainer _gameObjectDataStore; + GameObjectLocaleContainer _gameObjectLocaleStore; + GameObjectTemplateContainer _gameObjectTemplateStore; + + ItemTemplateContainer _itemTemplateStore; + ItemLocaleContainer _itemLocaleStore; + ItemSetNameLocaleContainer _itemSetNameLocaleStore; + QuestLocaleContainer _questLocaleStore; + NpcTextLocaleContainer _npcTextLocaleStore; + PageTextLocaleContainer _pageTextLocaleStore; + TrinityStringLocaleContainer _trinityStringLocaleStore; + GossipMenuItemsLocaleContainer _gossipMenuItemsLocaleStore; + PointOfInterestLocaleContainer _pointOfInterestLocaleStore; + RespawnTimes _creatureRespawnTimes; + ACE_Thread_Mutex _creatureRespawnTimesMutex; + RespawnTimes _goRespawnTimes; + ACE_Thread_Mutex _goRespawnTimesMutex; + + CacheVendorItemContainer _cacheVendorItemStore; + CacheTrainerSpellContainer _cacheTrainerSpellStore; + + std::set<uint32> _difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate + std::set<uint32> _hasDifficultyEntries[MAX_DIFFICULTY - 1]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate enum CreatureLinkedRespawnType { diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h index 8651680cb49..d096bb7ab63 100644 --- a/src/server/game/Grids/GridDefines.h +++ b/src/server/game/Grids/GridDefines.h @@ -65,6 +65,16 @@ typedef GridRefManager<DynamicObject> DynamicObjectMapType; typedef GridRefManager<GameObject> GameObjectMapType; typedef GridRefManager<Player> PlayerMapType; +enum GridMapTypeMask +{ + GRID_MAP_TYPE_MASK_CORPSE = 0x01, + GRID_MAP_TYPE_MASK_CREATURE = 0x02, + GRID_MAP_TYPE_MASK_DYNAMICOBJECT = 0x04, + GRID_MAP_TYPE_MASK_GAMEOBJECT = 0x08, + GRID_MAP_TYPE_MASK_PLAYER = 0x10, + GRID_MAP_TYPE_MASK_ALL = 0x1F +}; + typedef Grid<Player, AllWorldObjectTypes, AllGridObjectTypes> GridType; typedef NGrid<MAX_NUMBER_OF_CELLS, Player, AllWorldObjectTypes, AllGridObjectTypes> NGridType; diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp index 2446e9d4276..17d3066e64d 100755 --- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -343,24 +343,17 @@ bool AnyDeadUnitObjectInRangeCheck::operator()(Creature* u) bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Player* u) { - return AnyDeadUnitObjectInRangeCheck::operator()(u) - && (i_spellInfo->CheckTarget(i_searchObj, u, true) == SPELL_CAST_OK) - && i_searchObj->IsTargetMatchingCheck(u, i_check); + return AnyDeadUnitObjectInRangeCheck::operator()(u) && i_check(u); } bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Corpse* u) { - Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); - return owner && AnyDeadUnitObjectInRangeCheck::operator()(u) - && (i_spellInfo->CheckTarget(i_searchObj, owner, true) == SPELL_CAST_OK) - && i_searchObj->IsTargetMatchingCheck(owner, i_check); + return AnyDeadUnitObjectInRangeCheck::operator()(u) && i_check(u); } bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Creature* u) { - return AnyDeadUnitObjectInRangeCheck::operator()(u) - && (i_spellInfo->CheckTarget(i_searchObj, u, true) == SPELL_CAST_OK) - && i_searchObj->IsTargetMatchingCheck(u, i_check); + return AnyDeadUnitObjectInRangeCheck::operator()(u) && i_check(u); } template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &); diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 4bec8b2e897..48b9860eb0b 100755 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -30,6 +30,7 @@ #include "Player.h" #include "Unit.h" #include "CreatureAI.h" +#include "Spell.h" class Player; //class Map; @@ -168,12 +169,33 @@ namespace Trinity template<class Check> struct WorldObjectSearcher { + uint32 i_mapTypeMask; uint32 i_phaseMask; WorldObject* &i_object; Check &i_check; - WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {} + WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL) + : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {} + + void Visit(GameObjectMapType &m); + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &m); + void Visit(DynamicObjectMapType &m); + + template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {} + }; + + template<class Check> + struct WorldObjectLastSearcher + { + uint32 i_mapTypeMask; + uint32 i_phaseMask; + WorldObject* &i_object; + Check &i_check; + + WorldObjectLastSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL) + : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {} void Visit(GameObjectMapType &m); void Visit(PlayerMapType &m); @@ -187,12 +209,13 @@ namespace Trinity template<class Check> struct WorldObjectListSearcher { + uint32 i_mapTypeMask; uint32 i_phaseMask; std::list<WorldObject*> &i_objects; Check& i_check; - WorldObjectListSearcher(WorldObject const* searcher, std::list<WorldObject*> &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {} + WorldObjectListSearcher(WorldObject const* searcher, std::list<WorldObject*> &objects, Check & check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL) + : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {} void Visit(PlayerMapType &m); void Visit(CreatureMapType &m); @@ -206,14 +229,17 @@ namespace Trinity template<class Do> struct WorldObjectWorker { + uint32 i_mapTypeMask; uint32 i_phaseMask; Do const& i_do; - WorldObjectWorker(WorldObject const* searcher, Do const& _do) - : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} + WorldObjectWorker(WorldObject const* searcher, Do const& _do, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL) + : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} void Visit(GameObjectMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT)) + return; for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) if (itr->getSource()->InSamePhase(i_phaseMask)) i_do(itr->getSource()); @@ -221,12 +247,16 @@ namespace Trinity void Visit(PlayerMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER)) + return; for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) if (itr->getSource()->InSamePhase(i_phaseMask)) i_do(itr->getSource()); } void Visit(CreatureMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE)) + return; for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) if (itr->getSource()->InSamePhase(i_phaseMask)) i_do(itr->getSource()); @@ -234,6 +264,8 @@ namespace Trinity void Visit(CorpseMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE)) + return; for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) if (itr->getSource()->InSamePhase(i_phaseMask)) i_do(itr->getSource()); @@ -241,6 +273,8 @@ namespace Trinity void Visit(DynamicObjectMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT)) + return; for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) if (itr->getSource()->InSamePhase(i_phaseMask)) i_do(itr->getSource()); @@ -527,57 +561,11 @@ namespace Trinity // CHECKS && DO classes // WorldObject check classes - class RaiseDeadObjectCheck - { - public: - RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Creature* u) - { - if (i_funit->GetTypeId() != TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) || - u->getDeathState() != CORPSE || u->isInFlight() || - (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 || - (u->GetDisplayId() != u->GetNativeDisplayId())) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; - - class ExplodeCorpseObjectCheck - { - public: - ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Player* u) - { - if (u->getDeathState() != CORPSE || u->isInFlight() || - u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId())) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - bool operator()(Creature* u) - { - if (u->getDeathState() != CORPSE || u->isInFlight() || - (u->GetDisplayId() != u->GetNativeDisplayId()) || - (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) != 0) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; class AnyDeadUnitObjectInRangeCheck { public: - AnyDeadUnitObjectInRangeCheck(Unit const* searchObj, float range) : i_searchObj(searchObj), i_range(range) {} + AnyDeadUnitObjectInRangeCheck(Unit* searchObj, float range) : i_searchObj(searchObj), i_range(range) {} bool operator()(Player* u); bool operator()(Corpse* u); bool operator()(Creature* u); @@ -590,15 +578,16 @@ namespace Trinity class AnyDeadUnitSpellTargetInRangeCheck : public AnyDeadUnitObjectInRangeCheck { public: - AnyDeadUnitSpellTargetInRangeCheck(Unit const* searchObj, float range, SpellInfo const* spellInfo, SpellTargetSelectionCheckTypes check) - : AnyDeadUnitObjectInRangeCheck(searchObj, range), i_spellInfo(spellInfo), i_check(check) {} + AnyDeadUnitSpellTargetInRangeCheck(Unit* searchObj, float range, SpellInfo const* spellInfo, SpellTargetCheckTypes check) + : AnyDeadUnitObjectInRangeCheck(searchObj, range), i_spellInfo(spellInfo), i_check(searchObj, searchObj, spellInfo, check, NULL) + {} bool operator()(Player* u); bool operator()(Corpse* u); bool operator()(Creature* u); template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; } protected: SpellInfo const* i_spellInfo; - SpellTargetSelectionCheckTypes i_check; + WorldObjectSpellTargetCheck i_check; }; // WorldObject do classes diff --git a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h index 34fe7757c5f..40b3863679b 100755 --- a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h +++ b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h @@ -51,6 +51,9 @@ inline void Trinity::ObjectUpdater::Visit(CreatureMapType &m) template<class Check> void Trinity::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT)) + return; + // already found if (i_object) return; @@ -71,6 +74,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m) template<class Check> void Trinity::WorldObjectSearcher<Check>::Visit(PlayerMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER)) + return; + // already found if (i_object) return; @@ -91,6 +97,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(PlayerMapType &m) template<class Check> void Trinity::WorldObjectSearcher<Check>::Visit(CreatureMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE)) + return; + // already found if (i_object) return; @@ -111,6 +120,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CreatureMapType &m) template<class Check> void Trinity::WorldObjectSearcher<Check>::Visit(CorpseMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE)) + return; + // already found if (i_object) return; @@ -131,6 +143,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CorpseMapType &m) template<class Check> void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT)) + return; + // already found if (i_object) return; @@ -148,9 +163,93 @@ void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m) } } + +template<class Check> +void Trinity::WorldObjectLastSearcher<Check>::Visit(GameObjectMapType &m) +{ + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT)) + return; + + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template<class Check> +void Trinity::WorldObjectLastSearcher<Check>::Visit(PlayerMapType &m) +{ + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER)) + return; + + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template<class Check> +void Trinity::WorldObjectLastSearcher<Check>::Visit(CreatureMapType &m) +{ + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE)) + return; + + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template<class Check> +void Trinity::WorldObjectLastSearcher<Check>::Visit(CorpseMapType &m) +{ + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE)) + return; + + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template<class Check> +void Trinity::WorldObjectLastSearcher<Check>::Visit(DynamicObjectMapType &m) +{ + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT)) + return; + + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + template<class Check> void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER)) + return; + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) if (itr->getSource()->InSamePhase(i_phaseMask)) if (i_check(itr->getSource())) @@ -160,6 +259,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m) template<class Check> void Trinity::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE)) + return; + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) if (itr->getSource()->InSamePhase(i_phaseMask)) if (i_check(itr->getSource())) @@ -169,6 +271,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m) template<class Check> void Trinity::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE)) + return; + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) if (itr->getSource()->InSamePhase(i_phaseMask)) if (i_check(itr->getSource())) @@ -178,6 +283,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m) template<class Check> void Trinity::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT)) + return; + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) if (itr->getSource()->InSamePhase(i_phaseMask)) if (i_check(itr->getSource())) @@ -187,6 +295,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m) template<class Check> void Trinity::WorldObjectListSearcher<Check>::Visit(DynamicObjectMapType &m) { + if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT)) + return; + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) if (itr->getSource()->InSamePhase(i_phaseMask)) if (i_check(itr->getSource())) diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index fd5b40f8031..1af656d7664 100755 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -585,7 +585,7 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV { Player* Leader = ObjectAccessor::FindPlayer(GetLeaderGUID()); LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(sLFGMgr->GetDungeon(GetGUID())); - if ((Leader && dungeon && Leader->isAlive() && Leader->GetMapId() != dungeon->map) || !dungeon) + if ((Leader && dungeon && Leader->isAlive() && Leader->GetMapId() != uint32(dungeon->map)) || !dungeon) { Disband(); return false; diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index 9b2d502b331..929532b6362 100755 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -115,42 +115,53 @@ void WorldSession::SendAuctionOwnerNotification(AuctionEntry* auction) //this void creates new auction and adds auction to some auctionhouse void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_SELL_ITEM"); - - uint64 auctioneer, item; - uint32 etime, bid, buyout, count; + uint64 auctioneer; + uint32 itemsCount, etime, bid, buyout; recv_data >> auctioneer; - recv_data.read_skip<uint32>(); // const 1? - recv_data >> item; - recv_data >> count; // 3.2.2, number of items being auctioned + recv_data >> 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); + return; + } + + for (uint32 i = 0; i < itemsCount; ++i) + { + recv_data >> itemGUIDs[i]; + recv_data >> count[i]; + + if (!itemGUIDs[i] || !count[i] || count[i] > 1000 ) + return; + } + recv_data >> bid; recv_data >> buyout; recv_data >> etime; - Player* player = GetPlayer(); - - if (!item || !bid || !etime) - return; //check for cheaters + if (!bid || !etime) + return; Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(auctioneer)); return; } AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->getFaction()); if (!auctionHouseEntry) { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", uint32(GUID_LOPART(auctioneer))); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", GUID_LOPART(auctioneer)); return; } - // client send time in minutes, convert to common used sec time etime *= MINUTE; - // client understand only 3 auction time - switch (etime) + switch(etime) { case 1*MIN_AUCTION_TIME: case 2*MIN_AUCTION_TIME: @@ -160,96 +171,181 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) return; } - // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - Item* it = player->GetItemByGuid(item); - //do not allow to sell already auctioned items - if (sAuctionMgr->GetAItem(GUID_LOPART(item))) - { - sLog->outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", player->GetName(), GUID_LOPART(item)); - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } - // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction) - if (!it) + Item* items[MAX_AUCTION_ITEMS]; + + uint32 finalCount = 0; + + for (uint32 i = 0; i < itemsCount; ++i) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); - return; + Item* item = _player->GetItemByGuid(itemGUIDs[i]); + + if (!item) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); + return; + } + + if (sAuctionMgr->GetAItem(item->GetGUIDLow()) || !item->CanBeTraded() || item->IsNotEmptyBag() || + item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) || + item->GetCount() < count[i]) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } + + items[i] = item; + finalCount += count[i]; } - if (!it->CanBeTraded()) + if (!finalCount) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } - if (it->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || it->GetUInt32Value(ITEM_FIELD_DURATION)) + for (uint32 i = 0; i < itemsCount; ++i) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; + Item* item = items[i]; + + if (item->GetMaxStackCount() < finalCount) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } } - if (it->IsNotEmptyBag()) + for (uint32 i = 0; i < itemsCount; ++i) { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } + Item* item = items[i]; - AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); + uint32 auctionTime = uint32(etime * sWorld->getRate(RATE_AUCTION_TIME)); + AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); - //we have to take deposit : - uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, it, count); - if (!player->HasEnoughMoney(deposit)) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); - return; - } + uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, item, finalCount); + if (!_player->HasEnoughMoney(deposit)) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); + return; + } - if (AccountMgr::IsGMAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) - { - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", - GetPlayerName(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), count); - } + _player->ModifyMoney(-int32(deposit)); - player->ModifyMoney(-int32(deposit)); + AuctionEntry* AH = new AuctionEntry; + AH->Id = sObjectMgr->GenerateAuctionID(); - uint32 auction_time = uint32(etime * sWorld->getRate(RATE_AUCTION_TIME)); + if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + AH->auctioneer = 23442; + else + AH->auctioneer = GUID_LOPART(auctioneer); - AuctionEntry* AH = new AuctionEntry; - AH->Id = sObjectMgr->GenerateAuctionID(); - if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) - AH->auctioneer = 23442; - else - AH->auctioneer = GUID_LOPART(auctioneer); - AH->item_guidlow = GUID_LOPART(item); - AH->item_template = it->GetEntry(); - AH->owner = player->GetGUIDLow(); - AH->startbid = bid; - AH->bidder = 0; - AH->bid = 0; - AH->buyout = buyout; - AH->expire_time = time(NULL) + auction_time; - AH->deposit = deposit; - AH->auctionHouseEntry = auctionHouseEntry; - - sLog->outDetail("selling item %u to auctioneer %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", GUID_LOPART(item), AH->auctioneer, bid, buyout, auction_time, AH->GetHouseId()); - sAuctionMgr->AddAItem(it); - auctionHouse->AddAuction(AH); - - player->MoveItemFromInventory(it->GetBagSlot(), it->GetSlot(), true); + if (itemsCount == 1 && item->GetCount() == count[i]) + { + if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) + { + sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", + GetPlayerName(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount()); + } - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - it->DeleteFromInventoryDB(trans); - it->SaveToDB(trans); // recursive and not have transaction guard into self, not in inventiory and can be save standalone - AH->SaveToDB(trans); - player->SaveInventoryAndGoldToDB(trans); - CharacterDatabase.CommitTransaction(trans); + AH->item_guidlow = item->GetGUIDLow(); + AH->item_template = item->GetEntry(); + AH->owner = _player->GetGUIDLow(); + AH->startbid = bid; + AH->bidder = 0; + AH->bid = 0; + AH->buyout = buyout; + AH->expire_time = time(NULL) + auctionTime; + AH->deposit = deposit; + AH->auctionHouseEntry = auctionHouseEntry; + + sLog->outDetail("CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName(), _player->GetGUIDLow(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUIDLow(), AH->auctioneer, item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); + sAuctionMgr->AddAItem(item); + auctionHouse->AddAuction(AH); + + _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + item->DeleteFromInventoryDB(trans); + item->SaveToDB(trans); + AH->SaveToDB(trans); + _player->SaveInventoryAndGoldToDB(trans); + CharacterDatabase.CommitTransaction(trans); + + SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); + + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); + return; + } + else + { + Item* newItem = item->CloneItem(finalCount, _player); + if (!newItem) + { + sLog->outError("CMSG_AUCTION_SELL_ITEM: Could not create clone of item %u", item->GetEntry()); + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } - SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); + if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) + { + sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", + GetPlayerName(), GetAccountId(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetCount()); + } + + AH->item_guidlow = newItem->GetGUIDLow(); + AH->item_template = newItem->GetEntry(); + AH->owner = _player->GetGUIDLow(); + AH->startbid = bid; + AH->bidder = 0; + AH->bid = 0; + AH->buyout = buyout; + AH->expire_time = time(NULL) + auctionTime; + AH->deposit = deposit; + AH->auctionHouseEntry = auctionHouseEntry; + + sLog->outDetail("CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName(), _player->GetGUIDLow(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetGUIDLow(), AH->auctioneer, newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); + sAuctionMgr->AddAItem(newItem); + auctionHouse->AddAuction(AH); + + for (uint32 i = 0; i < itemsCount; ++i) + { + Item* item = items[i]; + + if (item->GetCount() == count[i]) + { + _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + item->DeleteFromInventoryDB(trans); + item->SaveToDB(trans); + CharacterDatabase.CommitTransaction(trans); + } + else + { + item->SetCount(item->GetCount() - count[i]); + item->SetState(ITEM_CHANGED, _player); + _player->ItemRemovedQuestCheck(item->GetEntry(), count[i]); + item->SendUpdateToPlayer(_player); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + item->SaveToDB(trans); + CharacterDatabase.CommitTransaction(trans); + } + } + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + AH->SaveToDB(trans); + _player->SaveInventoryAndGoldToDB(trans); + CharacterDatabase.CommitTransaction(trans); - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); + SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); + + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); + return; + } + } } // this function is called when client bids or buys out auction diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index be547c84b19..820079a90e1 100755 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -88,7 +88,7 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recv_data*/) data << uint32(counter); // raid reset count std::set<uint32> sentMaps; - + ResetTimeByMapDifficultyMap const& resets = sInstanceSaveMgr->GetResetTimeMap(); for (ResetTimeByMapDifficultyMap::const_iterator itr = resets.begin(); itr != resets.end(); ++itr) { @@ -102,7 +102,7 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recv_data*/) continue; sentMaps.insert(mapId); - + data << uint32(mapId); data << uint32(itr->second - cur_time); data << uint32(mapEntry->unk_time); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index c4208215053..16129985d0f 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -197,7 +197,7 @@ bool LoginQueryHolder::Initialize() stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_INSTANCELOCKTIMES); stmt->setUInt32(0, m_accountId); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADINSTANCELOCKTIMES, stmt); - + return res; } @@ -686,6 +686,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte } Player newChar(this); + newChar.GetMotionMaster()->Initialize(); if (!newChar.Create(sObjectMgr->GenerateLowGuid(HIGHGUID_PLAYER), createInfo)) { // Player not create (race/class/etc problem?) @@ -1968,7 +1969,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) trans->Append(stmt); // Achievement conversion - for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->factionchange_achievements.begin(); it != sObjectMgr->factionchange_achievements.end(); ++it) + for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChange_Achievements.begin(); it != sObjectMgr->FactionChange_Achievements.end(); ++it) { uint32 achiev_alliance = it->first; uint32 achiev_horde = it->second; @@ -1979,7 +1980,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) } // Item conversion - for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->factionchange_items.begin(); it != sObjectMgr->factionchange_items.end(); ++it) + for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChange_Items.begin(); it != sObjectMgr->FactionChange_Items.end(); ++it) { uint32 item_alliance = it->first; uint32 item_horde = it->second; @@ -1988,7 +1989,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) } // Spell conversion - for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->factionchange_spells.begin(); it != sObjectMgr->factionchange_spells.end(); ++it) + for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChange_Spells.begin(); it != sObjectMgr->FactionChange_Spells.end(); ++it) { uint32 spell_alliance = it->first; uint32 spell_horde = it->second; @@ -1999,7 +2000,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) } // Reputation conversion - for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->factionchange_reputations.begin(); it != sObjectMgr->factionchange_reputations.end(); ++it) + for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChange_Reputation.begin(); it != sObjectMgr->FactionChange_Reputation.end(); ++it) { uint32 reputation_alliance = it->first; uint32 reputation_horde = it->second; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 8184334d2b1..1cd4df5de2c 100755 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1194,16 +1194,6 @@ void WorldSession::HandleSetActionBarToggles(WorldPacket& recv_data) GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, 2, ActionBar); } -void WorldSession::HandleWardenDataOpcode(WorldPacket& recv_data) -{ - recv_data.read_skip<uint8>(); - /* - uint8 tmp; - recv_data >> tmp; - sLog->outDebug("Received opcode CMSG_WARDEN_DATA, not resolve.uint8 = %u", tmp); - */ -} - void WorldSession::HandlePlayedTime(WorldPacket& recv_data) { uint8 unk1; @@ -1491,20 +1481,14 @@ void WorldSession::HandleTimeSyncResp(WorldPacket & recv_data) void WorldSession::HandleResetInstancesOpcode(WorldPacket & /*recv_data*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_RESET_INSTANCES"); - Group* group = _player->GetGroup(); - if (group) + + if (Group* group = _player->GetGroup()) { if (group->IsLeader(_player->GetGUID())) - { group->ResetInstances(INSTANCE_RESET_ALL, false, _player); - group->ResetInstances(INSTANCE_RESET_ALL, true, _player); - } } else - { _player->ResetInstances(INSTANCE_RESET_ALL, false); - _player->ResetInstances(INSTANCE_RESET_ALL, true); - } } void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket & recv_data) @@ -1524,7 +1508,7 @@ void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket & recv_data) return; // cannot reset while in an instance - Map* map = _player->GetMap(); + Map* map = _player->FindMap(); if (map && map->IsDungeon()) { sLog->outError("WorldSession::HandleSetDungeonDifficultyOpcode: player (Name: %s, GUID: %u) tried to reset the instance while player is inside!", _player->GetName(), _player->GetGUIDLow()); @@ -1545,8 +1529,7 @@ void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket & recv_data) if (!pGroupGuy->IsInMap(pGroupGuy)) return; - map = pGroupGuy->GetMap(); - if (map && map->IsNonRaidDungeon()) + if (pGroupGuy->GetMap()->IsNonRaidDungeon()) { sLog->outError("WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while group member (Name: %s, GUID: %u) is inside!", _player->GetGUIDLow(), pGroupGuy->GetName(), pGroupGuy->GetGUIDLow()); return; @@ -1579,7 +1562,7 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket & recv_data) } // cannot reset while in an instance - Map* map = _player->GetMap(); + Map* map = _player->FindMap(); if (map && map->IsDungeon()) { sLog->outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); @@ -1603,8 +1586,7 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket & recv_data) if (!pGroupGuy->IsInMap(pGroupGuy)) return; - map = pGroupGuy->GetMap(); - if (map && map->IsRaid()) + if (pGroupGuy->GetMap()->IsRaid()) { sLog->outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); return; diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index 945116ea5d8..385b91c9f7d 100755 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -621,7 +621,7 @@ void WorldSession::HandleStablePet(WorldPacket & recv_data) Pet* pet = _player->GetPet(); // can't place in stable dead pet - if (!pet||!pet->isAlive()||pet->getPetType() != HUNTER_PET) + if (!pet || !pet->isAlive() || pet->getPetType() != HUNTER_PET) { SendStableResult(STABLE_ERR_STABLE); return; @@ -859,16 +859,22 @@ void WorldSession::HandleStableSwapPetCallback(PreparedQueryResult result, uint3 return; } - // move alive pet to slot or delete dead pet Pet* pet = _player->GetPet(); + // The player's pet could have been removed during the delay of the DB callback + if (!pet) + { + SendStableResult(STABLE_ERR_STABLE); + return; + } + // move alive pet to slot or delete dead pet _player->RemovePet(pet, pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED); // summon unstabled pet - Pet* newpet = new Pet(_player); - if (!newpet->LoadPetFromDB(_player, petEntry, petId)) + Pet* newPet = new Pet(_player); + if (!newPet->LoadPetFromDB(_player, petEntry, petId)) { - delete newpet; + delete newPet; SendStableResult(STABLE_ERR_STABLE); } else diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index fb94800d1bd..f278e6b017e 100755 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -160,6 +160,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid case COMMAND_STAY: //flat=1792 //STAY pet->AttackStop(); pet->InterruptNonMeleeSpells(false); + pet->StopMoving(); pet->GetMotionMaster()->Clear(false); pet->GetMotionMaster()->MoveIdle(); charmInfo->SetCommandState(COMMAND_STAY); diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index f363fa71038..7faabb730e4 100755 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -241,9 +241,8 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) CharacterDatabase.CommitTransaction(trans); } -void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) +void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recv_data) { - // ok sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_SHOW_SIGNATURES"); uint8 signs = 0; @@ -256,7 +255,7 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) QueryResult result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low); if (!result) { - sLog->outError("Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName()); + sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName()); return; } Field* fields = result->Fetch(); diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index abb62fb0185..a18fbcddfca 100755 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -257,7 +257,7 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) mapid = corpseMapEntry->entrance_map; x = corpseMapEntry->entrance_x; y = corpseMapEntry->entrance_y; - z = entranceMap->GetHeight(x, y, MAX_HEIGHT); + z = entranceMap->GetHeight(GetPlayer()->GetPhaseMask(), x, y, MAX_HEIGHT); } } } diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index 6cba7b7fb4f..761fb9657c9 100755 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -652,7 +652,7 @@ uint32 WorldSession::getDialogStatus(Player* player, Object* questgiver, uint32 if (!pQuest) continue; ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, pQuest->GetQuestId()); - if (!sConditionMgr->IsPlayerMeetToConditions(player, conditions)) + if (!sConditionMgr->IsObjectMeetToConditions(player, conditions)) continue; QuestStatus status = player->GetQuestStatus(quest_id); @@ -680,7 +680,7 @@ uint32 WorldSession::getDialogStatus(Player* player, Object* questgiver, uint32 continue; ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, pQuest->GetQuestId()); - if (!sConditionMgr->IsPlayerMeetToConditions(player, conditions)) + if (!sConditionMgr->IsObjectMeetToConditions(player, conditions)) continue; QuestStatus status = player->GetQuestStatus(quest_id); diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 09ba46654ee..4e3a5a91db7 100755 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -166,24 +166,6 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) targets.Read(recvPacket, pUser); HandleClientCastFlags(recvPacket, castFlags, targets); - if (!pItem->IsTargetValidForItemUse(targets.GetUnitTarget())) - { - // free gray item after use fail - pUser->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); - - // send spell error - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId)) - { - // for implicit area/coord target spells - if (!targets.GetUnitTarget()) - Spell::SendCastResult(_player, spellInfo, castCount, SPELL_FAILED_NO_VALID_TARGETS); - // for explicit target spells - else - Spell::SendCastResult(_player, spellInfo, castCount, SPELL_FAILED_BAD_TARGETS); - } - return; - } - // Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state. if (!sScriptMgr->OnItemUse(pUser, pItem, targets)) { diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp index 8eb1eab06d9..44889e6dda8 100755 --- a/src/server/game/Handlers/TaxiHandler.cpp +++ b/src/server/game/Handlers/TaxiHandler.cpp @@ -292,3 +292,12 @@ void WorldSession::HandleActivateTaxiOpcode(WorldPacket & recv_data) GetPlayer()->ActivateTaxiPathTo(nodes, npc); } + +void WorldSession::SendActivateTaxiReply(ActivateTaxiReply reply) +{ + WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); + data << uint32(reply); + SendPacket(&data); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_ACTIVATETAXIREPLY"); +} diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 1869a21c738..d0a96e3b62e 100755 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -316,7 +316,7 @@ void InstanceScript::DoSendNotifyToInstance(char const* format, ...) for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) if (Player* player = i->getSource()) if (WorldSession* session = player->GetSession()) - session->SendNotification(buff); + session->SendNotification("%s", buff); } } diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index a0ede8c7eef..edc8d24c635 100755 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -102,9 +102,7 @@ uint32 LootStore::LoadLootTable() QueryResult result = WorldDatabase.PQuery("SELECT entry, item, ChanceOrQuestChance, lootmode, groupid, mincountOrRef, maxcount FROM %s", GetName()); if (!result) - { return 0; -} uint32 count = 0; @@ -341,7 +339,7 @@ LootItem::LootItem(LootStoreItem const& li) bool LootItem::AllowedForPlayer(Player const* player) const { // DB conditions check - if (!sConditionMgr->IsPlayerMeetToConditions(const_cast<Player*>(player), conditions)) + if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(player), conditions)) return false; ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid); @@ -1367,7 +1365,7 @@ bool LootTemplate::addConditionItem(Condition* cond) { for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i) { - if (i->itemid == cond->mSourceEntry) + if (i->itemid == uint32(cond->SourceEntry)) { i->conditions.push_back(cond); return true; @@ -1383,7 +1381,7 @@ bool LootTemplate::addConditionItem(Condition* cond) { for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i) { - if ((*i).itemid == cond->mSourceEntry) + if ((*i).itemid == uint32(cond->SourceEntry)) { (*i).conditions.push_back(cond); return true; @@ -1395,7 +1393,7 @@ bool LootTemplate::addConditionItem(Condition* cond) { for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i) { - if ((*i).itemid == cond->mSourceEntry) + if ((*i).itemid == uint32(cond->SourceEntry)) { (*i).conditions.push_back(cond); return true; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index ec362cf1a83..81b4f958e5d 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -31,6 +31,7 @@ #include "ObjectMgr.h" #include "Group.h" #include "LFGMgr.h" +#include "DynamicTree.h" union u_map_magic { @@ -368,6 +369,7 @@ bool Map::EnsureGridLoaded(const Cell &cell) // Add resurrectable corpses to world object list in grid sObjectAccessor->AddCorpsesToGrid(GridCoord(cell.GridX(), cell.GridY()), grid->GetGridType(cell.CellX(), cell.CellY()), this); + Balance(); return true; } @@ -498,6 +500,7 @@ void Map::VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Trinity::Obj void Map::Update(const uint32 t_diff) { + _dynamicTree.update(t_diff); /// update worldsessions for existing players for (m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter) { @@ -663,9 +666,11 @@ void Map::RemovePlayerFromMap(Player* player, bool remove) ASSERT(remove); //maybe deleted in logoutplayer when player is not in a map if (remove) + { DeleteFromWorld(player); - sScriptMgr->OnPlayerLeaveMap(this, player); + sScriptMgr->OnPlayerLeaveMap(this, player); + } } template<class T> @@ -1018,24 +1023,24 @@ void Map::UnloadAll() // ***************************** GridMap::GridMap() { - m_flags = 0; + _flags = 0; // Area data - m_gridArea = 0; - m_area_map = NULL; + _gridArea = 0; + _areaMap = NULL; // Height level data - m_gridHeight = INVALID_HEIGHT; - m_gridGetHeight = &GridMap::getHeightFromFlat; + _gridHeight = INVALID_HEIGHT; + _gridGetHeight = &GridMap::getHeightFromFlat; m_V9 = NULL; m_V8 = NULL; // Liquid data - m_liquidType = 0; - m_liquid_offX = 0; - m_liquid_offY = 0; - m_liquid_width = 0; - m_liquid_height = 0; - m_liquidLevel = INVALID_HEIGHT; - m_liquid_type = NULL; - m_liquid_map = NULL; + _liquidType = 0; + _liquidOffX = 0; + _liquidOffY = 0; + _liquidWidth = 0; + _liquidHeight = 0; + _liquidLevel = INVALID_HEIGHT; + _liquidData = NULL; + _liquidMap = NULL; } GridMap::~GridMap() @@ -1093,17 +1098,17 @@ bool GridMap::loadData(char *filename) void GridMap::unloadData() { - delete[] m_area_map; + delete[] _areaMap; delete[] m_V9; delete[] m_V8; - delete[] m_liquid_type; - delete[] m_liquid_map; - m_area_map = NULL; + delete[] _liquidData; + delete[] _liquidMap; + _areaMap = NULL; m_V9 = NULL; m_V8 = NULL; - m_liquid_type = NULL; - m_liquid_map = NULL; - m_gridGetHeight = &GridMap::getHeightFromFlat; + _liquidData = NULL; + _liquidMap = NULL; + _gridGetHeight = &GridMap::getHeightFromFlat; } bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/) @@ -1114,11 +1119,11 @@ bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/) if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapAreaMagic.asUInt) return false; - m_gridArea = header.gridArea; + _gridArea = header.gridArea; if (!(header.flags & MAP_AREA_NO_AREA)) { - m_area_map = new uint16 [16*16]; - if (fread(m_area_map, sizeof(uint16), 16*16, in) != 16*16) + _areaMap = new uint16 [16*16]; + if (fread(_areaMap, sizeof(uint16), 16*16, in) != 16*16) return false; } return true; @@ -1132,7 +1137,7 @@ bool GridMap::loadHeihgtData(FILE* in, uint32 offset, uint32 /*size*/) if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapHeightMagic.asUInt) return false; - m_gridHeight = header.gridHeight; + _gridHeight = header.gridHeight; if (!(header.flags & MAP_HEIGHT_NO_HEIGHT)) { if ((header.flags & MAP_HEIGHT_AS_INT16)) @@ -1142,8 +1147,8 @@ bool GridMap::loadHeihgtData(FILE* in, uint32 offset, uint32 /*size*/) if (fread(m_uint16_V9, sizeof(uint16), 129*129, in) != 129*129 || fread(m_uint16_V8, sizeof(uint16), 128*128, in) != 128*128) return false; - m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535; - m_gridGetHeight = &GridMap::getHeightFromUint16; + _gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535; + _gridGetHeight = &GridMap::getHeightFromUint16; } else if ((header.flags & MAP_HEIGHT_AS_INT8)) { @@ -1152,8 +1157,8 @@ bool GridMap::loadHeihgtData(FILE* in, uint32 offset, uint32 /*size*/) if (fread(m_uint8_V9, sizeof(uint8), 129*129, in) != 129*129 || fread(m_uint8_V8, sizeof(uint8), 128*128, in) != 128*128) return false; - m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255; - m_gridGetHeight = &GridMap::getHeightFromUint8; + _gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255; + _gridGetHeight = &GridMap::getHeightFromUint8; } else { @@ -1162,11 +1167,11 @@ bool GridMap::loadHeihgtData(FILE* in, uint32 offset, uint32 /*size*/) if (fread(m_V9, sizeof(float), 129*129, in) != 129*129 || fread(m_V8, sizeof(float), 128*128, in) != 128*128) return false; - m_gridGetHeight = &GridMap::getHeightFromFloat; + _gridGetHeight = &GridMap::getHeightFromFloat; } } else - m_gridGetHeight = &GridMap::getHeightFromFlat; + _gridGetHeight = &GridMap::getHeightFromFlat; return true; } @@ -1178,23 +1183,23 @@ bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/) if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapLiquidMagic.asUInt) return false; - m_liquidType = header.liquidType; - m_liquid_offX = header.offsetX; - m_liquid_offY = header.offsetY; - m_liquid_width = header.width; - m_liquid_height= header.height; - m_liquidLevel = header.liquidLevel; + _liquidType = header.liquidType; + _liquidOffX = header.offsetX; + _liquidOffY = header.offsetY; + _liquidWidth = header.width; + _liquidHeight= header.height; + _liquidLevel = header.liquidLevel; if (!(header.flags & MAP_LIQUID_NO_TYPE)) { - m_liquid_type = new uint8 [16*16]; - if (fread(m_liquid_type, sizeof(uint8), 16*16, in) != 16*16) + _liquidData = new uint8 [16*16]; + if (fread(_liquidData, sizeof(uint8), 16*16, in) != 16*16) return false; } if (!(header.flags & MAP_LIQUID_NO_HEIGHT)) { - m_liquid_map = new float [m_liquid_width*m_liquid_height]; - if (fread(m_liquid_map, sizeof(float), m_liquid_width*m_liquid_height, in) != m_liquid_width*m_liquid_height) + _liquidMap = new float [_liquidWidth*_liquidHeight]; + if (fread(_liquidMap, sizeof(float), _liquidWidth*_liquidHeight, in) != _liquidWidth*_liquidHeight) return false; } return true; @@ -1202,25 +1207,25 @@ bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/) uint16 GridMap::getArea(float x, float y) { - if (!m_area_map) - return m_gridArea; + if (!_areaMap) + return _gridArea; x = 16 * (32 - x/SIZE_OF_GRIDS); y = 16 * (32 - y/SIZE_OF_GRIDS); int lx = (int)x & 15; int ly = (int)y & 15; - return m_area_map[lx*16 + ly]; + return _areaMap[lx*16 + ly]; } float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const { - return m_gridHeight; + return _gridHeight; } float GridMap::getHeightFromFloat(float x, float y) const { if (!m_V8 || !m_V9) - return m_gridHeight; + return _gridHeight; x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); @@ -1302,7 +1307,7 @@ float GridMap::getHeightFromFloat(float x, float y) const float GridMap::getHeightFromUint8(float x, float y) const { if (!m_uint8_V8 || !m_uint8_V9) - return m_gridHeight; + return _gridHeight; x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); @@ -1363,13 +1368,13 @@ float GridMap::getHeightFromUint8(float x, float y) const } } // Calculate height - return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight; + return (float)((a * x) + (b * y) + c)*_gridIntHeightMultiplier + _gridHeight; } float GridMap::getHeightFromUint16(float x, float y) const { if (!m_uint16_V8 || !m_uint16_V9) - return m_gridHeight; + return _gridHeight; x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); @@ -1430,45 +1435,45 @@ float GridMap::getHeightFromUint16(float x, float y) const } } // Calculate height - return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight; + return (float)((a * x) + (b * y) + c)*_gridIntHeightMultiplier + _gridHeight; } float GridMap::getLiquidLevel(float x, float y) { - if (!m_liquid_map) - return m_liquidLevel; + if (!_liquidMap) + return _liquidLevel; x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); - int cx_int = ((int)x & (MAP_RESOLUTION-1)) - m_liquid_offY; - int cy_int = ((int)y & (MAP_RESOLUTION-1)) - m_liquid_offX; + int cx_int = ((int)x & (MAP_RESOLUTION-1)) - _liquidOffY; + int cy_int = ((int)y & (MAP_RESOLUTION-1)) - _liquidOffX; - if (cx_int < 0 || cx_int >=m_liquid_height) + if (cx_int < 0 || cx_int >=_liquidHeight) return INVALID_HEIGHT; - if (cy_int < 0 || cy_int >=m_liquid_width) + if (cy_int < 0 || cy_int >=_liquidWidth) return INVALID_HEIGHT; - return m_liquid_map[cx_int*m_liquid_width + cy_int]; + return _liquidMap[cx_int*_liquidWidth + cy_int]; } uint8 GridMap::getTerrainType(float x, float y) { - if (!m_liquid_type) + if (!_liquidData) return 0; x = 16 * (32 - x/SIZE_OF_GRIDS); y = 16 * (32 - y/SIZE_OF_GRIDS); int lx = (int)x & 15; int ly = (int)y & 15; - return m_liquid_type[lx*16 + ly]; + return _liquidData[lx*16 + ly]; } // Get water state on map inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data) { // Check water type (if no water return) - if (!m_liquid_type && !m_liquidType) + if (!_liquidType && !_liquidData) return LIQUID_MAP_NO_WATER; // Get cell @@ -1479,7 +1484,7 @@ inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 R int y_int = (int)cy & (MAP_RESOLUTION-1); // Check water type in cell - uint8 type = m_liquid_type ? m_liquid_type[(x_int>>3)*16 + (y_int>>3)] : m_liquidType; + uint8 type = _liquidData ? _liquidData[(x_int>>3)*16 + (y_int>>3)] : _liquidType; if (type == 0) return LIQUID_MAP_NO_WATER; @@ -1489,15 +1494,15 @@ inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 R // Check water level: // Check water height map - int lx_int = x_int - m_liquid_offY; - int ly_int = y_int - m_liquid_offX; - if (lx_int < 0 || lx_int >=m_liquid_height) + int lx_int = x_int - _liquidOffY; + int ly_int = y_int - _liquidOffX; + if (lx_int < 0 || lx_int >=_liquidHeight) return LIQUID_MAP_NO_WATER; - if (ly_int < 0 || ly_int >=m_liquid_width) + if (ly_int < 0 || ly_int >=_liquidWidth) return LIQUID_MAP_NO_WATER; // Get water level - float liquid_level = m_liquid_map ? m_liquid_map[lx_int*m_liquid_width + ly_int] : m_liquidLevel; + float liquid_level = _liquidMap ? _liquidMap[lx_int*_liquidWidth + ly_int] : _liquidLevel; // Get ground level (sub 0.2 for fix some errors) float ground_level = getHeight(x, y); @@ -1539,19 +1544,19 @@ inline GridMap* Map::GetGrid(float x, float y) return GridMaps[gx][gy]; } -float Map::GetWaterOrGroundLevel(float x, float y, float z, float* ground /*= NULL*/, bool swim /*= false*/) const +float Map::GetWaterOrGroundLevel(float x, float y, float z, float* ground /*= NULL*/, bool /*swim = false*/) const { if (const_cast<Map*>(this)->GetGrid(x, y)) { // we need ground level (including grid height version) for proper return water level in point - float ground_z = GetHeight(x, y, z, true, 50.0f); + float ground_z = GetHeight(PHASEMASK_NORMAL, x, y, z, true, 50.0f); if (ground) *ground = ground_z; LiquidData liquid_status; ZLiquidStatus res = getLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status); - return res ? ( swim ? liquid_status.level - 2.0f : liquid_status.level) : ground_z; + return res ? liquid_status.level : ground_z; } return VMAP_INVALID_HEIGHT_VALUE; @@ -1793,6 +1798,31 @@ void Map::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 area zoneid = entry ? ((entry->zone != 0) ? entry->zone : entry->ID) : 0; } +bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const +{ + return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2) + && _dynamicTree.isInLineOfSight(x1, y1, z1, x2, y2, z2, phasemask); +} + +bool Map::getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist) +{ + Vector3 startPos = Vector3(x1, y1, z1); + Vector3 dstPos = Vector3(x2, y2, z2); + + Vector3 resultPos; + bool result = _dynamicTree.getObjectHitPos(phasemask, startPos, dstPos, resultPos, modifyDist); + + rx = resultPos.x; + ry = resultPos.y; + rz = resultPos.z; + return result; +} + +float Map::GetHeight(uint32 phasemask, float x, float y, float z, bool vmap/*=true*/, float maxSearchDist/*=DEFAULT_HEIGHT_SEARCH*/) const +{ + return std::max<float>(GetHeight(x, y, z, vmap, maxSearchDist), _dynamicTree.getHeight(x, y, z, maxSearchDist, phasemask)); +} + bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const { // Check surface in x, y point for liquid @@ -2346,7 +2376,7 @@ bool InstanceMap::AddPlayerToMap(Player* player) if (uint32 dungeonId = sLFGMgr->GetDungeon(group->GetGUID(), true)) if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) if (LFGDungeonEntry const* randomDungeon = sLFGDungeonStore.LookupEntry(*(sLFGMgr->GetSelectedDungeons(player->GetGUID()).begin()))) - if (dungeon->map == GetId() && dungeon->difficulty == GetDifficulty() && randomDungeon->type == LFG_TYPE_RANDOM) + if (uint32(dungeon->map) == GetId() && dungeon->difficulty == GetDifficulty() && randomDungeon->type == LFG_TYPE_RANDOM) player->CastSpell(player, LFG_SPELL_LUCK_OF_THE_DRAW, true); } diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index f3b45bd8f37..d8db4c947a3 100755 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -30,6 +30,8 @@ #include "SharedDefines.h" #include "GridRefManager.h" #include "MapRefManager.h" +#include "DynamicTree.h" +#include "GameObjectModel.h" #include <bitset> #include <list> @@ -141,55 +143,58 @@ struct LiquidData class GridMap { - uint32 m_flags; - // Area data - uint16 m_gridArea; - uint16 *m_area_map; - // Height level data - float m_gridHeight; - float m_gridIntHeightMultiplier; + uint32 _flags; union{ - float *m_V9; - uint16 *m_uint16_V9; - uint8 *m_uint8_V9; + float* m_V9; + uint16* m_uint16_V9; + uint8* m_uint8_V9; }; union{ - float *m_V8; - uint16 *m_uint16_V8; - uint8 *m_uint8_V8; + float* m_V8; + uint16* m_uint16_V8; + uint8* m_uint8_V8; }; + // Height level data + float _gridHeight; + float _gridIntHeightMultiplier; + + // Area data + uint16* _areaMap; + // Liquid data - uint16 m_liquidType; - uint8 m_liquid_offX; - uint8 m_liquid_offY; - uint8 m_liquid_width; - uint8 m_liquid_height; - float m_liquidLevel; - uint8 *m_liquid_type; - float *m_liquid_map; - - bool loadAreaData(FILE* in, uint32 offset, uint32 size); - bool loadHeihgtData(FILE* in, uint32 offset, uint32 size); - bool loadLiquidData(FILE* in, uint32 offset, uint32 size); + float _liquidLevel; + uint8* _liquidData; + float* _liquidMap; + uint16 _gridArea; + uint16 _liquidType; + uint8 _liquidOffX; + uint8 _liquidOffY; + uint8 _liquidWidth; + uint8 _liquidHeight; + + + bool loadAreaData(FILE* in, uint32 offset, uint32 size); + bool loadHeihgtData(FILE* in, uint32 offset, uint32 size); + bool loadLiquidData(FILE* in, uint32 offset, uint32 size); // Get height functions and pointers - typedef float (GridMap::*pGetHeightPtr) (float x, float y) const; - pGetHeightPtr m_gridGetHeight; - float getHeightFromFloat(float x, float y) const; - float getHeightFromUint16(float x, float y) const; - float getHeightFromUint8(float x, float y) const; - float getHeightFromFlat(float x, float y) const; + typedef float (GridMap::*GetHeightPtr) (float x, float y) const; + GetHeightPtr _gridGetHeight; + float getHeightFromFloat(float x, float y) const; + float getHeightFromUint16(float x, float y) const; + float getHeightFromUint8(float x, float y) const; + float getHeightFromFlat(float x, float y) const; public: GridMap(); ~GridMap(); - bool loadData(char *filaname); - void unloadData(); + bool loadData(char* filaname); + void unloadData(); uint16 getArea(float x, float y); - inline float getHeight(float x, float y) {return (this->*m_gridGetHeight)(x, y);} - float getLiquidLevel(float x, float y); - uint8 getTerrainType(float x, float y); + inline float getHeight(float x, float y) {return (this->*_gridGetHeight)(x, y);} + float getLiquidLevel(float x, float y); + uint8 getTerrainType(float x, float y); ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0); }; @@ -425,7 +430,13 @@ class Map : public GridRefManager<NGridType> InstanceMap* ToInstanceMap(){ if (IsDungeon()) return reinterpret_cast<InstanceMap*>(this); else return NULL; } const InstanceMap* ToInstanceMap() const { if (IsDungeon()) return (const InstanceMap*)((InstanceMap*)this); else return NULL; } float GetWaterOrGroundLevel(float x, float y, float z, float* ground = NULL, bool swim = false) const; - + float GetHeight(uint32 phasemask, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; + bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const; + void Balance() { _dynamicTree.balance(); } + void Remove(const GameObjectModel& mdl) { _dynamicTree.remove(mdl); } + void Insert(const GameObjectModel& mdl) { _dynamicTree.insert(mdl); } + bool Contains(const GameObjectModel& mdl) const { return _dynamicTree.contains(mdl);} + bool getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist); private: void LoadMapAndVMap(int gx, int gy); void LoadVMap(int gx, int gy); @@ -481,6 +492,7 @@ class Map : public GridRefManager<NGridType> uint32 i_InstanceId; uint32 m_unloadTimer; float m_VisibleDistance; + DynamicMapTree _dynamicTree; MapRefManager m_mapRefManager; MapRefManager::iterator m_mapRefIter; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 323f31c9bb4..f1ebfb6ec96 100755 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -100,6 +100,7 @@ enum Races // Class value is index in ChrClasses.dbc enum Classes { + CLASS_NONE = 0, CLASS_WARRIOR = 1, CLASS_PALADIN = 2, CLASS_HUNTER = 3, @@ -1566,6 +1567,7 @@ enum GameObjectDestructibleState GO_DESTRUCTIBLE_REBUILDING = 3, }; +// EmotesText.dbc enum TextEmotes { TEXT_EMOTE_AGREE = 1, @@ -1729,7 +1731,7 @@ enum TextEmotes TEXT_EMOTE_ATTACKMYTARGET = 307, TEXT_EMOTE_OOM = 323, TEXT_EMOTE_FOLLOW = 324, - TEXT_EMOTE_HELP = 325, + TEXT_EMOTE_WAIT = 325, TEXT_EMOTE_HEALME = 326, TEXT_EMOTE_OPENFIRE = 327, TEXT_EMOTE_FLIRT = 328, @@ -1738,7 +1740,7 @@ enum TextEmotes TEXT_EMOTE_WINK = 363, TEXT_EMOTE_PAT = 364, TEXT_EMOTE_SERIOUS = 365, - TEXT_EMOTE_MOUNTSPECIAL = 366, + TEXT_EMOTE_MOUNT_SPECIAL = 366, TEXT_EMOTE_GOODLUCK = 367, TEXT_EMOTE_BLAME = 368, TEXT_EMOTE_BLANK = 369, @@ -1751,6 +1753,7 @@ enum TextEmotes TEXT_EMOTE_ENEMY = 376, TEXT_EMOTE_EYEBROW = 377, TEXT_EMOTE_TOAST = 378, + TEXT_EMOTE_FAIL = 379, TEXT_EMOTE_HIGHFIVE = 380, TEXT_EMOTE_ABSENT = 381, TEXT_EMOTE_ARM = 382, @@ -1805,6 +1808,7 @@ enum TextEmotes TEXT_EMOTE_SNEEZE = 436, TEXT_EMOTE_SNORT = 437, TEXT_EMOTE_SQUEAL = 438, + TEXT_EMOTE_STOPATTACK = 439, TEXT_EMOTE_SUSPICIOUS = 440, TEXT_EMOTE_THINK = 441, TEXT_EMOTE_TRUCE = 442, @@ -1820,402 +1824,695 @@ enum TextEmotes TEXT_EMOTE_YW = 453, }; +// Emotes.dbc enum Emote { - EMOTE_ONESHOT_NONE = 0, - EMOTE_ONESHOT_TALK = 1, - EMOTE_ONESHOT_BOW = 2, - EMOTE_ONESHOT_WAVE = 3, - EMOTE_ONESHOT_CHEER = 4, - EMOTE_ONESHOT_EXCLAMATION = 5, - EMOTE_ONESHOT_QUESTION = 6, - EMOTE_ONESHOT_EAT = 7, - EMOTE_STATE_DANCE = 10, - EMOTE_ONESHOT_LAUGH = 11, - EMOTE_STATE_SLEEP = 12, - EMOTE_STATE_SIT = 13, - EMOTE_ONESHOT_RUDE = 14, - EMOTE_ONESHOT_ROAR = 15, - EMOTE_ONESHOT_KNEEL = 16, - EMOTE_ONESHOT_KISS = 17, - EMOTE_ONESHOT_CRY = 18, - EMOTE_ONESHOT_CHICKEN = 19, - EMOTE_ONESHOT_BEG = 20, - EMOTE_ONESHOT_APPLAUD = 21, - EMOTE_ONESHOT_SHOUT = 22, - EMOTE_ONESHOT_FLEX = 23, - EMOTE_ONESHOT_SHY = 24, - EMOTE_ONESHOT_POINT = 25, - EMOTE_STATE_STAND = 26, - EMOTE_STATE_READYUNARMED = 27, - EMOTE_STATE_WORK_SHEATHED = 28, - EMOTE_STATE_POINT = 29, - EMOTE_STATE_NONE = 30, - EMOTE_ONESHOT_WOUND = 33, - EMOTE_ONESHOT_WOUNDCRITICAL = 34, - EMOTE_ONESHOT_ATTACKUNARMED = 35, - EMOTE_ONESHOT_ATTACK1H = 36, - EMOTE_ONESHOT_ATTACK2HTIGHT = 37, - EMOTE_ONESHOT_ATTACK2HLOOSE = 38, - EMOTE_ONESHOT_PARRYUNARMED = 39, - EMOTE_ONESHOT_PARRYSHIELD = 43, - EMOTE_ONESHOT_READYUNARMED = 44, - EMOTE_ONESHOT_READY1H = 45, - EMOTE_ONESHOT_READYBOW = 48, - EMOTE_ONESHOT_SPELLPRECAST = 50, - EMOTE_ONESHOT_SPELLCAST = 51, - EMOTE_ONESHOT_BATTLEROAR = 53, - EMOTE_ONESHOT_SPECIALATTACK1H = 54, - EMOTE_ONESHOT_KICK = 60, - EMOTE_ONESHOT_ATTACKTHROWN = 61, - EMOTE_STATE_STUN = 64, - EMOTE_STATE_DEAD = 65, - EMOTE_ONESHOT_SALUTE = 66, - EMOTE_STATE_KNEEL = 68, - EMOTE_STATE_USESTANDING = 69, - EMOTE_ONESHOT_WAVE_NOSHEATHE = 70, - EMOTE_ONESHOT_CHEER_NOSHEATHE = 71, - EMOTE_ONESHOT_EAT_NOSHEATHE = 92, - EMOTE_STATE_STUN_NOSHEATHE = 93, - EMOTE_ONESHOT_DANCE = 94, - EMOTE_ONESHOT_SALUTE_NOSHEATH = 113, - EMOTE_STATE_USESTANDING_NOSHEATHE = 133, - EMOTE_ONESHOT_LAUGH_NOSHEATHE = 153, - EMOTE_STATE_WORK = 173, - EMOTE_STATE_SPELLPRECAST = 193, - EMOTE_ONESHOT_READYRIFLE = 213, - EMOTE_STATE_READYRIFLE = 214, - EMOTE_STATE_WORK_MINING = 233, - EMOTE_STATE_WORK_CHOPWOOD = 234, - EMOTE_STATE_APPLAUD = 253, - EMOTE_ONESHOT_LIFTOFF = 254, - EMOTE_ONESHOT_YES = 273, - EMOTE_ONESHOT_NO = 274, - EMOTE_ONESHOT_TRAIN = 275, - EMOTE_ONESHOT_LAND = 293, - EMOTE_STATE_AT_EASE = 313, - EMOTE_STATE_READY1H = 333, - EMOTE_STATE_SPELLKNEELSTART = 353, - EMOTE_STATE_SUBMERGED = 373, - EMOTE_ONESHOT_SUBMERGE = 374, - EMOTE_STATE_READY2H = 375, - EMOTE_STATE_READYBOW = 376, - EMOTE_ONESHOT_MOUNTSPECIAL = 377, - EMOTE_STATE_TALK = 378, - EMOTE_STATE_FISHING = 379, - EMOTE_ONESHOT_FISHING = 380, - EMOTE_ONESHOT_LOOT = 381, - EMOTE_STATE_WHIRLWIND = 382, - EMOTE_STATE_DROWNED = 383, - EMOTE_STATE_HOLD_BOW = 384, - EMOTE_STATE_HOLD_RIFLE = 385, - EMOTE_STATE_HOLD_THROWN = 386, - EMOTE_ONESHOT_DROWN = 387, - EMOTE_ONESHOT_STOMP = 388, - EMOTE_ONESHOT_ATTACKOFF = 389, - EMOTE_ONESHOT_ATTACKOFFPIERCE = 390, - EMOTE_STATE_ROAR = 391, - EMOTE_STATE_LAUGH = 392, - EMOTE_ONESHOT_CREATURE_SPECIAL = 393, - EMOTE_ONESHOT_JUMPLANDRUN = 394, - EMOTE_ONESHOT_JUMPEND = 395, - EMOTE_ONESHOT_TALK_NOSHEATHE = 396, - EMOTE_ONESHOT_POINT_NOSHEATHE = 397, - EMOTE_STATE_CANNIBALIZE = 398, - EMOTE_ONESHOT_JUMPSTART = 399, - EMOTE_STATE_DANCESPECIAL = 400, - EMOTE_ONESHOT_DANCESPECIAL = 401, - EMOTE_ONESHOT_CUSTOMSPELL01 = 402, - EMOTE_ONESHOT_CUSTOMSPELL02 = 403, - EMOTE_ONESHOT_CUSTOMSPELL03 = 404, - EMOTE_ONESHOT_CUSTOMSPELL04 = 405, - EMOTE_ONESHOT_CUSTOMSPELL05 = 406, - EMOTE_ONESHOT_CUSTOMSPELL06 = 407, - EMOTE_ONESHOT_CUSTOMSPELL07 = 408, - EMOTE_ONESHOT_CUSTOMSPELL08 = 409, - EMOTE_ONESHOT_CUSTOMSPELL09 = 410, - EMOTE_ONESHOT_CUSTOMSPELL10 = 411, - EMOTE_STATE_EXCLAIM = 412, - EMOTE_STATE_DANCE_CUSTOM = 413, - EMOTE_STATE_SIT_CHAIR_MED = 415, - EMOTE_STATE_CUSTOM_SPELL_01 = 416, - EMOTE_STATE_CUSTOM_SPELL_02 = 417, - EMOTE_STATE_EAT = 418, - EMOTE_STATE_CUSTOM_SPELL_04 = 419, - EMOTE_STATE_CUSTOM_SPELL_03 = 420, - EMOTE_STATE_CUSTOM_SPELL_05 = 421, - EMOTE_STATE_SPELLEFFECT_HOLD = 422, - EMOTE_STATE_EAT_NO_SHEATHE = 423, - EMOTE_STATE_MOUNT = 424, - EMOTE_STATE_READY2HL = 425, - EMOTE_STATE_SIT_CHAIR_HIGH = 426, - EMOTE_STATE_FALL = 427, - EMOTE_STATE_LOOT = 428, - EMOTE_STATE_SUBMERGED_NEW = 429, - EMOTE_ONESHOT_COWER = 430, - EMOTE_STATE_COWER = 431, - EMOTE_ONESHOT_USESTANDING = 432, - EMOTE_STATE_STEALTH_STAND = 433, - EMOTE_ONESHOT_OMNICAST_GHOUL = 434, - EMOTE_ONESHOT_ATTACKBOW = 435, - EMOTE_ONESHOT_ATTACKRIFLE = 436, - EMOTE_STATE_SWIM_IDLE = 437, - EMOTE_STATE_ATTACK_UNARMED = 438, - EMOTE_ONESHOT_SPELLCAST_W_SOUND = 439, - EMOTE_ONESHOT_DODGE = 440, - EMOTE_ONESHOT_PARRY1H = 441, - EMOTE_ONESHOT_PARRY2H = 442, - EMOTE_ONESHOT_PARRY2HL = 443, - EMOTE_STATE_FLYFALL = 444, - EMOTE_ONESHOT_FLYDEATH = 445, - EMOTE_STATE_FLY_FALL = 446, - EMOTE_ONESHOT_FLY_SIT_GROUND_DOWN = 447, - EMOTE_ONESHOT_FLY_SIT_GROUND_UP = 448, - EMOTE_ONESHOT_EMERGE = 449, - EMOTE_ONESHOT_DRAGONSPIT = 450, - EMOTE_STATE_SPECIALUNARMED = 451, - EMOTE_ONESHOT_FLYGRAB = 452, - EMOTE_STATE_FLYGRABCLOSED = 453, - EMOTE_ONESHOT_FLYGRABTHROWN = 454, - EMOTE_STATE_FLY_SIT_GROUND = 455, - EMOTE_STATE_WALKBACKWARDS = 456, - EMOTE_ONESHOT_FLYTALK = 457, - EMOTE_ONESHOT_FLYATTACK1H = 458, - EMOTE_STATE_CUSTOMSPELL08 = 459, - EMOTE_ONESHOT_FLY_DRAGONSPIT = 460, - EMOTE_STATE_SIT_CHAIR_LOW = 461, - EMOTE_ONE_SHOT_STUN = 462, - EMOTE_ONESHOT_SPELLCAST_OMNI = 463, - EMOTE_STATE_READYTHROWN = 464 -}; - + EMOTE_ONESHOT_NONE = 0, + EMOTE_ONESHOT_TALK = 1, + EMOTE_ONESHOT_BOW = 2, + EMOTE_ONESHOT_WAVE = 3, + EMOTE_ONESHOT_CHEER = 4, + EMOTE_ONESHOT_EXCLAMATION = 5, + EMOTE_ONESHOT_QUESTION = 6, + EMOTE_ONESHOT_EAT = 7, + EMOTE_STATE_DANCE = 10, + EMOTE_ONESHOT_LAUGH = 11, + EMOTE_STATE_SLEEP = 12, + EMOTE_STATE_SIT = 13, + EMOTE_ONESHOT_RUDE = 14, + EMOTE_ONESHOT_ROAR = 15, + EMOTE_ONESHOT_KNEEL = 16, + EMOTE_ONESHOT_KISS = 17, + EMOTE_ONESHOT_CRY = 18, + EMOTE_ONESHOT_CHICKEN = 19, + EMOTE_ONESHOT_BEG = 20, + EMOTE_ONESHOT_APPLAUD = 21, + EMOTE_ONESHOT_SHOUT = 22, + EMOTE_ONESHOT_FLEX = 23, + EMOTE_ONESHOT_SHY = 24, + EMOTE_ONESHOT_POINT = 25, + EMOTE_STATE_STAND = 26, + EMOTE_STATE_READY_UNARMED = 27, + EMOTE_STATE_WORK_SHEATHED = 28, + EMOTE_STATE_POINT = 29, + EMOTE_STATE_NONE = 30, + EMOTE_ONESHOT_WOUND = 33, + EMOTE_ONESHOT_WOUND_CRITICAL = 34, + EMOTE_ONESHOT_ATTACK_UNARMED = 35, + EMOTE_ONESHOT_ATTACK1H = 36, + EMOTE_ONESHOT_ATTACK2HTIGHT = 37, + EMOTE_ONESHOT_ATTACK2H_LOOSE = 38, + EMOTE_ONESHOT_PARRY_UNARMED = 39, + EMOTE_ONESHOT_PARRY_SHIELD = 43, + EMOTE_ONESHOT_READY_UNARMED = 44, + EMOTE_ONESHOT_READY1H = 45, + EMOTE_ONESHOT_READY_BOW = 48, + EMOTE_ONESHOT_SPELL_PRECAST = 50, + EMOTE_ONESHOT_SPELL_CAST = 51, + EMOTE_ONESHOT_BATTLE_ROAR = 53, + EMOTE_ONESHOT_SPECIALATTACK1H = 54, + EMOTE_ONESHOT_KICK = 60, + EMOTE_ONESHOT_ATTACK_THROWN = 61, + EMOTE_STATE_STUN = 64, + EMOTE_STATE_DEAD = 65, + EMOTE_ONESHOT_SALUTE = 66, + EMOTE_STATE_KNEEL = 68, + EMOTE_STATE_USE_STANDING = 69, + EMOTE_ONESHOT_WAVE_NO_SHEATHE = 70, + EMOTE_ONESHOT_CHEER_NO_SHEATHE = 71, + EMOTE_ONESHOT_EAT_NO_SHEATHE = 92, + EMOTE_STATE_STUN_NO_SHEATHE = 93, + EMOTE_ONESHOT_DANCE = 94, + EMOTE_ONESHOT_SALUTE_NO_SHEATH = 113, + EMOTE_STATE_USE_STANDING_NO_SHEATHE = 133, + EMOTE_ONESHOT_LAUGH_NO_SHEATHE = 153, + EMOTE_STATE_WORK = 173, + EMOTE_STATE_SPELL_PRECAST = 193, + EMOTE_ONESHOT_READY_RIFLE = 213, + EMOTE_STATE_READY_RIFLE = 214, + EMOTE_STATE_WORK_MINING = 233, + EMOTE_STATE_WORK_CHOPWOOD = 234, + EMOTE_STATE_APPLAUD = 253, + EMOTE_ONESHOT_LIFTOFF = 254, + EMOTE_ONESHOT_YES = 273, + EMOTE_ONESHOT_NO = 274, + EMOTE_ONESHOT_TRAIN = 275, + EMOTE_ONESHOT_LAND = 293, + EMOTE_STATE_AT_EASE = 313, + EMOTE_STATE_READY1H = 333, + EMOTE_STATE_SPELL_KNEEL_START = 353, + EMOTE_STATE_SUBMERGED = 373, + EMOTE_ONESHOT_SUBMERGE = 374, + EMOTE_STATE_READY2H = 375, + EMOTE_STATE_READY_BOW = 376, + EMOTE_ONESHOT_MOUNT_SPECIAL = 377, + EMOTE_STATE_TALK = 378, + EMOTE_STATE_FISHING = 379, + EMOTE_ONESHOT_FISHING = 380, + EMOTE_ONESHOT_LOOT = 381, + EMOTE_STATE_WHIRLWIND = 382, + EMOTE_STATE_DROWNED = 383, + EMOTE_STATE_HOLD_BOW = 384, + EMOTE_STATE_HOLD_RIFLE = 385, + EMOTE_STATE_HOLD_THROWN = 386, + EMOTE_ONESHOT_DROWN = 387, + EMOTE_ONESHOT_STOMP = 388, + EMOTE_ONESHOT_ATTACK_OFF = 389, + EMOTE_ONESHOT_ATTACK_OFF_PIERCE = 390, + EMOTE_STATE_ROAR = 391, + EMOTE_STATE_LAUGH = 392, + EMOTE_ONESHOT_CREATURE_SPECIAL = 393, + EMOTE_ONESHOT_JUMPLANDRUN = 394, + EMOTE_ONESHOT_JUMPEND = 395, + EMOTE_ONESHOT_TALK_NO_SHEATHE = 396, + EMOTE_ONESHOT_POINT_NO_SHEATHE = 397, + EMOTE_STATE_CANNIBALIZE = 398, + EMOTE_ONESHOT_JUMPSTART = 399, + EMOTE_STATE_DANCESPECIAL = 400, + EMOTE_ONESHOT_DANCESPECIAL = 401, + EMOTE_ONESHOT_CUSTOM_SPELL_01 = 402, + EMOTE_ONESHOT_CUSTOM_SPELL_02 = 403, + EMOTE_ONESHOT_CUSTOM_SPELL_03 = 404, + EMOTE_ONESHOT_CUSTOM_SPELL_04 = 405, + EMOTE_ONESHOT_CUSTOM_SPELL_05 = 406, + EMOTE_ONESHOT_CUSTOM_SPELL_06 = 407, + EMOTE_ONESHOT_CUSTOM_SPELL_07 = 408, + EMOTE_ONESHOT_CUSTOM_SPELL_08 = 409, + EMOTE_ONESHOT_CUSTOM_SPELL_09 = 410, + EMOTE_ONESHOT_CUSTOM_SPELL_10 = 411, + EMOTE_STATE_EXCLAIM = 412, + EMOTE_STATE_DANCE_CUSTOM = 413, + EMOTE_STATE_SIT_CHAIR_MED = 415, + EMOTE_STATE_CUSTOM_SPELL_01 = 416, + EMOTE_STATE_CUSTOM_SPELL_02 = 417, + EMOTE_STATE_EAT = 418, + EMOTE_STATE_CUSTOM_SPELL_04 = 419, + EMOTE_STATE_CUSTOM_SPELL_03 = 420, + EMOTE_STATE_CUSTOM_SPELL_05 = 421, + EMOTE_STATE_SPELLEFFECT_HOLD = 422, + EMOTE_STATE_EAT_NO_SHEATHE = 423, + EMOTE_STATE_MOUNT = 424, + EMOTE_STATE_READY2HL = 425, + EMOTE_STATE_SIT_CHAIR_HIGH = 426, + EMOTE_STATE_FALL = 427, + EMOTE_STATE_LOOT = 428, + EMOTE_STATE_SUBMERGED_NEW = 429, + EMOTE_ONESHOT_COWER = 430, + EMOTE_STATE_COWER = 431, + EMOTE_ONESHOT_USE_STANDING = 432, + EMOTE_STATE_STEALTH_STAND = 433, + EMOTE_ONESHOT_OMNICAST_GHOUL = 434, + EMOTE_ONESHOT_ATTACK_BOW = 435, + EMOTE_ONESHOT_ATTACK_RIFLE = 436, + EMOTE_STATE_SWIM_IDLE = 437, + EMOTE_STATE_ATTACK_UNARMED = 438, + EMOTE_ONESHOT_SPELL_CAST_W_SOUND = 439, + EMOTE_ONESHOT_DODGE = 440, + EMOTE_ONESHOT_PARRY1H = 441, + EMOTE_ONESHOT_PARRY2H = 442, + EMOTE_ONESHOT_PARRY2HL = 443, + EMOTE_STATE_FLYFALL = 444, + EMOTE_ONESHOT_FLYDEATH = 445, + EMOTE_STATE_FLY_FALL = 446, + EMOTE_ONESHOT_FLY_SIT_GROUND_DOWN = 447, + EMOTE_ONESHOT_FLY_SIT_GROUND_UP = 448, + EMOTE_ONESHOT_EMERGE = 449, + EMOTE_ONESHOT_DRAGON_SPIT = 450, + EMOTE_STATE_SPECIAL_UNARMED = 451, + EMOTE_ONESHOT_FLYGRAB = 452, + EMOTE_STATE_FLYGRABCLOSED = 453, + EMOTE_ONESHOT_FLYGRABTHROWN = 454, + EMOTE_STATE_FLY_SIT_GROUND = 455, + EMOTE_STATE_WALK_BACKWARDS = 456, + EMOTE_ONESHOT_FLYTALK = 457, + EMOTE_ONESHOT_FLYATTACK1H = 458, + EMOTE_STATE_CUSTOM_SPELL_08 = 459, + EMOTE_ONESHOT_FLY_DRAGON_SPIT = 460, + EMOTE_STATE_SIT_CHAIR_LOW = 461, + EMOTE_ONESHOT_STUN = 462, + EMOTE_ONESHOT_SPELL_CAST_OMNI = 463, + EMOTE_STATE_READY_THROWN = 465, + EMOTE_ONESHOT_WORK_CHOPWOOD = 466, + EMOTE_ONESHOT_WORK_MINING = 467, + EMOTE_STATE_SPELL_CHANNEL_OMNI = 468, + EMOTE_STATE_SPELL_CHANNEL_DIRECTED = 469, + EMOTE_STAND_STATE_NONE = 470, + EMOTE_STATE_READYJOUST = 471, + EMOTE_STATE_STRANGULATE = 473, + EMOTE_STATE_READY_SPELL_OMNI = 474, + EMOTE_STATE_HOLD_JOUST = 475, + EMOTE_ONESHOT_CRY_JAINA = 476 +}; + +// AnimationData.dbc enum Anim { - ANIM_STAND = 0x0, - ANIM_DEATH = 0x1, - ANIM_SPELL = 0x2, - ANIM_STOP = 0x3, - ANIM_WALK = 0x4, - ANIM_RUN = 0x5, - ANIM_DEAD = 0x6, - ANIM_RISE = 0x7, - ANIM_STANDWOUND = 0x8, - ANIM_COMBATWOUND = 0x9, - ANIM_COMBATCRITICAL = 0xA, - ANIM_SHUFFLE_LEFT = 0xB, - ANIM_SHUFFLE_RIGHT = 0xC, - ANIM_WALK_BACKWARDS = 0xD, - ANIM_STUN = 0xE, - ANIM_HANDS_CLOSED = 0xF, - ANIM_ATTACKUNARMED = 0x10, - ANIM_ATTACK1H = 0x11, - ANIM_ATTACK2HTIGHT = 0x12, - ANIM_ATTACK2HLOOSE = 0x13, - ANIM_PARRYUNARMED = 0x14, - ANIM_PARRY1H = 0x15, - ANIM_PARRY2HTIGHT = 0x16, - ANIM_PARRY2HLOOSE = 0x17, - ANIM_PARRYSHIELD = 0x18, - ANIM_READYUNARMED = 0x19, - ANIM_READY1H = 0x1A, - ANIM_READY2HTIGHT = 0x1B, - ANIM_READY2HLOOSE = 0x1C, - ANIM_READYBOW = 0x1D, - ANIM_DODGE = 0x1E, - ANIM_SPELLPRECAST = 0x1F, - ANIM_SPELLCAST = 0x20, - ANIM_SPELLCASTAREA = 0x21, - ANIM_NPCWELCOME = 0x22, - ANIM_NPCGOODBYE = 0x23, - ANIM_BLOCK = 0x24, - ANIM_JUMPSTART = 0x25, - ANIM_JUMP = 0x26, - ANIM_JUMPEND = 0x27, - ANIM_FALL = 0x28, - ANIM_SWIMIDLE = 0x29, - ANIM_SWIM = 0x2A, - ANIM_SWIM_LEFT = 0x2B, - ANIM_SWIM_RIGHT = 0x2C, - ANIM_SWIM_BACKWARDS = 0x2D, - ANIM_ATTACKBOW = 0x2E, - ANIM_FIREBOW = 0x2F, - ANIM_READYRIFLE = 0x30, - ANIM_ATTACKRIFLE = 0x31, - ANIM_LOOT = 0x32, - ANIM_SPELL_PRECAST_DIRECTED = 0x33, - ANIM_SPELL_PRECAST_OMNI = 0x34, - ANIM_SPELL_CAST_DIRECTED = 0x35, - ANIM_SPELL_CAST_OMNI = 0x36, - ANIM_SPELL_BATTLEROAR = 0x37, - ANIM_SPELL_READYABILITY = 0x38, - ANIM_SPELL_SPECIAL1H = 0x39, - ANIM_SPELL_SPECIAL2H = 0x3A, - ANIM_SPELL_SHIELDBASH = 0x3B, - ANIM_EMOTE_TALK = 0x3C, - ANIM_EMOTE_EAT = 0x3D, - ANIM_EMOTE_WORK = 0x3E, - ANIM_EMOTE_USE_STANDING = 0x3F, - ANIM_EMOTE_EXCLAMATION = 0x40, - ANIM_EMOTE_QUESTION = 0x41, - ANIM_EMOTE_BOW = 0x42, - ANIM_EMOTE_WAVE = 0x43, - ANIM_EMOTE_CHEER = 0x44, - ANIM_EMOTE_DANCE = 0x45, - ANIM_EMOTE_LAUGH = 0x46, - ANIM_EMOTE_SLEEP = 0x47, - ANIM_EMOTE_SIT_GROUND = 0x48, - ANIM_EMOTE_RUDE = 0x49, - ANIM_EMOTE_ROAR = 0x4A, - ANIM_EMOTE_KNEEL = 0x4B, - ANIM_EMOTE_KISS = 0x4C, - ANIM_EMOTE_CRY = 0x4D, - ANIM_EMOTE_CHICKEN = 0x4E, - ANIM_EMOTE_BEG = 0x4F, - ANIM_EMOTE_APPLAUD = 0x50, - ANIM_EMOTE_SHOUT = 0x51, - ANIM_EMOTE_FLEX = 0x52, - ANIM_EMOTE_SHY = 0x53, - ANIM_EMOTE_POINT = 0x54, - ANIM_ATTACK1HPIERCE = 0x55, - ANIM_ATTACK2HLOOSEPIERCE = 0x56, - ANIM_ATTACKOFF = 0x57, - ANIM_ATTACKOFFPIERCE = 0x58, - ANIM_SHEATHE = 0x59, - ANIM_HIPSHEATHE = 0x5A, - ANIM_MOUNT = 0x5B, - ANIM_RUN_LEANRIGHT = 0x5C, - ANIM_RUN_LEANLEFT = 0x5D, - ANIM_MOUNT_SPECIAL = 0x5E, - ANIM_KICK = 0x5F, - ANIM_SITDOWN = 0x60, - ANIM_SITTING = 0x61, - ANIM_SITUP = 0x62, - ANIM_SLEEPDOWN = 0x63, - ANIM_SLEEPING = 0x64, - ANIM_SLEEPUP = 0x65, - ANIM_SITCHAIRLOW = 0x66, - ANIM_SITCHAIRMEDIUM = 0x67, - ANIM_SITCHAIRHIGH = 0x68, - ANIM_LOADBOW = 0x69, - ANIM_LOADRIFLE = 0x6A, - ANIM_ATTACKTHROWN = 0x6B, - ANIM_READYTHROWN = 0x6C, - ANIM_HOLDBOW = 0x6D, - ANIM_HOLDRIFLE = 0x6E, - ANIM_HOLDTHROWN = 0x6F, - ANIM_LOADTHROWN = 0x70, - ANIM_EMOTE_SALUTE = 0x71, - ANIM_KNEELDOWN = 0x72, - ANIM_KNEELING = 0x73, - ANIM_KNEELUP = 0x74, - ANIM_ATTACKUNARMEDOFF = 0x75, - ANIM_SPECIALUNARMED = 0x76, - ANIM_STEALTHWALK = 0x77, - ANIM_STEALTHSTAND = 0x78, - ANIM_KNOCKDOWN = 0x79, - ANIM_EATING = 0x7A, - ANIM_USESTANDINGLOOP = 0x7B, - ANIM_CHANNELCASTDIRECTED = 0x7C, - ANIM_CHANNELCASTOMNI = 0x7D, - ANIM_WHIRLWIND = 0x7E, - ANIM_BIRTH = 0x7F, - ANIM_USESTANDINGSTART = 0x80, - ANIM_USESTANDINGEND = 0x81, - ANIM_HOWL = 0x82, - ANIM_DROWN = 0x83, - ANIM_DROWNED = 0x84, - ANIM_FISHINGCAST = 0x85, - ANIM_FISHINGLOOP = 0x86, - ANIM_FLY = 0x87, - ANIM_EMOTE_WORK_NO_SHEATHE = 0x88, - ANIM_EMOTE_STUN_NO_SHEATHE = 0x89, - ANIM_EMOTE_USE_STANDING_NO_SHEATHE= 0x8A, - ANIM_SPELL_SLEEP_DOWN = 0x8B, - ANIM_SPELL_KNEEL_START = 0x8C, - ANIM_SPELL_KNEEL_LOOP = 0x8D, - ANIM_SPELL_KNEEL_END = 0x8E, - ANIM_SPRINT = 0x8F, - ANIM_IN_FIGHT = 0x90, - - ANIM_GAMEOBJ_SPAWN = 145, - ANIM_GAMEOBJ_CLOSE = 146, - ANIM_GAMEOBJ_CLOSED = 147, - ANIM_GAMEOBJ_OPEN = 148, - ANIM_GAMEOBJ_OPENED = 149, - ANIM_GAMEOBJ_DESTROY = 150, - ANIM_GAMEOBJ_DESTROYED = 151, - ANIM_GAMEOBJ_REBUILD = 152, - ANIM_GAMEOBJ_CUSTOM0 = 153, - ANIM_GAMEOBJ_CUSTOM1 = 154, - ANIM_GAMEOBJ_CUSTOM2 = 155, - ANIM_GAMEOBJ_CUSTOM3 = 156, - ANIM_GAMEOBJ_DESPAWN = 157, - ANIM_HOLD = 158, - ANIM_DECAY = 159, - ANIM_BOWPULL = 160, - ANIM_BOWRELEASE = 161, - ANIM_SHIPSTART = 162, - ANIM_SHIPMOVEING = 163, - ANIM_SHIPSTOP = 164, - ANIM_GROUPARROW = 165, - ANIM_ARROW = 166, - ANIM_CORPSEARROW = 167, - ANIM_GUIDEARROW = 168, - ANIM_SWAY = 169, - ANIM_DRUIDCATPOUNCE = 170, - ANIM_DRUIDCATRIP = 171, - ANIM_DRUIDCATRAKE = 172, - ANIM_DRUIDCATRAVAGE = 173, - ANIM_DRUIDCATCLAW = 174, - ANIM_DRUIDCATCOWER = 175, - ANIM_DRUIDBEARSWIPE = 176, - ANIM_DRUIDBEARBITE = 177, - ANIM_DRUIDBEARMAUL = 178, - ANIM_DRUIDBEARBASH = 179, - ANIM_DRAGONTAIL = 180, - ANIM_DRAGONSTOMP = 181, - ANIM_DRAGONSPIT = 182, - ANIM_DRAGONSPITHOVER = 183, - ANIM_DRAGONSPITFLY = 184, - ANIM_EMOTEYES = 185, - ANIM_EMOTENO = 186, - ANIM_JUMPLANDRUN = 187, - ANIM_LOOTHOLD = 188, - ANIM_LOOTUP = 189, - ANIM_STANDHIGH = 190, - ANIM_IMPACT = 191, - ANIM_LIFTOFF = 192, - ANIM_HOVER = 193, - ANIM_SUCCUBUSENTICE = 194, - ANIM_EMOTETRAIN = 195, - ANIM_EMOTEDEAD = 196, - ANIM_EMOTEDANCEONCE = 197, - ANIM_DEFLECT = 198, - ANIM_EMOTEEATNOSHEATHE = 199, - ANIM_LAND = 200, - ANIM_SUBMERGE = 201, - ANIM_SUBMERGED = 202, - ANIM_CANNIBALIZE = 203, - ANIM_ARROWBIRTH = 204, - ANIM_GROURARROWBIRTH = 205, - ANIM_CORPSEARROWBIRTH = 206, - ANIM_GUIDEARROWBIRTH = 207, - ANIM_EMOTETALKNOSHEATHE = 208, - ANIM_EMOTEPOINTNOSHEATHE = 209, - ANIM_EMOTESALUTENOSHEATHE = 210, - ANIM_EMOTEDANCESPECIAL = 211, - ANIM_MUTILATE = 212, - ANIM_CUSTOMSPELL01 = 213, - ANIM_CUSTOMSPELL02 = 214, - ANIM_CUSTOMSPELL03 = 215, - ANIM_CUSTOMSPELL04 = 216, - ANIM_CUSTOMSPELL05 = 217, - ANIM_CUSTOMSPELL06 = 218, - ANIM_CUSTOMSPELL07 = 219, - ANIM_CUSTOMSPELL08 = 220, - ANIM_CUSTOMSPELL09 = 221, - ANIM_CUSTOMSPELL10 = 222, - ANIM_StealthRun = 223 + ANIM_STAND = 0, + ANIM_DEATH = 1, + ANIM_SPELL = 2, + ANIM_STOP = 3, + ANIM_WALK = 4, + ANIM_RUN = 5, + ANIM_DEAD = 6, + ANIM_RISE = 7, + ANIM_STAND_WOUND = 8, + ANIM_COMBAT_WOUND = 9, + ANIM_COMBAT_CRITICAL = 10, + ANIM_SHUFFLE_LEFT = 11, + ANIM_SHUFFLE_RIGHT = 12, + ANIM_WALK_BACKWARDS = 13, + ANIM_STUN = 14, + ANIM_HANDS_CLOSED = 15, + ANIM_ATTACK_UNARMED = 16, + ANIM_ATTACK1H = 17, + ANIM_ATTACK2H = 18, + ANIM_ATTACK2HL = 19, + ANIM_PARRY_UNARMED = 20, + ANIM_PARRY1H = 21, + ANIM_PARRY2H = 22, + ANIM_PARRY2HL = 23, + ANIM_SHIELD_BLOCK = 24, + ANIM_READY_UNARMED = 25, + ANIM_READY1H = 26, + ANIM_READY2H = 27, + ANIM_READY2HL = 28, + ANIM_READY_BOW = 29, + ANIM_DODGE = 30, + ANIM_SPELL_PRECAST = 31, + ANIM_SPELL_CAST = 32, + ANIM_SPELL_CAST_AREA = 33, + ANIM_NPC_WELCOME = 34, + ANIM_NPC_GOODBYE = 35, + ANIM_BLOCK = 36, + ANIM_JUMP_START = 37, + ANIM_JUMP = 38, + ANIM_JUMP_END = 39, + ANIM_FALL = 40, + ANIM_SWIM_IDLE = 41, + ANIM_SWIM = 42, + ANIM_SWIM_LEFT = 43, + ANIM_SWIM_RIGHT = 44, + ANIM_SWIM_BACKWARDS = 45, + ANIM_ATTACK_BOW = 46, + ANIM_FIRE_BOW = 47, + ANIM_READY_RIFLE = 48, + ANIM_ATTACK_RIFLE = 49, + ANIM_LOOT = 50, + ANIM_READY_SPELL_DIRECTED = 51, + ANIM_READY_SPELL_OMNI = 52, + ANIM_SPELL_CAST_DIRECTED = 53, + ANIM_SPELL_CAST_OMNI = 54, + ANIM_BATTLE_ROAR = 55, + ANIM_READY_ABILITY = 56, + ANIM_SPECIAL1H = 57, + ANIM_SPECIAL2H = 58, + ANIM_SHIELD_BASH = 59, + ANIM_EMOTE_TALK = 60, + ANIM_EMOTE_EAT = 61, + ANIM_EMOTE_WORK = 62, + ANIM_EMOTE_USE_STANDING = 63, + ANIM_EMOTE_TALK_EXCLAMATION = 64, + ANIM_EMOTE_TALK_QUESTION = 65, + ANIM_EMOTE_BOW = 66, + ANIM_EMOTE_WAVE = 67, + ANIM_EMOTE_CHEER = 68, + ANIM_EMOTE_DANCE = 69, + ANIM_EMOTE_LAUGH = 70, + ANIM_EMOTE_SLEEP = 71, + ANIM_EMOTE_SIT_GROUND = 72, + ANIM_EMOTE_RUDE = 73, + ANIM_EMOTE_ROAR = 74, + ANIM_EMOTE_KNEEL = 75, + ANIM_EMOTE_KISS = 76, + ANIM_EMOTE_CRY = 77, + ANIM_EMOTE_CHICKEN = 78, + ANIM_EMOTE_BEG = 79, + ANIM_EMOTE_APPLAUD = 80, + ANIM_EMOTE_SHOUT = 81, + ANIM_EMOTE_FLEX = 82, + ANIM_EMOTE_SHY = 83, + ANIM_EMOTE_POINT = 84, + ANIM_ATTACK1H_PIERCE = 85, + ANIM_ATTACK2H_LOOSE_PIERCE = 86, + ANIM_ATTACK_OFF = 87, + ANIM_ATTACK_OFF_PIERCE = 88, + ANIM_SHEATHE = 89, + ANIM_HIP_SHEATHE = 90, + ANIM_MOUNT = 91, + ANIM_RUN_RIGHT = 92, + ANIM_RUN_LEFT = 93, + ANIM_MOUNT_SPECIAL = 94, + ANIM_KICK = 95, + ANIM_SIT_GROUND_DOWN = 96, + ANIM_SIT_GROUND = 97, + ANIM_SIT_GROUND_UP = 98, + ANIM_SLEEP_DOWN = 99, + ANIM_SLEEP = 100, + ANIM_SLEEP_UP = 101, + ANIM_SIT_CHAIR_LOW = 102, + ANIM_SIT_CHAIR_MED = 103, + ANIM_SIT_CHAIR_HIGH = 104, + ANIM_LOAD_BOW = 105, + ANIM_LOAD_RIFLE = 106, + ANIM_ATTACK_THROWN = 107, + ANIM_READY_THROWN = 108, + ANIM_HOLD_BOW = 109, + ANIM_HOLD_RIFLE = 110, + ANIM_HOLD_THROWN = 111, + ANIM_LOAD_THROWN = 112, + ANIM_EMOTE_SALUTE = 113, + ANIM_KNEEL_START = 114, + ANIM_KNEEL_LOOP = 115, + ANIM_KNEEL_END = 116, + ANIM_ATTACK_UNARMED_OFF = 117, + ANIM_SPECIAL_UNARMED = 118, + ANIM_STEALTH_WALK = 119, + ANIM_STEALTH_STAND = 120, + ANIM_KNOCKDOWN = 121, + ANIM_EATING_LOOP = 122, + ANIM_USE_STANDING_LOOP = 123, + ANIM_CHANNEL_CAST_DIRECTED = 124, + ANIM_CHANNEL_CAST_OMNI = 125, + ANIM_WHIRLWIND = 126, + ANIM_BIRTH = 127, + ANIM_USE_STANDING_START = 128, + ANIM_USE_STANDING_END = 129, + ANIM_CREATURE_SPECIAL = 130, + ANIM_DROWN = 131, + ANIM_DROWNED = 132, + ANIM_FISHING_CAST = 133, + ANIM_FISHING_LOOP = 134, + ANIM_FLY = 135, + ANIM_EMOTE_WORK_NO_SHEATHE = 136, + ANIM_EMOTE_STUN_NO_SHEATHE = 137, + ANIM_EMOTE_USE_STANDING_NO_SHEATHE = 138, + ANIM_SPELL_SLEEP_DOWN = 139, + ANIM_SPELL_KNEEL_START = 140, + ANIM_SPELL_KNEEL_LOOP = 141, + ANIM_SPELL_KNEEL_END = 142, + ANIM_SPRINT = 143, + ANIM_IN_FIGHT = 144, + ANIM_SPAWN = 145, + ANIM_CLOSE = 146, + ANIM_CLOSED = 147, + ANIM_OPEN = 148, + ANIM_OPENED = 149, + ANIM_DESTROY = 150, + ANIM_DESTROYED = 151, + ANIM_REBUILD = 152, + ANIM_CUSTOM_0 = 153, + ANIM_CUSTOM_1 = 154, + ANIM_CUSTOM_2 = 155, + ANIM_CUSTOM_3 = 156, + ANIM_DESPAWN = 157, + ANIM_HOLD = 158, + ANIM_DECAY = 159, + ANIM_BOW_PULL = 160, + ANIM_BOW_RELEASE = 161, + ANIM_SHIP_START = 162, + ANIM_SHIP_MOVING = 163, + ANIM_SHIP_STOP = 164, + ANIM_GROUP_ARROW = 165, + ANIM_ARROW = 166, + ANIM_CORPSE_ARROW = 167, + ANIM_GUIDE_ARROW = 168, + ANIM_SWAY = 169, + ANIM_DRUID_CAT_POUNCE = 170, + ANIM_DRUID_CAT_RIP = 171, + ANIM_DRUID_CAT_RAKE = 172, + ANIM_DRUID_CAT_RAVAGE = 173, + ANIM_DRUID_CAT_CLAW = 174, + ANIM_DRUID_CAT_COWER = 175, + ANIM_DRUID_BEAR_SWIPE = 176, + ANIM_DRUID_BEAR_BITE = 177, + ANIM_DRUID_BEAR_MAUL = 178, + ANIM_DRUID_BEAR_BASH = 179, + ANIM_DRAGON_TAIL = 180, + ANIM_DRAGON_STOMP = 181, + ANIM_DRAGON_SPIT = 182, + ANIM_DRAGON_SPIT_HOVER = 183, + ANIM_DRAGON_SPIT_FLY = 184, + ANIM_EMOTE_YES = 185, + ANIM_EMOTE_NO = 186, + ANIM_JUMP_LAND_RUN = 187, + ANIM_LOOT_HOLD = 188, + ANIM_LOOT_UP = 189, + ANIM_STAND_HIGH = 190, + ANIM_IMPACT = 191, + ANIM_LIFTOFF = 192, + ANIM_HOVER = 193, + ANIM_SUCCUBUS_ENTICE = 194, + ANIM_EMOTE_TRAIN = 195, + ANIM_EMOTE_DEAD = 196, + ANIM_EMOTE_DANCE_ONCE = 197, + ANIM_DEFLECT = 198, + ANIM_EMOTE_EAT_NO_SHEATHE = 199, + ANIM_LAND = 200, + ANIM_SUBMERGE = 201, + ANIM_SUBMERGED = 202, + ANIM_CANNIBALIZE = 203, + ANIM_ARROW_BIRTH = 204, + ANIM_GROUP_ARROW_BIRTH = 205, + ANIM_CORPSE_ARROW_BIRTH = 206, + ANIM_GUIDE_ARROW_BIRTH = 207, + ANIM_EMOTE_TALK_NO_SHEATHE = 208, + ANIM_EMOTE_POINT_NO_SHEATHE = 209, + ANIM_EMOTE_SALUTE_NO_SHEATHE = 210, + ANIM_EMOTE_DANCE_SPECIAL = 211, + ANIM_MUTILATE = 212, + ANIM_CUSTOM_SPELL_01 = 213, + ANIM_CUSTOM_SPELL_02 = 214, + ANIM_CUSTOM_SPELL_03 = 215, + ANIM_CUSTOM_SPELL_04 = 216, + ANIM_CUSTOM_SPELL_05 = 217, + ANIM_CUSTOM_SPELL_06 = 218, + ANIM_CUSTOM_SPELL_07 = 219, + ANIM_CUSTOM_SPELL_08 = 220, + ANIM_CUSTOM_SPELL_09 = 221, + ANIM_CUSTOM_SPELL_10 = 222, + ANIM_STEALTH_RUN = 223, + ANIM_EMERGE = 224, + ANIM_COWER = 225, + ANIM_GRAB = 226, + ANIM_GRAB_CLOSED = 227, + ANIM_GRAB_THROWN = 228, + ANIM_FLY_STAND = 229, + ANIM_FLY_DEATH = 230, + ANIM_FLY_SPELL = 231, + ANIM_FLY_STOP = 232, + ANIM_FLY_WALK = 233, + ANIM_FLY_RUN = 234, + ANIM_FLY_DEAD = 235, + ANIM_FLY_RISE = 236, + ANIM_FLY_STAND_WOUND = 237, + ANIM_FLY_COMBAT_WOUND = 238, + ANIM_FLY_COMBAT_CRITICAL = 239, + ANIM_FLY_SHUFFLE_LEFT = 240, + ANIM_FLY_SHUFFLE_RIGHT = 241, + ANIM_FLY_WALK_BACKWARDS = 242, + ANIM_FLY_STUN = 243, + ANIM_FLY_HANDS_CLOSED = 244, + ANIM_FLY_ATTACK_UNARMED = 245, + ANIM_FLY_ATTACK1H = 246, + ANIM_FLY_ATTACK2H = 247, + ANIM_FLY_ATTACK2HL = 248, + ANIM_FLY_PARRY_UNARMED = 249, + ANIM_FLY_PARRY1H = 250, + ANIM_FLY_PARRY2H = 251, + ANIM_FLY_PARRY2HL = 252, + ANIM_FLY_SHIELD_BLOCK = 253, + ANIM_FLY_READY_UNARMED = 254, + ANIM_FLY_READY1H = 255, + ANIM_FLY_READY2H = 256, + ANIM_FLY_READY2HL = 257, + ANIM_FLY_READY_BOW = 258, + ANIM_FLY_DODGE = 259, + ANIM_FLY_SPELL_PRECAST = 260, + ANIM_FLY_SPELL_CAST = 261, + ANIM_FLY_SPELL_CAST_AREA = 262, + ANIM_FLY_NPC_WELCOME = 263, + ANIM_FLY_NPC_GOODBYE = 264, + ANIM_FLY_BLOCK = 265, + ANIM_FLY_JUMP_START = 266, + ANIM_FLY_JUMP = 267, + ANIM_FLY_JUMP_END = 268, + ANIM_FLY_FALL = 269, + ANIM_FLY_SWIM_IDLE = 270, + ANIM_FLY_SWIM = 271, + ANIM_FLY_SWIM_LEFT = 272, + ANIM_FLY_SWIM_RIGHT = 273, + ANIM_FLY_SWIM_BACKWARDS = 274, + ANIM_FLY_ATTACK_BOW = 275, + ANIM_FLY_FIRE_BOW = 276, + ANIM_FLY_READY_RIFLE = 277, + ANIM_FLY_ATTACK_RIFLE = 278, + ANIM_FLY_LOOT = 279, + ANIM_FLY_READY_SPELL_DIRECTED = 280, + ANIM_FLY_READY_SPELL_OMNI = 281, + ANIM_FLY_SPELL_CAST_DIRECTED = 282, + ANIM_FLY_SPELL_CAST_OMNI = 283, + ANIM_FLY_SPELL_BATTLE_ROAR = 284, + ANIM_FLY_READY_ABILITY = 285, + ANIM_FLY_SPECIAL1H = 286, + ANIM_FLY_SPECIAL2H = 287, + ANIM_FLY_SHIELD_BASH = 288, + ANIM_FLY_EMOTE_TALK = 289, + ANIM_FLY_EMOTE_EAT = 290, + ANIM_FLY_EMOTE_WORK = 291, + ANIM_FLY_USE_STANDING = 292, + ANIM_FLY_EMOTE_TALK_EXCLAMATION = 293, + ANIM_FLY_EMOTE_TALK_QUESTION = 294, + ANIM_FLY_EMOTE_BOW = 295, + ANIM_FLY_EMOTE_WAVE = 296, + ANIM_FLY_EMOTE_CHEER = 297, + ANIM_FLY_EMOTE_DANCE = 298, + ANIM_FLY_EMOTE_LAUGH = 299, + ANIM_FLY_EMOTE_SLEEP = 300, + ANIM_FLY_EMOTE_SIT_GROUND = 301, + ANIM_FLY_EMOTE_RUDE = 302, + ANIM_FLY_EMOTE_ROAR = 303, + ANIM_FLY_EMOTE_KNEEL = 304, + ANIM_FLY_EMOTE_KISS = 305, + ANIM_FLY_EMOTE_CRY = 306, + ANIM_FLY_EMOTE_CHICKEN = 307, + ANIM_FLY_EMOTE_BEG = 308, + ANIM_FLY_EMOTE_APPLAUD = 309, + ANIM_FLY_EMOTE_SHOUT = 310, + ANIM_FLY_EMOTE_FLEX = 311, + ANIM_FLY_EMOTE_SHY = 312, + ANIM_FLY_EMOTE_POINT = 313, + ANIM_FLY_ATTACK1H_PIERCE = 314, + ANIM_FLY_ATTACK2H_LOOSE_PIERCE = 315, + ANIM_FLY_ATTACK_OFF = 316, + ANIM_FLY_ATTACK_OFF_PIERCE = 317, + ANIM_FLY_SHEATH = 318, + ANIM_FLY_HIP_SHEATH = 319, + ANIM_FLY_MOUNT = 320, + ANIM_FLY_RUN_RIGHT = 321, + ANIM_FLY_RUN_LEFT = 322, + ANIM_FLY_MOUNT_SPECIAL = 323, + ANIM_FLY_KICK = 324, + ANIM_FLY_SIT_GROUND_DOWN = 325, + ANIM_FLY_SIT_GROUND = 326, + ANIM_FLY_SIT_GROUND_UP = 327, + ANIM_FLY_SLEEP_DOWN = 328, + ANIM_FLY_SLEEP = 329, + ANIM_FLY_SLEEP_UP = 330, + ANIM_FLY_SIT_CHAIR_LOW = 331, + ANIM_FLY_SIT_CHAIR_MED = 332, + ANIM_FLY_SIT_CHAIR_HIGH = 333, + ANIM_FLY_LOAD_BOW = 334, + ANIM_FLY_LOAD_RIFLE = 335, + ANIM_FLY_ATTACK_THROWN = 336, + ANIM_FLY_READY_THROWN = 337, + ANIM_FLY_HOLD_BOW = 338, + ANIM_FLY_HOLD_RIFLE = 339, + ANIM_FLY_HOLD_THROWN = 340, + ANIM_FLY_LOAD_THROWN = 341, + ANIM_FLY_EMOTE_SALUTE = 342, + ANIM_FLY_KNEEL_START = 343, + ANIM_FLY_KNEEL_LOOP = 344, + ANIM_FLY_KNEEL_END = 345, + ANIM_FLY_ATTACK_UNARMED_OFF = 346, + ANIM_FLY_SPECIAL_UNARMED = 347, + ANIM_FLY_STEALTH_WALK = 348, + ANIM_FLY_STEALTH_STAND = 349, + ANIM_FLY_KNOCKDOWN = 350, + ANIM_FLY_EATING_LOOP = 351, + ANIM_FLY_USE_STANDING_LOOP = 352, + ANIM_FLY_CHANNEL_CAST_DIRECTED = 353, + ANIM_FLY_CHANNEL_CAST_OMNI = 354, + ANIM_FLY_WHIRLWIND = 355, + ANIM_FLY_BIRTH = 356, + ANIM_FLY_USE_STANDING_START = 357, + ANIM_FLY_USE_STANDING_END = 358, + ANIM_FLY_CREATURE_SPECIAL = 359, + ANIM_FLY_DROWN = 360, + ANIM_FLY_DROWNED = 361, + ANIM_FLY_FISHING_CAST = 362, + ANIM_FLY_FISHING_LOOP = 363, + ANIM_FLY_FLY = 364, + ANIM_FLY_EMOTE_WORK_NO_SHEATHE = 365, + ANIM_FLY_EMOTE_STUN_NO_SHEATHE = 366, + ANIM_FLY_EMOTE_USE_STANDING_NO_SHEATHE = 367, + ANIM_FLY_SPELL_SLEEP_DOWN = 368, + ANIM_FLY_SPELL_KNEEL_START = 369, + ANIM_FLY_SPELL_KNEEL_LOOP = 370, + ANIM_FLY_SPELL_KNEEL_END = 371, + ANIM_FLY_SPRINT = 372, + ANIM_FLY_IN_FLIGHT = 373, + ANIM_FLY_SPAWN = 374, + ANIM_FLY_CLOSE = 375, + ANIM_FLY_CLOSED = 376, + ANIM_FLY_OPEN = 377, + ANIM_FLY_OPENED = 378, + ANIM_FLY_DESTROY = 379, + ANIM_FLY_DESTROYED = 380, + ANIM_FLY_REBUILD = 381, + ANIM_FLY_CUSTOM_0 = 382, + ANIM_FLY_CUSTOM_1 = 383, + ANIM_FLY_CUSTOM_2 = 384, + ANIM_FLY_CUSTOM_3 = 385, + ANIM_FLY_DESPAWN = 386, + ANIM_FLY_HOLD = 387, + ANIM_FLY_DECAY = 388, + ANIM_FLY_BOW_PULL = 389, + ANIM_FLY_BOW_RELEASE = 390, + ANIM_FLY_SHIP_START = 391, + ANIM_FLY_SHIP_MOVING = 392, + ANIM_FLY_SHIP_STOP = 393, + ANIM_FLY_GROUP_ARROW = 394, + ANIM_FLY_ARROW = 395, + ANIM_FLY_CORPSE_ARROW = 396, + ANIM_FLY_GUIDE_ARROW = 397, + ANIM_FLY_SWAY = 398, + ANIM_FLY_DRUID_CAT_POUNCE = 399, + ANIM_FLY_DRUID_CAT_RIP = 400, + ANIM_FLY_DRUID_CAT_RAKE = 401, + ANIM_FLY_DRUID_CAT_RAVAGE = 402, + ANIM_FLY_DRUID_CAT_CLAW = 403, + ANIM_FLY_DRUID_CAT_COWER = 404, + ANIM_FLY_DRUID_BEAR_SWIPE = 405, + ANIM_FLY_DRUID_BEAR_BITE = 406, + ANIM_FLY_DRUID_BEAR_MAUL = 407, + ANIM_FLY_DRUID_BEAR_BASH = 408, + ANIM_FLY_DRAGON_TAIL = 409, + ANIM_FLY_DRAGON_STOMP = 410, + ANIM_FLY_DRAGON_SPIT = 411, + ANIM_FLY_DRAGON_SPIT_HOVER = 412, + ANIM_FLY_DRAGON_SPIT_FLY = 413, + ANIM_FLY_EMOTE_YES = 414, + ANIM_FLY_EMOTE_NO = 415, + ANIM_FLY_JUMP_LAND_RUN = 416, + ANIM_FLY_LOOT_HOLD = 417, + ANIM_FLY_LOOT_UP = 418, + ANIM_FLY_STAND_HIGH = 419, + ANIM_FLY_IMPACT = 420, + ANIM_FLY_LIFTOFF = 421, + ANIM_FLY_HOVER = 422, + ANIM_FLY_SUCCUBUS_ENTICE = 423, + ANIM_FLY_EMOTE_TRAIN = 424, + ANIM_FLY_EMOTE_DEAD = 425, + ANIM_FLY_EMOTE_DANCE_ONCE = 426, + ANIM_FLY_DEFLECT = 427, + ANIM_FLY_EMOTE_EAT_NO_SHEATHE = 428, + ANIM_FLY_LAND = 429, + ANIM_FLY_SUBMERGE = 430, + ANIM_FLY_SUBMERGED = 431, + ANIM_FLY_CANNIBALIZE = 432, + ANIM_FLY_ARROW_BIRTH = 433, + ANIM_FLY_GROUP_ARROW_BIRTH = 434, + ANIM_FLY_CORPSE_ARROW_BIRTH = 435, + ANIM_FLY_GUIDE_ARROW_BIRTH = 436, + ANIM_FLY_EMOTE_TALK_NO_SHEATHE = 437, + ANIM_FLY_EMOTE_POINT_NO_SHEATHE = 438, + ANIM_FLY_EMOTE_SALUTE_NO_SHEATHE = 439, + ANIM_FLY_EMOTE_DANCE_SPECIAL = 440, + ANIM_FLY_MUTILATE = 441, + ANIM_FLY_CUSTOM_SPELL_01 = 442, + ANIM_FLY_CUSTOM_SPELL_02 = 443, + ANIM_FLY_CUSTOM_SPELL_03 = 444, + ANIM_FLY_CUSTOM_SPELL_04 = 445, + ANIM_FLY_CUSTOM_SPELL_05 = 446, + ANIM_FLY_CUSTOM_SPELL_06 = 447, + ANIM_FLY_CUSTOM_SPELL_07 = 448, + ANIM_FLY_CUSTOM_SPELL_08 = 449, + ANIM_FLY_CUSTOM_SPELL_09 = 450, + ANIM_FLY_CUSTOM_SPELL_10 = 451, + ANIM_FLY_STEALTH_RUN = 452, + ANIM_FLY_EMERGE = 453, + ANIM_FLY_COWER = 454, + ANIM_FLY_GRAB = 455, + ANIM_FLY_GRAB_CLOSED = 456, + ANIM_FLY_GRAB_THROWN = 457, + ANIM_TO_FLY = 458, + ANIM_TO_HOVER = 459, + ANIM_TO_GROUND = 460, + ANIM_FLY_TO_FLY = 461, + ANIM_FLY_TO_HOVER = 462, + ANIM_FLY_TO_GROUND = 463, + ANIM_SETTLE = 464, + ANIM_FLY_SETTLE = 465, + ANIM_DEATH_START = 466, + ANIM_DEATH_LOOP = 467, + ANIM_DEATH_END = 468, + ANIM_FLY_DEATH_START = 469, + ANIM_FLY_DEATH_LOOP = 470, + ANIM_FLY_DEATH_END = 471, + ANIM_DEATH_END_HOLD = 472, + ANIM_FLY_DEATH_END_HOLD = 473, + ANIM_STRANGULATE = 474, + ANIM_FLY_STRANGULATE = 475, + ANIM_READY_JOUST = 476, + ANIM_LOAD_JOUST = 477, + ANIM_HOLD_JOUST = 478, + ANIM_FLY_READY_JOUST = 479, + ANIM_FLY_LOAD_JOUST = 480, + ANIM_FLY_HOLD_JOUST = 481, + ANIM_ATTACK_JOUST = 482, + ANIM_FLY_ATTACK_JOUST = 483, + ANIM_RECLINED_MOUNT = 484, + ANIM_FLY_RECLINED_MOUNT = 485, + ANIM_TO_ALTERED = 486, + ANIM_FROM_ALTERED = 487, + ANIM_FLY_TO_ALTERED = 488, + ANIM_FLY_FROM_ALTERED = 489, + ANIM_IN_STOCKS = 490, + ANIM_FLY_IN_STOCKS = 491, + ANIM_VEHICLE_GRAB = 492, + ANIM_VEHICLE_THROW = 493, + ANIM_FLY_VEHICLE_GRAB = 494, + ANIM_FLY_VEHICLE_THROW = 495, + ANIM_TO_ALTERED_POST_SWAP = 496, + ANIM_FROM_ALTERED_POST_SWAP = 497, + ANIM_FLY_TO_ALTERED_POST_SWAP = 498, + ANIM_FLY_FROM_ALTERED_POST_SWAP = 499, + ANIM_RECLINED_MOUNT_PASSENGER = 500, + ANIM_FLY_RECLINED_MOUNT_PASSENGER = 501, + ANIM_CARRY2H = 502, + ANIM_CARRIED2H = 503, + ANIM_FLY_CARRY2H = 504, + ANIM_FLY_CARRIED2H = 505 }; enum LockKeyType @@ -2413,7 +2710,7 @@ enum HolidayIds HOLIDAY_HARVEST_FESTIVAL = 321, HOLIDAY_HALLOWS_END = 324, HOLIDAY_LUNAR_FESTIVAL = 327, - HOLIDAY_LOVE_IS_IN_THE_AIR = 335, + // HOLIDAY_LOVE_IS_IN_THE_AIR = 335, unused/duplicated HOLIDAY_FIRE_FESTIVAL = 341, HOLIDAY_CALL_TO_ARMS_EY = 353, HOLIDAY_BREWFEST = 372, @@ -2426,7 +2723,7 @@ enum HolidayIds HOLIDAY_WOTLK_LAUNCH = 406, HOLIDAY_DAY_OF_DEAD = 409, HOLIDAY_CALL_TO_ARMS_IC = 420, - HOLIDAY_LOVE_IS_IN_THE_AIR_2 = 423, + HOLIDAY_LOVE_IS_IN_THE_AIR = 423, HOLIDAY_KALU_AK_FISHING_DERBY = 424, HOLIDAY_CALL_TO_ARMS_BFG = 435, HOLIDAY_CALL_TO_ARMS_TP = 436, @@ -2561,8 +2858,8 @@ enum SkillType SKILL_SURVIVAL2 = 142, SKILL_RIDING_HORSE = 148, SKILL_RIDING_WOLF = 149, - SKILL_RIDING_RAM = 152, SKILL_RIDING_TIGER = 150, + SKILL_RIDING_RAM = 152, SKILL_SWIMING = 155, SKILL_2H_MACES = 160, SKILL_UNARMED = 162, @@ -3245,4 +3542,21 @@ enum RemoveMethod GROUP_REMOVEMETHOD_LEAVE = 2, }; +enum ActivateTaxiReply +{ + ERR_TAXIOK = 0, + ERR_TAXIUNSPECIFIEDSERVERERROR = 1, + ERR_TAXINOSUCHPATH = 2, + ERR_TAXINOTENOUGHMONEY = 3, + ERR_TAXITOOFARAWAY = 4, + ERR_TAXINOVENDORNEARBY = 5, + ERR_TAXINOTVISITED = 6, + ERR_TAXIPLAYERBUSY = 7, + ERR_TAXIPLAYERALREADYMOUNTED = 8, + ERR_TAXIPLAYERSHAPESHIFTED = 9, + ERR_TAXIPLAYERMOVING = 10, + ERR_TAXISAMENODE = 11, + ERR_TAXINOTSTANDING = 12 +}; + #endif diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 4945ae2a014..27816753ca7 100755 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -53,9 +53,9 @@ void MotionMaster::Initialize() // set new default movement generator void MotionMaster::InitDefault() { - if (i_owner->GetTypeId() == TYPEID_UNIT) + if (_owner->GetTypeId() == TYPEID_UNIT) { - MovementGenerator* movement = FactorySelector::selectMovementGenerator(i_owner->ToCreature()); + MovementGenerator* movement = FactorySelector::selectMovementGenerator(_owner->ToCreature()); Mutate(movement == NULL ? &si_idleMovement : movement, MOTION_SLOT_IDLE); } else @@ -77,42 +77,42 @@ MotionMaster::~MotionMaster() void MotionMaster::UpdateMotion(uint32 diff) { - if (!i_owner) + if (!_owner) return; - if (i_owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) // what about UNIT_STATE_DISTRACTED? Why is this not included? + if (_owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) // what about UNIT_STATE_DISTRACTED? Why is this not included? return; ASSERT(!empty()); - m_cleanFlag |= MMCF_UPDATE; - if (!top()->Update(*i_owner, diff)) + _cleanFlag |= MMCF_UPDATE; + if (!top()->Update(*_owner, diff)) { - m_cleanFlag &= ~MMCF_UPDATE; + _cleanFlag &= ~MMCF_UPDATE; MovementExpired(); } else - m_cleanFlag &= ~MMCF_UPDATE; + _cleanFlag &= ~MMCF_UPDATE; - if (m_expList) + if (_expList) { - for (size_t i = 0; i < m_expList->size(); ++i) + for (size_t i = 0; i < _expList->size(); ++i) { - MovementGenerator* mg = (*m_expList)[i]; + MovementGenerator* mg = (*_expList)[i]; DirectDelete(mg); } - delete m_expList; - m_expList = NULL; + delete _expList; + _expList = NULL; if (empty()) Initialize(); else if (needInitTop()) InitTop(); - else if (m_cleanFlag & MMCF_RESET) - top()->Reset(*i_owner); + else if (_cleanFlag & MMCF_RESET) + top()->Reset(*_owner); - m_cleanFlag &= ~MMCF_RESET; + _cleanFlag &= ~MMCF_RESET; } } @@ -128,7 +128,7 @@ void MotionMaster::DirectClean(bool reset) if (needInitTop()) InitTop(); else if (reset) - top()->Reset(*i_owner); + top()->Reset(*_owner); } void MotionMaster::DelayedClean() @@ -152,14 +152,14 @@ void MotionMaster::DirectExpire(bool reset) } while (!top()) - --i_top; + --_top; if (empty()) Initialize(); else if (needInitTop()) InitTop(); else if (reset) - top()->Reset(*i_owner); + top()->Reset(*_owner); } void MotionMaster::DelayedExpire() @@ -172,7 +172,7 @@ void MotionMaster::DelayedExpire() } while (!top()) - --i_top; + --_top; } void MotionMaster::MoveIdle() @@ -184,9 +184,9 @@ void MotionMaster::MoveIdle() void MotionMaster::MoveRandom(float spawndist) { - if (i_owner->GetTypeId() == TYPEID_UNIT) + if (_owner->GetTypeId() == TYPEID_UNIT) { - sLog->outStaticDebug("Creature (GUID: %u) start moving random", i_owner->GetGUIDLow()); + sLog->outStaticDebug("Creature (GUID: %u) start moving random", _owner->GetGUIDLow()); Mutate(new RandomMovementGenerator<Creature>(spawndist), MOTION_SLOT_IDLE); } } @@ -195,15 +195,15 @@ void MotionMaster::MoveTargetedHome() { Clear(false); - if (i_owner->GetTypeId()==TYPEID_UNIT && !((Creature*)i_owner)->GetCharmerOrOwnerGUID()) + if (_owner->GetTypeId()==TYPEID_UNIT && !((Creature*)_owner)->GetCharmerOrOwnerGUID()) { - sLog->outStaticDebug("Creature (Entry: %u GUID: %u) targeted home", i_owner->GetEntry(), i_owner->GetGUIDLow()); + sLog->outStaticDebug("Creature (Entry: %u GUID: %u) targeted home", _owner->GetEntry(), _owner->GetGUIDLow()); Mutate(new HomeMovementGenerator<Creature>(), MOTION_SLOT_ACTIVE); } - else if (i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID()) + else if (_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)_owner)->GetCharmerOrOwnerGUID()) { - sLog->outStaticDebug("Pet or controlled creature (Entry: %u GUID: %u) targeting home", i_owner->GetEntry(), i_owner->GetGUIDLow() ); - Unit *target = ((Creature*)i_owner)->GetCharmerOrOwner(); + sLog->outStaticDebug("Pet or controlled creature (Entry: %u GUID: %u) targeting home", _owner->GetEntry(), _owner->GetGUIDLow() ); + Unit *target = ((Creature*)_owner)->GetCharmerOrOwner(); if (target) { sLog->outStaticDebug("Following %s (GUID: %u)", target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() ); @@ -212,21 +212,21 @@ void MotionMaster::MoveTargetedHome() } else { - sLog->outError("Player (GUID: %u) attempt targeted home", i_owner->GetGUIDLow()); + sLog->outError("Player (GUID: %u) attempt targeted home", _owner->GetGUIDLow()); } } void MotionMaster::MoveConfused() { - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_PLAYER) { - sLog->outStaticDebug("Player (GUID: %u) move confused", i_owner->GetGUIDLow()); + sLog->outStaticDebug("Player (GUID: %u) move confused", _owner->GetGUIDLow()); Mutate(new ConfusedMovementGenerator<Player>(), MOTION_SLOT_CONTROLLED); } else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) move confused", - i_owner->GetEntry(), i_owner->GetGUIDLow()); + _owner->GetEntry(), _owner->GetGUIDLow()); Mutate(new ConfusedMovementGenerator<Creature>(), MOTION_SLOT_CONTROLLED); } } @@ -234,14 +234,14 @@ void MotionMaster::MoveConfused() void MotionMaster::MoveChase(Unit* target, float dist, float angle) { // ignore movement request if target not exist - if (!target || target == i_owner || i_owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) + if (!target || target == _owner || _owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) return; - //i_owner->ClearUnitState(UNIT_STATE_FOLLOW); - if (i_owner->GetTypeId() == TYPEID_PLAYER) + //_owner->ClearUnitState(UNIT_STATE_FOLLOW); + if (_owner->GetTypeId() == TYPEID_PLAYER) { sLog->outStaticDebug("Player (GUID: %u) chase to %s (GUID: %u)", - i_owner->GetGUIDLow(), + _owner->GetGUIDLow(), target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow()); Mutate(new ChaseMovementGenerator<Player>(*target,dist,angle), MOTION_SLOT_ACTIVE); @@ -249,7 +249,7 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle) else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) chase to %s (GUID: %u)", - i_owner->GetEntry(), i_owner->GetGUIDLow(), + _owner->GetEntry(), _owner->GetGUIDLow(), target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow()); Mutate(new ChaseMovementGenerator<Creature>(*target,dist,angle), MOTION_SLOT_ACTIVE); @@ -259,13 +259,13 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle) void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlot slot) { // ignore movement request if target not exist - if (!target || target == i_owner || i_owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) + if (!target || target == _owner || _owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) return; - //i_owner->AddUnitState(UNIT_STATE_FOLLOW); - if (i_owner->GetTypeId() == TYPEID_PLAYER) + //_owner->AddUnitState(UNIT_STATE_FOLLOW); + if (_owner->GetTypeId() == TYPEID_PLAYER) { - sLog->outStaticDebug("Player (GUID: %u) follow to %s (GUID: %u)", i_owner->GetGUIDLow(), + sLog->outStaticDebug("Player (GUID: %u) follow to %s (GUID: %u)", _owner->GetGUIDLow(), target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow()); Mutate(new FollowMovementGenerator<Player>(*target,dist,angle), slot); @@ -273,7 +273,7 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlo else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) follow to %s (GUID: %u)", - i_owner->GetEntry(), i_owner->GetGUIDLow(), + _owner->GetEntry(), _owner->GetGUIDLow(), target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow()); Mutate(new FollowMovementGenerator<Creature>(*target,dist,angle), slot); @@ -282,15 +282,15 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlo void MotionMaster::MovePoint(uint32 id, float x, float y, float z) { - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_PLAYER) { - sLog->outStaticDebug("Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), id, x, y, z); + sLog->outStaticDebug("Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), id, x, y, z); Mutate(new PointMovementGenerator<Player>(id, x, y, z), MOTION_SLOT_ACTIVE); } else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)", - i_owner->GetEntry(), i_owner->GetGUIDLow(), id, x, y, z); + _owner->GetEntry(), _owner->GetGUIDLow(), id, x, y, z); Mutate(new PointMovementGenerator<Creature>(id, x, y, z), MOTION_SLOT_ACTIVE); } } @@ -300,9 +300,9 @@ void MotionMaster::MoveLand(uint32 id, Position const& pos, float speed) float x, y, z; pos.GetPosition(x, y, z); - sLog->outStaticDebug("Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)", i_owner->GetEntry(), id, x, y, z); + sLog->outStaticDebug("Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)", _owner->GetEntry(), id, x, y, z); - Movement::MoveSplineInit init(*i_owner); + Movement::MoveSplineInit init(*_owner); init.MoveTo(x,y,z); init.SetVelocity(speed); init.SetAnimation(Movement::ToGround); @@ -315,9 +315,9 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed) float x, y, z; pos.GetPosition(x, y, z); - sLog->outStaticDebug("Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)", i_owner->GetEntry(), id, x, y, z); + sLog->outStaticDebug("Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)", _owner->GetEntry(), id, x, y, z); - Movement::MoveSplineInit init(*i_owner); + Movement::MoveSplineInit init(*_owner); init.MoveTo(x,y,z); init.SetVelocity(speed); init.SetAnimation(Movement::ToFly); @@ -328,66 +328,63 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed) void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ) { //this function may make players fall below map - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_PLAYER) return; float x, y, z; float moveTimeHalf = speedZ / Movement::gravity; float dist = 2 * moveTimeHalf * speedXY; - i_owner->GetNearPoint(i_owner, x, y, z, i_owner->GetObjectSize(), dist, i_owner->GetAngle(srcX, srcY) + M_PI); + _owner->GetNearPoint(_owner, x, y, z, _owner->GetObjectSize(), dist, _owner->GetAngle(srcX, srcY) + M_PI); MoveJump(x, y, z, speedXY, speedZ); } void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ) { //this function may make players fall below map - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_PLAYER) return; float x, y, z; float moveTimeHalf = speedZ / Movement::gravity; float dist = 2 * moveTimeHalf * speedXY; - i_owner->GetClosePoint(x, y, z, i_owner->GetObjectSize(), dist, angle); + _owner->GetClosePoint(x, y, z, _owner->GetObjectSize(), dist, angle); MoveJump(x, y, z, speedXY, speedZ); } void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id) { - sLog->outStaticDebug("Unit (GUID: %u) jump to point (X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), x, y, z); + sLog->outStaticDebug("Unit (GUID: %u) jump to point (X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), x, y, z); float moveTimeHalf = speedZ / Movement::gravity; float max_height = -Movement::computeFallElevation(moveTimeHalf,false,-speedZ); - Movement::MoveSplineInit init(*i_owner); + Movement::MoveSplineInit init(*_owner); init.MoveTo(x,y,z); init.SetParabolic(max_height,0); init.SetVelocity(speedXY); init.Launch(); - if (i_owner->GetTypeId() == TYPEID_PLAYER) - Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED); - else - Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE); + Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED); } void MotionMaster::MoveFall(uint32 id/*=0*/) { // use larger distance for vmap height search than in most other cases - float tz = i_owner->GetMap()->GetHeight(i_owner->GetPositionX(), i_owner->GetPositionY(), i_owner->GetPositionZ(), true, MAX_FALL_DISTANCE); + float tz = _owner->GetMap()->GetHeight(_owner->GetPhaseMask(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ(), true, MAX_FALL_DISTANCE); if (tz <= INVALID_HEIGHT) { sLog->outStaticDebug("MotionMaster::MoveFall: unable retrive a proper height at map %u (x: %f, y: %f, z: %f).", - i_owner->GetMap()->GetId(), i_owner->GetPositionX(), i_owner->GetPositionX(), i_owner->GetPositionZ()); + _owner->GetMap()->GetId(), _owner->GetPositionX(), _owner->GetPositionX(), _owner->GetPositionZ()); return; } // Abort too if the ground is very near - if (fabs(i_owner->GetPositionZ() - tz) < 0.1f) + if (fabs(_owner->GetPositionZ() - tz) < 0.1f) return; - Movement::MoveSplineInit init(*i_owner); - init.MoveTo(i_owner->GetPositionX(),i_owner->GetPositionY(),tz); + Movement::MoveSplineInit init(*_owner); + init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz); init.SetFall(); init.Launch(); Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED); @@ -398,45 +395,45 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id) if (Impl[MOTION_SLOT_CONTROLLED] && Impl[MOTION_SLOT_CONTROLLED]->GetMovementGeneratorType() != DISTRACT_MOTION_TYPE) return; - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_PLAYER) { - sLog->outStaticDebug("Player (GUID: %u) charge point (X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), x, y, z); + sLog->outStaticDebug("Player (GUID: %u) charge point (X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), x, y, z); Mutate(new PointMovementGenerator<Player>(id, x, y, z, speed), MOTION_SLOT_CONTROLLED); } else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) charge point (X: %f Y: %f Z: %f)", - i_owner->GetEntry(), i_owner->GetGUIDLow(), x, y, z); + _owner->GetEntry(), _owner->GetGUIDLow(), x, y, z); Mutate(new PointMovementGenerator<Creature>(id, x, y, z, speed), MOTION_SLOT_CONTROLLED); } } void MotionMaster::MoveSeekAssistance(float x, float y, float z) { - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_PLAYER) { - sLog->outError("Player (GUID: %u) attempt to seek assistance", i_owner->GetGUIDLow()); + sLog->outError("Player (GUID: %u) attempt to seek assistance", _owner->GetGUIDLow()); } else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) seek assistance (X: %f Y: %f Z: %f)", - i_owner->GetEntry(), i_owner->GetGUIDLow(), x, y, z); - i_owner->AttackStop(); - i_owner->ToCreature()->SetReactState(REACT_PASSIVE); + _owner->GetEntry(), _owner->GetGUIDLow(), x, y, z); + _owner->AttackStop(); + _owner->ToCreature()->SetReactState(REACT_PASSIVE); Mutate(new AssistanceMovementGenerator(x, y, z), MOTION_SLOT_ACTIVE); } } void MotionMaster::MoveSeekAssistanceDistract(uint32 time) { - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_PLAYER) { - sLog->outError("Player (GUID: %u) attempt to call distract after assistance", i_owner->GetGUIDLow()); + sLog->outError("Player (GUID: %u) attempt to call distract after assistance", _owner->GetGUIDLow()); } else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) is distracted after assistance call (Time: %u)", - i_owner->GetEntry(), i_owner->GetGUIDLow(), time); + _owner->GetEntry(), _owner->GetGUIDLow(), time); Mutate(new AssistanceDistractMovementGenerator(time), MOTION_SLOT_ACTIVE); } } @@ -446,12 +443,12 @@ void MotionMaster::MoveFleeing(Unit* enemy, uint32 time) if (!enemy) return; - if (i_owner->HasAuraType(SPELL_AURA_PREVENTS_FLEEING)) + if (_owner->HasAuraType(SPELL_AURA_PREVENTS_FLEEING)) return; - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_PLAYER) { - sLog->outStaticDebug("Player (GUID: %u) flee from %s (GUID: %u)", i_owner->GetGUIDLow(), + sLog->outStaticDebug("Player (GUID: %u) flee from %s (GUID: %u)", _owner->GetGUIDLow(), enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUIDLow() : enemy->ToCreature()->GetDBTableGUIDLow()); Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); @@ -459,7 +456,7 @@ void MotionMaster::MoveFleeing(Unit* enemy, uint32 time) else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) flee from %s (GUID: %u)%s", - i_owner->GetEntry(), i_owner->GetGUIDLow(), + _owner->GetEntry(), _owner->GetGUIDLow(), enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUIDLow() : enemy->ToCreature()->GetDBTableGUIDLow(), time ? " for a limited time" : ""); @@ -472,24 +469,24 @@ void MotionMaster::MoveFleeing(Unit* enemy, uint32 time) void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) { - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_PLAYER) { if (path < sTaxiPathNodesByPath.size()) { - sLog->outStaticDebug("%s taxi to (Path %u node %u)", i_owner->GetName(), path, pathnode); + sLog->outStaticDebug("%s taxi to (Path %u node %u)", _owner->GetName(), path, pathnode); FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(sTaxiPathNodesByPath[path], pathnode); Mutate(mgen, MOTION_SLOT_CONTROLLED); } else { sLog->outError("%s attempt taxi to (not existed Path %u node %u)", - i_owner->GetName(), path, pathnode); + _owner->GetName(), path, pathnode); } } else { sLog->outError("Creature (Entry: %u GUID: %u) attempt taxi to (Path %u node %u)", - i_owner->GetEntry(), i_owner->GetGUIDLow(), path, pathnode); + _owner->GetEntry(), _owner->GetGUIDLow(), path, pathnode); } } @@ -498,14 +495,14 @@ void MotionMaster::MoveDistract(uint32 timer) if (Impl[MOTION_SLOT_CONTROLLED]) return; - if (i_owner->GetTypeId() == TYPEID_PLAYER) + if (_owner->GetTypeId() == TYPEID_PLAYER) { - sLog->outStaticDebug("Player (GUID: %u) distracted (timer: %u)", i_owner->GetGUIDLow(), timer); + sLog->outStaticDebug("Player (GUID: %u) distracted (timer: %u)", _owner->GetGUIDLow(), timer); } else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) (timer: %u)", - i_owner->GetEntry(), i_owner->GetGUIDLow(), timer); + _owner->GetEntry(), _owner->GetGUIDLow(), timer); } DistractMovementGenerator* mgen = new DistractMovementGenerator(timer); @@ -517,23 +514,23 @@ void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot) if (MovementGenerator *curr = Impl[slot]) { Impl[slot] = NULL; // in case a new one is generated in this slot during directdelete - if (i_top == slot && (m_cleanFlag & MMCF_UPDATE)) + if (_top == slot && (_cleanFlag & MMCF_UPDATE)) DelayedDelete(curr); else DirectDelete(curr); } - else if (i_top < slot) + else if (_top < slot) { - i_top = slot; + _top = slot; } Impl[slot] = m; - if (i_top > slot) - needInit[slot] = true; + if (_top > slot) + _needInit[slot] = true; else { - needInit[slot] = false; - m->Initialize(*i_owner); + _needInit[slot] = false; + m->Initialize(*_owner); } } @@ -546,19 +543,19 @@ void MotionMaster::MovePath(uint32 path_id, bool repeatable) /*while (!empty()) { MovementGenerator *curr = top(); - curr->Finalize(*i_owner); + curr->Finalize(*_owner); pop(); if (!isStatic(curr)) delete curr; }*/ - //i_owner->GetTypeId() == TYPEID_PLAYER ? + //_owner->GetTypeId() == TYPEID_PLAYER ? //Mutate(new WaypointMovementGenerator<Player>(path_id, repeatable)): Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable), MOTION_SLOT_IDLE); sLog->outStaticDebug("%s (GUID: %u) start moving over path(Id:%u, repeatable: %s)", - i_owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", - i_owner->GetGUIDLow(), path_id, repeatable ? "YES" : "NO"); + _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", + _owner->GetGUIDLow(), path_id, repeatable ? "YES" : "NO"); } void MotionMaster::MoveRotate(uint32 time, RotateDirection direction) @@ -576,7 +573,7 @@ void MotionMaster::propagateSpeedChange() { (*it)->unitSpeedChanged(); }*/ - for (int i = 0; i <= i_top; ++i) + for (int i = 0; i <= _top; ++i) { if (Impl[i]) Impl[i]->unitSpeedChanged(); @@ -601,34 +598,34 @@ MovementGeneratorType MotionMaster::GetMotionSlotType(int slot) const void MotionMaster::InitTop() { - top()->Initialize(*i_owner); - needInit[i_top] = false; + top()->Initialize(*_owner); + _needInit[_top] = false; } void MotionMaster::DirectDelete(_Ty curr) { if (isStatic(curr)) return; - curr->Finalize(*i_owner); + curr->Finalize(*_owner); delete curr; } void MotionMaster::DelayedDelete(_Ty curr) { - sLog->outCrash("Unit (Entry %u) is trying to delete its updating MG (Type %u)!", i_owner->GetEntry(), curr->GetMovementGeneratorType()); + sLog->outCrash("Unit (Entry %u) is trying to delete its updating MG (Type %u)!", _owner->GetEntry(), curr->GetMovementGeneratorType()); if (isStatic(curr)) return; - if (!m_expList) - m_expList = new ExpireList(); - m_expList->push_back(curr); + if (!_expList) + _expList = new ExpireList(); + _expList->push_back(curr); } bool MotionMaster::GetDestination(float &x, float &y, float &z) { - if (i_owner->movespline->Finalized()) + if (_owner->movespline->Finalized()) return false; - const G3D::Vector3& dest = i_owner->movespline->FinalDestination(); + const G3D::Vector3& dest = _owner->movespline->FinalDestination(); x = dest.x; y = dest.y; z = dest.z; diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index a5bd0861b04..d6144bfcc3a 100755 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -83,24 +83,25 @@ class MotionMaster //: private std::stack<MovementGenerator *> private: //typedef std::stack<MovementGenerator *> Impl; typedef MovementGenerator* _Ty; - _Ty Impl[MAX_MOTION_SLOT]; - bool needInit[MAX_MOTION_SLOT]; - typedef std::vector<_Ty> ExpireList; - int i_top; - void pop() { Impl[i_top] = NULL; --i_top; } - void push(_Ty _Val) { ++i_top; Impl[i_top] = _Val; } + void pop() + { + Impl[_top] = NULL; + while (!top()) + --_top; + } + void push(_Ty _Val) { ++_top; Impl[_top] = _Val; } - bool needInitTop() const { return needInit[i_top]; } + bool needInitTop() const { return _needInit[_top]; } void InitTop(); public: - explicit MotionMaster(Unit* unit) : i_top(-1), i_owner(unit), m_expList(NULL), m_cleanFlag(MMCF_NONE) + explicit MotionMaster(Unit* unit) : _expList(NULL), _top(-1), _owner(unit), _cleanFlag(MMCF_NONE) { for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i) { Impl[i] = NULL; - needInit[i] = true; + _needInit[i] = true; } } ~MotionMaster(); @@ -108,9 +109,9 @@ class MotionMaster //: private std::stack<MovementGenerator *> void Initialize(); void InitDefault(); - bool empty() const { return (i_top < 0); } - int size() const { return i_top + 1; } - _Ty top() const { return Impl[i_top]; } + bool empty() const { return (_top < 0); } + int size() const { return _top + 1; } + _Ty top() const { return Impl[_top]; } _Ty GetMotionSlot(int slot) const { return Impl[slot]; } void DirectDelete(_Ty curr); @@ -119,12 +120,12 @@ class MotionMaster //: private std::stack<MovementGenerator *> void UpdateMotion(uint32 diff); void Clear(bool reset = true) { - if (m_cleanFlag & MMCF_UPDATE) + if (_cleanFlag & MMCF_UPDATE) { if (reset) - m_cleanFlag |= MMCF_RESET; + _cleanFlag |= MMCF_RESET; else - m_cleanFlag &= ~MMCF_RESET; + _cleanFlag &= ~MMCF_RESET; DelayedClean(); } else @@ -132,12 +133,12 @@ class MotionMaster //: private std::stack<MovementGenerator *> } void MovementExpired(bool reset = true) { - if (m_cleanFlag & MMCF_UPDATE) + if (_cleanFlag & MMCF_UPDATE) { if (reset) - m_cleanFlag |= MMCF_RESET; + _cleanFlag |= MMCF_RESET; else - m_cleanFlag &= ~MMCF_RESET; + _cleanFlag &= ~MMCF_RESET; DelayedExpire(); } else @@ -187,9 +188,13 @@ class MotionMaster //: private std::stack<MovementGenerator *> void DirectExpire(bool reset); void DelayedExpire(); - Unit *i_owner; - ExpireList* m_expList; - uint8 m_cleanFlag; + typedef std::vector<_Ty> ExpireList; + ExpireList* _expList; + _Ty Impl[MAX_MOTION_SLOT]; + int _top; + Unit* _owner; + bool _needInit[MAX_MOTION_SLOT]; + uint8 _cleanFlag; }; #endif diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index ed5b73dd378..216afbb2b20 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -157,7 +157,7 @@ FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z) y = temp_y; return true; } - float new_z = _map->GetHeight(temp_x, temp_y, z, true); + float new_z = _map->GetHeight(owner.GetPhaseMask(), temp_x, temp_y, z, true); if (new_z <= INVALID_HEIGHT) continue; @@ -169,8 +169,8 @@ FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z) if (!(new_z - z) || distance / fabs(new_z - z) > 1.0f) { - float new_z_left = _map->GetHeight(temp_x + 1.0f*cos(angle+static_cast<float>(M_PI/2)),temp_y + 1.0f*sin(angle+static_cast<float>(M_PI/2)),z,true); - float new_z_right = _map->GetHeight(temp_x + 1.0f*cos(angle-static_cast<float>(M_PI/2)),temp_y + 1.0f*sin(angle-static_cast<float>(M_PI/2)),z,true); + float new_z_left = _map->GetHeight(owner.GetPhaseMask(), temp_x + 1.0f*cos(angle+static_cast<float>(M_PI/2)),temp_y + 1.0f*sin(angle+static_cast<float>(M_PI/2)),z,true); + float new_z_right = _map->GetHeight(owner.GetPhaseMask(), temp_x + 1.0f*cos(angle-static_cast<float>(M_PI/2)),temp_y + 1.0f*sin(angle-static_cast<float>(M_PI/2)),z,true); if (fabs(new_z_left - new_z) < 1.2f && fabs(new_z_right - new_z) < 1.2f) { x = temp_x; diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index dc47898352e..5725aec54f6 100755 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -57,7 +57,7 @@ void HomeMovementGenerator<Creature>::_setTargetLocation(Creature & owner) owner.ClearUnitState(UNIT_STATE_ALL_STATE & ~UNIT_STATE_EVADE); } -bool HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32 time_diff) +bool HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32 /*time_diff*/) { arrived = owner.movespline->Finalized(); return !arrived; diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index 02f9ebce847..c565e150740 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -41,7 +41,7 @@ void PointMovementGenerator<T>::Initialize(T &unit) } template<class T> -bool PointMovementGenerator<T>::Update(T &unit, const uint32 &diff) +bool PointMovementGenerator<T>::Update(T &unit, const uint32 & /*diff*/) { if (!&unit) return false; diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 22adc7be92f..b65fa210723 100755 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -33,11 +33,10 @@ #endif template<> -void RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature) +void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature) { - float respX, respY, respZ, respO, currZ, destX, destY, destZ, travelDistZ; + float respX, respY, respZ, respO, destX, destY, destZ, travelDistZ; creature.GetHomePosition(respX, respY, respZ, respO); - currZ = creature.GetPositionZ(); Map const* map = creature.GetBaseMap(); // For 2D/3D system selection @@ -78,17 +77,17 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature) // The fastest way to get an accurate result 90% of the time. // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long. - destZ = map->GetHeight(destX, destY, respZ+travelDistZ-2.0f, false); + destZ = map->GetHeight(creature.GetPhaseMask(), destX, destY, respZ+travelDistZ-2.0f, false); if (fabs(destZ - respZ) > travelDistZ) // Map check { // Vmap Horizontal or above - destZ = map->GetHeight(destX, destY, respZ - 2.0f, true); + destZ = map->GetHeight(creature.GetPhaseMask(), destX, destY, respZ - 2.0f, true); if (fabs(destZ - respZ) > travelDistZ) { // Vmap Higher - destZ = map->GetHeight(destX, destY, respZ+travelDistZ-2.0f, true); + destZ = map->GetHeight(creature.GetPhaseMask(), destX, destY, respZ+travelDistZ-2.0f, true); // let's forget this bad coords where a z cannot be find and retry at next tick if (fabs(destZ - respZ) > travelDistZ) diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 964b4402438..064a8fc8297 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -38,15 +38,18 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner) return; float x, y, z; - - if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset)) - { - if (!owner.movespline->Finalized()) - return; - - owner.GetPosition(x, y, z); - } - else if (!i_offset) + //! Following block of code deleted by MrSmite in issue 4891 + //! Code kept for learning and diagnostical purposes +// +// if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset)) +// { +// if (!owner.movespline->Finalized()) +// return; +// +// owner.GetPosition(x, y, z); +// } +// else + if (!i_offset) { if (i_target->IsWithinMeleeRange(&owner)) return; diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index bf2eecc89f6..b851dbc0e05 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -39,8 +39,9 @@ class TargetedMovementGeneratorMedium { protected: TargetedMovementGeneratorMedium(Unit &target, float offset, float angle) : - TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle), - i_recalculateTravel(false), i_targetReached(false), i_recheckDistance(0) + TargetedMovementGeneratorBase(target), i_recheckDistance(0), + i_offset(offset), i_angle(angle), + i_recalculateTravel(false), i_targetReached(false) { } ~TargetedMovementGeneratorMedium() {} diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 55cf3c28d46..fb2249c508e 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -78,7 +78,7 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature) if (i_path->at(i_currentNode)->event_id && urand(0, 99) < i_path->at(i_currentNode)->event_chance) { - sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Creature movement start script %u at point %u for %u.", i_path->at(i_currentNode)->event_id, i_currentNode, creature.GetGUID()); + sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Creature movement start script %u at point %u for "UI64FMTD".", i_path->at(i_currentNode)->event_id, i_currentNode, creature.GetGUID()); creature.GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, &creature, NULL/*, false*/); } @@ -111,8 +111,8 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature &creature) m_isArrivalDone = false; - creature.AddUnitState(UNIT_STATE_ROAMING_MOVE); - + creature.AddUnitState(UNIT_STATE_ROAMING_MOVE); + Movement::MoveSplineInit init(creature); init.MoveTo(node->x, node->y, node->z); @@ -147,7 +147,7 @@ bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint3 if (CanMove(diff)) return StartMove(creature); } - else + else { if (creature.IsStopped()) Stop(STOP_TIME_FOR_PLAYER); @@ -155,7 +155,7 @@ bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint3 { OnArrived(creature); return StartMove(creature); - } + } } return true; } @@ -201,20 +201,17 @@ void FlightPathMovementGenerator::Initialize(Player &player) InitEndGridInfo(); } -void FlightPathMovementGenerator::Finalize(Player & player) +void FlightPathMovementGenerator::Finalize(Player& player) { // remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack) player.ClearUnitState(UNIT_STATE_IN_FLIGHT); player.Dismount(); - player.RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); + player.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); - if(player.m_taxi.empty()) + if (player.m_taxi.empty()) { player.getHostileRefManager().setOnlineOfflineState(true); - if(player.pvpInfo.inHostileArea) - player.CastSpell(&player, 2479, true); - // update z position to ground and orientation for landing point // this prevent cheating with landing point at lags // when client side flight end early in comparison server side @@ -243,7 +240,7 @@ void FlightPathMovementGenerator::Reset(Player & player) init.Launch(); } -bool FlightPathMovementGenerator::Update(Player &player, const uint32 diff) +bool FlightPathMovementGenerator::Update(Player &player, const uint32 /*diff*/) { uint32 pointId = (uint32)player.movespline->currentPathIdx(); if (pointId > i_currentNode) @@ -296,7 +293,7 @@ bool FlightPathMovementGenerator::GetResetPosition(Player&, float& x, float& y, x = node.x; y = node.y; z = node.z; return true; } - + void FlightPathMovementGenerator::InitEndGridInfo() { /*! Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index aa6d327db3b..9c2475267f6 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -42,7 +42,7 @@ template<class T, class P> class PathMovementBase { public: - PathMovementBase() : i_currentNode(0), i_path(NULL) {} + PathMovementBase() : i_path(NULL), i_currentNode(0) {} virtual ~PathMovementBase() {}; // template pattern, not defined .. override required @@ -63,7 +63,8 @@ class WaypointMovementGenerator<Creature> public PathMovementBase<Creature, WaypointPath const*> { public: - WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) : i_nextMoveTime(0), path_id(_path_id), m_isArrivalDone(false), repeating(_repeating) {} + WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) + : i_nextMoveTime(0), m_isArrivalDone(false), path_id(_path_id), repeating(_repeating) {} ~WaypointMovementGenerator() { i_path = NULL; } void Initialize(Creature &); void Finalize(Creature &); diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp index 4eaa6b57b36..5d0344f9769 100644 --- a/src/server/game/Movement/Spline/MoveSpline.cpp +++ b/src/server/game/Movement/Spline/MoveSpline.cpp @@ -187,7 +187,7 @@ void MoveSpline::Initialize(const MoveSplineInitArgs& args) } MoveSpline::MoveSpline() : m_Id(0), time_passed(0), - vertical_acceleration(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0), initialOrientation(0.f) + vertical_acceleration(0.f), initialOrientation(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0) { splineflags.done = true; } diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h index 4b8dbcc8ee3..d4b19b21634 100644 --- a/src/server/game/Movement/Spline/MoveSpline.h +++ b/src/server/game/Movement/Spline/MoveSpline.h @@ -47,7 +47,6 @@ namespace Movement Result_NextCycle = 0x04, Result_NextSegment = 0x08, }; - #pragma region fields friend class PacketBuilder; protected: MySpline spline; @@ -88,7 +87,6 @@ namespace Movement void _Finalize(); void _Interrupt() { splineflags.done = true;} - #pragma endregion public: void Initialize(const MoveSplineInitArgs&); diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h index de91f63c30a..33973064e09 100644 --- a/src/server/game/Movement/Spline/MoveSplineFlag.h +++ b/src/server/game/Movement/Spline/MoveSplineFlag.h @@ -98,14 +98,14 @@ namespace Movement void operator &= (uint32 f) { raw() &= f;} void operator |= (uint32 f) { raw() |= f;} - void EnableAnimation(uint8 anim) { raw() = raw() & ~(Mask_Animations|Falling|Parabolic) | Animation|anim;} - void EnableParabolic() { raw() = raw() & ~(Mask_Animations|Falling|Animation) | Parabolic;} - void EnableFalling() { raw() = raw() & ~(Mask_Animations|Parabolic|Animation) | Falling;} - void EnableFlying() { raw() = raw() & ~Catmullrom | Flying; } - void EnableCatmullRom() { raw() = raw() & ~Flying | Catmullrom; } - void EnableFacingPoint() { raw() = raw() & ~Mask_Final_Facing | Final_Point;} - void EnableFacingAngle() { raw() = raw() & ~Mask_Final_Facing | Final_Angle;} - void EnableFacingTarget() { raw() = raw() & ~Mask_Final_Facing | Final_Target;} + void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations|Falling|Parabolic)) | Animation|anim;} + void EnableParabolic() { raw() = (raw() & ~(Mask_Animations|Falling|Animation)) | Parabolic;} + void EnableFalling() { raw() = (raw() & ~(Mask_Animations|Parabolic|Animation)) | Falling;} + void EnableFlying() { raw() = (raw() & ~Catmullrom) | Flying; } + void EnableCatmullRom() { raw() = (raw() & ~Flying) | Catmullrom; } + void EnableFacingPoint() { raw() = (raw() & ~Mask_Final_Facing) | Final_Point;} + void EnableFacingAngle() { raw() = (raw() & ~Mask_Final_Facing) | Final_Angle;} + void EnableFacingTarget() { raw() = (raw() & ~Mask_Final_Facing) | Final_Target;} uint8 animId : 8; bool done : 1; diff --git a/src/server/game/Movement/Spline/Spline.cpp b/src/server/game/Movement/Spline/Spline.cpp index 14c1bd0c117..6970acf5415 100644 --- a/src/server/game/Movement/Spline/Spline.cpp +++ b/src/server/game/Movement/Spline/Spline.cpp @@ -56,7 +56,6 @@ SplineBase::InitMethtod SplineBase::initializers[SplineBase::ModesEnd] = }; /////////// -#pragma region evaluation methtods using G3D::Matrix4; static const Matrix4 s_catmullRomCoeffs( @@ -199,7 +198,6 @@ float SplineBase::SegLengthBezier3(index_type index) const } return length; } -#pragma endregion void SplineBase::init_spline(const Vector3 * controls, index_type count, EvaluationMode m) { diff --git a/src/server/game/Movement/Spline/Spline.h b/src/server/game/Movement/Spline/Spline.h index 28876b220d4..627cdcf3e3b 100644 --- a/src/server/game/Movement/Spline/Spline.h +++ b/src/server/game/Movement/Spline/Spline.h @@ -39,7 +39,6 @@ public: ModesEnd }; - #pragma region fields protected: ControlArray points; @@ -84,10 +83,9 @@ protected: void UninitializedSpline() const { ASSERT(false);} - #pragma endregion public: - explicit SplineBase() : m_mode(UninitializedMode), index_lo(0), index_hi(0), cyclic(false) {} + explicit SplineBase() : index_lo(0), index_hi(0), m_mode(UninitializedMode), cyclic(false) {} /** Caclulates the position for given segment Idx, and percent of segment length t @param t - percent of segment length, assumes that t in range [0, 1] @@ -138,13 +136,11 @@ class Spline : public SplineBase public: typedef length_type LengthType; typedef std::vector<length_type> LengthArray; - #pragma region fields protected: LengthArray lengths; index_type computeIndexInBounds(length_type length) const; - #pragma endregion public: explicit Spline(){} diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index 1a0b21c9615..abd8ebbb302 100755 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -342,9 +342,14 @@ void Quest::BuildExtraQuestInfo(WorldPacket& data, Player* player) const data << uint32(0); // 4.x Unk } +bool Quest::IsAutoAccept() const +{ + return sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT) ? false : (Flags & QUEST_FLAGS_AUTO_ACCEPT); +} + bool Quest::IsAutoComplete() const { - return Method == 0 || HasFlag(QUEST_FLAGS_AUTOCOMPLETE); + return sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) ? false : (Method == 0 || HasFlag(QUEST_FLAGS_AUTOCOMPLETE)); } bool Quest::IsAllowedInRaid() const diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 0edd44328f1..1c8afd2a90b 100755 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -261,6 +261,7 @@ class Quest uint32 GetQuestStartScript() const { return StartScript; } uint32 GetQuestCompleteScript() const { return CompleteScript; } bool IsRepeatable() const { return Flags & QUEST_TRINITY_FLAGS_REPEATABLE; } + bool IsAutoAccept() const; bool IsAutoComplete() const; uint32 GetFlags() const { return Flags; } uint32 GetMinimapTargetMark() const { return MinimapTargetMark; } @@ -271,9 +272,8 @@ class Quest 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); } + 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 IsAutoAccept() const { return Flags & QUEST_FLAGS_AUTO_ACCEPT; } 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; } @@ -405,17 +405,17 @@ class Quest struct QuestStatusData { - QuestStatusData(): m_status(QUEST_STATUS_NONE), m_explored(false), m_timer(0), m_playercount(0) + QuestStatusData(): Status(QUEST_STATUS_NONE), Timer(0), PlayerCount(0), Explored(false) { - memset(m_itemcount, 0, QUEST_ITEM_OBJECTIVES_COUNT * sizeof(uint16)); - memset(m_creatureOrGOcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint16)); + memset(ItemCount, 0, QUEST_ITEM_OBJECTIVES_COUNT * sizeof(uint16)); + memset(CreatureOrGOCount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint16)); } - QuestStatus m_status; - bool m_explored; - uint32 m_timer; - uint16 m_itemcount[QUEST_ITEM_OBJECTIVES_COUNT]; - uint16 m_creatureOrGOcount[QUEST_OBJECTIVES_COUNT]; - uint16 m_playercount; + QuestStatus Status; + uint32 Timer; + uint16 ItemCount[QUEST_ITEM_OBJECTIVES_COUNT]; + uint16 CreatureOrGOCount[QUEST_OBJECTIVES_COUNT]; + uint16 PlayerCount; + bool Explored; }; #endif diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp index d988959f890..b1f38dfb86d 100755 --- a/src/server/game/Reputation/ReputationMgr.cpp +++ b/src/server/game/Reputation/ReputationMgr.cpp @@ -45,7 +45,7 @@ bool ReputationMgr::IsAtWar(uint32 faction_id) const if (!factionEntry) { - sLog->outError("ReputationMgr::IsAtWar: Can't get AtWar flag of %s for unknown faction (faction id) #%u.", m_player->GetName(), faction_id); + sLog->outError("ReputationMgr::IsAtWar: Can't get AtWar flag of %s for unknown faction (faction id) #%u.", _player->GetName(), faction_id); return 0; } @@ -68,7 +68,7 @@ int32 ReputationMgr::GetReputation(uint32 faction_id) const if (!factionEntry) { - sLog->outError("ReputationMgr::GetReputation: Can't get reputation of %s for unknown faction (faction id) #%u.", m_player->GetName(), faction_id); + sLog->outError("ReputationMgr::GetReputation: Can't get reputation of %s for unknown faction (faction id) #%u.", _player->GetName(), faction_id); return 0; } @@ -80,8 +80,8 @@ int32 ReputationMgr::GetBaseReputation(FactionEntry const* factionEntry) const if (!factionEntry) return 0; - uint32 raceMask = m_player->getRaceMask(); - uint32 classMask = m_player->getClassMask(); + uint32 raceMask = _player->getRaceMask(); + uint32 classMask = _player->getClassMask(); for (int i=0; i < 4; i++) { if ((factionEntry->BaseRepRaceMask[i] & raceMask || @@ -124,9 +124,9 @@ ReputationRank ReputationMgr::GetBaseRank(FactionEntry const* factionEntry) cons void ReputationMgr::ApplyForceReaction(uint32 faction_id, ReputationRank rank, bool apply) { if (apply) - m_forcedReactions[faction_id] = rank; + _forcedReactions[faction_id] = rank; else - m_forcedReactions.erase(faction_id); + _forcedReactions.erase(faction_id); } uint32 ReputationMgr::GetDefaultStateFlags(FactionEntry const* factionEntry) const @@ -134,8 +134,8 @@ uint32 ReputationMgr::GetDefaultStateFlags(FactionEntry const* factionEntry) con if (!factionEntry) return 0; - uint32 raceMask = m_player->getRaceMask(); - uint32 classMask = m_player->getClassMask(); + uint32 raceMask = _player->getRaceMask(); + uint32 classMask = _player->getClassMask(); for (int i=0; i < 4; i++) { if ((factionEntry->BaseRepRaceMask[i] & raceMask || @@ -152,14 +152,14 @@ uint32 ReputationMgr::GetDefaultStateFlags(FactionEntry const* factionEntry) con void ReputationMgr::SendForceReactions() { WorldPacket data; - data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+m_forcedReactions.size()*(4+4)); - data << uint32(m_forcedReactions.size()); - for (ForcedReactions::const_iterator itr = m_forcedReactions.begin(); itr != m_forcedReactions.end(); ++itr) + data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+_forcedReactions.size()*(4+4)); + data << uint32(_forcedReactions.size()); + for (ForcedReactions::const_iterator itr = _forcedReactions.begin(); itr != _forcedReactions.end(); ++itr) { data << uint32(itr->first); // faction_id (Faction.dbc) data << uint32(itr->second); // reputation rank } - m_player->SendDirectMessage(&data); + _player->SendDirectMessage(&data); } void ReputationMgr::SendState(FactionState const* faction) @@ -176,7 +176,7 @@ void ReputationMgr::SendState(FactionState const* faction) data << (uint32) faction->ReputationListID; data << (uint32) faction->Standing; - for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + for (FactionStateList::iterator itr = _factions.begin(); itr != _factions.end(); ++itr) { if (itr->second.needSend) { @@ -191,7 +191,7 @@ void ReputationMgr::SendState(FactionState const* faction) } data.put<uint32>(p_count, count); - m_player->SendDirectMessage(&data); + _player->SendDirectMessage(&data); } void ReputationMgr::SendInitialReputations() @@ -201,7 +201,7 @@ void ReputationMgr::SendInitialReputations() RepListID a = 0; - for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + for (FactionStateList::iterator itr = _factions.begin(); itr != _factions.end(); ++itr) { // fill in absent fields for (; a != itr->first; a++) @@ -226,33 +226,33 @@ void ReputationMgr::SendInitialReputations() data << uint32 (0x00000000); } - m_player->SendDirectMessage(&data); + _player->SendDirectMessage(&data); } void ReputationMgr::SendStates() { - for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + for (FactionStateList::iterator itr = _factions.begin(); itr != _factions.end(); ++itr) SendState(&(itr->second)); } void ReputationMgr::SendVisible(FactionState const* faction) const { - if (m_player->GetSession()->PlayerLoading()) + if (_player->GetSession()->PlayerLoading()) return; // make faction visible in reputation list at client WorldPacket data(SMSG_SET_FACTION_VISIBLE, 4); data << faction->ReputationListID; - m_player->SendDirectMessage(&data); + _player->SendDirectMessage(&data); } void ReputationMgr::Initialize() { - m_factions.clear(); - m_visibleFactionCount = 0; - m_honoredFactionCount = 0; - m_reveredFactionCount = 0; - m_exaltedFactionCount = 0; + _factions.clear(); + _visibleFactionCount = 0; + _honoredFactionCount = 0; + _reveredFactionCount = 0; + _exaltedFactionCount = 0; for (unsigned int i = 1; i < sFactionStore.GetNumRows(); i++) { @@ -269,18 +269,18 @@ void ReputationMgr::Initialize() newFaction.needSave = true; if (newFaction.Flags & FACTION_FLAG_VISIBLE) - ++m_visibleFactionCount; + ++_visibleFactionCount; UpdateRankCounters(REP_HOSTILE, GetBaseRank(factionEntry)); - m_factions[newFaction.ReputationListID] = newFaction; + _factions[newFaction.ReputationListID] = newFaction; } } } bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental) { - sScriptMgr->OnPlayerReputationChange(m_player, factionEntry->ID, standing, incremental); + sScriptMgr->OnPlayerReputationChange(_player, factionEntry->ID, standing, incremental); bool res = false; // if spillover definition exists in DB, override DBC if (const RepSpilloverTemplate* repTemplate = sObjectMgr->GetRepSpilloverTemplate(factionEntry->ID)) @@ -289,7 +289,7 @@ bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standi { if (repTemplate->faction[i]) { - if (m_player->GetReputationRank(repTemplate->faction[i]) <= ReputationRank(repTemplate->faction_rank[i])) + if (_player->GetReputationRank(repTemplate->faction[i]) <= ReputationRank(repTemplate->faction_rank[i])) { // bonuses are already given, so just modify standing by rate int32 spilloverRep = int32(standing * repTemplate->faction_rate[i]); @@ -309,9 +309,9 @@ bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standi spillOverRepOut *= factionEntry->spilloverRateOut; if (FactionEntry const* parent = sFactionStore.LookupEntry(factionEntry->team)) { - FactionStateList::iterator parentState = m_factions.find(parent->reputationListID); + FactionStateList::iterator parentState = _factions.find(parent->reputationListID); // some team factions have own reputation standing, in this case do not spill to other sub-factions - if (parentState != m_factions.end() && (parentState->second.Flags & FACTION_FLAG_SPECIAL)) + if (parentState != _factions.end() && (parentState->second.Flags & FACTION_FLAG_SPECIAL)) { SetOneFactionReputation(parent, int32(spillOverRepOut), incremental); } @@ -338,8 +338,8 @@ bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standi } } // spillover done, update faction itself - FactionStateList::iterator faction = m_factions.find(factionEntry->reputationListID); - if (faction != m_factions.end()) + FactionStateList::iterator faction = _factions.find(factionEntry->reputationListID); + if (faction != _factions.end()) { res = SetOneFactionReputation(factionEntry, standing, incremental); // only this faction gets reported to client, even if it has no own visible standing @@ -350,8 +350,8 @@ bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standi bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental) { - FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); - if (itr != m_factions.end()) + FactionStateList::iterator itr = _factions.find(factionEntry->reputationListID); + if (itr != _factions.end()) { int32 BaseRep = GetBaseReputation(factionEntry); @@ -381,12 +381,12 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in UpdateRankCounters(old_rank, new_rank); - m_player->ReputationChanged(factionEntry); - m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID); - m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID); - m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION, factionEntry->ID); - m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION, factionEntry->ID); - m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION, factionEntry->ID); + _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); return true; } @@ -400,7 +400,7 @@ void ReputationMgr::SetVisible(FactionTemplateEntry const*factionTemplateEntry) if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->faction)) // Never show factions of the opposing team - if (!(factionEntry->BaseRepRaceMask[1] & m_player->getRaceMask() && factionEntry->BaseRepValue[1] == Reputation_Bottom)) + if (!(factionEntry->BaseRepRaceMask[1] & _player->getRaceMask() && factionEntry->BaseRepValue[1] == Reputation_Bottom)) SetVisible(factionEntry); } @@ -409,8 +409,8 @@ void ReputationMgr::SetVisible(FactionEntry const* factionEntry) if (factionEntry->reputationListID < 0) return; - FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); - if (itr == m_factions.end()) + FactionStateList::iterator itr = _factions.find(factionEntry->reputationListID); + if (itr == _factions.end()) return; SetVisible(&itr->second); @@ -431,15 +431,15 @@ void ReputationMgr::SetVisible(FactionState* faction) faction->needSend = true; faction->needSave = true; - ++m_visibleFactionCount; + ++_visibleFactionCount; SendVisible(faction); } void ReputationMgr::SetAtWar(RepListID repListID, bool on) { - FactionStateList::iterator itr = m_factions.find(repListID); - if (itr == m_factions.end()) + FactionStateList::iterator itr = _factions.find(repListID); + if (itr == _factions.end()) return; // always invisible or hidden faction can't change war state @@ -470,8 +470,8 @@ void ReputationMgr::SetAtWar(FactionState* faction, bool atWar) const void ReputationMgr::SetInactive(RepListID repListID, bool on) { - FactionStateList::iterator itr = m_factions.find(repListID); - if (itr == m_factions.end()) + FactionStateList::iterator itr = _factions.find(repListID); + if (itr == _factions.end()) return; SetInactive(&itr->second, on); @@ -512,7 +512,7 @@ void ReputationMgr::LoadFromDB(PreparedQueryResult result) FactionEntry const* factionEntry = sFactionStore.LookupEntry(fields[0].GetUInt16()); if (factionEntry && (factionEntry->reputationListID >= 0)) { - FactionState* faction = &m_factions[factionEntry->reputationListID]; + FactionState* faction = &_factions[factionEntry->reputationListID]; // update standing to current faction->Standing = int32(fields[1].GetUInt32()); @@ -558,12 +558,12 @@ void ReputationMgr::LoadFromDB(PreparedQueryResult result) void ReputationMgr::SaveToDB(SQLTransaction& trans) { - for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + for (FactionStateList::iterator itr = _factions.begin(); itr != _factions.end(); ++itr) { if (itr->second.needSave) { - trans->PAppend("DELETE FROM character_reputation WHERE guid = '%u' AND faction='%u'", m_player->GetGUIDLow(), itr->second.ID); - trans->PAppend("INSERT INTO character_reputation (guid, faction, standing, flags) VALUES ('%u', '%u', '%i', '%u')", m_player->GetGUIDLow(), itr->second.ID, itr->second.Standing, itr->second.Flags); + trans->PAppend("DELETE FROM character_reputation WHERE guid = '%u' AND faction='%u'", _player->GetGUIDLow(), itr->second.ID); + trans->PAppend("INSERT INTO character_reputation (guid, faction, standing, flags) VALUES ('%u', '%u', '%i', '%u')", _player->GetGUIDLow(), itr->second.ID, itr->second.Standing, itr->second.Flags); itr->second.needSave = false; } } @@ -572,16 +572,16 @@ void ReputationMgr::SaveToDB(SQLTransaction& trans) void ReputationMgr::UpdateRankCounters(ReputationRank old_rank, ReputationRank new_rank) { if (old_rank >= REP_EXALTED) - --m_exaltedFactionCount; + --_exaltedFactionCount; if (old_rank >= REP_REVERED) - --m_reveredFactionCount; + --_reveredFactionCount; if (old_rank >= REP_HONORED) - --m_honoredFactionCount; + --_honoredFactionCount; if (new_rank >= REP_EXALTED) - ++m_exaltedFactionCount; + ++_exaltedFactionCount; if (new_rank >= REP_REVERED) - ++m_reveredFactionCount; + ++_reveredFactionCount; if (new_rank >= REP_HONORED) - ++m_honoredFactionCount; + ++_honoredFactionCount; } diff --git a/src/server/game/Reputation/ReputationMgr.h b/src/server/game/Reputation/ReputationMgr.h index b73574d288f..84013f7ec20 100755 --- a/src/server/game/Reputation/ReputationMgr.h +++ b/src/server/game/Reputation/ReputationMgr.h @@ -50,8 +50,8 @@ struct FactionState { uint32 ID; RepListID ReputationListID; - uint8 Flags; int32 Standing; + uint8 Flags; bool needSend; bool needSave; }; @@ -64,8 +64,8 @@ class Player; class ReputationMgr { public: // constructors and global modifiers - explicit ReputationMgr(Player* owner) : m_player(owner), - m_visibleFactionCount(0), m_honoredFactionCount(0), m_reveredFactionCount(0), m_exaltedFactionCount(0) {} + explicit ReputationMgr(Player* owner) : _player(owner), + _visibleFactionCount(0), _honoredFactionCount(0), _reveredFactionCount(0), _exaltedFactionCount(0) {} ~ReputationMgr() {} void SaveToDB(SQLTransaction& trans); @@ -77,12 +77,12 @@ class ReputationMgr static ReputationRank ReputationToRank(int32 standing); public: // accessors - uint8 GetVisibleFactionCount() const { return m_visibleFactionCount; } - uint8 GetHonoredFactionCount() const { return m_honoredFactionCount; } - uint8 GetReveredFactionCount() const { return m_reveredFactionCount; } - uint8 GetExaltedFactionCount() const { return m_exaltedFactionCount; } + uint8 GetVisibleFactionCount() const { return _visibleFactionCount; } + uint8 GetHonoredFactionCount() const { return _honoredFactionCount; } + uint8 GetReveredFactionCount() const { return _reveredFactionCount; } + uint8 GetExaltedFactionCount() const { return _exaltedFactionCount; } - FactionStateList const& GetStateList() const { return m_factions; } + FactionStateList const& GetStateList() const { return _factions; } FactionState const* GetState(FactionEntry const* factionEntry) const { @@ -91,8 +91,8 @@ class ReputationMgr FactionState const* GetState(RepListID id) const { - FactionStateList::const_iterator repItr = m_factions.find (id); - return repItr != m_factions.end() ? &repItr->second : NULL; + FactionStateList::const_iterator repItr = _factions.find (id); + return repItr != _factions.end() ? &repItr->second : NULL; } bool IsAtWar(uint32 faction_id) const; @@ -111,8 +111,8 @@ class ReputationMgr ReputationRank const* GetForcedRankIfAny(FactionTemplateEntry const* factionTemplateEntry) const { - ForcedReactions::const_iterator forceItr = m_forcedReactions.find(factionTemplateEntry->faction); - return forceItr != m_forcedReactions.end() ? &forceItr->second : NULL; + ForcedReactions::const_iterator forceItr = _forcedReactions.find(factionTemplateEntry->faction); + return forceItr != _forcedReactions.end() ? &forceItr->second : NULL; } public: // modifiers @@ -149,13 +149,13 @@ class ReputationMgr void SendVisible(FactionState const* faction) const; void UpdateRankCounters(ReputationRank old_rank, ReputationRank new_rank); private: - Player* m_player; - FactionStateList m_factions; - ForcedReactions m_forcedReactions; - uint8 m_visibleFactionCount :8; - uint8 m_honoredFactionCount :8; - uint8 m_reveredFactionCount :8; - uint8 m_exaltedFactionCount :8; + Player* _player; + FactionStateList _factions; + ForcedReactions _forcedReactions; + uint8 _visibleFactionCount :8; + uint8 _honoredFactionCount :8; + uint8 _reveredFactionCount :8; + uint8 _exaltedFactionCount :8; }; #endif diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index c46721db6cd..1207b654817 100755 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -39,6 +39,7 @@ void AddSC_warrior_spell_scripts(); void AddSC_quest_spell_scripts(); void AddSC_item_spell_scripts(); void AddSC_example_spell_scripts(); +void AddSC_holiday_spell_scripts(); void AddSC_SmartSCripts(); @@ -245,7 +246,6 @@ void AddSC_ironforge(); void AddSC_isle_of_queldanas(); void AddSC_loch_modan(); void AddSC_redridge_mountains(); -void AddSC_searing_gorge(); void AddSC_silvermoon_city(); void AddSC_silverpine_forest(); void AddSC_stormwind_city(); @@ -642,6 +642,7 @@ void AddSpellScripts() AddSC_quest_spell_scripts(); AddSC_item_spell_scripts(); AddSC_example_spell_scripts(); + AddSC_holiday_spell_scripts(); } void AddCommandScripts() @@ -855,7 +856,6 @@ void AddEasternKingdomsScripts() AddSC_isle_of_queldanas(); AddSC_loch_modan(); AddSC_redridge_mountains(); - AddSC_searing_gorge(); AddSC_silvermoon_city(); AddSC_silverpine_forest(); AddSC_stormwind_city(); diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index d5e8f71e1fd..47751338d66 100755 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -395,7 +395,7 @@ void ScriptMgr::CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scri { SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId); - for (SpellScriptsMap::iterator itr = bounds.first; itr != bounds.second; ++itr) + for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr) { SpellScriptLoader* tmpscript = ScriptRegistry<SpellScriptLoader>::GetScriptById(itr->second); if (!tmpscript) @@ -416,7 +416,7 @@ void ScriptMgr::CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& script { SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId); - for (SpellScriptsMap::iterator itr = bounds.first; itr != bounds.second; ++itr) + for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr) { SpellScriptLoader* tmpscript = ScriptRegistry<SpellScriptLoader>::GetScriptById(itr->second); if (!tmpscript) @@ -433,12 +433,12 @@ void ScriptMgr::CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& script } } -void ScriptMgr::CreateSpellScriptLoaders(uint32 spellId, std::vector<std::pair<SpellScriptLoader*, SpellScriptsMap::iterator> >& scriptVector) +void ScriptMgr::CreateSpellScriptLoaders(uint32 spellId, std::vector<std::pair<SpellScriptLoader*, SpellScriptsContainer::iterator> >& scriptVector) { SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId); scriptVector.reserve(std::distance(bounds.first, bounds.second)); - for (SpellScriptsMap::iterator itr = bounds.first; itr != bounds.second; ++itr) + for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr) { SpellScriptLoader* tmpscript = ScriptRegistry<SpellScriptLoader>::GetScriptById(itr->second); if (!tmpscript) @@ -1036,14 +1036,12 @@ void ScriptMgr::OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry) FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionExpire(ah, entry); } -bool ScriptMgr::OnConditionCheck(Condition* condition, Player* player, Unit* invoker) +bool ScriptMgr::OnConditionCheck(Condition* condition, ConditionSourceInfo& sourceInfo) { ASSERT(condition); - ASSERT(player); - // invoker can be NULL. - GET_SCRIPT_RET(ConditionScript, condition->mScriptId, tmpscript, true); - return tmpscript->OnConditionCheck(condition, player, invoker); + GET_SCRIPT_RET(ConditionScript, condition->ScriptId, tmpscript, true); + return tmpscript->OnConditionCheck(condition, sourceInfo); } void ScriptMgr::OnInstall(Vehicle* veh) diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 60052bea0ea..048a7581215 100755 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -62,6 +62,7 @@ class WorldObject; struct AchievementCriteriaData; struct AuctionEntry; +struct ConditionSourceInfo; struct Condition; struct ItemTemplate; struct OutdoorPvPData; @@ -572,7 +573,7 @@ class ConditionScript : public ScriptObject bool IsDatabaseBound() const { return true; } // Called when a single condition is checked for a player. - virtual bool OnConditionCheck(Condition* /*condition*/, Player* /*player*/, Unit* /*invoker*/) { return true; } + virtual bool OnConditionCheck(Condition* /*condition*/, ConditionSourceInfo& /*sourceInfo*/) { return true; } }; class VehicleScript : public ScriptObject @@ -938,7 +939,7 @@ class ScriptMgr public: /* ConditionScript */ - bool OnConditionCheck(Condition* condition, Player* player, Unit* invoker); + bool OnConditionCheck(Condition* condition, ConditionSourceInfo& sourceInfo); public: /* VehicleScript */ diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 4ed8f90b10e..707dd65e2ad 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -27,7 +27,6 @@ OpcodeHandler* opcodeTable[NUM_OPCODE_HANDLERS] = { }; /// Correspondence between opcodes and their names void InitOpcodes() { - #define DEFINE_OPCODE_HANDLER(opcode, status, processing, handler) \ if (opcode == 0) \ sLog->outError("Opcode %s got value 0", #opcode); \ @@ -803,7 +802,7 @@ void InitOpcodes() //DEFINE_OPCODE_HANDLER(SMSG_AREA_SPIRIT_HEALER_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(CMSG_GM_UNTEACH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(SMSG_WARDEN_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(CMSG_WARDEN_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWardenDataOpcode ); + //DEFINE_OPCODE_HANDLER(CMSG_WARDEN_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleWardenDataOpcode ); //DEFINE_OPCODE_HANDLER(SMSG_GROUP_JOINED_BATTLEGROUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(MSG_BATTLEGROUND_PLAYER_POSITIONS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlegroundPlayerPositionsOpcode); //DEFINE_OPCODE_HANDLER(CMSG_PET_STOP_ATTACK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetStopAttack ); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 978f33c88aa..e93c0eb8102 100755 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -42,6 +42,8 @@ #include "zlib.h" #include "ScriptMgr.h" #include "Transport.h" +#include "WardenWin.h" +#include "WardenMac.h" bool MapSessionFilter::Process(WorldPacket* packet) { @@ -98,6 +100,8 @@ m_sessionDbLocaleIndex(locale), m_latency(0), m_TutorialsChanged(false), recruiterId(recruiter), isRecruiter(isARecruiter), timeLastWhoCommand(0) { + _warden = NULL; + if (sock) { m_Address = sock->GetRemoteAddress(); @@ -124,6 +128,9 @@ WorldSession::~WorldSession() m_Socket = NULL; } + if (_warden) + delete _warden; + ///- empty incoming packet queue WorldPacket* packet = NULL; while (_recvQueue.next(packet)) @@ -144,6 +151,12 @@ char const* WorldSession::GetPlayerName() const return GetPlayer() ? GetPlayer()->GetName() : "<none>"; } +/// Get player guid if available. Use for logging purposes only +uint32 WorldSession::GetGuidLow() const +{ + return GetPlayer() ? GetPlayer()->GetGUIDLow() : 0; +} + /// Send a packet to the client void WorldSession::SendPacket(WorldPacket const* packet) { @@ -349,6 +362,9 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) delete packet; } + if (m_Socket && !m_Socket->IsClosed() && _warden) + _warden->Update(); + ProcessQueryCallbacks(); //check if we are safe to proceed with logout @@ -360,6 +376,9 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) if (ShouldLogOut(currTime) && !m_playerLoading) LogoutPlayer(true); + if (m_Socket && GetPlayer() && _warden) + _warden->Update(); + ///- Cleanup socket pointer if need if (m_Socket && m_Socket->IsClosed()) { @@ -520,8 +539,8 @@ void WorldSession::LogoutPlayer(bool Save) // calls to GetMap in this case may cause crashes _player->CleanupsBeforeDelete(); sLog->outChar("Account: %d (IP: %s) Logout Character:[%s] (GUID: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName(), _player->GetGUIDLow()); - Map* _map = _player->GetMap(); - _map->RemovePlayerFromMap(_player, true); + if (Map* _map = _player->FindMap()) + _map->RemovePlayerFromMap(_player, true); SetPlayer(NULL); // deleted in Remove call ///- Send the 'logout complete' packet to the client @@ -997,3 +1016,18 @@ void WorldSession::ProcessQueryCallbacks() _stableSwapCallback.FreeResult(); } } + +void WorldSession::InitWarden(BigNumber* k, std::string os) +{ + if (os == "Win") + { + _warden = new WardenWin(); + _warden->Init(this, k); + } + else if (os == "OSX") + { + // Disabled as it is causing the client to crash + // _warden = new WardenMac(); + // _warden->Init(this, k); + } +} diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index ec2587f8b29..21cc3991b9f 100755 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -29,6 +29,7 @@ #include "DatabaseEnv.h" #include "World.h" #include "WorldPacket.h" +#include "Cryptography/BigNumber.h" struct ItemTemplate; struct AuctionEntry; @@ -46,6 +47,7 @@ class WorldPacket; class WorldSocket; class LoginQueryHolder; class SpellCastTargets; +class Warden; struct AreaTableEntry; struct LfgJoinResultData; struct LfgLockStatus; @@ -252,11 +254,14 @@ class WorldSession uint32 GetAccountId() const { return _accountId; } Player* GetPlayer() const { return _player; } char const* GetPlayerName() const; + uint32 GetGuidLow() const; void SetSecurity(AccountTypes security) { _security = security; } std::string const& GetRemoteAddress() { return m_Address; } void SetPlayer(Player* player); uint8 Expansion() const { return m_expansion; } + void InitWarden(BigNumber* k, std::string os); + /// Session in auth.queue currently void SetInQueue(bool state) { m_inQueue = state; } @@ -501,6 +506,7 @@ class WorldSession void HandleSetActionButtonOpcode(WorldPacket& recvPacket); void HandleGameObjectUseOpcode(WorldPacket& recPacket); + void HandleMeetingStoneInfo(WorldPacket& recPacket); void HandleGameobjectReportUse(WorldPacket& recvPacket); void HandleNameQueryOpcode(WorldPacket& recvPacket); @@ -585,6 +591,7 @@ class WorldSession void HandleActivateTaxiOpcode(WorldPacket& recvPacket); void HandleActivateTaxiExpressOpcode(WorldPacket& recvPacket); void HandleMoveSplineDoneOpcode(WorldPacket& recvPacket); + void SendActivateTaxiReply(ActivateTaxiReply reply); void HandleTabardVendorActivateOpcode(WorldPacket& recvPacket); void HandleBankerActivateOpcode(WorldPacket& recvPacket); @@ -950,6 +957,9 @@ class WorldSession typedef std::list<AddonInfo> AddonsList; + // Warden + Warden* _warden; // Remains NULL if Warden system is not enabled by config + time_t _logoutTime; bool m_inQueue; // session wait in auth.queue bool m_playerLoading; // code processed in LoginPlayer diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 881464ce40a..22689e40c2b 100755 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -869,7 +869,8 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) "expansion, " //6 "mutetime, " //7 "locale, " //8 - "recruiter " //9 + "recruiter, " //9 + "os " "FROM account " "WHERE username = '%s'", safe_account.c_str()); @@ -926,10 +927,10 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) id = fields[0].GetUInt32(); /* if (security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB - security = SEC_ADMINISTRATOR; - */ + 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. @@ -950,6 +951,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) locale = LOCALE_enUS; uint32 recruiter = fields[9].GetUInt32(); + std::string os = fields[10].GetString(); // Checks gmlevel per Realm result = LoginDatabase.PQuery ("SELECT " @@ -1000,8 +1002,6 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) } // Check that Key and account name are the same on client and server - SHA1Hash sha; - uint32 t = 0; uint32 seed = m_Seed; @@ -1009,7 +1009,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) sha.UpdateData ((uint8 *) & t, 4); sha.UpdateData ((uint8 *) & clientSeed, 4); sha.UpdateData ((uint8 *) & seed, 4); - sha.UpdateBigNumbers (&K, NULL); + sha.UpdateBigNumbers (&k, NULL); sha.Finalize(); std::string address = GetRemoteAddress(); @@ -1037,13 +1037,17 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) // 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); - m_Crypt.Init(&K); + m_Crypt.Init(&k); m_Session->LoadGlobalAccountData(); m_Session->LoadTutorialsData(); packetAddon.rpos(0); m_Session->ReadAddonsInfo(packetAddon); + // Initialize Warden system only if it is enabled by config + if (sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED)) + m_Session->InitWarden(&k, os); + // Sleep this Network thread for uint32 sleepTime = sWorld->getIntConfig(CONFIG_SESSION_ADD_DELAY); ACE_OS::sleep (ACE_Time_Value (0, sleepTime)); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index b3b4cf4a30d..273fcb4f049 100755 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -419,10 +419,10 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= }; AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* caster): -m_base(base), m_spellInfo(base->GetSpellInfo()), m_effIndex(effIndex), -m_baseAmount(baseAmount ? *baseAmount : m_spellInfo->Effects[m_effIndex].BasePoints), -m_canBeRecalculated(true), m_spellmod(NULL), m_isPeriodic(false), -m_periodicTimer(0), m_tickNumber(0) +m_base(base), m_spellInfo(base->GetSpellInfo()), +m_baseAmount(baseAmount ? *baseAmount : m_spellInfo->Effects[effIndex].BasePoints), +m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex), +m_canBeRecalculated(true), m_isPeriodic(false) { CalculatePeriodic(caster, true, false); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 930dfba4289..28a5beafa2c 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -95,18 +95,19 @@ class AuraEffect Aura* const m_base; SpellInfo const* const m_spellInfo; - uint8 const m_effIndex; int32 const m_baseAmount; int32 m_amount; - bool m_canBeRecalculated; SpellModifier* m_spellmod; - bool m_isPeriodic; int32 m_periodicTimer; int32 m_amplitude; uint32 m_tickNumber; + + uint8 const m_effIndex; + bool m_canBeRecalculated; + bool m_isPeriodic; private: bool IsPeriodicTickCrit(Unit* target, Unit const* caster) const; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index d20411eb8a6..6015a944bdb 100755 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -37,8 +37,8 @@ #include "Vehicle.h" AuraApplication::AuraApplication(Unit* target, Unit* caster, Aura* aura, uint8 effMask): -m_target(target), m_base(aura), m_slot(MAX_AURAS), m_flags(AFLAG_NONE), -m_effectsToApply(effMask), m_removeMode(AURA_REMOVE_NONE), m_needClientUpdate(false) +_target(target), _base(aura), _removeMode(AURA_REMOVE_NONE), _slot(MAX_AURAS), +_flags(AFLAG_NONE), _effectsToApply(effMask), _needClientUpdate(false) { ASSERT(GetTarget() && GetBase()); @@ -70,7 +70,7 @@ m_effectsToApply(effMask), m_removeMode(AURA_REMOVE_NONE), m_needClientUpdate(fa // Register Visible Aura if (slot < MAX_AURAS) { - m_slot = slot; + _slot = slot; GetTarget()->SetVisibleAura(slot, this); SetNeedClientUpdate(); sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Aura: %u Effect: %d put to unit visible auras slot: %u", GetBase()->GetId(), GetEffectMask(), slot); @@ -89,7 +89,7 @@ void AuraApplication::_Remove() if (slot >= MAX_AURAS) return; - if (AuraApplication * foundAura = m_target->GetAuraApplication(GetBase()->GetId(), GetBase()->GetCasterGUID(), GetBase()->GetCastItemGUID())) + if (AuraApplication * foundAura = _target->GetAuraApplication(GetBase()->GetId(), GetBase()->GetCasterGUID(), GetBase()->GetCastItemGUID())) { // Reuse visible aura slot by aura which is still applied - prevent storing dead pointers if (slot == foundAura->GetSlot()) @@ -115,7 +115,7 @@ void AuraApplication::_Remove() void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) { // mark as selfcasted if needed - m_flags |= (GetBase()->GetCasterGUID() == GetTarget()->GetGUID()) ? AFLAG_CASTER : AFLAG_NONE; + _flags |= (GetBase()->GetCasterGUID() == GetTarget()->GetGUID()) ? AFLAG_CASTER : AFLAG_NONE; // aura is casted by self or an enemy // one negative effect and we know aura is negative @@ -130,7 +130,7 @@ void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) break; } } - m_flags |= negativeFound ? AFLAG_NEGATIVE : AFLAG_POSITIVE; + _flags |= negativeFound ? AFLAG_NEGATIVE : AFLAG_POSITIVE; } // aura is casted by friend // one positive effect and we know aura is positive @@ -145,7 +145,7 @@ void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) break; } } - m_flags |= positiveFound ? AFLAG_POSITIVE : AFLAG_NEGATIVE; + _flags |= positiveFound ? AFLAG_POSITIVE : AFLAG_NEGATIVE; } // there are more auras that require this flag, this is just the beginning @@ -164,19 +164,19 @@ void AuraApplication::_HandleEffect(uint8 effIndex, bool apply) AuraEffect* aurEff = GetBase()->GetEffect(effIndex); ASSERT(aurEff); ASSERT(HasEffect(effIndex) == (!apply)); - ASSERT((1<<effIndex) & m_effectsToApply); + ASSERT((1<<effIndex) & _effectsToApply); sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AuraApplication::_HandleEffect: %u, apply: %u: amount: %u", aurEff->GetAuraType(), apply, aurEff->GetAmount()); if (apply) { - ASSERT(!(m_flags & (1<<effIndex))); - m_flags |= 1<<effIndex; + ASSERT(!(_flags & (1<<effIndex))); + _flags |= 1<<effIndex; aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, true); } else { - ASSERT(m_flags & (1<<effIndex)); - m_flags &= ~(1<<effIndex); + ASSERT(_flags & (1<<effIndex)); + _flags &= ~(1<<effIndex); aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, false); // Remove all triggered by aura spells vs unlimited duration @@ -187,19 +187,19 @@ void AuraApplication::_HandleEffect(uint8 effIndex, bool apply) void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const { - data << uint8(m_slot); + data << uint8(_slot); if (remove) { - ASSERT(!m_target->GetVisibleAura(m_slot)); + ASSERT(!_target->GetVisibleAura(_slot)); data << uint32(0); return; } - ASSERT(m_target->GetVisibleAura(m_slot)); + ASSERT(_target->GetVisibleAura(_slot)); Aura const* aura = GetBase(); data << uint32(aura->GetId()); - uint32 flags = m_flags; + uint32 flags = _flags; if (aura->GetMaxDuration() > 0 && !(aura->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_HIDE_DURATION)) flags |= AFLAG_DURATION; data << uint16(flags); @@ -225,13 +225,13 @@ void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const void AuraApplication::ClientUpdate(bool remove) { - m_needClientUpdate = false; + _needClientUpdate = false; WorldPacket data(SMSG_AURA_UPDATE); data.append(GetTarget()->GetPackGUID()); BuildUpdatePacket(data, remove); - m_target->SendMessageToSet(&data, true); + _target->SendMessageToSet(&data, true); } uint8 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 avalibleEffectMask, WorldObject* owner) @@ -535,7 +535,13 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) bool addUnit = true; // check target immunities - if (itr->first->IsImmunedToSpell(GetSpellInfo()) + for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + { + if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), effIndex)) + itr->second &= ~(1 << effIndex); + } + if (!itr->second + || itr->first->IsImmunedToSpell(GetSpellInfo()) || !CanBeAppliedOn(itr->first)) addUnit = false; @@ -1849,6 +1855,10 @@ bool Aura::CanStackWith(Aura const* existingAura) const if (!sameCaster) { + // Channeled auras can stack if not forbidden by db or aura type + if (existingAura->GetSpellInfo()->IsChanneled()) + return true; + if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_STACK_FOR_DIFF_CASTERS) return true; @@ -1870,7 +1880,7 @@ bool Aura::CanStackWith(Aura const* existingAura) const case SPELL_AURA_OBS_MOD_HEALTH: case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: // periodic auras which target areas are not allowed to stack this way (replenishment for example) - if (m_spellInfo->Effects[i].IsArea() || existingSpellInfo->Effects[i].IsArea()) + if (m_spellInfo->Effects[i].IsTargetingArea() || existingSpellInfo->Effects[i].IsTargetingArea()) break; return true; default: @@ -2050,7 +2060,7 @@ void Aura::TriggerProcOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo) if (aurApp->HasEffect(i)) // TODO: OnEffectProc hook here (allowing prevention of selected effects) GetEffect(i)->HandleProc(aurApp, eventInfo); - // TODO: AfterEffectProc hook here + // TODO: AfterEffectProc hook here // TODO: AfterProc hook here @@ -2100,6 +2110,30 @@ bool Aura::CallScriptCheckAreaTargetHandlers(Unit* target) return true; } +void Aura::CallScriptDispel(DispelInfo* dispelInfo) +{ + for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr) + { + (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL); + std::list<AuraScript::AuraDispelHandler>::iterator hookItrEnd = (*scritr)->OnDispel.end(), hookItr = (*scritr)->OnDispel.begin(); + for (; hookItr != hookItrEnd ; ++hookItr) + (*hookItr).Call(*scritr, dispelInfo); + (*scritr)->_FinishScriptCall(); + } +} + +void Aura::CallScriptAfterDispel(DispelInfo* dispelInfo) +{ + for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr) + { + (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL); + std::list<AuraScript::AuraDispelHandler>::iterator hookItrEnd = (*scritr)->AfterDispel.end(), hookItr = (*scritr)->AfterDispel.begin(); + for (; hookItr != hookItrEnd ; ++hookItr) + (*hookItr).Call(*scritr, dispelInfo); + (*scritr)->_FinishScriptCall(); + } +} + bool Aura::CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode) { bool preventDefault = false; diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index de743eb2991..2f50d47a79b 100755 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -21,6 +21,7 @@ #include "SpellAuraDefines.h" #include "SpellInfo.h" +#include "Unit.h" class Unit; class SpellInfo; @@ -46,13 +47,13 @@ class AuraApplication friend void Unit::RemoveAura(AuraApplication * aurApp, AuraRemoveMode mode); friend AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint8 effMask); private: - Unit* const m_target; - Aura* const m_base; - uint8 m_slot; // Aura slot on unit - uint8 m_flags; // Aura info flag - uint8 m_effectsToApply; // Used only at spell hit to determine which effect should be applied - AuraRemoveMode m_removeMode:8; // Store info for know remove aura reason - bool m_needClientUpdate:1; + Unit* const _target; + Aura* const _base; + AuraRemoveMode _removeMode:8; // Store info for know remove aura reason + uint8 _slot; // Aura slot on unit + uint8 _flags; // Aura info flag + uint8 _effectsToApply; // Used only at spell hit to determine which effect should be applied + bool _needClientUpdate:1; explicit AuraApplication(Unit* target, Unit* caster, Aura* base, uint8 effMask); void _Remove(); @@ -61,22 +62,22 @@ class AuraApplication void _HandleEffect(uint8 effIndex, bool apply); public: - Unit* GetTarget() const { return m_target; } - Aura* GetBase() const { return m_base; } + Unit* GetTarget() const { return _target; } + Aura* GetBase() const { return _base; } - uint8 GetSlot() const { return m_slot; } - uint8 GetFlags() const { return m_flags; } - uint8 GetEffectMask() const { return m_flags & (AFLAG_EFF_INDEX_0 | AFLAG_EFF_INDEX_1 | AFLAG_EFF_INDEX_2); } - bool HasEffect(uint8 effect) const { ASSERT(effect < MAX_SPELL_EFFECTS); return m_flags & (1<<effect); } - bool IsPositive() const { return m_flags & AFLAG_POSITIVE; } - bool IsSelfcasted() const { return m_flags & AFLAG_CASTER; } - uint8 GetEffectsToApply() const { return m_effectsToApply; } + uint8 GetSlot() const { return _slot; } + uint8 GetFlags() const { return _flags; } + uint8 GetEffectMask() const { return _flags & (AFLAG_EFF_INDEX_0 | AFLAG_EFF_INDEX_1 | AFLAG_EFF_INDEX_2); } + bool HasEffect(uint8 effect) const { ASSERT(effect < MAX_SPELL_EFFECTS); return _flags & (1<<effect); } + bool IsPositive() const { return _flags & AFLAG_POSITIVE; } + bool IsSelfcasted() const { return _flags & AFLAG_CASTER; } + uint8 GetEffectsToApply() const { return _effectsToApply; } - void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; } - AuraRemoveMode GetRemoveMode() const {return m_removeMode;} + void SetRemoveMode(AuraRemoveMode mode) { _removeMode = mode; } + AuraRemoveMode GetRemoveMode() const {return _removeMode;} - void SetNeedClientUpdate() { m_needClientUpdate = true;} - bool IsNeedClientUpdate() const { return m_needClientUpdate;} + void SetNeedClientUpdate() { _needClientUpdate = true;} + bool IsNeedClientUpdate() const { return _needClientUpdate;} void BuildUpdatePacket(ByteBuffer& data, bool remove) const; void ClientUpdate(bool remove = false); }; @@ -186,7 +187,7 @@ class Aura bool CanStackWith(Aura const* existingAura) const; // Proc system - // this subsystem is not yet in use - the core of it is functional, but still some research has to be done + // this subsystem is not yet in use - the core of it is functional, but still some research has to be done // and some dependant problems fixed before it can replace old proc system (for example cooldown handling) // currently proc system functionality is implemented in Unit::ProcDamageAndSpell bool IsProcOnCooldown() const; @@ -201,6 +202,8 @@ class Aura // AuraScript void LoadScripts(); bool CallScriptCheckAreaTargetHandlers(Unit* target); + void CallScriptDispel(DispelInfo* dispelInfo); + void CallScriptAfterDispel(DispelInfo* dispelInfo); bool CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode); bool CallScriptEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode); void CallScriptAfterEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index c56969b2094..88654dcc4b1 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -593,33 +593,6 @@ Spell::~Spell() CheckEffectExecuteData(); } -template<typename T> -WorldObject* Spell::FindCorpseUsing() -{ - // non-standard target selection - float max_range = m_spellInfo->GetMaxRange(false); - - CellCoord p(Trinity::ComputeCellCoord(m_caster->GetPositionX(), m_caster->GetPositionY())); - Cell cell(p); - cell.SetNoCreate(); - - WorldObject* result = NULL; - - T u_check(m_caster, max_range); - Trinity::WorldObjectSearcher<T> searcher(m_caster, result, u_check); - - TypeContainerVisitor<Trinity::WorldObjectSearcher<T>, GridTypeMapContainer > grid_searcher(searcher); - cell.Visit(p, grid_searcher, *m_caster->GetMap(), *m_caster, max_range); - - if (!result) - { - TypeContainerVisitor<Trinity::WorldObjectSearcher<T>, WorldTypeMapContainer > world_searcher(searcher); - cell.Visit(p, world_searcher, *m_caster->GetMap(), *m_caster, max_range); - } - - return result; -} - void Spell::InitExplicitTargets(SpellCastTargets const& targets) { m_targets = targets; @@ -689,9 +662,41 @@ void Spell::InitExplicitTargets(SpellCastTargets const& targets) m_targets.RemoveSrc(); } +void Spell::SelectExplicitTargets() +{ + // here go all explicit target changes made to explicit targets after spell prepare phase is finished + if (Unit* target = m_targets.GetUnitTarget()) + { + // check for explicit target redirection, for Grounding Totem for example + if (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT_ENEMY + || (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT && !m_spellInfo->IsPositive())) + { + Unit* redirect; + switch (m_spellInfo->DmgClass) + { + case SPELL_DAMAGE_CLASS_MAGIC: + redirect = m_caster->GetMagicHitRedirectTarget(target, m_spellInfo); + break; + case SPELL_DAMAGE_CLASS_MELEE: + case SPELL_DAMAGE_CLASS_RANGED: + redirect = m_caster->GetMeleeHitRedirectTarget(target, m_spellInfo); + break; + default: + redirect = NULL; + break; + } + if (redirect && (redirect != target)) + m_targets.SetUnitTarget(redirect); + } + } +} + void Spell::SelectSpellTargets() { - uint32 processedTargets = 0; + // select targets for cast phase + SelectExplicitTargets(); + + uint32 processedAreaEffectsMask = 0; for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { // not call for empty effect. @@ -699,9 +704,6 @@ void Spell::SelectSpellTargets() if (!m_spellInfo->Effects[i].IsEffect()) continue; - if (processedTargets & (1 << i)) - continue; - // set expected type of implicit targets to be sent to client uint32 implicitTargetMask = GetTargetFlagMask(m_spellInfo->Effects[i].TargetA.GetObjectType()) | GetTargetFlagMask(m_spellInfo->Effects[i].TargetB.GetObjectType()); if (implicitTargetMask & TARGET_FLAG_UNIT) @@ -709,13 +711,8 @@ void Spell::SelectSpellTargets() if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM)) m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT); - uint32 targetA = m_spellInfo->Effects[i].TargetA.GetTarget(); - uint32 targetB = m_spellInfo->Effects[i].TargetB.GetTarget(); - - if (targetA) - processedTargets |= SelectEffectTargets(i, m_spellInfo->Effects[i].TargetA); - if (targetB) - processedTargets |= SelectEffectTargets(i, m_spellInfo->Effects[i].TargetB); + SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetA, processedAreaEffectsMask); + SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetB, processedAreaEffectsMask); // Select targets of effect based on effect type // those are used when no valid target could be added for spell effect based on spell target type @@ -777,6 +774,938 @@ void Spell::SelectSpellTargets() } } +void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask) +{ + if (!targetType.GetTarget()) + return; + + uint32 effectMask = 1 << effIndex; + // set the same target list for all effects + // some spells appear to need this, however this requires more research + switch (targetType.GetSelectionCategory()) + { + case TARGET_SELECT_CATEGORY_NEARBY: + case TARGET_SELECT_CATEGORY_CONE: + case TARGET_SELECT_CATEGORY_AREA: + // targets for effect already selected + if (effectMask & processedEffectMask) + return; + // choose which targets we can select at once + for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j) + if (GetSpellInfo()->Effects[effIndex].TargetA.GetTarget() == GetSpellInfo()->Effects[j].TargetA.GetTarget() && + GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == GetSpellInfo()->Effects[j].TargetB.GetTarget() && + GetSpellInfo()->Effects[effIndex].ImplicitTargetConditions == GetSpellInfo()->Effects[j].ImplicitTargetConditions && + GetSpellInfo()->Effects[effIndex].CalcRadius(m_caster) == GetSpellInfo()->Effects[j].CalcRadius(m_caster)) + effectMask |= 1 << j; + processedEffectMask |= effectMask; + break; + default: + break; + } + + switch(targetType.GetSelectionCategory()) + { + case TARGET_SELECT_CATEGORY_CHANNEL: + SelectImplicitChannelTargets(effIndex, targetType); + break; + case TARGET_SELECT_CATEGORY_NEARBY: + SelectImplicitNearbyTargets(effIndex, targetType, effectMask); + break; + case TARGET_SELECT_CATEGORY_CONE: + SelectImplicitConeTargets(effIndex, targetType, effectMask); + break; + case TARGET_SELECT_CATEGORY_AREA: + SelectImplicitAreaTargets(effIndex, targetType, effectMask); + break; + case TARGET_SELECT_CATEGORY_DEFAULT: + switch (targetType.GetObjectType()) + { + case TARGET_OBJECT_TYPE_SRC: + switch(targetType.GetReferenceType()) + { + case TARGET_REFERENCE_TYPE_CASTER: + m_targets.SetSrc(*m_caster); + break; + default: + ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_SRC"); + break; + } + break; + case TARGET_OBJECT_TYPE_DEST: + switch(targetType.GetReferenceType()) + { + case TARGET_REFERENCE_TYPE_CASTER: + SelectImplicitCasterDestTargets(effIndex, targetType); + break; + case TARGET_REFERENCE_TYPE_TARGET: + SelectImplicitTargetDestTargets(effIndex, targetType); + break; + case TARGET_REFERENCE_TYPE_DEST: + SelectImplicitDestDestTargets(effIndex, targetType); + break; + default: + ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST"); + break; + } + break; + default: + switch(targetType.GetReferenceType()) + { + case TARGET_REFERENCE_TYPE_CASTER: + SelectImplicitCasterObjectTargets(effIndex, targetType); + break; + case TARGET_REFERENCE_TYPE_TARGET: + SelectImplicitTargetObjectTargets(effIndex, targetType); + break; + default: + ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT"); + break; + } + break; + } + break; + case TARGET_SELECT_CATEGORY_NYI: + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: target type %u, found in spellID %u, effect %u is not implemented yet!", m_spellInfo->Id, effIndex, targetType.GetTarget()); + break; + default: + ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target category"); + break; + } +} + +void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +{ + if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER) + { + ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target reference type"); + return; + } + + Spell* channeledSpell = m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL); + if (!channeledSpell) + { + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::SelectImplicitChannelTargets: cannot find channel spell for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + return; + } + switch (targetType.GetTarget()) + { + case TARGET_UNIT_CHANNEL_TARGET: + // unit target may be no longer avalible - teleported out of map for example + if (Unit* target = Unit::GetUnit(*m_caster, channeledSpell->m_targets.GetUnitTargetGUID())) + AddUnitTarget(target, 1 << effIndex); + else + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + break; + case TARGET_DEST_CHANNEL_TARGET: + if (channeledSpell->m_targets.HasDst()) + m_targets.SetDst(channeledSpell->m_targets); + else if (WorldObject* target = ObjectAccessor::GetWorldObject(*m_caster, channeledSpell->m_targets.GetObjectTargetGUID())) + m_targets.SetDst(*target); + else + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + break; + case TARGET_DEST_CHANNEL_CASTER: + m_targets.SetDst(*channeledSpell->GetCaster()); + break; + default: + ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target type"); + break; + } +} + +void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +{ + if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER) + { + ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target reference type"); + return; + } + + float range = 0.0f; + switch (targetType.GetCheckType()) + { + case TARGET_CHECK_ENEMY: + range = m_spellInfo->GetMaxRange(false, m_caster, this); + break; + case TARGET_CHECK_ALLY: + case TARGET_CHECK_PARTY: + case TARGET_CHECK_RAID: + case TARGET_CHECK_RAID_CLASS: + range = m_spellInfo->GetMaxRange(true, m_caster, this); + break; + case TARGET_CHECK_ENTRY: + case TARGET_CHECK_DEFAULT: + range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive(), m_caster, this); + break; + default: + ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented selection check type"); + break; + } + + ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions; + + // handle emergency case - try to use other provided targets if no conditions provided + if (targetType.GetCheckType() == TARGET_CHECK_ENTRY && (!condList || condList->empty())) + { + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::SelectImplicitNearbyTargets: no conditions entry for target with TARGET_CHECK_ENTRY of spell ID %u, effect %u - selecting default targets", m_spellInfo->Id, effIndex); + switch (targetType.GetObjectType()) + { + case TARGET_OBJECT_TYPE_GOBJ: + if (m_spellInfo->RequiresSpellFocus) + { + if (focusObject) + AddGOTarget(focusObject, effMask); + return; + } + break; + case TARGET_OBJECT_TYPE_DEST: + if (m_spellInfo->RequiresSpellFocus) + { + if (focusObject) + m_targets.SetDst(*focusObject); + return; + } + break; + default: + break; + } + } + + WorldObject* target = SearchNearbyTarget(range, targetType.GetObjectType(), targetType.GetCheckType(), condList); + if (!target) + { + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::SelectImplicitNearbyTargets: cannot find nearby target for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + return; + } + + switch (targetType.GetObjectType()) + { + case TARGET_OBJECT_TYPE_UNIT: + if (Unit* unitTarget = target->ToUnit()) + AddUnitTarget(unitTarget, effMask, false); + break; + case TARGET_OBJECT_TYPE_GOBJ: + if (GameObject* gobjTarget = target->ToGameObject()) + AddGOTarget(gobjTarget, effMask); + break; + case TARGET_OBJECT_TYPE_DEST: + m_targets.SetDst(*target); + break; + default: + ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target object type"); + break; + } + + SelectImplicitChainTargets(effIndex, targetType, target, effMask); +} + +void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +{ + if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER) + { + ASSERT(false && "Spell::SelectImplicitConeTargets: received not implemented target reference type"); + return; + } + std::list<WorldObject*> targets; + SpellTargetObjectTypes objectType = targetType.GetObjectType(); + SpellTargetCheckTypes selectionType = targetType.GetCheckType(); + ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions; + float coneAngle = M_PI/2; + float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod; + + if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList)) + { + Trinity::WorldObjectSpellConeTargetCheck check(coneAngle, radius, m_caster, m_spellInfo, selectionType, condList); + Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> searcher(m_caster, targets, check, containerTypeMask); + SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, radius); + + if (!targets.empty()) + { + // 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::RandomResizeList(targets, maxTargets); + } + + // for compability with older code - add only unit and go targets + // TODO: remove this + std::list<Unit*> unitTargets; + std::list<GameObject*> gObjTargets; + + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + { + if (Unit* unitTarget = (*itr)->ToUnit()) + unitTargets.push_back(unitTarget); + else if (GameObject* gObjTarget = (*itr)->ToGameObject()) + gObjTargets.push_back(gObjTarget); + } + + CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex); + + for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr) + AddUnitTarget(*itr, effMask, false); + + for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr) + AddGOTarget(*itr, effMask); + } + } +} + +void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +{ + Unit* referer = NULL; + switch (targetType.GetReferenceType()) + { + case TARGET_REFERENCE_TYPE_SRC: + case TARGET_REFERENCE_TYPE_DEST: + case TARGET_REFERENCE_TYPE_CASTER: + referer = m_caster; + break; + case TARGET_REFERENCE_TYPE_TARGET: + referer = m_targets.GetUnitTarget(); + break; + case TARGET_REFERENCE_TYPE_LAST: + { + // find last added target for this effect + for (std::list<TargetInfo>::reverse_iterator ihit = m_UniqueTargetInfo.rbegin(); ihit != m_UniqueTargetInfo.rend(); ++ihit) + { + if (ihit->effectMask & (1<<effIndex)) + { + referer = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); + break; + } + } + break; + } + default: + ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type"); + return; + } + if (!referer) + return; + + Position const* center = NULL; + switch (targetType.GetReferenceType()) + { + case TARGET_REFERENCE_TYPE_SRC: + center = m_targets.GetSrc(); + break; + case TARGET_REFERENCE_TYPE_DEST: + center = m_targets.GetDst(); + break; + case TARGET_REFERENCE_TYPE_CASTER: + case TARGET_REFERENCE_TYPE_TARGET: + case TARGET_REFERENCE_TYPE_LAST: + center = referer; + break; + default: + ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type"); + return; + } + std::list<WorldObject*> targets; + float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod; + SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions); + + // Custom entries + // TODO: remove those + switch (m_spellInfo->Id) + { + case 46584: // Raise Dead + { + if (Player* playerCaster = m_caster->ToPlayer()) + { + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + { + switch ((*itr)->GetTypeId()) + { + case TYPEID_UNIT: + case TYPEID_PLAYER: + { + Unit* unitTarget = (*itr)->ToUnit(); + if (unitTarget->isAlive() || !playerCaster->isHonorOrXPTarget(unitTarget) + || ((unitTarget->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0) + || (unitTarget->GetDisplayId() != unitTarget->GetNativeDisplayId())) + break; + AddUnitTarget(unitTarget, effMask, false); + // no break; + } + case TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet + m_targets.SetDst(*(*itr)); + return; // nothing more to do here + default: + break; + } + } + } + return; // don't add targets to target map + } + // Corpse Explosion + case 49158: + case 51325: + case 51326: + case 51327: + case 51328: + // check if our target is not valid (spell can target ghoul or dead unit) + if (!(m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetDisplayId() == m_targets.GetUnitTarget()->GetNativeDisplayId() && + ((m_targets.GetUnitTarget()->GetEntry() == 26125 && m_targets.GetUnitTarget()->GetOwnerGUID() == m_caster->GetGUID()) + || m_targets.GetUnitTarget()->isDead()))) + { + // remove existing targets + CleanupTargetList(); + + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + { + switch ((*itr)->GetTypeId()) + { + case TYPEID_UNIT: + case TYPEID_PLAYER: + if (!(*itr)->ToUnit()->isDead()) + break; + AddUnitTarget((*itr)->ToUnit(), 1 << effIndex, false); + return; + default: + break; + } + } + if (m_caster->GetTypeId() == TYPEID_PLAYER) + m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true); + SendCastResult(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW); + finish(false); + } + return; + default: + break; + } + std::list<Unit*> unitTargets; + std::list<GameObject*> gObjTargets; + // for compability with older code - add only unit and go targets + // TODO: remove this + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + { + if (Unit* unitTarget = (*itr)->ToUnit()) + unitTargets.push_back(unitTarget); + else if (GameObject* gObjTarget = (*itr)->ToGameObject()) + gObjTargets.push_back(gObjTarget); + } + + if (!unitTargets.empty()) + { + // Special target selection for smart heals and energizes + uint32 maxSize = 0; + int32 power = -1; + switch (m_spellInfo->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + switch (m_spellInfo->Id) + { + case 52759: // Ancestral Awakening + case 71610: // Echoes of Light (Althor's Abacus normal version) + case 71641: // Echoes of Light (Althor's Abacus heroic version) + maxSize = 1; + power = POWER_HEALTH; + break; + case 54968: // Glyph of Holy Light + maxSize = m_spellInfo->MaxAffectedTargets; + power = POWER_HEALTH; + break; + case 57669: // Replenishment + // In arenas Replenishment may only affect the caster + if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->InArena()) + { + unitTargets.clear(); + unitTargets.push_back(m_caster); + break; + } + maxSize = 10; + power = POWER_MANA; + break; + default: + break; + } + break; + case SPELLFAMILY_PRIEST: + if (m_spellInfo->SpellFamilyFlags[0] == 0x10000000) // Circle of Healing + { + maxSize = m_caster->HasAura(55675) ? 6 : 5; // Glyph of Circle of Healing + power = POWER_HEALTH; + } + else if (m_spellInfo->Id == 64844) // Divine Hymn + { + maxSize = 3; + power = POWER_HEALTH; + } + else if (m_spellInfo->Id == 64904) // Hymn of Hope + { + maxSize = 3; + power = POWER_MANA; + } + else + break; + + // Remove targets outside caster's raid + for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();) + { + if (!(*itr)->IsInRaidWith(m_caster)) + itr = unitTargets.erase(itr); + else + ++itr; + } + break; + case SPELLFAMILY_DRUID: + if (m_spellInfo->SpellFamilyFlags[1] == 0x04000000) // Wild Growth + { + maxSize = m_caster->HasAura(62970) ? 6 : 5; // Glyph of Wild Growth + power = POWER_HEALTH; + } + else if (m_spellInfo->SpellFamilyFlags[2] == 0x0100) // Starfall + { + // Remove targets not in LoS or in stealth + for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();) + { + if ((*itr)->HasStealthAura() || (*itr)->HasInvisibilityAura() || !(*itr)->IsWithinLOSInMap(m_caster)) + itr = unitTargets.erase(itr); + else + ++itr; + } + break; + } + else + break; + + // Remove targets outside caster's raid + for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();) + if (!(*itr)->IsInRaidWith(m_caster)) + itr = unitTargets.erase(itr); + else + ++itr; + break; + default: + break; + } + + if (maxSize && power != -1) + { + if (Powers(power) == POWER_HEALTH) + { + if (unitTargets.size() > maxSize) + { + unitTargets.sort(Trinity::HealthPctOrderPred()); + unitTargets.resize(maxSize); + } + } + else + { + for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();) + if ((*itr)->getPowerType() != (Powers)power) + itr = unitTargets.erase(itr); + else + ++itr; + + if (unitTargets.size() > maxSize) + { + unitTargets.sort(Trinity::PowerPctOrderPred((Powers)power)); + unitTargets.resize(maxSize); + } + } + } + + // 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(); + + if (m_spellInfo->Id == 5246) //Intimidating Shout + unitTargets.remove(m_targets.GetUnitTarget()); + Trinity::RandomResizeList(unitTargets, maxTargets); + } + + CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex); + + for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr) + AddUnitTarget(*itr, effMask, false); + } + + 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::RandomResizeList(gObjTargets, maxTargets); + } + for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr) + AddGOTarget(*itr, effMask); + } +} + +void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +{ + switch(targetType.GetTarget()) + { + case TARGET_DEST_CASTER: + m_targets.SetDst(*m_caster); + return; + case TARGET_DEST_HOME: + if (Player* playerCaster = m_caster->ToPlayer()) + m_targets.SetDst(playerCaster->m_homebindX, playerCaster->m_homebindY, playerCaster->m_homebindZ, playerCaster->GetOrientation(), playerCaster->m_homebindMapId); + return; + case TARGET_DEST_DB: + if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id)) + { + // TODO: fix this check + if (m_spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS)) + m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId); + else if (st->target_mapId == m_caster->GetMapId()) + m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation); + } + else + { + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id); + WorldObject* target = m_targets.GetObjectTarget(); + m_targets.SetDst(target ? *target : *m_caster); + } + return; + case TARGET_DEST_CASTER_FISHING: + { + float min_dis = m_spellInfo->GetMinRange(true); + float max_dis = m_spellInfo->GetMaxRange(true); + float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis; + float x, y, z, angle; + angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f); + m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle); + m_targets.SetDst(x, y, z, m_caster->GetOrientation()); + return; + } + default: + break; + } + + float dist; + float angle = targetType.CalcDirectionAngle(); + float objSize = m_caster->GetObjectSize(); + if (targetType.GetTarget() == TARGET_DEST_CASTER_SUMMON) + dist = PET_FOLLOW_DIST; + else + dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + + if (dist < objSize) + dist = objSize; + else if (targetType.GetTarget() == TARGET_DEST_CASTER_RANDOM) + dist = objSize + (dist - objSize) * (float)rand_norm(); + + Position pos; + if (targetType.GetTarget() == TARGET_DEST_CASTER_FRONT_LEAP) + m_caster->GetFirstCollisionPosition(pos, dist, angle); + else + m_caster->GetNearPosition(pos, dist, angle); + m_targets.SetDst(*m_caster); + m_targets.ModDst(pos); +} + +void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +{ + WorldObject* target = m_targets.GetObjectTarget(); + switch(targetType.GetTarget()) + { + case TARGET_DEST_TARGET_ENEMY: + case TARGET_DEST_TARGET_ANY: + m_targets.SetDst(*target); + return; + default: + break; + } + + float angle = targetType.CalcDirectionAngle(); + float objSize = target->GetObjectSize(); + float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + if (dist < objSize) + dist = objSize; + else if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM) + dist = objSize + (dist - objSize) * (float)rand_norm(); + + Position pos; + target->GetNearPosition(pos, dist, angle); + m_targets.SetDst(*target); + m_targets.ModDst(pos); +} + +void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +{ + // set destination to caster if no dest provided + // can only happen if previous destination target could not be set for some reason + // (not found nearby target, or channel target for example + // maybe we should abort the spell in such case? + if (!m_targets.HasDst()) + m_targets.SetDst(*m_caster); + + switch(targetType.GetTarget()) + { + case TARGET_DEST_DYNOBJ_ENEMY: + case TARGET_DEST_DYNOBJ_ALLY: + case TARGET_DEST_DYNOBJ_NONE: + case TARGET_DEST_DEST: + return; + case TARGET_DEST_TRAJ: + SelectImplicitTrajTargets(); + return; + default: + break; + } + + float angle = targetType.CalcDirectionAngle(); + float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM) + dist *= (float)rand_norm(); + + Position pos = *m_targets.GetDst(); + m_caster->MovePosition(pos, dist, angle); + m_targets.ModDst(pos); +} + +void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +{ + switch(targetType.GetTarget()) + { + case TARGET_UNIT_CASTER: + AddUnitTarget(m_caster, 1 << effIndex, false); + break; + case TARGET_UNIT_MASTER: + if (Unit* owner = m_caster->GetCharmerOrOwner()) + AddUnitTarget(owner, 1 << effIndex); + break; + case TARGET_UNIT_PET: + if (Guardian* pet = m_caster->GetGuardianPet()) + AddUnitTarget(pet, 1 << effIndex); + break; + case TARGET_UNIT_SUMMONER: + if (m_caster->isSummon()) + if (Unit* unit = m_caster->ToTempSummon()->GetSummoner()) + AddUnitTarget(unit, 1 << effIndex); + break; + case TARGET_UNIT_VEHICLE: + if (Unit *vehicle = m_caster->GetVehicleBase()) + AddUnitTarget(vehicle, 1 << effIndex); + break; + case TARGET_UNIT_PASSENGER_0: + case TARGET_UNIT_PASSENGER_1: + case TARGET_UNIT_PASSENGER_2: + case TARGET_UNIT_PASSENGER_3: + case TARGET_UNIT_PASSENGER_4: + case TARGET_UNIT_PASSENGER_5: + case TARGET_UNIT_PASSENGER_6: + case TARGET_UNIT_PASSENGER_7: + if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle()) + if (Unit *unit = m_caster->GetVehicleKit()->GetPassenger(targetType.GetTarget() - TARGET_UNIT_PASSENGER_0)) + AddUnitTarget(unit, 1 << effIndex); + break; + default: + break; + } +} + +void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +{ + ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!"); + if (Unit* unit = m_targets.GetUnitTarget()) + AddUnitTarget(unit, 1 << effIndex); + else if (GameObject* gobj = m_targets.GetGOTarget()) + AddGOTarget(gobj, 1 << effIndex); + else + AddItemTarget(m_targets.GetItemTarget(), effIndex); + + if (WorldObject* target = m_targets.GetObjectTarget()) + SelectImplicitChainTargets(effIndex, targetType, target, 1 << effIndex); +} + +void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask) +{ + uint32 maxTargets = m_spellInfo->Effects[effIndex].ChainTarget; + if (Player* modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this); + + if (maxTargets > 1) + { + // mark damage multipliers as used + for (uint32 k = effIndex; k < MAX_SPELL_EFFECTS; ++k) + if (effMask & (1 << k)) + m_damageMultipliers[k] = 1.0f; + m_applyMultiplierMask |= effMask; + + std::list<WorldObject*> targets; + SearchChainTargets(targets, maxTargets - 1, target, targetType.GetObjectType(), targetType.GetCheckType() + , m_spellInfo->Effects[effIndex].ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY); + + // for backward compability + std::list<Unit*> unitTargets; + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + if (Unit* unitTarget = (*itr)->ToUnit()) + unitTargets.push_back(unitTarget); + + CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex); + + for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr) + AddUnitTarget(*itr, effMask, false); + } +} + +float tangent(float x) +{ + x = tan(x); + //if (x < std::numeric_limits<float>::max() && x > -std::numeric_limits<float>::max()) return x; + //if (x >= std::numeric_limits<float>::max()) return std::numeric_limits<float>::max(); + //if (x <= -std::numeric_limits<float>::max()) return -std::numeric_limits<float>::max(); + if (x < 100000.0f && x > -100000.0f) return x; + if (x >= 100000.0f) return 100000.0f; + if (x <= 100000.0f) return -100000.0f; + return 0.0f; +} + +#define DEBUG_TRAJ(a) //a + +void Spell::SelectImplicitTrajTargets() +{ + if (!m_targets.HasTraj()) + return; + + float dist2d = m_targets.GetDist2d(); + if (!dist2d) + return; + + float srcToDestDelta = m_targets.GetDst()->m_positionZ - m_targets.GetSrc()->m_positionZ; + + std::list<WorldObject*> targets; + Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, m_targets.GetSrc(), m_caster, m_spellInfo); + Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> searcher(m_caster, targets, check, GRID_MAP_TYPE_MASK_ALL); + SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, m_targets.GetSrc(), dist2d); + if (targets.empty()) + return; + + targets.sort(Trinity::ObjectDistanceOrderPred(m_caster)); + + float b = tangent(m_targets.GetElevation()); + float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d); + if (a > -0.0001f) + a = 0; + DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: a %f b %f", a, b);) + + float bestDist = m_spellInfo->GetMaxRange(false); + + std::list<WorldObject*>::const_iterator itr = targets.begin(); + for (; itr != targets.end(); ++itr) + { + if (Unit* unitTarget = (*itr)->ToUnit()) + if (m_caster == *itr || m_caster->IsOnVehicle(unitTarget) || (unitTarget)->GetVehicle())//(*itr)->IsOnVehicle(m_caster)) + continue; + + const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3) + // TODO: all calculation should be based on src instead of m_caster + const float objDist2d = m_targets.GetSrc()->GetExactDist2d(*itr) * cos(m_targets.GetSrc()->GetRelativeAngle(*itr)); + const float dz = (*itr)->GetPositionZ() - m_targets.GetSrc()->m_positionZ; + + DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: check %u, dist between %f %f, height between %f %f.", (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size);) + + float dist = objDist2d - size; + float height = dist * (a * dist + b); + DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);) + if (dist < bestDist && height < dz + size && height > dz - size) + { + bestDist = dist > 0 ? dist : 0; + break; + } + +#define CHECK_DIST {\ + DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)\ + if (dist > bestDist)\ + continue;\ + if (dist < objDist2d + size && dist > objDist2d - size)\ + {\ + bestDist = dist;\ + break;\ + }\ + } + + if (!a) + { + height = dz - size; + dist = height / b; + CHECK_DIST; + + height = dz + size; + dist = height / b; + CHECK_DIST; + + continue; + } + + height = dz - size; + float sqrt1 = b * b + 4 * a * height; + if (sqrt1 > 0) + { + sqrt1 = sqrt(sqrt1); + dist = (sqrt1 - b) / (2 * a); + CHECK_DIST; + } + + height = dz + size; + float sqrt2 = b * b + 4 * a * height; + if (sqrt2 > 0) + { + sqrt2 = sqrt(sqrt2); + dist = (sqrt2 - b) / (2 * a); + CHECK_DIST; + + dist = (-sqrt2 - b) / (2 * a); + CHECK_DIST; + } + + if (sqrt1 > 0) + { + dist = (-sqrt1 - b) / (2 * a); + CHECK_DIST; + } + } + + if (m_targets.GetSrc()->GetExactDist2d(m_targets.GetDst()) > bestDist) + { + float x = m_targets.GetSrc()->m_positionX + cos(m_caster->GetOrientation()) * bestDist; + float y = m_targets.GetSrc()->m_positionY + sin(m_caster->GetOrientation()) * bestDist; + float z = m_targets.GetSrc()->m_positionZ + bestDist * (a * bestDist + b); + + if (itr != targets.end()) + { + float distSq = (*itr)->GetExactDistSq(x, y, z); + float sizeSq = (*itr)->GetObjectSize(); + sizeSq *= sizeSq; + DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);) + if (distSq > sizeSq) + { + float factor = 1 - sqrt(sizeSq / distSq); + x += factor * ((*itr)->GetPositionX() - x); + y += factor * ((*itr)->GetPositionY() - y); + z += factor * ((*itr)->GetPositionZ() - z); + + distSq = (*itr)->GetExactDistSq(x, y, z); + DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);) + } + } + + Position trajDst; + trajDst.Relocate(x, y, z, m_caster->GetOrientation()); + m_targets.ModDst(trajDst); + } +} + void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex) { // special case for SPELL_EFFECT_SUMMON_RAF_FRIEND and SPELL_EFFECT_SUMMON_PLAYER @@ -849,6 +1778,192 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex) } } +uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList) +{ + // this function selects which containers need to be searched for spell target + uint32 retMask = GRID_MAP_TYPE_MASK_ALL; + + // filter searchers based on searched object type + switch (objType) + { + case TARGET_OBJECT_TYPE_UNIT: + case TARGET_OBJECT_TYPE_UNIT_AND_DEST: + case TARGET_OBJECT_TYPE_CORPSE: + case TARGET_OBJECT_TYPE_CORPSE_ENEMY: + case TARGET_OBJECT_TYPE_CORPSE_ALLY: + retMask &= GRID_MAP_TYPE_MASK_PLAYER | GRID_MAP_TYPE_MASK_CORPSE | GRID_MAP_TYPE_MASK_CREATURE; + break; + case TARGET_OBJECT_TYPE_GOBJ: + case TARGET_OBJECT_TYPE_GOBJ_ITEM: + retMask &= GRID_MAP_TYPE_MASK_GAMEOBJECT; + break; + default: + break; + } + if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_DEAD)) + retMask &= ~GRID_MAP_TYPE_MASK_CORPSE; + if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS) + retMask &= GRID_MAP_TYPE_MASK_CORPSE | GRID_MAP_TYPE_MASK_PLAYER; + if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS) + retMask &= GRID_MAP_TYPE_MASK_PLAYER; + + if (condList) + retMask &= sConditionMgr->GetSearcherTypeMaskForConditionList(*condList); + return retMask; +} + +template<class SEARCHER> +void Spell::SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* referer, Position const* pos, float radius) +{ + if (!containerMask) + return; + + // search world and grid for possible targets + bool searchInGrid = containerMask & (GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_GAMEOBJECT); + bool searchInWorld = containerMask & (GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER | GRID_MAP_TYPE_MASK_CORPSE); + if (searchInGrid || searchInWorld) + { + float x,y; + x = pos->GetPositionX(); + y = pos->GetPositionY(); + + CellCoord p(Trinity::ComputeCellCoord(x, y)); + Cell cell(p); + cell.SetNoCreate(); + + Map& map = *(referer->GetMap()); + + if (searchInWorld) + { + TypeContainerVisitor<SEARCHER, WorldTypeMapContainer> world_object_notifier(searcher); + cell.Visit(p, world_object_notifier, map, radius, x, y); + } + if (searchInGrid) + { + TypeContainerVisitor<SEARCHER, GridTypeMapContainer > grid_object_notifier(searcher); + cell.Visit(p, grid_object_notifier, map, radius, x , y); + } + } +} + +WorldObject* Spell::SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList) +{ + WorldObject* target = NULL; + uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList); + if (!containerTypeMask) + return NULL; + Trinity::WorldObjectSpellNearbyTargetCheck check(range, m_caster, m_spellInfo, selectionType, condList); + Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck> searcher(m_caster, target, check, containerTypeMask); + SearchTargets<Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, range); + return target; +} + +void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList) +{ + uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList); + if (!containerTypeMask) + return; + Trinity::WorldObjectSpellAreaTargetCheck check(range, position, m_caster, referer, m_spellInfo, selectionType, condList); + Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(m_caster, targets, check, containerTypeMask); + SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, range); +} + +void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionList* condList, bool isChainHeal) +{ + // max dist for jump target selection + float jumpRadius = 0.0f; + switch (m_spellInfo->DmgClass) + { + case SPELL_DAMAGE_CLASS_RANGED: + // 7.5y for multi shot + jumpRadius = 7.5f; + break; + case SPELL_DAMAGE_CLASS_MELEE: + // 5y for swipe, cleave and similar + jumpRadius = 5.0f; + break; + case SPELL_DAMAGE_CLASS_NONE: + case SPELL_DAMAGE_CLASS_MAGIC: + // 12.5y for chain heal spell since 3.2 patch + if (isChainHeal) + jumpRadius = 12.5f; + // 10y as default for magic chain spells + else + jumpRadius = 10.0f; + break; + } + + // chain lightning/heal spells and similar - allow to jump at larger distance and go out of los + bool isBouncingFar = (m_spellInfo->AttributesEx4 & SPELL_ATTR4_AREA_TARGET_CHAIN + || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE + || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC); + + // max dist which spell can reach + float searchRadius = jumpRadius; + if (isBouncingFar) + searchRadius *= chainTargets; + + std::list<WorldObject*> tempTargets; + SearchAreaTargets(tempTargets, searchRadius, target, m_caster, objectType, selectType, condList); + tempTargets.remove(target); + + // remove targets which are always invalid for chain spells + // for some spells allow only chain targets in front of caster (swipe for example) + if (!isBouncingFar) + { + for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end();) + { + std::list<WorldObject*>::iterator checkItr = itr++; + if (!m_caster->HasInArc(static_cast<float>(M_PI), *checkItr)) + tempTargets.erase(checkItr); + } + } + + while (chainTargets) + { + // try to get unit for next chain jump + std::list<WorldObject*>::iterator foundItr = tempTargets.end(); + // get unit with highest hp deficit in dist + if (isChainHeal) + { + uint32 maxHPDeficit = 0; + for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr) + { + if (Unit* unitTarget = (*itr)->ToUnit()) + { + uint32 deficit = unitTarget->GetMaxHealth() - unitTarget->GetHealth(); + if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unitTarget, jumpRadius) && target->IsWithinLOSInMap(unitTarget)) + { + foundItr = itr; + maxHPDeficit = deficit; + } + } + } + } + // get closest object + else + { + for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr) + { + if (foundItr == tempTargets.end()) + { + if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr)) + foundItr = itr; + } + else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr)) + foundItr = itr; + } + } + // not found any valid target - chain ends + if (foundItr == tempTargets.end()) + break; + target = *foundItr; + tempTargets.erase(foundItr); + targets.push_back(target); + --chainTargets; + } +} + void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/) { //========================================================================================== @@ -1402,13 +2517,17 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) } } -SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, const uint32 effectMask, bool scaleAura) +SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleAura) { if (!unit || !effectMask) return SPELL_MISS_EVADE; - // Recheck immune (only for delayed spells) - if (m_spellInfo->Speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo))) + // For delayed spells immunity may be applied between missile launch and hit - check immunity for that case + // disable effects to which unit is immune + for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) + if (effectMask & (1 << effectNumber) && unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber)) + effectMask &= ~(1 << effectNumber); + if (!effectMask || (m_spellInfo->Speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo)))) return SPELL_MISS_IMMUNE; PrepareScriptHitHandlers(); @@ -1563,7 +2682,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, const uint32 effectMask, bool } for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) - if (effectMask & (1 << effectNumber) && !unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber)) //Handle effect only if the target isn't immune. + if (effectMask & (1 << effectNumber)) HandleEffects(unit, NULL, NULL, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); return SPELL_MISS_NONE; @@ -1771,1082 +2890,6 @@ struct ChainHealingOrder : public std::binary_function<const Unit*, const Unit*, } }; -void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uint32 num, SpellTargets TargetType) -{ - Unit* cur = m_targets.GetUnitTarget(); - if (!cur) - return; - - //FIXME: This very like horrible hack and wrong for most spells - if (m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE) - max_range += num * CHAIN_SPELL_JUMP_RADIUS; - - std::list<Unit*> tempUnitMap; - if (TargetType == SPELL_TARGETS_CHAINHEAL) - { - SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, SPELL_TARGETS_ALLY); - tempUnitMap.sort(ChainHealingOrder(m_caster)); - } - else - SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, TargetType); - tempUnitMap.remove(cur); - - while (num) - { - TagUnitMap.push_back(cur); - --num; - - if (tempUnitMap.empty()) - break; - - std::list<Unit*>::iterator next; - - if (TargetType == SPELL_TARGETS_CHAINHEAL) - { - next = tempUnitMap.begin(); - while (cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS || !cur->IsWithinLOSInMap(*next)) - { - ++next; - if (next == tempUnitMap.end()) - return; - } - } - else - { - tempUnitMap.sort(Trinity::ObjectDistanceOrderPred(cur)); - next = tempUnitMap.begin(); - - if (cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) // Don't search beyond the max jump radius - break; - - // Check if (*next) is a valid chain target. If not, don't add to TagUnitMap, and repeat loop. - // If you want to add any conditions to exclude a target from TagUnitMap, add condition in this while () loop. - while ((m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE - && !m_caster->isInFrontInMap(*next, max_range)) - || !m_caster->canSeeOrDetect(*next) - || !cur->IsWithinLOSInMap(*next) - || (*next)->GetCreatureType() == CREATURE_TYPE_CRITTER - || ((GetSpellInfo()->AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED) && !(*next)->CanFreeMove())) - { - ++next; - if (next == tempUnitMap.end() || cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) // Don't search beyond the max jump radius - return; - } - } - - cur = *next; - tempUnitMap.erase(next); - } -} - -void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry) -{ - if (TargetType == SPELL_TARGETS_GO) - return; - - Position const* pos; - switch (type) - { - case PUSH_DST_CENTER: - CheckDst(); - pos = m_targets.GetDst(); - break; - case PUSH_SRC_CENTER: - CheckSrc(); - pos = m_targets.GetSrc(); - break; - case PUSH_CHAIN: - { - Unit* target = m_targets.GetUnitTarget(); - if (!target) - { - sLog->outError("SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id); - return; - } - pos = target; - break; - } - default: - pos = m_caster; - break; - } - - Trinity::SpellNotifierCreatureAndPlayer notifier(m_caster, TagUnitMap, radius, type, TargetType, pos, entry, m_spellInfo); - if ((m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS) || (TargetType == SPELL_TARGETS_ENTRY && !entry)) - m_caster->GetMap()->VisitWorld(pos->m_positionX, pos->m_positionY, radius, notifier); - else - m_caster->GetMap()->VisitAll(pos->m_positionX, pos->m_positionY, radius, notifier); -} - -void Spell::SearchGOAreaTarget(std::list<GameObject*> &TagGOMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry) -{ - if (TargetType != SPELL_TARGETS_GO) - return; - - Position const* pos; - switch (type) - { - case PUSH_DST_CENTER: - CheckDst(); - pos = m_targets.GetDst(); - break; - case PUSH_SRC_CENTER: - CheckSrc(); - pos = m_targets.GetSrc(); - break; - default: - pos = m_caster; - break; - } - - Trinity::GameObjectInRangeCheck check(pos->m_positionX, pos->m_positionY, pos->m_positionZ, radius, entry); - Trinity::GameObjectListSearcher<Trinity::GameObjectInRangeCheck> searcher(m_caster, TagGOMap, check); - m_caster->GetMap()->VisitGrid(pos->m_positionX, pos->m_positionY, radius, searcher); -} - -WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType, SpellEffIndex effIndex) -{ - switch (TargetType) - { - case SPELL_TARGETS_ENTRY: - { - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id); - if (conditions.empty()) - { - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell (ID: %u) (caster Entry: %u) does not have record in `conditions` for spell script target (ConditionSourceType 13)", m_spellInfo->Id, m_caster->GetEntry()); - if (m_spellInfo->IsPositive()) - return SearchNearbyTarget(range, SPELL_TARGETS_ALLY, effIndex); - else - return SearchNearbyTarget(range, SPELL_TARGETS_ENEMY, effIndex); - } - - Creature* creatureScriptTarget = NULL; - GameObject* goScriptTarget = NULL; - - for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST) - { - if ((*i_spellST)->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) - continue; - if ((*i_spellST)->mConditionValue3 && !((*i_spellST)->mConditionValue3 & (1 << uint32(effIndex)))) - continue; - switch ((*i_spellST)->mConditionValue1) - { - case SPELL_TARGET_TYPE_CONTROLLED: - for (Unit::ControlList::iterator itr = m_caster->m_Controlled.begin(); itr != m_caster->m_Controlled.end(); ++itr) - if ((*itr)->GetEntry() == (*i_spellST)->mConditionValue2 && (*itr)->IsWithinDistInMap(m_caster, range)) - { - goScriptTarget = NULL; - creatureScriptTarget = (*itr)->ToCreature(); - range = m_caster->GetDistance(creatureScriptTarget); - } - break; - case SPELL_TARGET_TYPE_GAMEOBJECT: - if ((*i_spellST)->mConditionValue2) - { - if (GameObject* go = m_caster->FindNearestGameObject((*i_spellST)->mConditionValue2, range)) - { - // remember found target and range, next attempt will find more near target with another entry - goScriptTarget = go; - creatureScriptTarget = NULL; - range = m_caster->GetDistance(goScriptTarget); - } - } - else if (focusObject) //Focus Object - { - float frange = m_caster->GetDistance(focusObject); - if (range >= frange) - { - creatureScriptTarget = NULL; - goScriptTarget = focusObject; - range = frange; - } - } - break; - case SPELL_TARGET_TYPE_CREATURE: - if (m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetEntry() == (*i_spellST)->mConditionValue2) - return m_targets.GetUnitTarget(); - case SPELL_TARGET_TYPE_DEAD: - default: - if (Creature* cre = m_caster->FindNearestCreature((*i_spellST)->mConditionValue2, range, (*i_spellST)->mConditionValue1 != SPELL_TARGET_TYPE_DEAD)) - { - creatureScriptTarget = cre; - goScriptTarget = NULL; - range = m_caster->GetDistance(creatureScriptTarget); - } - break; - } - } - - if (creatureScriptTarget) - return creatureScriptTarget; - else - return goScriptTarget; - } - default: - case SPELL_TARGETS_ENEMY: - { - Unit* target = NULL; - Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range); - Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check); - m_caster->VisitNearbyObject(range, searcher); - return target; - } - case SPELL_TARGETS_ALLY: - { - Unit* target = NULL; - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range); - Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check); - m_caster->VisitNearbyObject(range, searcher); - return target; - } - } -} - -uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) -{ - SpellNotifyPushType pushType = PUSH_NONE; - Player* modOwner = NULL; - if (m_originalCaster) - modOwner = m_originalCaster->GetSpellModOwner(); - - uint32 effectMask = 1 << i; - // ENTRY targets may have different selection lists, skip those for now until we can compare lists easily and quickly - if (GetSpellInfo()->Effects[i].TargetA.GetSelectionCheckType() != TARGET_SELECT_CHECK_ENTRY && - GetSpellInfo()->Effects[i].TargetB.GetSelectionCheckType() != TARGET_SELECT_CHECK_ENTRY) - for (uint32 j = i + 1; j < MAX_SPELL_EFFECTS; ++j) - if (GetSpellInfo()->Effects[i].TargetA.GetTarget() == GetSpellInfo()->Effects[j].TargetA.GetTarget() && - GetSpellInfo()->Effects[i].TargetB.GetTarget() == GetSpellInfo()->Effects[j].TargetB.GetTarget() && - GetSpellInfo()->Effects[i].CalcRadius(m_caster) == GetSpellInfo()->Effects[j].CalcRadius(m_caster)) - effectMask |= 1 << j; - - switch (cur.GetType()) - { - case TARGET_TYPE_UNIT_CASTER: - { - switch (cur.GetTarget()) - { - case TARGET_UNIT_CASTER: - AddUnitTarget(m_caster, effectMask, false); - break; - case TARGET_DEST_CASTER_FISHING: - { - float min_dis = m_spellInfo->GetMinRange(true); - float max_dis = m_spellInfo->GetMaxRange(true); - float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis; - float x, y, z, angle; - angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f); - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle); - m_targets.SetDst(x, y, z, m_caster->GetOrientation()); - break; - } - case TARGET_UNIT_MASTER: - if (Unit* owner = m_caster->GetCharmerOrOwner()) - AddUnitTarget(owner, effectMask); - break; - case TARGET_UNIT_PET: - if (Guardian* pet = m_caster->GetGuardianPet()) - AddUnitTarget(pet, effectMask); - break; - case TARGET_UNIT_SUMMONER: - if (m_caster->isSummon()) - if (Unit* unit = m_caster->ToTempSummon()->GetSummoner()) - AddUnitTarget(unit, effectMask); - break; - case TARGET_UNIT_CASTER_AREA_PARTY: - case TARGET_UNIT_CASTER_AREA_RAID: - pushType = PUSH_CASTER_CENTER; - break; - case TARGET_UNIT_VEHICLE: - if (Unit* vehicle = m_caster->GetVehicleBase()) - AddUnitTarget(vehicle, effectMask); - break; - case TARGET_UNIT_PASSENGER_0: - case TARGET_UNIT_PASSENGER_1: - case TARGET_UNIT_PASSENGER_2: - case TARGET_UNIT_PASSENGER_3: - case TARGET_UNIT_PASSENGER_4: - case TARGET_UNIT_PASSENGER_5: - case TARGET_UNIT_PASSENGER_6: - case TARGET_UNIT_PASSENGER_7: - if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle()) - if (Unit* unit = m_caster->GetVehicleKit()->GetPassenger(cur.GetTarget() - TARGET_UNIT_PASSENGER_0)) - AddUnitTarget(unit, effectMask); - break; - default: - break; - } - break; - } - - case TARGET_TYPE_UNIT_TARGET: - { - Unit* target = m_targets.GetUnitTarget(); - if (!target) - { - sLog->outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id); - break; - } - - switch (cur.GetTarget()) - { - case TARGET_UNIT_TARGET_ENEMY: - if (Unit* magnet = m_caster->SelectMagnetTarget(target, m_spellInfo)) - if (magnet != target) - m_targets.SetUnitTarget(magnet); - pushType = PUSH_CHAIN; - break; - case TARGET_UNIT_TARGET_ANY: - if (!m_spellInfo->IsPositive()) - if (Unit* magnet = m_caster->SelectMagnetTarget(target, m_spellInfo)) - if (magnet != target) - m_targets.SetUnitTarget(magnet); - pushType = PUSH_CHAIN; - break; - case TARGET_UNIT_TARGET_CHAINHEAL_ALLY: - pushType = PUSH_CHAIN; - break; - case TARGET_UNIT_TARGET_ALLY: - AddUnitTarget(target, effectMask, false); - break; - case TARGET_UNIT_TARGET_RAID: - case TARGET_UNIT_TARGET_PARTY: - case TARGET_UNIT_TARGET_MINIPET: - AddUnitTarget(target, effectMask, false); - break; - case TARGET_UNIT_TARGET_PASSENGER: - AddUnitTarget(target, effectMask, false); - break; - case TARGET_UNIT_LASTTARGET_AREA_PARTY: - case TARGET_UNIT_TARGET_AREA_RAID_CLASS: - pushType = PUSH_CASTER_CENTER; // not real - break; - default: - break; - } - break; - } - - case TARGET_TYPE_UNIT_NEARBY: - { - WorldObject* target = NULL; - float range; - - switch (cur.GetTarget()) - { - case TARGET_UNIT_NEARBY_ENEMY: - range = m_spellInfo->GetMaxRange(false); - if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - target = SearchNearbyTarget(range, SPELL_TARGETS_ENEMY, SpellEffIndex(i)); - break; - case TARGET_UNIT_NEARBY_ALLY: - case TARGET_UNIT_NEARBY_PARTY: // TODO: fix party/raid targets - case TARGET_UNIT_NEARBY_RAID: - range = m_spellInfo->GetMaxRange(true); - if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - target = SearchNearbyTarget(range, SPELL_TARGETS_ALLY, SpellEffIndex(i)); - break; - case TARGET_UNIT_NEARBY_ENTRY: - case TARGET_GAMEOBJECT_NEARBY_ENTRY: - range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive()); - if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY, SpellEffIndex(i)); - break; - default: - break; - } - - if (!target) - return 0; - else if (target->GetTypeId() == TYPEID_GAMEOBJECT) - AddGOTarget((GameObject*)target, effectMask); - else - { - pushType = PUSH_CHAIN; - - if (m_targets.GetUnitTarget() != target) - m_targets.SetUnitTarget((Unit*)target); - } - - break; - } - - case TARGET_TYPE_AREA_SRC: - pushType = PUSH_SRC_CENTER; - break; - - case TARGET_TYPE_AREA_DST: - pushType = PUSH_DST_CENTER; - break; - - case TARGET_TYPE_AREA_CONE: - if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_BACK) - pushType = PUSH_IN_BACK; - else if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_LINE) - pushType = PUSH_IN_LINE; - else - pushType = PUSH_IN_FRONT; - break; - - case TARGET_TYPE_DEST_CASTER: //4+8+2 - { - if (cur.GetTarget() == TARGET_SRC_CASTER) - { - m_targets.SetSrc(*m_caster); - break; - } - else if (cur.GetTarget() == TARGET_DEST_CASTER) - { - m_targets.SetDst(*m_caster); - break; - } - - float angle, dist; - - float objSize = m_caster->GetObjectSize(); - if (cur.GetTarget() == TARGET_DEST_CASTER_SUMMON) - dist = 0.0f; - else - dist = m_spellInfo->Effects[i].CalcRadius(m_caster); - if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, dist, this); - if (dist < objSize) - dist = objSize; - else if (cur.GetTarget() == TARGET_DEST_CASTER_RANDOM) - dist = objSize + (dist - objSize) * (float)rand_norm(); - - switch (cur.GetTarget()) - { - case TARGET_DEST_CASTER_FRONT_LEFT: angle = static_cast<float>(-M_PI/4); break; - case TARGET_DEST_CASTER_BACK_LEFT: angle = static_cast<float>(-3*M_PI/4); break; - case TARGET_DEST_CASTER_BACK_RIGHT: angle = static_cast<float>(3*M_PI/4); break; - case TARGET_DEST_CASTER_FRONT_RIGHT:angle = static_cast<float>(M_PI/4); break; - case TARGET_DEST_CASTER_SUMMON: - case TARGET_DEST_CASTER_FRONT_LEAP: - case TARGET_DEST_CASTER_FRONT: angle = 0.0f; break; - case TARGET_DEST_CASTER_BACK: angle = static_cast<float>(M_PI); break; - case TARGET_DEST_CASTER_RIGHT: angle = static_cast<float>(-M_PI/2); break; - case TARGET_DEST_CASTER_LEFT: angle = static_cast<float>(M_PI/2); break; - default: angle = (float)rand_norm()*static_cast<float>(2*M_PI); break; - } - - Position pos; - if (cur.GetTarget() == TARGET_DEST_CASTER_FRONT_LEAP) - m_caster->GetFirstCollisionPosition(pos, dist, angle); - else - m_caster->GetNearPosition(pos, dist, angle); - m_targets.SetDst(*m_caster); - m_targets.ModDst(pos); - break; - } - - case TARGET_TYPE_DEST_TARGET: //2+8+2 - { - Unit* target = m_targets.GetUnitTarget(); - if (!target) - { - sLog->outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id); - break; - } - - if (cur.GetTarget() == TARGET_DEST_TARGET_ENEMY || cur.GetTarget() == TARGET_DEST_TARGET_ANY) - { - m_targets.SetDst(*target); - break; - } - - float angle, dist; - - float objSize = target->GetObjectSize(); - dist = m_spellInfo->Effects[i].CalcRadius(m_caster); - if (dist < objSize) - dist = objSize; - else if (cur.GetTarget() == TARGET_DEST_TARGET_RANDOM) - dist = objSize + (dist - objSize) * (float)rand_norm(); - - switch (cur.GetTarget()) - { - case TARGET_DEST_TARGET_FRONT: angle = 0.0f; break; - case TARGET_DEST_TARGET_BACK: angle = static_cast<float>(M_PI); break; - case TARGET_DEST_TARGET_RIGHT: angle = static_cast<float>(M_PI/2); break; - case TARGET_DEST_TARGET_LEFT: angle = static_cast<float>(-M_PI/2); break; - case TARGET_DEST_TARGET_FRONT_LEFT: angle = static_cast<float>(-M_PI/4); break; - case TARGET_DEST_TARGET_BACK_LEFT: angle = static_cast<float>(-3*M_PI/4); break; - case TARGET_DEST_TARGET_BACK_RIGHT: angle = static_cast<float>(3*M_PI/4); break; - case TARGET_DEST_TARGET_FRONT_RIGHT:angle = static_cast<float>(M_PI/4); break; - default: angle = (float)rand_norm()*static_cast<float>(2*M_PI); break; - } - - Position pos; - target->GetNearPosition(pos, dist, angle); - m_targets.SetDst(*target); - m_targets.ModDst(pos); - break; - } - - case TARGET_TYPE_DEST_DEST: //5+8+1 - { - if (!m_targets.HasDst()) - { - sLog->outError("SPELL: no destination for spell ID %u", m_spellInfo->Id); - break; - } - - float angle; - switch (cur.GetTarget()) - { - case TARGET_DEST_DYNOBJ_ENEMY: - case TARGET_DEST_DYNOBJ_ALLY: - case TARGET_DEST_DYNOBJ_NONE: - case TARGET_DEST_DEST: - return effectMask; - case TARGET_DEST_TRAJ: - SelectTrajTargets(); - return effectMask; - case TARGET_DEST_DEST_FRONT: angle = 0.0f; break; - case TARGET_DEST_DEST_BACK: angle = static_cast<float>(M_PI); break; - case TARGET_DEST_DEST_RIGHT: angle = static_cast<float>(M_PI/2); break; - case TARGET_DEST_DEST_LEFT: angle = static_cast<float>(-M_PI/2); break; - case TARGET_DEST_DEST_FRONT_LEFT: angle = static_cast<float>(-M_PI/4); break; - case TARGET_DEST_DEST_BACK_LEFT: angle = static_cast<float>(-3*M_PI/4); break; - case TARGET_DEST_DEST_BACK_RIGHT: angle = static_cast<float>(3*M_PI/4); break; - case TARGET_DEST_DEST_FRONT_RIGHT:angle = static_cast<float>(M_PI/4); break; - default: angle = (float)rand_norm()*static_cast<float>(2*M_PI); break; - } - - float dist = m_spellInfo->Effects[i].CalcRadius(m_caster); - if (cur.GetTarget() == TARGET_DEST_DEST_RANDOM || cur.GetTarget() == TARGET_DEST_DEST_RADIUS) - dist *= (float)rand_norm(); - - // must has dst, no need to set flag - Position pos = *m_targets.GetDst(); - m_caster->MovePosition(pos, dist, angle); - m_targets.ModDst(pos); - break; - } - - case TARGET_TYPE_DEST_SPECIAL: - { - switch (cur.GetTarget()) - { - case TARGET_DEST_DB: - if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id)) - { - //TODO: fix this check - if (m_spellInfo->Effects[0].Effect == SPELL_EFFECT_TELEPORT_UNITS || m_spellInfo->Effects[1].Effect == SPELL_EFFECT_TELEPORT_UNITS || m_spellInfo->Effects[2].Effect == SPELL_EFFECT_TELEPORT_UNITS) - m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId); - else if (st->target_mapId == m_caster->GetMapId()) - m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation); - } - else - { - sLog->outError("SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id); - Unit* target = NULL; - if (uint64 guid = m_caster->GetUInt64Value(UNIT_FIELD_TARGET)) - target = ObjectAccessor::GetUnit(*m_caster, guid); - m_targets.SetDst(target ? *target : *m_caster); - } - break; - case TARGET_DEST_HOME: - if (m_caster->GetTypeId() == TYPEID_PLAYER) - m_targets.SetDst(m_caster->ToPlayer()->m_homebindX, m_caster->ToPlayer()->m_homebindY, m_caster->ToPlayer()->m_homebindZ, m_caster->ToPlayer()->GetOrientation(), m_caster->ToPlayer()->m_homebindMapId); - break; - case TARGET_DEST_NEARBY_ENTRY: - { - float range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive()); - if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - - if (WorldObject* target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY, SpellEffIndex(i))) - m_targets.SetDst(*target); - break; - } - default: - break; - } - break; - } - - case TARGET_TYPE_CHANNEL: - { - if (!m_originalCaster || !m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) - { - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: no current channeled spell for spell ID %u - spell triggering this spell was interrupted.", m_spellInfo->Id); - break; - } - - switch (cur.GetTarget()) - { - case TARGET_UNIT_CHANNEL_TARGET: - // unit target may be no longer avalible - teleported out of map for example - if (Unit* target = Unit::GetUnit(*m_caster, m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.GetUnitTargetGUID())) - AddUnitTarget(target, effectMask); - else - sLog->outError("SPELL: cannot find channel spell target for spell ID %u", m_spellInfo->Id); - break; - case TARGET_DEST_CHANNEL_TARGET: - if (m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.HasDst()) - m_targets.SetDst(m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets); - else if (Unit* target = Unit::GetUnit(*m_caster, m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.GetUnitTargetGUID())) - m_targets.SetDst(*target); - else - sLog->outError("SPELL: cannot find channel spell destination for spell ID %u", m_spellInfo->Id); - break; - case TARGET_DEST_CHANNEL_CASTER: - m_targets.SetDst(*m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->GetCaster()); - break; - default: - break; - } - break; - } - - default: - { - switch (cur.GetTarget()) - { - case TARGET_GAMEOBJECT_TARGET: - if (m_targets.GetGOTarget()) - AddGOTarget(m_targets.GetGOTarget(), effectMask); - break; - case TARGET_GAMEOBJECT_ITEM_TARGET: - if (m_targets.GetGOTargetGUID()) - AddGOTarget(m_targets.GetGOTarget(), effectMask); - else if (m_targets.GetItemTarget()) - AddItemTarget(m_targets.GetItemTarget(), effectMask); - break; - default: - sLog->outError("SPELL (caster[type: %u; guidlow: %u], spell: %u): unhandled spell target (%u)", - m_caster->GetTypeId(), m_caster->GetGUIDLow(), m_spellInfo->Id, cur.GetTarget()); - break; - } - break; - } - } - - if (pushType == PUSH_CHAIN) // Chain - { - Unit* target = m_targets.GetUnitTarget(); - if (!target) - { - sLog->outError("SPELL: no chain unit target for spell ID %u", m_spellInfo->Id); - return 0; - } - - //Chain: 2, 6, 22, 25, 45, 77 - uint32 maxTargets = m_spellInfo->Effects[i].ChainTarget; - if (modOwner) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this); - - if (maxTargets > 1) - { - //otherwise, this multiplier is used for something else - for (uint32 k = i; k < MAX_SPELL_EFFECTS; ++k) - if (effectMask & (1 << k)) - m_damageMultipliers[k] = 1.0f; - m_applyMultiplierMask |= effectMask; - - float range; - std::list<Unit*> unitList; - - switch (cur.GetTarget()) - { - case TARGET_UNIT_NEARBY_ENEMY: - case TARGET_UNIT_TARGET_ENEMY: - case TARGET_UNIT_NEARBY_ENTRY: // fix me - range = m_spellInfo->GetMaxRange(false); - if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - SearchChainTarget(unitList, range, maxTargets, SPELL_TARGETS_ENEMY); - break; - case TARGET_UNIT_TARGET_CHAINHEAL_ALLY: - case TARGET_UNIT_NEARBY_ALLY: // fix me - case TARGET_UNIT_NEARBY_PARTY: - case TARGET_UNIT_NEARBY_RAID: - range = m_spellInfo->GetMaxRange(true); - if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - SearchChainTarget(unitList, range, maxTargets, SPELL_TARGETS_CHAINHEAL); - break; - default: - break; - } - - CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i)); - - for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) - AddUnitTarget(*itr, effectMask, false); - } - else - AddUnitTarget(target, effectMask, false); - } - else if (pushType) - { - float radius; - SpellTargets targetType; - switch (cur.GetTarget()) - { - case TARGET_UNIT_SRC_AREA_ENEMY: - case TARGET_UNIT_DEST_AREA_ENEMY: - case TARGET_UNIT_CONE_ENEMY_24: - case TARGET_UNIT_CONE_ENEMY_54: - case TARGET_UNIT_CONE_ENEMY_104: - radius = m_spellInfo->Effects[i].CalcRadius(); - targetType = SPELL_TARGETS_ENEMY; - break; - case TARGET_UNIT_SRC_AREA_ALLY: - case TARGET_UNIT_DEST_AREA_ALLY: - case TARGET_UNIT_CONE_ALLY: - radius = m_spellInfo->Effects[i].CalcRadius(); - targetType = SPELL_TARGETS_ALLY; - break; - case TARGET_UNIT_DEST_AREA_ENTRY: - case TARGET_UNIT_SRC_AREA_ENTRY: - case TARGET_UNIT_CONE_ENTRY: // fix me - radius = m_spellInfo->Effects[i].CalcRadius(); - targetType = SPELL_TARGETS_ENTRY; - break; - case TARGET_GAMEOBJECT_SRC_AREA: - case TARGET_GAMEOBJECT_DEST_AREA: - case TARGET_GAMEOBJECT_CONE: - radius = m_spellInfo->Effects[i].CalcRadius(); - targetType = SPELL_TARGETS_GO; - break; - default: - radius = m_spellInfo->Effects[i].CalcRadius(); - targetType = SPELL_TARGETS_NONE; - break; - } - - if (modOwner) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); - radius *= m_spellValue->RadiusMod; - - std::list<Unit*> unitList; - std::list<GameObject*> gobjectList; - switch (targetType) - { - case SPELL_TARGETS_ENTRY: - { - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id); - if (!conditions.empty()) - { - for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST) - { - if ((*i_spellST)->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) - continue; - if ((*i_spellST)->mConditionValue3 && !((*i_spellST)->mConditionValue3 & effectMask)) - continue; - if ((*i_spellST)->mConditionValue1 == SPELL_TARGET_TYPE_CREATURE) - SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, (*i_spellST)->mConditionValue2); - else if ((*i_spellST)->mConditionValue1 == SPELL_TARGET_TYPE_CONTROLLED) - { - for (Unit::ControlList::iterator itr = m_caster->m_Controlled.begin(); itr != m_caster->m_Controlled.end(); ++itr) - if ((*itr)->GetEntry() == (*i_spellST)->mConditionValue2 && - (*itr)->IsInMap(m_caster)) // For 60243 and 52173 need skip radius check or use range (no radius entry for effect) - unitList.push_back(*itr); - } - } - } - else - { - // Custom entries - // TODO: move these to sql - switch (m_spellInfo->Id) - { - case 46584: // Raise Dead - { - if (WorldObject* result = FindCorpseUsing<Trinity::RaiseDeadObjectCheck> ()) - { - switch (result->GetTypeId()) - { - case TYPEID_UNIT: - m_targets.SetDst(*result); - break; - default: - break; - } - } - break; - } - // Corpse Explosion - case 49158: - case 51325: - case 51326: - case 51327: - case 51328: - // Search for ghoul if our ghoul or dead body not valid unit target - if (!(m_targets.GetUnitTarget() && ((m_targets.GetUnitTarget()->GetEntry() == 26125 && m_targets.GetUnitTarget()->GetOwnerGUID() == m_caster->GetGUID()) - || (m_targets.GetUnitTarget()->getDeathState() == CORPSE - && m_targets.GetUnitTarget()->GetTypeId() == TYPEID_UNIT - && !(m_targets.GetUnitTarget()->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) - && m_targets.GetUnitTarget()->GetDisplayId() == m_targets.GetUnitTarget()->GetNativeDisplayId())))) - { - CleanupTargetList(); - - WorldObject* result = FindCorpseUsing <Trinity::ExplodeCorpseObjectCheck> (); - - if (result) - { - switch (result->GetTypeId()) - { - case TYPEID_UNIT: - case TYPEID_PLAYER: - m_targets.SetUnitTarget((Unit*)result); - break; - default: - break; - } - } - else - { - if (m_caster->GetTypeId() == TYPEID_PLAYER) - m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true); - SendCastResult(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW); - finish(false); - } - } - break; - - default: - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell (ID: %u) (caster Entry: %u) does not have type CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET record in `conditions` table.", m_spellInfo->Id, m_caster->GetEntry()); - - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_TELEPORT_UNITS) - SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, 0); - else if (m_spellInfo->IsPositiveEffect(i)) - SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ALLY); - else - SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENEMY); - } - } - break; - } - case SPELL_TARGETS_GO: - { - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id); - if (!conditions.empty()) - { - for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST) - { - if ((*i_spellST)->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) - continue; - if ((*i_spellST)->mConditionValue3 && !((*i_spellST)->mConditionValue3 & effectMask)) - continue; - if ((*i_spellST)->mConditionValue1 == SPELL_TARGET_TYPE_GAMEOBJECT) - SearchGOAreaTarget(gobjectList, radius, pushType, SPELL_TARGETS_GO, (*i_spellST)->mConditionValue2); - } - } - else - { - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_ACTIVATE_OBJECT) - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell (ID: %u) (caster Entry: %u) with SPELL_EFFECT_ACTIVATE_OBJECT does not have type CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET record in `conditions` table.", m_spellInfo->Id, m_caster->GetEntry()); - SearchGOAreaTarget(gobjectList, radius, pushType, SPELL_TARGETS_GO); - } - break; - } - case SPELL_TARGETS_ALLY: - case SPELL_TARGETS_ENEMY: - case SPELL_TARGETS_CHAINHEAL: - case SPELL_TARGETS_ANY: - SearchAreaTarget(unitList, radius, pushType, targetType); - break; - default: - switch (cur.GetTarget()) - { - case TARGET_UNIT_SRC_AREA_PARTY: - case TARGET_UNIT_DEST_AREA_PARTY: - m_caster->GetPartyMemberInDist(unitList, radius); //fix me - break; - case TARGET_UNIT_LASTTARGET_AREA_PARTY: - m_targets.GetUnitTarget()->GetPartyMemberInDist(unitList, radius); - break; - case TARGET_UNIT_CASTER_AREA_PARTY: - m_caster->GetPartyMemberInDist(unitList, radius); - break; - case TARGET_UNIT_CASTER_AREA_RAID: - m_caster->GetRaidMember(unitList, radius); - break; - case TARGET_UNIT_TARGET_AREA_RAID_CLASS: - { - Player* targetPlayer = m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetTypeId() == TYPEID_PLAYER - ? (Player*)m_targets.GetUnitTarget() : NULL; - - Group* group = targetPlayer ? targetPlayer->GetGroup() : NULL; - if (group) - { - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* Target = itr->getSource(); - - // IsHostileTo check duel and controlled by enemy - if (Target && targetPlayer->IsWithinDistInMap(Target, radius) && targetPlayer->getClass() == Target->getClass() && !m_caster->IsHostileTo(Target)) - AddUnitTarget(Target, effectMask); - } - } - else if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), effectMask); - break; - } - default: - break; - } - break; - } - - if (!unitList.empty()) - { - // Special target selection for smart heals and energizes - uint32 maxSize = 0; - int32 power = -1; - switch (m_spellInfo->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - switch (m_spellInfo->Id) - { - case 52759: // Ancestral Awakening - case 71610: // Echoes of Light (Althor's Abacus normal version) - case 71641: // Echoes of Light (Althor's Abacus heroic version) - maxSize = 1; - power = POWER_HEALTH; - break; - case 54968: // Glyph of Holy Light - maxSize = m_spellInfo->MaxAffectedTargets; - power = POWER_HEALTH; - break; - case 57669: // Replenishment - // In arenas Replenishment may only affect the caster - if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->InArena()) - { - unitList.clear(); - unitList.push_back(m_caster); - break; - } - maxSize = 10; - power = POWER_MANA; - break; - default: - break; - } - break; - case SPELLFAMILY_PRIEST: - if (m_spellInfo->SpellFamilyFlags[0] == 0x10000000) // Circle of Healing - { - maxSize = m_caster->HasAura(55675) ? 6 : 5; // Glyph of Circle of Healing - power = POWER_HEALTH; - } - else if (m_spellInfo->Id == 64844) // Divine Hymn - { - maxSize = 3; - power = POWER_HEALTH; - } - else if (m_spellInfo->Id == 64904) // Hymn of Hope - { - maxSize = 3; - power = POWER_MANA; - } - else - break; - - // Remove targets outside caster's raid - for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();) - { - if (!(*itr)->IsInRaidWith(m_caster)) - itr = unitList.erase(itr); - else - ++itr; - } - break; - case SPELLFAMILY_DRUID: - if (m_spellInfo->SpellFamilyFlags[1] == 0x04000000) // Wild Growth - { - maxSize = m_caster->HasAura(62970) ? 6 : 5; // Glyph of Wild Growth - power = POWER_HEALTH; - } - else if (m_spellInfo->SpellFamilyFlags[2] == 0x0100) // Starfall - { - // Remove targets not in LoS or in stealth - for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();) - { - if ((*itr)->HasStealthAura() || (*itr)->HasInvisibilityAura() || !(*itr)->IsWithinLOSInMap(m_caster)) - itr = unitList.erase(itr); - else - ++itr; - } - break; - } - else - break; - - // Remove targets outside caster's raid - for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();) - if (!(*itr)->IsInRaidWith(m_caster)) - itr = unitList.erase(itr); - else - ++itr; - break; - default: - break; - } - - if (maxSize && power != -1) - { - if (Powers(power) == POWER_HEALTH) - { - if (unitList.size() > maxSize) - { - unitList.sort(Trinity::HealthPctOrderPred()); - unitList.resize(maxSize); - } - } - else - { - for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();) - if ((*itr)->getPowerType() != (Powers)power) - itr = unitList.erase(itr); - else - ++itr; - - if (unitList.size() > maxSize) - { - unitList.sort(Trinity::PowerPctOrderPred((Powers)power)); - unitList.resize(maxSize); - } - } - } - - // 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)->IsAffectingSpell(m_spellInfo)) - maxTargets += (*j)->GetAmount(); - - if (m_spellInfo->Id == 5246) //Intimidating Shout - unitList.remove(m_targets.GetUnitTarget()); - Trinity::RandomResizeList(unitList, maxTargets); - } - - CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i)); - - for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) - AddUnitTarget(*itr, effectMask, false); - } - - if (!gobjectList.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)->IsAffectingSpell(m_spellInfo)) - maxTargets += (*j)->GetAmount(); - - Trinity::RandomResizeList(gobjectList, maxTargets); - } - for (std::list<GameObject*>::iterator itr = gobjectList.begin(); itr != gobjectList.end(); ++itr) - AddGOTarget(*itr, effectMask); - } - } - - return effectMask; -} - void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura) { if (m_CastItem) @@ -2856,20 +2899,6 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered InitExplicitTargets(*targets); - if (Player* plrCaster = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself()) - { - //check for special spell conditions - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL, m_spellInfo->Id); - if (!conditions.empty()) - if (!sConditionMgr->IsPlayerMeetToConditions(plrCaster, conditions)) - { - //SendCastResult(SPELL_FAILED_DONT_REPORT); - SendCastResult(plrCaster, m_spellInfo, m_cast_count, SPELL_FAILED_DONT_REPORT); - finish(false); - return; - } - } - // Fill aura scaling information if (m_caster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING)) { @@ -3762,6 +3791,27 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas case SPELL_FAILED_SILENCED: data << uint32(0); // Unknown break; + case SPELL_FAILED_REAGENTS: + { + uint32 missingItem = 0; + for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++) + { + if (spellInfo->Reagent[i] <= 0) + continue; + + uint32 itemid = spellInfo->Reagent[i]; + uint32 itemcount = spellInfo->ReagentCount[i]; + + if (!caster->HasItemCount(itemid, itemcount)) + { + missingItem = itemid; + break; + } + } + + data << uint32(missingItem); // first missing item + break; + } default: break; } @@ -4617,7 +4667,7 @@ SpellCastResult Spell::CheckCast(bool strict) Unit::AuraEffectList const& blockSpells = m_caster->GetAuraEffectsByType(SPELL_AURA_BLOCK_SPELL_FAMILY); for (Unit::AuraEffectList::const_iterator blockItr = blockSpells.begin(); blockItr != blockSpells.end(); ++blockItr) - if ((*blockItr)->GetMiscValue() == m_spellInfo->SpellFamilyName) + if (uint32((*blockItr)->GetMiscValue()) == m_spellInfo->SpellFamilyName) return SPELL_FAILED_SPELL_UNAVAILABLE; bool reqCombat = true; @@ -4693,6 +4743,25 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_DONT_REPORT; } + // check spell cast conditions from database + { + ConditionSourceInfo condInfo = ConditionSourceInfo(m_caster); + condInfo.mConditionTargets[1] = m_targets.GetObjectTarget(); + ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL, m_spellInfo->Id); + if (!conditions.empty() && !sConditionMgr->IsObjectMeetToConditions(condInfo, conditions)) + { + // send error msg to player if condition failed and text message available + // TODO: using WorldSession::SendNotification is not blizzlike + if (Player* playerCaster = m_caster->ToPlayer()) + { + if (playerCaster->GetSession() && condInfo.mLastFailedCondition + && condInfo.mLastFailedCondition->ErrorTextId) + playerCaster->GetSession()->SendNotification(condInfo.mLastFailedCondition->ErrorTextId); + } + return SPELL_FAILED_DONT_REPORT; + } + } + // Don't check explicit target for passive spells (workaround) (check should be skipped only for learn case) // those spells may have incorrect target entries or not filled at all (for example 15332) // such spells when learned are not targeting anyone using targeting system, they should apply directly to caster instead @@ -4736,6 +4805,16 @@ SpellCastResult Spell::CheckCast(bool strict) } } + //Check for line of sight for spells with dest + if (m_targets.HasDst()) + { + float x, y, z; + m_targets.GetDst()->GetPosition(x, y, z); + + if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOS(x, y, z)) + return SPELL_FAILED_LINE_OF_SIGHT; + } + // check pet presence for (int j = 0; j < MAX_SPELL_EFFECTS; ++j) { @@ -5266,7 +5345,7 @@ SpellCastResult Spell::CheckCast(bool strict) { float x, y, z; m_caster->GetPosition(x, y, z); - float ground_Z = m_caster->GetMap()->GetHeight(x, y, z); + float ground_Z = m_caster->GetMap()->GetHeight(m_caster->GetPhaseMask(), x, y, z); if (fabs(ground_Z - z) < 0.1f) return SPELL_FAILED_DONT_REPORT; break; @@ -5368,6 +5447,9 @@ SpellCastResult Spell::CheckCast(bool strict) } case SPELL_AURA_PERIODIC_MANA_LEECH: { + if (m_spellInfo->Effects[i].IsTargetingArea()) + break; + if (!m_targets.GetUnitTarget()) return SPELL_FAILED_BAD_IMPLICIT_TARGETS; @@ -5871,7 +5953,7 @@ SpellCastResult Spell::CheckItems() } } if (!p_caster->HasItemCount(itemid, itemcount)) - return SPELL_FAILED_ITEM_NOT_READY; //0x54 + return SPELL_FAILED_REAGENTS; } } @@ -6554,7 +6636,7 @@ void Spell::HandleLaunchPhase() continue; // do not consume ammo anymore for Hunter's volley spell - if (IsTriggered() && m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellInfo->IsAOE()) + if (IsTriggered() && m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellInfo->IsTargetingArea()) usesAmmo = false; if (usesAmmo) @@ -6605,7 +6687,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) if (m_damage > 0) { - if (m_spellInfo->Effects[i].IsArea()) + if (m_spellInfo->Effects[i].IsTargetingArea()) { m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); if (m_caster->GetTypeId() == TYPEID_UNIT) @@ -6719,150 +6801,6 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value) } } -float tangent(float x) -{ - x = tan(x); - //if (x < std::numeric_limits<float>::max() && x > -std::numeric_limits<float>::max()) return x; - //if (x >= std::numeric_limits<float>::max()) return std::numeric_limits<float>::max(); - //if (x <= -std::numeric_limits<float>::max()) return -std::numeric_limits<float>::max(); - if (x < 100000.0f && x > -100000.0f) return x; - if (x >= 100000.0f) return 100000.0f; - if (x <= 100000.0f) return -100000.0f; - return 0.0f; -} - -#define DEBUG_TRAJ(a) //a - -void Spell::SelectTrajTargets() -{ - if (!m_targets.HasTraj()) - return; - - float dist2d = m_targets.GetDist2d(); - if (!dist2d) - return; - - float srcToDestDelta = m_targets.GetDst()->m_positionZ - m_targets.GetSrc()->m_positionZ; - - UnitList unitList; - SearchAreaTarget(unitList, dist2d, PUSH_IN_THIN_LINE, SPELL_TARGETS_ANY); - if (unitList.empty()) - return; - - unitList.sort(Trinity::ObjectDistanceOrderPred(m_caster)); - - float b = tangent(m_targets.GetElevation()); - float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d); - if (a > -0.0001f) - a = 0; - DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: a %f b %f", a, b);) - - float bestDist = m_spellInfo->GetMaxRange(false); - - UnitList::const_iterator itr = unitList.begin(); - for (; itr != unitList.end(); ++itr) - { - if (m_caster == *itr || m_caster->IsOnVehicle(*itr) || (*itr)->GetVehicle())//(*itr)->IsOnVehicle(m_caster)) - continue; - - const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3) - // TODO: all calculation should be based on src instead of m_caster - const float objDist2d = m_targets.GetSrc()->GetExactDist2d(*itr) * cos(m_targets.GetSrc()->GetRelativeAngle(*itr)); - const float dz = (*itr)->GetPositionZ() - m_targets.GetSrc()->m_positionZ; - - DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: check %u, dist between %f %f, height between %f %f.", (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size);) - - float dist = objDist2d - size; - float height = dist * (a * dist + b); - DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);) - if (dist < bestDist && height < dz + size && height > dz - size) - { - bestDist = dist > 0 ? dist : 0; - break; - } - -#define CHECK_DIST {\ - DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)\ - if (dist > bestDist)\ - continue;\ - if (dist < objDist2d + size && dist > objDist2d - size)\ - {\ - bestDist = dist;\ - break;\ - }\ - } - - if (!a) - { - height = dz - size; - dist = height / b; - CHECK_DIST; - - height = dz + size; - dist = height / b; - CHECK_DIST; - - continue; - } - - height = dz - size; - float sqrt1 = b * b + 4 * a * height; - if (sqrt1 > 0) - { - sqrt1 = sqrt(sqrt1); - dist = (sqrt1 - b) / (2 * a); - CHECK_DIST; - } - - height = dz + size; - float sqrt2 = b * b + 4 * a * height; - if (sqrt2 > 0) - { - sqrt2 = sqrt(sqrt2); - dist = (sqrt2 - b) / (2 * a); - CHECK_DIST; - - dist = (-sqrt2 - b) / (2 * a); - CHECK_DIST; - } - - if (sqrt1 > 0) - { - dist = (-sqrt1 - b) / (2 * a); - CHECK_DIST; - } - } - - if (m_targets.GetSrc()->GetExactDist2d(m_targets.GetDst()) > bestDist) - { - float x = m_targets.GetSrc()->m_positionX + cos(m_caster->GetOrientation()) * bestDist; - float y = m_targets.GetSrc()->m_positionY + sin(m_caster->GetOrientation()) * bestDist; - float z = m_targets.GetSrc()->m_positionZ + bestDist * (a * bestDist + b); - - if (itr != unitList.end()) - { - float distSq = (*itr)->GetExactDistSq(x, y, z); - float sizeSq = (*itr)->GetObjectSize(); - sizeSq *= sizeSq; - DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);) - if (distSq > sizeSq) - { - float factor = 1 - sqrt(sizeSq / distSq); - x += factor * ((*itr)->GetPositionX() - x); - y += factor * ((*itr)->GetPositionY() - y); - z += factor * ((*itr)->GetPositionZ() - z); - - distSq = (*itr)->GetExactDistSq(x, y, z); - DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);) - } - } - - Position trajDst; - trajDst.Relocate(x, y, z, m_caster->GetOrientation()); - m_targets.ModDst(trajDst); - } -} - void Spell::PrepareTargetProcessing() { CheckEffectExecuteData(); @@ -7214,3 +7152,152 @@ void Spell::CancelGlobalCooldown() else if (m_caster->GetTypeId() == TYPEID_PLAYER) m_caster->ToPlayer()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo); } + +namespace Trinity +{ + +WorldObjectSpellTargetCheck::WorldObjectSpellTargetCheck(Unit* caster, Unit* referer, SpellInfo const* spellInfo, + SpellTargetCheckTypes selectionType, ConditionList* condList) : _caster(caster), _referer(referer), _spellInfo(spellInfo), + _targetSelectionType(selectionType), _condList(condList) +{ + if (condList) + _condSrcInfo = new ConditionSourceInfo(NULL, caster); + else + _condSrcInfo = NULL; +} + +WorldObjectSpellTargetCheck::~WorldObjectSpellTargetCheck() +{ + if (_condSrcInfo) + delete _condSrcInfo; +} + +bool WorldObjectSpellTargetCheck::operator()(WorldObject* target) +{ + if (_spellInfo->CheckTarget(_caster, target, true) != SPELL_CAST_OK) + return false; + Unit* unitTarget = target->ToUnit(); + if (Corpse* corpseTarget = target->ToCorpse()) + { + // use ofter for party/assistance checks + if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID())) + unitTarget = owner; + else + return false; + } + if (unitTarget) + { + switch (_targetSelectionType) + { + case TARGET_CHECK_ENEMY: + if (unitTarget->isTotem()) + return false; + if (!_caster->_IsValidAttackTarget(unitTarget, _spellInfo)) + return false; + break; + case TARGET_CHECK_ALLY: + if (unitTarget->isTotem()) + return false; + if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo)) + return false; + break; + case TARGET_CHECK_PARTY: + if (unitTarget->isTotem()) + return false; + if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo)) + return false; + if (!_referer->IsInPartyWith(unitTarget)) + return false; + break; + case TARGET_CHECK_RAID_CLASS: + if (_referer->getClass() != unitTarget->getClass()) + return false; + // nobreak; + case TARGET_CHECK_RAID: + if (unitTarget->isTotem()) + return false; + if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo)) + return false; + if (!_referer->IsInRaidWith(unitTarget)) + return false; + break; + default: + break; + } + } + if (!_condSrcInfo) + return true; + _condSrcInfo->mConditionTargets[0] = target; + return sConditionMgr->IsObjectMeetToConditions(*_condSrcInfo, *_condList); +} + +WorldObjectSpellNearbyTargetCheck::WorldObjectSpellNearbyTargetCheck(float range, Unit* caster, SpellInfo const* spellInfo, + SpellTargetCheckTypes selectionType, ConditionList* condList) + : WorldObjectSpellTargetCheck(caster, caster, spellInfo, selectionType, condList), _range(range), _position(caster) +{ +} + +bool WorldObjectSpellNearbyTargetCheck::operator()(WorldObject* target) +{ + float dist = target->GetDistance(*_position); + if (dist < _range && WorldObjectSpellTargetCheck::operator ()(target)) + { + _range = dist; + return true; + } + return false; +} + +WorldObjectSpellAreaTargetCheck::WorldObjectSpellAreaTargetCheck(float range, Position const* position, Unit* caster, + Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList) + : WorldObjectSpellTargetCheck(caster, referer, spellInfo, selectionType, condList), _range(range), _position(position) +{ +} + +bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target) +{ + if (!target->IsWithinDist3d(_position, _range)) + return false; + return WorldObjectSpellTargetCheck::operator ()(target); +} + +WorldObjectSpellConeTargetCheck::WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit* caster, + SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList) + : WorldObjectSpellAreaTargetCheck(range, caster, caster, caster, spellInfo, selectionType, condList), _coneAngle(coneAngle) +{ +} + +bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target) +{ + if (_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_BACK) + { + if (!_caster->isInBack(target, _coneAngle)) + return false; + } + else if (_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_LINE) + { + if (!_caster->HasInLine(target, _caster->GetObjectSize())) + return false; + } + else + { + if (!_caster->isInFront(target, _coneAngle)) + return false; + } + return WorldObjectSpellAreaTargetCheck::operator ()(target); +} + +WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo) + : WorldObjectSpellAreaTargetCheck(range, position, caster, caster, spellInfo, TARGET_CHECK_DEFAULT, NULL) +{ +} + +bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target) +{ + // return all targets on missile trajectory (0 - size of a missile) + if (!_caster->HasInLine(target, 0)) + return false; + return WorldObjectSpellAreaTargetCheck::operator ()(target); +} + +} //namespace Trinity diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index dc3a95030ae..dd377d66feb 100755 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -79,19 +79,6 @@ enum SpellRangeFlag SPELL_RANGE_RANGED = 2, //hunter range and ranged weapon }; -enum SpellNotifyPushType -{ - PUSH_NONE = 0, - PUSH_IN_FRONT, - PUSH_IN_BACK, - PUSH_IN_LINE, - PUSH_IN_THIN_LINE, - PUSH_SRC_CENTER, - PUSH_DST_CENTER, - PUSH_CASTER_CENTER, //this is never used in grid search - PUSH_CHAIN, -}; - class SpellCastTargets { public: @@ -210,17 +197,6 @@ enum SpellEffectHandleMode SPELL_EFFECT_HANDLE_HIT_TARGET, }; -enum SpellTargets -{ - SPELL_TARGETS_NONE = 0, - SPELL_TARGETS_ALLY, - SPELL_TARGETS_ENEMY, - SPELL_TARGETS_ENTRY, - SPELL_TARGETS_CHAINHEAL, - SPELL_TARGETS_ANY, - SPELL_TARGETS_GO -}; - namespace Trinity { struct SpellNotifierCreatureAndPlayer; @@ -228,7 +204,6 @@ namespace Trinity class Spell { - friend struct Trinity::SpellNotifierCreatureAndPlayer; friend void Unit::SetCurrentCastedSpell(Spell* pSpell); friend class SpellScript; public: @@ -364,6 +339,32 @@ class Spell Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, uint64 originalCasterGUID = 0, bool skipCheck = false); ~Spell(); + void InitExplicitTargets(SpellCastTargets const& targets); + void SelectExplicitTargets(); + + void SelectSpellTargets(); + void SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask); + void SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); + void SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); + void SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); + void SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); + void SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); + void SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); + void SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); + void SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); + void SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); + void SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask); + void SelectImplicitTrajTargets(); + + void SelectEffectTypeImplicitTargets(uint8 effIndex); + + uint32 GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList); + template<class SEARCHER> void SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* referer, Position const* pos, float radius); + + WorldObject* SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList = NULL); + void SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList); + void SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionList* condList, bool isChainHeal); + void prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura = NULL); void cancel(); void update(uint32 difftime); @@ -403,14 +404,6 @@ class Spell void DoCreateItem(uint32 i, uint32 itemtype); void WriteSpellGoTargets(WorldPacket* data); - void InitExplicitTargets(SpellCastTargets const& targets); - void SelectSpellTargets(); - void SelectEffectTypeImplicitTargets(uint8 effIndex); - uint32 SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur); - void SelectTrajTargets(); - - template<typename T> WorldObject* FindCorpseUsing(); - bool CheckEffectTarget(Unit const* target, uint32 eff) const; bool CanAutoCast(Unit* target); void CheckSrc() { if (!m_targets.HasSrc()) m_targets.SetSrc(*m_caster); } @@ -605,10 +598,6 @@ class Spell void DoAllEffectOnTarget(GOTargetInfo* target); void DoAllEffectOnTarget(ItemTargetInfo* target); bool UpdateChanneledTargetList(); - void SearchAreaTarget(std::list<Unit*> &unitList, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry = 0); - void SearchGOAreaTarget(std::list<GameObject*> &gobjectList, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry = 0); - void SearchChainTarget(std::list<Unit*> &unitList, float radius, uint32 unMaxTargets, SpellTargets TargetType); - WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType, SpellEffIndex effIndex); bool IsValidDeadOrAliveTarget(Unit const* target) const; void HandleLaunchPhase(); void DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier); @@ -642,7 +631,7 @@ class Spell // effect helpers void GetSummonPosition(uint32 i, Position &pos, float radius = 0.0f, uint32 count = 0); - void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties); + void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numSummons); void CalculateJumpSpeeds(uint8 i, float dist, float & speedxy, float & speedz); SpellCastResult CanOpenLock(uint32 effIndex, uint32 lockid, SkillType& skillid, int32& reqSkillValue, int32& skillValue); @@ -674,98 +663,52 @@ class Spell namespace Trinity { - struct SpellNotifierCreatureAndPlayer + struct WorldObjectSpellTargetCheck { - std::list<Unit*> *i_data; - SpellNotifyPushType i_push_type; - float i_radius; - SpellTargets i_TargetType; - const Unit* const i_source; - uint32 i_entry; - const Position* const i_pos; - SpellInfo const* i_spellProto; - - SpellNotifierCreatureAndPlayer(Unit* source, std::list<Unit*> &data, float radius, SpellNotifyPushType type, - SpellTargets TargetType = SPELL_TARGETS_ENEMY, const Position* pos = NULL, uint32 entry = 0, SpellInfo const* spellProto = NULL) - : i_data(&data), i_push_type(type), i_radius(radius), i_TargetType(TargetType), - i_source(source), i_entry(entry), i_pos(pos), i_spellProto(spellProto) - { - ASSERT(i_source); - } + Unit* _caster; + Unit* _referer; + SpellInfo const* _spellInfo; + SpellTargetCheckTypes _targetSelectionType; + ConditionSourceInfo* _condSrcInfo; + ConditionList* _condList; + + WorldObjectSpellTargetCheck(Unit* caster, Unit* referer, SpellInfo const* spellInfo, + SpellTargetCheckTypes selectionType, ConditionList* condList); + ~WorldObjectSpellTargetCheck(); + bool operator()(WorldObject* target); + }; - template<class T> inline void Visit(GridRefManager<T>& m) - { - for (typename GridRefManager<T>::iterator itr = m.begin(); itr != m.end(); ++itr) - { - Unit* target = (Unit*)itr->getSource(); - - if (i_spellProto->CheckTarget(i_source, target, true) != SPELL_CAST_OK) - continue; - - switch (i_TargetType) - { - case SPELL_TARGETS_ENEMY: - if (target->isTotem()) - continue; - if (!i_source->_IsValidAttackTarget(target, i_spellProto)) - continue; - break; - case SPELL_TARGETS_ALLY: - if (target->isTotem()) - continue; - if (!i_source->_IsValidAssistTarget(target, i_spellProto)) - continue; - break; - case SPELL_TARGETS_ENTRY: - if (target->GetEntry()!= i_entry) - continue; - break; - case SPELL_TARGETS_ANY: - default: - break; - } - - switch (i_push_type) - { - case PUSH_SRC_CENTER: - case PUSH_DST_CENTER: - case PUSH_CHAIN: - default: - if (target->IsWithinDist3d(i_pos, i_radius)) - i_data->push_back(target); - break; - case PUSH_IN_FRONT: - if (i_source->isInFront(target, i_radius, static_cast<float>(M_PI/2))) - i_data->push_back(target); - break; - case PUSH_IN_BACK: - if (i_source->isInBack(target, i_radius, static_cast<float>(M_PI/2))) - i_data->push_back(target); - break; - case PUSH_IN_LINE: - if (i_source->HasInLine(target, i_radius, i_source->GetObjectSize())) - i_data->push_back(target); - break; - case PUSH_IN_THIN_LINE: // only traj - if (i_pos->HasInLine(target, i_radius, 0)) - i_data->push_back(target); - break; - } - } - } + struct WorldObjectSpellNearbyTargetCheck : public WorldObjectSpellTargetCheck + { + float _range; + Position const* _position; + WorldObjectSpellNearbyTargetCheck(float range, Unit* caster, SpellInfo const* spellInfo, + SpellTargetCheckTypes selectionType, ConditionList* condList); + bool operator()(WorldObject* target); + }; + + struct WorldObjectSpellAreaTargetCheck : public WorldObjectSpellTargetCheck + { + float _range; + Position const* _position; + WorldObjectSpellAreaTargetCheck(float range, Position const* position, Unit* caster, + Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList); + bool operator()(WorldObject* target); + }; - #ifdef _WIN32 - template<> inline void Visit(CorpseMapType &) {} - template<> inline void Visit(GameObjectMapType &) {} - template<> inline void Visit(DynamicObjectMapType &) {} - #endif + struct WorldObjectSpellConeTargetCheck : public WorldObjectSpellAreaTargetCheck + { + float _coneAngle; + WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit* caster, + SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList); + bool operator()(WorldObject* target); }; - #ifndef _WIN32 - template<> inline void SpellNotifierCreatureAndPlayer::Visit(CorpseMapType&) {} - template<> inline void SpellNotifierCreatureAndPlayer::Visit(GameObjectMapType&) {} - template<> inline void SpellNotifierCreatureAndPlayer::Visit(DynamicObjectMapType&) {} - #endif + struct WorldObjectSpellTrajTargetCheck : public WorldObjectSpellAreaTargetCheck + { + WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo); + bool operator()(WorldObject* target); + }; } typedef void(Spell::*pEffect)(SpellEffIndex effIndex); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 6ea53fcfd8b..271d4859c4c 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -764,600 +764,6 @@ void Spell::EffectDummy(SpellEffIndex effIndex) // selection by spell family switch (m_spellInfo->SpellFamilyName) { - case SPELLFAMILY_GENERIC: - { - switch (m_spellInfo->Id) - { - case 31225: // Shimmering Vessel (restore creature to life) - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) - return; - unitTarget->ToCreature()->setDeathState(JUST_ALIVED); - return; - } - case 12162: // Deep wounds - case 12850: // (now good common check for this spells) - case 12868: - { - if (!unitTarget) - return; - - // apply percent damage mods - damage = m_caster->SpellDamageBonus(unitTarget, m_spellInfo, damage, SPELL_DIRECT_DAMAGE); - - switch (m_spellInfo->Id) - { - case 12162: ApplyPctN(damage, 16); break; // Rank 1 - case 12850: ApplyPctN(damage, 32); break; // Rank 2 - case 12868: ApplyPctN(damage, 48); break; // Rank 3 - default: - sLog->outError("Spell::EffectDummy: Spell %u not handled in DW", m_spellInfo->Id); - return; - } - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(12721); - uint32 ticks = spellInfo->GetDuration() / spellInfo->Effects[EFFECT_0].Amplitude; - - // Add remaining ticks to damage done - if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(12721, EFFECT_0, m_caster->GetGUID())) - damage += aurEff->GetAmount() * (ticks - aurEff->GetTickNumber()); - - damage = damage / ticks; - m_caster->CastCustomSpell(unitTarget, 12721, &damage, NULL, NULL, true); - return; - } - case 13567: // Dummy Trigger - { - // can be used for different aura triggering, so select by aura - if (!m_triggeredByAuraSpell || !unitTarget) - return; - - switch (m_triggeredByAuraSpell->Id) - { - case 26467: // Persistent Shield - m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true); - break; - default: - sLog->outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u", m_triggeredByAuraSpell->Id); - break; - } - return; - } - case 17251: // Spirit Healer Res - { - if (!unitTarget || !m_originalCaster) - return; - - if (m_originalCaster->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8); - data << uint64(unitTarget->GetGUID()); - m_originalCaster->ToPlayer()->GetSession()->SendPacket(&data); - } - return; - } - case 23019: // Crystal Prison Dummy DND - { - if (!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || unitTarget->ToCreature()->isPet()) - return; - - Creature* creatureTarget = unitTarget->ToCreature(); - - m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, uint32(creatureTarget->GetRespawnTime()-time(NULL))); - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019"); - - creatureTarget->DespawnOrUnsummon(); - - return; - } - case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires - { - int32 r = irand(0, 119); - if (r < 20) // Transporter Malfunction - 1/6 polymorph - m_caster->CastSpell(m_caster, 23444, true); - else if (r < 100) // Evil Twin - 4/6 evil twin - m_caster->CastSpell(m_caster, 23445, true); - else // Transporter Malfunction - 1/6 miss the target - m_caster->CastSpell(m_caster, 36902, true); - return; - } - case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan - if (roll_chance_i(50)) // Gadgetzan Transporter - success - m_caster->CastSpell(m_caster, 23441, true); - else // Gadgetzan Transporter Failure - failure - m_caster->CastSpell(m_caster, 23446, true); - return; - case 25860: // Reindeer Transformation - { - if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED)) - return; - - float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT); - float speed = m_caster->GetSpeedRate(MOVE_RUN); - - m_caster->RemoveAurasByType(SPELL_AURA_MOUNTED); - - //5 different spells used depending on mounted speed and if mount can fly or not - if (flyspeed >= 4.1f) - // Flying Reindeer - m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer - else if (flyspeed >= 3.8f) - // Flying Reindeer - m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer - else if (flyspeed >= 1.6f) - // Flying Reindeer - m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer - else if (speed >= 2.0f) - // Reindeer - m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer - else - // Reindeer - m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer - - return; - } - case 26074: // Holiday Cheer - // implemented at client side - return; - // Polarity Shift - case 28089: - if (unitTarget) - unitTarget->CastSpell(unitTarget, roll_chance_i(50) ? 28059 : 28084, true, NULL, NULL, m_caster->GetGUID()); - break; - // Polarity Shift - case 39096: - if (unitTarget) - unitTarget->CastSpell(unitTarget, roll_chance_i(50) ? 39088 : 39091, true, NULL, NULL, m_caster->GetGUID()); - break; - case 29200: // Purify Helboar Meat - { - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - - spell_id = roll_chance_i(50) - ? 29277 // Summon Purified Helboar Meat - : 29278; // Summon Toxic Helboar Meat - - m_caster->CastSpell(m_caster, spell_id, true, NULL); - return; - } - case 29858: // Soulshatter - if (unitTarget && unitTarget->CanHaveThreatList() - && unitTarget->getThreatManager().getThreat(m_caster) > 0.0f) - m_caster->CastSpell(unitTarget, 32835, true); - return; - case 30458: // Nigh Invulnerability - if (!m_CastItem) return; - if (roll_chance_i(86)) // Nigh-Invulnerability - success - m_caster->CastSpell(m_caster, 30456, true, m_CastItem); - else // Complete Vulnerability - backfire in 14% casts - m_caster->CastSpell(m_caster, 30457, true, m_CastItem); - return; - case 30507: // Poultryizer - if (!m_CastItem) return; - if (roll_chance_i(80)) // Poultryized! - success - m_caster->CastSpell(unitTarget, 30501, true, m_CastItem); - else // Poultryized! - backfire 20% - m_caster->CastSpell(unitTarget, 30504, true, m_CastItem); - return; - case 35745: // Socrethar's Stone - { - switch (m_caster->GetAreaId()) - { - case 3900: - spell_id = 35743; - break; // Socrethar Portal - case 3742: - spell_id = 35744; - break; // Socrethar Portal - default: - return; - } - - m_caster->CastSpell(m_caster, spell_id, true); - return; - } - case 37674: // Chaos Blast - { - if (!unitTarget) - return; - - int32 basepoints0 = 100; - m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true); - return; - } - // Wrath of the Astromancer - case 42784: - { - uint32 count = 0; - for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) - if (ihit->effectMask & (1<<effIndex)) - ++count; - - damage = 12000; // maybe wrong value - damage /= count; - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(42784); - - // now deal the damage - for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) - if (ihit->effectMask & (1<<effIndex)) - { - if (Unit* casttarget = Unit::GetUnit((*unitTarget), ihit->targetGUID)) - m_caster->DealDamage(casttarget, damage, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, spellInfo, false); - } - - return; - } - // Demon Broiled Surprise - case 43723: - { - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - - Player* player = (Player*)m_caster; - - if (player && player->GetQuestStatus(11379) == QUEST_STATUS_INCOMPLETE) - { - Creature* creature = player->FindNearestCreature(19973, 10, false); - if (!creature) - { - SendCastResult(SPELL_FAILED_NOT_HERE); - return; - } - - player->CastSpell(player, 43753, false); - } - return; - } - case 44875: // Complete Raptor Capture - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) - return; - - unitTarget->ToCreature()->DespawnOrUnsummon(); - - //cast spell Raptor Capture Credit - m_caster->CastSpell(m_caster, 42337, true, NULL); - return; - } - case 47170: // Impale Leviroth - { - if (!unitTarget || (unitTarget->GetEntry() != 26452 && unitTarget->HealthAbovePct(95))) - return; - - m_caster->DealDamage(unitTarget, unitTarget->CountPctFromMaxHealth(93)); - return; - } - case 49357: // Brewfest Mount Transformation - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED)) - return; - m_caster->RemoveAurasByType(SPELL_AURA_MOUNTED); - // Ram for Alliance, Kodo for Horde - if (m_caster->ToPlayer()->GetTeam() == ALLIANCE) - { - if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f) - // 100% Ram - m_caster->CastSpell(m_caster, 43900, true); - else - // 60% Ram - m_caster->CastSpell(m_caster, 43899, true); - } - else - { - if (m_caster->ToPlayer()->GetSpeedRate(MOVE_RUN) >= 2.0f) - // 100% Kodo - m_caster->CastSpell(m_caster, 49379, true); - else - // 60% Kodo - m_caster->CastSpell(m_caster, 49378, true); - } - return; - case 52845: // Brewfest Mount Transformation (Faction Swap) - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED)) - return; - m_caster->RemoveAurasByType(SPELL_AURA_MOUNTED); - // Ram for Horde, Kodo for Alliance - if (m_caster->ToPlayer()->GetTeam() == HORDE) - { - if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f) - // 100% Ram - m_caster->CastSpell(m_caster, 43900, true); - else - // 60% Ram - m_caster->CastSpell(m_caster, 43899, true); - } - else - { - if (m_caster->ToPlayer()->GetSpeedRate(MOVE_RUN) >= 2.0f) - // 100% Kodo - m_caster->CastSpell(m_caster, 49379, true); - else - // 60% Kodo - m_caster->CastSpell(m_caster, 49378, true); - } - return; - case 55004: // Nitro Boosts - if (!m_CastItem) - return; - if (roll_chance_i(95)) // Nitro Boosts - success - m_caster->CastSpell(m_caster, 54861, true, m_CastItem); - else // Knocked Up - backfire 5% - m_caster->CastSpell(m_caster, 46014, true, m_CastItem); - return; - case 50243: // Teach Language - { - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - - // spell has a 1/3 chance to trigger one of the below - if (roll_chance_i(66)) - return; - if (m_caster->ToPlayer()->GetTeam() == ALLIANCE) - { - // 1000001 - gnomish binary - m_caster->CastSpell(m_caster, 50242, true); - } - else - { - // 01001000 - goblin binary - m_caster->CastSpell(m_caster, 50246, true); - } - - return; - } - case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite) - { - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - - if (Battleground* bg = m_caster->ToPlayer()->GetBattleground()) - bg->EventPlayerDroppedFlag(m_caster->ToPlayer()); - - m_caster->CastSpell(m_caster, 30452, true, NULL); - return; - } - case 52759: // Ancestral Awakening - if (!unitTarget) - return; - m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true); - return; - case 54171: // Divine Storm - { - if (m_UniqueTargetInfo.size()) - { - int32 heal = damage / m_UniqueTargetInfo.size(); - m_caster->CastCustomSpell(unitTarget, 54172, &heal, NULL, NULL, true); - } - return; - } - case 58418: // Portal to Orgrimmar - case 58420: // Portal to Stormwind - return; // implemented in EffectScript[0] - case 62324: // Throw Passenger - { - if (m_targets.HasTraj()) - { - if (Vehicle* vehicle = m_caster->GetVehicleKit()) - if (Unit* passenger = vehicle->GetPassenger(damage - 1)) - { - std::list<Unit*> unitList; - // use 99 because it is 3d search - SearchAreaTarget(unitList, 99, PUSH_DST_CENTER, SPELL_TARGETS_ENTRY, 33114); - float minDist = 99 * 99; - Unit* target = NULL; - for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) - { - if (Vehicle* seat = (*itr)->GetVehicleKit()) - if (!seat->GetPassenger(0)) - if (Unit* device = seat->GetPassenger(2)) - if (!device->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) - { - float dist = (*itr)->GetExactDistSq(m_targets.GetDst()); - if (dist < minDist) - { - minDist = dist; - target = (*itr); - } - } - } - if (target && target->IsWithinDist2d(m_targets.GetDst(), m_spellInfo->Effects[effIndex].CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct - passenger->EnterVehicle(target, 0); - else - { - passenger->ExitVehicle(); - float x, y, z; - m_targets.GetDst()->GetPosition(x, y, z); - passenger->GetMotionMaster()->MoveJump(x, y, z, m_targets.GetSpeedXY(), m_targets.GetSpeedZ()); - } - } - } - return; - } - case 64385: // Unusual Compass - { - m_caster->SetOrientation(float(urand(0, 62832)) / 10000.0f); - WorldPacket data; - m_caster->BuildHeartBeatMsg(&data); - m_caster->SendMessageToSet(&data, true); - return; - } - case 53808: // Pygmy Oil - { - Aura* pAura = m_caster->GetAura(53806); - if (pAura) - pAura->RefreshDuration(); - else - { - pAura = m_caster->GetAura(53805); - if (!pAura || pAura->GetStackAmount() < 5 || !roll_chance_i(50)) - m_caster->CastSpell(m_caster, 53805, true); - else - { - pAura->Remove(); - m_caster->CastSpell(m_caster, 53806, true); - } - } - return; - } - case 54577: // U.D.E.D. - { - if (unitTarget->GetEntry() != 29402) - return; - - m_caster->SummonGameObject(192693, unitTarget->GetPositionX(), unitTarget->GetPositionY(), - unitTarget->GetPositionZ(), unitTarget->GetOrientation(), 0, 0, 0, 0, 100); - - for (uint8 i = 0; i < 4; ++i) - m_caster->SummonGameObject(191567, float(unitTarget->GetPositionX() + irand(-7, 7)), - float(unitTarget->GetPositionY() + irand(-7, 7)), unitTarget->GetPositionZ(), unitTarget->GetOrientation(), - 0, 0, 0, 0, 100); - - unitTarget->Kill(unitTarget); - return; - } - case 51961: // Captured Chicken Cover - Quest 12702 & 12532 - { - if (m_caster->GetTypeId() != TYPEID_PLAYER - || !unitTarget->HasAura(51959) - || !(m_caster->ToPlayer()->GetQuestStatus(12702) == QUEST_STATUS_INCOMPLETE || m_caster->ToPlayer()->GetQuestStatus(12532) == QUEST_STATUS_INCOMPLETE)) - return; - - m_caster->CastSpell(m_caster, 51037, true); - unitTarget->Kill(unitTarget); - return; - } - } - - break; - } - case SPELLFAMILY_WARRIOR: - // Charge - if (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_WARRIOR_CHARGE && m_spellInfo->SpellVisual[0] == 867) - { - int32 chargeBasePoints0 = damage; - m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true); - - //Juggernaut crit bonus - if (m_caster->HasAura(64976)) - m_caster->CastSpell(m_caster, 65156, true); - return; - } - // Slam - if (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_WARRIOR_SLAM && m_spellInfo->SpellIconID == 559) - { - int32 bp0 = damage; - m_caster->CastCustomSpell(unitTarget, 50783, &bp0, NULL, NULL, true, 0); - return; - } - // Execute - if (m_spellInfo->SpellFamilyFlags[EFFECT_0] & SPELLFAMILYFLAG_WARRIOR_EXECUTE) - { - if (!unitTarget) - return; - - spell_id = 20647; - - int32 rageUsed = std::min<int32>(300 - m_powerCost, m_caster->GetPower(POWER_RAGE)); - int32 newRage = std::max<int32>(0, m_caster->GetPower(POWER_RAGE) - rageUsed); - - // Sudden Death rage save - if (AuraEffect* aurEff = m_caster->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_GENERIC, 1989, EFFECT_0)) - { - int32 ragesave = aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue() * 10; - newRage = std::max(newRage, ragesave); - } - - m_caster->SetPower(POWER_RAGE, uint32(newRage)); - - // Glyph of Execution bonus - if (AuraEffect* aurEff = m_caster->GetAuraEffect(58367, EFFECT_0)) - rageUsed += aurEff->GetAmount() * 10; - - bp = damage + int32(rageUsed * m_spellInfo->Effects[effIndex].DamageMultiplier + m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.2f); - break; - } - // Concussion Blow - if (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_WARRIOR_CONCUSSION_BLOW) - { - m_damage += CalculatePctF(damage, m_caster->GetTotalAttackPowerValue(BASE_ATTACK)); - return; - } - switch (m_spellInfo->Id) - { - // Bloodthirst - case 23881: - { - m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL); - return; - } - } - break; - case SPELLFAMILY_WARLOCK: - // Life Tap - if ((m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_WARLOCK_LIFETAP) && m_caster->ToPlayer()) - { - float spFactor = 0.0f; - switch (m_spellInfo->Id) - { - case 11689: spFactor = 0.2f; break; - case 27222: - case 57946: spFactor = 0.5f; break; - } - int32 damage = int32(m_spellInfo->Effects[EFFECT_0].CalcValue() + (6.3875 * m_spellInfo->BaseLevel)); - int32 mana = int32(damage + (m_caster->ToPlayer()->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+SPELL_SCHOOL_SHADOW) * spFactor)); - - if (unitTarget && (int32(unitTarget->GetHealth()) > damage)) - { - // Shouldn't Appear in Combat Log - unitTarget->ModifyHealth(-damage); - - // Improved Life Tap mod - if (AuraEffect const* aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, 208, 0)) - AddPctN(mana, aurEff->GetAmount()); - - m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, false); - - // Mana Feed - int32 manaFeedVal = 0; - if (AuraEffect const* aurEff = m_caster->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARLOCK, 1982, 0)) - manaFeedVal = aurEff->GetAmount(); - - if (manaFeedVal > 0) - { - ApplyPctN(manaFeedVal, mana); - m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL); - } - } - else - SendCastResult(SPELL_FAILED_FIZZLE); - return; - } - break; - case SPELLFAMILY_DRUID: - // Starfall - if (m_spellInfo->SpellFamilyFlags[2] & SPELLFAMILYFLAG2_DRUID_STARFALL) - { - //Shapeshifting into an animal form or mounting cancels the effect. - if (m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted()) - { - if (m_triggeredByAuraSpell) - m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id); - return; - } - - //Any effect which causes you to lose control of your character will supress the starfall effect. - if (m_caster->HasUnitState(UNIT_STATE_CONTROLLED)) - return; - - m_caster->CastSpell(unitTarget, damage, true); - return; - } - break; case SPELLFAMILY_PALADIN: switch (m_spellInfo->Id) { @@ -1391,128 +797,40 @@ void Spell::EffectDummy(SpellEffIndex effIndex) } } break; - case SPELLFAMILY_SHAMAN: - // Cleansing Totem Pulse - if (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_SHAMAN_TOTEM_EFFECTS && m_spellInfo->SpellIconID == 1673) - { - int32 bp1 = 1; - // Cleansing Totem Effect - if (unitTarget) - m_caster->CastCustomSpell(unitTarget, 52025, NULL, &bp1, NULL, true, NULL, NULL, m_originalCasterGUID); - return; - } - // Healing Stream Totem - if (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_SHAMAN_HEALING_STREAM) - { - if (!unitTarget) - return; - if (Unit* owner = m_caster->GetOwner()) - { - if (m_triggeredByAuraSpell) - damage = int32(owner->SpellHealingBonus(unitTarget, m_triggeredByAuraSpell, damage, HEAL)); - - // Restorative Totems - if (AuraEffect* dummy = owner->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 338, 1)) - AddPctN(damage, dummy->GetAmount()); - - // Glyph of Healing Stream Totem - if (AuraEffect const* aurEff = owner->GetAuraEffect(55456, EFFECT_0)) - AddPctN(damage, aurEff->GetAmount()); - } - m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID); - return; - } - // Mana Spring Totem - if (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_SHAMAN_MANA_SPRING) - { - if (!unitTarget || unitTarget->getPowerType() != POWER_MANA) - return; - m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID); - return; - } - // Lava Lash - if (m_spellInfo->SpellFamilyFlags[2] & SPELLFAMILYFLAG2_SHAMAN_LAVA_LASH) - { - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - - if (m_caster->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) - { - // Damage is increased by 25% if your off-hand weapon is enchanted with Flametongue. - if (m_caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0x200000, 0, 0)) - AddPctN(m_damage, damage); - } - return; - } - break; case SPELLFAMILY_DEATHKNIGHT: - // Death strike - if (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_DK_DEATH_STRIKE) - { - uint32 count = unitTarget->GetDiseasesByCaster(m_caster->GetGUID()); - bp = int32(count * m_caster->CountPctFromMaxHealth(int32(m_spellInfo->Effects[EFFECT_0].DamageMultiplier))); - // Improved Death Strike - if (AuraEffect const* aurEff = m_caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_DEATHKNIGHT, 2751, 0)) - AddPctN(bp, m_caster->CalculateSpellDamage(m_caster, aurEff->GetSpellInfo(), 2)); - m_caster->CastCustomSpell(m_caster, 45470, &bp, NULL, NULL, false); - return; - } - // Death Coil - if (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_DK_DEATH_COIL) - { - if (m_caster->IsFriendlyTo(unitTarget)) - { - bp = int32(damage * 1.5f); - m_caster->CastCustomSpell(unitTarget, 47633, &bp, NULL, NULL, true); - } - else - { - bp = damage; - m_caster->CastCustomSpell(unitTarget, 47632, &bp, NULL, NULL, true); - } - return; - } switch (m_spellInfo->Id) { - case 49560: // Death Grip - Position pos; - GetSummonPosition(effIndex, pos); - if (Unit* unit = unitTarget->GetVehicleBase()) // what is this for? - unit->CastSpell(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), damage, true); - else if (!unitTarget->HasAuraType(SPELL_AURA_DEFLECT_SPELLS)) // Deterrence - unitTarget->CastSpell(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), damage, true); - return; - case 46584: // Raise Dead - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; + case 46584: // Raise Dead + if (m_caster->GetTypeId() != TYPEID_PLAYER) + return; - // Do we have talent Master of Ghouls? - if (m_caster->HasAura(52143)) - // summon as pet - bp = 52150; - else - // or guardian - bp = 46585; + // Do we have talent Master of Ghouls? + if (m_caster->HasAura(52143)) + // summon as pet + bp = 52150; + else + // or guardian + bp = 46585; - if (m_targets.HasDst()) - targets.SetDst(*m_targets.GetDst()); - else - { - targets.SetDst(*m_caster); - // Corpse not found - take reagents (only not triggered cast can take them) - triggered = false; - } - // Remove cooldown - summon spellls have category - m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true); - spell_id = 48289; - break; - // Raise dead - take reagents and trigger summon spells - case 48289: - if (m_targets.HasDst()) - targets.SetDst(*m_targets.GetDst()); + if (m_targets.HasDst()) + targets.SetDst(*m_targets.GetDst()); + else + { + targets.SetDst(*m_caster); + // Corpse not found - take reagents (only not triggered cast can take them) + triggered = false; + } + // Remove cooldown - summon spellls have category + m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true); + spell_id = 48289; + break; + // Raise dead - take reagents and trigger summon spells + case 48289: + if (m_targets.HasDst()) + targets.SetDst(*m_targets.GetDst()); - spell_id = CalculateDamage(0, NULL); - break; + spell_id = CalculateDamage(0, NULL); + break; } break; } @@ -3057,6 +2375,36 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) TempSummon* summon = NULL; + // determine how many units should be summoned + uint32 numSummons; + + // some spells need to summon many units, for those spells number of summons is stored in effect value + // however so far noone found a generic check to find all of those (there's no related data in summonproperties.dbc + // and in spell attributes, possibly we need to add a table for those) + // so here's a list of MiscValueB values, which is currently most generic check + switch (properties->Id) + { + case 64: + case 61: + case 1101: + case 66: + case 648: + case 2301: + case 1061: + case 1261: + case 629: + case 181: + case 715: + case 1562: + case 833: + case 1161: + numSummons = (damage > 0) ? damage : 1; + break; + default: + numSummons = 1; + break; + } + switch (properties->Category) { case SUMMON_CATEGORY_WILD: @@ -3064,7 +2412,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) case SUMMON_CATEGORY_UNK: if (properties->Flags & 512) { - SummonGuardian(effIndex, entry, properties); + SummonGuardian(effIndex, entry, properties, numSummons); break; } switch (properties->Type) @@ -3073,7 +2421,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) case SUMMON_TYPE_GUARDIAN: case SUMMON_TYPE_GUARDIAN2: case SUMMON_TYPE_MINION: - SummonGuardian(effIndex, entry, properties); + SummonGuardian(effIndex, entry, properties, numSummons); break; // Summons a vehicle, but doesn't force anyone to enter it (see SUMMON_CATEGORY_VEHICLE) case SUMMON_TYPE_VEHICLE: @@ -3106,7 +2454,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) summon->SelectLevel(summon->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp summon->SetUInt32Value(UNIT_NPC_FLAGS, summon->GetCreatureInfo()->npcflag); - summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE); + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); summon->AI()->EnterEvadeMode(); break; @@ -3115,14 +2463,9 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) { float radius = m_spellInfo->Effects[effIndex].CalcRadius(); - uint32 amount = damage > 0 ? damage : 1; - if (m_spellInfo->Id == 18662 || // Curse of Doom - properties->Id == 2081) // Mechanical Dragonling, Arcanite Dragonling, Mithril Dragonling TODO: Research on meaning of basepoints - amount = 1; - TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN; - for (uint32 count = 0; count < amount; ++count) + for (uint32 count = 0; count < numSummons; ++count) { GetSummonPosition(effIndex, pos, radius, count); @@ -3144,7 +2487,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) }//switch break; case SUMMON_CATEGORY_PET: - SummonGuardian(effIndex, entry, properties); + SummonGuardian(effIndex, entry, properties, numSummons); break; case SUMMON_CATEGORY_PUPPET: summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_originalCaster, m_spellInfo->Id); @@ -3330,7 +2673,7 @@ void Spell::EffectDispel(SpellEffIndex effIndex) // Send dispelled spell info dataSuccess << uint32(itr->first->GetId()); // Spell Id dataSuccess << uint8(0); // 0 - dispelled !=0 cleansed - unitTarget->RemoveAurasDueToSpellByDispel(itr->first->GetId(), itr->first->GetCasterGUID(), m_caster, itr->second); + unitTarget->RemoveAurasDueToSpellByDispel(itr->first->GetId(), m_spellInfo->Id, itr->first->GetCasterGUID(), m_caster, itr->second); } m_caster->SendMessageToSet(&dataSuccess, true); @@ -3795,7 +3138,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex) { SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(67); if (properties) - SummonGuardian(effIndex, petentry, properties); + SummonGuardian(effIndex, petentry, properties, 1); return; } @@ -5601,7 +4944,7 @@ void Spell::EffectStuck(SpellEffIndex /*effIndex*/) if (target->isInFlight()) return; - target->TeleportTo(target->GetStartPosition(), m_caster == m_caster ? TELE_TO_SPELL : 0); + target->TeleportTo(target->GetStartPosition(), TELE_TO_SPELL); // homebind location is loaded always // target->TeleportTo(target->m_homebindMapId, target->m_homebindX, target->m_homebindY, target->m_homebindZ, target->GetOrientation(), (m_caster == m_caster ? TELE_TO_SPELL : 0)); @@ -5627,7 +4970,7 @@ void Spell::EffectSummonPlayer(SpellEffIndex /*effIndex*/) return; float x, y, z; - m_caster->GetClosePoint(x, y, z, unitTarget->GetObjectSize()); + m_caster->GetPosition(x, y, z); unitTarget->ToPlayer()->SetSummonPoint(m_caster->GetMapId(), x, y, z); @@ -6016,7 +5359,10 @@ void Spell::EffectLeap(SpellEffIndex /*effIndex*/) if (!m_targets.HasDst()) return; - unitTarget->NearTeleportTo(m_targets.GetDst()->GetPositionX(), m_targets.GetDst()->GetPositionY(), m_targets.GetDst()->GetPositionZ(), m_targets.GetDst()->GetOrientation(), unitTarget == m_caster); + Position pos; + m_targets.GetDst()->GetPosition(&pos); + unitTarget->GetFirstCollisionPosition(pos, unitTarget->GetDistance(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() + 2.0f), 0.0f); + unitTarget->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), unitTarget == m_caster); } void Spell::EffectReputation(SpellEffIndex effIndex) @@ -7062,7 +6408,7 @@ void Spell::EffectGameObjectSetDestructionState(SpellEffIndex effIndex) gameObjTarget->SetDestructibleState(GameObjectDestructibleState(m_spellInfo->Effects[effIndex].MiscValue), player, true); } -void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties) +void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numGuardians) { Unit* caster = m_originalCaster; if (!caster) @@ -7081,27 +6427,16 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* if (uint16 skill202 = caster->ToPlayer()->GetSkillValue(SKILL_ENGINEERING)) level = skill202 / 5; - //float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); float radius = 5.0f; - uint32 amount = damage > 0 ? damage : 1; int32 duration = m_spellInfo->GetDuration(); - switch (m_spellInfo->Id) - { - case 1122: // Inferno - amount = 1; - break; - case 49028: // Dancing Rune Weapon - if (AuraEffect* aurEff = m_originalCaster->GetAuraEffect(63330, 0)) // glyph of Dancing Rune Weapon - duration += aurEff->GetAmount(); - break; - } + if (Player* modOwner = m_originalCaster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration); //TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN; Map* map = caster->GetMap(); - for (uint32 count = 0; count < amount; ++count) + for (uint32 count = 0; count < numGuardians; ++count) { Position pos; GetSummonPosition(i, pos, radius, count); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 718efaed411..8b8f1fb5afc 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -20,6 +20,7 @@ #include "SpellMgr.h" #include "Spell.h" #include "DBCStores.h" +#include "ConditionMgr.h" uint32 GetTargetFlagMask(SpellTargetObjectTypes objType) { @@ -80,7 +81,7 @@ SpellTargetObjectTypes SpellImplicitTargetInfo::GetObjectType() const return _data[_target].ObjectType; } -SpellTargetSelectionCheckTypes SpellImplicitTargetInfo::GetSelectionCheckType() const +SpellTargetCheckTypes SpellImplicitTargetInfo::GetCheckType() const { return _data[_target].SelectionCheckType; } @@ -158,23 +159,25 @@ uint32 SpellImplicitTargetInfo::GetExplicitTargetMask(bool& srcSet, bool& dstSet case TARGET_OBJECT_TYPE_UNIT_AND_DEST: case TARGET_OBJECT_TYPE_UNIT: case TARGET_OBJECT_TYPE_DEST: - switch (GetSelectionCheckType()) + switch (GetCheckType()) { - case TARGET_SELECT_CHECK_ENEMY: + case TARGET_CHECK_ENEMY: targetMask = TARGET_FLAG_UNIT_ENEMY; break; - case TARGET_SELECT_CHECK_ALLY: + case TARGET_CHECK_ALLY: targetMask = TARGET_FLAG_UNIT_ALLY; break; - case TARGET_SELECT_CHECK_PARTY: + case TARGET_CHECK_PARTY: targetMask = TARGET_FLAG_UNIT_PARTY; break; - case TARGET_SELECT_CHECK_RAID: + case TARGET_CHECK_RAID: targetMask = TARGET_FLAG_UNIT_RAID; break; - case TARGET_SELECT_CHECK_PASSENGER: + case TARGET_CHECK_PASSENGER: targetMask = TARGET_FLAG_UNIT_PASSENGER; break; + case TARGET_CHECK_RAID_CLASS: + // nobreak; default: targetMask = TARGET_FLAG_UNIT; break; @@ -344,117 +347,117 @@ SpellSelectTargetTypes SpellImplicitTargetInfo::Type[TOTAL_SPELL_TARGETS]; SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_TARGETS] = { - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 1 TARGET_UNIT_CASTER - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 2 TARGET_UNIT_NEARBY_ENEMY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 3 TARGET_UNIT_NEARBY_PARTY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 4 TARGET_UNIT_NEARBY_ALLY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 5 TARGET_UNIT_PET - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 6 TARGET_UNIT_TARGET_ENEMY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 7 TARGET_UNIT_SRC_AREA_ENTRY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 8 TARGET_UNIT_DEST_AREA_ENTRY - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 9 TARGET_DEST_HOME - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 10 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 11 TARGET_UNIT_SRC_AREA_UNK_11 - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 12 - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 13 - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 14 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 15 TARGET_UNIT_SRC_AREA_ENEMY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 16 TARGET_UNIT_DEST_AREA_ENEMY - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 17 TARGET_DEST_DB - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 18 TARGET_DEST_CASTER - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 19 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 20 TARGET_UNIT_CASTER_AREA_PARTY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 21 TARGET_UNIT_TARGET_ALLY - {TARGET_OBJECT_TYPE_SRC, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 22 TARGET_SRC_CASTER - {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 23 TARGET_GAMEOBJECT_TARGET - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_FRONT}, // 24 TARGET_UNIT_CONE_ENEMY_24 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 25 TARGET_UNIT_TARGET_ANY - {TARGET_OBJECT_TYPE_GOBJ_ITEM, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 26 TARGET_GAMEOBJECT_ITEM_TARGET - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 27 TARGET_UNIT_MASTER - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 28 TARGET_DEST_DYNOBJ_ENEMY - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 29 TARGET_DEST_DYNOBJ_ALLY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 30 TARGET_UNIT_SRC_AREA_ALLY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 31 TARGET_UNIT_DEST_AREA_ALLY - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 32 TARGET_DEST_CASTER_SUMMON - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 33 TARGET_UNIT_SRC_AREA_PARTY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 34 TARGET_UNIT_DEST_AREA_PARTY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 35 TARGET_UNIT_TARGET_PARTY - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 36 TARGET_DEST_CASTER_UNK_36 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_LAST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 37 TARGET_UNIT_LASTTARGET_AREA_PARTY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 38 TARGET_UNIT_NEARBY_ENTRY - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 39 TARGET_DEST_CASTER_FISHING - {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 40 TARGET_GAMEOBJECT_NEARBY_ENTRY - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 41 TARGET_DEST_CASTER_FRONT_RIGHT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 42 TARGET_DEST_CASTER_BACK_RIGHT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 43 TARGET_DEST_CASTER_BACK_LEFT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 44 TARGET_DEST_CASTER_FRONT_LEFT - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 45 TARGET_UNIT_TARGET_CHAINHEAL_ALLY - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 46 TARGET_DEST_NEARBY_ENTRY - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 47 TARGET_DEST_CASTER_FRONT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK}, // 48 TARGET_DEST_CASTER_BACK - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 49 TARGET_DEST_CASTER_RIGHT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 50 TARGET_DEST_CASTER_LEFT - {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 51 TARGET_GAMEOBJECT_SRC_AREA - {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 52 TARGET_GAMEOBJECT_DEST_AREA - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 53 TARGET_DEST_TARGET_ENEMY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_FRONT}, // 54 TARGET_UNIT_CONE_ENEMY_54 - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 55 TARGET_DEST_CASTER_FRONT_LEAP - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 56 TARGET_UNIT_CASTER_AREA_RAID - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 57 TARGET_UNIT_TARGET_RAID - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 58 TARGET_UNIT_NEARBY_RAID - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_FRONT}, // 59 TARGET_UNIT_CONE_ALLY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_FRONT}, // 60 TARGET_UNIT_CONE_ENTRY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 61 TARGET_UNIT_TARGET_AREA_RAID_CLASS - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 62 TARGET_UNK_62 - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 63 TARGET_DEST_TARGET_ANY - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 64 TARGET_DEST_TARGET_FRONT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK}, // 65 TARGET_DEST_TARGET_BACK - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 66 TARGET_DEST_TARGET_RIGHT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 67 TARGET_DEST_TARGET_LEFT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 68 TARGET_DEST_TARGET_FRONT_RIGHT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 69 TARGET_DEST_TARGET_BACK_RIGHT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 70 TARGET_DEST_TARGET_BACK_LEFT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 71 TARGET_DEST_TARGET_FRONT_LEFT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 72 TARGET_DEST_CASTER_RANDOM - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 73 TARGET_DEST_CASTER_RADIUS - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 74 TARGET_DEST_TARGET_RANDOM - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 75 TARGET_DEST_TARGET_RADIUS - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 76 TARGET_DEST_CHANNEL_TARGET - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 77 TARGET_UNIT_CHANNEL_TARGET - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 78 TARGET_DEST_DEST_FRONT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK}, // 79 TARGET_DEST_DEST_BACK - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 80 TARGET_DEST_DEST_RIGHT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 81 TARGET_DEST_DEST_LEFT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 82 TARGET_DEST_DEST_FRONT_RIGHT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 83 TARGET_DEST_DEST_BACK_RIGHT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 84 TARGET_DEST_DEST_BACK_LEFT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 85 TARGET_DEST_DEST_FRONT_LEFT - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 86 TARGET_DEST_DEST_RANDOM - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 87 TARGET_DEST_DEST - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 88 TARGET_DEST_DYNOBJ_NONE - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 89 TARGET_DEST_TRAJ - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 90 TARGET_UNIT_TARGET_MINIPET - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 91 TARGET_DEST_DEST_RADIUS - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 92 TARGET_UNIT_SUMMONER - {TARGET_OBJECT_TYPE_CORPSE, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 93 TARGET_CORPSE_SRC_AREA_ENEMY - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 94 TARGET_UNIT_VEHICLE - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_PASSENGER, TARGET_DIR_NONE}, // 95 TARGET_UNIT_TARGET_PASSENGER - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 96 TARGET_UNIT_PASSENGER_0 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 97 TARGET_UNIT_PASSENGER_1 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 98 TARGET_UNIT_PASSENGER_2 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 99 TARGET_UNIT_PASSENGER_3 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 100 TARGET_UNIT_PASSENGER_4 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 101 TARGET_UNIT_PASSENGER_5 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 102 TARGET_UNIT_PASSENGER_6 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 103 TARGET_UNIT_PASSENGER_7 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_FRONT}, // 104 TARGET_UNIT_CONE_ENEMY_104 - {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 105 TARGET_UNIT_UNK_105 - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 106 TARGET_DEST_CHANNEL_CASTER - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 107 TARGET_UNK_DEST_AREA_UNK_107 - {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 108 TARGET_GAMEOBJECT_CONE - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 109 - {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 110 TARGET_DEST_UNK_110 + {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 1 TARGET_UNIT_CASTER + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 2 TARGET_UNIT_NEARBY_ENEMY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 3 TARGET_UNIT_NEARBY_PARTY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 4 TARGET_UNIT_NEARBY_ALLY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 5 TARGET_UNIT_PET + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 6 TARGET_UNIT_TARGET_ENEMY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 7 TARGET_UNIT_SRC_AREA_ENTRY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 8 TARGET_UNIT_DEST_AREA_ENTRY + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 9 TARGET_DEST_HOME + {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 10 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 11 TARGET_UNIT_SRC_AREA_UNK_11 + {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 12 + {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 13 + {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 14 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 15 TARGET_UNIT_SRC_AREA_ENEMY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 16 TARGET_UNIT_DEST_AREA_ENEMY + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 17 TARGET_DEST_DB + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 18 TARGET_DEST_CASTER + {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 19 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 20 TARGET_UNIT_CASTER_AREA_PARTY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 21 TARGET_UNIT_TARGET_ALLY + {TARGET_OBJECT_TYPE_SRC, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 22 TARGET_SRC_CASTER + {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 23 TARGET_GAMEOBJECT_TARGET + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENEMY, TARGET_DIR_FRONT}, // 24 TARGET_UNIT_CONE_ENEMY_24 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 25 TARGET_UNIT_TARGET_ANY + {TARGET_OBJECT_TYPE_GOBJ_ITEM, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 26 TARGET_GAMEOBJECT_ITEM_TARGET + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 27 TARGET_UNIT_MASTER + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 28 TARGET_DEST_DYNOBJ_ENEMY + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 29 TARGET_DEST_DYNOBJ_ALLY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 30 TARGET_UNIT_SRC_AREA_ALLY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 31 TARGET_UNIT_DEST_AREA_ALLY + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 32 TARGET_DEST_CASTER_SUMMON + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 33 TARGET_UNIT_SRC_AREA_PARTY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 34 TARGET_UNIT_DEST_AREA_PARTY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 35 TARGET_UNIT_TARGET_PARTY + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 36 TARGET_DEST_CASTER_UNK_36 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_LAST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 37 TARGET_UNIT_LASTTARGET_AREA_PARTY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 38 TARGET_UNIT_NEARBY_ENTRY + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 39 TARGET_DEST_CASTER_FISHING + {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 40 TARGET_GAMEOBJECT_NEARBY_ENTRY + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 41 TARGET_DEST_CASTER_FRONT_RIGHT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 42 TARGET_DEST_CASTER_BACK_RIGHT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 43 TARGET_DEST_CASTER_BACK_LEFT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 44 TARGET_DEST_CASTER_FRONT_LEFT + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 45 TARGET_UNIT_TARGET_CHAINHEAL_ALLY + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 46 TARGET_DEST_NEARBY_ENTRY + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 47 TARGET_DEST_CASTER_FRONT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK}, // 48 TARGET_DEST_CASTER_BACK + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 49 TARGET_DEST_CASTER_RIGHT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 50 TARGET_DEST_CASTER_LEFT + {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 51 TARGET_GAMEOBJECT_SRC_AREA + {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 52 TARGET_GAMEOBJECT_DEST_AREA + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 53 TARGET_DEST_TARGET_ENEMY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENEMY, TARGET_DIR_FRONT}, // 54 TARGET_UNIT_CONE_ENEMY_54 + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 55 TARGET_DEST_CASTER_FRONT_LEAP + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 56 TARGET_UNIT_CASTER_AREA_RAID + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 57 TARGET_UNIT_TARGET_RAID + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 58 TARGET_UNIT_NEARBY_RAID + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ALLY, TARGET_DIR_FRONT}, // 59 TARGET_UNIT_CONE_ALLY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENTRY, TARGET_DIR_FRONT}, // 60 TARGET_UNIT_CONE_ENTRY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_RAID_CLASS,TARGET_DIR_NONE}, // 61 TARGET_UNIT_TARGET_AREA_RAID_CLASS + {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 62 TARGET_UNK_62 + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 63 TARGET_DEST_TARGET_ANY + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 64 TARGET_DEST_TARGET_FRONT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK}, // 65 TARGET_DEST_TARGET_BACK + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 66 TARGET_DEST_TARGET_RIGHT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 67 TARGET_DEST_TARGET_LEFT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 68 TARGET_DEST_TARGET_FRONT_RIGHT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 69 TARGET_DEST_TARGET_BACK_RIGHT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 70 TARGET_DEST_TARGET_BACK_LEFT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 71 TARGET_DEST_TARGET_FRONT_LEFT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 72 TARGET_DEST_CASTER_RANDOM + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 73 TARGET_DEST_CASTER_RADIUS + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 74 TARGET_DEST_TARGET_RANDOM + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 75 TARGET_DEST_TARGET_RADIUS + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 76 TARGET_DEST_CHANNEL_TARGET + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 77 TARGET_UNIT_CHANNEL_TARGET + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 78 TARGET_DEST_DEST_FRONT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK}, // 79 TARGET_DEST_DEST_BACK + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 80 TARGET_DEST_DEST_RIGHT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 81 TARGET_DEST_DEST_LEFT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 82 TARGET_DEST_DEST_FRONT_RIGHT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 83 TARGET_DEST_DEST_BACK_RIGHT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 84 TARGET_DEST_DEST_BACK_LEFT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 85 TARGET_DEST_DEST_FRONT_LEFT + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 86 TARGET_DEST_DEST_RANDOM + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 87 TARGET_DEST_DEST + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 88 TARGET_DEST_DYNOBJ_NONE + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 89 TARGET_DEST_TRAJ + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 90 TARGET_UNIT_TARGET_MINIPET + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 91 TARGET_DEST_DEST_RADIUS + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 92 TARGET_UNIT_SUMMONER + {TARGET_OBJECT_TYPE_CORPSE, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 93 TARGET_CORPSE_SRC_AREA_ENEMY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 94 TARGET_UNIT_VEHICLE + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_PASSENGER, TARGET_DIR_NONE}, // 95 TARGET_UNIT_TARGET_PASSENGER + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 96 TARGET_UNIT_PASSENGER_0 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 97 TARGET_UNIT_PASSENGER_1 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 98 TARGET_UNIT_PASSENGER_2 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 99 TARGET_UNIT_PASSENGER_3 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 100 TARGET_UNIT_PASSENGER_4 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 101 TARGET_UNIT_PASSENGER_5 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 102 TARGET_UNIT_PASSENGER_6 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 103 TARGET_UNIT_PASSENGER_7 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENEMY, TARGET_DIR_FRONT}, // 104 TARGET_UNIT_CONE_ENEMY_104 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 105 TARGET_UNIT_UNK_105 + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 106 TARGET_DEST_CHANNEL_CASTER + {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 107 TARGET_UNK_DEST_AREA_UNK_107 + {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 108 TARGET_GAMEOBJECT_CONE + {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 109 + {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 110 TARGET_DEST_UNK_110 }; SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex) @@ -463,7 +466,6 @@ SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* _spellInfo = spellInfo; _effIndex = effIndex; - Effect = _effect ? _effect->Effect : 0; ApplyAuraName = _effect ? _effect->EffectApplyAuraName : 0; Amplitude = _effect ? _effect->EffectAmplitude : 0; @@ -484,6 +486,7 @@ SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* ItemType = _effect ? _effect->EffectItemType : 0; TriggerSpell = _effect ? _effect->EffectTriggerSpell : 0; SpellClassMask = _effect ? _effect->EffectSpellClassMask : flag96(0); + ImplicitTargetConditions = NULL; } bool SpellEffectInfo::IsEffect() const @@ -506,7 +509,7 @@ bool SpellEffectInfo::IsAura(AuraType aura) const return IsAura() && ApplyAuraName == aura; } -bool SpellEffectInfo::IsArea() const +bool SpellEffectInfo::IsTargetingArea() const { return TargetA.IsArea() || TargetB.IsArea(); } @@ -1014,6 +1017,11 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry) ChainEntry = NULL; } +SpellInfo::~SpellInfo() +{ + _UnloadImplicitTargetConditionLists(); +} + bool SpellInfo::HasEffect(SpellEffects effect) const { for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) @@ -1137,10 +1145,19 @@ bool SpellInfo::IsAbilityOfSkillType(uint32 skillType) const return false; } -bool SpellInfo::IsAOE() const +bool SpellInfo::IsAffectingArea() const +{ + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + if (Effects[i].IsEffect() && (Effects[i].IsTargetingArea() || Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || Effects[i].IsAreaAuraEffect())) + return true; + return false; +} + +// checks if spell targets are selected from area, doesn't include spell effects in check (like area wide auras for example) +bool SpellInfo::IsTargetingArea() const { for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].IsEffect() && Effects[i].IsArea()) + if (Effects[i].IsEffect() && Effects[i].IsTargetingArea()) return true; return false; } @@ -1630,38 +1647,99 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a return SPELL_CAST_OK; } -SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, bool implicit) const +SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* target, bool implicit) const { if (AttributesEx & SPELL_ATTR1_CANT_TARGET_SELF && caster == target) return SPELL_FAILED_BAD_TARGETS; - if (AttributesEx & SPELL_ATTR1_CANT_TARGET_IN_COMBAT && target->isInCombat()) - return SPELL_FAILED_TARGET_AFFECTING_COMBAT; + // check visibility - ignore stealth for implicit (area) targets + if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE) && !caster->canSeeOrDetect(target, implicit)) + return SPELL_FAILED_BAD_TARGETS; + + Unit const* unitTarget = target->ToUnit(); + + // creature/player specific target checks + if (unitTarget) + { + if (AttributesEx & SPELL_ATTR1_CANT_TARGET_IN_COMBAT && unitTarget->isInCombat()) + return SPELL_FAILED_TARGET_AFFECTING_COMBAT; + + // only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts + if (((AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS) != 0) != unitTarget->HasAuraType(SPELL_AURA_GHOST)) + { + if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS) + return SPELL_FAILED_TARGET_NOT_GHOST; + else + return SPELL_FAILED_BAD_TARGETS; + } + + if (caster != unitTarget) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + { + // Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells) + if (AttributesEx2 & SPELL_ATTR2_CANT_TARGET_TAPPED) + if (Creature const* targetCreature = unitTarget->ToCreature()) + if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(caster->ToPlayer())) + return SPELL_FAILED_CANT_CAST_ON_TAPPED; + + if (AttributesCu & SPELL_ATTR0_CU_PICKPOCKET) + { + if (unitTarget->GetTypeId() == TYPEID_PLAYER) + return SPELL_FAILED_BAD_TARGETS; + else if ((unitTarget->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0) + return SPELL_FAILED_TARGET_NO_POCKETS; + } - if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS && !target->ToPlayer()) + // Not allow disarm unarmed player + if (Mechanic == MECHANIC_DISARM) + { + if (unitTarget->GetTypeId() == TYPEID_PLAYER) + { + Player const* player = unitTarget->ToPlayer(); + if (!player->GetWeaponForAttack(BASE_ATTACK) || !player->IsUseEquipedWeapon(true)) + return SPELL_FAILED_TARGET_NO_WEAPONS; + } + else if (!unitTarget->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID)) + return SPELL_FAILED_TARGET_NO_WEAPONS; + } + } + } + } + // corpse specific target checks + else if (Corpse const* corpseTarget = target->ToCorpse()) + { + // cannot target bare bones + if (corpseTarget->GetType() == CORPSE_BONES) + return SPELL_FAILED_BAD_TARGETS; + // we have to use owner for some checks (aura preventing resurrection for example) + if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID())) + unitTarget = owner; + // we're not interested in corpses without owner + else + return SPELL_FAILED_BAD_TARGETS; + } + // other types of objects - always valid + else return SPELL_CAST_OK; + + // corpseOwner and unit specific target checks + if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS && !unitTarget->ToPlayer()) return SPELL_FAILED_TARGET_NOT_PLAYER; - if (!IsAllowingDeadTarget() && !target->isAlive()) + if (!IsAllowingDeadTarget() && !unitTarget->isAlive()) return SPELL_FAILED_TARGETS_DEAD; - if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS && !(!target->isAlive() && target->HasAuraType(SPELL_AURA_GHOST))) - return SPELL_FAILED_TARGET_NOT_GHOST; - // check this flag only for implicit targets (chain and area), allow to explicitly target units for spells like Shield of Righteousness - if (implicit && AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED && !target->CanFreeMove()) + if (implicit && AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED && !unitTarget->CanFreeMove()) return SPELL_FAILED_BAD_TARGETS; - // check visibility - ignore stealth for implicit (area) targets - if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE) && !caster->canSeeOrDetect(target, implicit)) - return SPELL_FAILED_BAD_TARGETS; - // checked in Unit::IsValidAttack/AssistTarget, shouldn't be checked for ENTRY targets //if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_UNTARGETABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) // return SPELL_FAILED_BAD_TARGETS; //if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_POSSESSED_FRIENDS) - if (!CheckTargetCreatureType(target)) + if (!CheckTargetCreatureType(unitTarget)) { if (target->GetTypeId() == TYPEID_PLAYER) return SPELL_FAILED_TARGET_IS_PLAYER; @@ -1670,65 +1748,32 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, b } // check GM mode and GM invisibility - only for player casts (npc casts are controlled by AI) and negative spells - if (target != caster && (caster->IsControlledByPlayer() || !IsPositive()) && target->GetTypeId() == TYPEID_PLAYER) + if (unitTarget != caster && (caster->IsControlledByPlayer() || !IsPositive()) && unitTarget->GetTypeId() == TYPEID_PLAYER) { - if (!target->ToPlayer()->IsVisible()) + if (!unitTarget->ToPlayer()->IsVisible()) return SPELL_FAILED_BM_OR_INVISGOD; - if (target->ToPlayer()->isGameMaster()) + if (unitTarget->ToPlayer()->isGameMaster()) return SPELL_FAILED_BM_OR_INVISGOD; } // not allow casting on flying player - if (target->HasUnitState(UNIT_STATE_IN_FLIGHT)) + if (unitTarget->HasUnitState(UNIT_STATE_IN_FLIGHT)) return SPELL_FAILED_BAD_TARGETS; - if (TargetAuraState && !target->HasAuraState(AuraStateType(TargetAuraState), this, caster)) + if (TargetAuraState && !unitTarget->HasAuraState(AuraStateType(TargetAuraState), this, caster)) return SPELL_FAILED_TARGET_AURASTATE; - if (TargetAuraStateNot && target->HasAuraState(AuraStateType(TargetAuraStateNot), this, caster)) + if (TargetAuraStateNot && unitTarget->HasAuraState(AuraStateType(TargetAuraStateNot), this, caster)) return SPELL_FAILED_TARGET_AURASTATE; - if (TargetAuraSpell && !target->HasAura(sSpellMgr->GetSpellIdForDifficulty(TargetAuraSpell, caster))) + if (TargetAuraSpell && !unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(TargetAuraSpell, caster))) return SPELL_FAILED_TARGET_AURASTATE; - if (ExcludeTargetAuraSpell && target->HasAura(sSpellMgr->GetSpellIdForDifficulty(ExcludeTargetAuraSpell, caster))) + if (ExcludeTargetAuraSpell && unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(ExcludeTargetAuraSpell, caster))) return SPELL_FAILED_TARGET_AURASTATE; - if (caster != target) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - { - // Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells) - if (AttributesEx2 & SPELL_ATTR2_CANT_TARGET_TAPPED) - if (Creature const* targetCreature = target->ToCreature()) - if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(caster->ToPlayer())) - return SPELL_FAILED_CANT_CAST_ON_TAPPED; - - if (AttributesCu & SPELL_ATTR0_CU_PICKPOCKET) - { - if (target->GetTypeId() == TYPEID_PLAYER) - return SPELL_FAILED_BAD_TARGETS; - else if ((target->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0) - return SPELL_FAILED_TARGET_NO_POCKETS; - } - - // Not allow disarm unarmed player - if (Mechanic == MECHANIC_DISARM) - { - if (target->GetTypeId() == TYPEID_PLAYER) - { - Player const* player = target->ToPlayer(); - if (!player->GetWeaponForAttack(BASE_ATTACK) || !player->IsUseEquipedWeapon(true)) - return SPELL_FAILED_TARGET_NO_WEAPONS; - } - else if (!target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID)) - return SPELL_FAILED_TARGET_NO_WEAPONS; - } - } - } - - if (target->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) + if (unitTarget->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) if (HasEffect(SPELL_EFFECT_SELF_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT_NEW)) return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; @@ -2102,13 +2147,19 @@ float SpellInfo::GetMinRange(bool positive) const return RangeEntry->minRangeHostile; } -float SpellInfo::GetMaxRange(bool positive) const +float SpellInfo::GetMaxRange(bool positive, Unit* caster, Spell* spell) const { if (!RangeEntry) return 0.0f; + float range; if (positive) - return RangeEntry->maxRangeFriend; - return RangeEntry->maxRangeHostile; + range = RangeEntry->maxRangeFriend; + else + range = RangeEntry->maxRangeHostile; + if (caster) + if (Player* modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(Id, SPELLMOD_RANGE, range, spell); + return range; } int32 SpellInfo::GetDuration() const @@ -2698,3 +2749,20 @@ SpellEffectEntry const* SpellEntry::GetSpellEffect(uint32 eff) const { return GetSpellEffectEntry(Id, eff); } + +void SpellInfo::_UnloadImplicitTargetConditionLists() +{ + // find the same instances of ConditionList and delete them. + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + ConditionList* cur = Effects[i].ImplicitTargetConditions; + if (!cur) + continue; + for (uint8 j = i; j < MAX_SPELL_EFFECTS; ++j) + { + if (Effects[j].ImplicitTargetConditions == cur) + Effects[j].ImplicitTargetConditions = NULL; + } + delete cur; + } +} diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 44fb49bb17f..baf03589794 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -36,6 +36,7 @@ struct SpellRangeEntry; struct SpellRadiusEntry; struct SpellEntry; struct SpellCastTimesEntry; +struct Condition; enum SpellCastTargetFlags { @@ -105,15 +106,16 @@ enum SpellTargetObjectTypes TARGET_OBJECT_TYPE_CORPSE_ALLY, }; -enum SpellTargetSelectionCheckTypes +enum SpellTargetCheckTypes { - TARGET_SELECT_CHECK_DEFAULT, - TARGET_SELECT_CHECK_ENTRY, - TARGET_SELECT_CHECK_ENEMY, - TARGET_SELECT_CHECK_ALLY, - TARGET_SELECT_CHECK_PARTY, - TARGET_SELECT_CHECK_RAID, - TARGET_SELECT_CHECK_PASSENGER, + TARGET_CHECK_DEFAULT, + TARGET_CHECK_ENTRY, + TARGET_CHECK_ENEMY, + TARGET_CHECK_ALLY, + TARGET_CHECK_PARTY, + TARGET_CHECK_RAID, + TARGET_CHECK_RAID_CLASS, + TARGET_CHECK_PASSENGER, }; enum SpellTargetDirectionTypes @@ -220,7 +222,7 @@ public: SpellTargetSelectionCategories GetSelectionCategory() const; SpellTargetReferenceTypes GetReferenceType() const; SpellTargetObjectTypes GetObjectType() const; - SpellTargetSelectionCheckTypes GetSelectionCheckType() const; + SpellTargetCheckTypes GetCheckType() const; SpellTargetDirectionTypes GetDirectionType() const; float CalcDirectionAngle() const; @@ -240,7 +242,7 @@ private: SpellTargetObjectTypes ObjectType; // type of object returned by target type SpellTargetReferenceTypes ReferenceType; // defines which object is used as a reference when selecting target SpellTargetSelectionCategories SelectionCategory; - SpellTargetSelectionCheckTypes SelectionCheckType; // defines selection criteria + SpellTargetCheckTypes SelectionCheckType; // defines selection criteria SpellTargetDirectionTypes DirectionType; // direction for cone and dest targets }; static StaticData _data[TOTAL_SPELL_TARGETS]; @@ -271,6 +273,7 @@ public: uint32 ItemType; uint32 TriggerSpell; flag96 SpellClassMask; + std::list<Condition*>* ImplicitTargetConditions; SpellEffectInfo() {} SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex); @@ -279,7 +282,7 @@ public: bool IsEffect(SpellEffects effectName) const; bool IsAura() const; bool IsAura(AuraType aura) const; - bool IsArea() const; + bool IsTargetingArea() const; bool IsAreaAuraEffect() const; bool IsFarUnitTargetEffect() const; bool IsFarDestTargetEffect() const; @@ -431,6 +434,7 @@ public: SpellTotemsEntry const* GetSpellTotems() const; SpellInfo(SpellEntry const* spellEntry); + ~SpellInfo(); bool HasEffect(SpellEffects effect) const; bool HasAura(AuraType aura) const; @@ -446,7 +450,8 @@ public: bool IsAbilityLearnedWithProfession() const; bool IsAbilityOfSkillType(uint32 skillType) const; - bool IsAOE() const; + bool IsAffectingArea() const; + bool IsTargetingArea() const; bool NeedsExplicitUnitTarget() const; bool NeedsToBeTriggeredByCaster() const; @@ -480,7 +485,7 @@ public: SpellCastResult CheckShapeshift(uint32 form) const; SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const; - SpellCastResult CheckTarget(Unit const* caster, Unit const* target, bool implicit = true) const; + SpellCastResult CheckTarget(Unit const* caster, WorldObject const* target, bool implicit = true) const; SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const; bool CheckTargetCreatureType(Unit const* target) const; @@ -498,7 +503,7 @@ public: SpellSpecificType GetSpellSpecific() const; float GetMinRange(bool positive = false) const; - float GetMaxRange(bool positive = false) const; + float GetMaxRange(bool positive = false, Unit* caster = NULL, Spell* spell = NULL) const; int32 GetDuration() const; int32 GetMaxDuration() const; @@ -524,6 +529,9 @@ public: bool _IsPositiveEffect(uint8 effIndex, bool deep) const; bool _IsPositiveSpell() const; static bool _IsPositiveTarget(uint32 targetA, uint32 targetB); + + // unloading helpers + void _UnloadImplicitTargetConditionLists(); }; #endif // _SPELLINFO_H diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index a5bea319fee..67bd7939d70 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -104,9 +104,6 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto, // Hamstring - limit duration to 10s in PvP if (spellproto->SpellFamilyFlags[0] & 0x2) return DIMINISHING_LIMITONLY; - // Improved Hamstring - else if (spellproto->AttributesEx3 & 0x80000 && spellproto->SpellIconID == 23) - return DIMINISHING_ROOT; // Charge Stun (own diminishing) else if (spellproto->SpellFamilyFlags[0] & 0x01000000) return DIMINISHING_CHARGE; @@ -2647,11 +2644,20 @@ void SpellMgr::UnloadSpellInfoStore() for (uint32 i = 0; i < mSpellInfoMap.size(); ++i) { if (mSpellInfoMap[i]) - delete mSpellInfoMap[i]; + delete mSpellInfoMap[i]; } mSpellInfoMap.clear(); } +void SpellMgr::UnloadSpellInfoImplicitTargetConditionLists() +{ + for (uint32 i = 0; i < mSpellInfoMap.size(); ++i) + { + if (mSpellInfoMap[i]) + mSpellInfoMap[i]->_UnloadImplicitTargetConditionLists(); + } +} + void SpellMgr::LoadSpellCustomAttr() { uint32 oldMSTime = getMSTime(); @@ -2893,6 +2899,7 @@ void SpellMgr::LoadSpellCustomAttr() case 64588: // Thrust (Argent Tournament) case 66479: // Thrust (Argent Tournament) case 68505: // Thrust (Argent Tournament) + case 62709: // Counterattack! (Argent Tournament) case 62626: // Break-Shield (Argent Tournament, Player) case 64590: // Break-Shield (Argent Tournament, Player) case 64342: // Break-Shield (Argent Tournament, NPC) diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 14137b6a91b..9fffd474651 100755 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -360,17 +360,6 @@ struct SpellThreatEntry typedef std::map<uint32, SpellThreatEntry> SpellThreatMap; -// Spell script target related declarations (accessed using SpellMgr functions) -enum SpellScriptTargetType -{ - SPELL_TARGET_TYPE_GAMEOBJECT = 0, - SPELL_TARGET_TYPE_CREATURE = 1, - SPELL_TARGET_TYPE_DEAD = 2, - SPELL_TARGET_TYPE_CONTROLLED = 3, -}; - -#define MAX_SPELL_TARGET_TYPE 4 - // coordinates for spells (accessed using SpellMgr functions) struct SpellTargetPosition { @@ -726,6 +715,7 @@ class SpellMgr void LoadSpellAreas(); void LoadSpellInfoStore(); void UnloadSpellInfoStore(); + void UnloadSpellInfoImplicitTargetConditionLists(); void LoadSpellCustomAttr(); void LoadDbcDataCorrections(); diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 8e20fd21fcf..03fea614c0d 100755 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -468,6 +468,11 @@ void SpellScript::PreventHitAura() m_spell->m_spellAura->Remove(); } +void SpellScript::GetSummonPosition(uint32 i, Position &pos, float radius = 0.0f, uint32 count = 0) +{ + m_spell->GetSummonPosition(i, pos, radius, count); +} + void SpellScript::PreventHitEffect(SpellEffIndex effIndex) { if (!IsInHitPhase() && !IsInEffectHook()) @@ -542,6 +547,14 @@ bool AuraScript::_Validate(SpellInfo const* entry) if (!entry->HasAreaAuraEffect()) sLog->outError("TSCR: Spell `%u` of script `%s` does not have area aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + for (std::list<AuraDispelHandler>::iterator itr = OnDispel.begin(); itr != OnDispel.end(); ++itr) + if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) + sLog->outError("TSCR: Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `OnDispel` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + + for (std::list<AuraDispelHandler>::iterator itr = AfterDispel.begin(); itr != AfterDispel.end(); ++itr) + if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) + sLog->outError("TSCR: Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `AfterDispel` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + for (std::list<EffectApplyHandler>::iterator itr = OnEffectApply.begin(); itr != OnEffectApply.end(); ++itr) if (!(*itr).GetAffectedEffectsMask(entry)) sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectApply` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); @@ -607,6 +620,16 @@ bool AuraScript::CheckAreaTargetHandler::Call(AuraScript* auraScript, Unit* _tar return (auraScript->*pHandlerScript)(_target); } +AuraScript::AuraDispelHandler::AuraDispelHandler(AuraDispelFnType _pHandlerScript) +{ + pHandlerScript = _pHandlerScript; +} + +void AuraScript::AuraDispelHandler::Call(AuraScript* auraScript, DispelInfo* _dispelInfo) +{ + (auraScript->*pHandlerScript)(_dispelInfo); +} + AuraScript::EffectBase::EffectBase(uint8 _effIndex, uint16 _effName) : _SpellScript::EffectAuraNameCheck(_effName), _SpellScript::EffectHook(_effIndex) { diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index a1d8e6563b0..1bf8d25adef 100755 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -21,6 +21,7 @@ #include "Util.h" #include "SharedDefines.h" #include "SpellAuraDefines.h" +#include "Spell.h" #include <stack> class Unit; @@ -333,7 +334,8 @@ class SpellScript : public _SpellScript int32 GetHitHeal(); void SetHitHeal(int32 heal); void PreventHitHeal() { SetHitHeal(0); } - + Spell* GetSpell() { return m_spell; } + void GetSummonPosition(uint32 i, Position &pos, float radius, uint32 count); // returns current spell hit target aura Aura* GetHitAura(); // prevents applying aura on current spell hit target @@ -385,6 +387,8 @@ enum AuraScriptHookType AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, AURA_SCRIPT_HOOK_CHECK_AREA_TARGET, + AURA_SCRIPT_HOOK_DISPEL, + AURA_SCRIPT_HOOK_AFTER_DISPEL, /*AURA_SCRIPT_HOOK_APPLY, AURA_SCRIPT_HOOK_REMOVE, */ }; @@ -400,6 +404,7 @@ class AuraScript : public _SpellScript #define AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) \ typedef bool(CLASSNAME::*AuraCheckAreaTargetFnType)(Unit* target); \ + typedef void(CLASSNAME::*AuraDispelFnType)(DispelInfo* dispelInfo); \ typedef void(CLASSNAME::*AuraEffectApplicationModeFnType)(AuraEffect const*, AuraEffectHandleModes); \ typedef void(CLASSNAME::*AuraEffectPeriodicFnType)(AuraEffect const*); \ typedef void(CLASSNAME::*AuraEffectUpdatePeriodicFnType)(AuraEffect*); \ @@ -418,6 +423,14 @@ class AuraScript : public _SpellScript private: AuraCheckAreaTargetFnType pHandlerScript; }; + class AuraDispelHandler + { + public: + AuraDispelHandler(AuraDispelFnType pHandlerScript); + void Call(AuraScript* auraScript, DispelInfo* dispelInfo); + private: + AuraDispelFnType pHandlerScript; + }; class EffectBase : public _SpellScript::EffectAuraNameCheck, public _SpellScript::EffectHook { public: @@ -493,6 +506,7 @@ class AuraScript : public _SpellScript #define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \ class CheckAreaTargetFunction : public AuraScript::CheckAreaTargetHandler { public: CheckAreaTargetFunction(AuraCheckAreaTargetFnType _pHandlerScript) : AuraScript::CheckAreaTargetHandler((AuraScript::AuraCheckAreaTargetFnType)_pHandlerScript) {} }; \ + class AuraDispelFunction : public AuraScript::AuraDispelHandler { public: AuraDispelFunction(AuraDispelFnType _pHandlerScript) : AuraScript::AuraDispelHandler((AuraScript::AuraDispelFnType)_pHandlerScript) {} }; \ class EffectPeriodicHandlerFunction : public AuraScript::EffectPeriodicHandler { public: EffectPeriodicHandlerFunction(AuraEffectPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectPeriodicHandler((AuraScript::AuraEffectPeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \ class EffectUpdatePeriodicHandlerFunction : public AuraScript::EffectUpdatePeriodicHandler { public: EffectUpdatePeriodicHandlerFunction(AuraEffectUpdatePeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectUpdatePeriodicHandler((AuraScript::AuraEffectUpdatePeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \ class EffectCalcAmountHandlerFunction : public AuraScript::EffectCalcAmountHandler { public: EffectCalcAmountHandlerFunction(AuraEffectCalcAmountFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectCalcAmountHandler((AuraScript::AuraEffectCalcAmountFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \ @@ -540,6 +554,17 @@ class AuraScript : public _SpellScript // where function is: bool function (Unit* target); HookList<CheckAreaTargetHandler> DoCheckAreaTarget; #define AuraCheckAreaTargetFn(F) CheckAreaTargetFunction(&F) + + // executed when aura is dispelled by a unit + // example: OnDispel += AuraDispelFn(class::function); + // where function is: void function (DispelInfo* dispelInfo); + HookList<AuraDispelHandler> OnDispel; + // executed after aura is dispelled by a unit + // example: AfterDispel += AuraDispelFn(class::function); + // where function is: void function (DispelInfo* dispelInfo); + HookList<AuraDispelHandler> AfterDispel; + #define AuraDispelFn(F) AuraDispelFunction(&F) + // executed when aura effect is applied with specified mode to target // should be used when when effect handler preventing/replacing is needed, do not use this hook for triggering spellcasts/removing auras etc - may be unsafe // example: OnEffectApply += AuraEffectApplyFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes); diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index b076447dd90..4d9c5a93875 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -404,15 +404,15 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; - if (guid != 0 && guid < sObjectMgr->m_hiCharGuid) + if (guid != 0 && guid < sObjectMgr->_hiCharGuid) { result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE guid = '%d'", guid); if (result) - guid = sObjectMgr->m_hiCharGuid; // use first free if exists + guid = sObjectMgr->_hiCharGuid; // use first free if exists else incHighest = false; } else - guid = sObjectMgr->m_hiCharGuid; + guid = sObjectMgr->_hiCharGuid; // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) @@ -564,15 +564,15 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s if (!changenth(line, 1, newguid)) // character_inventory.guid update ROLLBACK(DUMP_FILE_BROKEN); - if (!changeGuid(line, 2, items, sObjectMgr->m_hiItemGuid, true)) + if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update - if (!changeGuid(line, 4, items, sObjectMgr->m_hiItemGuid)) + if (!changeGuid(line, 4, items, sObjectMgr->_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update break; } case DTT_MAIL: // mail { - if (!changeGuid(line, 1, mails, sObjectMgr->m_mailid)) + if (!changeGuid(line, 1, mails, sObjectMgr->_mailId)) ROLLBACK(DUMP_FILE_BROKEN); // mail.id update if (!changenth(line, 6, newguid)) // mail.receiver update ROLLBACK(DUMP_FILE_BROKEN); @@ -580,9 +580,9 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s } case DTT_MAIL_ITEM: // mail_items { - if (!changeGuid(line, 1, mails, sObjectMgr->m_mailid)) + if (!changeGuid(line, 1, mails, sObjectMgr->_mailId)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id - if (!changeGuid(line, 2, items, sObjectMgr->m_hiItemGuid)) + if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid if (!changenth(line, 3, newguid)) // mail_items.receiver ROLLBACK(DUMP_FILE_BROKEN); @@ -591,7 +591,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s case DTT_ITEM: { // item, owner, data field:item, owner guid - if (!changeGuid(line, 1, items, sObjectMgr->m_hiItemGuid)) + if (!changeGuid(line, 1, items, sObjectMgr->_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update if (!changenth(line, 3, newguid)) // item_instance.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); @@ -601,7 +601,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s { if (!changenth(line, 1, newguid)) // character_gifts.guid update ROLLBACK(DUMP_FILE_BROKEN); - if (!changeGuid(line, 2, items, sObjectMgr->m_hiItemGuid)) + if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update break; } @@ -662,11 +662,11 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s // in case of name conflict player has to rename at login anyway sWorld->AddCharacterNameData(guid, name, gender, race, playerClass); - sObjectMgr->m_hiItemGuid += items.size(); - sObjectMgr->m_mailid += mails.size(); + sObjectMgr->_hiItemGuid += items.size(); + sObjectMgr->_mailId += mails.size(); if (incHighest) - ++sObjectMgr->m_hiCharGuid; + ++sObjectMgr->_hiCharGuid; fclose(fin); diff --git a/src/server/game/Warden/Modules/WardenModuleMac.h b/src/server/game/Warden/Modules/WardenModuleMac.h new file mode 100644 index 00000000000..46011c5bcd9 --- /dev/null +++ b/src/server/game/Warden/Modules/WardenModuleMac.h @@ -0,0 +1,614 @@ +/* + * 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 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 _WARDEN_MODULE_MAC_H +#define _WARDEN_MODULE_MAC_H + +uint8 Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data[9318] = +{ + 0x07, 0x0C, 0x44, 0xCD, 0xC9, 0xFB, 0x99, 0xBC, 0x7C, 0x77, 0xDC, 0xE8, 0x8D, 0x07, 0xBE, 0x55, + 0x37, 0x5C, 0x84, 0x10, 0x23, 0xE1, 0x36, 0x5B, 0xF1, 0xBC, 0x60, 0xF3, 0x68, 0xBA, 0x60, 0x69, + 0xDF, 0x48, 0x54, 0xFF, 0x49, 0x1F, 0xA6, 0x28, 0x08, 0x5A, 0x77, 0xFE, 0x4C, 0x3A, 0x9A, 0x28, + 0xA5, 0x9E, 0x01, 0x93, 0x05, 0xE4, 0xCD, 0x26, 0x41, 0xD7, 0xD6, 0x73, 0x81, 0xFD, 0xF5, 0xDB, + 0xA5, 0xF7, 0xF9, 0x1D, 0xFE, 0xF4, 0x06, 0x7C, 0xD0, 0xF8, 0x5A, 0xE8, 0x11, 0xFF, 0xE5, 0xF9, + 0x54, 0x49, 0xF7, 0xF0, 0xF8, 0x66, 0x22, 0x97, 0xA4, 0xB2, 0x86, 0xFE, 0xA6, 0x3A, 0x7F, 0x3B, + 0xF6, 0x47, 0xB4, 0x14, 0xEB, 0x9E, 0xC9, 0xEA, 0x0B, 0x41, 0xB4, 0x5B, 0xC2, 0xFB, 0x63, 0x1C, + 0x46, 0xC4, 0xAB, 0x3F, 0x30, 0x70, 0x7F, 0x35, 0xA3, 0xD2, 0x1A, 0xDE, 0x36, 0x79, 0x02, 0x05, + 0x0E, 0x47, 0xFF, 0xDF, 0x1F, 0xB7, 0xE0, 0x11, 0x7F, 0xB8, 0x43, 0x8C, 0x46, 0xF0, 0x4D, 0x39, + 0x83, 0x7C, 0x44, 0xE7, 0xD0, 0x02, 0x54, 0xAB, 0x84, 0xB3, 0x64, 0xCA, 0xD2, 0xB6, 0xF5, 0xDC, + 0x06, 0x2B, 0x39, 0x27, 0x5B, 0x18, 0x82, 0xC4, 0xD6, 0x95, 0xB1, 0xDE, 0x2F, 0x0C, 0xAD, 0x96, + 0x12, 0xBF, 0x82, 0x0B, 0x78, 0x77, 0x7B, 0x42, 0x96, 0x87, 0xF6, 0x7B, 0xE2, 0x0B, 0x36, 0x2C, + 0x34, 0xCD, 0xFA, 0x01, 0x60, 0x3F, 0x52, 0x9B, 0xAB, 0xAC, 0x25, 0xF1, 0xDE, 0xD0, 0x61, 0x12, + 0x21, 0xF2, 0xDE, 0xB7, 0xA4, 0x5F, 0x5F, 0xA2, 0xA7, 0x31, 0xAC, 0x2D, 0xA3, 0x42, 0xCF, 0x73, + 0x88, 0x53, 0x02, 0x60, 0x9A, 0x11, 0xCB, 0xDF, 0xB9, 0x97, 0x10, 0x3F, 0xBD, 0xF6, 0x14, 0x38, + 0x1D, 0xAD, 0xC5, 0x22, 0x99, 0x40, 0x1C, 0xA3, 0x3D, 0x2E, 0x2E, 0x93, 0x70, 0xE4, 0x5B, 0x3E, + 0x9E, 0xDC, 0x6E, 0x4D, 0xC2, 0xDA, 0x2D, 0x54, 0x4A, 0xDF, 0xFD, 0x30, 0x4C, 0xAF, 0x5D, 0xDE, + 0xEB, 0xFF, 0xCF, 0xE3, 0x9A, 0x3C, 0x4F, 0xB3, 0x7D, 0x61, 0xEB, 0x66, 0xD8, 0xBC, 0x12, 0xC1, + 0xD4, 0x66, 0xBD, 0x89, 0x64, 0x8E, 0x68, 0xA6, 0xD4, 0xDC, 0xA4, 0x00, 0x84, 0x9A, 0x53, 0x1E, + 0x4D, 0x1B, 0x84, 0x19, 0xF8, 0x0A, 0x85, 0x96, 0x99, 0x64, 0xEB, 0xAE, 0x11, 0xFB, 0xC8, 0xBB, + 0xC0, 0x8E, 0x5B, 0x8E, 0xE3, 0x95, 0x50, 0x8A, 0xD4, 0x68, 0x0A, 0x11, 0xED, 0xC2, 0x8F, 0x87, + 0xA7, 0x3F, 0xB4, 0x99, 0xDF, 0x37, 0xF6, 0x4F, 0x32, 0x4E, 0x0B, 0x99, 0x35, 0xD0, 0x1E, 0x40, + 0x00, 0x8C, 0x3C, 0xCE, 0xC8, 0xE3, 0x89, 0x7B, 0x09, 0xA3, 0xA7, 0x35, 0x5B, 0x2B, 0x82, 0x98, + 0xC3, 0xEE, 0xD8, 0xAF, 0x59, 0x0C, 0xFB, 0x28, 0x57, 0x21, 0x79, 0x33, 0xDC, 0x3E, 0xD7, 0x66, + 0x02, 0x47, 0xC1, 0x1E, 0xB8, 0x85, 0x28, 0x1A, 0x1C, 0x5C, 0xA2, 0x11, 0x18, 0x9C, 0xB7, 0x54, + 0x4B, 0x97, 0x6D, 0x90, 0x93, 0x31, 0x6C, 0x07, 0x3B, 0xE9, 0x35, 0xD7, 0x3B, 0x59, 0x7A, 0x5B, + 0xEC, 0xE1, 0x63, 0xC4, 0xB6, 0x1A, 0x97, 0xEE, 0x1A, 0xD0, 0xF5, 0xF6, 0xBF, 0x10, 0x55, 0xCB, + 0x7F, 0xF7, 0x3C, 0x2D, 0x7D, 0xDF, 0x5C, 0xE1, 0x84, 0xF1, 0xD5, 0x87, 0x05, 0xEE, 0x94, 0xE3, + 0x55, 0xF3, 0x8B, 0xD1, 0x4B, 0xBF, 0x7E, 0x93, 0xEB, 0xAB, 0x09, 0x36, 0x3E, 0x8D, 0xA6, 0x90, + 0xC5, 0x2E, 0x0A, 0xF4, 0x2B, 0x9E, 0xBC, 0xDA, 0xC1, 0x3A, 0x77, 0x96, 0x8E, 0xA2, 0x28, 0x53, + 0x0B, 0x37, 0xEC, 0x3F, 0xA6, 0xED, 0xF7, 0x32, 0x3A, 0x7D, 0xE5, 0x64, 0x1C, 0xAE, 0x6B, 0xB4, + 0x08, 0xDA, 0xCD, 0x3E, 0x32, 0xC7, 0x0F, 0xDF, 0xDE, 0x9D, 0x4D, 0x20, 0xE0, 0x71, 0x7C, 0xB7, + 0xAF, 0x87, 0x99, 0x4B, 0xCC, 0x3B, 0xFB, 0x26, 0xAA, 0x01, 0xF3, 0x77, 0x01, 0x7E, 0x8C, 0x0D, + 0x09, 0x9D, 0x40, 0xFD, 0x3D, 0xA1, 0xEA, 0x53, 0x99, 0x68, 0x87, 0xE2, 0xCA, 0x1B, 0x1F, 0x45, + 0x83, 0xF1, 0x74, 0xBB, 0x65, 0x49, 0x46, 0xD2, 0x43, 0xDA, 0xE1, 0x4D, 0x29, 0x3A, 0x41, 0x81, + 0xF6, 0x46, 0x03, 0x43, 0x19, 0xBA, 0x2F, 0x79, 0xF0, 0xA3, 0xB4, 0x92, 0x08, 0x74, 0xE0, 0x61, + 0x0F, 0x26, 0xEF, 0xDE, 0x3B, 0x52, 0x9F, 0xB4, 0x06, 0x5D, 0xC6, 0xBC, 0x3C, 0xA5, 0x86, 0x7C, + 0x35, 0x21, 0xF7, 0x05, 0xCD, 0x05, 0x15, 0x31, 0xE0, 0xC0, 0xF6, 0x12, 0x70, 0x56, 0xF9, 0x25, + 0xB7, 0x91, 0x34, 0x85, 0x5D, 0xE9, 0x5D, 0xB8, 0x4F, 0x4C, 0xFB, 0xB5, 0xB6, 0x2F, 0xAE, 0xA3, + 0x2A, 0x99, 0x25, 0x4D, 0x17, 0x41, 0x47, 0xC3, 0xF5, 0x04, 0x52, 0xCC, 0xDE, 0x4E, 0xA3, 0x42, + 0x30, 0x19, 0xA5, 0xD5, 0x94, 0x46, 0xC0, 0x78, 0xF7, 0x7D, 0xD9, 0x9D, 0x0A, 0xCF, 0xEE, 0x0C, + 0x5C, 0x92, 0x85, 0x10, 0xF5, 0xEC, 0x2E, 0x48, 0xC1, 0x35, 0x86, 0x1E, 0x6A, 0xBE, 0xF0, 0x89, + 0x64, 0xF7, 0x4A, 0x71, 0xE7, 0x10, 0x6B, 0xEC, 0xC0, 0xC9, 0xB7, 0x94, 0x66, 0x27, 0x22, 0x2D, + 0xA2, 0x94, 0xAB, 0xBE, 0x36, 0xAC, 0x76, 0xB9, 0x2D, 0x8A, 0x04, 0xEF, 0x08, 0x3D, 0xA7, 0x9A, + 0xC7, 0x73, 0x78, 0xB2, 0xCD, 0x9E, 0x59, 0x90, 0x39, 0x1E, 0x54, 0x51, 0x18, 0x25, 0x22, 0x2A, + 0x38, 0x20, 0x73, 0xF1, 0x7F, 0x01, 0x07, 0x81, 0xA9, 0x3F, 0xE8, 0x90, 0x9C, 0xF6, 0x45, 0x14, + 0x8D, 0x82, 0xCB, 0xB0, 0x7D, 0x77, 0xA5, 0x97, 0x34, 0x81, 0x28, 0x6C, 0x1B, 0x0F, 0x60, 0x4B, + 0x35, 0xC5, 0x1C, 0xE4, 0xE2, 0x4C, 0x0A, 0xE1, 0xF9, 0xD0, 0xE8, 0xCC, 0x18, 0x25, 0xF6, 0xA0, + 0x41, 0xDF, 0x9B, 0x68, 0x75, 0x64, 0x0D, 0xE3, 0x1F, 0xA4, 0xA7, 0xFF, 0x02, 0xB5, 0x68, 0xA3, + 0x62, 0xAE, 0xD2, 0x1D, 0x36, 0x37, 0x18, 0x6C, 0xCE, 0x20, 0x25, 0xAF, 0xDD, 0x20, 0xB5, 0xF4, + 0xCF, 0x05, 0x3B, 0xF0, 0xD7, 0xB0, 0x43, 0xDB, 0xD7, 0xC7, 0x87, 0x1D, 0xD6, 0xD1, 0xD0, 0x33, + 0x20, 0x66, 0x10, 0x3C, 0x5E, 0x9D, 0xA8, 0x21, 0x48, 0x31, 0x65, 0x4C, 0xBD, 0xF5, 0x40, 0x97, + 0xC8, 0x0A, 0x87, 0x25, 0x0C, 0x54, 0x35, 0xCE, 0xEC, 0x76, 0xE8, 0xAD, 0x95, 0xCD, 0xC6, 0x7E, + 0xCD, 0x7C, 0xFD, 0x5F, 0x5B, 0xD6, 0x6B, 0xC6, 0xC4, 0x26, 0xA9, 0x16, 0xD7, 0xC8, 0xCE, 0x9E, + 0x3E, 0xB0, 0x81, 0xA1, 0x9A, 0xBE, 0x8A, 0xF9, 0x7D, 0xB0, 0x1B, 0x03, 0x9B, 0xBA, 0xF7, 0xF5, + 0x74, 0x13, 0x0F, 0x44, 0x51, 0x98, 0xAC, 0x56, 0x69, 0x24, 0xB1, 0xEA, 0xCD, 0x27, 0x25, 0xE5, + 0x58, 0x26, 0xCA, 0x44, 0xBA, 0x6D, 0xAA, 0x6E, 0x2F, 0xC8, 0x5E, 0x18, 0x6F, 0x08, 0xA0, 0xE8, + 0x57, 0xFB, 0x77, 0x99, 0x8A, 0xBD, 0x56, 0x1D, 0xD2, 0xD8, 0x63, 0x7A, 0xCE, 0xD3, 0xC9, 0xE2, + 0x99, 0xC2, 0x96, 0xB8, 0x8E, 0x88, 0x09, 0x80, 0xC6, 0x9A, 0xC3, 0xC5, 0xFB, 0xF5, 0x3C, 0x90, + 0x70, 0xAB, 0xF1, 0xA6, 0x80, 0x17, 0x2A, 0x25, 0xD3, 0xD2, 0x2B, 0xEE, 0xF5, 0xD2, 0x7F, 0xBD, + 0x2D, 0x83, 0xCC, 0x2A, 0x8C, 0xE2, 0xB4, 0xC4, 0xF4, 0x84, 0x34, 0x68, 0x04, 0xAD, 0x62, 0x27, + 0xE5, 0x19, 0x40, 0x17, 0xD7, 0x0A, 0xC4, 0x0A, 0x7E, 0x24, 0xBB, 0x38, 0xBC, 0xA3, 0x3B, 0x4A, + 0x58, 0x7C, 0x6B, 0xD2, 0x29, 0x46, 0xD6, 0xCF, 0x1C, 0x4B, 0xCC, 0x4E, 0x99, 0x28, 0xFC, 0x10, + 0xB1, 0x8B, 0x59, 0xF8, 0x2B, 0x6F, 0x43, 0x67, 0x01, 0x24, 0xFB, 0xCA, 0xB4, 0xBD, 0x35, 0x4B, + 0x7D, 0x50, 0xC0, 0x83, 0xD4, 0xB9, 0xC7, 0x37, 0x45, 0xB9, 0x24, 0xD7, 0x6D, 0x9D, 0xA6, 0x9C, + 0x7C, 0x1F, 0xE6, 0xB9, 0x97, 0x2C, 0x47, 0x5E, 0xCA, 0x30, 0xEB, 0xE5, 0xFD, 0x70, 0xD2, 0x37, + 0xE7, 0x6A, 0x3A, 0xEF, 0x00, 0xCF, 0x10, 0xF3, 0x3B, 0xA1, 0x62, 0xF0, 0x7D, 0xEA, 0x32, 0x50, + 0x87, 0x73, 0xAC, 0xB5, 0x61, 0x85, 0x6D, 0xDD, 0xD9, 0xD8, 0x84, 0xCD, 0x23, 0x3F, 0x11, 0x63, + 0xB1, 0xAB, 0xDF, 0x37, 0xAF, 0x84, 0x7C, 0x12, 0x77, 0x41, 0xFF, 0xF1, 0xF7, 0x5F, 0xF5, 0x40, + 0x23, 0xE1, 0x07, 0xC6, 0x89, 0x95, 0xF3, 0xA8, 0x5F, 0x1C, 0xE4, 0xE3, 0x86, 0x04, 0xD2, 0x17, + 0x52, 0xA3, 0x74, 0x51, 0x53, 0x6E, 0x44, 0x42, 0x92, 0x10, 0xBD, 0x7F, 0x5A, 0x13, 0x14, 0x85, + 0x59, 0x08, 0xF2, 0x87, 0x9A, 0x20, 0x98, 0xE8, 0x2E, 0xF1, 0x0F, 0x3D, 0x42, 0x79, 0x75, 0x88, + 0x45, 0x19, 0x8E, 0x6B, 0xF0, 0xCE, 0x22, 0x47, 0x30, 0x29, 0xC1, 0x94, 0xFE, 0x79, 0x4E, 0xDC, + 0xE3, 0x7F, 0x00, 0x4E, 0x67, 0x7D, 0xD7, 0x84, 0x2A, 0x01, 0x4E, 0x17, 0x07, 0x17, 0xD7, 0x1E, + 0x4D, 0xC5, 0x0B, 0x1C, 0x76, 0x8F, 0x02, 0x33, 0x26, 0xC6, 0x75, 0x35, 0xD2, 0x76, 0xAD, 0x8C, + 0xE9, 0x08, 0x9E, 0xCD, 0x07, 0x72, 0x3A, 0x61, 0x29, 0x2C, 0x99, 0xB9, 0x72, 0x6F, 0xF7, 0x69, + 0xAF, 0xEA, 0x3E, 0x56, 0xBE, 0xD8, 0x3A, 0xD7, 0xFC, 0x86, 0xE7, 0xB8, 0x45, 0x37, 0xF7, 0xE0, + 0x47, 0xD4, 0x0B, 0x36, 0xD4, 0xF1, 0x4B, 0x28, 0x2B, 0xE5, 0x1E, 0xB1, 0x06, 0x5B, 0x39, 0x59, + 0x34, 0x3D, 0x05, 0x23, 0x49, 0x8D, 0x9D, 0xC9, 0xEA, 0xC3, 0x42, 0x00, 0x65, 0x75, 0x09, 0xEC, + 0x30, 0xB6, 0xDB, 0xFB, 0x93, 0xFA, 0x93, 0x6D, 0x8D, 0xBE, 0xF5, 0x8D, 0x1E, 0x22, 0xB3, 0xAB, + 0x90, 0xB1, 0xA4, 0xE8, 0xCD, 0xB0, 0xBB, 0x2A, 0xF7, 0x39, 0xF2, 0x9C, 0x73, 0x18, 0xCF, 0xD4, + 0x14, 0xB5, 0xDD, 0x1A, 0x65, 0x6B, 0x47, 0x11, 0x16, 0xAD, 0xB4, 0xFC, 0xA3, 0x31, 0x56, 0xBD, + 0xBD, 0xB2, 0xC4, 0xCC, 0x39, 0xDA, 0x60, 0x86, 0x4E, 0x7F, 0x37, 0x99, 0xCF, 0x88, 0x47, 0x2A, + 0x1D, 0x09, 0xDA, 0xE1, 0x07, 0xF0, 0x1B, 0x97, 0x9E, 0x13, 0x43, 0x9E, 0x99, 0xA9, 0x2B, 0x1C, + 0x2D, 0xDB, 0xED, 0x0C, 0x58, 0xD2, 0xBE, 0x25, 0x25, 0x44, 0x62, 0x37, 0x7A, 0x50, 0x9A, 0x68, + 0x3E, 0x9A, 0xE5, 0xE2, 0xCA, 0x3F, 0xFF, 0x01, 0xF8, 0x17, 0xF4, 0xA8, 0xFF, 0x8E, 0x99, 0xDB, + 0x6E, 0x13, 0xD7, 0x7F, 0x1F, 0xDE, 0xDE, 0x2F, 0x9F, 0x37, 0x60, 0x41, 0xF0, 0xA0, 0xB7, 0x4F, + 0x80, 0x7D, 0xBA, 0xF9, 0xF1, 0xA6, 0x2C, 0x03, 0xD7, 0x3F, 0x3C, 0xC6, 0x45, 0x7C, 0xFF, 0x40, + 0x7C, 0x6D, 0x73, 0x6D, 0x42, 0x8F, 0x87, 0xDA, 0x66, 0xB3, 0xDF, 0x20, 0x17, 0x27, 0x86, 0x28, + 0xD6, 0x7F, 0x90, 0x0D, 0xFC, 0x62, 0x87, 0x59, 0x6B, 0x15, 0xB3, 0xBD, 0xF5, 0x15, 0x5F, 0x12, + 0x21, 0xE3, 0x50, 0x6A, 0xEA, 0x83, 0x9A, 0x1B, 0xC9, 0x29, 0x44, 0x32, 0xD7, 0x72, 0x68, 0x1B, + 0xA6, 0x1B, 0xDD, 0x65, 0xDB, 0x0A, 0xF7, 0xEE, 0xF1, 0xF2, 0xA6, 0x68, 0x6D, 0xEB, 0xB9, 0xF2, + 0x5A, 0xF9, 0xEE, 0xA3, 0xD0, 0xAE, 0xE2, 0x18, 0x29, 0xFF, 0xFD, 0x9B, 0x94, 0x6C, 0x03, 0xFC, + 0x3C, 0xF2, 0xEB, 0x3D, 0x50, 0x16, 0xA5, 0xB6, 0x64, 0x25, 0xFC, 0x3F, 0x79, 0xC0, 0x7F, 0x22, + 0x0C, 0x06, 0xFB, 0xAA, 0xAC, 0x2D, 0xC1, 0x1F, 0x24, 0x3F, 0x72, 0x87, 0xBE, 0xE5, 0xFD, 0x25, + 0x70, 0x65, 0x31, 0xA1, 0xD8, 0x63, 0xD3, 0xB6, 0x67, 0x99, 0xAF, 0xC4, 0x78, 0x44, 0xC7, 0x60, + 0x95, 0x9B, 0x2F, 0x3C, 0x0A, 0x44, 0xEB, 0x80, 0x34, 0x50, 0xE9, 0x01, 0x37, 0xF8, 0x55, 0x4D, + 0xE1, 0x73, 0x24, 0xC5, 0xF2, 0x9D, 0xCD, 0x70, 0x1A, 0x77, 0x57, 0x19, 0xF6, 0xA8, 0xEC, 0x69, + 0x25, 0xEF, 0xE4, 0xE2, 0x8C, 0x9A, 0x51, 0x90, 0x95, 0x21, 0xC5, 0xC1, 0x0C, 0xAD, 0x33, 0xF7, + 0x0E, 0xC5, 0xC4, 0xFF, 0x3D, 0xA9, 0xEA, 0x36, 0xCF, 0x15, 0x57, 0xB8, 0x37, 0xB7, 0x9A, 0x92, + 0x59, 0xDF, 0x91, 0x5C, 0x07, 0x78, 0xAD, 0xE6, 0xE0, 0x71, 0xD7, 0x17, 0x65, 0x8A, 0x62, 0x52, + 0x30, 0x95, 0xA1, 0xC5, 0x2F, 0xC7, 0x6D, 0x94, 0xDA, 0xA8, 0xFE, 0xF8, 0x28, 0x99, 0xC9, 0x9D, + 0x28, 0xFB, 0x6D, 0x22, 0xD0, 0x44, 0xAE, 0x02, 0x89, 0xEA, 0x93, 0xC6, 0x11, 0xC9, 0x19, 0x35, + 0x82, 0x7A, 0x76, 0x87, 0x9A, 0x5D, 0x39, 0x9E, 0x5A, 0x6B, 0x53, 0x45, 0x2F, 0x10, 0x6E, 0x86, + 0x95, 0xB5, 0x8F, 0x87, 0xB6, 0x37, 0x58, 0x48, 0x16, 0x01, 0x4D, 0xE1, 0xD1, 0x13, 0x21, 0xC3, + 0xAA, 0x8F, 0xDE, 0xE1, 0xFF, 0x5F, 0xEA, 0xBC, 0xBC, 0xDF, 0xF2, 0xB9, 0x0D, 0x96, 0x53, 0xF0, + 0x08, 0xB9, 0x01, 0x9E, 0x70, 0x87, 0xF3, 0x89, 0xFA, 0x1A, 0xB0, 0x06, 0xF3, 0xEC, 0x13, 0xC5, + 0x8D, 0x21, 0xF5, 0x2B, 0x47, 0x35, 0x48, 0x01, 0x34, 0xA2, 0x8D, 0x55, 0x24, 0x37, 0xFC, 0x5A, + 0x43, 0x0D, 0x0B, 0x3E, 0x0A, 0x95, 0x5B, 0xEF, 0x9F, 0x38, 0x41, 0x25, 0x52, 0xE3, 0x1C, 0xBF, + 0x7D, 0x3B, 0x1C, 0x32, 0x83, 0xBF, 0xBF, 0x69, 0xD2, 0xB5, 0x73, 0xD4, 0x5F, 0x4F, 0x0E, 0xBA, + 0xFF, 0x6C, 0xB6, 0xB4, 0xBB, 0x62, 0xD7, 0xEB, 0x5C, 0xC8, 0x44, 0x50, 0x38, 0xAD, 0x4F, 0xA0, + 0xB2, 0x90, 0x0F, 0x58, 0x2E, 0x93, 0x0F, 0xE8, 0xEB, 0x2F, 0x65, 0x76, 0x56, 0xD9, 0xDD, 0x79, + 0x75, 0xE1, 0xAD, 0x4A, 0x1A, 0x24, 0x5F, 0xE0, 0x82, 0x62, 0xF9, 0x96, 0x90, 0xD6, 0x4F, 0xFC, + 0xF6, 0x9E, 0xAE, 0x1C, 0xDA, 0x4D, 0x3B, 0xC4, 0x44, 0x4B, 0xAC, 0x69, 0xD7, 0x0E, 0x89, 0xAD, + 0xED, 0xF8, 0x6A, 0x8C, 0x4B, 0xAE, 0xC4, 0xEA, 0x02, 0x78, 0x0B, 0x41, 0xF6, 0x98, 0xE9, 0x1E, + 0xE2, 0x17, 0x0A, 0x0A, 0xA3, 0x1E, 0xE3, 0xF4, 0xEE, 0x7E, 0x3C, 0x81, 0x52, 0xCB, 0x2E, 0xF2, + 0x75, 0x0F, 0xD9, 0xD3, 0x58, 0xE0, 0xFF, 0x14, 0xA1, 0x4F, 0x7F, 0x19, 0xCA, 0xD1, 0xDA, 0x32, + 0x1F, 0xCD, 0x74, 0x41, 0x22, 0x8A, 0xBF, 0x96, 0x04, 0x35, 0xB7, 0x44, 0x86, 0x39, 0x59, 0xC6, + 0x96, 0x17, 0x99, 0x72, 0x72, 0xA1, 0x4E, 0x33, 0x65, 0x02, 0x1C, 0xA7, 0x1D, 0x6C, 0x24, 0xE1, + 0x85, 0x6A, 0x1E, 0x02, 0x88, 0xCE, 0x0E, 0x6D, 0x5F, 0x6B, 0x38, 0xD5, 0xA0, 0x5F, 0x15, 0x3C, + 0x4B, 0xBD, 0xD3, 0x6E, 0x0A, 0x70, 0x10, 0x3F, 0x6A, 0xB5, 0xAB, 0x72, 0x7D, 0x78, 0x42, 0x79, + 0x23, 0x16, 0x49, 0x4F, 0x97, 0x15, 0xF3, 0xA7, 0x6E, 0x73, 0x41, 0xB2, 0x78, 0x21, 0x3F, 0x32, + 0x17, 0x7F, 0x97, 0xBB, 0xA8, 0xDE, 0x17, 0xD6, 0xFB, 0x32, 0x95, 0x3D, 0x93, 0x07, 0x9D, 0xD2, + 0x5E, 0x99, 0xCD, 0x7C, 0x3E, 0x92, 0x1B, 0xCE, 0xA8, 0xA9, 0xAC, 0xF5, 0xFA, 0xAB, 0x23, 0xCB, + 0xA1, 0xD6, 0xF9, 0x09, 0x30, 0x5E, 0x7E, 0xF5, 0x24, 0x80, 0x5B, 0x5C, 0x5B, 0x3E, 0x76, 0xA6, + 0xE5, 0x21, 0x7E, 0xB3, 0x40, 0x5F, 0x75, 0xE7, 0x1D, 0x93, 0x41, 0x90, 0xF6, 0xAB, 0x98, 0x72, + 0x56, 0x8C, 0xFF, 0x06, 0xC5, 0x2C, 0xE0, 0xAE, 0xE6, 0xD0, 0x38, 0xC9, 0x3D, 0x88, 0x35, 0xF5, + 0x31, 0x36, 0x95, 0x49, 0x9C, 0x0C, 0x3F, 0x8D, 0xBC, 0xAA, 0xEC, 0x1B, 0x94, 0xCB, 0x77, 0x35, + 0xE8, 0xD8, 0xBF, 0x03, 0x81, 0xB2, 0x84, 0x06, 0x7C, 0x98, 0x58, 0x7D, 0x49, 0x7C, 0x87, 0xDF, + 0x69, 0xCB, 0xC7, 0xA4, 0x02, 0x68, 0xFD, 0x5F, 0x2C, 0x0B, 0xEB, 0xA5, 0x3A, 0xF3, 0x8F, 0x9A, + 0xA6, 0xA0, 0x10, 0x22, 0x05, 0x88, 0xFD, 0x85, 0x52, 0x14, 0x8F, 0x94, 0x2F, 0xA6, 0x1F, 0xE5, + 0x90, 0xE8, 0xFF, 0xEB, 0x1B, 0xD1, 0x76, 0x9B, 0xA2, 0x69, 0x83, 0x3F, 0x38, 0xC0, 0x58, 0x62, + 0xDA, 0x85, 0x7C, 0x59, 0xD1, 0xFD, 0x70, 0xCC, 0x16, 0xE8, 0xE5, 0x57, 0xBB, 0x2D, 0xE8, 0x99, + 0x5D, 0xC0, 0x9C, 0x07, 0x21, 0x56, 0x14, 0xEE, 0xA5, 0x28, 0x6B, 0x4E, 0x1A, 0x1E, 0x41, 0xBB, + 0x60, 0x63, 0x53, 0x5D, 0xAA, 0xB3, 0x9A, 0x7A, 0xB2, 0xAD, 0x6E, 0x2A, 0x2A, 0x6A, 0x00, 0xF7, + 0xEA, 0x92, 0xB8, 0x12, 0x73, 0x5D, 0xA7, 0x58, 0xA3, 0xE1, 0xB3, 0xB2, 0x6B, 0x79, 0x1E, 0xCD, + 0xD1, 0x1C, 0xFB, 0x89, 0xF9, 0xE5, 0xD8, 0xF9, 0x7C, 0xEA, 0xEF, 0x1D, 0x13, 0x86, 0x2E, 0xDD, + 0xFE, 0x52, 0x81, 0xC8, 0xF9, 0xE9, 0x42, 0x44, 0x36, 0x0B, 0x3C, 0xD9, 0x14, 0x09, 0x73, 0xCD, + 0x78, 0x19, 0xEF, 0x9D, 0xC5, 0x90, 0xB6, 0xE7, 0x45, 0x47, 0xEE, 0x0E, 0x7C, 0x0F, 0x5D, 0x4B, + 0xCC, 0x1D, 0x66, 0xC5, 0xC4, 0x4D, 0xAB, 0x55, 0xF0, 0x83, 0x68, 0xFE, 0x5C, 0xAB, 0x11, 0x71, + 0xB7, 0x45, 0xB4, 0x55, 0x1B, 0xDA, 0x77, 0x44, 0x07, 0x6A, 0x13, 0x99, 0xF4, 0x9D, 0x2B, 0xF8, + 0x78, 0x6B, 0x2E, 0x4C, 0x6B, 0xC5, 0x18, 0x9B, 0x7D, 0x26, 0xF8, 0x78, 0x53, 0x27, 0x14, 0x83, + 0x94, 0xA3, 0x9F, 0x5C, 0xAF, 0x84, 0x9B, 0x76, 0x9F, 0x77, 0xC8, 0x18, 0xA6, 0x00, 0x38, 0x67, + 0x6A, 0x08, 0xEE, 0xE3, 0x43, 0x3D, 0x09, 0xD9, 0xDD, 0xC9, 0x29, 0x33, 0x80, 0x56, 0x70, 0xD6, + 0x98, 0x50, 0x0C, 0x12, 0xC7, 0xF8, 0x3C, 0xC4, 0xFB, 0x9F, 0xFE, 0xFD, 0x5D, 0xAE, 0x9E, 0x1B, + 0x1E, 0x09, 0x99, 0xBC, 0xA5, 0x2A, 0x1A, 0xD0, 0x03, 0x41, 0x2D, 0xCC, 0xEB, 0x28, 0x6A, 0xCC, + 0xEE, 0x1F, 0x3F, 0x97, 0xDA, 0x97, 0xD5, 0x1A, 0xFF, 0x9B, 0xFD, 0xAC, 0x5A, 0x3F, 0xAB, 0x6F, + 0x73, 0x76, 0x5C, 0x28, 0xBE, 0x3D, 0x41, 0x01, 0x25, 0xFD, 0x3A, 0x72, 0x41, 0xA5, 0x8F, 0x99, + 0x03, 0x77, 0x11, 0x81, 0xEB, 0x35, 0x3D, 0x46, 0xA7, 0xA0, 0x1C, 0xDE, 0x9C, 0xD7, 0x8B, 0xD7, + 0x0A, 0x3C, 0x5D, 0x25, 0xEC, 0xF3, 0x3D, 0x54, 0xEF, 0x6A, 0x15, 0x59, 0x9B, 0xD5, 0x6F, 0xC5, + 0x1E, 0x7F, 0x55, 0x28, 0x50, 0x6F, 0xFA, 0xE8, 0x05, 0x59, 0x50, 0xD6, 0x80, 0x8C, 0xFD, 0x42, + 0x15, 0xEB, 0xC6, 0x0D, 0x62, 0xE2, 0xF3, 0x52, 0x76, 0xF7, 0x1A, 0xA0, 0x25, 0x34, 0x5F, 0x66, + 0xEA, 0xE7, 0xD9, 0x3A, 0x9C, 0x6C, 0x56, 0x7E, 0x13, 0x8F, 0xC7, 0xD1, 0xC1, 0x93, 0x69, 0x19, + 0x7C, 0xBE, 0xCE, 0x16, 0x6F, 0x4D, 0xDB, 0xC6, 0x80, 0x09, 0xCC, 0xB9, 0x72, 0xBA, 0x5B, 0xF3, + 0x49, 0xB1, 0x86, 0xBB, 0x49, 0xA0, 0x2C, 0xF1, 0x82, 0x88, 0x9F, 0xF7, 0x99, 0xB9, 0x2A, 0x94, + 0xE5, 0xA7, 0xB7, 0xDB, 0x7B, 0x7B, 0xBF, 0x6A, 0xDA, 0x69, 0xB5, 0x6B, 0xB9, 0x8A, 0x07, 0xF3, + 0xF8, 0x89, 0x1B, 0x9D, 0xA7, 0x46, 0x3A, 0x13, 0x04, 0xFD, 0x3A, 0x2D, 0x76, 0xCA, 0xD6, 0x00, + 0xF3, 0xED, 0x42, 0x1C, 0x98, 0x46, 0x1E, 0x50, 0xE0, 0x59, 0xE2, 0x67, 0x03, 0x7E, 0xAF, 0xEB, + 0xD3, 0x76, 0x7E, 0x01, 0xF8, 0x85, 0x33, 0x0F, 0x07, 0x99, 0x87, 0x6A, 0x37, 0xE9, 0x29, 0x30, + 0xA4, 0xE6, 0x04, 0xF0, 0x1E, 0x25, 0xE5, 0x88, 0x37, 0xF1, 0x18, 0x85, 0xE6, 0xD0, 0x53, 0x52, + 0x47, 0x45, 0xE0, 0x07, 0x0F, 0x27, 0xE1, 0x8D, 0xBB, 0x21, 0xBD, 0xA8, 0xC8, 0x93, 0xBD, 0xD3, + 0x66, 0x7C, 0xED, 0x24, 0x33, 0xE1, 0xC5, 0x5D, 0x7E, 0xE2, 0xDA, 0x71, 0x21, 0xD0, 0x3A, 0x70, + 0xB0, 0xB3, 0x70, 0x33, 0x64, 0x7B, 0x8D, 0x4E, 0x0F, 0xAA, 0x2B, 0x25, 0xBF, 0x54, 0x5C, 0x08, + 0xFD, 0x3B, 0x0A, 0xE0, 0x70, 0x2E, 0xFF, 0x4B, 0x1B, 0xA5, 0x6D, 0x19, 0x46, 0x1E, 0x84, 0xAF, + 0x32, 0x42, 0x55, 0xC9, 0xDB, 0x32, 0xC6, 0xCD, 0x06, 0x33, 0x53, 0xE5, 0x95, 0x71, 0x4E, 0xDE, + 0xE5, 0x83, 0xD2, 0x48, 0xCB, 0x32, 0x69, 0xA6, 0xFA, 0xA2, 0x8F, 0xC5, 0x45, 0x3A, 0x04, 0xEB, + 0x5B, 0xAB, 0x1B, 0x9F, 0xFF, 0xB7, 0x80, 0x50, 0x34, 0xB3, 0x17, 0xBC, 0xD3, 0x29, 0x5E, 0x53, + 0x0E, 0x98, 0xA7, 0x2D, 0x8D, 0xE0, 0xB5, 0x45, 0xEB, 0x24, 0x3D, 0xB6, 0x4E, 0xFF, 0x95, 0x6E, + 0x17, 0xAC, 0xA6, 0x8A, 0x1D, 0x6F, 0x7F, 0xDB, 0x74, 0x13, 0x81, 0x51, 0x40, 0x82, 0x8B, 0xAB, + 0x70, 0x71, 0x7F, 0x19, 0x63, 0x41, 0x1A, 0x12, 0x80, 0x97, 0x3E, 0x58, 0xFE, 0xE7, 0x9C, 0xA9, + 0x08, 0xB1, 0x41, 0x30, 0x69, 0xBA, 0xC0, 0x81, 0xE1, 0x0B, 0x87, 0x14, 0xBB, 0xD8, 0x9E, 0x4A, + 0x33, 0x92, 0x3B, 0xBD, 0x7F, 0xD4, 0x95, 0x3C, 0x2D, 0x45, 0xB1, 0x2A, 0x9B, 0x9B, 0xC2, 0x86, + 0xA0, 0x25, 0x7C, 0x94, 0x55, 0x05, 0xE5, 0x2D, 0xCB, 0xA4, 0x0B, 0x0B, 0x25, 0xBF, 0x8B, 0xFE, + 0xA0, 0xF2, 0x65, 0xA0, 0x9C, 0x90, 0x4F, 0xE1, 0xE9, 0x2B, 0x40, 0x60, 0x7F, 0x23, 0x82, 0x8A, + 0x89, 0x50, 0x72, 0x9C, 0x07, 0xBD, 0xD0, 0x84, 0x88, 0xA6, 0xB6, 0x3A, 0x43, 0x87, 0xBB, 0xDB, + 0x3E, 0x35, 0x6C, 0xBA, 0x51, 0x2E, 0xB4, 0xE7, 0xF6, 0xC4, 0x05, 0xE0, 0x95, 0x42, 0x96, 0x3E, + 0xE2, 0x39, 0xE9, 0x18, 0x8F, 0xD4, 0x9B, 0xEC, 0x18, 0x95, 0x8F, 0x79, 0xB8, 0xE3, 0xF4, 0x0D, + 0xD1, 0x15, 0x52, 0x26, 0xDA, 0x04, 0x9C, 0xA2, 0x08, 0xE4, 0x00, 0xB1, 0xD1, 0x38, 0x5C, 0x54, + 0x1E, 0xFB, 0x00, 0xFE, 0x22, 0xF8, 0x1D, 0xC6, 0x94, 0x8E, 0xA6, 0xEE, 0x6D, 0x07, 0x1F, 0x2B, + 0x06, 0x2C, 0x92, 0x6D, 0xEF, 0x86, 0x2F, 0x03, 0x7A, 0xBF, 0x05, 0x63, 0x2F, 0x43, 0x3E, 0xA7, + 0xF0, 0x5D, 0xD3, 0x82, 0xBF, 0x0B, 0xE6, 0x76, 0xEC, 0x8E, 0x5E, 0x6F, 0xD4, 0x88, 0xEF, 0xBB, + 0xED, 0xAF, 0x14, 0xC0, 0xA6, 0x51, 0x04, 0x7B, 0x60, 0x98, 0xB8, 0x7A, 0xF9, 0x1A, 0x5A, 0x28, + 0xC4, 0x40, 0x10, 0xBA, 0x4A, 0x8D, 0x0D, 0x30, 0xF9, 0x09, 0xDA, 0x6E, 0x1C, 0x78, 0xF7, 0x6A, + 0xAC, 0x2F, 0x49, 0xC6, 0x31, 0x56, 0x9D, 0x58, 0x63, 0x74, 0x6E, 0xAB, 0xA9, 0xD4, 0xF4, 0xC9, + 0x84, 0xA3, 0x9B, 0x97, 0x7A, 0x0E, 0x9E, 0xED, 0x7A, 0xC4, 0x01, 0xFB, 0xC3, 0xD6, 0x4F, 0x97, + 0x38, 0x84, 0x2F, 0x97, 0xF0, 0x33, 0x9B, 0x8A, 0x9C, 0x40, 0x23, 0x11, 0xDA, 0xC2, 0x5E, 0x28, + 0x5A, 0x78, 0x95, 0xF1, 0xB9, 0x41, 0x12, 0x4A, 0x77, 0x90, 0x86, 0xEC, 0xB3, 0xCC, 0x6D, 0x4C, + 0x40, 0x68, 0xAE, 0x40, 0x2F, 0x96, 0x9A, 0x1B, 0xA1, 0x46, 0x67, 0x1C, 0xE3, 0x54, 0xB7, 0x8A, + 0xF1, 0xAC, 0x38, 0x92, 0x1E, 0xBA, 0xD4, 0xD2, 0xCE, 0x46, 0x11, 0xA7, 0xCC, 0x73, 0xE3, 0x49, + 0x00, 0x9B, 0x93, 0xDE, 0xA6, 0x81, 0x3E, 0x85, 0x51, 0xB7, 0x43, 0x41, 0x64, 0xAC, 0x5B, 0x15, + 0xB7, 0xBC, 0x61, 0xF5, 0x87, 0xC4, 0x3D, 0xD1, 0x92, 0x57, 0x05, 0x27, 0x3E, 0x82, 0x5A, 0xCE, + 0xED, 0x5A, 0x59, 0x3B, 0x21, 0x01, 0x13, 0xB2, 0x67, 0x0F, 0x4D, 0xC4, 0x01, 0x9D, 0x19, 0x15, + 0x67, 0x02, 0xFF, 0xF7, 0xB7, 0xDD, 0xCB, 0xDB, 0x81, 0x13, 0xBA, 0x0C, 0x69, 0x32, 0x43, 0xBD, + 0x1A, 0x4F, 0xC8, 0x57, 0xD5, 0x3F, 0xE9, 0xBB, 0xC0, 0x0F, 0x98, 0xB5, 0x35, 0x65, 0x44, 0x7C, + 0x49, 0x05, 0x0B, 0x49, 0xE1, 0x6D, 0x34, 0x28, 0x2A, 0x77, 0xFE, 0x86, 0xC2, 0x87, 0x37, 0x2F, + 0x02, 0x53, 0x68, 0xC7, 0xDA, 0xF8, 0xAE, 0xA6, 0xE1, 0x47, 0xFA, 0xB8, 0xEE, 0x2D, 0x7E, 0xF0, + 0xB1, 0xE5, 0x64, 0xB6, 0x30, 0xC8, 0x0A, 0x5F, 0xB1, 0x6B, 0x11, 0xB2, 0x86, 0xD7, 0x4B, 0x0F, + 0x34, 0x4D, 0xEC, 0x5C, 0x72, 0x70, 0x05, 0xE8, 0xB4, 0x26, 0x76, 0x0F, 0x6E, 0x2D, 0x5E, 0x1E, + 0x80, 0x02, 0x6D, 0x4C, 0xCF, 0x92, 0x55, 0x5D, 0x2A, 0x2D, 0xDC, 0xBB, 0x01, 0xCD, 0x53, 0x06, + 0x02, 0xE7, 0x29, 0x1C, 0x34, 0x40, 0x88, 0x39, 0x8E, 0xD3, 0x58, 0x9A, 0x80, 0x18, 0xA1, 0xDD, + 0xC9, 0xB1, 0x59, 0x6B, 0x1D, 0xA2, 0xAE, 0xE6, 0x39, 0x1E, 0x37, 0x99, 0xFA, 0x1A, 0x88, 0x0F, + 0x26, 0x6A, 0x0D, 0xEF, 0x16, 0xE1, 0x2A, 0xEB, 0x22, 0x5D, 0x7B, 0xD3, 0x25, 0x93, 0x2C, 0x84, + 0xE5, 0x8D, 0xFA, 0xD6, 0x67, 0xE4, 0x36, 0x68, 0x80, 0x72, 0x78, 0xD3, 0x3B, 0xD1, 0xEF, 0xC0, + 0xA8, 0x1E, 0x32, 0x13, 0x2E, 0x02, 0xB1, 0xDF, 0x05, 0xA7, 0x3F, 0x7C, 0xAC, 0x5E, 0xC2, 0x15, + 0x4B, 0xD0, 0x94, 0xA1, 0x3C, 0x6C, 0x65, 0xDF, 0x6B, 0x05, 0x1F, 0x09, 0x09, 0x7D, 0xEA, 0x11, + 0x38, 0x85, 0x12, 0x7F, 0xE2, 0x0C, 0x8E, 0xF5, 0xED, 0xF8, 0x24, 0x6F, 0xCA, 0xDB, 0xDA, 0x65, + 0x08, 0xCA, 0x1F, 0x17, 0x3E, 0xFF, 0x68, 0x7B, 0xAA, 0x12, 0xDD, 0x98, 0x65, 0x94, 0x14, 0x63, + 0x8A, 0xC7, 0x56, 0xE2, 0x07, 0x2A, 0x53, 0xAB, 0xA9, 0x42, 0xB9, 0xF9, 0xBE, 0x38, 0x06, 0xB7, + 0xD1, 0xE6, 0xDF, 0x5A, 0xE3, 0x83, 0xFF, 0xE1, 0xAF, 0xE1, 0xF7, 0x89, 0xE9, 0x3B, 0xDC, 0x9A, + 0x23, 0x3B, 0x4C, 0xD1, 0xC6, 0xA0, 0xD5, 0x40, 0x01, 0x20, 0x7D, 0x2B, 0xEB, 0x60, 0x8E, 0x40, + 0x62, 0xC9, 0x26, 0xD7, 0x1C, 0xE6, 0x6D, 0xB6, 0x87, 0xC4, 0xCE, 0x19, 0xFC, 0xBB, 0x59, 0x3A, + 0x66, 0x21, 0x22, 0x91, 0x0C, 0x59, 0x66, 0x54, 0x4D, 0x86, 0xCA, 0xA2, 0x11, 0x72, 0xB6, 0xE6, + 0x04, 0x50, 0x25, 0x38, 0x9F, 0x87, 0x40, 0x9C, 0x5C, 0xB4, 0xFC, 0xD1, 0x04, 0xC0, 0xE1, 0xE2, + 0xC9, 0xFB, 0xD2, 0xBC, 0xE7, 0xB2, 0x38, 0x6B, 0x98, 0xAB, 0x90, 0x24, 0xBB, 0xB0, 0x45, 0xBA, + 0xEB, 0x29, 0xBD, 0xA6, 0xCD, 0xCC, 0x91, 0x7A, 0xEA, 0x2E, 0x84, 0x78, 0x6E, 0x07, 0x78, 0x1D, + 0x73, 0x14, 0xC4, 0x1F, 0x3D, 0x75, 0x72, 0x8E, 0xA0, 0x70, 0xE9, 0x93, 0xC2, 0x2C, 0x2F, 0x98, + 0x46, 0x07, 0x07, 0x12, 0x32, 0xFE, 0xDE, 0x2E, 0x24, 0xD5, 0xD0, 0xA3, 0x5A, 0x0C, 0xB4, 0x1D, + 0xD7, 0x57, 0xAB, 0x51, 0xAE, 0x0A, 0x19, 0xBD, 0x0D, 0x0B, 0xCA, 0x8A, 0x3B, 0x64, 0xFB, 0xF5, + 0x43, 0xC5, 0x04, 0xB1, 0x16, 0xC5, 0x34, 0xF7, 0x63, 0xEF, 0xC9, 0xBA, 0x94, 0x6A, 0xA4, 0x04, + 0x49, 0xB8, 0xF4, 0xF5, 0x3C, 0x0D, 0x84, 0xC3, 0x4B, 0xDE, 0xF1, 0xD5, 0x62, 0x15, 0x76, 0x84, + 0xED, 0xA4, 0x8A, 0x25, 0x3D, 0x87, 0xB7, 0xEA, 0x26, 0xDA, 0xCE, 0xB8, 0x7E, 0x8A, 0xDB, 0xAB, + 0x70, 0xB1, 0x18, 0x53, 0xEA, 0xF4, 0x74, 0xCB, 0x9A, 0x2B, 0x10, 0x5A, 0x4F, 0x06, 0x2B, 0x6B, + 0x4A, 0xF0, 0xF3, 0xB2, 0x10, 0x14, 0x9D, 0xBD, 0x18, 0x46, 0x3E, 0x7F, 0xAD, 0xB3, 0x03, 0xDD, + 0x80, 0xE2, 0xA5, 0x5D, 0x87, 0xAD, 0x67, 0x1C, 0x20, 0x06, 0xFD, 0x62, 0x65, 0x5D, 0x12, 0xC5, + 0x0A, 0x8C, 0x99, 0x8B, 0x97, 0xA1, 0x1F, 0x06, 0x8A, 0x78, 0x7A, 0xA5, 0x46, 0x65, 0xA8, 0xFA, + 0xC4, 0x81, 0x99, 0x02, 0x16, 0x7C, 0xB4, 0x09, 0xAD, 0xE8, 0x35, 0x2E, 0x6B, 0x4F, 0x55, 0xAC, + 0x23, 0x41, 0xA8, 0x5A, 0x0C, 0x71, 0x7E, 0x08, 0x3E, 0x6D, 0x5B, 0x46, 0x92, 0x3B, 0x8B, 0x8C, + 0xBE, 0x09, 0x52, 0xEA, 0xC5, 0xAE, 0x1B, 0x2A, 0xC8, 0x2D, 0x36, 0xE7, 0x2E, 0xCF, 0xA6, 0x30, + 0x9F, 0x14, 0xB2, 0xFA, 0xA2, 0xA3, 0xFF, 0xC7, 0x0B, 0xA6, 0xC8, 0x8C, 0xCD, 0xB3, 0x0B, 0xFC, + 0x76, 0x9F, 0xA1, 0xB9, 0x34, 0x86, 0xB5, 0x5B, 0x4C, 0x3D, 0x87, 0xA0, 0x5D, 0xE2, 0x95, 0x65, + 0xCF, 0xCD, 0x16, 0x40, 0x7D, 0x1B, 0xB1, 0xB8, 0x83, 0x37, 0x14, 0x6E, 0x02, 0xB2, 0x8E, 0x17, + 0x9E, 0x10, 0x87, 0x83, 0x62, 0x57, 0x60, 0x98, 0xA7, 0xE5, 0xCB, 0x82, 0x6E, 0xCC, 0xC7, 0x63, + 0x99, 0xB8, 0x1D, 0xA9, 0xED, 0x5B, 0xE9, 0x0E, 0xC8, 0x7D, 0xCE, 0x48, 0xE4, 0xE4, 0x3F, 0x1C, + 0x77, 0xBF, 0xEF, 0x3A, 0x63, 0x25, 0xAA, 0xDE, 0x2D, 0xC2, 0x42, 0x22, 0xEC, 0x99, 0xB6, 0xBF, + 0x65, 0xA0, 0x2A, 0x5C, 0x51, 0x63, 0x9D, 0xFB, 0x3F, 0xA0, 0x7E, 0x2B, 0xCC, 0x04, 0xE1, 0x74, + 0x13, 0x61, 0x80, 0x15, 0x3C, 0x2F, 0x9E, 0x3E, 0x63, 0x24, 0xA2, 0x13, 0xF9, 0xCD, 0xF6, 0xA9, + 0x88, 0x3A, 0xC9, 0x1F, 0xE9, 0xF2, 0x5F, 0x04, 0xD3, 0xE7, 0x00, 0x4B, 0xCD, 0xA5, 0x60, 0xBE, + 0x49, 0x89, 0xCC, 0x68, 0x48, 0x51, 0xEC, 0x7D, 0x8B, 0xDD, 0x23, 0xF0, 0x5D, 0xDC, 0x46, 0xA7, + 0x35, 0x77, 0xBF, 0x2D, 0x5C, 0xDB, 0x8B, 0x11, 0xE9, 0x15, 0xE6, 0xC7, 0x50, 0xEF, 0x01, 0x5A, + 0x4D, 0x04, 0x5D, 0xBF, 0xF9, 0x52, 0x36, 0xDE, 0x74, 0xE5, 0xF6, 0xF3, 0x37, 0x45, 0x28, 0x85, + 0x86, 0x9E, 0x1E, 0xFA, 0xF9, 0xB9, 0x1A, 0x04, 0xD7, 0xE7, 0xCB, 0xDC, 0x47, 0xFB, 0x49, 0x34, + 0x3A, 0x63, 0x26, 0x2D, 0x73, 0x6F, 0xC6, 0x28, 0xEE, 0x83, 0xBD, 0x8F, 0x2D, 0xF2, 0x1A, 0x19, + 0x75, 0x1B, 0xB6, 0x60, 0x4C, 0x38, 0x3D, 0xD7, 0x4D, 0x66, 0x7F, 0x01, 0xCF, 0x20, 0x1D, 0x45, + 0xD5, 0x32, 0x24, 0x96, 0x15, 0x0E, 0x5C, 0x6A, 0xD3, 0xE9, 0xC5, 0xD1, 0xF9, 0x11, 0x94, 0x41, + 0xD0, 0xC8, 0xBD, 0xBD, 0x17, 0xFB, 0x0A, 0x20, 0x89, 0x05, 0xBA, 0xCB, 0xF6, 0xBF, 0x9E, 0x83, + 0x44, 0x04, 0x54, 0x54, 0xA3, 0xDC, 0x1D, 0xEF, 0x3C, 0x01, 0x07, 0x80, 0x8A, 0x4F, 0x15, 0x3E, + 0x2D, 0xFE, 0xAF, 0xEB, 0x71, 0xA3, 0xE7, 0x20, 0x56, 0x2A, 0x19, 0x37, 0x8C, 0xDA, 0xE2, 0xB2, + 0xAB, 0xB4, 0x39, 0x3C, 0xC6, 0x7C, 0x7D, 0xD2, 0x91, 0xBE, 0x62, 0xF8, 0x4D, 0x01, 0x4E, 0xB4, + 0x3A, 0x19, 0xE2, 0x3E, 0x26, 0xD6, 0x2A, 0x55, 0x96, 0xC0, 0x0F, 0xA5, 0x35, 0x28, 0x0A, 0x5C, + 0xC1, 0x55, 0xD3, 0x72, 0x60, 0xF9, 0x65, 0xD0, 0xB2, 0x6C, 0x58, 0xAF, 0x8B, 0x00, 0x2B, 0x4C, + 0xF0, 0x4E, 0x8D, 0x15, 0x2F, 0xE5, 0x93, 0x05, 0x94, 0xF0, 0x02, 0x80, 0xDF, 0xFA, 0xEA, 0xA8, + 0xE8, 0x93, 0x50, 0xEB, 0xE1, 0x4D, 0x26, 0x34, 0xD3, 0x33, 0x83, 0x64, 0x30, 0x7D, 0x19, 0x51, + 0x50, 0x79, 0xF5, 0xF1, 0xD1, 0x2F, 0x7C, 0xC9, 0xF0, 0x3F, 0xF8, 0x60, 0x3B, 0x7E, 0x5D, 0x06, + 0x63, 0xED, 0x92, 0x0D, 0x0F, 0xD8, 0x9C, 0x6F, 0x74, 0x40, 0xF1, 0x40, 0xEC, 0x81, 0xAD, 0xAE, + 0xF0, 0xB2, 0x5E, 0x79, 0x71, 0x99, 0x89, 0x4F, 0xB9, 0xB2, 0x82, 0x15, 0x0D, 0x80, 0x7A, 0x68, + 0x13, 0x85, 0x4A, 0x6C, 0x6B, 0x1B, 0xD3, 0xA7, 0x67, 0x84, 0x14, 0xC5, 0xCE, 0xC9, 0xF2, 0x61, + 0x45, 0x7E, 0xEE, 0x7E, 0x6F, 0xD4, 0xB5, 0x15, 0xEE, 0x2C, 0x6C, 0xCC, 0x9D, 0x88, 0x38, 0x55, + 0x65, 0x78, 0xCF, 0x65, 0x8D, 0x2F, 0x22, 0xDD, 0xD9, 0x58, 0x9B, 0x60, 0x48, 0xEB, 0x96, 0xD5, + 0x17, 0xEE, 0x40, 0xFC, 0xA1, 0x9C, 0x70, 0x51, 0x2B, 0x0F, 0xCB, 0x80, 0x2C, 0x4A, 0x28, 0x4E, + 0x49, 0xAF, 0xA0, 0x6D, 0xA5, 0xF7, 0x58, 0x7E, 0x23, 0x30, 0xE9, 0x22, 0xE5, 0xC0, 0xD5, 0x65, + 0x13, 0xE6, 0xC1, 0x71, 0x94, 0xAF, 0xDE, 0x6A, 0x53, 0x4C, 0xDE, 0xB8, 0x35, 0xFE, 0x1F, 0xF0, + 0x51, 0x61, 0x5F, 0xC2, 0xA4, 0xA9, 0x66, 0x92, 0x93, 0x89, 0xC2, 0x4E, 0xDB, 0x7B, 0x9C, 0x11, + 0x62, 0xE5, 0xE6, 0xD7, 0x86, 0xD0, 0x8B, 0x33, 0x9E, 0x15, 0x78, 0x11, 0xF1, 0xC9, 0xA6, 0x4B, + 0xA9, 0xB8, 0x38, 0xDE, 0xB2, 0x55, 0xB6, 0x0E, 0xEF, 0x6E, 0xC9, 0xC8, 0x5A, 0x39, 0x1C, 0xEE, + 0x0F, 0x5C, 0x83, 0x2A, 0x46, 0x22, 0x4C, 0xA6, 0xD3, 0x38, 0xBA, 0x19, 0xA6, 0xB5, 0x70, 0x80, + 0xCF, 0x84, 0x6B, 0x02, 0x98, 0xAB, 0x4C, 0x48, 0x4F, 0xF2, 0x19, 0xDB, 0xBB, 0xB3, 0x1E, 0x21, + 0x41, 0xD2, 0x67, 0x16, 0x05, 0xC9, 0x21, 0x03, 0x3C, 0xC5, 0x7C, 0x0E, 0x85, 0xD8, 0x6F, 0x9D, + 0x57, 0x12, 0xE4, 0xC7, 0xCB, 0x73, 0xC3, 0xFE, 0xA3, 0x9E, 0xCD, 0x4D, 0x50, 0x4F, 0x4F, 0xDE, + 0x4A, 0x54, 0x17, 0x64, 0x6B, 0x13, 0x07, 0x7D, 0x48, 0x14, 0x92, 0x4D, 0x29, 0x1C, 0xF9, 0x4D, + 0xB9, 0xAE, 0x56, 0xF8, 0xF5, 0xCB, 0x8B, 0x8B, 0x0E, 0xD1, 0x91, 0xD5, 0xE5, 0xB9, 0x2B, 0xA5, + 0x1E, 0x55, 0x2C, 0xC3, 0x48, 0x31, 0x81, 0x7C, 0xD1, 0x36, 0x36, 0x52, 0x59, 0xC6, 0xCA, 0xEB, + 0x65, 0x8E, 0x89, 0x1A, 0x65, 0xC8, 0xF3, 0xC4, 0x67, 0x2B, 0x5A, 0xD3, 0xD4, 0x35, 0x01, 0x4A, + 0x2C, 0xA8, 0x7F, 0xA2, 0xC2, 0x52, 0xA1, 0x2C, 0xB2, 0x55, 0x7C, 0x5C, 0xF9, 0xC2, 0xD2, 0x77, + 0x5E, 0xF3, 0x31, 0xFD, 0xD7, 0x79, 0x8D, 0x0E, 0xE1, 0x37, 0x87, 0xC9, 0x47, 0x43, 0x4E, 0xA9, + 0x7D, 0x9E, 0x51, 0x83, 0x57, 0x15, 0x4E, 0x6A, 0x43, 0x1F, 0xC8, 0x83, 0xA3, 0x31, 0xE8, 0x19, + 0x7E, 0xC3, 0x0D, 0x2A, 0x3A, 0x15, 0x85, 0xBE, 0x16, 0xA3, 0x4C, 0xCD, 0xC6, 0x1A, 0xB1, 0x48, + 0xDB, 0x02, 0xED, 0xA6, 0xFF, 0x9B, 0xC2, 0x6E, 0x7C, 0x3B, 0xC6, 0xCC, 0x8F, 0x0C, 0xDB, 0xE0, + 0x11, 0x66, 0xDA, 0x0F, 0x85, 0x68, 0x25, 0x34, 0x7A, 0x7C, 0x4D, 0x13, 0x19, 0xA7, 0x37, 0xBA, + 0x1B, 0x8A, 0xBA, 0x99, 0x0B, 0x39, 0x7D, 0x37, 0xA6, 0x32, 0x81, 0xD3, 0x73, 0x21, 0x6E, 0x4A, + 0x32, 0x26, 0xC5, 0xE6, 0x8F, 0x33, 0x52, 0x48, 0x23, 0x4A, 0x21, 0xBD, 0xF9, 0x12, 0xC0, 0xFD, + 0xDC, 0x39, 0x1B, 0x4B, 0xCE, 0x56, 0x44, 0xC4, 0x9B, 0x9C, 0xF4, 0xBE, 0xC0, 0x9A, 0xFD, 0x28, + 0xA1, 0xB2, 0xAE, 0xA7, 0xFB, 0x31, 0xB6, 0xF6, 0x62, 0x68, 0xC9, 0x44, 0xCA, 0x0F, 0x51, 0xFF, + 0xCB, 0x7C, 0x67, 0xAE, 0xF4, 0xFD, 0xC0, 0x71, 0x50, 0x35, 0x65, 0xF3, 0x9C, 0x08, 0xA0, 0x1B, + 0x3B, 0x42, 0x69, 0x95, 0x42, 0x7A, 0xE3, 0x87, 0xF3, 0xD6, 0xE9, 0xA7, 0x22, 0x5B, 0x83, 0x0B, + 0x5B, 0xE9, 0x0A, 0x0A, 0xFA, 0x2D, 0x82, 0x42, 0x73, 0xDF, 0x76, 0xAF, 0xE6, 0xD3, 0x9D, 0xB1, + 0xA4, 0xD8, 0xB6, 0xC5, 0x5F, 0xC7, 0x98, 0xCC, 0x80, 0xA3, 0xB7, 0x67, 0xF4, 0x28, 0xA4, 0x98, + 0xB5, 0x5D, 0xB3, 0x0E, 0x77, 0xF4, 0xD0, 0x7E, 0xE2, 0x1C, 0xE2, 0x6B, 0xB4, 0x67, 0x42, 0x40, + 0xCB, 0x5A, 0x59, 0x43, 0x80, 0xA4, 0x92, 0xEC, 0xEB, 0x1E, 0xFB, 0x08, 0xFA, 0x17, 0xFE, 0x5E, + 0xF5, 0xD5, 0x1E, 0x12, 0xEB, 0xE8, 0x91, 0x78, 0x0E, 0x13, 0x67, 0xF9, 0x51, 0x0B, 0xBF, 0xA6, + 0x9B, 0x19, 0x26, 0x1D, 0xAE, 0xF7, 0x3A, 0xBB, 0xD7, 0x61, 0x62, 0xFA, 0xDB, 0x75, 0x26, 0x34, + 0xB7, 0xAF, 0x8C, 0xDD, 0xF5, 0xC1, 0x1C, 0x65, 0x23, 0xF2, 0xEC, 0x58, 0xA1, 0x9E, 0x82, 0x66, + 0x58, 0x4C, 0xF8, 0x44, 0x20, 0x87, 0x26, 0xCA, 0x09, 0xD6, 0xCD, 0x19, 0x4C, 0x39, 0x2A, 0x63, + 0xC8, 0xE2, 0x04, 0x18, 0x32, 0xBC, 0x87, 0x39, 0x7A, 0x0A, 0x59, 0xAA, 0xD5, 0xEB, 0xAE, 0x20, + 0x10, 0x9A, 0xBD, 0xB5, 0x14, 0xFC, 0x59, 0xCE, 0x86, 0x96, 0x42, 0x4A, 0xB0, 0xAE, 0xA5, 0x65, + 0x56, 0x34, 0x04, 0x13, 0x7C, 0xA0, 0x8B, 0x44, 0x11, 0xCE, 0xC3, 0x3C, 0x32, 0x56, 0xE4, 0xE0, + 0xFC, 0xAF, 0x7E, 0x89, 0xFB, 0x44, 0x4A, 0x34, 0x1C, 0x02, 0x7F, 0x69, 0xF1, 0x38, 0x8B, 0x3C, + 0x23, 0x54, 0x4A, 0xD8, 0xF5, 0x69, 0x70, 0xCA, 0x04, 0x99, 0x2A, 0xB0, 0x66, 0x22, 0x55, 0x14, + 0x82, 0x2A, 0x4B, 0x63, 0xA5, 0x05, 0x1E, 0x62, 0x49, 0x6B, 0xC1, 0x83, 0x6B, 0xA5, 0x74, 0xDD, + 0x20, 0x26, 0xAD, 0xDD, 0xD1, 0x37, 0x2C, 0x7E, 0x36, 0xE0, 0xBF, 0xC1, 0xEA, 0x37, 0x89, 0x5F, + 0x74, 0x6F, 0xAC, 0x05, 0x71, 0x94, 0x8D, 0x79, 0x1B, 0xAB, 0x03, 0xD9, 0x96, 0x9E, 0x40, 0x69, + 0x47, 0x23, 0x77, 0x35, 0x35, 0x60, 0x6C, 0xAA, 0x0B, 0x07, 0xC7, 0x64, 0xF7, 0x7F, 0x43, 0x6B, + 0x02, 0x69, 0x41, 0xCA, 0x1B, 0x51, 0xD9, 0x87, 0xEB, 0x36, 0xDD, 0x9E, 0xFF, 0xA1, 0x50, 0x6A, + 0x33, 0x5F, 0x25, 0x04, 0x97, 0x46, 0x99, 0x4D, 0xA4, 0x37, 0xD9, 0xA2, 0x23, 0x6E, 0x4C, 0x1B, + 0x36, 0xED, 0x9F, 0x09, 0x30, 0x26, 0xAB, 0x6F, 0x98, 0x0F, 0xF6, 0x13, 0x44, 0x4F, 0xF1, 0x61, + 0x73, 0x53, 0x39, 0x90, 0x88, 0xAE, 0x32, 0xC7, 0x33, 0x6B, 0x1A, 0xA1, 0xE8, 0x6F, 0x82, 0x99, + 0x73, 0x20, 0x44, 0xCF, 0x27, 0x17, 0xF8, 0x88, 0x19, 0x45, 0xD2, 0x41, 0x0A, 0xDB, 0x68, 0xA8, + 0x59, 0xBC, 0x73, 0xF7, 0xF1, 0x2D, 0x58, 0xBA, 0x60, 0x26, 0xA2, 0xB8, 0x93, 0x31, 0x32, 0xAB, + 0x13, 0xDE, 0x61, 0x0D, 0xD7, 0xA0, 0xFC, 0x44, 0x2A, 0xEE, 0xA3, 0xCF, 0x37, 0x17, 0xF9, 0xF8, + 0x63, 0x5A, 0x0C, 0x94, 0x78, 0x57, 0x24, 0xC0, 0x20, 0x12, 0xDA, 0xF0, 0x91, 0x22, 0x0D, 0x8E, + 0x3D, 0x48, 0xA0, 0x41, 0xFC, 0x65, 0x34, 0x0A, 0x4B, 0xE4, 0xFF, 0xEE, 0xB9, 0xF6, 0xD5, 0x48, + 0x60, 0xD1, 0x08, 0x75, 0x19, 0x7D, 0x23, 0xE6, 0x48, 0x80, 0xA4, 0x80, 0x72, 0x25, 0xE8, 0xF5, + 0x08, 0xFA, 0x70, 0xB5, 0x93, 0x6C, 0xA0, 0xFD, 0x28, 0xD4, 0xC6, 0xB5, 0xE3, 0x6D, 0x70, 0x6B, + 0x6D, 0x3F, 0x61, 0x01, 0xEB, 0xC9, 0xE7, 0xE1, 0x55, 0x67, 0x43, 0xE7, 0xBE, 0x1B, 0xE5, 0xA6, + 0xB7, 0x6C, 0x8F, 0x6D, 0xE4, 0x22, 0xCF, 0x8C, 0x6C, 0x67, 0xE6, 0xF3, 0xEC, 0x07, 0xB3, 0xE9, + 0x51, 0xBE, 0xBD, 0xC8, 0xCE, 0x67, 0xF2, 0x14, 0x7B, 0xDD, 0x8C, 0x70, 0x6E, 0x4C, 0x3E, 0x1E, + 0xA6, 0xCB, 0xD7, 0x4B, 0x0F, 0x61, 0x76, 0x39, 0x91, 0xE9, 0xD2, 0x43, 0x51, 0x8E, 0x86, 0x82, + 0x7B, 0xB2, 0xCD, 0xF6, 0x0E, 0x74, 0x0F, 0xA3, 0xD4, 0x25, 0xC2, 0x16, 0xCB, 0xFB, 0x8A, 0x2A, + 0x0B, 0xFA, 0xCF, 0xC0, 0x99, 0x38, 0x48, 0xCD, 0x87, 0xB6, 0x39, 0x74, 0x5C, 0x9F, 0x0A, 0x12, + 0xA7, 0x42, 0x1B, 0xF2, 0xBC, 0x9A, 0x38, 0x12, 0xA1, 0x5F, 0x64, 0x54, 0x2A, 0x0C, 0xFB, 0xF9, + 0xF0, 0xB3, 0x4B, 0xC5, 0xD1, 0xAE, 0x15, 0x52, 0x14, 0xDE, 0x91, 0x16, 0x38, 0xAF, 0x01, 0x16, + 0x8D, 0x29, 0x3E, 0xFE, 0x62, 0xF3, 0x57, 0x10, 0x6C, 0x21, 0x10, 0x9F, 0x8F, 0x4C, 0xF9, 0xE8, + 0x7F, 0x77, 0xFF, 0xF7, 0x01, 0x53, 0x7E, 0xB8, 0xC3, 0xFC, 0x88, 0xF1, 0xB1, 0x5A, 0x63, 0xAB, + 0xC2, 0x78, 0x8C, 0x15, 0x96, 0x61, 0xC7, 0x88, 0xC5, 0x45, 0x16, 0xE9, 0xE1, 0xD5, 0x77, 0xB4, + 0xC9, 0xA6, 0xAB, 0x47, 0xEE, 0x86, 0xFE, 0xD1, 0x2C, 0xAB, 0x23, 0x18, 0xA7, 0xB0, 0x4D, 0x18, + 0x52, 0xB7, 0xEF, 0x68, 0xCB, 0x80, 0xF9, 0x05, 0x15, 0x7A, 0xCB, 0x61, 0xC5, 0xCE, 0xCF, 0x92, + 0x3B, 0xCA, 0x7C, 0xEC, 0x02, 0x6F, 0x6B, 0x1E, 0x27, 0xAC, 0x07, 0xF2, 0x63, 0xB8, 0xDC, 0x1C, + 0x6A, 0x52, 0xB5, 0xF2, 0x90, 0xEB, 0x16, 0xA1, 0x2C, 0x9C, 0x3D, 0x20, 0x4B, 0xB3, 0xB9, 0x3B, + 0xD3, 0xE0, 0x7A, 0xCC, 0x9E, 0xF8, 0x95, 0x32, 0x2A, 0x34, 0x4A, 0xBC, 0x1E, 0x21, 0x05, 0x02, + 0x1A, 0xF4, 0x19, 0x32, 0x7B, 0x4A, 0x08, 0x15, 0x1B, 0xB1, 0xD5, 0x25, 0x53, 0x78, 0x99, 0xD8, + 0x9D, 0x8E, 0x45, 0xAE, 0x44, 0x52, 0x90, 0xC3, 0x89, 0xE7, 0xA5, 0x3E, 0xFA, 0xBC, 0x1C, 0x43, + 0x7B, 0x2E, 0x6B, 0x26, 0x84, 0x19, 0xA7, 0x4D, 0xDC, 0xD6, 0x4D, 0x29, 0x0F, 0x3A, 0xA5, 0xBC, + 0x09, 0x07, 0x53, 0x20, 0x8E, 0xE2, 0x91, 0x38, 0x73, 0x70, 0xA0, 0xAE, 0x10, 0xE0, 0x62, 0x49, + 0xAD, 0x71, 0x64, 0xC7, 0x8F, 0x15, 0x04, 0x42, 0xB4, 0xA6, 0x37, 0xEB, 0x9A, 0xB2, 0x00, 0x20, + 0xC6, 0x55, 0x3C, 0x14, 0xAB, 0xC2, 0x15, 0xF5, 0xB7, 0x79, 0x81, 0x5D, 0x36, 0xC2, 0xEC, 0xBA, + 0xC3, 0xB5, 0xAC, 0xF5, 0x2A, 0x92, 0x2A, 0xAC, 0x4D, 0x7F, 0x71, 0x5A, 0xFE, 0x74, 0xAC, 0xFE, + 0x70, 0x58, 0x9F, 0x61, 0x10, 0x95, 0xED, 0x04, 0xF7, 0x1E, 0x49, 0x99, 0xCD, 0xAB, 0x2C, 0x3A, + 0x8F, 0x00, 0x26, 0x48, 0x5F, 0x0F, 0x80, 0xFF, 0x72, 0x05, 0x82, 0xE4, 0xDD, 0x6F, 0x7C, 0xDA, + 0x42, 0x91, 0x94, 0x57, 0x8F, 0xC0, 0xA7, 0xBA, 0x46, 0x8C, 0x15, 0xE9, 0xEA, 0x5E, 0xCD, 0xE7, + 0x63, 0xB3, 0x15, 0x50, 0x5E, 0x71, 0x35, 0xEE, 0x84, 0xFA, 0x23, 0x4B, 0xEE, 0x5B, 0x99, 0xDF, + 0x0D, 0xE5, 0x69, 0xC7, 0xD7, 0xF7, 0x49, 0xC4, 0xEF, 0x19, 0x88, 0x57, 0xB5, 0x4F, 0x3E, 0x18, + 0xF9, 0x61, 0x1A, 0xFE, 0xFB, 0x15, 0xE3, 0x65, 0x49, 0x19, 0x17, 0xBA, 0xC0, 0x26, 0x8A, 0x5E, + 0x8D, 0x29, 0x50, 0x62, 0x19, 0x6E, 0xFA, 0x22, 0x7E, 0xEA, 0xE6, 0x2F, 0x90, 0xEF, 0x71, 0x21, + 0xAD, 0x2A, 0xFC, 0x97, 0xBA, 0xC7, 0x71, 0x7D, 0x68, 0x1C, 0x53, 0xB1, 0xD4, 0x59, 0xED, 0xE1, + 0x56, 0x54, 0xD1, 0x89, 0xC4, 0xB0, 0xB8, 0x88, 0x78, 0xCA, 0xF7, 0x85, 0x7E, 0xA0, 0xE8, 0xF4, + 0xE5, 0x12, 0xE8, 0x24, 0x9A, 0x51, 0xE9, 0xA3, 0x52, 0x96, 0x59, 0x47, 0x07, 0x63, 0xAE, 0x18, + 0x41, 0xAB, 0x17, 0xE8, 0x94, 0xDF, 0x94, 0x2F, 0x8F, 0x36, 0x34, 0x91, 0x20, 0x52, 0xE0, 0x11, + 0x2E, 0xFF, 0xBD, 0xBD, 0x6E, 0x49, 0xE2, 0x41, 0xA6, 0xD0, 0x10, 0xD0, 0x2C, 0xE4, 0x2E, 0x9F, + 0xBF, 0x36, 0xAD, 0xDA, 0xA5, 0xFE, 0xD9, 0xEC, 0xC1, 0x55, 0x20, 0xCB, 0x10, 0xAD, 0x4D, 0xE3, + 0xD2, 0xE7, 0x09, 0xFB, 0x14, 0xC2, 0x11, 0x33, 0x2C, 0xFA, 0xDE, 0x82, 0x15, 0x4D, 0xF0, 0xB6, + 0x71, 0x3C, 0x58, 0x80, 0xD2, 0x87, 0x05, 0x89, 0xEF, 0x00, 0x6C, 0x8A, 0xFB, 0x14, 0xF3, 0x65, + 0x22, 0xCD, 0xBF, 0x25, 0x03, 0x60, 0x12, 0x38, 0x2B, 0x0A, 0xF1, 0xFB, 0xCB, 0x80, 0x11, 0x3B, + 0x59, 0xE2, 0xEF, 0x07, 0xC8, 0x97, 0x50, 0xFE, 0x56, 0x4C, 0x52, 0x4F, 0x73, 0xD9, 0xCA, 0x89, + 0x7B, 0xEA, 0x50, 0x5E, 0xCB, 0xB9, 0xEE, 0xC8, 0xFF, 0xC5, 0x13, 0x62, 0x00, 0x9F, 0xBF, 0x61, + 0xC7, 0x2F, 0x0F, 0xBF, 0x75, 0xC3, 0x0E, 0x72, 0x2C, 0xF7, 0xDF, 0xA5, 0xAE, 0x94, 0x15, 0x8F, + 0xBB, 0x1D, 0x26, 0xA0, 0xCB, 0x8B, 0x40, 0x78, 0x48, 0xB4, 0x41, 0x47, 0x6B, 0x7D, 0x45, 0xBE, + 0x39, 0xA5, 0xE2, 0xB7, 0x11, 0xEF, 0xE8, 0x19, 0xA0, 0x62, 0x26, 0xE1, 0xD5, 0x94, 0x54, 0x9D, + 0xA4, 0x28, 0xEE, 0x7F, 0x7F, 0x25, 0xAD, 0xDB, 0x28, 0x2C, 0xDB, 0xA7, 0x63, 0xF8, 0x0E, 0x6E, + 0xE2, 0x0F, 0x8F, 0xC7, 0x17, 0x31, 0xB2, 0x8D, 0xA8, 0x92, 0x7A, 0x81, 0xD5, 0x88, 0x2E, 0xD3, + 0xF2, 0xE5, 0x08, 0x76, 0xC7, 0x93, 0xDB, 0xC0, 0x0B, 0x38, 0x58, 0xF7, 0x6F, 0xC4, 0x58, 0xAD, + 0xB0, 0x3B, 0xDC, 0xE6, 0xD1, 0xB3, 0xC2, 0x39, 0x25, 0xE7, 0x48, 0x19, 0xC8, 0x27, 0xD1, 0xDF, + 0x9F, 0x5F, 0xB8, 0x5A, 0x50, 0xE9, 0x0B, 0x51, 0x43, 0x2C, 0xA6, 0x09, 0x39, 0x14, 0xF5, 0x3E, + 0x03, 0x6E, 0x55, 0x7D, 0xE3, 0x42, 0xE5, 0xBB, 0x40, 0xA0, 0x71, 0xAA, 0xF1, 0xAF, 0x6E, 0xF2, + 0xE2, 0x59, 0x94, 0xF2, 0x9F, 0x79, 0x67, 0x23, 0x6F, 0xCA, 0x85, 0xF6, 0x1F, 0xA3, 0x87, 0x7B, + 0xE6, 0x62, 0xEE, 0x8F, 0x0D, 0x48, 0x89, 0x98, 0x37, 0x35, 0x91, 0x05, 0x58, 0xA3, 0x83, 0x28, + 0x13, 0xA2, 0x1E, 0xD1, 0x49, 0x5F, 0x68, 0x59, 0x47, 0x49, 0xED, 0x7B, 0xC2, 0x45, 0x58, 0xCB, + 0xB7, 0xC8, 0x91, 0x3B, 0xF5, 0xB4, 0xC4, 0x8C, 0x01, 0xE3, 0x78, 0x3A, 0x3D, 0xD9, 0x58, 0x0B, + 0xA3, 0xB2, 0x8C, 0xFA, 0xF1, 0x8C, 0xC5, 0x77, 0x93, 0xC9, 0x88, 0x80, 0x67, 0xB5, 0x62, 0x55, + 0x6E, 0x01, 0x74, 0xF3, 0x81, 0x9E, 0xAE, 0x27, 0xB0, 0x20, 0xC6, 0xE1, 0xAE, 0xE7, 0xBB, 0x8D, + 0x12, 0x27, 0x6D, 0x23, 0xF3, 0x1D, 0xCD, 0x5E, 0x20, 0xAC, 0x10, 0x06, 0x1D, 0x3C, 0xB4, 0x86, + 0xB7, 0x0E, 0x8C, 0x9D, 0x14, 0xD5, 0xAC, 0xFF, 0xFE, 0xE5, 0x6B, 0xEB, 0xED, 0x3F, 0xF5, 0x40, + 0xBA, 0x69, 0x66, 0x90, 0xFA, 0x54, 0xAC, 0xB9, 0xCB, 0x07, 0x38, 0xAF, 0xE4, 0x40, 0x41, 0x0C, + 0x0A, 0x44, 0x2D, 0x31, 0x46, 0x4E, 0x2B, 0x75, 0xFA, 0x06, 0xA3, 0x59, 0xC3, 0x27, 0x53, 0xFC, + 0xB6, 0xEF, 0xBA, 0x10, 0xAA, 0x65, 0x1D, 0x1C, 0xAB, 0x19, 0x8C, 0x54, 0x1D, 0x3B, 0xBB, 0x10, + 0x05, 0xAA, 0xAE, 0xEF, 0x80, 0x03, 0x28, 0xA7, 0x4D, 0xA9, 0xD8, 0xA8, 0x34, 0x75, 0xC6, 0x2B, + 0x43, 0x82, 0x59, 0x00, 0x2E, 0xEE, 0xF9, 0x8A, 0x8F, 0x8E, 0x1C, 0x21, 0xA0, 0xDC, 0xAA, 0xFC, + 0xBF, 0x15, 0x2F, 0x6D, 0x00, 0x33, 0x81, 0x24, 0x86, 0x58, 0xCF, 0xD5, 0x5A, 0xC4, 0xB3, 0x28, + 0x97, 0xC5, 0x45, 0xAB, 0x8D, 0x48, 0xDE, 0xEA, 0xB2, 0xFD, 0x1E, 0xD3, 0x13, 0x57, 0xFF, 0xFB, + 0x24, 0xDE, 0x7A, 0x9D, 0x43, 0xF8, 0xC7, 0xDD, 0x1A, 0x28, 0x7C, 0x39, 0xA4, 0xDA, 0x58, 0xB7, + 0xBD, 0x1D, 0x24, 0xDE, 0xCF, 0x85, 0x7E, 0xEF, 0x5A, 0x4F, 0xF1, 0xB4, 0xCB, 0xA6, 0x5E, 0xC0, + 0x80, 0xE6, 0x0B, 0xC0, 0x69, 0xAD, 0x5D, 0xB4, 0x88, 0xBD, 0xFB, 0x78, 0x2C, 0x3C, 0xA6, 0x69, + 0x77, 0x16, 0xD6, 0xA9, 0xFF, 0x4A, 0x6C, 0xC0, 0x48, 0x27, 0x64, 0x41, 0x51, 0x79, 0xC6, 0xF9, + 0x85, 0x71, 0x9C, 0x89, 0xD2, 0x68, 0xF5, 0xBB, 0xE5, 0x83, 0xF5, 0xD0, 0xEB, 0x25, 0xC7, 0x1E, + 0x50, 0xA8, 0x1F, 0x50, 0x86, 0xEE, 0x1F, 0xE9, 0x4A, 0xB3, 0xA0, 0x18, 0xF8, 0xCE, 0xD6, 0x0B, + 0xF2, 0x41, 0xFC, 0x21, 0x20, 0x1A, 0xA3, 0x9D, 0xB7, 0xD1, 0x49, 0x79, 0xE2, 0x7B, 0xF3, 0x8B, + 0x40, 0x6F, 0xE2, 0x45, 0x00, 0x5A, 0x81, 0x7D, 0x39, 0x93, 0x3B, 0x59, 0xE0, 0x3E, 0xCA, 0xC5, + 0x61, 0x80, 0x65, 0x2D, 0xC9, 0xAD, 0x2C, 0x26, 0x66, 0x11, 0x3A, 0xA6, 0xBA, 0xF5, 0x3B, 0x49, + 0xC5, 0xB1, 0xAA, 0xB6, 0xBC, 0x68, 0x00, 0x51, 0x82, 0x1A, 0x39, 0x2B, 0x28, 0x5C, 0x39, 0xF2, + 0xB4, 0x7E, 0x93, 0x63, 0xEA, 0xD7, 0xBE, 0x7F, 0xA0, 0xCC, 0x47, 0x31, 0x2E, 0xBA, 0x9C, 0xD0, + 0x67, 0xBF, 0xE0, 0xDE, 0x46, 0xCA, 0xA1, 0x84, 0x57, 0x6B, 0x15, 0x0A, 0xC6, 0xAB, 0x32, 0x74, + 0x37, 0x34, 0xDA, 0x1A, 0x95, 0xA6, 0xA4, 0xEE, 0xF6, 0xC6, 0xFB, 0x70, 0x56, 0x0C, 0xC4, 0xCA, + 0x0D, 0xD5, 0xCB, 0x03, 0xA3, 0x21, 0xF5, 0x6D, 0x0F, 0xD1, 0xEE, 0x77, 0x73, 0xA4, 0xF9, 0x95, + 0x34, 0x2F, 0x0C, 0x5B, 0x7F, 0x48, 0x6A, 0x02, 0x4A, 0xA4, 0x59, 0x68, 0x0F, 0xF4, 0x64, 0x73, + 0x84, 0xCE, 0xED, 0x43, 0x54, 0x46, 0xD9, 0x42, 0x4C, 0x84, 0xD5, 0xFE, 0x5B, 0xD3, 0x51, 0x17, + 0x4E, 0xB8, 0x7A, 0x42, 0x87, 0x45, 0xDB, 0xC3, 0x2C, 0xC8, 0x8B, 0x86, 0xB3, 0x95, 0x0B, 0xCF, + 0x27, 0xC4, 0xA8, 0xEE, 0x60, 0x13, 0xD3, 0x9F, 0xFC, 0xD0, 0x7F, 0x84, 0x5B, 0x24, 0x5D, 0xCF, + 0xE4, 0xA4, 0x83, 0x35, 0xD1, 0x7A, 0x72, 0x78, 0xB6, 0xB4, 0xA2, 0x32, 0x0F, 0x68, 0x61, 0x7C, + 0xB7, 0x46, 0x20, 0x1A, 0xA5, 0x94, 0x63, 0x71, 0xAA, 0xA0, 0x77, 0x95, 0x28, 0x63, 0xCE, 0xFE, + 0x69, 0xB6, 0x44, 0x10, 0xF6, 0xC1, 0xD7, 0xED, 0x11, 0x73, 0x9E, 0x46, 0xDE, 0xC3, 0xFF, 0x9E, + 0xB9, 0xEC, 0xEC, 0xE4, 0xE3, 0xFD, 0x1E, 0xD3, 0x55, 0x08, 0x36, 0xC8, 0xDC, 0xD1, 0x0E, 0x00, + 0xEE, 0x86, 0x78, 0x08, 0xB7, 0xAD, 0xD8, 0xE1, 0x59, 0x60, 0x33, 0x14, 0xF4, 0x5C, 0x55, 0xA4, + 0xF1, 0x0D, 0x0E, 0x16, 0xCD, 0x1C, 0x72, 0x6D, 0x89, 0xEB, 0x41, 0x42, 0xB1, 0xF5, 0x63, 0x80, + 0xD6, 0x06, 0xC3, 0x1C, 0xBE, 0x7B, 0x95, 0x2A, 0x5B, 0x27, 0x08, 0xDC, 0xB7, 0x2A, 0xDC, 0x8E, + 0x3C, 0xA0, 0x84, 0x5F, 0xA8, 0xF1, 0x7B, 0x1F, 0xE1, 0x70, 0x37, 0x2D, 0x28, 0xDC, 0x7C, 0xB8, + 0xA7, 0x47, 0x60, 0x77, 0xAC, 0x55, 0xE3, 0x97, 0x5A, 0xC1, 0xA6, 0xA2, 0xFF, 0xCB, 0xF6, 0x45, + 0x28, 0x1E, 0xD2, 0x1C, 0xE8, 0x9E, 0x45, 0xF7, 0x1E, 0xD5, 0x92, 0xB4, 0x5A, 0x5E, 0x6A, 0xE0, + 0xF7, 0x1A, 0x81, 0xD7, 0x96, 0x62, 0xB5, 0xD9, 0xE7, 0x0E, 0x3A, 0xA3, 0xE8, 0x60, 0x30, 0x45, + 0x96, 0x86, 0x58, 0xDD, 0xBA, 0x04, 0x5E, 0xF4, 0x5D, 0xE3, 0x82, 0x7D, 0x3B, 0xD5, 0xD6, 0x28, + 0xFF, 0xC6, 0xDE, 0x3A, 0x3D, 0xF8, 0xB5, 0x6A, 0x5A, 0x1D, 0x34, 0x63, 0x48, 0x6F, 0xE9, 0xC8, + 0x5F, 0x56, 0x17, 0x14, 0x56, 0xC7, 0xE4, 0xC2, 0x38, 0x68, 0x8A, 0x81, 0x0F, 0x4D, 0x4A, 0x91, + 0x79, 0x85, 0x40, 0xB1, 0x7A, 0xA5, 0x4A, 0xF1, 0xC2, 0xA2, 0x3B, 0x62, 0x4D, 0xD8, 0xD8, 0x41, + 0x80, 0x66, 0x48, 0x7A, 0x96, 0xF7, 0xB2, 0x05, 0xDC, 0xB2, 0xD7, 0xBF, 0xB8, 0xB3, 0x0C, 0xD5, + 0x12, 0x90, 0xBA, 0x86, 0xDB, 0x2D, 0x2D, 0x2F, 0x1A, 0xBE, 0xA8, 0xF0, 0x42, 0xA1, 0xE6, 0x9B, + 0x89, 0x57, 0x69, 0xFD, 0x1B, 0x18, 0x94, 0xC2, 0xE1, 0x53, 0xD3, 0xAD, 0x2D, 0x90, 0x8B, 0xEA, + 0xAB, 0x29, 0x47, 0x08, 0xE6, 0x4B, 0xAC, 0x3A, 0xFC, 0x8C, 0x40, 0xC3, 0x45, 0xD9, 0xCF, 0x24, + 0xA9, 0x17, 0xC4, 0xAD, 0x46, 0xAC, 0x27, 0xAD, 0xE6, 0xEE, 0xF2, 0xF7, 0x5F, 0x6C, 0xD7, 0xE7, + 0xF2, 0x01, 0xED, 0x98, 0x4E, 0x7A, 0x03, 0x94, 0x4C, 0x26, 0x69, 0x5E, 0x8D, 0xDC, 0x13, 0xD6, + 0x3A, 0x2D, 0x4A, 0x70, 0x0E, 0x39, 0x94, 0x63, 0xDE, 0x08, 0x7A, 0x72, 0x4D, 0xFE, 0x89, 0xCA, + 0x8C, 0x4D, 0x39, 0x6A, 0x99, 0xAD, 0xAC, 0xE7, 0x8F, 0x6E, 0xD2, 0x18, 0x98, 0xF4, 0x1B, 0xD7, + 0x0A, 0x60, 0xA2, 0x00, 0x1B, 0xB3, 0xE6, 0x37, 0xA1, 0x1F, 0x30, 0xBD, 0xFD, 0xA8, 0x58, 0xB7, + 0xFF, 0xF1, 0x45, 0x74, 0x9B, 0xE9, 0xA8, 0x80, 0x12, 0x0F, 0x98, 0xF7, 0x9E, 0x62, 0xF5, 0x4A, + 0x0C, 0x32, 0x58, 0x87, 0x65, 0x2D, 0xE4, 0x90, 0x44, 0xB2, 0xB1, 0x8A, 0xFB, 0x29, 0x99, 0x3C, + 0xE8, 0xEB, 0x4F, 0x99, 0x21, 0x47, 0x0D, 0xAA, 0x9F, 0x54, 0xAA, 0xFC, 0x47, 0xB6, 0x35, 0xFE, + 0x24, 0x73, 0xC2, 0x26, 0x18, 0x1E, 0x61, 0x18, 0xC7, 0xF5, 0xE1, 0xD9, 0x5C, 0x7E, 0xCA, 0x71, + 0xA5, 0xA6, 0x4D, 0x91, 0xC0, 0xC5, 0x0C, 0x65, 0x98, 0x69, 0x9B, 0x51, 0xDF, 0xC2, 0x88, 0x51, + 0x21, 0x49, 0x8D, 0x23, 0x52, 0x27, 0xAD, 0x83, 0xD7, 0xB3, 0x73, 0x34, 0x90, 0xD3, 0xA7, 0xDE, + 0x9D, 0x8C, 0x5F, 0xCA, 0xA6, 0x2C, 0x95, 0x01, 0xCC, 0x24, 0x59, 0x70, 0x74, 0xBB, 0x72, 0xD7, + 0x80, 0x25, 0x03, 0xD1, 0xB2, 0x0A, 0xF8, 0x0A, 0x53, 0x9E, 0x03, 0x6F, 0xA4, 0xFB, 0x20, 0x52, + 0x46, 0x0C, 0x2B, 0xD8, 0x25, 0x4D, 0xE8, 0xBA, 0xB7, 0x97, 0x8E, 0x77, 0x52, 0xA6, 0x18, 0x92, + 0xBE, 0x86, 0x89, 0x0B, 0x57, 0xBD, 0xBE, 0xAC, 0x74, 0xE5, 0x64, 0xEA, 0x0C, 0xEE, 0xA2, 0x70, + 0x09, 0x0A, 0x07, 0x97, 0xCD, 0x42, 0xD1, 0x91, 0x7E, 0x7F, 0xDE, 0xF5, 0x06, 0xBA, 0xBB, 0x91, + 0xF5, 0x90, 0x4D, 0x67, 0xDF, 0x02, 0x94, 0x7C, 0xAE, 0xC8, 0xD9, 0x80, 0x20, 0xF2, 0xFE, 0xA9, + 0x1B, 0x91, 0x34, 0x34, 0x18, 0xFE, 0xF2, 0xD1, 0xD2, 0xB6, 0xE4, 0xA6, 0x77, 0xD3, 0x63, 0x2C, + 0x82, 0x8A, 0xE0, 0x87, 0xEB, 0x30, 0xC5, 0x14, 0x7E, 0x55, 0x0E, 0x87, 0x7F, 0xD3, 0x5B, 0x88, + 0xA9, 0xA7, 0x1B, 0xB8, 0x55, 0xE1, 0x60, 0x1B, 0xF3, 0x09, 0x8D, 0xE4, 0x31, 0xFF, 0xAA, 0xB0, + 0xFC, 0x29, 0xD2, 0x3F, 0xEE, 0x8C, 0x99, 0x0B, 0x79, 0x1F, 0x60, 0x6F, 0xF7, 0xE0, 0x5A, 0x5E, + 0xD2, 0xB2, 0x52, 0x6C, 0xD4, 0xF5, 0x96, 0x76, 0xAC, 0x51, 0x07, 0xA0, 0xEC, 0x01, 0x34, 0x37, + 0xDB, 0xB0, 0xBE, 0x04, 0x2C, 0x1D, 0xCF, 0x1C, 0x8B, 0xF4, 0xAE, 0x03, 0x7A, 0x9C, 0x6A, 0xDA, + 0xC6, 0xD7, 0xB2, 0xE8, 0x9C, 0x2D, 0xCB, 0x42, 0x7C, 0xFA, 0x49, 0x3E, 0xCA, 0x93, 0xA3, 0x2E, + 0x34, 0x16, 0x35, 0xC7, 0xEB, 0x14, 0x65, 0x95, 0xDD, 0x50, 0x3F, 0xE2, 0xA7, 0xB8, 0x31, 0x30, + 0x19, 0xC5, 0x39, 0xE6, 0xD6, 0xD8, 0xCB, 0x8B, 0x35, 0x85, 0xB9, 0x2F, 0x5F, 0x72, 0x38, 0xA0, + 0x32, 0x7D, 0x0B, 0x30, 0x69, 0x4E, 0xEB, 0x97, 0x1B, 0x5A, 0xCC, 0xCB, 0x9F, 0x14, 0xD1, 0xC4, + 0x66, 0x03, 0xE3, 0xC9, 0xC8, 0x70, 0xD0, 0x08, 0xE6, 0x1B, 0x08, 0xEF, 0xB2, 0x13, 0xF3, 0xAE, + 0x61, 0x5E, 0xE2, 0xF9, 0x72, 0x7B, 0x20, 0x63, 0x86, 0x8A, 0x3A, 0xBD, 0xFB, 0x08, 0xA9, 0x90, + 0xA6, 0xFF, 0xC4, 0xF7, 0xDA, 0x6D, 0x2C, 0x96, 0x5F, 0xB8, 0xE0, 0x73, 0x7C, 0x92, 0xA1, 0xE5, + 0xF9, 0x10, 0x01, 0x6F, 0xCD, 0xFF, 0x16, 0xCE, 0x54, 0x2E, 0x16, 0x87, 0x65, 0xA4, 0xB1, 0xD4, + 0xA2, 0x7E, 0xD2, 0x09, 0xC5, 0x97, 0x7C, 0xDA, 0xAC, 0x7B, 0xA4, 0xA1, 0x0A, 0xD3, 0x84, 0x1E, + 0xEA, 0xE3, 0x8E, 0xA3, 0xB2, 0x30, 0x23, 0x84, 0x51, 0x0C, 0x78, 0x43, 0x46, 0x86, 0xF0, 0x10, + 0xED, 0xF6, 0x57, 0xA7, 0x40, 0x33, 0xCC, 0x19, 0xC6, 0xB7, 0xFA, 0x45, 0x7C, 0x22, 0x26, 0x07, + 0x0F, 0xC7, 0x6E, 0x86, 0xB7, 0x71, 0xA4, 0xC3, 0x1E, 0x54, 0x9F, 0xAF, 0x84, 0x94, 0xEB, 0x84, + 0x6E, 0xE8, 0xDE, 0xA6, 0xC8, 0xA6, 0xBB, 0x93, 0xF6, 0x06, 0x1B, 0x49, 0x82, 0x06, 0x01, 0xAC, + 0x6A, 0x69, 0x9C, 0x44, 0xC2, 0xFF, 0x84, 0xA0, 0xDD, 0x87, 0xD2, 0xF7, 0xFB, 0xF8, 0x05, 0x14, + 0x59, 0x3F, 0x6B, 0x68, 0x90, 0x11, 0x78, 0x8F, 0xA1, 0x6F, 0x0F, 0x7B, 0x62, 0x47, 0xD0, 0xB1, + 0xBB, 0x80, 0x7D, 0x3C, 0x1F, 0x09, 0x7B, 0xE9, 0x60, 0x32, 0x78, 0xB1, 0xE6, 0x1B, 0xD0, 0x9C, + 0x9D, 0xA5, 0x56, 0x47, 0xB7, 0x47, 0x4B, 0x42, 0xCA, 0xBA, 0x34, 0x40, 0x30, 0xE4, 0x80, 0x9F, + 0x74, 0xD9, 0x4F, 0x64, 0x4B, 0x3F, 0x7C, 0x04, 0x76, 0x45, 0x1C, 0x58, 0xA2, 0xC8, 0x5C, 0xC6, + 0x08, 0x5B, 0xD2, 0x80, 0x58, 0xC1, 0x22, 0x3F, 0x9C, 0x99, 0xCD, 0xB8, 0x4A, 0xF6, 0x3E, 0xD4, + 0xFF, 0x26, 0x4C, 0xBF, 0xD5, 0xA0, 0x38, 0x40, 0x30, 0x1D, 0x04, 0x9A, 0xE0, 0x8C, 0x04, 0x6A, + 0x87, 0xB6, 0x16, 0x3F, 0x0C, 0xF9, 0xC5, 0x85, 0x43, 0x77, 0x50, 0x9B, 0xF8, 0x75, 0xA3, 0x9A, + 0xAD, 0x2A, 0x1D, 0x7C, 0xF9, 0xD3, 0x00, 0x7D, 0xFC, 0xA8, 0x5F, 0x7C, 0xC8, 0xEB, 0x69, 0xC4, + 0xAC, 0x16, 0xEB, 0xED, 0x53, 0xBE, 0x66, 0x95, 0xFC, 0x81, 0x65, 0x17, 0x65, 0xEB, 0x0B, 0x7F, + 0xF7, 0x57, 0x35, 0x50, 0x43, 0xBB, 0xC5, 0x1A, 0xC9, 0xA2, 0xCF, 0x7B, 0x1D, 0xC0, 0x9E, 0x02, + 0x79, 0x29, 0x23, 0xB6, 0x24, 0xCF, 0x55, 0x5A, 0x52, 0x3A, 0x51, 0xCE, 0x03, 0xB9, 0x0F, 0xF7, + 0x45, 0x5F, 0x10, 0xE7, 0x78, 0xD6, 0x2B, 0xF8, 0xD0, 0x8C, 0x7F, 0xE8, 0xA1, 0xA5, 0x7F, 0x07, + 0x51, 0xE4, 0xF6, 0xB8, 0xC4, 0xB5, 0xF1, 0xC4, 0xC0, 0x18, 0x2A, 0xD2, 0xC3, 0x86, 0xB9, 0xB1, + 0x35, 0xD8, 0xDD, 0xD3, 0x77, 0x73, 0xAB, 0x01, 0x4A, 0xDE, 0x76, 0x5F, 0x3C, 0x6E, 0x56, 0xB3, + 0x82, 0xC3, 0x7B, 0x03, 0x81, 0x29, 0x7F, 0xE0, 0x83, 0x40, 0xF4, 0x52, 0xF5, 0x32, 0x6A, 0x12, + 0x32, 0x84, 0xBE, 0xBE, 0x92, 0xDA, 0x04, 0x32, 0x40, 0xCF, 0x13, 0xE8, 0x5E, 0x6D, 0x79, 0x71, + 0x5C, 0x98, 0x8C, 0x83, 0xEE, 0x37, 0xE2, 0x65, 0xAA, 0x83, 0xF9, 0xD5, 0xD8, 0xDF, 0x5B, 0x70, + 0x46, 0x64, 0xAB, 0xAA, 0x16, 0x53, 0x66, 0x4B, 0x7F, 0xA6, 0x79, 0x24, 0xBC, 0xD5, 0x35, 0xEF, + 0x14, 0xF6, 0xEA, 0x75, 0xF1, 0xD3, 0x41, 0x18, 0x44, 0x58, 0xD8, 0xA0, 0x49, 0x52, 0x99, 0x7B, + 0x25, 0x6B, 0x65, 0x4B, 0x1B, 0xC7, 0x1D, 0xFB, 0x87, 0x27, 0x8D, 0x3B, 0xBD, 0xC1, 0xF7, 0xD3, + 0x51, 0xED, 0x7F, 0x43, 0xB6, 0x23, 0xC2, 0x70, 0x61, 0xB3, 0xB0, 0x0D, 0xB2, 0xE9, 0x58, 0x5E, + 0xFA, 0x23, 0xD1, 0xC7, 0x06, 0x76, 0xBF, 0x48, 0x06, 0xF4, 0xF9, 0xFC, 0x1C, 0x6F, 0xD6, 0xF8, + 0xFF, 0x9E, 0x40, 0xCF, 0xAD, 0xB7, 0x95, 0xF7, 0x2C, 0x5B, 0xD2, 0xD5, 0x49, 0xA3, 0xAB, 0xCA, + 0x3E, 0x5B, 0xB0, 0x8B, 0x2E, 0x70, 0x27, 0x7D, 0x36, 0x88, 0xB5, 0x25, 0xBA, 0xE9, 0x67, 0x62, + 0xB0, 0xA8, 0x26, 0x8C, 0xA4, 0xB7, 0x14, 0xAE, 0xEC, 0xF1, 0x0D, 0xF1, 0x3E, 0xFC, 0x76, 0x5A, + 0x27, 0x32, 0x60, 0xBE, 0x71, 0x74, 0xE2, 0x54, 0x66, 0xC1, 0xAF, 0x6E, 0xBD, 0x11, 0x3A, 0x1F, + 0x0A, 0x0B, 0xF5, 0x61, 0x04, 0xF3, 0x0A, 0x2B, 0x8B, 0x90, 0x8F, 0x82, 0x42, 0x03, 0x18, 0x1B, + 0xC5, 0x08, 0x53, 0xB9, 0x53, 0x35, 0xB1, 0x05, 0x9F, 0x05, 0x59, 0x85, 0x2C, 0x25, 0x48, 0xD3, + 0x2C, 0xB6, 0xFE, 0xF8, 0x3B, 0x08, 0x49, 0xF3, 0xC1, 0x56, 0x87, 0x49, 0xEB, 0x4D, 0x05, 0x1F, + 0xE5, 0x0F, 0xB5, 0x99, 0xDA, 0xBF, 0x78, 0xC9, 0xFA, 0x1F, 0x62, 0x66, 0x4B, 0xB8, 0x76, 0xAF, + 0x69, 0xDD, 0x4A, 0x80, 0x52, 0x58, 0xB2, 0x04, 0x0B, 0x87, 0x66, 0xF9, 0xE2, 0xF0, 0x66, 0x15, + 0x7F, 0x4C, 0x40, 0x6B, 0x4A, 0xD6, 0x47, 0xD8, 0x81, 0xF1, 0x3B, 0xEF, 0x5C, 0xF7, 0x10, 0x7D, + 0x5C, 0xBC, 0x53, 0x11, 0xFF, 0x8B, 0x6D, 0x4C, 0x08, 0x16, 0x47, 0x48, 0xF2, 0xA0, 0x2C, 0xEF, + 0x33, 0x31, 0x90, 0x94, 0x45, 0x66, 0xC8, 0x3F, 0x84, 0x11, 0xDA, 0x8C, 0xD7, 0x90, 0x8F, 0xF0, + 0x3D, 0xF2, 0xBB, 0x86, 0xFF, 0x90, 0xF3, 0xFB, 0x52, 0xF5, 0x60, 0x3E, 0xF3, 0xBD, 0xAC, 0x3A, + 0x6C, 0x74, 0x7D, 0x03, 0x85, 0xB6, 0xFA, 0xA4, 0x75, 0xD6, 0x52, 0xDB, 0xD2, 0xB8, 0x30, 0xF1, + 0x78, 0x7B, 0xCF, 0xC5, 0x57, 0xDF, 0x52, 0xB9, 0xEF, 0xC5, 0xEF, 0xCA, 0x6D, 0x38, 0x0E, 0x28, + 0xC4, 0x9D, 0x93, 0x4D, 0x73, 0x0A, 0xD1, 0x11, 0xAD, 0x33, 0x27, 0xC9, 0x7E, 0xF8, 0x85, 0x1D, + 0x05, 0x41, 0x6A, 0xAA, 0x6A, 0xA5, 0xBE, 0xD0, 0x93, 0x05, 0x8A, 0x73, 0xF2, 0xF0, 0x61, 0x94, + 0x25, 0xF0, 0xA9, 0x12, 0x12, 0xD8, 0xFF, 0xB1, 0xF0, 0x06, 0xA5, 0x47, 0x69, 0x15, 0xCC, 0xE9, + 0x6B, 0x9D, 0x6E, 0xD9, 0x96, 0xA7, 0xEF, 0x9D, 0x75, 0x9A, 0xD0, 0xD7, 0x90, 0xFE, 0xAF, 0xEB, + 0xC1, 0xBA, 0x83, 0x48, 0x46, 0x54, 0x7C, 0x86, 0x4B, 0x45, 0x4B, 0xA6, 0xE4, 0x3A, 0x33, 0x52, + 0xFD, 0xAF, 0x45, 0x92, 0xF4, 0xB0, 0x88, 0x62, 0x28, 0x9D, 0x52, 0x14, 0xBE, 0x5F, 0xD8, 0xCB, + 0x32, 0x69, 0xC8, 0xB3, 0xB3, 0x27, 0xE4, 0xDC, 0x85, 0xCD, 0x3D, 0x84, 0x51, 0xC1, 0xB6, 0x1F, + 0x50, 0x9F, 0x80, 0x9B, 0xF2, 0xA8, 0xCE, 0x59, 0xAF, 0x25, 0xA7, 0x5A, 0xD6, 0x23, 0xDA, 0xFF, + 0xDC, 0x0A, 0xF1, 0xF8, 0x93, 0x1D, 0xE3, 0x00, 0x90, 0x64, 0x91, 0xCF, 0xEC, 0xDC, 0x40, 0xB8, + 0x64, 0x10, 0xBC, 0x1E, 0x07, 0xF6, 0x98, 0xC1, 0xDE, 0x1B, 0xF3, 0x7D, 0x3A, 0x63, 0x2D, 0x82, + 0xD0, 0x55, 0x0A, 0x45, 0x3F, 0x12, 0x9D, 0xF1, 0x97, 0x9E, 0x5C, 0xAD, 0x2F, 0x1E, 0x36, 0x13, + 0x56, 0xFC, 0xEF, 0xF5, 0x59, 0x9A, 0x2B, 0xE5, 0x99, 0xBB, 0x58, 0xD8, 0x18, 0xD4, 0xB0, 0x0C, + 0x6E, 0x84, 0x7A, 0x50, 0x4C, 0x37, 0x52, 0x32, 0x77, 0xE8, 0x4D, 0x4B, 0x98, 0x42, 0x74, 0x98, + 0x92, 0x42, 0xA9, 0x38, 0x78, 0xBE, 0x51, 0xC0, 0x87, 0x66, 0x5B, 0x20, 0x1C, 0xBC, 0xE6, 0x60, + 0xA4, 0x4F, 0x19, 0x13, 0x61, 0x5E, 0x85, 0x3B, 0xE4, 0xC6, 0x98, 0xCE, 0x13, 0x0A, 0xA1, 0x97, + 0xA8, 0x28, 0x6A, 0x8A, 0xFA, 0x9D, 0x55, 0xA6, 0x64, 0x23, 0x96, 0x1D, 0xB2, 0x2A, 0x51, 0x27, + 0xB6, 0x00, 0x83, 0x96, 0xF6, 0x05, 0x0F, 0x8F, 0xF4, 0x7D, 0x17, 0x20, 0x10, 0xB9, 0x7C, 0xA2, + 0x70, 0x81, 0x58, 0x15, 0x06, 0x49, 0xCA, 0xD1, 0x22, 0x21, 0xC4, 0x9E, 0x07, 0xD2, 0x1F, 0x34, + 0x57, 0x6F, 0xB5, 0xED, 0x81, 0x3D, 0x88, 0x5F, 0x8F, 0x9C, 0x0D, 0xEC, 0x65, 0xCC, 0x52, 0x7F, + 0x26, 0xCC, 0x3E, 0xB4, 0xEF, 0x7E, 0xD6, 0x6F, 0x18, 0xA8, 0xF7, 0xA0, 0xA8, 0x87, 0x78, 0x6A, + 0x4C, 0xFB, 0xEC, 0x5C, 0x4A, 0xE5, 0x2D, 0x99, 0xF2, 0x13, 0x0F, 0x6D, 0xA3, 0xD9, 0x0D, 0x40, + 0xFD, 0xF3, 0xC8, 0x5C, 0xE8, 0xCA, 0xF1, 0x10, 0xE7, 0x40, 0xAA, 0xE5, 0x26, 0x22, 0x6D, 0xF0, + 0xE9, 0x5B, 0xB0, 0x5F, 0x2F, 0x48, 0xD1, 0x74, 0x93, 0xC7, 0x62, 0x1E, 0x5D, 0xE8, 0x6B, 0xBA, + 0x3B, 0xC6, 0xB5, 0x0E, 0x7D, 0x5B, 0x0F, 0x1B, 0x4A, 0x9E, 0x28, 0xBC, 0x78, 0xDF, 0x8C, 0x61, + 0x3A, 0xCD, 0xB6, 0xEF, 0x9D, 0xAE, 0x35, 0x4F, 0xEB, 0x43, 0x9E, 0xCC, 0xA2, 0x1C, 0xAC, 0x40, + 0x94, 0xE8, 0x96, 0x97, 0x1C, 0x54, 0xBB, 0x59, 0x49, 0x01, 0x71, 0xA6, 0x95, 0xB2, 0x58, 0x2C, + 0xAD, 0x91, 0x01, 0x39, 0x53, 0x9B, 0xF4, 0x7F, 0xC3, 0x26, 0xFB, 0x95, 0x5D, 0x56, 0xB8, 0x98, + 0x30, 0x48, 0xC6, 0xE5, 0xC8, 0xBA, 0xE2, 0x88, 0x9C, 0x1F, 0x7B, 0x6F, 0xAD, 0x63, 0xB6, 0xAB, + 0x93, 0xB5, 0xEE, 0xBF, 0x42, 0xEC, 0x8F, 0xA6, 0x09, 0xC4, 0xB4, 0x6B, 0x5B, 0x16, 0x14, 0xCB, + 0xA4, 0xCC, 0x94, 0x62, 0xA7, 0x82, 0x6B, 0xED, 0xAC, 0x51, 0x23, 0x78, 0x8B, 0xF1, 0x48, 0xD6, + 0x12, 0x5F, 0xE7, 0x1D, 0x14, 0xD8, 0xF9, 0x42, 0xCA, 0xB9, 0x12, 0xFD, 0xDC, 0x29, 0xCB, 0x70, + 0xD8, 0x2B, 0x70, 0x75, 0xFC, 0x74, 0xAA, 0xA4, 0xEF, 0xFE, 0xD7, 0xF0, 0x29, 0xD5, 0xA8, 0xA7, + 0x9D, 0x9A, 0x88, 0x93, 0xE0, 0xFD, 0xC8, 0xD2, 0x4C, 0x81, 0x3D, 0x71, 0x25, 0x7A, 0x5C, 0xE8, + 0xC8, 0xBA, 0xBA, 0x15, 0x71, 0x1D, 0x77, 0x15, 0x3B, 0x34, 0x87, 0x61, 0xD1, 0xA5, 0xF4, 0x59, + 0x75, 0x18, 0x5D, 0x85, 0x4B, 0xE7, 0x15, 0x9B, 0xCE, 0xD0, 0x9C, 0x08, 0x90, 0x97, 0x55, 0x0B, + 0x06, 0x8E, 0xFA, 0x18, 0x99, 0xBC, 0xB1, 0x78, 0x80, 0xC7, 0x59, 0xEC, 0x43, 0x8C, 0x55, 0x32, + 0xCF, 0x2E, 0xDE, 0xC6, 0x23, 0xFA, 0xAE, 0xE5, 0xFC, 0x44, 0x78, 0x4A, 0xB9, 0xD2, 0xE5, 0xDC, + 0xE3, 0x47, 0x0D, 0xF2, 0x33, 0x77, 0xB3, 0xA7, 0x0A, 0x6B, 0xFC, 0xDA, 0xD3, 0x9B, 0x4A, 0x09, + 0x30, 0xC7, 0xE2, 0xB2, 0x9C, 0xE1, 0x46, 0xEA, 0xD7, 0xE5, 0x25, 0x1E, 0xA5, 0x08, 0xDD, 0x50, + 0xA3, 0x1F, 0x20, 0xCF, 0xF4, 0x85, 0x3F, 0xFD, 0x3C, 0xBC, 0xE5, 0xF3, 0x4A, 0xF9, 0xE8, 0x8C, + 0xF0, 0xAD, 0xCC, 0x27, 0x60, 0x29, 0xE2, 0xCD, 0x8C, 0xA0, 0x96, 0x0E, 0xD0, 0x2B, 0x9E, 0xB4, + 0x58, 0x11, 0x9C, 0x20, 0xC7, 0xB8, 0x3D, 0xB3, 0xA2, 0x85, 0x0F, 0x01, 0xBE, 0x19, 0x17, 0xC1, + 0x7E, 0x37, 0x75, 0xA1, 0xDB, 0x65, 0x85, 0x6F, 0xA0, 0x31, 0xE5, 0x11, 0x72, 0x1E, 0x91, 0x11, + 0x85, 0x88, 0xE1, 0x2F, 0xD6, 0xFC, 0xBA, 0x98, 0x13, 0x1E, 0xC5, 0xBF, 0xC1, 0xB6, 0xFA, 0xCC, + 0xBC, 0x73, 0x39, 0x2C, 0xC6, 0xFE, 0xF6, 0x4C, 0x70, 0xBC, 0xEA, 0x14, 0xEA, 0x61, 0x86, 0x93, + 0x38, 0x29, 0xFF, 0x1B, 0x83, 0x30, 0x0F, 0xEF, 0xE5, 0x58, 0xAF, 0x03, 0x72, 0x9F, 0xD3, 0x24, + 0xB3, 0x7E, 0x7F, 0x33, 0x76, 0x0E, 0x51, 0x5C, 0x41, 0x47, 0xBC, 0x30, 0x73, 0xF1, 0x64, 0xCA, + 0x87, 0x7F, 0xD0, 0xB7, 0x74, 0x03, 0x50, 0xA4, 0x0D, 0xBA, 0xB3, 0x24, 0x6F, 0x5E, 0x22, 0x89, + 0x6B, 0xD4, 0x07, 0xD3, 0x6B, 0x4D, 0x36, 0x5B, 0x8F, 0x85, 0xE6, 0xF3, 0x8A, 0x94, 0xDD, 0x60, + 0x70, 0x49, 0x14, 0x7F, 0x0A, 0xBC, 0x7B, 0xB2, 0xD0, 0x11, 0x87, 0x9E, 0xA2, 0x8D, 0xCF, 0x89, + 0x56, 0x34, 0x66, 0x71, 0x03, 0xB8, 0xF2, 0x93, 0xC3, 0x12, 0x10, 0x49, 0x29, 0x4B, 0x0A, 0xC8, + 0x88, 0x4C, 0x87, 0x0F, 0x84, 0x50, 0x74, 0x5B, 0x22, 0x78, 0xCF, 0xF7, 0xC8, 0xAB, 0x92, 0x4F, + 0x96, 0x54, 0x7B, 0xAB, 0xAE, 0xC2, 0x53, 0x8C, 0x5A, 0xF8, 0x0D, 0x8E, 0x8D, 0x25, 0x4A, 0xDA, + 0x94, 0xBE, 0x9A, 0x84, 0x56, 0x88, 0x08, 0x59, 0xA0, 0x44, 0x81, 0x48, 0x29, 0xF4, 0x38, 0x1B, + 0xD9, 0xBA, 0xB2, 0x1E, 0xA7, 0x9A, 0xA8, 0x06, 0x77, 0x76, 0x92, 0x7B, 0x25, 0x21, 0x4F, 0x41, + 0x3B, 0x2D, 0xE4, 0xD9, 0xC7, 0xE2, 0xE6, 0x43, 0x5A, 0x18, 0xA3, 0x92, 0xFE, 0xAB, 0x24, 0xC0, + 0x58, 0xC8, 0x02, 0xD8, 0xD1, 0x6C, 0xDD, 0xC9, 0x40, 0x1F, 0xD2, 0xF7, 0x90, 0xDB, 0x29, 0x22, + 0x26, 0x26, 0x83, 0xEA, 0xEB, 0xE2, 0x8A, 0x83, 0x56, 0x32, 0xDB, 0xE8, 0xF6, 0x06, 0x40, 0xE5, + 0x8B, 0xC4, 0xA8, 0xFC, 0x45, 0x2A, 0x22, 0xCF, 0xAB, 0xF6, 0x85, 0x73, 0x97, 0xC6, 0x91, 0xF1, + 0x2B, 0x31, 0xDC, 0x1C, 0xB2, 0x62, 0x9B, 0x6A, 0x02, 0xAC, 0x94, 0xDC, 0x5B, 0x39, 0xF0, 0xB6, + 0x57, 0xE8, 0x39, 0x9A, 0xA9, 0x87, 0x3F, 0x65, 0x5F, 0xD4, 0x49, 0x84, 0x91, 0x74, 0xEA, 0x7E, + 0xD2, 0x44, 0x74, 0x2A, 0xA7, 0x82, 0x28, 0x64, 0x85, 0x2E, 0x0D, 0xB1, 0x93, 0x51, 0x04, 0x0C, + 0x16, 0x3D, 0x42, 0xE2, 0x8F, 0xE9, 0x9F, 0x78, 0xD7, 0xD4, 0x18, 0xC2, 0x9F, 0x9C, 0x9A, 0x6B, + 0x03, 0x95, 0xF1, 0x23, 0xD1, 0x2B, 0x4C, 0x05, 0x1B, 0x8F, 0x21, 0x3B, 0x49, 0x91, 0xD6, 0xBB, + 0xE6, 0x7F, 0xF7, 0x41, 0x52, 0x67, 0x1E, 0x76, 0xDF, 0xF6, 0x8B, 0x7E, 0x84, 0xCD, 0x5A, 0x4F, + 0xB9, 0x7B, 0xEB, 0xBF, 0xFF, 0xC9, 0xC4, 0x69, 0x1D, 0x34, 0xDE, 0x2D, 0x33, 0xDE, 0x02, 0x4C, + 0x7F, 0x38, 0x7D, 0x84, 0xEF, 0x1E, 0x82, 0x6C, 0x28, 0x9E, 0x51, 0xB4, 0x94, 0x40, 0x1F, 0x93, + 0x20, 0x29, 0xE9, 0x6D, 0x61, 0x48, 0x19, 0x84, 0xC1, 0x70, 0xE5, 0xE1, 0x94, 0xAA, 0x43, 0x73, + 0xF6, 0x99, 0xC3, 0x1F, 0x5F, 0x52, 0xE6, 0x34, 0x70, 0x8C, 0x76, 0x26, 0xE7, 0xAA, 0x44, 0x26, + 0xB4, 0x00, 0x3F, 0x2D, 0xA0, 0x5B, 0xDE, 0xC6, 0x02, 0xE2, 0x5B, 0xF6, 0xDB, 0xB2, 0xA0, 0x76, + 0xFA, 0xA0, 0x95, 0x44, 0x11, 0xEE, 0x8D, 0x42, 0x16, 0x2E, 0x5E, 0xAC, 0xBB, 0xC5, 0x65, 0xE8, + 0x49, 0x29, 0xC1, 0x3B, 0x6A, 0x8D, 0x27, 0xEB, 0x25, 0x3B, 0x41, 0x19, 0x4A, 0xB3, 0x0A, 0x95, + 0x20, 0xEB, 0xA6, 0x0B, 0x20, 0xC3, 0xE1, 0xFC, 0x2A, 0x5C, 0xD6, 0xA2, 0x31, 0x70, 0xB0, 0xE6, + 0xEA, 0xC9, 0x11, 0xAB, 0xD2, 0x41, 0xF2, 0xB4, 0x13, 0xDC, 0x79, 0xAB, 0xA0, 0xF3, 0x3C, 0x13, + 0xC9, 0xE3, 0x19, 0xC0, 0x1F, 0x7A, 0x48, 0xEB, 0x06, 0x62, 0x4D, 0xEC, 0x67, 0x14, 0x60, 0x83, + 0xD6, 0xA8, 0xBF, 0xDF, 0x08, 0x21, 0xDF, 0x04, 0x94, 0x26, 0xC9, 0xDA, 0xD0, 0xA3, 0x04, 0xDC, + 0x03, 0x14, 0x90, 0x17, 0xB8, 0x5A, 0x4B, 0xF6, 0x75, 0x9B, 0xAB, 0xB3, 0xA5, 0xC3, 0xC9, 0xFE, + 0x75, 0xE1, 0x47, 0x59, 0xB5, 0xD4, 0x17, 0x94, 0xD5, 0xF4, 0x2A, 0x52, 0x7D, 0xCC, 0xC6, 0x4F, + 0x99, 0x14, 0x65, 0xDE, 0x5C, 0xD7, 0x32, 0xAB, 0x75, 0xA9, 0x6E, 0x82, 0xE3, 0xE7, 0xF4, 0xF3, + 0xC1, 0x4A, 0xE3, 0x19, 0x4F, 0xD2, 0xA7, 0xFE, 0xE5, 0x42, 0x6E, 0x38, 0xF4, 0x33, 0x6E, 0xF9, + 0x0C, 0x76, 0xF1, 0x89, 0x55, 0xAB, 0x08, 0x3D, 0xC5, 0x47, 0x4E, 0xB5, 0x2F, 0x00, 0x33, 0x84, + 0xCD, 0xCE, 0x24, 0xEA, 0xDB, 0x3D, 0x25, 0x9B, 0x24, 0xC1, 0xCA, 0xA3, 0xB6, 0x3A, 0x7D, 0xBF, + 0x8A, 0xB9, 0x60, 0xEF, 0xE6, 0x2B, 0x8C, 0x4A, 0xAC, 0x3F, 0xA4, 0x0D, 0x82, 0x8E, 0xD1, 0x70, + 0x67, 0x97, 0xA7, 0x17, 0xB9, 0x52, 0xB2, 0x5A, 0xE8, 0xEC, 0x8D, 0x94, 0xC5, 0x96, 0xFC, 0x9B, + 0xD3, 0x10, 0x7E, 0xD3, 0x06, 0xB4, 0xAA, 0xC7, 0x63, 0xA1, 0x56, 0x9F, 0x04, 0x7F, 0x96, 0xEE, + 0x39, 0xDC, 0x18, 0x60, 0x2F, 0x71, 0x2D, 0xEB, 0xF5, 0x1A, 0x4D, 0xFE, 0xB3, 0x49, 0x37, 0xFE, + 0xC5, 0x7F, 0x6C, 0xEE, 0x17, 0x48, 0xF5, 0xED, 0xA7, 0xB9, 0x95, 0x0B, 0x61, 0x2E, 0x2C, 0x87, + 0xA7, 0x5D, 0xA5, 0xAC, 0x89, 0xEC, 0x11, 0x0C, 0xD5, 0xCD, 0xE1, 0xB6, 0x9C, 0x4B, 0x8F, 0xCF, + 0x21, 0x75, 0xA1, 0x1B, 0x35, 0x41, 0x4D, 0x4E, 0x9B, 0xDE, 0xE2, 0xE8, 0x0E, 0x23, 0x9A, 0x9A, + 0x2B, 0xAC, 0x41, 0x6E, 0xEF, 0xD1, 0xAC, 0x7E, 0x74, 0xB7, 0x16, 0x83, 0x10, 0x85, 0x84, 0x60, + 0x28, 0xF0, 0xD1, 0xA0, 0x5E, 0xB7, 0x8E, 0xEF, 0x7B, 0x4C, 0x27, 0xAF, 0x8A, 0x9E, 0x3F, 0x29, + 0x1B, 0x12, 0x01, 0x07, 0xF1, 0xAA, 0xFE, 0x2E, 0xFF, 0x18, 0x9A, 0xCD, 0xF4, 0x0E, 0xC1, 0x74, + 0x6D, 0xD4, 0xCE, 0xF3, 0xF9, 0x3C, 0xE2, 0x12, 0x03, 0x07, 0x1B, 0x9D, 0x3D, 0x6E, 0xD9, 0x79, + 0xB3, 0x56, 0x14, 0xC5, 0xEA, 0x06, 0xD1, 0xAD, 0x2C, 0x07, 0x58, 0x90, 0x0E, 0x80, 0x6B, 0x60, + 0x43, 0x82, 0xAA, 0x0C, 0xEE, 0x1B +}; + +uint8 Module_0DBBF209A27B1E279A9FEC5C168A15F7_Key[16] = +{ + 0x5B, 0x27, 0x27, 0x01, 0x24, 0x56, 0xB4, 0xD4, 0x2D, 0xD0, 0x96, 0x77, 0x49, 0x51, 0xDC, 0x0A +}; + +#endif diff --git a/src/server/game/Warden/Modules/WardenModuleWin.h b/src/server/game/Warden/Modules/WardenModuleWin.h new file mode 100644 index 00000000000..ca61a270a81 --- /dev/null +++ b/src/server/game/Warden/Modules/WardenModuleWin.h @@ -0,0 +1,1204 @@ +/* + * 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 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 _WARDEN_MODULE_WIN_H +#define _WARDEN_MODULE_WIN_H + +uint8 Module_79C0768D657977D697E10BAD956CCED1_Data[18756] = +{ + 0x21, 0x6C, 0xBB, 0x6A, 0xB9, 0xAF, 0xE8, 0xA1, 0x9A, 0x79, 0x18, 0xF1, 0x27, 0x9A, 0x14, 0xF5, + 0x42, 0x5D, 0x00, 0xBA, 0x74, 0x57, 0x0E, 0xAF, 0xD2, 0xAE, 0x8E, 0x51, 0xA5, 0xC1, 0x17, 0x4E, + 0xEC, 0x7F, 0xAC, 0xBC, 0xDD, 0x42, 0x87, 0xA6, 0xF9, 0xC1, 0x4A, 0xCE, 0xB5, 0xDD, 0xB3, 0xF8, + 0x06, 0x52, 0x9D, 0xF2, 0xAE, 0x2A, 0x49, 0x2B, 0x7B, 0x72, 0x5F, 0x40, 0x01, 0x16, 0xDB, 0x98, + 0x77, 0x1F, 0xE3, 0x61, 0x5A, 0x99, 0x39, 0x66, 0x2F, 0x2F, 0x35, 0xBF, 0x00, 0x20, 0xE4, 0xE0, + 0x8F, 0x98, 0xAD, 0xFC, 0xDB, 0x7D, 0xDD, 0xE8, 0x7A, 0xE9, 0x21, 0x6C, 0x86, 0x80, 0x3A, 0xE7, + 0x75, 0x66, 0x0E, 0xD9, 0xC6, 0xC5, 0xD8, 0xD8, 0xA9, 0x9B, 0x84, 0x09, 0xF0, 0xB3, 0x7C, 0x72, + 0x53, 0xE2, 0x29, 0xF9, 0x64, 0x8C, 0x17, 0xFD, 0x90, 0xAE, 0x48, 0x5A, 0x30, 0xFA, 0x30, 0xB7, + 0x54, 0x58, 0x59, 0x61, 0xA0, 0x24, 0x57, 0xE4, 0xF0, 0x05, 0xA2, 0x3F, 0x7A, 0xA6, 0x51, 0x7E, + 0x4F, 0x35, 0xF4, 0xE5, 0xFF, 0x98, 0xE9, 0x3E, 0x1F, 0xF1, 0x66, 0x48, 0x5B, 0xF8, 0xCF, 0x3B, + 0x37, 0x3B, 0x60, 0x47, 0x1C, 0xF7, 0xBE, 0x59, 0x70, 0x3A, 0x03, 0x4C, 0xE6, 0xBD, 0xB6, 0xED, + 0x46, 0xAF, 0x04, 0x5A, 0xAA, 0xC4, 0x30, 0xCF, 0x0B, 0x05, 0x86, 0xA9, 0x56, 0x5B, 0x09, 0xF0, + 0x92, 0x59, 0xC8, 0x48, 0x58, 0x33, 0xBF, 0x81, 0x70, 0x51, 0x92, 0x98, 0xE9, 0x4F, 0x2B, 0xDD, + 0x5B, 0x0A, 0x42, 0x51, 0x73, 0x97, 0xF6, 0x66, 0x00, 0xF2, 0x04, 0x50, 0x4A, 0x54, 0x62, 0x7A, + 0x00, 0x10, 0x5B, 0xAD, 0x0E, 0xFC, 0xE1, 0x44, 0x55, 0x4E, 0x21, 0x76, 0xC6, 0x4B, 0xD5, 0x2E, + 0xF5, 0xF4, 0x0E, 0xFC, 0x55, 0xE1, 0xDE, 0x32, 0x20, 0x22, 0x03, 0x98, 0xF0, 0xD3, 0x4A, 0xE5, + 0x45, 0x49, 0x0C, 0xE8, 0x76, 0xE1, 0xBF, 0x4A, 0x53, 0xD3, 0xCE, 0x64, 0xCF, 0x82, 0xCF, 0x67, + 0xA9, 0x3F, 0xF1, 0x06, 0x24, 0x33, 0x0A, 0x98, 0x6A, 0x5C, 0xAB, 0xEE, 0x7F, 0x64, 0xE3, 0x65, + 0x1F, 0xF6, 0xBE, 0xAF, 0x9C, 0x63, 0x53, 0x54, 0x06, 0x84, 0x4F, 0xF2, 0x7D, 0xC5, 0xBD, 0x70, + 0xC7, 0x6F, 0x59, 0x93, 0x7C, 0xEE, 0xC0, 0xCA, 0xF5, 0x56, 0x21, 0x58, 0x5B, 0xD8, 0x1D, 0xB4, + 0xB7, 0x60, 0x72, 0x46, 0xA2, 0x60, 0x3F, 0xC3, 0x30, 0xAB, 0xE0, 0x3B, 0xAC, 0x9E, 0xB9, 0x64, + 0xA8, 0xEF, 0xD0, 0xE1, 0xE5, 0xE1, 0x83, 0x48, 0xB8, 0x35, 0xA7, 0x12, 0x11, 0x00, 0xC9, 0x29, + 0x1A, 0x41, 0x1D, 0x3B, 0xFB, 0x33, 0x0B, 0x66, 0x45, 0x86, 0x61, 0x70, 0x35, 0x4C, 0x5F, 0x64, + 0x8E, 0xF5, 0x57, 0xBE, 0xA6, 0xFA, 0x49, 0xC9, 0x89, 0xA4, 0x74, 0x02, 0x9E, 0xE7, 0x67, 0x14, + 0x8B, 0xB9, 0xE7, 0xA8, 0xB0, 0x75, 0x65, 0x22, 0xB7, 0xCD, 0xFA, 0x55, 0x18, 0x00, 0x55, 0xB5, + 0x09, 0x70, 0x7E, 0x05, 0x0B, 0x11, 0x42, 0xF0, 0x80, 0x58, 0x2F, 0xFE, 0x3B, 0x2C, 0x4A, 0xCA, + 0x50, 0x34, 0xD0, 0x6F, 0xF1, 0xCC, 0x7F, 0x35, 0xD7, 0x9B, 0xF2, 0x97, 0x16, 0xFE, 0x5F, 0x6C, + 0x94, 0xDC, 0xAC, 0x63, 0xC8, 0x85, 0x2E, 0x60, 0x41, 0x34, 0x89, 0xD3, 0xDD, 0xBF, 0x2D, 0x69, + 0xC2, 0xF7, 0x74, 0xB2, 0x56, 0xD9, 0x76, 0xA2, 0x35, 0x30, 0x60, 0x35, 0xAB, 0x50, 0x21, 0xAE, + 0xFC, 0xFA, 0x19, 0x06, 0xDE, 0x89, 0x46, 0xFF, 0x34, 0x2F, 0x19, 0x84, 0x85, 0xF5, 0x1E, 0x60, + 0x91, 0x0D, 0x8C, 0x94, 0xDB, 0x2E, 0xEE, 0x4D, 0x0A, 0x29, 0x64, 0x81, 0xAD, 0x4C, 0xBF, 0x41, + 0x51, 0x04, 0xCD, 0x1C, 0x5C, 0x89, 0xD3, 0x3A, 0x91, 0xD9, 0x5C, 0x7E, 0xF3, 0xE9, 0x5B, 0x9E, + 0xC2, 0xD2, 0xE4, 0xD5, 0xEF, 0x47, 0x63, 0xD2, 0xD4, 0x19, 0x3E, 0xDF, 0xCF, 0xA4, 0x10, 0x47, + 0x16, 0x93, 0xC2, 0xF2, 0x22, 0xED, 0x1D, 0x9E, 0x21, 0x63, 0xC4, 0xCB, 0x89, 0xBB, 0x3E, 0xF7, + 0x89, 0x68, 0x6D, 0x2C, 0xDF, 0x2C, 0x6F, 0xB2, 0x8D, 0x75, 0xF8, 0xC6, 0x57, 0x98, 0x47, 0x86, + 0x40, 0x72, 0xBB, 0xD7, 0x32, 0xCD, 0x7A, 0x15, 0x64, 0x83, 0xD9, 0x50, 0x2E, 0xDE, 0x0C, 0x8C, + 0x30, 0xCD, 0xB0, 0x64, 0xD6, 0x7F, 0xE7, 0xAD, 0x6E, 0x01, 0x3E, 0x14, 0x8A, 0x24, 0x86, 0x1F, + 0x92, 0xAB, 0x1A, 0xE5, 0xD6, 0xBF, 0x64, 0xE5, 0xF6, 0x34, 0x62, 0xD5, 0x92, 0x5B, 0x64, 0xC4, + 0xFC, 0x1B, 0x7F, 0xA0, 0x13, 0xC1, 0xD4, 0xEB, 0x92, 0x90, 0xEF, 0x8C, 0x5E, 0x75, 0x4B, 0x78, + 0x56, 0x5F, 0xA2, 0x55, 0x4B, 0x1B, 0xE3, 0xDD, 0x80, 0x7E, 0xCF, 0x69, 0x97, 0x5A, 0x76, 0xD5, + 0xAA, 0x7D, 0x85, 0x73, 0x10, 0x4E, 0x79, 0x9A, 0x10, 0x10, 0x01, 0xD8, 0xD7, 0x85, 0x41, 0x8D, + 0x3D, 0xEA, 0xE3, 0x59, 0xD9, 0x31, 0x4B, 0x23, 0xC6, 0x53, 0x11, 0xA6, 0x35, 0x29, 0x64, 0x7E, + 0x28, 0xD7, 0x8D, 0x03, 0x70, 0x5C, 0x53, 0xA7, 0x6D, 0x81, 0x30, 0x7B, 0xDF, 0x2B, 0xAE, 0xAB, + 0x6F, 0x52, 0x93, 0xCF, 0xDD, 0x00, 0x35, 0xE9, 0x65, 0x4A, 0x04, 0x79, 0x11, 0x30, 0xCA, 0xC7, + 0xD2, 0xF3, 0x34, 0xAC, 0x32, 0x1F, 0xE4, 0xE5, 0x83, 0x12, 0x66, 0xD6, 0xA6, 0xE4, 0xEB, 0x67, + 0x7E, 0xDD, 0x64, 0x3E, 0xF1, 0x0C, 0xE6, 0x1C, 0xB6, 0xE1, 0xB0, 0x2B, 0xE7, 0x83, 0xB4, 0x4A, + 0x82, 0xDD, 0xC1, 0x22, 0x3F, 0x03, 0x38, 0x90, 0xB2, 0xA9, 0x7B, 0x60, 0x57, 0xF9, 0xDD, 0x04, + 0x60, 0x5D, 0x7C, 0x2C, 0xD3, 0xE6, 0xFE, 0x02, 0x5A, 0x7D, 0x2A, 0x48, 0x81, 0x42, 0x20, 0x84, + 0xFF, 0x1D, 0xCC, 0x64, 0x11, 0x70, 0xE5, 0x4F, 0x9F, 0xE0, 0x11, 0xFB, 0xF0, 0xE2, 0xC4, 0x9B, + 0x11, 0x30, 0x7F, 0x2F, 0x7F, 0xA1, 0xB1, 0xBC, 0x5F, 0x29, 0x21, 0xDF, 0xB4, 0xEB, 0xB2, 0x4F, + 0xAA, 0x2D, 0x95, 0x60, 0x47, 0x78, 0x37, 0x67, 0xCD, 0xFA, 0x36, 0x17, 0x8F, 0x64, 0x15, 0xAF, + 0x04, 0xAA, 0x5C, 0x76, 0x23, 0x07, 0x64, 0x96, 0xB2, 0x5A, 0xCF, 0x03, 0xDC, 0xC3, 0x2D, 0xFB, + 0x0D, 0x2D, 0xA8, 0xBD, 0xCE, 0x58, 0xF8, 0x44, 0x75, 0xA1, 0x07, 0xAA, 0xDF, 0x25, 0xDC, 0x25, + 0x32, 0xCF, 0xA8, 0x92, 0xC5, 0xC0, 0xD5, 0x70, 0x21, 0x19, 0x6F, 0x32, 0xCA, 0x16, 0xFA, 0x8C, + 0xB2, 0x86, 0xF6, 0xD5, 0x2E, 0xD9, 0x0A, 0x9C, 0x96, 0xDB, 0x4D, 0xA4, 0x11, 0x02, 0x4C, 0x33, + 0x99, 0xB3, 0x5E, 0x45, 0x5C, 0xF1, 0x99, 0x61, 0x04, 0x20, 0xC9, 0xC8, 0xB3, 0xB4, 0xD3, 0x8B, + 0x24, 0x78, 0x55, 0x2E, 0xB7, 0x48, 0x43, 0x17, 0xBF, 0xB9, 0x2A, 0xCC, 0xD5, 0x4A, 0x49, 0xB2, + 0x4E, 0x1E, 0xC7, 0x45, 0x4E, 0x55, 0xC4, 0xBC, 0xB1, 0xD2, 0xA6, 0x62, 0xE9, 0x95, 0xBB, 0xCD, + 0x87, 0xD2, 0x7C, 0xE5, 0xC6, 0x77, 0x5B, 0xFF, 0xAF, 0xDD, 0x44, 0x9D, 0x3D, 0x10, 0x05, 0x3C, + 0x77, 0x7A, 0xF8, 0x84, 0x0D, 0x04, 0x55, 0xB5, 0x20, 0xEA, 0xD2, 0x3F, 0x04, 0x33, 0xFF, 0xE2, + 0x01, 0x3B, 0x51, 0x46, 0x3E, 0x34, 0xAA, 0x40, 0xCA, 0x7C, 0x85, 0x46, 0x57, 0xD9, 0xB7, 0xE1, + 0xDC, 0x65, 0xEF, 0x11, 0x66, 0x0B, 0xBA, 0xD8, 0x37, 0x66, 0x96, 0x64, 0x54, 0x8B, 0x05, 0x81, + 0x47, 0x87, 0x70, 0xA8, 0x54, 0xC6, 0x02, 0x08, 0xB4, 0xAD, 0x69, 0x3C, 0xC0, 0x03, 0x69, 0x19, + 0xE6, 0xAC, 0x13, 0xD5, 0x3F, 0x2C, 0x9D, 0x61, 0xCC, 0xA8, 0x60, 0xB5, 0x60, 0x85, 0x19, 0x5B, + 0x3E, 0x82, 0xCA, 0x34, 0x70, 0x06, 0xCD, 0x37, 0x3E, 0x91, 0x2F, 0x49, 0x82, 0x0A, 0x87, 0xE8, + 0x09, 0x18, 0xB3, 0xF4, 0x16, 0xA4, 0xA5, 0x46, 0xC5, 0x76, 0x6D, 0x73, 0xB1, 0x93, 0xDC, 0x69, + 0xF4, 0x49, 0xF8, 0x2F, 0x97, 0xB4, 0xAA, 0x19, 0x4A, 0x60, 0xD2, 0xF9, 0x7B, 0x5A, 0xF0, 0x57, + 0x45, 0xC6, 0xA2, 0x64, 0x37, 0x56, 0xED, 0x6B, 0x5E, 0x1D, 0x9E, 0x35, 0x5E, 0xFE, 0xDE, 0x04, + 0x08, 0x3B, 0x62, 0x40, 0x82, 0xD4, 0xF9, 0xF3, 0x54, 0x95, 0x3E, 0x57, 0x49, 0x3A, 0x41, 0x41, + 0xDA, 0xD4, 0x78, 0x80, 0xC7, 0xF1, 0xDE, 0xA7, 0xFF, 0xDC, 0x53, 0xC9, 0x3A, 0x37, 0xA5, 0x83, + 0xDE, 0xE8, 0x51, 0x33, 0x7B, 0xE6, 0xAC, 0xA5, 0xC4, 0x7D, 0x34, 0xB0, 0x99, 0x0D, 0x03, 0x34, + 0x0F, 0x8D, 0xB8, 0x10, 0x4E, 0x30, 0x38, 0x10, 0xFC, 0x62, 0xC3, 0xC0, 0xF5, 0x67, 0x69, 0xF5, + 0x23, 0xB4, 0xF2, 0x6B, 0x79, 0xA8, 0xEE, 0xF0, 0xDD, 0x06, 0xA1, 0x50, 0x41, 0x3E, 0x1D, 0x04, + 0xB0, 0xB7, 0xC8, 0x58, 0x20, 0x72, 0xF6, 0x41, 0x53, 0x58, 0xAA, 0xAB, 0xA1, 0x19, 0xB0, 0x99, + 0xE4, 0x35, 0x44, 0x32, 0xF0, 0x34, 0x52, 0x4E, 0xD0, 0xBC, 0x1D, 0xD2, 0x14, 0x6A, 0x22, 0x46, + 0x93, 0x52, 0xFF, 0xD5, 0xD9, 0xEF, 0x19, 0xAF, 0xFB, 0x9A, 0x0D, 0x4A, 0x14, 0x49, 0xAE, 0xC0, + 0x09, 0x5E, 0x40, 0x36, 0x63, 0xE7, 0xC3, 0xFA, 0x84, 0x1C, 0xBF, 0x65, 0x17, 0xED, 0xED, 0x49, + 0x93, 0xB9, 0xCD, 0x85, 0x3F, 0x95, 0x57, 0xF9, 0xE7, 0x59, 0x55, 0x59, 0xED, 0x3A, 0xA1, 0x90, + 0x24, 0x36, 0xB8, 0x38, 0x91, 0x57, 0x59, 0xDB, 0xDE, 0x8E, 0x8B, 0x3A, 0xBB, 0x31, 0x76, 0x39, + 0x0D, 0x20, 0x84, 0x8A, 0x05, 0x5A, 0xC1, 0x93, 0x04, 0x5E, 0x9E, 0x2E, 0x41, 0x13, 0xC9, 0x7F, + 0xAB, 0x45, 0x86, 0x99, 0xB2, 0x5C, 0x7E, 0x1A, 0x1C, 0x9C, 0x7C, 0xCF, 0x60, 0x38, 0xF7, 0x02, + 0x8A, 0xE6, 0x74, 0x4F, 0x31, 0x67, 0x99, 0x96, 0xC3, 0x79, 0xEB, 0x19, 0x07, 0xAD, 0xBB, 0xD2, + 0xD7, 0x51, 0x75, 0xDD, 0xD5, 0x44, 0xC2, 0x9A, 0xDE, 0x01, 0x68, 0x8C, 0xBF, 0x11, 0xFE, 0x5F, + 0xB9, 0xCF, 0x25, 0x35, 0xD2, 0xF7, 0x29, 0xE0, 0x63, 0x0F, 0x0A, 0xCA, 0xB9, 0x38, 0xB6, 0xDA, + 0xDD, 0x66, 0xD9, 0x5F, 0x67, 0x42, 0x15, 0xD8, 0x1C, 0xD1, 0x1C, 0xCC, 0xD6, 0xB9, 0x29, 0x85, + 0x99, 0xD6, 0xDD, 0xCE, 0x8E, 0x3D, 0x63, 0x1C, 0x31, 0x32, 0x37, 0xCD, 0xE1, 0xF8, 0xEA, 0x4E, + 0x31, 0x25, 0xF7, 0x2D, 0xE1, 0xCA, 0x36, 0x5B, 0xEC, 0xAC, 0x2B, 0xB0, 0xA5, 0x69, 0x3B, 0x4C, + 0xAE, 0xD7, 0x15, 0xF7, 0x7F, 0x5C, 0x5F, 0x82, 0xF0, 0x1D, 0x44, 0x62, 0xA0, 0x72, 0x57, 0xAD, + 0xB3, 0xD7, 0x1B, 0xA9, 0xE2, 0x76, 0xFF, 0x18, 0xA6, 0x3E, 0xF9, 0xF5, 0x6F, 0xB5, 0x13, 0x26, + 0x72, 0x0F, 0xF4, 0xE1, 0x7D, 0x43, 0x86, 0x48, 0x42, 0x0B, 0x94, 0x96, 0xBF, 0x0E, 0x32, 0x1C, + 0xE0, 0x18, 0x69, 0xA9, 0xAE, 0x83, 0x6F, 0x36, 0xE7, 0x04, 0x20, 0xEE, 0x34, 0xFF, 0x21, 0xE9, + 0xBA, 0x3B, 0x38, 0x48, 0x2D, 0x81, 0x38, 0x48, 0x25, 0xE5, 0x4A, 0xAD, 0x81, 0xA9, 0xE8, 0x33, + 0x0A, 0x4C, 0x60, 0xAE, 0xBB, 0xCC, 0x24, 0x96, 0x44, 0xF3, 0x1A, 0x2A, 0x89, 0xCB, 0xD9, 0x5E, + 0x89, 0x4C, 0xFD, 0x62, 0xA8, 0x38, 0x1E, 0x73, 0x63, 0xB3, 0xF1, 0x3E, 0xAC, 0xB1, 0x0B, 0x5D, + 0x10, 0xE5, 0xCC, 0x88, 0x2F, 0x9D, 0x57, 0xF1, 0x33, 0xA6, 0x50, 0x13, 0x2C, 0x54, 0x81, 0x1B, + 0x90, 0xD8, 0x6F, 0x7C, 0x02, 0x86, 0xA8, 0x02, 0x5F, 0xCE, 0x24, 0x22, 0x76, 0x73, 0xE8, 0x66, + 0xDC, 0x7F, 0x8F, 0x69, 0x4E, 0xBB, 0x63, 0xEB, 0xCD, 0x38, 0xE6, 0xEE, 0x84, 0x70, 0x97, 0x2F, + 0xD1, 0x77, 0xEE, 0x63, 0xE4, 0x2D, 0x42, 0xDE, 0x17, 0x95, 0x18, 0xB5, 0xA9, 0x4D, 0xFD, 0x2A, + 0xA8, 0x07, 0x1F, 0xCC, 0x3F, 0x22, 0x3B, 0x03, 0x49, 0xCF, 0x83, 0x83, 0x85, 0xAA, 0x87, 0xA0, + 0xC6, 0x30, 0x8C, 0x8F, 0x91, 0x88, 0x67, 0xA7, 0x1F, 0xE0, 0xE2, 0x40, 0x1E, 0xE9, 0x12, 0x2E, + 0x5C, 0x33, 0x44, 0x29, 0x0D, 0xEA, 0x34, 0x8B, 0x1A, 0x48, 0x80, 0x67, 0x45, 0x2A, 0xF2, 0x82, + 0xD8, 0x78, 0x7E, 0x36, 0x59, 0x6C, 0x32, 0x58, 0x3B, 0x0F, 0x2C, 0x0B, 0xD1, 0xFA, 0x67, 0x2B, + 0x0C, 0xFF, 0x16, 0x57, 0x04, 0x38, 0x51, 0x4F, 0x34, 0xEE, 0x94, 0x8B, 0xBB, 0x7B, 0xBE, 0xEA, + 0x37, 0xB5, 0x9F, 0xBA, 0xDE, 0xC1, 0xC6, 0x34, 0x2D, 0x36, 0xE6, 0xC8, 0x67, 0x6A, 0x74, 0x56, + 0xB5, 0x05, 0x53, 0xAE, 0x5C, 0x94, 0x83, 0xF9, 0xE0, 0xD7, 0x21, 0xC2, 0x71, 0x4B, 0x0F, 0x9C, + 0x64, 0x1C, 0xF4, 0x6A, 0xF8, 0xE3, 0x3C, 0x8F, 0xD2, 0x20, 0xCF, 0x14, 0xAC, 0x21, 0xF5, 0x2A, + 0xE7, 0xEC, 0x5C, 0x49, 0xAB, 0x21, 0xF2, 0x41, 0x2C, 0x3B, 0xA0, 0x49, 0x43, 0xF3, 0x14, 0xFE, + 0x68, 0x7C, 0x83, 0x05, 0xF3, 0x71, 0x77, 0x02, 0x2B, 0xD4, 0x94, 0x2B, 0x28, 0x5E, 0x4A, 0x5E, + 0x6E, 0x81, 0x1A, 0xD3, 0xDA, 0x58, 0x9F, 0xD6, 0x7B, 0x6D, 0xAD, 0x14, 0xBC, 0x60, 0xFC, 0xC4, + 0x83, 0x0A, 0x8E, 0x9B, 0x8D, 0x5B, 0x24, 0x77, 0x10, 0x34, 0x78, 0xC9, 0x8F, 0xA5, 0x2D, 0x0F, + 0x6A, 0x88, 0x7F, 0x24, 0x40, 0x46, 0x25, 0x3A, 0xDE, 0xB9, 0x9E, 0xA2, 0xE7, 0x8D, 0x52, 0xA2, + 0xFF, 0xDE, 0xB4, 0x95, 0xDB, 0x05, 0x2E, 0xDF, 0x29, 0x28, 0xB5, 0x76, 0xD6, 0x1D, 0x09, 0x45, + 0x69, 0x29, 0xF9, 0x95, 0xAA, 0x36, 0x71, 0xD9, 0x3F, 0xFF, 0x6B, 0x04, 0xFE, 0xED, 0x63, 0xC8, + 0x3C, 0x4B, 0x6B, 0x0B, 0xF3, 0xD8, 0x71, 0x15, 0xDA, 0xC0, 0xC9, 0xE2, 0x0D, 0x87, 0x94, 0x61, + 0xBE, 0xEF, 0x79, 0x92, 0x4C, 0x14, 0x92, 0xBF, 0x0C, 0x4E, 0xA0, 0x1B, 0x58, 0x00, 0x30, 0xF6, + 0xD0, 0x09, 0xD6, 0x1E, 0x81, 0xA0, 0xE7, 0xFD, 0xFD, 0xFF, 0x21, 0x47, 0xAB, 0xDE, 0x67, 0xC6, + 0xF4, 0x19, 0x60, 0x0C, 0x49, 0xE5, 0xC4, 0xBD, 0x64, 0x05, 0xED, 0x89, 0xD7, 0xBD, 0x74, 0xF7, + 0xD4, 0xCC, 0x4B, 0x9E, 0xEB, 0x6E, 0xB7, 0x87, 0xB6, 0x31, 0x07, 0xCB, 0x6E, 0x0D, 0xDF, 0x3A, + 0xD8, 0x64, 0x1F, 0xF9, 0x2C, 0xEE, 0xC0, 0x61, 0x22, 0x0E, 0x5A, 0x20, 0x0C, 0xD4, 0x4F, 0xC5, + 0x2D, 0x82, 0x63, 0x39, 0x36, 0x34, 0x07, 0xC6, 0x23, 0xBC, 0xF1, 0x56, 0xC6, 0x8C, 0x39, 0x23, + 0x43, 0xFF, 0xEC, 0xBE, 0x95, 0x7B, 0xC7, 0xFD, 0xA9, 0x99, 0x3D, 0xDF, 0x50, 0x28, 0x39, 0xCA, + 0x80, 0xCF, 0x1C, 0xE7, 0x81, 0x06, 0xB4, 0x43, 0x55, 0xFB, 0xB0, 0xA4, 0x5D, 0x78, 0x39, 0x71, + 0x88, 0xEC, 0xBB, 0x01, 0x69, 0x5E, 0x85, 0x97, 0x1F, 0xEB, 0x6C, 0x82, 0x07, 0xF4, 0x00, 0x1B, + 0x90, 0x03, 0x1B, 0x92, 0x9A, 0x4A, 0x95, 0x9D, 0x45, 0x45, 0x65, 0x6F, 0x8B, 0x70, 0x4C, 0xFE, + 0x48, 0x94, 0x5B, 0x71, 0x86, 0x70, 0x45, 0xB7, 0x85, 0xD9, 0x59, 0x29, 0x94, 0x47, 0x5A, 0x17, + 0x96, 0xA1, 0x0E, 0xFD, 0x72, 0x71, 0xE1, 0x3F, 0x7B, 0xE6, 0x59, 0x2A, 0x91, 0x5A, 0x6B, 0x82, + 0xB1, 0xA1, 0x31, 0xC2, 0xE4, 0xE3, 0xB9, 0x8E, 0x5A, 0x68, 0xC1, 0x18, 0xD4, 0x4B, 0x02, 0x2E, + 0x50, 0x3D, 0x73, 0x53, 0x2B, 0x13, 0x77, 0x19, 0xC7, 0x03, 0x0B, 0xB5, 0xAD, 0x5C, 0x0B, 0x6B, + 0x66, 0x12, 0xF0, 0xE8, 0x67, 0xB7, 0xF7, 0x88, 0x64, 0xA8, 0x2C, 0x51, 0xA7, 0xF8, 0x5E, 0xB3, + 0x39, 0xEC, 0x1B, 0xDF, 0x6C, 0x89, 0x16, 0xFD, 0x51, 0x26, 0x29, 0x8D, 0x0E, 0xBE, 0x1B, 0xCE, + 0x61, 0xE5, 0x22, 0x09, 0xC1, 0x0F, 0xAD, 0x0C, 0xA1, 0x61, 0xF8, 0x49, 0x29, 0x11, 0x7C, 0x93, + 0x0C, 0xBE, 0xD0, 0x11, 0x6F, 0x24, 0x4E, 0x4B, 0xF5, 0xEF, 0x41, 0x3D, 0x0C, 0x69, 0xC6, 0xA6, + 0xBF, 0x87, 0x68, 0xFF, 0x2F, 0x76, 0xD9, 0xFD, 0x1D, 0x8E, 0x9F, 0x80, 0x19, 0x3B, 0x35, 0x8B, + 0x2D, 0xDB, 0x5C, 0x3E, 0x86, 0xE8, 0xBF, 0xF1, 0x30, 0x88, 0xE4, 0x80, 0xD0, 0x49, 0xC3, 0x50, + 0xF8, 0x1E, 0xCE, 0xDA, 0xAC, 0x2E, 0x3F, 0x97, 0x51, 0x12, 0x89, 0x47, 0x5D, 0xF4, 0xD4, 0x77, + 0x93, 0x66, 0x74, 0xE3, 0x4C, 0xCD, 0xB4, 0xC8, 0x00, 0x85, 0x64, 0x8C, 0x04, 0x72, 0x1C, 0x14, + 0xDA, 0x77, 0xD7, 0x1D, 0x39, 0xC3, 0x65, 0xD0, 0x28, 0x51, 0xCA, 0x91, 0xAE, 0x2D, 0xCD, 0x50, + 0x0D, 0x1B, 0xA4, 0xF1, 0x5D, 0x4C, 0x28, 0x1C, 0x57, 0xE5, 0x00, 0xEC, 0xA4, 0x02, 0x3B, 0xCA, + 0x70, 0xF3, 0x8B, 0x3C, 0x4F, 0xEE, 0x9D, 0x08, 0xFF, 0x66, 0x31, 0xCE, 0x37, 0x93, 0x90, 0x3D, + 0x6E, 0xDE, 0xB9, 0xCF, 0x35, 0xAA, 0xF0, 0x43, 0x3E, 0x6B, 0x19, 0xEC, 0x69, 0x7A, 0xF0, 0xC6, + 0xC3, 0x7D, 0x49, 0x89, 0x43, 0xCC, 0x2C, 0x20, 0x2E, 0xB8, 0x5D, 0xCC, 0xDB, 0x39, 0xCB, 0x0B, + 0x76, 0xD8, 0xAC, 0xD6, 0x2A, 0x76, 0x59, 0x7F, 0x6A, 0x1B, 0xCD, 0x4A, 0x93, 0xCA, 0x42, 0x5F, + 0xC7, 0x98, 0xFA, 0xC9, 0x30, 0x2E, 0x9F, 0x8F, 0xE5, 0xB5, 0x37, 0x41, 0x19, 0xF4, 0xA0, 0xE5, + 0xDA, 0x7D, 0x3C, 0xF5, 0x61, 0xCC, 0x98, 0x27, 0xED, 0xE4, 0x5C, 0x0E, 0x7C, 0x1B, 0x33, 0x38, + 0x77, 0x20, 0x92, 0xC9, 0xD3, 0x38, 0xC3, 0x03, 0x2C, 0xAF, 0xE2, 0x77, 0x34, 0x4B, 0xE2, 0x1C, + 0x9F, 0xE4, 0x4D, 0xAB, 0x12, 0xFE, 0xCD, 0xB3, 0x2C, 0xD3, 0xE2, 0x42, 0xB8, 0xE7, 0xE0, 0x14, + 0x88, 0x31, 0xB1, 0xDC, 0x35, 0xDE, 0xCD, 0x3D, 0x3B, 0xDF, 0x6C, 0x00, 0xA3, 0x48, 0xA6, 0x71, + 0x7E, 0xC6, 0x3A, 0xE8, 0x07, 0xCE, 0xC8, 0xE7, 0xDC, 0xB1, 0x98, 0x17, 0xDB, 0x75, 0x20, 0xFE, + 0x38, 0xC7, 0x1F, 0x02, 0x8E, 0xE4, 0x91, 0x79, 0x3D, 0xC0, 0x50, 0x2D, 0xC7, 0x49, 0x33, 0x6C, + 0xDF, 0x3C, 0xE9, 0x42, 0xE9, 0x27, 0xBC, 0x39, 0x38, 0xAA, 0x98, 0x16, 0x6E, 0x1F, 0x71, 0xDF, + 0x3B, 0xBA, 0x15, 0x2F, 0x69, 0xEB, 0x06, 0x5C, 0xFB, 0xF8, 0x4C, 0x83, 0x2C, 0x28, 0xC2, 0x19, + 0xAD, 0x04, 0xA1, 0xB0, 0x7F, 0xF1, 0x9C, 0x84, 0x38, 0x42, 0x45, 0x3E, 0x1E, 0xC7, 0x95, 0xD5, + 0xAF, 0x35, 0x7E, 0x2A, 0xCC, 0x06, 0x9D, 0x9A, 0xCF, 0xC2, 0x56, 0xE6, 0x73, 0x7F, 0x7E, 0x9D, + 0x9B, 0x01, 0x27, 0x76, 0x14, 0x8C, 0x3E, 0x3A, 0xBD, 0x2E, 0x6C, 0x7C, 0xB7, 0xF2, 0x9A, 0x92, + 0x41, 0xBC, 0xD0, 0x48, 0xF6, 0xE6, 0x16, 0x62, 0x01, 0x4D, 0x3D, 0x8E, 0xD2, 0x98, 0x8F, 0x61, + 0x70, 0x7C, 0x41, 0xCC, 0xCA, 0x3D, 0x3E, 0x0B, 0x70, 0xC3, 0x9F, 0x9D, 0x3E, 0x33, 0x50, 0x2B, + 0xB0, 0x47, 0xC8, 0xA3, 0xAA, 0x55, 0xBA, 0x16, 0x3B, 0xF4, 0x07, 0x98, 0x1B, 0x6C, 0x49, 0x6A, + 0xA5, 0xB4, 0x7A, 0xBE, 0x28, 0x37, 0xF2, 0x55, 0x69, 0x09, 0x7A, 0xEC, 0x94, 0x1C, 0x60, 0xE3, + 0xB5, 0x89, 0x07, 0x58, 0x43, 0xA3, 0x3F, 0x1D, 0x94, 0x20, 0x49, 0x5E, 0xC1, 0xB7, 0x4E, 0x2C, + 0x75, 0x95, 0x54, 0x91, 0x4A, 0x01, 0x90, 0xF8, 0xF1, 0x81, 0xC6, 0x4C, 0x9A, 0x63, 0x20, 0x55, + 0x65, 0x8D, 0x30, 0xA2, 0xD4, 0xC7, 0xAF, 0x18, 0xA5, 0x83, 0xB6, 0x68, 0x1B, 0x35, 0x13, 0x6D, + 0xC6, 0x77, 0x5A, 0x04, 0xFB, 0xD5, 0xBD, 0x2B, 0x0D, 0x55, 0x5E, 0xEC, 0x7A, 0x80, 0x17, 0x01, + 0x9C, 0x4F, 0x55, 0x39, 0x57, 0x9F, 0x31, 0x9E, 0xB9, 0xB1, 0x35, 0xD5, 0x2F, 0xB9, 0xF3, 0x6A, + 0x9C, 0x30, 0xEA, 0x1B, 0xE9, 0x34, 0x4A, 0x2F, 0xB1, 0x36, 0x9C, 0xF0, 0x8A, 0xE9, 0x62, 0xDB, + 0x06, 0x32, 0x64, 0x39, 0x58, 0x29, 0xBD, 0xB1, 0x2C, 0x06, 0x56, 0x54, 0xAF, 0x6B, 0x97, 0x5A, + 0x7D, 0x49, 0xB6, 0xDF, 0x06, 0xFC, 0x9F, 0x06, 0x64, 0x89, 0xF5, 0xF4, 0xC4, 0x55, 0x02, 0x19, + 0xAA, 0xC9, 0x1D, 0x8A, 0x5E, 0x3D, 0xA7, 0x13, 0xEC, 0x52, 0x29, 0x8B, 0x6E, 0xC5, 0xA0, 0x62, + 0x9E, 0x89, 0x96, 0xDF, 0x5E, 0x74, 0x69, 0x53, 0x75, 0xCA, 0xF0, 0x95, 0x0E, 0xF8, 0x42, 0xB6, + 0x06, 0x62, 0xDA, 0x92, 0x48, 0xC3, 0x37, 0x50, 0x59, 0xDF, 0x59, 0xAF, 0xAF, 0x0E, 0x2E, 0x84, + 0xE5, 0x2F, 0x3C, 0xC9, 0x7E, 0x2A, 0xE5, 0xA9, 0x41, 0xB1, 0x51, 0x82, 0xC6, 0x42, 0xEC, 0x65, + 0xFD, 0xCB, 0x54, 0x29, 0x33, 0xC2, 0xE5, 0x5E, 0x10, 0xFB, 0x9E, 0x19, 0xE2, 0x75, 0x53, 0x43, + 0x50, 0xD5, 0x10, 0x8E, 0xBC, 0xC6, 0x2A, 0x0A, 0x8D, 0x7F, 0x4A, 0xF6, 0x07, 0x28, 0xA1, 0xEB, + 0x14, 0x1C, 0xD3, 0xE9, 0x63, 0x55, 0xC7, 0xD2, 0xE8, 0xB2, 0x3D, 0x17, 0x84, 0x63, 0xF9, 0x11, + 0xA4, 0x11, 0xE0, 0xA1, 0x83, 0x11, 0x11, 0xD2, 0xA0, 0x8C, 0x61, 0x74, 0x36, 0x63, 0xE9, 0xE8, + 0x98, 0x4C, 0x20, 0x38, 0x1F, 0xA5, 0x15, 0x60, 0x3E, 0x5C, 0x1B, 0xE6, 0xDE, 0xC1, 0x70, 0x7F, + 0xCB, 0x92, 0x76, 0x05, 0xD8, 0x63, 0xDF, 0x01, 0x7E, 0xF2, 0xF1, 0x01, 0xBD, 0xCE, 0x9A, 0x1E, + 0x50, 0x7F, 0xB4, 0xF4, 0x49, 0x5D, 0x7F, 0xCA, 0x86, 0x83, 0x2F, 0x63, 0x33, 0xEF, 0x4F, 0x35, + 0xA1, 0xBF, 0xB6, 0xCD, 0x25, 0xBA, 0x0E, 0xB9, 0xA3, 0x96, 0x41, 0xD4, 0x90, 0xFF, 0xEB, 0xF7, + 0x4F, 0x93, 0xC8, 0xD7, 0x04, 0x62, 0x6E, 0x88, 0xD7, 0x71, 0x0E, 0x0E, 0x37, 0x50, 0xCE, 0xFA, + 0x9B, 0xBD, 0x5B, 0xB0, 0xB7, 0x0F, 0x70, 0x75, 0x0A, 0x5D, 0xFC, 0x69, 0xB3, 0x07, 0x11, 0x9B, + 0xE8, 0x13, 0x0D, 0xBF, 0x08, 0x33, 0x59, 0x20, 0x4A, 0xBD, 0x27, 0x76, 0xED, 0xF2, 0x36, 0x0B, + 0xEA, 0xBC, 0x78, 0x17, 0xBD, 0x6E, 0x4F, 0x37, 0xD3, 0x26, 0x86, 0x85, 0xB1, 0x71, 0xEA, 0x55, + 0x73, 0xAA, 0x7C, 0xA2, 0x36, 0x75, 0xD2, 0xCD, 0xE4, 0xFC, 0xE7, 0xCE, 0x5E, 0xB1, 0xE5, 0xF4, + 0x65, 0xD7, 0x8F, 0x34, 0x07, 0x66, 0xA7, 0x4B, 0xCE, 0x55, 0xB0, 0x71, 0xFD, 0x20, 0x03, 0x5C, + 0xBA, 0x28, 0x0B, 0x71, 0x4D, 0x93, 0xB9, 0x77, 0x5E, 0x46, 0x6A, 0xCB, 0xD7, 0x0A, 0x59, 0x2E, + 0x26, 0x49, 0x0A, 0x36, 0x0F, 0x03, 0x6F, 0x32, 0xD7, 0xF0, 0xEC, 0x53, 0xF6, 0x0B, 0x1E, 0x08, + 0x27, 0x37, 0x69, 0xC5, 0x9F, 0x6C, 0x76, 0x27, 0x4C, 0x7A, 0x7C, 0xB7, 0xC8, 0x1B, 0xC4, 0x79, + 0xA1, 0xE3, 0xE0, 0xF3, 0x3B, 0x20, 0x07, 0x0C, 0xE4, 0xAB, 0x10, 0x6F, 0xA4, 0xFA, 0x7F, 0x08, + 0x6F, 0x5C, 0xAE, 0x06, 0xC5, 0x6D, 0x09, 0x1E, 0x2D, 0xDD, 0x80, 0xA7, 0x7B, 0x9E, 0xE6, 0x44, + 0x79, 0x3D, 0x55, 0x12, 0x51, 0x87, 0x4D, 0x4A, 0x66, 0x32, 0x2D, 0x4E, 0x17, 0x30, 0xAF, 0x77, + 0x7A, 0x8B, 0x44, 0x8D, 0xA4, 0xF8, 0x70, 0xC1, 0x99, 0x55, 0x3D, 0x4B, 0x08, 0x40, 0x2F, 0xA2, + 0xEA, 0xAA, 0x94, 0x24, 0xC3, 0xBD, 0x5C, 0x68, 0x35, 0x8D, 0x71, 0xA8, 0x3E, 0xBA, 0x00, 0x70, + 0x28, 0xB8, 0x10, 0x20, 0x8F, 0x5C, 0xE4, 0xC4, 0xBB, 0x22, 0x59, 0xA2, 0x35, 0x5F, 0x7A, 0x3D, + 0xF1, 0x24, 0x70, 0x1C, 0xE3, 0x3E, 0xED, 0x26, 0x07, 0xD7, 0x82, 0x4B, 0x80, 0x3B, 0x0C, 0xE4, + 0xAB, 0xCF, 0x71, 0x97, 0x87, 0x22, 0x2B, 0x53, 0x27, 0x99, 0x29, 0x10, 0x41, 0x30, 0xE8, 0x28, + 0xD2, 0x48, 0xAC, 0x25, 0x40, 0xBF, 0xDB, 0xED, 0x3A, 0xF4, 0x5D, 0x6E, 0x66, 0x1A, 0x08, 0xFF, + 0xEE, 0x49, 0x36, 0xD7, 0x68, 0x1E, 0xD7, 0xAB, 0xEC, 0xD6, 0x84, 0x1C, 0x8D, 0x35, 0x2D, 0x10, + 0x3C, 0x9C, 0x77, 0x12, 0xB3, 0x09, 0x5F, 0x0B, 0x2A, 0xB3, 0xCF, 0x8E, 0xE0, 0xF1, 0xAA, 0x71, + 0xB1, 0xE3, 0x58, 0x5C, 0xFF, 0xD1, 0x34, 0xE0, 0xBF, 0x20, 0x6D, 0x42, 0x86, 0xCA, 0x97, 0x1B, + 0x76, 0x2F, 0x08, 0x29, 0xEC, 0xD5, 0xDD, 0x04, 0x36, 0xFC, 0xCA, 0x39, 0xBE, 0x28, 0x8C, 0x1F, + 0x0D, 0x56, 0x77, 0xB7, 0xE0, 0x23, 0x41, 0x1E, 0xB4, 0x29, 0x17, 0x7A, 0xAF, 0xF9, 0x30, 0xCF, + 0xF1, 0xFE, 0xF4, 0x62, 0x32, 0xD9, 0xDB, 0x56, 0x9A, 0x2B, 0x31, 0xBF, 0xA5, 0x15, 0x19, 0x1E, + 0xEA, 0xCB, 0x5D, 0x6B, 0x65, 0x9A, 0x06, 0x1F, 0x9C, 0x0E, 0xC0, 0x5D, 0x8C, 0xFB, 0xD5, 0xCF, + 0xA4, 0x18, 0xA1, 0x0C, 0xAD, 0xD3, 0x98, 0x09, 0x3A, 0x86, 0x7F, 0x1C, 0x60, 0xC9, 0xFB, 0x42, + 0xF2, 0x37, 0x4E, 0xF0, 0x91, 0x02, 0x33, 0x41, 0xDE, 0xDB, 0xF8, 0x8E, 0x44, 0x00, 0xC5, 0x94, + 0x21, 0x39, 0x91, 0x0A, 0xB5, 0xC4, 0x44, 0xAC, 0x04, 0xF8, 0xB7, 0xA1, 0x13, 0x70, 0xA7, 0xEF, + 0x23, 0xBD, 0xF6, 0x12, 0x34, 0x30, 0x3A, 0x70, 0x81, 0x21, 0xE7, 0x66, 0xB8, 0x55, 0x00, 0xAF, + 0xC1, 0xC3, 0x56, 0x3D, 0xAB, 0x3D, 0xCA, 0x16, 0x4F, 0x6B, 0x3E, 0x69, 0xEF, 0xF8, 0xCA, 0x7B, + 0x65, 0x1C, 0xF3, 0xD9, 0xE8, 0xB0, 0xF6, 0xF3, 0x18, 0x9E, 0xDF, 0x45, 0xC7, 0xAF, 0xCE, 0xC8, + 0x5E, 0x51, 0x94, 0x76, 0x23, 0x80, 0xF8, 0x49, 0x9B, 0xB9, 0x7C, 0x2F, 0x3C, 0xE6, 0xB5, 0x2F, + 0xAD, 0xCC, 0xE7, 0xE7, 0x1E, 0x08, 0xBF, 0xFA, 0x70, 0x2C, 0xB3, 0xED, 0x0C, 0x29, 0x7D, 0xB0, + 0xBE, 0xE7, 0x91, 0x39, 0x73, 0xC2, 0x80, 0x77, 0x2F, 0x91, 0x1D, 0x2F, 0x45, 0x1E, 0x41, 0xE4, + 0x45, 0x2A, 0x7E, 0x93, 0xCE, 0x6D, 0x65, 0x18, 0x76, 0x61, 0x15, 0x05, 0x24, 0x0E, 0x65, 0xD6, + 0x19, 0x7A, 0xFF, 0x02, 0x94, 0xFB, 0x2D, 0x14, 0xE4, 0xA3, 0x9C, 0xFC, 0x48, 0x29, 0x3A, 0x7F, + 0x36, 0x4F, 0x18, 0xD5, 0x5B, 0x99, 0x4C, 0x97, 0x20, 0x36, 0x77, 0xA6, 0x75, 0xE3, 0x44, 0x92, + 0x47, 0x72, 0xEA, 0x1D, 0x00, 0x5A, 0x1D, 0xAF, 0x12, 0xAC, 0x26, 0xE9, 0x1E, 0x4C, 0x89, 0xCC, + 0x56, 0x01, 0x22, 0x4D, 0x45, 0x44, 0xAC, 0xB6, 0x75, 0xEF, 0x3F, 0x2B, 0x35, 0xC6, 0x06, 0x12, + 0xF6, 0xDB, 0xF1, 0x55, 0xF7, 0x05, 0xB0, 0xC0, 0x16, 0x13, 0x60, 0xAA, 0x01, 0x68, 0x1A, 0xCF, + 0xA3, 0xDE, 0xC2, 0xED, 0x60, 0xB9, 0x38, 0x0A, 0x78, 0x7C, 0x5A, 0x96, 0x70, 0x3E, 0x1E, 0xDC, + 0xCD, 0x80, 0xDE, 0x5B, 0x63, 0x94, 0x01, 0x9D, 0x68, 0x02, 0xB9, 0x64, 0xBC, 0x89, 0xCA, 0xB4, + 0x12, 0xD7, 0x5E, 0x20, 0xC7, 0xBD, 0x39, 0x21, 0xAD, 0x74, 0x3A, 0x04, 0x8F, 0x5F, 0xE2, 0x55, + 0xE2, 0xA4, 0x8F, 0xE0, 0xFB, 0x9D, 0xBD, 0x67, 0xCF, 0xD8, 0x93, 0x6C, 0x84, 0xE7, 0xB6, 0xCE, + 0xBD, 0x7B, 0xDA, 0x93, 0x18, 0x70, 0x6B, 0x48, 0xBA, 0x0E, 0x66, 0x09, 0x2E, 0x91, 0x55, 0x38, + 0x84, 0x02, 0x18, 0x1D, 0x49, 0xDE, 0x25, 0xB3, 0x7E, 0xE8, 0xD0, 0x6E, 0xDD, 0x13, 0x8F, 0xA4, + 0x95, 0x17, 0x01, 0x0D, 0x93, 0xB0, 0xD8, 0xBD, 0x0C, 0xCA, 0x48, 0x62, 0xFA, 0xF5, 0xEA, 0xC5, + 0x71, 0x21, 0x00, 0xEC, 0x3A, 0x88, 0x26, 0xA1, 0x52, 0xBA, 0xBF, 0x2A, 0x70, 0xEB, 0xF7, 0x2B, + 0x43, 0xF4, 0xF6, 0xE3, 0xD0, 0x63, 0x1A, 0xA1, 0x0C, 0x00, 0xFE, 0xF9, 0x12, 0xE1, 0xED, 0x2A, + 0xFD, 0x19, 0x4E, 0x51, 0x22, 0xA0, 0x4C, 0x09, 0x2F, 0x0B, 0x8A, 0x57, 0xFA, 0x3E, 0xF3, 0x02, + 0xE3, 0xF0, 0x8F, 0x17, 0x6E, 0xC1, 0x45, 0x34, 0x95, 0x61, 0x22, 0x9E, 0x72, 0xA9, 0x50, 0x77, + 0x07, 0x64, 0xEE, 0x52, 0x03, 0x10, 0xBA, 0x09, 0xF9, 0x45, 0x29, 0x58, 0x46, 0x24, 0xE7, 0x0F, + 0x21, 0xE0, 0xC8, 0xC8, 0x69, 0xCB, 0x4C, 0xD8, 0x39, 0x0E, 0x0C, 0x24, 0x68, 0x46, 0x1E, 0xD9, + 0x7A, 0x8C, 0xB2, 0x91, 0xF4, 0x1B, 0x96, 0xDE, 0x63, 0xFF, 0xE7, 0xCB, 0x86, 0x9F, 0xCD, 0xFB, + 0xBF, 0x67, 0xBE, 0x46, 0xF7, 0x0E, 0x1F, 0x1D, 0x77, 0x4F, 0x66, 0x4F, 0x4F, 0x09, 0x4E, 0x79, + 0x33, 0x80, 0x66, 0xA5, 0xD0, 0x47, 0xAD, 0x50, 0x3D, 0x45, 0xE5, 0x15, 0xCB, 0x05, 0xA9, 0xC8, + 0xFB, 0x0F, 0x00, 0xB6, 0x9F, 0xF7, 0xC2, 0x1B, 0x15, 0x2B, 0xD1, 0x01, 0xA2, 0x5A, 0xFB, 0x26, + 0x3D, 0x9E, 0xAC, 0x37, 0x2C, 0x0B, 0x3A, 0xD3, 0xE8, 0x99, 0xAF, 0xB0, 0x12, 0x17, 0x06, 0x0C, + 0x7B, 0xF1, 0x6D, 0xB5, 0x8D, 0x18, 0xE4, 0x32, 0x3F, 0x51, 0xC2, 0x20, 0x20, 0xC6, 0x47, 0x22, + 0x08, 0x94, 0x32, 0x99, 0x17, 0x4A, 0x50, 0x36, 0x1E, 0xA2, 0x88, 0xCE, 0x01, 0xAF, 0x78, 0xF5, + 0x6B, 0xF2, 0xA2, 0x0C, 0x8E, 0xC5, 0xE4, 0x31, 0x9C, 0x28, 0xA4, 0x7F, 0x4E, 0x64, 0x1D, 0xF5, + 0xC1, 0x1A, 0x68, 0xE2, 0xF4, 0x3A, 0x99, 0xBC, 0xD3, 0x31, 0xF9, 0xD8, 0x58, 0x7B, 0xB1, 0xB7, + 0x7D, 0x57, 0x2B, 0x7D, 0xAC, 0x4A, 0x43, 0x9E, 0xB2, 0x50, 0x96, 0x06, 0x99, 0x17, 0x89, 0x6A, + 0xA7, 0x2E, 0xC2, 0xB9, 0xA2, 0xBB, 0x96, 0xD4, 0x03, 0xD5, 0xF2, 0xB4, 0xA7, 0x78, 0xE6, 0x65, + 0x31, 0xD2, 0x43, 0x75, 0x4A, 0xD1, 0xB5, 0xE6, 0x07, 0x98, 0x27, 0xAA, 0xBD, 0xCD, 0x32, 0xF1, + 0x80, 0xCE, 0x9E, 0xCD, 0xF2, 0xA1, 0x50, 0xD0, 0x88, 0x02, 0xF0, 0x1C, 0x10, 0x70, 0xAA, 0xA5, + 0xDF, 0x70, 0x32, 0x7E, 0x89, 0xAE, 0x51, 0x37, 0x84, 0x13, 0x18, 0xCE, 0x7D, 0x4C, 0x8A, 0x16, + 0x99, 0xA2, 0x42, 0x9D, 0x5D, 0x9C, 0x81, 0x86, 0x4D, 0x15, 0x96, 0xF0, 0xE6, 0xE1, 0x38, 0x11, + 0xA6, 0x8A, 0x15, 0x14, 0xF7, 0x13, 0xAD, 0x33, 0x81, 0xB5, 0xF4, 0x65, 0x87, 0x87, 0x6F, 0x97, + 0x2F, 0x5D, 0xED, 0xEC, 0xA7, 0xB6, 0x91, 0xE2, 0xF3, 0x7B, 0xE5, 0xC8, 0x7E, 0x3A, 0x26, 0x54, + 0x9C, 0xC3, 0xD3, 0x6C, 0x4B, 0x6A, 0x78, 0x48, 0xF3, 0x0E, 0xCF, 0xBF, 0x9A, 0xC8, 0x60, 0x46, + 0x0B, 0x6C, 0x92, 0x6B, 0x88, 0x6F, 0x42, 0x39, 0xB0, 0xC2, 0x43, 0x8D, 0xA6, 0x4A, 0xF8, 0xF5, + 0x1E, 0x23, 0x74, 0xF7, 0x15, 0xB2, 0x15, 0xEB, 0x5A, 0x2A, 0xCA, 0xA5, 0x2C, 0xCC, 0x3C, 0x7D, + 0x63, 0x65, 0x7F, 0x3A, 0xA8, 0x35, 0xB0, 0x77, 0x54, 0x1A, 0xCB, 0xA5, 0x07, 0x1E, 0x2C, 0x60, + 0x3C, 0x66, 0x32, 0x55, 0x75, 0xEB, 0x57, 0x35, 0xE2, 0xD3, 0xC2, 0x73, 0x5D, 0xF7, 0xC2, 0xB6, + 0xEE, 0x45, 0x1C, 0x19, 0xE6, 0xF9, 0x23, 0x24, 0x23, 0xBA, 0x77, 0x6B, 0x93, 0x73, 0xA0, 0x9C, + 0xF9, 0xF0, 0x59, 0xE7, 0xB4, 0x60, 0xC3, 0xA6, 0x01, 0xEA, 0xC7, 0x52, 0x2B, 0xDC, 0xDC, 0x96, + 0x0F, 0x3C, 0xB0, 0x19, 0x19, 0xE1, 0x52, 0xB6, 0x17, 0x91, 0x2A, 0x4D, 0xC3, 0xFC, 0x44, 0x33, + 0x5F, 0x9D, 0x36, 0x51, 0x3C, 0x02, 0x6D, 0x68, 0x23, 0x64, 0x1B, 0xA0, 0xA3, 0xD7, 0xEA, 0x64, + 0x60, 0xB9, 0xEB, 0xC5, 0x3F, 0xB5, 0x52, 0xC8, 0xC4, 0xC8, 0x73, 0x36, 0x73, 0x28, 0x67, 0xF1, + 0x2A, 0x3C, 0xA6, 0x8A, 0xDB, 0x99, 0x81, 0x90, 0xDF, 0xD7, 0x4C, 0x1F, 0xD1, 0xD9, 0x0D, 0xCE, + 0x6C, 0xD8, 0x8A, 0x03, 0xB4, 0x70, 0x3A, 0x07, 0x2E, 0x2E, 0x5E, 0xA5, 0x5C, 0xBF, 0x51, 0x36, + 0x97, 0x42, 0xA5, 0x76, 0x2A, 0xCA, 0x0A, 0x51, 0x5D, 0x06, 0x78, 0x0E, 0xCF, 0x9E, 0x93, 0x59, + 0x5C, 0x17, 0x05, 0xB6, 0xF2, 0x0D, 0x02, 0xD6, 0x2D, 0x2E, 0x20, 0x62, 0x8D, 0xF7, 0x38, 0xE0, + 0xC1, 0x5E, 0x17, 0x72, 0x4D, 0xA4, 0x2F, 0x5B, 0xDC, 0xC6, 0x40, 0x82, 0x34, 0x04, 0x39, 0x69, + 0xF8, 0xBC, 0xB1, 0x79, 0x54, 0xD5, 0x1E, 0x2D, 0xD8, 0x8C, 0x90, 0x8D, 0xB4, 0xE3, 0x61, 0xB7, + 0x1D, 0xA2, 0x3C, 0xFB, 0x6A, 0x38, 0x98, 0x06, 0xDA, 0x56, 0x2C, 0xBF, 0x9B, 0x14, 0x76, 0xE6, + 0x3C, 0x01, 0x57, 0xCC, 0xC2, 0x08, 0x0C, 0xBC, 0x10, 0x09, 0x67, 0xAB, 0x01, 0x2A, 0x32, 0x6C, + 0x81, 0x2C, 0xAB, 0xD3, 0xEC, 0x7D, 0x87, 0x48, 0x16, 0x28, 0xAC, 0x1D, 0x61, 0x11, 0x31, 0x87, + 0xD6, 0x2B, 0xB0, 0x36, 0xB1, 0x18, 0xDD, 0xE7, 0xD0, 0x46, 0x57, 0x93, 0xFC, 0xDF, 0xD2, 0x3A, + 0x37, 0x49, 0x42, 0xDB, 0xE6, 0x45, 0x46, 0x22, 0xB0, 0xF2, 0x92, 0xEE, 0x52, 0x94, 0x9F, 0xFE, + 0xB1, 0xD2, 0x33, 0x45, 0xAD, 0xC9, 0x6D, 0x11, 0x79, 0x57, 0xF1, 0x80, 0xF4, 0x07, 0xAE, 0xDF, + 0x11, 0x6C, 0x85, 0x58, 0x49, 0x2F, 0x13, 0x81, 0xB9, 0x66, 0x73, 0xAB, 0x84, 0x94, 0x36, 0xC4, + 0xC6, 0x23, 0x5F, 0xC5, 0x36, 0xC6, 0xBE, 0x8E, 0x6B, 0xE9, 0x97, 0xF0, 0xAC, 0xB4, 0xF1, 0x11, + 0x43, 0xB4, 0xD2, 0xC0, 0x79, 0x5E, 0x88, 0x72, 0xC7, 0x46, 0x6B, 0x22, 0xC7, 0xF2, 0x7B, 0x61, + 0xC8, 0xFA, 0x39, 0x65, 0x45, 0x97, 0xF0, 0xC7, 0xCE, 0x74, 0x09, 0x9F, 0x5D, 0xB7, 0x68, 0xF2, + 0x2E, 0x6E, 0x2D, 0x42, 0x56, 0x9C, 0xED, 0xC5, 0x5A, 0x57, 0xD9, 0x53, 0x5A, 0xB4, 0xE8, 0x15, + 0x07, 0x1B, 0xFB, 0x31, 0x40, 0x14, 0x95, 0x77, 0x33, 0x74, 0x71, 0x73, 0x7B, 0xFA, 0xA7, 0xBF, + 0x51, 0xF8, 0x3D, 0xE6, 0xB1, 0xD0, 0x42, 0x25, 0x52, 0xFC, 0x4F, 0x1A, 0xA6, 0x4D, 0xAF, 0xCD, + 0x13, 0x62, 0x7A, 0xBF, 0x22, 0x98, 0xD6, 0x07, 0x9C, 0xAE, 0x5E, 0xFC, 0x96, 0xEC, 0x0E, 0x79, + 0x84, 0x1F, 0x73, 0x60, 0x6C, 0x02, 0x6C, 0xE5, 0xB7, 0xFD, 0x7A, 0x4B, 0x8D, 0x0D, 0xC0, 0xD7, + 0x0A, 0x70, 0x6E, 0xE1, 0x51, 0x0E, 0x8C, 0xAA, 0x02, 0x6A, 0xCF, 0x61, 0x04, 0xBD, 0x53, 0x9D, + 0xE0, 0xB5, 0x28, 0x1E, 0x24, 0xBA, 0x97, 0x13, 0x0C, 0x6E, 0x93, 0x71, 0xE2, 0x68, 0xEC, 0x73, + 0x2C, 0xEC, 0x80, 0xB2, 0x16, 0xD5, 0x38, 0xC6, 0x3B, 0xCE, 0xEB, 0xB9, 0x42, 0xBE, 0x37, 0xB5, + 0x39, 0x31, 0x00, 0x5F, 0xB6, 0xD1, 0xB6, 0xD9, 0x57, 0x34, 0x82, 0x12, 0x07, 0x05, 0x04, 0x4B, + 0x5E, 0xB8, 0xC7, 0x6F, 0xA3, 0x01, 0xB9, 0x1D, 0xFF, 0x5F, 0x52, 0xBF, 0x6E, 0x7B, 0xA8, 0xC3, + 0x6E, 0xAC, 0x00, 0xCD, 0x0A, 0xAB, 0x7D, 0x4E, 0x63, 0x43, 0xCE, 0x10, 0x21, 0x38, 0x42, 0x88, + 0x8D, 0xA7, 0x46, 0x7F, 0x74, 0x1F, 0x1D, 0x5F, 0x25, 0xD2, 0xC0, 0x18, 0x7D, 0x40, 0x61, 0x36, + 0x06, 0xB5, 0x09, 0xCA, 0xC6, 0xAD, 0xD6, 0x9E, 0xED, 0x45, 0xF6, 0x95, 0x32, 0x07, 0x84, 0x71, + 0xC8, 0x35, 0xB0, 0x81, 0x97, 0xC9, 0x60, 0xDE, 0xFD, 0x8E, 0x90, 0x67, 0xD7, 0x23, 0x51, 0x28, + 0x90, 0xA5, 0x6E, 0xB6, 0x59, 0x88, 0xD1, 0x8D, 0xCD, 0x17, 0xA3, 0x48, 0xE3, 0x3F, 0x00, 0x4E, + 0x9B, 0x21, 0xD5, 0xA4, 0x5A, 0xF0, 0xA0, 0xBA, 0x40, 0xB7, 0xBB, 0xE1, 0x3D, 0x16, 0x9E, 0xEE, + 0xBB, 0x9E, 0xB2, 0x91, 0xBD, 0x39, 0x77, 0xD6, 0xB5, 0x9C, 0xB5, 0xE8, 0xCF, 0x7D, 0x8C, 0x83, + 0x82, 0x1A, 0xBA, 0x11, 0xDA, 0xF3, 0x96, 0xDD, 0x09, 0x20, 0x9F, 0xEB, 0xAE, 0x39, 0xAC, 0x7C, + 0xF2, 0x41, 0x98, 0x21, 0x6B, 0x8D, 0x19, 0xFF, 0x36, 0x5E, 0x82, 0xAC, 0xEE, 0x1E, 0x0E, 0x77, + 0x63, 0x14, 0x4E, 0x87, 0xE8, 0x22, 0x01, 0xD4, 0xC4, 0xF3, 0xE6, 0x49, 0xE6, 0x25, 0x64, 0x5C, + 0x54, 0x4B, 0x10, 0xE7, 0xCD, 0x17, 0x8F, 0xFA, 0xA3, 0x4D, 0xCA, 0x49, 0xCA, 0x4D, 0x33, 0xBC, + 0x29, 0x71, 0x4D, 0xF9, 0x0D, 0x74, 0x01, 0xAC, 0x79, 0xA7, 0xD7, 0x75, 0xD3, 0x9B, 0x04, 0xEE, + 0xCB, 0xCD, 0x51, 0xCC, 0xAA, 0x68, 0xFB, 0x41, 0xD3, 0x2D, 0xC1, 0xC8, 0x72, 0xDC, 0x69, 0xBE, + 0x0A, 0x74, 0xFF, 0xA8, 0x0C, 0xB4, 0xE1, 0x1A, 0xD3, 0x30, 0x21, 0xA9, 0x34, 0xCC, 0xB5, 0xE9, + 0xCF, 0x38, 0x48, 0x3B, 0xFC, 0xD6, 0x88, 0xD8, 0xB7, 0x3D, 0x71, 0xE4, 0x36, 0xA2, 0xE6, 0x03, + 0x02, 0xE3, 0xFB, 0x68, 0x0F, 0x07, 0x3B, 0x80, 0x30, 0x1C, 0xF4, 0x88, 0x0D, 0x86, 0x1F, 0x83, + 0x4D, 0x93, 0xD4, 0x10, 0xB1, 0xFF, 0x2C, 0xCB, 0xBE, 0x8E, 0xA8, 0xDB, 0x09, 0xE5, 0xF7, 0x9C, + 0x82, 0x48, 0xE0, 0xC8, 0x2C, 0x7B, 0xA1, 0x46, 0x89, 0xE9, 0x0D, 0x82, 0x6F, 0xC1, 0xEA, 0xA5, + 0x84, 0x82, 0x33, 0x26, 0x4A, 0xB6, 0x84, 0x60, 0x21, 0x00, 0x89, 0x20, 0x84, 0x14, 0x7A, 0xDF, + 0x7B, 0xEB, 0x45, 0x6B, 0x76, 0xE6, 0xDB, 0x53, 0xBE, 0x6A, 0x95, 0xE1, 0xFE, 0x6A, 0x79, 0x07, + 0xBC, 0x9D, 0xB3, 0x37, 0x67, 0xAF, 0xC2, 0x1E, 0x2B, 0xFF, 0x9F, 0xC5, 0xF5, 0x54, 0xE0, 0x29, + 0x44, 0xA4, 0x2A, 0x6F, 0xB7, 0x52, 0x17, 0x2C, 0xB1, 0x72, 0x6E, 0x9F, 0x30, 0x9D, 0x42, 0x41, + 0xF6, 0xD5, 0x14, 0x3E, 0x32, 0x59, 0x42, 0xAD, 0x7A, 0x68, 0x53, 0xF9, 0x99, 0xFD, 0x30, 0xC0, + 0x68, 0xB6, 0x97, 0xD9, 0x1B, 0x9A, 0xF6, 0xB9, 0x06, 0xE2, 0x2E, 0x27, 0x60, 0xE9, 0x1A, 0xBD, + 0x88, 0xCD, 0xAD, 0xE0, 0xCB, 0xED, 0x76, 0x2B, 0x46, 0x24, 0xB0, 0x48, 0xBA, 0x55, 0x9B, 0xBD, + 0x6D, 0xF2, 0xF7, 0x8C, 0x59, 0x4E, 0xB6, 0xE4, 0x89, 0xE1, 0xD4, 0x97, 0x85, 0x15, 0x27, 0xAE, + 0xD0, 0x9A, 0x72, 0x98, 0xB0, 0x6F, 0x06, 0xB9, 0xFC, 0xFD, 0x0D, 0x51, 0x11, 0x7E, 0x02, 0x66, + 0xD2, 0xE7, 0x25, 0xD4, 0x4D, 0xAE, 0x78, 0x9F, 0x8E, 0x69, 0xDD, 0x43, 0x80, 0x2F, 0xE6, 0x6E, + 0x46, 0xD7, 0x1A, 0x05, 0x8F, 0x4B, 0x5E, 0xF7, 0x4E, 0x09, 0x9B, 0xAF, 0x4E, 0x2B, 0x14, 0x91, + 0x59, 0x67, 0xFF, 0xFF, 0xAA, 0x08, 0xE7, 0x25, 0x42, 0x4E, 0x17, 0xD6, 0xDF, 0xD8, 0x23, 0x45, + 0xB4, 0xE2, 0x15, 0xE8, 0xDB, 0xA8, 0x55, 0x81, 0x9B, 0xE3, 0x3F, 0x09, 0x0C, 0x16, 0x19, 0xE6, + 0xE3, 0x7F, 0x1D, 0xB6, 0xBB, 0x14, 0x3C, 0x58, 0xBB, 0x69, 0x5F, 0x7A, 0x1A, 0x51, 0x45, 0xEE, + 0xDB, 0xA5, 0x7F, 0x53, 0x27, 0x04, 0xA0, 0x60, 0x76, 0x7A, 0xAD, 0x29, 0x7A, 0x8B, 0x49, 0x4C, + 0x6D, 0x26, 0x01, 0x45, 0x9B, 0x2F, 0xC8, 0x6B, 0xE0, 0x11, 0x1E, 0xCE, 0x35, 0x18, 0xDA, 0x6A, + 0x7E, 0x14, 0x56, 0xFB, 0x19, 0xE2, 0xBC, 0xAF, 0xE9, 0x62, 0xF9, 0xD4, 0xB7, 0x21, 0x1D, 0x45, + 0x10, 0xB7, 0xF3, 0x10, 0x80, 0xD0, 0xA9, 0x20, 0x12, 0xFB, 0xFA, 0xB9, 0xF6, 0x9B, 0x32, 0xA9, + 0x68, 0x58, 0xD9, 0x97, 0xDD, 0x4D, 0xDB, 0x67, 0x95, 0x35, 0xFE, 0xFA, 0x9A, 0xB2, 0x8D, 0x39, + 0x32, 0xD0, 0x5F, 0x6E, 0x74, 0x62, 0x3F, 0xC0, 0xC9, 0x24, 0x49, 0xC9, 0x65, 0x27, 0x88, 0x52, + 0x60, 0xBB, 0x6B, 0x52, 0xAC, 0x35, 0x90, 0x47, 0xF8, 0x34, 0xF4, 0x8E, 0x9E, 0x43, 0xE6, 0x28, + 0xA5, 0x04, 0xA9, 0x10, 0x09, 0x4F, 0xE0, 0x2E, 0x3E, 0x12, 0xD9, 0xC3, 0xC3, 0xF0, 0xAB, 0x30, + 0x18, 0x13, 0x6C, 0x17, 0x06, 0x2C, 0x03, 0x60, 0x04, 0x5D, 0x0E, 0xC8, 0x7F, 0x80, 0x4B, 0xAD, + 0xAF, 0x34, 0x2B, 0xDC, 0x94, 0x1F, 0x68, 0x0A, 0xAB, 0xA3, 0xD7, 0x19, 0x23, 0x02, 0x8F, 0xBD, + 0xB9, 0x33, 0xD3, 0x93, 0x66, 0xC9, 0x19, 0x18, 0xEF, 0x08, 0x0C, 0xEE, 0xDB, 0xB3, 0x5E, 0x55, + 0xB2, 0xDC, 0xBB, 0x90, 0x02, 0x2B, 0x90, 0x67, 0x41, 0x3E, 0x65, 0xA0, 0x9B, 0xC4, 0x5D, 0x81, + 0xDC, 0x64, 0x82, 0xA9, 0x86, 0xA7, 0xB1, 0x1C, 0x6C, 0x7B, 0xA2, 0x07, 0xF1, 0xE0, 0x8E, 0x4F, + 0xBF, 0x07, 0x20, 0x48, 0x05, 0xE5, 0x1D, 0xB6, 0xD8, 0x83, 0x45, 0x7C, 0xAD, 0x84, 0x32, 0x94, + 0xCA, 0x88, 0x96, 0xAA, 0x07, 0xE8, 0x7B, 0x0A, 0x89, 0x46, 0x98, 0x2F, 0x93, 0x65, 0xEB, 0x7B, + 0x79, 0x50, 0x8C, 0x8D, 0x01, 0x6D, 0xCE, 0xB4, 0x5E, 0x1E, 0x74, 0x6D, 0xC3, 0x29, 0x0B, 0x34, + 0xB6, 0xB8, 0xE7, 0x9C, 0x2D, 0x71, 0x49, 0x65, 0x07, 0x1A, 0x7D, 0x04, 0x74, 0x42, 0xD7, 0x0D, + 0x96, 0x80, 0x85, 0xFC, 0x5D, 0x29, 0x79, 0x54, 0x8F, 0x08, 0x2A, 0x7F, 0xF2, 0xB8, 0x87, 0x13, + 0x29, 0x6E, 0xC4, 0xB7, 0x99, 0xBB, 0xC5, 0x6C, 0x4D, 0x01, 0x38, 0xB5, 0xFF, 0x93, 0xEC, 0x0F, + 0x96, 0xA5, 0x47, 0x78, 0xD1, 0xC0, 0x63, 0x61, 0xE0, 0x2D, 0xE4, 0x56, 0x7C, 0xAC, 0x77, 0x30, + 0x21, 0x55, 0x32, 0xFD, 0x4E, 0xC0, 0x31, 0x9B, 0x7C, 0x37, 0x04, 0x8B, 0xAB, 0x95, 0x03, 0xAC, + 0x22, 0x9E, 0x1F, 0x86, 0x2A, 0xB5, 0xD9, 0x32, 0x56, 0xCC, 0x4E, 0xE5, 0x1A, 0x70, 0x65, 0x5B, + 0x32, 0xC7, 0x1D, 0x96, 0x73, 0x62, 0x49, 0xB3, 0xC5, 0xA1, 0x83, 0xEB, 0x32, 0x6B, 0x6E, 0x17, + 0xC2, 0xD2, 0xBA, 0x90, 0x3B, 0xB5, 0x99, 0x18, 0x34, 0x4D, 0x15, 0x57, 0x19, 0xCD, 0x3C, 0xE1, + 0xCF, 0x55, 0x4A, 0x44, 0xD0, 0xFD, 0xD1, 0x29, 0xB5, 0x86, 0xA1, 0xAA, 0xB0, 0x6C, 0x30, 0xEE, + 0x14, 0xC2, 0x9E, 0x02, 0x31, 0xDF, 0x13, 0x0D, 0xC6, 0xFA, 0x9F, 0xC1, 0x17, 0xF1, 0x52, 0x08, + 0x8B, 0xBB, 0x81, 0xB8, 0x92, 0x7B, 0x19, 0x0F, 0x5E, 0x7A, 0xDF, 0xEB, 0x86, 0x8C, 0x5F, 0x6C, + 0x7A, 0xE9, 0xF1, 0x26, 0x55, 0x80, 0xFF, 0xBC, 0x6A, 0x0A, 0xBC, 0x23, 0xAB, 0xE8, 0x8E, 0xC3, + 0xA5, 0xD7, 0xFD, 0x52, 0x73, 0x68, 0x4B, 0x56, 0x7F, 0x60, 0x4A, 0x68, 0x84, 0x30, 0xE1, 0x1F, + 0x0C, 0x10, 0x41, 0x71, 0xFC, 0x10, 0xDF, 0x62, 0xCC, 0x4D, 0xD6, 0x2A, 0x7F, 0xB9, 0xAF, 0x46, + 0x94, 0x3A, 0xD7, 0x0F, 0x12, 0x2C, 0xB8, 0x17, 0x1F, 0x56, 0xF3, 0xCD, 0xA0, 0xE7, 0xBF, 0xA4, + 0xFB, 0xC5, 0xE8, 0x17, 0x4B, 0x8A, 0xE5, 0x3E, 0x96, 0x22, 0x17, 0x07, 0xA3, 0x17, 0x0A, 0x77, + 0x98, 0xF8, 0x9B, 0x59, 0x5C, 0x2F, 0xC9, 0x73, 0xA4, 0x5A, 0x17, 0x1F, 0xBD, 0x56, 0x3E, 0xA2, + 0xE6, 0x8F, 0x34, 0xF2, 0xE0, 0x20, 0x37, 0xE4, 0x98, 0xE1, 0xEC, 0xC4, 0x1E, 0x81, 0x13, 0x17, + 0x21, 0x95, 0x88, 0x60, 0x04, 0xDA, 0x91, 0xB9, 0x22, 0xF8, 0x64, 0x87, 0x8D, 0x32, 0x60, 0x37, + 0x33, 0x2E, 0x2B, 0x95, 0x43, 0x0C, 0x10, 0xDF, 0xFC, 0x64, 0x56, 0x89, 0x32, 0x47, 0xA3, 0x8F, + 0xF1, 0x3E, 0x34, 0x63, 0x35, 0xD9, 0x41, 0xD8, 0x1A, 0x23, 0x88, 0x39, 0x6D, 0x23, 0x2A, 0x20, + 0xCE, 0xFB, 0x80, 0x0F, 0x59, 0xB7, 0xFB, 0x1E, 0x24, 0xF5, 0x8A, 0x78, 0x2B, 0xE8, 0x13, 0x52, + 0x34, 0x5B, 0x65, 0x64, 0xAB, 0x78, 0x4D, 0x5C, 0x79, 0x3B, 0xF2, 0x7D, 0x1F, 0x5B, 0xA9, 0x37, + 0xAE, 0x4C, 0x9E, 0x30, 0x6B, 0x39, 0x3D, 0x75, 0x06, 0xCE, 0xFE, 0x87, 0xB7, 0x1B, 0x9C, 0x9F, + 0x44, 0x7E, 0x98, 0xFF, 0x3B, 0xA6, 0x71, 0x48, 0xE3, 0x07, 0x8C, 0x5E, 0x95, 0x96, 0x04, 0xC1, + 0xBF, 0x7A, 0x18, 0x06, 0xC2, 0xD2, 0x24, 0xD6, 0xC9, 0x4D, 0x65, 0xCE, 0x18, 0x8F, 0x8B, 0x0D, + 0xFC, 0x66, 0x40, 0xB1, 0xE6, 0xE5, 0xC5, 0xDE, 0xAE, 0x2E, 0x84, 0x3F, 0xBA, 0x16, 0x5A, 0x63, + 0x72, 0x0F, 0x3C, 0x82, 0x4A, 0xD7, 0x54, 0x54, 0x60, 0x1B, 0x6A, 0x16, 0x2D, 0xDA, 0x0F, 0xF9, + 0x61, 0xD2, 0x53, 0x2B, 0xE4, 0x22, 0x0E, 0x1D, 0x08, 0x69, 0x5D, 0x4D, 0x4D, 0x3E, 0x99, 0xBE, + 0x8A, 0x83, 0xA2, 0x5A, 0x68, 0x8B, 0xBB, 0x6A, 0xA5, 0x31, 0xB9, 0x65, 0xA6, 0x55, 0xD1, 0x09, + 0x8D, 0x6B, 0xAB, 0xD8, 0xF1, 0x06, 0x62, 0xA8, 0x1A, 0xDA, 0xA4, 0x4B, 0x68, 0xA9, 0xB8, 0xA5, + 0x9D, 0xD1, 0xAA, 0x42, 0x8E, 0x67, 0xA8, 0xC6, 0x29, 0x94, 0x69, 0x38, 0xA0, 0x66, 0x84, 0xBB, + 0x73, 0x3B, 0xFC, 0x7D, 0x6B, 0xCD, 0x39, 0x8F, 0x1C, 0x6C, 0xE0, 0x58, 0x97, 0x75, 0xB7, 0x09, + 0x40, 0x68, 0x45, 0xCD, 0x97, 0x78, 0x1A, 0x81, 0xA9, 0x6D, 0x6C, 0x59, 0xB8, 0x0C, 0x7D, 0x94, + 0x46, 0x23, 0xCC, 0xD4, 0x2D, 0x71, 0x95, 0x7F, 0x9F, 0x08, 0xE0, 0xE5, 0xF9, 0xC0, 0x2C, 0xC4, + 0x09, 0x27, 0x7C, 0x62, 0x5E, 0xF4, 0xB6, 0xAA, 0x9D, 0x18, 0x10, 0xCE, 0xCB, 0xCA, 0xFC, 0xC2, + 0x12, 0x5A, 0xC2, 0xC7, 0xFA, 0x47, 0x3B, 0x4A, 0x5C, 0xC7, 0x52, 0xCA, 0x97, 0xD4, 0xC3, 0x90, + 0x1D, 0x04, 0x50, 0x92, 0xFF, 0xCC, 0xA9, 0x85, 0x4D, 0x1F, 0x73, 0xE3, 0x5B, 0x4D, 0x20, 0xCA, + 0x46, 0x89, 0xD5, 0x26, 0x2B, 0xF5, 0x6B, 0x2A, 0x0B, 0x9C, 0x36, 0x15, 0x9A, 0xB2, 0x15, 0xC1, + 0xAF, 0x38, 0x3D, 0xA5, 0x4B, 0x47, 0x56, 0x32, 0x90, 0x60, 0x93, 0x5D, 0x8C, 0xE4, 0x3D, 0x3A, + 0x00, 0xB2, 0x84, 0x92, 0xE7, 0x9C, 0x09, 0xD4, 0x55, 0x01, 0xFC, 0xFC, 0x3C, 0x0B, 0x6B, 0x0B, + 0xD4, 0x39, 0x7B, 0x88, 0x40, 0x08, 0xDE, 0x2D, 0xFC, 0x9E, 0xEF, 0xFE, 0xCA, 0x45, 0xB6, 0x8F, + 0xDD, 0x59, 0x49, 0x16, 0x9B, 0x26, 0x88, 0x7F, 0x83, 0xA0, 0x29, 0x14, 0xA6, 0x96, 0x51, 0x1D, + 0x36, 0xCF, 0x7D, 0x01, 0x2E, 0xC3, 0xC5, 0xC2, 0x49, 0xAB, 0x70, 0xAC, 0x66, 0x08, 0xA4, 0xB7, + 0xB5, 0x37, 0x34, 0xEB, 0xD1, 0xA1, 0x52, 0xB1, 0xF8, 0x1C, 0x88, 0x36, 0x32, 0x00, 0xA4, 0x5B, + 0x3B, 0x93, 0x34, 0x20, 0x5F, 0xA9, 0x9B, 0x1E, 0xA6, 0xF9, 0xFC, 0xC5, 0x34, 0x2E, 0x64, 0xCE, + 0x97, 0x44, 0x71, 0x0D, 0x09, 0x89, 0xF2, 0x68, 0x41, 0xF9, 0x64, 0xA0, 0xFC, 0xE2, 0x43, 0x14, + 0x77, 0xB1, 0x68, 0x2C, 0xE6, 0xCB, 0xD4, 0x82, 0xE0, 0xF1, 0x93, 0x00, 0x50, 0x9F, 0x14, 0x6F, + 0x78, 0xDC, 0x7B, 0xC2, 0xD6, 0x31, 0x29, 0x85, 0xA6, 0xEB, 0x50, 0xEC, 0xA6, 0xDD, 0xAA, 0x50, + 0x65, 0x94, 0xEE, 0x68, 0xC3, 0x11, 0xAA, 0xB7, 0xA7, 0xEE, 0xBB, 0x39, 0x08, 0xA6, 0xE8, 0xC5, + 0x4E, 0x52, 0x84, 0xDD, 0xE6, 0x16, 0xF5, 0xC3, 0xAC, 0xB0, 0xBE, 0x3F, 0xA0, 0xC9, 0x1F, 0x17, + 0xC0, 0x8D, 0x7C, 0x80, 0x27, 0xAE, 0xBB, 0x47, 0x32, 0x94, 0x01, 0xCB, 0x72, 0x12, 0xCB, 0x74, + 0x56, 0x58, 0x17, 0x30, 0x57, 0x6C, 0x94, 0x08, 0xD4, 0x60, 0x50, 0x41, 0x35, 0xAB, 0xBD, 0x0B, + 0xA7, 0x43, 0x1B, 0x53, 0x19, 0xBA, 0x05, 0x67, 0xAF, 0x4C, 0xAD, 0x76, 0xBA, 0x7D, 0x75, 0x8E, + 0x64, 0x0C, 0xDD, 0xFB, 0xD9, 0x84, 0x3F, 0xB0, 0x57, 0x4D, 0x8C, 0xA0, 0x0F, 0xD9, 0xE0, 0x53, + 0xB9, 0x1D, 0xAE, 0xE1, 0xCC, 0x9E, 0xD5, 0x79, 0xDA, 0xB4, 0x0C, 0x0B, 0xDD, 0x95, 0x28, 0xDD, + 0x7F, 0x73, 0x43, 0x83, 0xC5, 0x45, 0x14, 0x00, 0xBA, 0x00, 0x9C, 0xC0, 0xC8, 0x62, 0x34, 0x66, + 0xF9, 0x78, 0x57, 0x0B, 0x9F, 0x85, 0xEE, 0x49, 0xF6, 0xA9, 0x86, 0x05, 0x6B, 0x0E, 0x1F, 0x26, + 0xD0, 0xD9, 0xEB, 0xA8, 0x5B, 0x9B, 0xCD, 0x4E, 0x25, 0x07, 0xE1, 0xE0, 0x60, 0xA0, 0xFB, 0x17, + 0x7C, 0x41, 0xAA, 0x20, 0xFE, 0x83, 0x25, 0x3A, 0x9A, 0x02, 0x87, 0x0A, 0x71, 0x87, 0xE5, 0xD3, + 0xC1, 0xDC, 0x85, 0xC8, 0xFA, 0x71, 0x2A, 0xCF, 0xA1, 0xF7, 0x44, 0x13, 0x9C, 0x03, 0x56, 0xC3, + 0x7A, 0xEE, 0x51, 0x35, 0x3C, 0x27, 0x30, 0xF3, 0x3E, 0x31, 0x5F, 0x00, 0x51, 0xA7, 0x1C, 0x92, + 0xA4, 0xE1, 0xC3, 0x43, 0x12, 0x03, 0x3C, 0xEE, 0xD3, 0xFA, 0x1C, 0x6A, 0x0F, 0xE0, 0x45, 0xBB, + 0x3B, 0x81, 0xF1, 0x37, 0x46, 0x9C, 0x6E, 0x21, 0x74, 0xFA, 0x93, 0x52, 0xF4, 0x57, 0x95, 0x81, + 0xD3, 0x57, 0x44, 0x5E, 0xF0, 0x54, 0x18, 0x3C, 0xFB, 0x3A, 0xE7, 0x10, 0x67, 0xF2, 0x20, 0x24, + 0x09, 0xD2, 0x6D, 0xAB, 0xC2, 0xBA, 0x3C, 0x30, 0xE9, 0x65, 0xF1, 0x50, 0xFB, 0x11, 0xB6, 0xCF, + 0x85, 0x7B, 0x6A, 0x4A, 0x56, 0x59, 0x59, 0xB7, 0xDE, 0xFB, 0xC8, 0x39, 0x6A, 0x52, 0x6D, 0xE6, + 0xB7, 0xC7, 0x7A, 0x62, 0x01, 0x25, 0x3D, 0x54, 0x54, 0xB4, 0xF2, 0xBA, 0xF9, 0xEE, 0xE3, 0x59, + 0xD0, 0x74, 0xB5, 0xBF, 0xDF, 0x3E, 0x3F, 0x87, 0x64, 0x82, 0xD9, 0xD5, 0xF9, 0xE8, 0xBB, 0xC5, + 0xA5, 0x61, 0x91, 0x9C, 0x2C, 0x99, 0xC0, 0x39, 0xB3, 0xEF, 0x33, 0x5E, 0x3E, 0x1E, 0x00, 0xC6, + 0x5A, 0x90, 0x1C, 0x50, 0x43, 0x3D, 0x4B, 0xA1, 0x3F, 0x46, 0xEB, 0xBA, 0x86, 0xA4, 0xEA, 0xE1, + 0xA9, 0x40, 0x97, 0x5A, 0x80, 0x97, 0x36, 0x1C, 0xA8, 0x19, 0x4E, 0x0D, 0xF8, 0xCB, 0x1C, 0xC7, + 0xD4, 0x1C, 0xB1, 0x4C, 0x2E, 0xDB, 0x2D, 0x96, 0x1E, 0xBA, 0xEB, 0x3D, 0xDE, 0x7D, 0xC7, 0x2E, + 0xF8, 0x36, 0x54, 0x5C, 0x94, 0xD0, 0x5A, 0x0E, 0x5D, 0xF6, 0x4D, 0x35, 0xD2, 0xC1, 0x52, 0xC7, + 0x3B, 0x58, 0x43, 0xEB, 0xB6, 0x54, 0xBA, 0xA5, 0xF1, 0x86, 0xDB, 0x23, 0xAB, 0x6A, 0x42, 0x00, + 0x90, 0xD2, 0x0C, 0x76, 0x32, 0xA0, 0xC2, 0xE3, 0x10, 0x0E, 0x0C, 0x8A, 0x7C, 0xA5, 0x5F, 0xC9, + 0x4E, 0x79, 0x6E, 0x38, 0x0D, 0xA1, 0xD8, 0x7E, 0x90, 0xDD, 0xA4, 0x35, 0x33, 0xBF, 0xCE, 0x69, + 0x8F, 0x93, 0xBC, 0xB4, 0xC8, 0xD2, 0xD1, 0xD8, 0x2F, 0x31, 0xF8, 0x0B, 0x12, 0x8B, 0xA2, 0xAA, + 0x7B, 0x36, 0x5F, 0x66, 0x0D, 0xF6, 0x34, 0x0F, 0xA7, 0x6A, 0xF3, 0x52, 0x4A, 0xB3, 0xCE, 0x83, + 0xB5, 0x57, 0x11, 0x74, 0xBF, 0x1D, 0x5E, 0xA4, 0x18, 0x84, 0xC6, 0xE4, 0xAC, 0x42, 0x93, 0x82, + 0x99, 0xF1, 0x4B, 0xE2, 0x07, 0x0E, 0x0C, 0xAD, 0xC4, 0x7E, 0x24, 0xC7, 0xF9, 0x22, 0x34, 0x31, + 0x0B, 0xC9, 0xBF, 0xA8, 0x74, 0xE9, 0xDE, 0xE8, 0x61, 0xDC, 0xC2, 0x49, 0x95, 0x78, 0x6F, 0x2D, + 0x46, 0x76, 0xD8, 0x2F, 0xA9, 0x56, 0x00, 0x38, 0x74, 0x54, 0xBB, 0x66, 0xE5, 0x9B, 0xA1, 0xAB, + 0xE4, 0x1E, 0x46, 0x71, 0x90, 0xC1, 0xF8, 0x16, 0x8A, 0x8F, 0x76, 0xE6, 0x4F, 0x06, 0xE8, 0xE8, + 0xAA, 0x25, 0xF2, 0x75, 0x3A, 0x0D, 0xBD, 0xF6, 0x40, 0xEE, 0x64, 0xE0, 0xF4, 0xD5, 0xBB, 0x76, + 0x7A, 0x8B, 0x43, 0xD8, 0x75, 0xD3, 0xAF, 0x1A, 0xE7, 0x59, 0x5E, 0x8E, 0xC8, 0xE4, 0xD9, 0x7C, + 0x3E, 0x02, 0x4D, 0xBE, 0x00, 0xD9, 0x6F, 0x46, 0xF1, 0x4A, 0x5B, 0x33, 0x97, 0x6E, 0x54, 0x5A, + 0x3A, 0x41, 0x6F, 0xC0, 0xB7, 0x3E, 0x78, 0xE5, 0xCF, 0x75, 0x1C, 0xEE, 0xD8, 0xA1, 0xEE, 0xD0, + 0x37, 0x94, 0xFE, 0x63, 0x1B, 0x2F, 0x63, 0x7A, 0xFE, 0x22, 0xCD, 0x32, 0xE1, 0xB6, 0xF8, 0x21, + 0x33, 0xDA, 0xCE, 0xB4, 0x91, 0x25, 0x21, 0x67, 0xA2, 0x6D, 0x5D, 0x49, 0xBD, 0x77, 0x92, 0x60, + 0xA3, 0x56, 0xBF, 0x1E, 0x1B, 0xF8, 0xE9, 0x40, 0xC5, 0xBF, 0x06, 0xFC, 0x14, 0xBC, 0xBC, 0x62, + 0xC0, 0xCB, 0x8D, 0x67, 0x7E, 0xDD, 0xB9, 0xCE, 0x66, 0xE2, 0x52, 0xC1, 0x21, 0x68, 0x93, 0xB4, + 0x6F, 0xFC, 0x81, 0x1F, 0x41, 0xD7, 0x7F, 0x10, 0xCF, 0x35, 0x9B, 0x72, 0xC6, 0xBC, 0x05, 0x5D, + 0x7D, 0x63, 0x09, 0xB4, 0xA8, 0x62, 0xAA, 0x42, 0x51, 0xC1, 0xC0, 0xF0, 0x2D, 0xE2, 0xBE, 0x6D, + 0x54, 0x53, 0x55, 0x7B, 0x39, 0x0A, 0xB0, 0x2A, 0xE0, 0x45, 0x0A, 0xEF, 0xD7, 0x7E, 0xB9, 0xAF, + 0xB9, 0xDA, 0x22, 0x5D, 0x65, 0xD5, 0x39, 0x0F, 0xE4, 0x2B, 0x8E, 0xAA, 0x79, 0xC9, 0xFB, 0xF0, + 0x00, 0x51, 0xE6, 0x59, 0x3F, 0x12, 0x54, 0x4A, 0x29, 0x23, 0xD3, 0x6A, 0x9F, 0xB9, 0x0D, 0x99, + 0x1E, 0x8A, 0xF6, 0x55, 0xD3, 0xDC, 0x8A, 0x48, 0xC3, 0xE5, 0x16, 0xDA, 0xFF, 0xB0, 0x3B, 0x92, + 0x49, 0xD6, 0x00, 0xB1, 0x13, 0x8E, 0xC2, 0x3F, 0x7C, 0xF9, 0x48, 0x55, 0xD5, 0xAC, 0xEA, 0x8A, + 0xC1, 0x5C, 0xA9, 0x48, 0xEA, 0x71, 0xDA, 0x99, 0xE9, 0x49, 0xBA, 0xD8, 0x1F, 0xF2, 0xB2, 0x51, + 0x5D, 0x13, 0xC7, 0x6A, 0x82, 0x8E, 0x64, 0x3A, 0x11, 0x56, 0x66, 0x24, 0x2D, 0xC1, 0x7D, 0x3A, + 0xB2, 0x45, 0xB6, 0xAE, 0x10, 0x8F, 0xBD, 0xD6, 0x9F, 0xAB, 0x44, 0xA7, 0x4A, 0x5D, 0x92, 0x7D, + 0x8F, 0xE5, 0x59, 0x4A, 0x10, 0x85, 0xFD, 0x3C, 0x40, 0x3B, 0xBF, 0xDF, 0xA7, 0x3A, 0x1D, 0xB5, + 0x67, 0x23, 0xF9, 0xAC, 0x59, 0x31, 0x2F, 0xD9, 0xD6, 0xF5, 0xEA, 0xD1, 0xDE, 0xAE, 0xFA, 0x44, + 0xFD, 0xE0, 0xBE, 0xE3, 0xF7, 0xEA, 0xD5, 0xF0, 0x26, 0x41, 0xE5, 0x3D, 0xBE, 0xAA, 0xFC, 0x57, + 0x49, 0xAE, 0x3E, 0x70, 0x8F, 0x9D, 0xF1, 0xB6, 0x32, 0x7D, 0xE7, 0x21, 0x4A, 0x7E, 0x99, 0xD7, + 0x90, 0xFE, 0xC5, 0xB2, 0xE8, 0xAC, 0x6D, 0xF7, 0x3C, 0xD3, 0x1E, 0x61, 0xF4, 0xFF, 0x8C, 0x13, + 0x5A, 0x7F, 0x87, 0x66, 0x47, 0x84, 0xF8, 0x3B, 0x0B, 0x70, 0xCF, 0xBA, 0x0C, 0x87, 0x93, 0x62, + 0x65, 0x1E, 0x47, 0xFC, 0x96, 0x25, 0x46, 0x01, 0xE0, 0xCE, 0xE2, 0x41, 0xC6, 0x38, 0x90, 0x0D, + 0xE3, 0xC7, 0x60, 0x4E, 0x08, 0x0F, 0x02, 0xF5, 0xB8, 0x70, 0x27, 0x89, 0x29, 0x6E, 0x79, 0x85, + 0x12, 0xA4, 0xCA, 0x6C, 0x69, 0xBE, 0x52, 0xFF, 0xBD, 0xCF, 0x3E, 0x07, 0xA8, 0x7B, 0x00, 0x44, + 0xE0, 0x3B, 0xA6, 0x50, 0xFF, 0xF9, 0xDA, 0x0D, 0xEB, 0xCC, 0x70, 0x21, 0x20, 0x5F, 0xF4, 0xAF, + 0x1B, 0x2C, 0xF8, 0x63, 0x9C, 0xB9, 0x8F, 0x0B, 0xBF, 0x1C, 0xA5, 0x85, 0xA6, 0x9A, 0x0A, 0x93, + 0x1E, 0x8B, 0xA3, 0x80, 0x63, 0x30, 0x24, 0xE1, 0xF0, 0xB6, 0x7B, 0x93, 0xC5, 0x72, 0xE9, 0x49, + 0x91, 0x1D, 0xB0, 0x77, 0xC0, 0xA2, 0x1D, 0xC9, 0x66, 0x90, 0xF7, 0x58, 0x92, 0x87, 0x4F, 0xB0, + 0x0D, 0x0A, 0x48, 0x16, 0x5F, 0x7D, 0xF4, 0xA6, 0xC9, 0x80, 0xD2, 0x38, 0xD6, 0xC7, 0xEE, 0x73, + 0xA6, 0xA8, 0x57, 0xC9, 0xAA, 0x32, 0x6A, 0x3C, 0xA7, 0x9F, 0x89, 0x79, 0x8B, 0xD9, 0x6B, 0x8C, + 0xB1, 0x26, 0x5D, 0x4B, 0xE9, 0xF0, 0x9D, 0xFA, 0xC0, 0xD3, 0xEA, 0x82, 0xDA, 0x7C, 0xCB, 0x43, + 0x90, 0x74, 0x24, 0xC6, 0xBD, 0x5B, 0x87, 0x29, 0xCA, 0xEC, 0x6E, 0xBA, 0x7C, 0x41, 0xF9, 0x99, + 0x0A, 0x92, 0xFA, 0x43, 0xAE, 0xE7, 0xF9, 0xFB, 0x55, 0x5B, 0x3A, 0xCC, 0x1C, 0xC5, 0x20, 0x37, + 0x53, 0x4A, 0x83, 0xC6, 0x79, 0x5A, 0x42, 0xF9, 0x23, 0x62, 0xA1, 0x3A, 0x42, 0xCE, 0x51, 0xC5, + 0x5D, 0xC9, 0x99, 0x1F, 0x82, 0xE7, 0x43, 0x72, 0x46, 0x70, 0x80, 0x25, 0x65, 0x98, 0x78, 0xC2, + 0xF9, 0xD4, 0x07, 0x2D, 0xAB, 0x79, 0x7D, 0x45, 0xC3, 0x0B, 0xEE, 0x18, 0xBB, 0x3C, 0x33, 0xE5, + 0x8B, 0xE5, 0x2A, 0x04, 0x53, 0x7C, 0x92, 0x92, 0x3E, 0x77, 0xE6, 0xB5, 0x8A, 0x7C, 0xAC, 0x3F, + 0xEA, 0xFC, 0x19, 0x64, 0xFD, 0xB4, 0xA3, 0x33, 0xCC, 0xBB, 0xE3, 0x5F, 0xBA, 0xAB, 0x9F, 0x2A, + 0x4E, 0x71, 0x96, 0x4D, 0x8D, 0x33, 0x39, 0x02, 0x0F, 0x6B, 0xFB, 0xC7, 0x76, 0x0D, 0xC4, 0x9D, + 0xB0, 0x6C, 0xA3, 0x91, 0x32, 0x23, 0x60, 0xF9, 0x53, 0x3C, 0x48, 0xCF, 0x54, 0x4A, 0x34, 0x6A, + 0x90, 0xB8, 0xDB, 0xB6, 0xFD, 0xD8, 0xB9, 0x79, 0xF1, 0x5D, 0x64, 0xFC, 0x2C, 0x6E, 0xA2, 0xD2, + 0x4D, 0x37, 0x56, 0xCB, 0x8D, 0xE9, 0xC9, 0x02, 0x3A, 0x7F, 0x53, 0x75, 0x98, 0x46, 0xF9, 0x8E, + 0xE2, 0x00, 0x05, 0x20, 0x8E, 0xAD, 0xAA, 0x38, 0x5F, 0x6A, 0x34, 0x16, 0x2E, 0x25, 0xFF, 0x7F, + 0xE2, 0x10, 0x2D, 0x49, 0x2C, 0xEF, 0xB5, 0xE5, 0x8A, 0x2A, 0x1F, 0x6F, 0x6C, 0x49, 0xF7, 0x78, + 0x80, 0xCA, 0xFA, 0x14, 0x5D, 0xAE, 0xA9, 0xCD, 0xC5, 0xB8, 0xA8, 0xDC, 0xFF, 0x84, 0xC5, 0x80, + 0x8E, 0x98, 0x5F, 0x7E, 0xF6, 0x26, 0xBB, 0x35, 0xF7, 0xA7, 0x40, 0x46, 0x83, 0x26, 0xDF, 0x3B, + 0x64, 0xE0, 0x67, 0x7A, 0xBE, 0x08, 0xF4, 0xE6, 0x1A, 0xF8, 0xFD, 0xBA, 0x0E, 0xBE, 0xB2, 0x28, + 0x6C, 0x45, 0xEA, 0xB1, 0x6C, 0xA8, 0x8E, 0x4F, 0xB8, 0xBC, 0x82, 0x0A, 0xD1, 0x84, 0xAB, 0x03, + 0x6C, 0x30, 0x85, 0xA1, 0x2C, 0x72, 0xA3, 0x08, 0x25, 0x4C, 0x97, 0x32, 0xEB, 0xAD, 0x0E, 0x3E, + 0xE8, 0x8E, 0x2B, 0xF0, 0xCF, 0x13, 0xCA, 0xD1, 0x53, 0xC6, 0xCD, 0x58, 0x98, 0xDE, 0xB0, 0x7E, + 0x0D, 0xBF, 0x94, 0x3E, 0xA7, 0x1C, 0x84, 0xBC, 0xB3, 0x9B, 0x6D, 0x54, 0x32, 0x39, 0x89, 0xF8, + 0x02, 0xAF, 0xBC, 0xB2, 0x53, 0x3B, 0x43, 0xF2, 0xCC, 0xC9, 0x05, 0xF2, 0xC4, 0x88, 0x37, 0x6E, + 0xE1, 0xA1, 0x55, 0x82, 0x7E, 0xBE, 0x83, 0xE0, 0x0B, 0xF8, 0x96, 0x45, 0x61, 0xC1, 0x96, 0x28, + 0x6D, 0x64, 0xCF, 0xF9, 0xC1, 0xC7, 0x3A, 0x18, 0xF3, 0x9A, 0x69, 0x2B, 0x07, 0x57, 0x55, 0xE8, + 0x09, 0xCB, 0x33, 0xC5, 0x4F, 0xBF, 0x0F, 0x9A, 0x22, 0xB1, 0xB3, 0x50, 0x15, 0xA3, 0xCB, 0x8D, + 0x6E, 0x29, 0x56, 0x89, 0x64, 0xAF, 0x5B, 0x0D, 0xD4, 0xE2, 0x6F, 0x6A, 0x38, 0xBD, 0xD8, 0xA1, + 0x7D, 0x0A, 0x6F, 0x7B, 0x07, 0x89, 0x5B, 0xD2, 0xFB, 0x34, 0x5F, 0xA9, 0x0F, 0x41, 0x18, 0xD3, + 0x99, 0xFD, 0xA8, 0x88, 0xFD, 0x4B, 0x9B, 0xCA, 0xAE, 0x5A, 0xB0, 0xEE, 0x23, 0x0F, 0x4B, 0x5C, + 0x99, 0xEA, 0x29, 0xF3, 0xF6, 0x97, 0x5F, 0xF9, 0xAF, 0x28, 0x4F, 0xEC, 0xD6, 0x01, 0x69, 0x8B, + 0x65, 0x08, 0x55, 0xCA, 0x05, 0xC0, 0xB4, 0xB2, 0x64, 0x2A, 0xF5, 0x3E, 0xDA, 0xA2, 0xD2, 0xBB, + 0xDF, 0x17, 0xFF, 0xCF, 0x9E, 0xDE, 0x8A, 0x1E, 0x5F, 0xFD, 0xEA, 0x12, 0x0F, 0xFF, 0x96, 0x20, + 0x0A, 0x15, 0xE6, 0x9B, 0x4F, 0x12, 0x0B, 0xCC, 0x39, 0x4D, 0xFD, 0xD4, 0x7A, 0xDA, 0x24, 0x11, + 0x2D, 0x93, 0x92, 0x9F, 0x3E, 0x3F, 0xA2, 0x9B, 0xAD, 0x98, 0x13, 0xE2, 0x5F, 0xF2, 0x7E, 0x84, + 0xA1, 0x43, 0xAB, 0x76, 0xB8, 0xFC, 0xA0, 0x01, 0x17, 0x38, 0xB3, 0x33, 0x13, 0x4A, 0xF5, 0x15, + 0xA5, 0x56, 0x66, 0xC5, 0x44, 0x0C, 0x88, 0x75, 0x76, 0xA5, 0x7E, 0x57, 0xD4, 0x22, 0xE5, 0x32, + 0x99, 0x60, 0x99, 0x7C, 0x65, 0x29, 0xBA, 0xB0, 0x5B, 0x1F, 0x84, 0x98, 0x0C, 0x06, 0x8A, 0xAE, + 0x96, 0x63, 0x91, 0xB1, 0x75, 0xE6, 0xE6, 0x7A, 0xBF, 0x1E, 0xB5, 0xB6, 0x76, 0x1B, 0xE2, 0xBF, + 0xB4, 0x1F, 0x4D, 0x33, 0xF9, 0x9D, 0x9C, 0x79, 0xE6, 0xF5, 0xA3, 0x8C, 0x72, 0xFE, 0xAE, 0xB1, + 0x13, 0x09, 0x20, 0x91, 0x7C, 0x11, 0x99, 0x68, 0x1A, 0xA7, 0x6B, 0x3F, 0x88, 0xC7, 0xF5, 0x94, + 0x0D, 0xBC, 0x3B, 0xA5, 0x14, 0xD7, 0x8B, 0xA0, 0xA0, 0x70, 0xB4, 0xC2, 0x4E, 0x2F, 0xA8, 0xB1, + 0x0D, 0x7B, 0x8C, 0xD4, 0x96, 0xC1, 0xD1, 0xC5, 0x13, 0x67, 0x24, 0x16, 0x3C, 0xC0, 0xFD, 0x79, + 0x3C, 0x11, 0x69, 0x03, 0xF6, 0x55, 0xF7, 0xF2, 0x09, 0x8B, 0x49, 0x5B, 0xDA, 0x05, 0x3C, 0xDB, + 0x1C, 0x01, 0x1F, 0xDC, 0x4D, 0xE2, 0x09, 0xB6, 0x1F, 0x5F, 0xE2, 0xB0, 0xDF, 0x77, 0xF8, 0x83, + 0x59, 0xCF, 0xEE, 0x8B, 0x14, 0x12, 0xEB, 0xBC, 0x9B, 0xB4, 0x38, 0xFD, 0x38, 0x53, 0xC9, 0xA1, + 0x4E, 0xF6, 0x80, 0xA8, 0xE5, 0x25, 0x89, 0x97, 0xCF, 0x94, 0x06, 0xE4, 0x25, 0xDF, 0x86, 0x46, + 0xA2, 0x54, 0xA7, 0x04, 0xB5, 0xCA, 0x67, 0xF1, 0x95, 0x65, 0x57, 0xE1, 0x38, 0x61, 0xCB, 0x20, + 0xE5, 0x98, 0xF4, 0x07, 0x95, 0x25, 0xBD, 0xBE, 0x9F, 0x87, 0x76, 0x4D, 0x52, 0x96, 0xAE, 0x82, + 0xAE, 0x2C, 0x3C, 0xB6, 0x7C, 0x1A, 0x36, 0xE5, 0x34, 0x13, 0x1B, 0x72, 0x52, 0x8F, 0xFF, 0xE7, + 0x6B, 0x83, 0xDB, 0x88, 0x4A, 0xDB, 0x95, 0x37, 0xFA, 0x9D, 0xA2, 0x49, 0xDB, 0x5A, 0xE3, 0x5C, + 0x95, 0xC7, 0xF8, 0xE0, 0x14, 0x38, 0xB2, 0xCD, 0x09, 0xF4, 0x2A, 0x2A, 0xF7, 0x1A, 0xA1, 0x8E, + 0xB8, 0xBC, 0x3B, 0x51, 0x9A, 0xE4, 0xD1, 0xCF, 0xA7, 0xD1, 0xF9, 0x63, 0x0F, 0x98, 0x3D, 0x61, + 0x51, 0xEC, 0x1B, 0x67, 0x68, 0x88, 0x25, 0x65, 0x0B, 0xA6, 0x32, 0xA2, 0xCD, 0x93, 0xE1, 0x16, + 0x01, 0x12, 0xB2, 0xDA, 0x35, 0xBA, 0x52, 0x66, 0x46, 0x44, 0x8D, 0xB3, 0x19, 0x33, 0xC1, 0x1F, + 0x47, 0x6C, 0x48, 0x7B, 0x5C, 0x8C, 0xA8, 0x68, 0x74, 0xDE, 0x7C, 0xB4, 0xDF, 0x05, 0x54, 0x35, + 0x8A, 0xFE, 0x78, 0xB5, 0x05, 0x78, 0xC3, 0xB4, 0x85, 0x12, 0x88, 0xBB, 0x49, 0x17, 0x46, 0x5D, + 0x7D, 0x1F, 0xF4, 0xB5, 0xD9, 0xEF, 0x62, 0xBA, 0xC4, 0x86, 0x61, 0x0B, 0xE0, 0xC5, 0xEE, 0x69, + 0xEC, 0xF9, 0x52, 0x93, 0x3F, 0xC7, 0x69, 0xE4, 0xD2, 0x9C, 0xE0, 0xEB, 0xB5, 0x5A, 0x55, 0xCE, + 0x87, 0xA3, 0x1C, 0x52, 0x2E, 0xC5, 0x99, 0x92, 0x7F, 0x10, 0x06, 0xC4, 0xA2, 0x5B, 0x77, 0x3D, + 0x53, 0xE8, 0xCA, 0xB5, 0x3B, 0x18, 0x58, 0x54, 0xC6, 0x63, 0xDB, 0x1D, 0xB6, 0x75, 0xD2, 0x69, + 0x64, 0x8A, 0x69, 0x0E, 0xF9, 0x57, 0x41, 0x4C, 0xC2, 0xF3, 0x59, 0x0A, 0x60, 0x76, 0x67, 0x4A, + 0xE6, 0xE8, 0x63, 0xB5, 0x0A, 0x39, 0xDE, 0x95, 0xD6, 0xFB, 0xD4, 0xEC, 0xA3, 0xBD, 0x1A, 0xB1, + 0x8F, 0x54, 0x1C, 0xD7, 0x39, 0x50, 0x8F, 0x92, 0x0D, 0x33, 0x9F, 0x49, 0x10, 0xB2, 0x73, 0x87, + 0x83, 0xF0, 0x72, 0x9D, 0xE7, 0xEA, 0x14, 0xC7, 0x5A, 0x23, 0x6F, 0x54, 0x3E, 0xB5, 0x86, 0x6D, + 0xD6, 0xE2, 0x3E, 0x97, 0x96, 0x5F, 0xF4, 0x1A, 0xFD, 0x8B, 0x96, 0x9B, 0x14, 0xD7, 0x25, 0x3A, + 0x96, 0x25, 0x7B, 0xBE, 0x32, 0x46, 0xC3, 0x20, 0x4E, 0x01, 0x98, 0x0A, 0x27, 0x53, 0x58, 0xFA, + 0xAF, 0x14, 0xE6, 0x6B, 0x99, 0x32, 0x85, 0x87, 0x8F, 0xDA, 0x09, 0x7C, 0x92, 0x9D, 0x4C, 0x87, + 0xF6, 0xB3, 0x67, 0x61, 0xA2, 0x7C, 0x25, 0x5D, 0x4E, 0xA7, 0x6F, 0xF0, 0xCB, 0x6C, 0x6A, 0xC3, + 0xE2, 0x19, 0x33, 0xBE, 0x73, 0x95, 0xE1, 0xBA, 0x39, 0x09, 0x7F, 0xAE, 0x72, 0x8A, 0x4E, 0x74, + 0xA1, 0xBF, 0x5B, 0x1D, 0x34, 0x89, 0xF0, 0x94, 0xE6, 0x84, 0x3C, 0x64, 0x29, 0x04, 0x07, 0x34, + 0xC3, 0x32, 0xEF, 0xF6, 0xE5, 0x24, 0x54, 0x09, 0xFA, 0x81, 0xDB, 0xF1, 0xCF, 0xE5, 0xDB, 0x98, + 0x27, 0xC0, 0xEB, 0xDA, 0x10, 0x73, 0x74, 0x76, 0xCA, 0xD7, 0xFE, 0xDF, 0x82, 0x63, 0x0F, 0x31, + 0x03, 0xBE, 0x10, 0xF4, 0xF6, 0x76, 0xDD, 0x27, 0xAD, 0xE4, 0xC1, 0xFA, 0xC5, 0x5A, 0x71, 0x8D, + 0x59, 0x39, 0x41, 0x6C, 0xDD, 0xFB, 0x4C, 0x5C, 0xB0, 0xB8, 0xF9, 0x67, 0x9C, 0xD7, 0x90, 0x44, + 0xE2, 0xF3, 0x39, 0x4C, 0x84, 0x1A, 0x13, 0x3F, 0xF2, 0xDF, 0x77, 0xA5, 0xF6, 0xAB, 0x69, 0x37, + 0x18, 0x56, 0x03, 0x86, 0xE9, 0xB7, 0xC8, 0xD8, 0x5A, 0xA1, 0x87, 0x00, 0xBC, 0x14, 0x44, 0xFF, + 0x21, 0xDD, 0xAC, 0x99, 0xD2, 0x78, 0xDF, 0x0C, 0xF3, 0xAC, 0x5F, 0xF4, 0x56, 0xE4, 0xAB, 0xCF, + 0x5F, 0x1C, 0x60, 0x7E, 0xFA, 0xDA, 0x36, 0x8A, 0xF2, 0xD4, 0x80, 0x64, 0xC5, 0x54, 0x53, 0xCA, + 0xF3, 0x80, 0x9A, 0x3C, 0x7C, 0x7B, 0x32, 0x30, 0x14, 0xB7, 0x17, 0x9B, 0x42, 0x7C, 0x94, 0x0D, + 0xC4, 0x43, 0x5B, 0xB0, 0x86, 0xE9, 0x1F, 0x80, 0xCD, 0x45, 0x97, 0x3D, 0x8A, 0xD0, 0x22, 0x91, + 0xA0, 0x14, 0xA5, 0xD7, 0x71, 0x07, 0x8D, 0xAB, 0x69, 0xE8, 0x38, 0x98, 0xEE, 0x70, 0x3D, 0x7B, + 0x86, 0x13, 0xDE, 0xAF, 0xE5, 0x89, 0x5A, 0x5F, 0x1F, 0xF9, 0xA5, 0x3F, 0xED, 0x62, 0xE6, 0x65, + 0x3B, 0x86, 0xF9, 0x76, 0xD6, 0x5A, 0x57, 0x54, 0x8B, 0x0D, 0x39, 0xEC, 0x9F, 0x00, 0xBF, 0x4E, + 0xF8, 0x62, 0x51, 0x83, 0x74, 0x16, 0x00, 0x3A, 0x4F, 0x71, 0x18, 0x73, 0xF0, 0x41, 0x71, 0xB4, + 0xDC, 0x79, 0xFC, 0x32, 0xDB, 0x38, 0x0C, 0x3F, 0x1B, 0x66, 0xA4, 0x27, 0xED, 0xA7, 0xE2, 0xE6, + 0xB0, 0x51, 0xF6, 0xBD, 0xEF, 0x2E, 0x0E, 0x10, 0x8F, 0x1D, 0x40, 0xDF, 0x85, 0x67, 0xC7, 0x25, + 0x11, 0x7F, 0x50, 0x99, 0xC8, 0xAE, 0xDF, 0x6A, 0xAF, 0x70, 0x8C, 0xD4, 0xB5, 0x6A, 0xA5, 0x21, + 0x1C, 0xBF, 0x0C, 0x75, 0xA2, 0x40, 0x03, 0x17, 0x58, 0x8C, 0x84, 0x4D, 0x82, 0x29, 0xE5, 0x7C, + 0x05, 0xA1, 0xAF, 0x48, 0x07, 0xD1, 0xF7, 0x53, 0xBC, 0x02, 0xF7, 0xCD, 0x60, 0x35, 0xEE, 0x04, + 0x03, 0xE1, 0x3A, 0xAA, 0x71, 0x54, 0x5B, 0xDD, 0x86, 0x68, 0xFB, 0xC6, 0xBC, 0xCF, 0xCD, 0x55, + 0xBC, 0x0E, 0x0D, 0x8D, 0x7B, 0x70, 0x1F, 0xE4, 0xEC, 0x2C, 0x91, 0x22, 0xF6, 0x55, 0xC9, 0x07, + 0x0F, 0x26, 0x60, 0x4F, 0xB0, 0x27, 0xFA, 0xAB, 0xBF, 0x3B, 0xF1, 0x3F, 0x52, 0xB8, 0xC7, 0x7B, + 0x52, 0xBF, 0x6E, 0xA4, 0x87, 0xCD, 0x40, 0x62, 0x4D, 0xDA, 0xD1, 0x37, 0x77, 0x44, 0xB3, 0x1D, + 0xD6, 0x2F, 0x9A, 0xA8, 0x61, 0x54, 0x6A, 0x1E, 0x2E, 0xE2, 0xC0, 0xBF, 0x7D, 0xAD, 0xB9, 0xDB, + 0x52, 0x5C, 0x0F, 0x15, 0x7F, 0x40, 0x8B, 0xC3, 0x4E, 0xC5, 0xC3, 0x59, 0x5A, 0x19, 0x3F, 0xA1, + 0xB3, 0x58, 0x3A, 0xC2, 0x06, 0x5B, 0x16, 0xF8, 0xEA, 0xFA, 0xB6, 0x8D, 0x93, 0xFF, 0xC4, 0x96, + 0x2C, 0x9F, 0xD0, 0xAB, 0x5A, 0x2B, 0x81, 0x17, 0xA9, 0x71, 0x38, 0x0F, 0x01, 0xEF, 0x5A, 0xC0, + 0xE9, 0x9F, 0x8B, 0x63, 0x47, 0x89, 0x50, 0xC2, 0xFB, 0x8A, 0x8B, 0x9F, 0xEE, 0xC4, 0xC4, 0x7A, + 0xDC, 0xAD, 0xC3, 0x6A, 0x70, 0xA4, 0x71, 0x53, 0xFD, 0xA9, 0x0D, 0xC0, 0x62, 0x23, 0xB8, 0x9D, + 0xAE, 0xA2, 0x12, 0x0B, 0x18, 0x42, 0xB6, 0x93, 0x2A, 0x85, 0x60, 0x09, 0x59, 0x69, 0x52, 0x1F, + 0x1E, 0xBA, 0xBF, 0x0F, 0xA6, 0x8E, 0xB0, 0x8A, 0x03, 0xCA, 0xC5, 0x1C, 0x8E, 0x89, 0xF2, 0x50, + 0xD7, 0x1A, 0xA9, 0x63, 0x83, 0x0F, 0x6D, 0x06, 0x27, 0x1F, 0x40, 0xDA, 0x0B, 0x9E, 0xEB, 0x1F, + 0x7E, 0x4F, 0x8A, 0xF0, 0x38, 0x86, 0x08, 0xC6, 0x3A, 0xFF, 0x29, 0xCC, 0xA7, 0x10, 0x27, 0xF3, + 0x99, 0x3E, 0x52, 0xF3, 0x0F, 0x83, 0x93, 0x9F, 0x63, 0xE8, 0x23, 0x41, 0x71, 0x98, 0x25, 0x1B, + 0xC9, 0x89, 0x15, 0x8F, 0xC8, 0x72, 0x35, 0x72, 0x7D, 0xF2, 0x36, 0x31, 0x64, 0xF5, 0x3A, 0x4C, + 0x15, 0x9B, 0x30, 0x77, 0x36, 0x03, 0xB9, 0xEE, 0xCA, 0x61, 0x22, 0x7C, 0xCF, 0xEE, 0x6C, 0xE4, + 0xEC, 0x83, 0x67, 0x10, 0x07, 0x7A, 0x21, 0x97, 0xDF, 0xC3, 0x2A, 0x27, 0x47, 0xDB, 0x1A, 0x76, + 0x2D, 0xA5, 0x9D, 0xD7, 0x39, 0x54, 0x4F, 0x62, 0x9C, 0xFD, 0x77, 0x0E, 0xB0, 0x4A, 0x0A, 0xD9, + 0x46, 0xC2, 0x28, 0x49, 0xB0, 0x53, 0x99, 0x2A, 0xC2, 0x81, 0xF9, 0x8A, 0xE1, 0x01, 0xDA, 0xCC, + 0x31, 0x60, 0x9B, 0x32, 0x4B, 0x69, 0x2B, 0x89, 0x00, 0xDA, 0xCD, 0x41, 0x0B, 0x13, 0xC0, 0x3C, + 0x4A, 0xD0, 0x32, 0x0A, 0x45, 0x31, 0x54, 0x38, 0x9E, 0x74, 0x56, 0x60, 0x8A, 0xFA, 0x0C, 0x0C, + 0xC8, 0xDC, 0x4E, 0x12, 0x9A, 0xD0, 0x2B, 0xAC, 0xF3, 0x16, 0xD3, 0xE4, 0x5C, 0xA8, 0x3B, 0x8A, + 0x8E, 0x04, 0x4B, 0x09, 0xDE, 0x91, 0x1C, 0xF2, 0x3D, 0xB5, 0x27, 0x23, 0x9A, 0x5F, 0xCA, 0xCE, + 0x1D, 0x81, 0x25, 0xD3, 0x0B, 0x07, 0x3B, 0xA2, 0xED, 0xC1, 0x68, 0xA3, 0x10, 0x1E, 0x49, 0xED, + 0x2B, 0x02, 0xD4, 0x65, 0x6B, 0xDE, 0xF7, 0xE8, 0x3D, 0xC3, 0x41, 0x1E, 0x75, 0xDB, 0xD0, 0xE4, + 0xA7, 0xFF, 0xFC, 0xB3, 0x0D, 0xAE, 0x72, 0x6D, 0xF2, 0x16, 0xF9, 0x4C, 0x9B, 0x2C, 0x83, 0x55, + 0x53, 0x32, 0xB1, 0x4E, 0xE7, 0x7E, 0x7F, 0xF6, 0xBE, 0xE4, 0x7A, 0xF3, 0xDB, 0x73, 0xA5, 0xDC, + 0xB3, 0x1F, 0x1B, 0x9E, 0x93, 0x58, 0x58, 0x4C, 0xDB, 0xED, 0x8C, 0x02, 0xB7, 0x43, 0x10, 0x7F, + 0x32, 0xF0, 0xFC, 0xD2, 0xDA, 0x18, 0xA6, 0x74, 0x80, 0x12, 0x9C, 0xBB, 0xB9, 0xA9, 0x03, 0x76, + 0xC9, 0x4E, 0xE0, 0xE3, 0x63, 0x96, 0xC8, 0x32, 0x04, 0x06, 0x15, 0x52, 0xD1, 0xB6, 0x03, 0x1B, + 0x5D, 0xF2, 0x40, 0x43, 0x37, 0xCF, 0x7C, 0xF5, 0xC4, 0xAB, 0x8B, 0x83, 0x63, 0x5D, 0xE3, 0x3B, + 0x3B, 0x66, 0xE6, 0x19, 0xEF, 0x51, 0x6B, 0x60, 0x6F, 0x3E, 0x71, 0x3D, 0x8E, 0x5A, 0x77, 0xD2, + 0x57, 0x9A, 0x06, 0xE9, 0xBB, 0x8A, 0x50, 0x58, 0x90, 0xF1, 0x17, 0xD7, 0x18, 0x9C, 0x24, 0x65, + 0x3D, 0x40, 0xA5, 0xA1, 0xD8, 0x24, 0x4B, 0xAA, 0x8A, 0x47, 0x3F, 0x0D, 0xB6, 0x60, 0xE6, 0x75, + 0xCD, 0x45, 0x6D, 0x54, 0xD9, 0x67, 0x65, 0xE0, 0x04, 0xCC, 0xBE, 0xCC, 0xAA, 0x8E, 0x3D, 0xB9, + 0x1E, 0x03, 0x25, 0x25, 0x31, 0x88, 0x36, 0xF6, 0x52, 0xD7, 0x4E, 0x75, 0xB5, 0xEA, 0x05, 0x83, + 0x59, 0xAD, 0xAF, 0xF4, 0x13, 0xCE, 0x5D, 0xF4, 0x52, 0x98, 0xBC, 0x63, 0xFE, 0xB0, 0xC5, 0x55, + 0xBD, 0x5A, 0x65, 0x3E, 0xAF, 0x24, 0x4C, 0x5E, 0xEA, 0x9A, 0x44, 0x32, 0x0E, 0x39, 0xCA, 0x60, + 0xB2, 0xBF, 0x62, 0x40, 0x19, 0x57, 0xDE, 0x7C, 0x70, 0xD7, 0xC3, 0x0E, 0x9A, 0x98, 0x6F, 0x26, + 0x22, 0x45, 0xC4, 0xD1, 0x8E, 0x6B, 0xC9, 0x3F, 0x1E, 0x71, 0x4F, 0x2E, 0x86, 0x42, 0x73, 0x00, + 0xEB, 0x98, 0x22, 0x03, 0x1F, 0x6F, 0xC3, 0xAF, 0xD0, 0x55, 0x8F, 0x95, 0x6F, 0x8E, 0x4B, 0xF0, + 0x21, 0x1D, 0xA7, 0xB1, 0xE8, 0x6B, 0xC7, 0x8A, 0xAD, 0x69, 0xD7, 0x6A, 0x7F, 0x09, 0x3A, 0x9F, + 0xBF, 0x30, 0x27, 0x18, 0x00, 0x11, 0xF2, 0x96, 0xAB, 0x57, 0xD3, 0x67, 0x5D, 0x2A, 0x36, 0xCF, + 0xE2, 0x05, 0xBB, 0x01, 0x83, 0x0B, 0xC7, 0x6D, 0xE9, 0xFD, 0x5A, 0xC8, 0x0D, 0x9C, 0xC0, 0xA2, + 0x41, 0x8D, 0x0E, 0x53, 0xB2, 0xD2, 0x2B, 0xD8, 0xE5, 0x4C, 0xEE, 0x81, 0x52, 0xED, 0xE8, 0xEA, + 0xF1, 0xF3, 0x2A, 0x5D, 0xEC, 0x2D, 0x0E, 0xFD, 0x76, 0x26, 0x4C, 0x25, 0x78, 0x26, 0x6F, 0x2F, + 0xF7, 0x31, 0xAB, 0xC0, 0x6C, 0x80, 0x1F, 0x2B, 0x8B, 0x1E, 0xC1, 0x09, 0x46, 0x5E, 0x94, 0x19, + 0xED, 0x07, 0x94, 0xEC, 0xCF, 0x3B, 0xC6, 0x51, 0x29, 0xC2, 0x87, 0xD4, 0x55, 0xD0, 0xAD, 0x82, + 0x66, 0x27, 0x61, 0x18, 0xDD, 0xB8, 0xBD, 0xF9, 0xE1, 0xCA, 0xAA, 0xBA, 0x49, 0x39, 0xD6, 0x43, + 0xA9, 0x10, 0x12, 0x7C, 0xA6, 0x82, 0xD8, 0xDB, 0x11, 0x76, 0x9D, 0xF0, 0x92, 0xFB, 0x31, 0xC1, + 0x9C, 0x31, 0x78, 0x1C, 0x11, 0xD6, 0xF3, 0x1F, 0x14, 0x39, 0xC6, 0x33, 0x46, 0x58, 0x8C, 0xE9, + 0x2B, 0x87, 0x94, 0xA6, 0xFA, 0x55, 0x5A, 0x3C, 0x39, 0x60, 0xD0, 0x26, 0x0F, 0xB3, 0x56, 0x18, + 0x77, 0x9C, 0x1B, 0x01, 0xBA, 0xE6, 0xB2, 0x1E, 0x8B, 0xA0, 0x63, 0x2D, 0x7E, 0xA2, 0x30, 0xFC, + 0xDF, 0x31, 0x99, 0xB2, 0xD6, 0x1E, 0xD3, 0xAB, 0xB7, 0xFA, 0x72, 0xB0, 0x6F, 0xE5, 0x6B, 0x9F, + 0xAF, 0xB4, 0xF0, 0x53, 0x06, 0x9C, 0xB0, 0x98, 0x6B, 0xF4, 0x5A, 0x52, 0xDB, 0xD0, 0x13, 0xED, + 0x73, 0x70, 0x11, 0xBB, 0xD0, 0x98, 0x58, 0xCA, 0x29, 0x44, 0xCB, 0x7C, 0x2D, 0x43, 0xDE, 0x4F, + 0xBF, 0x13, 0x06, 0xDD, 0x3C, 0x69, 0x49, 0xD2, 0xD7, 0xA7, 0x24, 0x9E, 0x0D, 0x3C, 0x8C, 0x73, + 0x0F, 0xB2, 0x4F, 0x16, 0x83, 0x7E, 0x7B, 0x3A, 0xD4, 0x49, 0x42, 0x26, 0x9C, 0x6F, 0xAF, 0xD6, + 0x73, 0xEF, 0x29, 0x3D, 0x1A, 0x21, 0x58, 0x48, 0xF7, 0xEE, 0xD2, 0xC8, 0x06, 0x4D, 0xB2, 0x3D, + 0x1E, 0xD6, 0xF6, 0xF3, 0x25, 0xC8, 0xD5, 0xF4, 0xB6, 0x07, 0x2C, 0xB0, 0x03, 0xDE, 0x83, 0xE0, + 0x1C, 0x68, 0x2E, 0x78, 0xB6, 0xDA, 0x99, 0xA6, 0xBD, 0xE8, 0x1D, 0x47, 0x6E, 0x7A, 0x4C, 0xC5, + 0xE4, 0x54, 0xEA, 0xDB, 0xB1, 0x6F, 0x9F, 0x53, 0xA6, 0x41, 0xE2, 0x24, 0x6C, 0x9C, 0x88, 0xF7, + 0x88, 0xA8, 0x90, 0x0D, 0x34, 0x61, 0xAA, 0x7D, 0x52, 0x5F, 0x8D, 0x81, 0xBE, 0xC9, 0x3E, 0x36, + 0x8D, 0x69, 0x81, 0x0D, 0x24, 0x7D, 0xCE, 0x03, 0xB8, 0x4E, 0x9C, 0xFD, 0x5A, 0x4A, 0x45, 0xAF, + 0x45, 0xB5, 0xFF, 0x49, 0xEA, 0x6C, 0xF7, 0xB9, 0xE5, 0xC1, 0xA6, 0x57, 0xF3, 0xCA, 0xCC, 0x46, + 0xD2, 0x20, 0xB3, 0xB1, 0xC0, 0x18, 0xEE, 0x82, 0xE4, 0x00, 0x3C, 0xA7, 0x8B, 0xA6, 0x3A, 0xDA, + 0x82, 0x53, 0x3C, 0x42, 0x4C, 0x3B, 0x16, 0xD0, 0x3E, 0x0E, 0xBA, 0x36, 0xA6, 0xEA, 0x36, 0x16, + 0x80, 0xA3, 0x51, 0xFD, 0xF8, 0xFA, 0xE5, 0x75, 0x64, 0x17, 0x0C, 0xE5, 0xAE, 0xB2, 0xE5, 0x14, + 0xC1, 0xA9, 0xAE, 0x3A, 0x7E, 0x4D, 0x0E, 0x5C, 0x67, 0x31, 0x02, 0xD2, 0x4D, 0xB3, 0xD6, 0xC6, + 0xE6, 0x86, 0xC2, 0x62, 0xE6, 0xB6, 0x53, 0x2C, 0x29, 0x72, 0x90, 0x55, 0xAC, 0x1C, 0xE7, 0x7F, + 0x7F, 0xA3, 0xE8, 0x21, 0xF0, 0x2D, 0x3E, 0x8A, 0xA3, 0xA2, 0xA2, 0x29, 0xEC, 0x36, 0x4B, 0x89, + 0x1C, 0xB6, 0xC1, 0xB9, 0x4A, 0x8F, 0x65, 0xDF, 0x97, 0x29, 0x0F, 0x0B, 0xB1, 0x61, 0x24, 0xA2, + 0xD2, 0x57, 0x7A, 0x99, 0xF7, 0x1D, 0xC8, 0xB4, 0xDD, 0xEE, 0x7A, 0xBE, 0x2E, 0x46, 0x9A, 0xF6, + 0x92, 0x13, 0xAC, 0x98, 0x64, 0x4C, 0xDD, 0x6B, 0x03, 0xD3, 0xF4, 0x14, 0xC9, 0x7D, 0xCE, 0x9B, + 0xF7, 0xD4, 0x80, 0xB1, 0x2A, 0x66, 0x33, 0xA4, 0xE2, 0x45, 0x99, 0x95, 0x77, 0xE1, 0x3E, 0x8A, + 0x43, 0x85, 0xD9, 0x79, 0x69, 0x0D, 0x55, 0xCF, 0x09, 0xF4, 0xFC, 0x07, 0x39, 0x20, 0x26, 0xB4, + 0x8B, 0xD0, 0x60, 0xFB, 0x42, 0x41, 0xEF, 0x02, 0x5F, 0x0D, 0xC7, 0x7F, 0x09, 0xFA, 0x26, 0x94, + 0x7A, 0xCD, 0xDE, 0x43, 0x86, 0x44, 0xD6, 0xC6, 0xB1, 0x77, 0x13, 0xB1, 0x08, 0xC9, 0xDD, 0x99, + 0xF0, 0xED, 0x7B, 0xB0, 0xAB, 0x31, 0x6D, 0x5B, 0x66, 0xA3, 0x53, 0xE2, 0x3B, 0x0F, 0x31, 0xA2, + 0x63, 0x6E, 0x05, 0xAD, 0xC6, 0x74, 0xC5, 0x2D, 0xB3, 0x79, 0xEB, 0x66, 0xF3, 0x6B, 0x79, 0x02, + 0x7A, 0x7D, 0x49, 0x59, 0x30, 0x04, 0x29, 0xD8, 0x5E, 0xF7, 0xF3, 0x6C, 0x5E, 0xC2, 0xA6, 0xFF, + 0x1B, 0x5A, 0xFE, 0x01, 0x54, 0x40, 0xEF, 0xA0, 0xD5, 0xDB, 0x47, 0xED, 0x2A, 0x9B, 0x85, 0x12, + 0x9F, 0x74, 0x5D, 0xB7, 0xA6, 0x80, 0x22, 0x34, 0x87, 0x81, 0x7E, 0x15, 0x87, 0x62, 0x03, 0x87, + 0x62, 0x6B, 0x85, 0xF1, 0x37, 0x55, 0x55, 0x31, 0x18, 0xBD, 0xEF, 0x57, 0x1D, 0x21, 0x5E, 0x87, + 0x37, 0x53, 0x61, 0x7B, 0xA5, 0x80, 0x71, 0x2C, 0x72, 0x83, 0x64, 0x73, 0xF2, 0x4C, 0xA0, 0x3F, + 0x4C, 0x3E, 0x21, 0xF3, 0x96, 0xBB, 0x9C, 0x05, 0xE1, 0x12, 0x47, 0xA2, 0x6E, 0xF6, 0x67, 0xFE, + 0x1B, 0x3F, 0x74, 0xA5, 0x6B, 0x2E, 0xB3, 0x77, 0x02, 0x64, 0x30, 0xAF, 0x6C, 0x64, 0x2E, 0x69, + 0x92, 0xA5, 0xD3, 0xA8, 0xEE, 0xEF, 0xB7, 0x89, 0xD9, 0x31, 0x1B, 0x61, 0xC8, 0x91, 0xF1, 0xC5, + 0x59, 0x7D, 0xCE, 0xDF, 0xFB, 0xF2, 0x10, 0xF7, 0x42, 0x02, 0xEC, 0x70, 0x2F, 0xE4, 0x02, 0xB4, + 0xFB, 0xA0, 0xFC, 0x83, 0x58, 0x68, 0xA2, 0x8E, 0x01, 0x8B, 0x10, 0xF6, 0x30, 0x86, 0xAA, 0x5A, + 0xC4, 0x95, 0x61, 0x02, 0x8E, 0xF2, 0xB7, 0x6B, 0x6C, 0x80, 0x5C, 0xCB, 0x11, 0x66, 0x97, 0x60, + 0x70, 0xD4, 0x06, 0xA9, 0xC7, 0x80, 0xE3, 0x2C, 0xA4, 0xE1, 0xAA, 0x34, 0x92, 0x13, 0x57, 0x05, + 0xF9, 0x70, 0xF3, 0xF4, 0x80, 0x73, 0xF2, 0x16, 0xDA, 0xBD, 0x39, 0x51, 0xD1, 0x40, 0xC1, 0x59, + 0x04, 0xCD, 0xE4, 0x79, 0x63, 0x24, 0x69, 0xC6, 0x99, 0x2F, 0x4D, 0x0D, 0x1C, 0x9C, 0x15, 0xED, + 0x41, 0x47, 0x12, 0x78, 0x6F, 0x8E, 0xFF, 0xA7, 0x34, 0xB8, 0x8B, 0x0C, 0x70, 0x96, 0x07, 0x0B, + 0x49, 0x42, 0x59, 0xFE, 0x5A, 0x08, 0x76, 0x36, 0x3D, 0x7D, 0xBA, 0x10, 0x1B, 0x11, 0xB4, 0x6B, + 0x1C, 0x59, 0x60, 0x02, 0x36, 0x30, 0xD9, 0xEC, 0xBA, 0xEE, 0x22, 0xFD, 0x0F, 0x2E, 0xA2, 0xE2, + 0x70, 0x9C, 0x0D, 0x18, 0x58, 0x88, 0x4A, 0x0D, 0xE7, 0x0E, 0xEF, 0xD8, 0x6F, 0xA7, 0x70, 0x12, + 0x9D, 0x06, 0x4C, 0x8C, 0xAD, 0x1A, 0x28, 0x01, 0xB6, 0x23, 0x53, 0x76, 0xDD, 0x3F, 0x17, 0x87, + 0x0B, 0xC1, 0xEB, 0x9C, 0x44, 0x67, 0x1B, 0x79, 0xE0, 0x67, 0xB2, 0x2A, 0x99, 0x72, 0xEB, 0x4C, + 0xB4, 0x17, 0x2E, 0xB5, 0xE8, 0x52, 0x1E, 0xCB, 0x3A, 0x3D, 0xF7, 0xF2, 0x21, 0xC7, 0xF1, 0x29, + 0x97, 0x22, 0x31, 0x2C, 0x39, 0x8A, 0xAF, 0x47, 0xF9, 0x3B, 0xA9, 0x8B, 0x2B, 0xEF, 0xE2, 0xF0, + 0x11, 0x59, 0xFC, 0xE4, 0x56, 0xFF, 0x4E, 0xA7, 0x92, 0xE5, 0xE5, 0x26, 0x16, 0xC8, 0x2C, 0x35, + 0xD2, 0x70, 0x9F, 0xAE, 0xA7, 0x08, 0x16, 0x2B, 0x64, 0xA1, 0xF6, 0xF3, 0xC1, 0x43, 0x27, 0x92, + 0x46, 0x4E, 0xA2, 0x01, 0x72, 0x18, 0x08, 0xAB, 0x22, 0x42, 0x1B, 0x9E, 0x35, 0xAE, 0xB3, 0xE6, + 0x42, 0x1B, 0x49, 0x31, 0xBB, 0xA4, 0xD0, 0xD6, 0x7A, 0xEB, 0xFE, 0x32, 0x37, 0x7F, 0xE6, 0x2F, + 0x75, 0x54, 0x1D, 0x88, 0x9F, 0x81, 0xEE, 0xF0, 0x97, 0xC9, 0x12, 0x80, 0x47, 0x5C, 0xCA, 0x3B, + 0x45, 0xF4, 0x63, 0xC3, 0x16, 0x2D, 0x7E, 0xCD, 0x80, 0xC2, 0xBA, 0x50, 0x1D, 0xC2, 0x31, 0x72, + 0xF0, 0x27, 0x97, 0xB0, 0xF4, 0x69, 0x43, 0x2B, 0x26, 0x89, 0x28, 0xFC, 0xBD, 0x03, 0x6A, 0x4A, + 0x22, 0x5D, 0xD3, 0x7D, 0xEC, 0xC8, 0xEC, 0x7B, 0x15, 0xFA, 0x05, 0x5D, 0x73, 0x6B, 0x5B, 0x1B, + 0xC9, 0x83, 0xD0, 0xFA, 0x24, 0xBA, 0x97, 0x11, 0x30, 0x04, 0xD3, 0x11, 0xCE, 0x24, 0xBD, 0x71, + 0xB7, 0xAA, 0xB2, 0xC2, 0x43, 0xC2, 0x67, 0x3B, 0x9C, 0x28, 0x62, 0x52, 0xF0, 0xFA, 0xCB, 0xFA, + 0xDF, 0x4F, 0xC9, 0x23, 0xD1, 0x94, 0xE1, 0x5F, 0x2A, 0xF2, 0xC7, 0x5F, 0x76, 0x6B, 0x86, 0x28, + 0x29, 0xF1, 0x54, 0x4F, 0x7A, 0x4D, 0xFD, 0xD0, 0x51, 0xFA, 0xBC, 0x6F, 0x7B, 0x44, 0xE5, 0xB0, + 0xF3, 0xC0, 0x34, 0x80, 0x6D, 0xE6, 0xDD, 0xCD, 0x7F, 0x67, 0x7B, 0x15, 0xC5, 0xE5, 0x14, 0x64, + 0x80, 0x81, 0xD9, 0x47, 0xCE, 0x71, 0x62, 0x94, 0xCE, 0x41, 0x61, 0xFA, 0xDD, 0x5A, 0x6D, 0xC1, + 0x28, 0x87, 0x39, 0xC4, 0xBC, 0x89, 0x3A, 0x99, 0x18, 0x80, 0xDC, 0x50, 0x72, 0xCF, 0x67, 0x4D, + 0x77, 0x6D, 0x6A, 0xB4, 0x17, 0x85, 0xD6, 0x2B, 0xC3, 0x4A, 0x7C, 0xD1, 0xF3, 0x0E, 0xA4, 0x8F, + 0x3B, 0xDA, 0x8A, 0x7B, 0x0A, 0x37, 0x7D, 0x36, 0xEC, 0x89, 0x87, 0xD9, 0x88, 0xB7, 0xC9, 0x1F, + 0xEB, 0xEE, 0x25, 0x46, 0xA9, 0x3B, 0x19, 0x16, 0x17, 0x2D, 0x0F, 0x8C, 0xEB, 0x19, 0xF3, 0x47, + 0xC7, 0x21, 0xA8, 0x1E, 0x7F, 0xC4, 0xE3, 0x6B, 0x96, 0x1D, 0x63, 0xDD, 0xC2, 0xEF, 0xB2, 0x65, + 0x60, 0x07, 0xE5, 0xD3, 0x48, 0x49, 0x9A, 0xF2, 0xB0, 0x76, 0x2D, 0xFB, 0x68, 0xF8, 0xAD, 0xE9, + 0x3C, 0x52, 0x37, 0x9A, 0xD1, 0xAE, 0x16, 0x37, 0x2E, 0xB3, 0x63, 0xE0, 0x66, 0xB1, 0x4D, 0x49, + 0x83, 0xD2, 0xEA, 0x20, 0xFD, 0x43, 0x84, 0x5B, 0x22, 0xBC, 0x0C, 0xA1, 0x85, 0x28, 0xF7, 0x45, + 0xF1, 0x2A, 0xC2, 0xFE, 0x87, 0x4C, 0xFC, 0x0A, 0x5B, 0xD9, 0x84, 0x7A, 0xAC, 0x8C, 0xBD, 0xDF, + 0xDC, 0xA5, 0xFC, 0xD0, 0x85, 0x65, 0xA2, 0x73, 0x1C, 0x7C, 0xFD, 0xF9, 0xBA, 0x1E, 0xBD, 0x5F, + 0x06, 0xE8, 0xFC, 0x62, 0xD1, 0xF7, 0x13, 0x52, 0xE3, 0xC2, 0xEB, 0xEE, 0x0E, 0x7E, 0x9D, 0x8A, + 0x19, 0x3E, 0xA2, 0x62, 0x06, 0xC5, 0xA1, 0xDC, 0x6B, 0x4A, 0x59, 0xA6, 0x57, 0x73, 0xCB, 0x57, + 0x16, 0x99, 0xFB, 0x93, 0x36, 0xDF, 0x0E, 0x1A, 0x38, 0xD4, 0x89, 0x02, 0x79, 0xB6, 0xA8, 0x52, + 0xCB, 0x2E, 0x96, 0xD4, 0xD8, 0x52, 0xA9, 0x7C, 0xE3, 0x97, 0x47, 0x6F, 0x6E, 0x82, 0x6D, 0x3A, + 0x01, 0x8F, 0x2F, 0x59, 0xDF, 0x93, 0xBA, 0x52, 0xC4, 0x46, 0xDA, 0xC5, 0x0C, 0x2E, 0x40, 0xB8, + 0x37, 0x55, 0x40, 0xB8, 0x13, 0xCD, 0x51, 0x96, 0xCE, 0x4A, 0x6C, 0x0D, 0xF9, 0x5A, 0xE6, 0x34, + 0x95, 0xF0, 0xFF, 0x54, 0x93, 0x05, 0x9D, 0x56, 0x94, 0xF7, 0x23, 0x90, 0x00, 0x44, 0xA7, 0xD9, + 0x86, 0x71, 0xB2, 0xFD, 0x58, 0x19, 0xBB, 0xEC, 0x6B, 0x90, 0x07, 0x2B, 0x7A, 0x20, 0x4B, 0xFD, + 0x0E, 0xB8, 0xF8, 0x00, 0x13, 0xC2, 0xF2, 0x32, 0x39, 0xED, 0x71, 0x59, 0x71, 0xC4, 0xDC, 0xE5, + 0xC2, 0xA9, 0x2B, 0x7B, 0x52, 0x00, 0xCB, 0x49, 0xB4, 0x00, 0xE6, 0x98, 0x13, 0xC1, 0x2F, 0x3A, + 0x19, 0x86, 0xD5, 0x74, 0xCD, 0xBC, 0xBA, 0x4C, 0x48, 0x00, 0x8E, 0x22, 0xD5, 0xAC, 0x11, 0xEF, + 0xC8, 0xCD, 0x99, 0xBA, 0xBC, 0x0F, 0xD4, 0xC0, 0xAE, 0x15, 0x2F, 0x82, 0x6D, 0x4D, 0x44, 0x10, + 0xF1, 0xF5, 0x55, 0xF0, 0x00, 0xAF, 0xEA, 0x96, 0x1F, 0xE6, 0xA6, 0x9A, 0x78, 0xDD, 0x6D, 0xD5, + 0xDF, 0xA4, 0x4D, 0xAE, 0x05, 0xEE, 0x12, 0x9F, 0x9B, 0x99, 0xAC, 0xE4, 0xBE, 0x9E, 0x56, 0xCC, + 0x4B, 0x6D, 0x26, 0xB9, 0x56, 0x9B, 0x9B, 0x52, 0x6D, 0x14, 0x28, 0x7D, 0xE8, 0x75, 0xCB, 0x59, + 0xC0, 0x50, 0x69, 0x6B, 0xD7, 0x68, 0x06, 0xA8, 0x38, 0xD1, 0xBB, 0xD9, 0xA3, 0x3D, 0xA1, 0xBD, + 0x7D, 0x9E, 0xD2, 0xB9, 0x5D, 0x35, 0x02, 0xE0, 0xD4, 0xAF, 0x66, 0x56, 0x7D, 0xF4, 0x88, 0x74, + 0x3C, 0x28, 0x2C, 0xBA, 0x20, 0xC1, 0x2A, 0x93, 0xA9, 0xBA, 0x90, 0xE8, 0xC2, 0xE9, 0x15, 0xC8, + 0x8F, 0xBD, 0x27, 0xDE, 0x21, 0xBF, 0x56, 0x69, 0x93, 0x72, 0x7E, 0xE4, 0xE7, 0x7D, 0xE8, 0x4D, + 0xBF, 0x24, 0xA2, 0x77, 0xC0, 0xE0, 0x30, 0xD9, 0xEE, 0x82, 0xCD, 0x21, 0x60, 0xFC, 0xD1, 0x6F, + 0xB4, 0x40, 0x01, 0xFE, 0xF4, 0x73, 0xAF, 0xBB, 0xF6, 0x2B, 0x41, 0xFC, 0xDE, 0x74, 0x78, 0xE5, + 0x7E, 0xAB, 0xC9, 0xED, 0x63, 0x4B, 0x3E, 0x1A, 0x27, 0xCD, 0xBF, 0x85, 0xA4, 0x70, 0x92, 0x36, + 0x56, 0x70, 0x4A, 0xEE, 0x45, 0xAB, 0x33, 0x0A, 0x76, 0xB8, 0x0B, 0xEA, 0x55, 0xC7, 0x4E, 0xD7, + 0xD9, 0xC7, 0x10, 0x8D, 0x09, 0xFA, 0x10, 0x30, 0x62, 0x20, 0xE5, 0xBC, 0xFB, 0x74, 0x72, 0xA6, + 0x77, 0xB5, 0xBB, 0xD7, 0xD6, 0x60, 0x3A, 0x6B, 0x5D, 0xF5, 0x35, 0xF4, 0x84, 0xA0, 0x19, 0x49, + 0x36, 0x00, 0xC9, 0x35, 0xCC, 0xF7, 0xFE, 0x92, 0xF9, 0x4B, 0x8B, 0xB3, 0xBE, 0x98, 0xBF, 0xF4, + 0x25, 0xB1, 0x62, 0x4D, 0x41, 0xA0, 0xF7, 0x36, 0x6C, 0x86, 0x3C, 0x4F, 0xC4, 0xF8, 0xF2, 0xFC, + 0xE6, 0x34, 0x30, 0x95, 0x32, 0x9D, 0xE5, 0x85, 0x70, 0xD8, 0xB8, 0xD6, 0xD9, 0x42, 0xB9, 0x05, + 0x6E, 0x4B, 0x6F, 0x29, 0x33, 0x8E, 0xE4, 0x31, 0x3C, 0x21, 0x7B, 0x19, 0x31, 0x97, 0xD5, 0x62, + 0x6B, 0xF6, 0x98, 0x3C, 0xA5, 0x54, 0x18, 0x16, 0x03, 0x49, 0x51, 0x1F, 0x13, 0x37, 0xFB, 0x18, + 0x9D, 0xCF, 0x16, 0x43, 0x34, 0x7D, 0xB6, 0x5C, 0x9E, 0x74, 0x4D, 0x66, 0x23, 0x99, 0xDE, 0x6E, + 0x57, 0xFE, 0x47, 0x0D, 0x3B, 0x59, 0x3F, 0x01, 0x79, 0x75, 0x0D, 0x78, 0x62, 0x4A, 0xA5, 0xF2, + 0xF8, 0xD6, 0xAE, 0x11, 0x85, 0x88, 0x13, 0x98, 0x07, 0x0B, 0x92, 0x99, 0xC6, 0x9F, 0x85, 0x24, + 0xB1, 0x48, 0xEF, 0x59, 0x11, 0xCB, 0xAB, 0x92, 0xE4, 0x58, 0x50, 0xAA, 0xE8, 0x97, 0xD5, 0xCD, + 0x63, 0x57, 0x61, 0x62, 0x06, 0xBD, 0x26, 0x08, 0x0E, 0xC6, 0x42, 0x98, 0x8E, 0x82, 0x13, 0xD7, + 0xB8, 0x18, 0x7B, 0xAA, 0xFD, 0x42, 0x51, 0x07, 0xDE, 0x6F, 0xCF, 0xE7, 0x87, 0xF6, 0xBF, 0x15, + 0x8D, 0x8E, 0xFD, 0xA9, 0x4A, 0x45, 0x81, 0x57, 0x8F, 0x22, 0x4D, 0x63, 0x21, 0x4E, 0x41, 0x3C, + 0xCD, 0x77, 0xF5, 0xEC, 0xB8, 0x15, 0x8A, 0xBC, 0x69, 0x22, 0x98, 0xE5, 0xA4, 0x66, 0x47, 0xC5, + 0x9F, 0xE9, 0x9D, 0x06, 0xD8, 0xD2, 0x37, 0xA0, 0x4C, 0xDC, 0x33, 0xD4, 0xE7, 0xED, 0x77, 0x7D, + 0xA2, 0x20, 0x81, 0xB2, 0x46, 0xC5, 0xF6, 0xF5, 0x2A, 0x76, 0x50, 0xAF, 0xC2, 0x5A, 0xC7, 0x8F, + 0xD8, 0x3C, 0x4F, 0x2F, 0xE3, 0x56, 0x04, 0xB2, 0x6C, 0x8C, 0x0D, 0x84, 0xD7, 0xE0, 0xB5, 0x45, + 0xB2, 0x93, 0x34, 0xA0, 0xC2, 0xF4, 0x3A, 0x28, 0xDC, 0x50, 0xE8, 0xF3, 0xF0, 0x7C, 0x67, 0x1A, + 0x11, 0xD7, 0x8D, 0xB2, 0x71, 0x3D, 0xB3, 0x68, 0x49, 0x19, 0x29, 0x54, 0xDF, 0x44, 0xB9, 0x48, + 0xDD, 0x9E, 0xCE, 0xCD, 0x2D, 0x69, 0xB6, 0x18, 0xAD, 0xBC, 0xDC, 0xDF, 0x1F, 0x48, 0x04, 0x16, + 0xD6, 0x3A, 0x39, 0x7E, 0x30, 0xDB, 0x9D, 0xE1, 0x14, 0xF2, 0x5F, 0xDB, 0x1D, 0xBB, 0x7F, 0x4F, + 0x49, 0xBF, 0x4D, 0x2B, 0x9B, 0x5C, 0x7E, 0xA8, 0x1B, 0x79, 0x4F, 0x29, 0xA2, 0xF8, 0xBA, 0x36, + 0x86, 0x10, 0xFA, 0x7C, 0x45, 0x99, 0xE9, 0xD1, 0xDB, 0x93, 0xDB, 0x2A, 0xD5, 0xA8, 0x61, 0x48, + 0xBA, 0xD9, 0x40, 0xD7, 0xAE, 0xE5, 0x35, 0xAA, 0xF0, 0xA5, 0xFD, 0xC5, 0x64, 0x0B, 0x31, 0xA5, + 0x9D, 0x83, 0x31, 0xF6, 0xB8, 0xB5, 0x18, 0x3E, 0xB4, 0x2A, 0x8E, 0x70, 0x7A, 0xB8, 0xAC, 0xB5, + 0x92, 0xDD, 0x12, 0xA7, 0x9D, 0x41, 0xB1, 0x16, 0xE8, 0x45, 0x63, 0x1B, 0xB9, 0x73, 0xF1, 0x19, + 0xF6, 0xAE, 0x0F, 0xF3, 0xF7, 0x60, 0xED, 0x27, 0x70, 0x12, 0x8C, 0x12, 0x3A, 0xCF, 0xA6, 0xDC, + 0xBD, 0x17, 0x82, 0x05, 0x6E, 0x10, 0x04, 0xD4, 0xE7, 0x10, 0x9B, 0x83, 0x55, 0xB0, 0xED, 0x1B, + 0xF9, 0x7D, 0x75, 0x8E, 0xB2, 0x26, 0xA7, 0xBD, 0xE2, 0x0F, 0x29, 0x25, 0x6C, 0xFD, 0xC9, 0xC4, + 0x72, 0xE1, 0x1C, 0xDC, 0x9E, 0xBE, 0x69, 0xB5, 0xE8, 0x31, 0x83, 0x03, 0x5A, 0xEA, 0xA3, 0x52, + 0xD7, 0x51, 0x8A, 0x76, 0xB8, 0x83, 0xF0, 0x5E, 0xDC, 0xFC, 0xED, 0x80, 0x36, 0x7A, 0x39, 0xC6, + 0xFC, 0xF3, 0xC3, 0xE1, 0x5D, 0x15, 0x05, 0x30, 0xF6, 0x74, 0x93, 0x45, 0xB5, 0x2B, 0x0B, 0x63, + 0x2E, 0xF1, 0x24, 0x4B, 0x16, 0xD9, 0x61, 0xDB, 0x97, 0x9A, 0xC8, 0xFF, 0xCE, 0x74, 0xE9, 0x39, + 0x93, 0x00, 0xF8, 0xE0, 0x50, 0x62, 0x07, 0x0A, 0x6B, 0xB4, 0xBA, 0x2B, 0x61, 0x09, 0x25, 0x58, + 0x18, 0x0A, 0xB8, 0xDA, 0x8D, 0xFA, 0x8C, 0x4A, 0x41, 0xBE, 0xA4, 0x51, 0x9B, 0x83, 0x14, 0xC4, + 0xB5, 0x81, 0xB0, 0xA1, 0x35, 0x48, 0x34, 0xEB, 0xAF, 0x74, 0xF4, 0x61, 0xC5, 0x00, 0x39, 0x7D, + 0xAD, 0xF1, 0x07, 0x9C, 0x43, 0x20, 0x8F, 0x4B, 0x3D, 0xD3, 0x7C, 0x91, 0x1D, 0xC3, 0x3B, 0x06, + 0x50, 0x59, 0xA9, 0xC9, 0xA3, 0x23, 0xC9, 0xA6, 0x8A, 0x29, 0x84, 0x0D, 0x7D, 0xEE, 0x56, 0x5D, + 0xA1, 0xB6, 0xA3, 0xE7, 0x1F, 0x2A, 0xFB, 0x95, 0x7B, 0xFC, 0x9F, 0x9A, 0x18, 0xEA, 0xFF, 0xFD, + 0x61, 0x75, 0x3A, 0xF2, 0x22, 0xFF, 0xEB, 0xA2, 0x7C, 0x5A, 0x16, 0xB1, 0xE9, 0x93, 0xB0, 0x4D, + 0xA7, 0xA4, 0xB0, 0xAF, 0x70, 0x8C, 0x7E, 0x7D, 0xE8, 0x4F, 0xAA, 0x9D, 0x81, 0xD6, 0xF8, 0xB5, + 0xB6, 0x32, 0xA5, 0x31, 0xA1, 0x55, 0x11, 0x3A, 0x01, 0x13, 0x38, 0x3A, 0x41, 0x7A, 0x79, 0x31, + 0x3C, 0x13, 0xF5, 0x2C, 0x97, 0x28, 0xBD, 0x1F, 0x2E, 0x68, 0xAB, 0xA1, 0x52, 0x5F, 0xBB, 0x2A, + 0xCB, 0x11, 0xFE, 0x4A, 0x34, 0x30, 0xCD, 0xDD, 0x38, 0xAC, 0xED, 0xD0, 0x53, 0xC6, 0xC4, 0x33, + 0xE5, 0x17, 0x41, 0xC8, 0x7D, 0x14, 0x9C, 0x8C, 0x2D, 0x59, 0x61, 0xB1, 0xEC, 0x6A, 0x48, 0xAD, + 0xC7, 0x42, 0x79, 0x9B, 0x63, 0xDB, 0xB0, 0xAD, 0xAF, 0x44, 0x85, 0x2E, 0x24, 0x11, 0xE6, 0x1E, + 0x56, 0xB2, 0x1B, 0x2E, 0x98, 0x7E, 0x64, 0x3D, 0x98, 0x69, 0x51, 0x05, 0x3D, 0x5C, 0x0A, 0x85, + 0xCA, 0x58, 0x0E, 0x11, 0x86, 0xA7, 0xD6, 0xAC, 0xFF, 0x21, 0x12, 0x9F, 0xA1, 0x52, 0xE4, 0xD9, + 0xD5, 0xAC, 0x9B, 0xE2, 0x4B, 0xF0, 0x57, 0xFA, 0xFC, 0x05, 0x84, 0xB6, 0xD9, 0xB0, 0xCE, 0x5E, + 0xA0, 0x73, 0x32, 0xCE, 0x15, 0x29, 0xE8, 0x8F, 0xC4, 0xD9, 0x22, 0x3A, 0x9D, 0x71, 0xC5, 0x37, + 0x2B, 0x33, 0x76, 0x63, 0x49, 0x52, 0x8A, 0x2E, 0x89, 0x6D, 0x5A, 0x04, 0x83, 0xC1, 0xD9, 0x46, + 0xC3, 0x5C, 0x93, 0x6C, 0x3B, 0xDB, 0xFC, 0x1C, 0xC1, 0x65, 0x3B, 0x2C, 0xAD, 0xD5, 0x78, 0x9A, + 0x3A, 0xE4, 0xC3, 0x04, 0x11, 0xD8, 0xBD, 0x63, 0xA9, 0x93, 0x01, 0xF1, 0x42, 0x89, 0x5E, 0x66, + 0x95, 0xF2, 0x75, 0x38, 0x30, 0x4B, 0x39, 0x41, 0x49, 0x54, 0x8E, 0x12, 0x36, 0xFB, 0x9A, 0xA0, + 0x61, 0x13, 0x1C, 0xC2, 0xB2, 0x30, 0x7E, 0xD5, 0x22, 0xEB, 0xA3, 0xB6, 0x69, 0x2E, 0x0F, 0x0B, + 0xB0, 0x29, 0xF3, 0x24, 0x5A, 0x29, 0xA6, 0x3F, 0xC9, 0xC1, 0x56, 0xC5, 0x8E, 0xAA, 0x0B, 0x17, + 0x44, 0xBC, 0xFF, 0xE3, 0x12, 0xB8, 0x3E, 0xA9, 0x16, 0xF9, 0x7F, 0x57, 0x92, 0x7C, 0x0C, 0xFD, + 0x87, 0x9D, 0x70, 0xED, 0x81, 0xD0, 0x77, 0x01, 0x77, 0x71, 0xF5, 0x6C, 0x7F, 0xCC, 0xE4, 0xF0, + 0xAD, 0x27, 0x66, 0x2D, 0x16, 0x7B, 0x4E, 0x95, 0xF9, 0x59, 0xAA, 0x8A, 0x83, 0xE3, 0x1E, 0xD9, + 0x6E, 0x9C, 0x84, 0xEB, 0xBD, 0x5B, 0x33, 0x68, 0xA9, 0x3F, 0xDA, 0x69, 0xCB, 0xF1, 0xC7, 0x64, + 0x99, 0x27, 0xEF, 0xFF, 0xE2, 0x37, 0x34, 0x2D, 0x3C, 0x92, 0xAF, 0x7B, 0xE6, 0x6D, 0x7E, 0xF9, + 0xD2, 0x95, 0x14, 0xF1, 0x01, 0x93, 0xF2, 0xBD, 0xDF, 0x59, 0x67, 0xF6, 0x2D, 0x36, 0xBB, 0x8E, + 0x16, 0xCA, 0x07, 0xEC, 0x34, 0xA0, 0xE2, 0x16, 0x6C, 0xEC, 0x23, 0x41, 0x87, 0x7A, 0x66, 0x82, + 0x09, 0x6A, 0xFE, 0x21, 0xB3, 0x9A, 0xC7, 0x12, 0x0D, 0x07, 0xEB, 0xCF, 0xCB, 0x44, 0x9B, 0xA3, + 0xA1, 0xD9, 0x07, 0x76, 0x1D, 0x93, 0x96, 0x1B, 0x6D, 0xA1, 0x65, 0x6D, 0xB2, 0x62, 0x81, 0x55, + 0xFD, 0xE1, 0x76, 0xF2, 0x6F, 0x9A, 0x71, 0x9F, 0xFC, 0x48, 0x8D, 0x58, 0x1D, 0x3E, 0xFE, 0xBC, + 0x02, 0xB5, 0x36, 0xEE, 0x58, 0x35, 0x82, 0xF3, 0x51, 0x93, 0x35, 0x7E, 0xFA, 0xAF, 0x7E, 0x56, + 0x7E, 0xE8, 0x59, 0x7E, 0x90, 0x73, 0x9B, 0x0E, 0x4D, 0x0D, 0x84, 0x75, 0x30, 0x29, 0xCA, 0xE7, + 0x2C, 0xB3, 0xAC, 0x53, 0x3C, 0xC3, 0x7D, 0x55, 0xCD, 0xE0, 0xB9, 0xF8, 0x44, 0x02, 0xF2, 0x2B, + 0xB7, 0xD1, 0x83, 0x75, 0xDC, 0x96, 0xE7, 0x62, 0x5A, 0x58, 0x63, 0x2D, 0xC1, 0x33, 0xD2, 0x74, + 0x27, 0x05, 0xFD, 0xB7, 0x69, 0x63, 0x34, 0x81, 0xDB, 0xC1, 0x24, 0x10, 0x3A, 0xC2, 0xE2, 0xE9, + 0x75, 0xF8, 0x90, 0x50, 0x3A, 0x3C, 0xAF, 0xCD, 0x4E, 0x78, 0xB0, 0xFA, 0x5F, 0x2C, 0x09, 0x90, + 0xFE, 0xDA, 0xE4, 0x99, 0x8E, 0x3E, 0x63, 0x74, 0x3C, 0x6C, 0xD6, 0xC5, 0x2A, 0x1A, 0xBD, 0x95, + 0xA3, 0xAB, 0xF3, 0xEF, 0x1E, 0x95, 0x02, 0x8E, 0xCB, 0x23, 0xED, 0x11, 0xDB, 0x42, 0x45, 0xD5, + 0x5D, 0xDF, 0xF6, 0xE5, 0x98, 0xB4, 0x46, 0x49, 0x1A, 0xC6, 0x87, 0xFC, 0xA1, 0x79, 0x15, 0xD8, + 0x84, 0x99, 0xFE, 0x0B, 0x33, 0x30, 0x21, 0xA7, 0x59, 0x0A, 0x35, 0xE6, 0x68, 0x62, 0x55, 0x58, + 0xB4, 0x74, 0xDC, 0x80, 0xA4, 0xAD, 0x97, 0x57, 0x08, 0x9D, 0xC9, 0x9C, 0x1C, 0x0E, 0xD6, 0xE5, + 0xE3, 0xC8, 0x13, 0x02, 0xA8, 0xB9, 0x06, 0x27, 0x55, 0x89, 0xE7, 0xA3, 0xBF, 0xB0, 0xA6, 0xD0, + 0x92, 0xAD, 0xDA, 0xFE, 0x9E, 0x38, 0x2B, 0x88, 0x18, 0x7E, 0x3E, 0x90, 0xC3, 0xC0, 0x90, 0xAB, + 0x10, 0x21, 0x49, 0x47, 0xD1, 0x9D, 0x0A, 0xE9, 0x9F, 0xF9, 0xBB, 0x44, 0x83, 0x43, 0xBE, 0xBB, + 0x72, 0xD3, 0x06, 0xB4, 0x1B, 0x11, 0x03, 0xB8, 0xF5, 0xE5, 0x85, 0x1C, 0x4D, 0x7B, 0x0E, 0x65, + 0x33, 0xB0, 0x06, 0xD4, 0x58, 0x1F, 0xC9, 0x52, 0x27, 0xAD, 0xC9, 0xDE, 0x33, 0x4D, 0xC5, 0x45, + 0x6F, 0x11, 0xE1, 0x1D, 0xB9, 0x26, 0xED, 0x5B, 0x9B, 0xF6, 0xFC, 0x87, 0xF7, 0x96, 0x58, 0x5D, + 0xD7, 0x10, 0x15, 0x59, 0x1E, 0x3C, 0xFC, 0xF2, 0x8C, 0x7B, 0xB8, 0x70, 0x35, 0xD2, 0xB3, 0xA2, + 0xF1, 0xE7, 0x9D, 0xC6, 0xAE, 0x37, 0x71, 0xDA, 0x04, 0x32, 0x09, 0x33, 0xF7, 0x7D, 0x45, 0x33, + 0x9F, 0x5C, 0xD6, 0x66, 0xEC, 0x68, 0xCA, 0xEC, 0xBF, 0x4C, 0xF8, 0xA1, 0x4D, 0x5C, 0x41, 0x0E, + 0x69, 0x1F, 0x96, 0xE8, 0xD9, 0x76, 0xB9, 0xEA, 0x04, 0xEF, 0x91, 0xD4, 0xD7, 0x36, 0xEF, 0xE9, + 0xE6, 0x7B, 0x81, 0x31, 0xFD, 0x4E, 0x15, 0x17, 0xF1, 0x25, 0x86, 0x4C, 0x94, 0x2A, 0xAA, 0x50, + 0xB0, 0x98, 0x19, 0xB4, 0x34, 0x81, 0xE2, 0x61, 0xE6, 0xEE, 0x9C, 0x70, 0x72, 0x38, 0xB8, 0xE8, + 0xA6, 0xE1, 0x9F, 0x24, 0xDC, 0xD2, 0x9D, 0xC3, 0x94, 0x43, 0x65, 0x5B, 0x22, 0x45, 0xF2, 0x75, + 0x33, 0x6D, 0xB9, 0x60, 0xC6, 0x9F, 0x0A, 0xC1, 0x1F, 0xFC, 0x8B, 0x7B, 0xAB, 0x71, 0x61, 0xAE, + 0xD2, 0x1B, 0xF6, 0x79, 0x3D, 0x63, 0x1F, 0x4F, 0x1C, 0xDD, 0x4B, 0x50, 0x02, 0x97, 0xCD, 0xF4, + 0xC7, 0x0B, 0xFC, 0xB3, 0xD1, 0x21, 0xD3, 0x73, 0x1B, 0x4B, 0xE8, 0x9F, 0x3D, 0x16, 0x88, 0x0E, + 0x7F, 0xCC, 0x26, 0xA6, 0xF5, 0x8F, 0x69, 0x7F, 0xAC, 0xE8, 0x3F, 0x7B, 0x29, 0x81, 0xDA, 0x14, + 0x8F, 0x98, 0x78, 0x11, 0x34, 0x46, 0x60, 0xAD, 0x9E, 0xB3, 0x69, 0xFD, 0x74, 0x95, 0x3A, 0x14, + 0x30, 0xBE, 0x34, 0xE2, 0xAC, 0x54, 0x81, 0x70, 0x1F, 0x47, 0xD7, 0x5A, 0xDE, 0x81, 0x29, 0x17, + 0x9B, 0x3F, 0xC7, 0x57, 0x56, 0x26, 0xCD, 0xF8, 0x3B, 0x4E, 0x94, 0x4E, 0xA4, 0x09, 0x46, 0x1A, + 0x6D, 0xA3, 0x44, 0x51, 0xA9, 0x9F, 0x97, 0x88, 0x5E, 0x5E, 0x70, 0xCA, 0xDE, 0xA4, 0xAF, 0x6D, + 0xBC, 0xCE, 0xF6, 0x67, 0x81, 0x10, 0xD3, 0xF5, 0xB8, 0xC9, 0x49, 0xF3, 0x98, 0x71, 0x2D, 0x29, + 0xBD, 0x34, 0x08, 0x25, 0x1B, 0x9A, 0x6F, 0xC3, 0x4D, 0xC3, 0x9F, 0x5E, 0xE2, 0xA2, 0xF3, 0x82, + 0x52, 0xA9, 0xF6, 0x79, 0x14, 0x6F, 0xD0, 0x12, 0xB6, 0x0D, 0x4C, 0xAC, 0x3E, 0x2A, 0x8C, 0x86, + 0xE1, 0xFF, 0x1C, 0x49, 0x43, 0xF2, 0x1D, 0x34, 0xA3, 0x0F, 0xA3, 0x9B, 0x2C, 0xF3, 0x9C, 0xFC, + 0x23, 0x4B, 0xE0, 0xCB, 0xE6, 0xBE, 0x7E, 0x8B, 0x51, 0x2D, 0x32, 0x92, 0xCC, 0xC6, 0xDB, 0x36, + 0x1B, 0x83, 0x80, 0x64, 0xD2, 0x23, 0x1C, 0x60, 0x90, 0x1C, 0x71, 0x06, 0x0F, 0x30, 0xC0, 0xDF, + 0xFE, 0xF7, 0x50, 0x5A, 0xF8, 0x9C, 0x97, 0x29, 0xFB, 0x7B, 0xEB, 0x91, 0x6A, 0x42, 0xE4, 0xAB, + 0x62, 0xB4, 0x1F, 0x14, 0xEC, 0x1A, 0x9F, 0xC4, 0x98, 0x77, 0x85, 0x8B, 0xF1, 0x15, 0x2B, 0x2C, + 0x3F, 0xAB, 0x3A, 0x5E, 0xD3, 0x50, 0x32, 0xDD, 0x23, 0x81, 0x89, 0x3B, 0xB8, 0xFD, 0x49, 0x78, + 0xA9, 0x35, 0x20, 0x2D, 0xBC, 0xFC, 0x10, 0x8A, 0x08, 0xA0, 0x57, 0x24, 0xFA, 0x29, 0xD3, 0x9C, + 0xC0, 0xC5, 0x06, 0xF2, 0x7D, 0xC4, 0x45, 0x38, 0x1F, 0xC6, 0xE4, 0xC8, 0x23, 0x65, 0xD2, 0x5A, + 0xE5, 0xCD, 0x63, 0x14, 0x56, 0x03, 0xAA, 0x29, 0x82, 0xAB, 0x67, 0x92, 0x2C, 0x71, 0x67, 0x6A, + 0x36, 0xF9, 0xE1, 0x89, 0xD2, 0x98, 0x88, 0x97, 0x65, 0x72, 0xE4, 0x3C, 0x5A, 0x1D, 0xB7, 0x34, + 0x4D, 0x01, 0x91, 0x5D, 0xC4, 0xAF, 0x88, 0x2F, 0xD1, 0x27, 0x26, 0x36, 0x16, 0x98, 0x39, 0x9A, + 0xEA, 0xFA, 0xDF, 0x3B, 0x7F, 0xD8, 0x76, 0x95, 0xDB, 0x03, 0x82, 0x86, 0xD0, 0x6D, 0x15, 0xD0, + 0xF0, 0xB9, 0xCC, 0xB9, 0xD6, 0xE1, 0x9C, 0xC7, 0xAE, 0x3C, 0xA8, 0xB9, 0x49, 0xA3, 0xC4, 0xB3, + 0x24, 0x3A, 0xA3, 0x50, 0x7E, 0xDF, 0xBE, 0x5F, 0xAF, 0xC3, 0x7C, 0x3C, 0xC7, 0x39, 0xD9, 0x29, + 0x06, 0xD5, 0x0B, 0xE8, 0xFA, 0x80, 0xC2, 0xCE, 0xA8, 0xD9, 0x20, 0xCE, 0x28, 0x0A, 0xDE, 0x15, + 0xB5, 0x0D, 0x9A, 0xB8, 0xB0, 0x7B, 0x33, 0xB8, 0x35, 0xEB, 0x4E, 0xDE, 0xF5, 0x9F, 0x66, 0x79, + 0x52, 0x44, 0xD2, 0x49, 0x3A, 0x94, 0xE2, 0xCB, 0x83, 0x22, 0x7D, 0xC6, 0x1C, 0xEB, 0x44, 0x28, + 0xE9, 0x38, 0x8F, 0xB7, 0xF6, 0x3D, 0x39, 0x8F, 0x64, 0x9F, 0x86, 0x85, 0x27, 0x7E, 0xBF, 0xD8, + 0xC3, 0x8B, 0x70, 0xF9, 0x7A, 0xE6, 0x19, 0xAF, 0xA8, 0x8F, 0x6C, 0x38, 0xE2, 0xB4, 0x1E, 0xF3, + 0xDD, 0xFD, 0x6C, 0xB4, 0x04, 0xB4, 0xD1, 0x37, 0xF4, 0x59, 0xFF, 0x5A, 0x8B, 0x73, 0x6B, 0x62, + 0x6C, 0x91, 0x23, 0x96, 0x61, 0xEC, 0x9F, 0xF6, 0x83, 0x18, 0xD9, 0xEE, 0xEF, 0x00, 0xB0, 0xEB, + 0x8D, 0xC6, 0x35, 0xCE, 0xB4, 0xE0, 0xBB, 0x84, 0xD3, 0xD7, 0xDB, 0x77, 0x4A, 0x07, 0xE7, 0x3B, + 0xF7, 0x12, 0xF8, 0x9D, 0xF5, 0x0A, 0xDF, 0xF4, 0x1B, 0x00, 0x1A, 0x77, 0xD9, 0x03, 0x21, 0xC2, + 0x46, 0xF7, 0x7E, 0x4B, 0xE2, 0xC1, 0xF1, 0x8D, 0xFE, 0x61, 0xB9, 0xD4, 0x0B, 0xC9, 0x65, 0x82, + 0xCF, 0x7F, 0x3D, 0x24, 0x9E, 0xC9, 0x97, 0x30, 0xE9, 0x81, 0xB4, 0x6B, 0xA5, 0x6A, 0xA7, 0xED, + 0xE3, 0x8F, 0x88, 0x09, 0x78, 0x36, 0x6A, 0x14, 0xB9, 0xBB, 0x93, 0xE6, 0xA2, 0x07, 0x72, 0x81, + 0xD2, 0x41, 0x75, 0x28, 0x50, 0x57, 0xDE, 0x68, 0x04, 0xB1, 0x0F, 0x1F, 0xCF, 0x0F, 0x3E, 0xCB, + 0x44, 0x3D, 0x2A, 0x01, 0xC1, 0x38, 0x61, 0x8E, 0xA1, 0x13, 0xB8, 0x82, 0x3F, 0xAC, 0xA7, 0x31, + 0x7B, 0xF7, 0xA7, 0xCD, 0xBF, 0x15, 0xD3, 0xC2, 0xCC, 0xDC, 0xD0, 0xB2, 0xC1, 0x44, 0xBA, 0x82, + 0x85, 0x2D, 0x59, 0x53, 0xE4, 0xBE, 0x6B, 0x69, 0x8F, 0x5C, 0x20, 0x38, 0x76, 0xE0, 0x49, 0x59, + 0x32, 0x0A, 0x90, 0x42, 0x13, 0x35, 0x24, 0x71, 0xD9, 0x98, 0x9A, 0x0F, 0x0A, 0x83, 0x90, 0x47, + 0xD0, 0x57, 0x29, 0xC8, 0xF5, 0x5B, 0xA8, 0x5D, 0x41, 0xCD, 0x61, 0x98, 0x5C, 0x28, 0x1B, 0xF2, + 0x9B, 0x31, 0x3F, 0x14, 0x79, 0x37, 0xEA, 0xDD, 0x42, 0xD3, 0x59, 0x20, 0x0D, 0x5A, 0x3D, 0x59, + 0x84, 0x1A, 0x48, 0x28, 0x6D, 0x48, 0x3B, 0x0C, 0x87, 0xB0, 0xBB, 0xEF, 0x72, 0x91, 0x85, 0xE0, + 0x9A, 0x2C, 0x78, 0xAF, 0xFE, 0x0D, 0x6D, 0x9A, 0x99, 0x10, 0x16, 0x7D, 0x42, 0x76, 0xA0, 0xAA, + 0xC7, 0xF9, 0x11, 0x5C, 0x04, 0x83, 0x0A, 0xA9, 0x48, 0x65, 0x28, 0x81, 0x65, 0x2E, 0xA7, 0x5A, + 0xFE, 0xDB, 0x10, 0x56, 0xEA, 0x19, 0x67, 0xC2, 0x61, 0xBB, 0x9B, 0x6B, 0x48, 0x4F, 0x22, 0x4C, + 0xB7, 0xEC, 0x15, 0x84, 0x08, 0x1A, 0xFE, 0x08, 0x46, 0xCA, 0x72, 0x10, 0x30, 0x81, 0xAE, 0xE7, + 0x1B, 0xAA, 0x2F, 0x1B, 0x22, 0x6A, 0x89, 0x95, 0x34, 0x9F, 0x53, 0xE4, 0xDA, 0x0B, 0x1B, 0x56, + 0xB4, 0xB7, 0x71, 0x99, 0xB8, 0x77, 0x91, 0xEB, 0x59, 0x61, 0x71, 0x84, 0xAF, 0x55, 0xBD, 0x33, + 0x1C, 0xD9, 0x7A, 0x40, 0xD3, 0x7B, 0x6C, 0xB0, 0xA4, 0x96, 0x07, 0x57, 0x49, 0x9C, 0xC1, 0x0B, + 0x23, 0xF3, 0xE5, 0x36, 0xA4, 0xE8, 0xE1, 0xEC, 0x51, 0xF1, 0xBB, 0x7B, 0x40, 0x4B, 0x05, 0xD1, + 0x3D, 0xD6, 0x6D, 0x22, 0x7C, 0x9D, 0x51, 0x28, 0x70, 0xF6, 0xB3, 0x0C, 0x6F, 0xB2, 0xE1, 0xBC, + 0xFF, 0xB8, 0xA3, 0x92, 0x7C, 0x0A, 0xA3, 0x36, 0x6D, 0xF8, 0xFC, 0x27, 0x45, 0x58, 0x94, 0xE0, + 0x0A, 0x90, 0xF8, 0x2A, 0xF3, 0x02, 0xA4, 0x98, 0xD8, 0xEF, 0x1C, 0x53, 0xE2, 0x47, 0xC7, 0x20, + 0xB2, 0x6F, 0xB7, 0x39, 0x5A, 0xA9, 0x49, 0xC2, 0x65, 0x18, 0x50, 0xBD, 0x7F, 0xB0, 0xDE, 0xBB, + 0x2F, 0x56, 0xDD, 0x62, 0x85, 0xAC, 0x3B, 0x7E, 0xCD, 0x00, 0x88, 0x7A, 0x22, 0xC5, 0x03, 0x03, + 0x26, 0xC4, 0x27, 0x09, 0xE8, 0x16, 0x36, 0xB7, 0x0B, 0xDF, 0xDA, 0x21, 0xEB, 0x59, 0xE8, 0x6D, + 0x96, 0x2D, 0x18, 0x89, 0xD4, 0x4E, 0x5A, 0x66, 0x63, 0x31, 0x15, 0xF0, 0x48, 0x50, 0x7A, 0xF3, + 0xA7, 0x82, 0xE0, 0x91, 0x04, 0xB2, 0x16, 0xAC, 0xA1, 0xD4, 0xC1, 0xE4, 0xBD, 0xC9, 0x43, 0x83, + 0xD9, 0x18, 0x11, 0x50, 0xC0, 0x93, 0x9D, 0x6B, 0x17, 0x63, 0xC8, 0xA3, 0xAF, 0xAC, 0xBF, 0x29, + 0x65, 0xA6, 0x4A, 0xE4, 0xCD, 0xE2, 0x89, 0x59, 0xF8, 0x96, 0xF8, 0x3B, 0x80, 0xCA, 0x68, 0xF2, + 0xBF, 0xBE, 0xFD, 0xD0, 0x84, 0x88, 0xE3, 0x3D, 0x08, 0x8A, 0x08, 0x39, 0xDC, 0x88, 0x71, 0x61, + 0x76, 0xAD, 0xB6, 0xBE, 0xC0, 0xA4, 0x28, 0xEE, 0x38, 0x8F, 0x2E, 0x8D, 0x3A, 0x28, 0xAE, 0xEB, + 0x93, 0x7E, 0xF4, 0x2E, 0x5F, 0x3B, 0xEA, 0x37, 0x9A, 0x53, 0x6C, 0xC5, 0x3A, 0x2F, 0x7F, 0xA9, + 0x80, 0x85, 0x18, 0xFE, 0x14, 0x0C, 0x37, 0xA7, 0xE2, 0x78, 0x90, 0x20, 0x1F, 0x41, 0x1C, 0x03, + 0xD1, 0xD0, 0x8C, 0xB2, 0x2D, 0x4C, 0x32, 0x81, 0x63, 0xF6, 0x6F, 0xD3, 0x7F, 0xB4, 0x6D, 0xA8, + 0xD6, 0xE0, 0x56, 0x84, 0xAD, 0x37, 0x96, 0x44, 0xB4, 0xAE, 0x6F, 0x49, 0x3E, 0x30, 0x0C, 0x79, + 0xE3, 0x93, 0xBA, 0xD2, 0x10, 0x71, 0xAC, 0x7C, 0x06, 0x89, 0x26, 0xCB, 0x72, 0x9E, 0xC4, 0xCC, + 0xBB, 0xA1, 0xDE, 0x9B, 0x66, 0x75, 0x6F, 0xAC, 0x51, 0x93, 0xE8, 0xF4, 0x43, 0xE4, 0x79, 0xF2, + 0x50, 0x67, 0x3D, 0x1B, 0x33, 0xB5, 0xEC, 0x93, 0x10, 0xCE, 0x78, 0x3C, 0x0C, 0x25, 0x44, 0x30, + 0x3C, 0xAB, 0x40, 0x6F, 0x4B, 0x54, 0x0C, 0x38, 0xD4, 0xEF, 0x18, 0xED, 0xA5, 0x75, 0x1E, 0x9C, + 0x06, 0x42, 0x11, 0x9D, 0xEC, 0xE8, 0x81, 0x38, 0xBE, 0xEF, 0x21, 0xB5, 0x0A, 0xC3, 0x38, 0x94, + 0x0C, 0x5A, 0xE2, 0x47, 0xDC, 0x2E, 0x82, 0xC3, 0xA6, 0x9D, 0xA6, 0x54, 0x5E, 0xE6, 0x7C, 0xFE, + 0x7E, 0x7B, 0x86, 0x9A, 0x54, 0xEC, 0xCD, 0xE5, 0x9F, 0xF7, 0x23, 0xDE, 0x06, 0x90, 0x93, 0xB6, + 0xCC, 0xC8, 0x3D, 0x75, 0xA6, 0x43, 0xEA, 0x1F, 0x44, 0xAB, 0xBB, 0x15, 0xC4, 0xAB, 0xB1, 0xDF, + 0xE9, 0x30, 0xB4, 0xB2, 0x3B, 0x5B, 0xA6, 0x57, 0xEE, 0x25, 0x4B, 0x83, 0x26, 0xE4, 0x6B, 0xE3, + 0x35, 0x62, 0xA5, 0xD2, 0xB6, 0xDE, 0xFD, 0x5F, 0x8C, 0x21, 0xF8, 0x15, 0x41, 0x1C, 0x61, 0xCD, + 0x78, 0x0F, 0x61, 0x9E, 0x0C, 0x7E, 0x88, 0xE3, 0x34, 0x7F, 0x0B, 0x00, 0x5D, 0x8A, 0x37, 0x5F, + 0xFB, 0x65, 0xB8, 0xEC, 0x6C, 0x6A, 0x7E, 0x8F, 0x70, 0x6A, 0x17, 0xFB, 0x6B, 0x9D, 0xD8, 0xC3, + 0xD5, 0x13, 0x49, 0xEC, 0xD0, 0xEC, 0x1B, 0xC7, 0x79, 0xBB, 0xD2, 0x89, 0x96, 0x39, 0x1C, 0xF3, + 0x70, 0xEA, 0xF0, 0xEA, 0x6B, 0x45, 0x51, 0xDB, 0x1A, 0x61, 0x60, 0x98, 0x1C, 0x7A, 0xA6, 0x48, + 0x65, 0xDA, 0x85, 0xBE, 0x6B, 0xC4, 0x27, 0x2F, 0x76, 0x6D, 0x5F, 0x4C, 0xDE, 0x92, 0xA1, 0xB3, + 0xD4, 0x11, 0xB4, 0x0B, 0x3A, 0x4C, 0x73, 0xC3, 0xAA, 0x9C, 0x0F, 0x95, 0x9B, 0x2C, 0x67, 0x02, + 0x47, 0xCD, 0xE3, 0x75, 0x84, 0x60, 0x5E, 0x17, 0xAB, 0xF0, 0xBC, 0xBE, 0xB4, 0xAA, 0x4C, 0xEA, + 0x11, 0x52, 0x87, 0xAC, 0x16, 0x56, 0x06, 0x1F, 0xC1, 0x97, 0xF9, 0xAB, 0x26, 0xD9, 0xCC, 0x58, + 0x01, 0xFF, 0x44, 0x21, 0xFE, 0x5D, 0x53, 0x0B, 0xA2, 0xAF, 0xBC, 0x9D, 0x63, 0x25, 0x87, 0x66, + 0xB3, 0x79, 0xB4, 0x9F, 0x49, 0xE6, 0x6E, 0xCB, 0x8B, 0x39, 0x8C, 0x46, 0x60, 0x3D, 0x5B, 0xEC, + 0x08, 0x1B, 0xB2, 0xEC, 0xA2, 0xAA, 0x9A, 0xDA, 0xAA, 0xAD, 0x25, 0xAB, 0x45, 0x99, 0x63, 0x23, + 0x6C, 0x53, 0x87, 0xA0, 0x5A, 0x6C, 0xD6, 0xE3, 0x6C, 0x34, 0x42, 0x0F, 0xF3, 0xA0, 0x23, 0xD3, + 0x16, 0x05, 0xAB, 0x05, 0x14, 0xA8, 0xA9, 0x02, 0x23, 0xFC, 0xC0, 0xED, 0x75, 0xC5, 0x43, 0x7C, + 0x1E, 0xB1, 0x69, 0xB6, 0x01, 0x96, 0x7B, 0x9E, 0x12, 0x1C, 0x72, 0x42, 0x0D, 0xAB, 0x0B, 0x79, + 0x22, 0xF3, 0xF0, 0xEB, 0x71, 0x83, 0x42, 0x3C, 0x11, 0xC7, 0x4F, 0x87, 0xFF, 0x5D, 0x19, 0x0B, + 0xE4, 0x1E, 0xC3, 0xA2, 0xD7, 0x0E, 0x9C, 0x3C, 0x7D, 0xFB, 0x4F, 0xDA, 0x99, 0x9F, 0xF8, 0x3E, + 0xD4, 0xA0, 0xA2, 0xF8, 0x83, 0x33, 0x1E, 0xE2, 0x1C, 0x52, 0x9D, 0xB8, 0x63, 0x8F, 0xA1, 0x4D, + 0x68, 0xAE, 0xCE, 0xD4, 0x12, 0x8E, 0x96, 0xA1, 0x78, 0x27, 0x6A, 0x29, 0x11, 0x19, 0x4C, 0x94, + 0x89, 0x0F, 0xFB, 0x7C, 0xA8, 0xAC, 0x7E, 0x84, 0x44, 0xC8, 0x7A, 0x18, 0xAE, 0x34, 0x0F, 0x6E, + 0x90, 0xDB, 0x1E, 0x79, 0xFA, 0xE8, 0xAF, 0x71, 0xE4, 0x80, 0x24, 0x53, 0x2F, 0xB6, 0xC2, 0x12, + 0x1F, 0xA0, 0x44, 0x98, 0x40, 0xAE, 0x01, 0xD6, 0xFB, 0x86, 0xBB, 0xC6, 0xF7, 0x2F, 0x38, 0x41, + 0xE3, 0x2E, 0x1F, 0x2E, 0x7C, 0x90, 0x1F, 0xD9, 0xD3, 0x34, 0x86, 0xC8, 0xA3, 0x8E, 0xAB, 0x5E, + 0x05, 0x55, 0x71, 0x5B, 0x21, 0xB7, 0x2F, 0x9E, 0x56, 0x32, 0x56, 0xD1, 0xDC, 0xC9, 0xDA, 0xDE, + 0xAC, 0x1D, 0x91, 0x0E, 0x4D, 0x1F, 0x4F, 0xE7, 0x31, 0xFE, 0x9A, 0x3F, 0x18, 0xAD, 0x85, 0x4E, + 0x66, 0x95, 0x76, 0x67, 0x6A, 0xC8, 0x90, 0x6A, 0xB5, 0xB0, 0x7D, 0xB2, 0xB3, 0xD7, 0xD6, 0x42, + 0xF1, 0x63, 0x52, 0xBD, 0x72, 0xE1, 0xD2, 0x63, 0x9A, 0x00, 0x45, 0x8E, 0x77, 0xCF, 0x93, 0xCF, + 0x1A, 0x31, 0xAA, 0x16, 0xA9, 0xCF, 0x45, 0xE3, 0x99, 0x3E, 0x6C, 0x70, 0xE9, 0x93, 0x83, 0x78, + 0x11, 0xB8, 0x80, 0xEA, 0x75, 0x5A, 0x87, 0xCE, 0x1D, 0xCD, 0x12, 0x5F, 0x1F, 0x6F, 0x86, 0x25, + 0x5E, 0x95, 0x22, 0x07, 0xFE, 0x29, 0xDA, 0x93, 0x52, 0x41, 0x62, 0x79, 0x06, 0x06, 0x83, 0xAE, + 0x42, 0x35, 0x5C, 0x9E, 0x01, 0xF8, 0xFA, 0x3F, 0x07, 0x15, 0xCA, 0x02, 0x69, 0x8E, 0xEA, 0x9E, + 0xEF, 0xF4, 0x99, 0x26, 0x73, 0x42, 0xC2, 0xEC, 0x0F, 0xEC, 0x03, 0x8F, 0x66, 0xC1, 0x88, 0x76, + 0xC5, 0xC2, 0x55, 0x46, 0x59, 0xC4, 0x28, 0x55, 0x93, 0xBF, 0x7C, 0x1C, 0x5C, 0xA0, 0xBA, 0x8A, + 0xCA, 0x8A, 0x81, 0x6C, 0xA3, 0xDE, 0x2D, 0x63, 0xC5, 0xCA, 0x0B, 0x8E, 0x99, 0xC9, 0xE4, 0x7E, + 0x32, 0x36, 0xD8, 0xFA, 0x80, 0xA5, 0x93, 0x4F, 0x5C, 0x97, 0x33, 0x74, 0xD2, 0x03, 0xFF, 0xFD, + 0x57, 0x84, 0x26, 0x62, 0x6A, 0x4C, 0x15, 0x45, 0xB9, 0x7C, 0xCD, 0xD8, 0x7B, 0xC5, 0x70, 0xA1, + 0xCB, 0xB4, 0xDE, 0xA6, 0xBD, 0xE0, 0xE9, 0x49, 0xB7, 0xEA, 0x21, 0x17, 0xCD, 0x0C, 0xA7, 0xF2, + 0x9B, 0xB6, 0x26, 0x06, 0xB1, 0x63, 0x3D, 0x0D, 0x1A, 0xAE, 0x57, 0xF1, 0x53, 0xDA, 0x61, 0x47, + 0x7E, 0x66, 0xC0, 0x2A, 0xAC, 0x7E, 0xE8, 0xE9, 0x4F, 0xC2, 0x21, 0x01, 0x0B, 0x9C, 0xA7, 0x98, + 0x05, 0x3A, 0x34, 0x68, 0x19, 0x26, 0x35, 0x57, 0xF7, 0xF8, 0xE0, 0x77, 0x7B, 0x42, 0x8D, 0xE0, + 0xD3, 0x08, 0x49, 0x62, 0x1D, 0x86, 0xBE, 0xC8, 0xDC, 0x2F, 0xE0, 0xFF, 0xC4, 0x6E, 0xBD, 0xEC, + 0x8B, 0x33, 0xF1, 0x61, 0x6E, 0x96, 0xEB, 0xEA, 0x87, 0x4C, 0xA3, 0x5F, 0x97, 0x92, 0x22, 0x0C, + 0x36, 0x05, 0xA5, 0xC1, 0xF6, 0xB8, 0xF5, 0xE0, 0xE4, 0x91, 0x73, 0x73, 0xD0, 0x38, 0x81, 0x24, + 0x13, 0xB4, 0x4B, 0xAB, 0x4C, 0xBB, 0x15, 0x56, 0xC2, 0x66, 0xF9, 0x27, 0xEF, 0xE0, 0x3D, 0x4E, + 0xDB, 0x12, 0xCB, 0xC1, 0xDE, 0x57, 0x1B, 0x7F, 0x69, 0x10, 0xE4, 0x6E, 0xF7, 0xCC, 0x0F, 0x64, + 0x31, 0x6A, 0xBF, 0x49, 0x6C, 0xF8, 0x9E, 0xC9, 0x37, 0xF9, 0x26, 0x32, 0x4A, 0x26, 0x97, 0x99, + 0x30, 0xA6, 0x86, 0x82, 0xCE, 0x04, 0x8B, 0xFB, 0x39, 0x3B, 0xEF, 0x05, 0xAE, 0x3F, 0xFD, 0xEA, + 0x21, 0xA7, 0xF9, 0xD8, 0x2D, 0x34, 0x42, 0xE4, 0xDC, 0x40, 0x1C, 0x82, 0x94, 0x89, 0xC4, 0x74, + 0x0C, 0xF6, 0x76, 0x65, 0x13, 0x29, 0x85, 0xE7, 0xF6, 0x8C, 0x19, 0x3D, 0xC2, 0x69, 0x79, 0x07, + 0x8C, 0x47, 0x24, 0x24, 0x4C, 0xD6, 0x41, 0x93, 0x70, 0x40, 0x08, 0x6D, 0x49, 0x4D, 0x92, 0xAA, + 0x9D, 0x02, 0xAB, 0x53, 0x8D, 0x8C, 0x96, 0x75, 0x54, 0xD0, 0xA2, 0x45, 0xBA, 0x19, 0x81, 0xFE, + 0x20, 0xCC, 0x93, 0x78, 0x4D, 0xBB, 0xA2, 0x21, 0xAB, 0xB5, 0x1B, 0x47, 0x0C, 0xA2, 0x34, 0x24, + 0x1E, 0xF3, 0x40, 0xF3, 0xC8, 0x79, 0xAE, 0x00, 0x40, 0xC3, 0xC4, 0x1B, 0x41, 0x5E, 0xF4, 0x08, + 0x7D, 0x15, 0xF1, 0xDF, 0xE2, 0x34, 0x78, 0xC3, 0x2A, 0x91, 0x8D, 0xC1, 0xA7, 0xF4, 0xD0, 0xF9, + 0xE7, 0x4E, 0x9F, 0xDC, 0x56, 0x16, 0x6C, 0x5B, 0x48, 0x10, 0x7E, 0xE9, 0xA6, 0x3F, 0x3B, 0xD0, + 0xFD, 0x12, 0x46, 0x1B, 0xFF, 0x61, 0x76, 0x61, 0xCC, 0x24, 0x1C, 0x94, 0xDF, 0x77, 0x6F, 0xAE, + 0x8E, 0xEE, 0x96, 0xF6, 0x9B, 0xB4, 0xE9, 0xA5, 0x1E, 0x6D, 0x7C, 0x2C, 0x43, 0xFB, 0x74, 0xF3, + 0x23, 0x86, 0xE6, 0x07, 0xC7, 0x36, 0xE3, 0xED, 0xAF, 0xDD, 0x75, 0x61, 0xCD, 0xFE, 0xEE, 0x4B, + 0x82, 0xF7, 0xC7, 0x66, 0x2B, 0x4C, 0xFF, 0x97, 0x77, 0x1A, 0xF5, 0xA5, 0x55, 0xF2, 0xBD, 0xC0, + 0xD4, 0xD8, 0x07, 0x2A, 0x92, 0xB0, 0x04, 0x56, 0x55, 0x3F, 0x1B, 0xCA, 0x21, 0x25, 0x3F, 0xB9, + 0x81, 0x01, 0x94, 0x43, 0xEE, 0x83, 0xD5, 0x10, 0xB4, 0x13, 0x19, 0xC0, 0x06, 0xBA, 0xEF, 0xA3, + 0xE4, 0xEC, 0xD8, 0x66, 0x30, 0x58, 0xA2, 0xE7, 0x81, 0x65, 0xDA, 0xA1, 0x35, 0x28, 0x4B, 0x47, + 0x17, 0x95, 0xA3, 0x8C, 0x67, 0x44, 0xC8, 0x8B, 0x1B, 0x5F, 0xE9, 0x0E, 0x99, 0xA3, 0x39, 0xAF, + 0x5C, 0xCA, 0x0D, 0x68, 0xAD, 0xE0, 0x91, 0xF3, 0x95, 0x54, 0x02, 0xFF, 0xC4, 0x23, 0xA1, 0x2E, + 0xCE, 0xD2, 0xFC, 0x34, 0x5A, 0xF0, 0x83, 0x82, 0x54, 0x07, 0xDE, 0x21, 0x0D, 0xE3, 0xDF, 0x86, + 0xC1, 0x6E, 0xAB, 0x95, 0x28, 0x90, 0xED, 0x3B, 0x93, 0x95, 0x9E, 0xDE, 0xBA, 0x3E, 0x32, 0x85, + 0x0F, 0xB9, 0x62, 0x68, 0x00, 0x93, 0x38, 0xF9, 0x6B, 0x36, 0x5E, 0xAB, 0x9F, 0xDD, 0x84, 0x97, + 0xB8, 0xAB, 0xDA, 0x29, 0x88, 0xEC, 0x9D, 0xFA, 0xAA, 0x34, 0x2B, 0x1E, 0xC0, 0x6C, 0x53, 0xD4, + 0x55, 0x40, 0x45, 0x9F, 0xEC, 0x0A, 0x90, 0x51, 0xC5, 0x7A, 0x8A, 0xF6, 0xEE, 0x62, 0xC2, 0xE9, + 0x57, 0x2A, 0x1D, 0x8F, 0xB6, 0x83, 0xF9, 0x44, 0x42, 0x33, 0x2A, 0x3D, 0xC7, 0x46, 0xDA, 0xCA, + 0xBC, 0x6B, 0x49, 0x7F, 0x94, 0xB0, 0x6C, 0x80, 0xEC, 0x76, 0x96, 0x12, 0xB9, 0x05, 0x47, 0x96, + 0x84, 0x98, 0xCF, 0x8F, 0x21, 0xF5, 0x6B, 0x86, 0xB8, 0xD4, 0x80, 0xBA, 0xEA, 0x3C, 0xF6, 0x7A, + 0x98, 0xE9, 0x1A, 0x5E, 0x2C, 0x69, 0x1A, 0x2A, 0x31, 0xB9, 0xE6, 0x28, 0xA3, 0xCA, 0xC2, 0x70, + 0xDB, 0xF0, 0x30, 0x28, 0xD3, 0xD6, 0x17, 0xAD, 0x73, 0x8D, 0xB3, 0xF5, 0xFD, 0xA3, 0x6D, 0x8A, + 0xAE, 0x7A, 0x69, 0xD7, 0x6E, 0x4C, 0x29, 0x44, 0xBD, 0x57, 0xBA, 0xC9, 0xFD, 0xA1, 0xEF, 0xA9, + 0xA0, 0x98, 0x39, 0x7A, 0x05, 0x61, 0x46, 0x55, 0x77, 0x5C, 0x1A, 0x39, 0x38, 0x98, 0xFA, 0x79, + 0x9A, 0xBC, 0x68, 0xDB, 0x29, 0x51, 0xDD, 0x2C, 0xEC, 0xFA, 0x61, 0x93, 0x93, 0x44, 0xF2, 0x7E, + 0xD7, 0xA2, 0x79, 0xF1, 0xBD, 0x19, 0x81, 0x36, 0x04, 0x3A, 0x26, 0x20, 0x07, 0x3E, 0x01, 0x8E, + 0x16, 0xE0, 0x6F, 0xF6, 0x29, 0xB8, 0x0B, 0xAC, 0x37, 0x19, 0x39, 0x91, 0x09, 0x23, 0xA6, 0x9C, + 0xAD, 0x08, 0x70, 0xA8, 0x66, 0x0A, 0x22, 0xA2, 0x2E, 0xC5, 0xB9, 0x7F, 0x58, 0xC0, 0x2F, 0x07, + 0x61, 0xB9, 0x2D, 0x3F, 0xA9, 0xB1, 0x67, 0x52, 0xC1, 0x1C, 0x2C, 0xB4, 0xFC, 0x02, 0xA8, 0x4F, + 0x71, 0x87, 0x7F, 0x42, 0x35, 0x93, 0x25, 0xF5, 0x81, 0x07, 0xF9, 0x75, 0x01, 0xBE, 0x08, 0x15, + 0xC5, 0xD1, 0xED, 0x91, 0xB6, 0x0B, 0xC8, 0x8B, 0x4D, 0x62, 0x54, 0xD7, 0x14, 0x9C, 0x3E, 0xEA, + 0x15, 0x3E, 0x91, 0x4F, 0x2F, 0xB5, 0x5C, 0x5A, 0x13, 0x6D, 0x24, 0xE5, 0xB1, 0xA2, 0xFC, 0xAF, + 0x5F, 0x85, 0x13, 0x52, 0x9F, 0x80, 0x19, 0xBB, 0xB7, 0x9A, 0xC6, 0x92, 0x49, 0x2D, 0x28, 0xA7, + 0xA2, 0x28, 0xFA, 0x4A, 0x7B, 0xBA, 0x99, 0x15, 0xA9, 0xF3, 0x51, 0xED, 0xA5, 0xD7, 0x9A, 0xC1, + 0x7A, 0x1E, 0x77, 0x57, 0xBB, 0xA7, 0x25, 0x10, 0xE9, 0x69, 0xAC, 0x50, 0xEF, 0xEC, 0x85, 0x02, + 0x52, 0xC9, 0x29, 0xE9, 0xCB, 0xC8, 0xD0, 0x2D, 0x43, 0xAD, 0x26, 0x93, 0xA8, 0x12, 0xE3, 0xEB, + 0xB1, 0x1E, 0xA2, 0x8D, 0xE4, 0xF7, 0x8F, 0x4B, 0x55, 0xE7, 0xD7, 0x98, 0x3B, 0x7B, 0x85, 0x16, + 0xEE, 0x5A, 0xD8, 0x61, 0x65, 0x57, 0xBC, 0x74, 0x62, 0xD3, 0xDC, 0x7C, 0x6D, 0xCC, 0x56, 0xB0, + 0x3B, 0xA7, 0xE9, 0x10, 0xDE, 0x6A, 0xF4, 0x3A, 0xEC, 0x7E, 0x2E, 0xD0, 0x1E, 0x81, 0x48, 0xD3, + 0xEC, 0xD7, 0xC5, 0xDB, 0x16, 0xBD, 0xD5, 0x5B, 0xAD, 0x8E, 0x13, 0x5A, 0x2A, 0x9E, 0x1A, 0x96, + 0xC3, 0x7E, 0x23, 0xAD, 0xA7, 0x45, 0xE0, 0xCE, 0xA4, 0x52, 0x0C, 0x2A, 0x2E, 0x84, 0x9D, 0xB3, + 0xB4, 0x21, 0x18, 0xA7, 0xCF, 0x57, 0xA3, 0xFE, 0xA1, 0x27, 0x99, 0xCE, 0x48, 0x1E, 0xA7, 0xDB, + 0x62, 0x13, 0x9B, 0x19, 0xE3, 0xBF, 0xAA, 0xA2, 0x9D, 0x29, 0xC9, 0x92, 0xD1, 0x5A, 0x43, 0x4E, + 0xC4, 0xF8, 0xB4, 0xD9, 0xFC, 0xBD, 0x1A, 0xBB, 0x4D, 0x23, 0x99, 0xF3, 0x86, 0xE6, 0xBC, 0xB7, + 0x03, 0xE1, 0xA9, 0xD7, 0xDF, 0x5C, 0x15, 0x56, 0xB4, 0x63, 0xC2, 0x71, 0x6D, 0x15, 0xF1, 0x85, + 0xB6, 0xFF, 0x85, 0x4B, 0x6C, 0x36, 0xDB, 0xA8, 0x07, 0x22, 0x92, 0x4F, 0xD5, 0xA3, 0x2B, 0x40, + 0x8F, 0x6D, 0x89, 0xE3, 0x3E, 0xA2, 0x40, 0xAE, 0x80, 0xA5, 0x3A, 0xD2, 0x5D, 0x7E, 0x74, 0x6A, + 0x94, 0xED, 0xA3, 0xF2, 0x4C, 0x2E, 0x57, 0xF2, 0xBE, 0x8B, 0x25, 0xEF, 0x87, 0x0C, 0x05, 0x99, + 0x27, 0x5E, 0xA5, 0xDE, 0xAE, 0x94, 0x49, 0xFD, 0x7A, 0x62, 0xA7, 0x74, 0x58, 0x8A, 0x1A, 0xED, + 0x15, 0x23, 0x1D, 0x83, 0xD7, 0xA4, 0x6B, 0x4F, 0x3F, 0x9C, 0xBB, 0x5B, 0x27, 0xAD, 0x5C, 0x7E, + 0xA2, 0xE0, 0xBF, 0x39, 0x0C, 0x73, 0xB1, 0x48, 0x07, 0xC1, 0x3B, 0xD5, 0xA6, 0x2D, 0x94, 0x20, + 0x6D, 0xE6, 0x91, 0xAD, 0xCC, 0xDE, 0x4A, 0x3C, 0x4C, 0x02, 0x92, 0xCD, 0x41, 0x46, 0x3C, 0x88, + 0x5A, 0xB6, 0xF6, 0x8F, 0x85, 0x05, 0x7E, 0x75, 0xAC, 0x92, 0x92, 0x99, 0xF4, 0x36, 0x21, 0xE9, + 0x0D, 0x19, 0x02, 0xA1, 0xF0, 0xF1, 0xDB, 0xD8, 0x8F, 0x48, 0x11, 0x5D, 0x84, 0x80, 0x24, 0xD8, + 0xEE, 0x57, 0xB2, 0x3A, 0xE6, 0x0E, 0xC5, 0xA1, 0x26, 0xF9, 0x0C, 0x2E, 0x6C, 0x3A, 0x7A, 0x8B, + 0x0B, 0x9B, 0x3D, 0x2E, 0xAF, 0x26, 0x7D, 0x02, 0x63, 0xC8, 0x0D, 0x24, 0x7D, 0x36, 0x19, 0xAB, + 0xAC, 0xA9, 0x10, 0xA0, 0x53, 0x25, 0x4C, 0xC7, 0x4C, 0x28, 0x4A, 0xC3, 0x38, 0x92, 0xE2, 0x3D, + 0xF3, 0xE1, 0x93, 0xDE, 0x3E, 0x77, 0xAC, 0xEF, 0x6A, 0x08, 0x44, 0xE8, 0x20, 0x18, 0xA3, 0xA0, + 0x90, 0x56, 0xDD, 0xAB, 0x77, 0x7D, 0x36, 0xC2, 0x91, 0xB5, 0x44, 0x8C, 0xD4, 0x57, 0x2C, 0x81, + 0xA1, 0xB9, 0xD9, 0x59, 0x50, 0x8A, 0x76, 0x88, 0x5A, 0x5E, 0x45, 0x99, 0xAC, 0x8C, 0x40, 0x14, + 0x46, 0x28, 0x77, 0xED, 0x1C, 0x7C, 0x59, 0x36, 0x83, 0x4A, 0xA7, 0x0A, 0x71, 0x9C, 0x3B, 0x02, + 0x43, 0x50, 0x74, 0x85, 0xE3, 0xD4, 0x0A, 0x3B, 0x1B, 0xE2, 0xD7, 0x1F, 0x79, 0x78, 0x4B, 0x00, + 0x8E, 0x0A, 0x99, 0xDF, 0x14, 0x17, 0xCD, 0xB8, 0xCF, 0x21, 0xB3, 0x85, 0x38, 0xDE, 0x01, 0xBA, + 0x1B, 0x95, 0x4B, 0x97, 0x2B, 0xB0, 0xC9, 0xED, 0x45, 0xCE, 0x22, 0x5B, 0x8E, 0x04, 0x91, 0x07, + 0x58, 0xC8, 0xB5, 0xA7, 0x06, 0x62, 0x9D, 0xC4, 0xAC, 0x1E, 0x08, 0xFD, 0xEA, 0xB7, 0x4D, 0x0B, + 0xD2, 0x79, 0xA8, 0xEF, 0x4F, 0xBE, 0x80, 0xE6, 0x55, 0x44, 0x7B, 0x59, 0x5E, 0x9C, 0x92, 0x6A, + 0x92, 0xF7, 0xE7, 0x78, 0xFB, 0x46, 0xA1, 0xF4, 0x1E, 0x36, 0x8B, 0xE2, 0x86, 0xA2, 0xE1, 0x19, + 0xB5, 0x29, 0xEA, 0xD2, 0x1D, 0x0B, 0x68, 0xC5, 0x2F, 0x4F, 0x48, 0x6A, 0xC8, 0x92, 0xCE, 0x64, + 0x9D, 0xA5, 0x86, 0xA5, 0x05, 0x40, 0xCE, 0xD7, 0x6C, 0x69, 0x9F, 0x6C, 0xB2, 0xA3, 0x11, 0x08, + 0xEF, 0x9B, 0xCD, 0x10, 0x07, 0x7B, 0x9E, 0x25, 0xF4, 0x1A, 0x2B, 0x21, 0x7E, 0xA5, 0xB9, 0xE1, + 0x33, 0x52, 0xFA, 0x04, 0x09, 0xD4, 0x78, 0xCB, 0x56, 0xE6, 0x55, 0x2C, 0xB4, 0x5D, 0xBB, 0x40, + 0x34, 0xE5, 0x23, 0x30, 0xB8, 0x65, 0x19, 0xF1, 0x5A, 0x08, 0xF2, 0xF4, 0x86, 0x45, 0xB7, 0x87, + 0x17, 0xFA, 0x68, 0x6A, 0x1F, 0x7E, 0x69, 0xDA, 0x89, 0x8E, 0xCA, 0xB6, 0xFF, 0x9F, 0x4E, 0x6F, + 0x25, 0x46, 0x46, 0xF6, 0x7B, 0x1E, 0xB3, 0x3D, 0x2C, 0x8C, 0x01, 0xA9, 0x7B, 0xDA, 0xE9, 0x4D, + 0x6E, 0x89, 0x9D, 0x0F, 0x3F, 0x9F, 0x15, 0x3C, 0xFE, 0x35, 0x61, 0x2A, 0x45, 0xC2, 0xA9, 0xC5, + 0x5C, 0x51, 0xCC, 0x6B, 0xCC, 0x2F, 0xA7, 0x60, 0x03, 0x71, 0xF0, 0xB3, 0xBF, 0x7B, 0x76, 0xCC, + 0x89, 0x2C, 0x31, 0x79, 0xE6, 0xDC, 0x7C, 0x39, 0x24, 0xD8, 0x1A, 0x98, 0x1F, 0x98, 0xCD, 0xD4, + 0x7E, 0x04, 0xF2, 0x92, 0x8D, 0x23, 0x03, 0x5F, 0xF3, 0x05, 0x3B, 0xB0, 0x0A, 0xF0, 0x7A, 0xCA, + 0x76, 0xCB, 0xD0, 0xBA, 0xA0, 0x7F, 0xBA, 0x0D, 0x68, 0x60, 0xC3, 0xEF, 0xDC, 0x44, 0x2E, 0x40, + 0x24, 0x9D, 0xCB, 0x1D, 0x5A, 0x0C, 0x51, 0x66, 0x1A, 0x2A, 0x68, 0xA6, 0x83, 0x20, 0x79, 0x9B, + 0x24, 0xEA, 0x10, 0x5A, 0xB4, 0x39, 0x58, 0xAC, 0xA0, 0x45, 0x3B, 0x16, 0xBE, 0x24, 0x59, 0x1D, + 0x18, 0x5C, 0xD8, 0xCD, 0xFE, 0x16, 0x5C, 0x84, 0x5C, 0x2D, 0x7D, 0x28, 0xC9, 0xCE, 0x9D, 0x38, + 0xF6, 0x2F, 0x9A, 0x8A, 0x93, 0x95, 0xDC, 0x73, 0x48, 0xFD, 0xF5, 0xAB, 0xF4, 0x06, 0xB4, 0x11, + 0x79, 0x7B, 0xF7, 0x75, 0x73, 0xC2, 0x2D, 0x9C, 0x91, 0x7E, 0x51, 0x12, 0x54, 0xAC, 0x55, 0x29, + 0x48, 0x7F, 0x50, 0x15, 0xC2, 0x79, 0x05, 0x3C, 0x8F, 0xB4, 0xAE, 0xDD, 0x28, 0x09, 0xCC, 0x1D, + 0xDE, 0xEF, 0x82, 0xFD, 0x64, 0xD1, 0x5A, 0xFE, 0x06, 0x18, 0x7C, 0xF6, 0x32, 0x67, 0xDB, 0xF1, + 0x55, 0xF4, 0x09, 0x33, 0xB4, 0x91, 0xA7, 0x68, 0xE7, 0xA3, 0x60, 0x93, 0xE6, 0x36, 0xDE, 0x28, + 0xB3, 0xBD, 0x90, 0x46, 0x7F, 0xE5, 0xAF, 0x3C, 0xB6, 0x5E, 0xF2, 0x98, 0xE6, 0x28, 0x07, 0xA9, + 0x21, 0x4C, 0xAA, 0xF7, 0x95, 0xD9, 0x25, 0x51, 0x7F, 0x26, 0x8F, 0xC9, 0xD6, 0x65, 0xCA, 0x07, + 0x82, 0x1F, 0x8E, 0xBF, 0xBA, 0x65, 0xF7, 0xB1, 0x51, 0x85, 0x99, 0x23, 0x4E, 0x48, 0x2E, 0x7B, + 0xC8, 0x09, 0xC4, 0x93, 0xB9, 0xDB, 0x6B, 0xAF, 0xCA, 0xC7, 0x0A, 0xC5, 0x6D, 0xD0, 0xC2, 0xD4, + 0xF5, 0xA1, 0x5E, 0x45, 0x28, 0x54, 0x1D, 0x87, 0xC8, 0x83, 0xAF, 0x9E, 0xB7, 0xC7, 0x4D, 0x48, + 0x3B, 0x49, 0x23, 0x8B, 0x23, 0x6A, 0x2D, 0xD6, 0x30, 0xAD, 0xD3, 0xFA, 0x35, 0x67, 0xF0, 0x0D, + 0x3A, 0xDC, 0x42, 0x57, 0xBE, 0xE6, 0x5B, 0x26, 0x0B, 0x30, 0x45, 0x7E, 0x71, 0x5D, 0x82, 0xE7, + 0x40, 0x45, 0x58, 0xBB, 0xF5, 0x07, 0xEC, 0x36, 0x47, 0xF7, 0x98, 0x05, 0x70, 0x83, 0x17, 0x9D, + 0xDD, 0x4A, 0x4A, 0xB7, 0xB5, 0xBC, 0x8B, 0xF5, 0x08, 0x47, 0x74, 0xF3, 0x0F, 0x3C, 0xB0, 0xC7, + 0x30, 0x88, 0xCF, 0xA2, 0xE1, 0xC3, 0x13, 0x52, 0x20, 0x2D, 0xAD, 0xB3, 0x99, 0x37, 0x71, 0x91, + 0xBB, 0x3F, 0x31, 0xAC, 0xEC, 0xB8, 0x2A, 0x84, 0x12, 0x34, 0x84, 0xE5, 0xBF, 0x47, 0x94, 0xD6, + 0x9A, 0x1F, 0xEB, 0x34, 0xAF, 0xDA, 0x93, 0x5D, 0x22, 0x88, 0x27, 0x1A, 0x04, 0x13, 0xAA, 0x06, + 0x52, 0x8C, 0x44, 0xCB, 0xCC, 0x70, 0x7A, 0xBF, 0xC3, 0x3D, 0x21, 0x71, 0x99, 0x4F, 0x06, 0x42, + 0x8B, 0x7F, 0xDA, 0xBC, 0xAF, 0x7C, 0x24, 0x94, 0x3F, 0xC9, 0xB9, 0xF0, 0xFB, 0x9C, 0xFB, 0x94, + 0xFC, 0x7F, 0xA0, 0x2F, 0x20, 0x4D, 0x57, 0x06, 0xDB, 0xA8, 0xC4, 0xBD, 0x02, 0x6C, 0xDD, 0x00, + 0x8C, 0x84, 0xEF, 0x63, 0xDB, 0x45, 0x34, 0x21, 0x69, 0x73, 0x53, 0x22, 0xD3, 0x61, 0xA6, 0x7A, + 0xDE, 0xC1, 0x66, 0xFD, 0x3B, 0x95, 0x13, 0x76, 0x06, 0xE4, 0x76, 0x0E, 0x63, 0xF2, 0x66, 0x56, + 0xE3, 0x80, 0x55, 0x57, 0xF3, 0x88, 0xA2, 0x5E, 0x84, 0x29, 0xFD, 0x44, 0x78, 0xA9, 0xF0, 0x3A, + 0xF9, 0xE7, 0xDD, 0x66, 0xE1, 0x48, 0xA4, 0xD7, 0x15, 0x06, 0x47, 0xBA, 0x1E, 0x70, 0xA0, 0xA2, + 0xBC, 0x79, 0xCF, 0x9B, 0xA6, 0x61, 0x95, 0x4F, 0xF8, 0x46, 0xA7, 0xD5, 0xB5, 0x5F, 0x66, 0xDD, + 0xE2, 0x5A, 0x8B, 0x29, 0xBA, 0x02, 0xC8, 0x1A, 0x17, 0xFD, 0x72, 0x45, 0xED, 0x63, 0x46, 0x64, + 0x5E, 0xC9, 0x24, 0x8D, 0x91, 0x38, 0xD1, 0xEF, 0xDF, 0x82, 0x09, 0xB0, 0x5B, 0x8C, 0x43, 0x5F, + 0xF9, 0x05, 0x34, 0x1E, 0x2B, 0x4D, 0xA8, 0xC3, 0xE5, 0x9A, 0xD5, 0x95, 0x1B, 0xC0, 0xB9, 0x30, + 0x55, 0xB1, 0xEF, 0x53, 0xD2, 0x86, 0x65, 0x96, 0xD1, 0x3C, 0x75, 0x9E, 0x43, 0xED, 0x72, 0x92, + 0x5F, 0xC3, 0xF8, 0x4C, 0x14, 0xA7, 0x77, 0x22, 0x48, 0x5E, 0xD0, 0x02, 0x32, 0xB4, 0x5F, 0xA9, + 0xCD, 0x9C, 0xF6, 0x46, 0x60, 0xEF, 0x4D, 0x14, 0x84, 0x6E, 0xC5, 0x2C, 0xA6, 0xB2, 0xFB, 0x38, + 0xD1, 0x0C, 0xB2, 0x87, 0xE8, 0x64, 0x1E, 0xFD, 0xC4, 0x28, 0x08, 0x37, 0x61, 0x85, 0x11, 0x44, + 0x76, 0xC9, 0x9F, 0xAD, 0x6D, 0xBC, 0xC0, 0xC8, 0x02, 0xC8, 0xDA, 0x22, 0x1D, 0xB3, 0x54, 0x5F, + 0x38, 0x0D, 0x1D, 0xC0, 0x78, 0x46, 0x7C, 0x46, 0x05, 0xC1, 0x51, 0x9A, 0xF7, 0x7E, 0x51, 0x75, + 0x32, 0xD6, 0xB1, 0x7E, 0x8B, 0x3A, 0xB9, 0xA8, 0x12, 0xAF, 0xF8, 0x20, 0x69, 0xED, 0x37, 0xB4, + 0xD2, 0x7D, 0x7C, 0x08, 0xE4, 0x74, 0xD8, 0x18, 0x2B, 0x6E, 0x65, 0x21, 0xC4, 0x8C, 0xF0, 0xB2, + 0x1A, 0x7D, 0xDD, 0xA5, 0xE9, 0xC3, 0x88, 0xEE, 0x7E, 0x80, 0xE3, 0x4B, 0x3A, 0x56, 0x3D, 0x4B, + 0x75, 0x62, 0xE1, 0xCE, 0xB6, 0xD5, 0xF1, 0xFC, 0x0C, 0x0A, 0x66, 0x10, 0xD2, 0xC0, 0xF3, 0xD3, + 0xCA, 0xFE, 0xD6, 0x73, 0xE4, 0x21, 0xDA, 0xED, 0xE4, 0xE4, 0x5A, 0xAC, 0x31, 0x6D, 0x84, 0x8E, + 0x24, 0x56, 0x6B, 0x09, 0x14, 0x09, 0x81, 0xD6, 0xC6, 0x92, 0x2B, 0xE5, 0x2F, 0x61, 0xCE, 0xD3, + 0xBD, 0x31, 0x10, 0x56, 0x4C, 0x68, 0x18, 0xA2, 0x4E, 0xBF, 0x22, 0x71, 0x77, 0x4A, 0xEC, 0x3F, + 0x8A, 0x10, 0xF9, 0x62, 0x7B, 0x4F, 0x7E, 0xE3, 0x16, 0x23, 0x3C, 0x4A, 0x7B, 0xD9, 0xCC, 0xA1, + 0x13, 0x09, 0x31, 0xD8, 0xD1, 0x23, 0xC4, 0xAD, 0x48, 0xD6, 0xC7, 0xCF, 0xB6, 0xE2, 0x5E, 0x53, + 0xAF, 0x45, 0xF4, 0xE4, 0x82, 0xDC, 0xB3, 0x5D, 0x19, 0x4A, 0x71, 0xBE, 0x75, 0x1D, 0x82, 0x9C, + 0xCD, 0x1F, 0x1E, 0xCE, 0xE1, 0xB6, 0x94, 0xED, 0x9A, 0x3A, 0x1A, 0x66, 0xFF, 0x5C, 0x43, 0x7D, + 0x51, 0x46, 0x09, 0xBB, 0xD0, 0x5D, 0x1A, 0x81, 0x98, 0x9A, 0xAC, 0x74, 0x94, 0xD3, 0x05, 0x55, + 0xE1, 0xE4, 0x2A, 0x43, 0xCC, 0xC8, 0x2C, 0x10, 0xA7, 0xE8, 0xAD, 0x5F, 0x02, 0xDF, 0x3B, 0x10, + 0x33, 0x43, 0x8A, 0x92, 0xF9, 0xCF, 0x12, 0x04, 0x60, 0xCD, 0xA0, 0x30, 0xA9, 0xE8, 0x32, 0x30, + 0x80, 0x8B, 0xF2, 0x09, 0xA4, 0x91, 0xFA, 0x3B, 0xBD, 0x1D, 0x54, 0xFD, 0xF8, 0xCF, 0x74, 0x70, + 0x50, 0x9B, 0x8D, 0x40, 0xBD, 0xC7, 0x3D, 0x4F, 0x03, 0x7B, 0x63, 0x32, 0xCE, 0x8B, 0x5B, 0x7C, + 0x9A, 0xE0, 0x3A, 0x37, 0x38, 0xCA, 0x31, 0x21, 0xDB, 0x4F, 0xF6, 0xF0, 0xDB, 0x4E, 0xE5, 0xDC, + 0x69, 0x4B, 0xAE, 0x28, 0x01, 0xF2, 0x46, 0x38, 0x6A, 0x9A, 0x50, 0x2D, 0xF4, 0x36, 0x5D, 0xEF, + 0x25, 0xB1, 0x31, 0xCA, 0x58, 0x5E, 0x4B, 0xE6, 0xAC, 0xCF, 0x0C, 0x20, 0x84, 0x7F, 0xF5, 0xC1, + 0x1A, 0xE5, 0x94, 0xC3, 0x3D, 0x77, 0x8E, 0xA3, 0x9B, 0xAF, 0x96, 0xBF, 0xD1, 0xEC, 0x35, 0x17, + 0x15, 0xDF, 0x2B, 0x00, 0xCD, 0x2C, 0xDB, 0xD3, 0x31, 0x8A, 0x6D, 0xE0, 0xB3, 0x1F, 0x71, 0xB4, + 0xA4, 0xCA, 0xFA, 0x40, 0xEB, 0x99, 0x4C, 0xFB, 0xFE, 0x9D, 0xBA, 0x26, 0x0F, 0x1B, 0x6D, 0xE6, + 0xB6, 0x2C, 0xAD, 0xF4, 0xD8, 0x12, 0xC0, 0xA3, 0xA4, 0x65, 0x10, 0x1B, 0xCD, 0xFD, 0x0A, 0xB0, + 0x52, 0x71, 0x56, 0xD4, 0x01, 0x49, 0xC9, 0x68, 0x06, 0xA1, 0xD3, 0x61, 0x8A, 0xC1, 0x07, 0x1B, + 0x06, 0x48, 0x78, 0x1B, 0x96, 0xCB, 0x7B, 0xC5, 0xF4, 0x8B, 0x27, 0x93, 0xF1, 0x10, 0x40, 0xB3, + 0x36, 0xA3, 0xA8, 0x19, 0xF3, 0x1B, 0x1B, 0xA4, 0xCD, 0x19, 0x18, 0x25, 0x7C, 0x24, 0xAC, 0x05, + 0xD1, 0xB2, 0xA1, 0x1E, 0x0B, 0xB3, 0xDA, 0x82, 0x3E, 0x78, 0x87, 0x12, 0x8F, 0xE6, 0xB9, 0x59, + 0x02, 0xDC, 0x15, 0x31, 0xA3, 0xAE, 0x22, 0x2F, 0xB7, 0x60, 0x08, 0x42, 0xA0, 0x4B, 0x94, 0xA1, + 0x1A, 0xD9, 0x32, 0x40, 0x2C, 0x33, 0x5A, 0x62, 0xB3, 0xDB, 0x9C, 0x04, 0x3B, 0xCE, 0x40, 0xCD, + 0x3C, 0x29, 0xDB, 0x1C, 0x98, 0xC7, 0x7B, 0x09, 0x65, 0x91, 0xCD, 0xB9, 0x71, 0x80, 0xF2, 0x14, + 0x90, 0x27, 0xA5, 0xC7, 0x16, 0xBB, 0xC8, 0x6D, 0x79, 0x0F, 0xC7, 0x06, 0x4F, 0xFD, 0xEF, 0x3D, + 0x7E, 0xA9, 0x1A, 0x20, 0x4A, 0x94, 0x3F, 0x84, 0xA1, 0x97, 0xE1, 0x99, 0xF5, 0x9E, 0xB2, 0x46, + 0x23, 0xC3, 0x48, 0x46, 0xC0, 0x2C, 0x7D, 0x64, 0x45, 0x7B, 0xA0, 0xBF, 0x5F, 0x14, 0xBC, 0xB2, + 0x17, 0x87, 0x68, 0x5C, 0x17, 0xCE, 0xCA, 0xEA, 0x73, 0x3C, 0xAE, 0x6C, 0x8C, 0x4A, 0x2C, 0xFB, + 0x77, 0x52, 0xE7, 0xA1, 0xFF, 0x6C, 0x23, 0x05, 0x1E, 0x69, 0x22, 0xF1, 0xDA, 0x6B, 0xB6, 0x01, + 0x44, 0xDE, 0xEB, 0x80, 0xB7, 0x84, 0x5B, 0xC7, 0xEA, 0x59, 0x5B, 0x3F, 0x23, 0x7E, 0x10, 0x00, + 0x27, 0x5C, 0x6A, 0x7B, 0xEB, 0xFF, 0xDF, 0x82, 0xEE, 0x85, 0x6C, 0xA5, 0x1A, 0xBF, 0xEB, 0x64, + 0xBB, 0x10, 0x46, 0x40, 0x51, 0x29, 0x2C, 0x6A, 0xD2, 0xF5, 0x58, 0x61, 0x5F, 0x77, 0x31, 0xBD, + 0x59, 0x0A, 0x1B, 0xF5, 0xC2, 0xFA, 0x9A, 0xB4, 0x59, 0xF4, 0x0A, 0xD1, 0x68, 0xCC, 0x21, 0x44, + 0xDC, 0x70, 0x80, 0xD1, 0x67, 0xCC, 0x24, 0x22, 0xC0, 0x77, 0x04, 0xED, 0xA3, 0xB4, 0x23, 0xC8, + 0xAD, 0x5E, 0x18, 0x64, 0x57, 0x89, 0x52, 0xDD, 0x25, 0x6C, 0x38, 0xCE, 0x5D, 0x45, 0x42, 0x18, + 0xA3, 0xE2, 0xD8, 0x6E, 0x21, 0x5F, 0xBB, 0x9D, 0xCA, 0x90, 0x57, 0x85, 0x0C, 0xD5, 0x56, 0xC8, + 0x12, 0x39, 0x27, 0x44, 0x77, 0xE6, 0x59, 0xE7, 0x08, 0xB0, 0x4E, 0x80, 0xBD, 0xE3, 0xE6, 0x8B, + 0xE1, 0x4B, 0x6E, 0xCE, 0xA9, 0x5C, 0x8E, 0xF2, 0xE2, 0xFE, 0x18, 0xFB, 0x74, 0xD6, 0x3C, 0x76, + 0xB8, 0xB0, 0x90, 0x00, 0x3A, 0xF4, 0xE4, 0xB7, 0xFD, 0x05, 0xA3, 0x7A, 0xD9, 0xF7, 0x0E, 0x18, + 0x66, 0xBC, 0x9A, 0x47, 0x18, 0x80, 0x4F, 0x4A, 0x6B, 0x9C, 0xF8, 0x48, 0x16, 0x49, 0x3F, 0x21, + 0xB4, 0x20, 0x59, 0x51, 0xDA, 0xD1, 0x4B, 0xE8, 0x5E, 0x48, 0x95, 0x77, 0x0A, 0x82, 0xA1, 0x8F, + 0xD2, 0x77, 0xC9, 0xC5, 0xE2, 0x79, 0x24, 0x87, 0x34, 0x0C, 0x9E, 0x17, 0x6F, 0x7B, 0xEA, 0x14, + 0x79, 0xF6, 0x0C, 0x95, 0x5F, 0x1C, 0x61, 0x01, 0x61, 0x6D, 0xD1, 0xF2, 0x6A, 0xA8, 0x09, 0xAA, + 0x0A, 0x6E, 0xF9, 0x28, 0x69, 0x49, 0x14, 0x60, 0x6D, 0xA3, 0xCF, 0x5E, 0x4C, 0x34, 0x8E, 0xFC, + 0x7E, 0x3E, 0x72, 0x3E, 0x02, 0x78, 0x3D, 0x1B, 0xA4, 0x93, 0x46, 0x39, 0x46, 0x0E, 0xF0, 0xE3, + 0x46, 0xF0, 0x4C, 0x2F, 0xE2, 0x14, 0x93, 0xF0, 0x2A, 0x5B, 0xE8, 0x05, 0xF7, 0x10, 0x3A, 0x6D, + 0x03, 0xA0, 0x5D, 0xF8, 0x5D, 0xD1, 0x4C, 0x58, 0x7B, 0xBF, 0xAB, 0x52, 0xC1, 0x6E, 0x72, 0x1E, + 0x60, 0x8C, 0x33, 0x4E, 0x22, 0xE7, 0x12, 0x51, 0x0B, 0xFE, 0x22, 0xDA, 0x8A, 0x53, 0xA7, 0xC6, + 0x9A, 0x66, 0x92, 0x76, 0x46, 0x3C, 0xC5, 0x72, 0x55, 0x6C, 0xD2, 0x8D, 0xF1, 0xD5, 0x6C, 0x09, + 0xEA, 0x2D, 0x1A, 0xF9, 0x99, 0x5E, 0x65, 0xCC, 0x6D, 0x55, 0x5F, 0x46, 0x66, 0xC3, 0xBB, 0xBE, + 0x1C, 0x53, 0x40, 0x3B, 0xE9, 0x15, 0x6C, 0xD6, 0x94, 0x8C, 0x5D, 0xB4, 0x4A, 0xDC, 0x2F, 0x2F, + 0xC1, 0xA8, 0xE1, 0xDF, 0x7A, 0xB5, 0x6D, 0xE2, 0xF8, 0xDB, 0xAA, 0x5D, 0x3D, 0x80, 0x5D, 0x33, + 0x6F, 0xCD, 0x5A, 0x84, 0xBC, 0x2D, 0x6E, 0x28, 0x97, 0x07, 0xA6, 0xF1, 0x0B, 0x22, 0x23, 0x58, + 0xDF, 0x50, 0x15, 0x73, 0xD6, 0x75, 0x63, 0xB6, 0x0F, 0xD8, 0x75, 0x9B, 0xF9, 0x9D, 0xBF, 0xE6, + 0xAF, 0xF8, 0xBF, 0xB4, 0x3A, 0xD4, 0x02, 0x3B, 0x8A, 0x4D, 0xF6, 0x44, 0x0E, 0x7F, 0x2B, 0xDB, + 0x9C, 0xAC, 0xD6, 0xB8, 0xC5, 0xB5, 0xEF, 0x1B, 0x67, 0xB0, 0x10, 0xCC, 0x1E, 0x24, 0xD4, 0x05, + 0x06, 0x6D, 0x3A, 0xFE, 0x95, 0x4C, 0x00, 0x8A, 0xD2, 0x53, 0x1B, 0x7A, 0xDE, 0xA0, 0x9F, 0x2D, + 0x10, 0x43, 0x2D, 0xA3, 0x8E, 0x66, 0x36, 0x27, 0x77, 0x05, 0x26, 0x78, 0x21, 0x09, 0x18, 0xD0, + 0x2E, 0x86, 0x1E, 0x56, 0x3B, 0x71, 0x3A, 0x46, 0x24, 0x7C, 0x90, 0x1E, 0x42, 0x36, 0x11, 0xA1, + 0x7C, 0x04, 0x80, 0x42, 0x0F, 0xA8, 0x4E, 0x07, 0xA1, 0x7B, 0x55, 0x5F, 0xA8, 0x8A, 0x1D, 0x36, + 0x9C, 0x16, 0xBD, 0xE0, 0x63, 0x0A, 0xE3, 0xC5, 0xF9, 0x55, 0xA4, 0xE9, 0x75, 0x7D, 0xD5, 0x82, + 0x32, 0x1E, 0x6B, 0x05, 0xE4, 0xF9, 0x8A, 0x8C, 0x18, 0x0E, 0xA0, 0xDF, 0x23, 0x4D, 0xA8, 0x4E, + 0xF0, 0x85, 0xFF, 0x04, 0xC5, 0xFE, 0x1E, 0x8A, 0x3F, 0xBF, 0x54, 0x05, 0x82, 0x8A, 0x0C, 0xDF, + 0xCA, 0x0A, 0xD0, 0x43, 0x76, 0xE5, 0x49, 0x55, 0x36, 0x24, 0x6F, 0x2F, 0x20, 0x58, 0x3A, 0xFE, + 0x62, 0x3A, 0x11, 0xAA, 0x2F, 0xB2, 0x25, 0x6F, 0x0B, 0x9D, 0xD8, 0xCC, 0xC5, 0x26, 0x16, 0x2E, + 0x74, 0x56, 0xBE, 0x99, 0xF4, 0xE7, 0x90, 0x88, 0x65, 0x1E, 0x6C, 0xAA, 0xB4, 0x2C, 0xCF, 0x12, + 0x63, 0x86, 0x8E, 0x9C, 0xF5, 0x75, 0x5A, 0x71, 0xBF, 0xFB, 0x54, 0xF3, 0x86, 0x61, 0xC5, 0x59, + 0xB4, 0xD5, 0x8E, 0x5D, 0x91, 0xA0, 0xB0, 0x9B, 0xB1, 0x95, 0xCE, 0x45, 0x0C, 0x4A, 0xFC, 0xE0, + 0x56, 0x73, 0x96, 0xC1, 0xAA, 0x0A, 0x65, 0x42, 0x42, 0xC1, 0xC7, 0x2D, 0x6E, 0xC8, 0x4A, 0x7F, + 0x40, 0x53, 0x0C, 0x7A, 0x99, 0x96, 0x59, 0xFA, 0xEC, 0xAD, 0xA1, 0xF0, 0xAB, 0xFE, 0xB6, 0x58, + 0x49, 0x65, 0xF4, 0x29, 0x2A, 0x21, 0x42, 0x93, 0x0A, 0xED, 0x38, 0xC0, 0x33, 0xFD, 0xCF, 0x8E, + 0xC1, 0xEC, 0x3A, 0xF9, 0x1F, 0xEA, 0x8F, 0xA2, 0xEA, 0xAE, 0xC4, 0xE7, 0x43, 0xCB, 0x53, 0xF1, + 0x77, 0xC9, 0x6C, 0x61, 0x35, 0xE2, 0xED, 0x25, 0x68, 0xF6, 0x8E, 0x06, 0xD6, 0x41, 0x87, 0x58, + 0x8A, 0xE4, 0x5F, 0x80, 0x59, 0xC7, 0x21, 0xAC, 0xC1, 0x95, 0xC8, 0xBA, 0xF9, 0x84, 0x1F, 0x70, + 0x15, 0x1C, 0xB1, 0xF1, 0x2B, 0xB4, 0xB7, 0xA0, 0x4B, 0xE3, 0xB3, 0xD4, 0x3C, 0x9C, 0x01, 0xB2, + 0x4A, 0xE5, 0x47, 0x39, 0x10, 0x32, 0xE0, 0x0E, 0x1C, 0xE9, 0x3E, 0x2E, 0xDD, 0x12, 0x2C, 0xDF, + 0xB7, 0x47, 0xE8, 0x88, 0x53, 0x28, 0xF2, 0xC6, 0x11, 0x12, 0x15, 0x4A, 0x60, 0x14, 0xA4, 0x78, + 0x54, 0x8E, 0x6A, 0x77, 0xD6, 0x74, 0xC2, 0xCD, 0x4B, 0xF9, 0xC2, 0x84, 0xE8, 0xD6, 0xED, 0x4D, + 0xB3, 0x0C, 0x32, 0x39, 0xCF, 0xB9, 0xF9, 0x0B, 0xC3, 0x52, 0xF5, 0x6E, 0x9A, 0x38, 0x84, 0xED, + 0x0D, 0x83, 0xFA, 0x83, 0x2D, 0xF4, 0xB3, 0xEE, 0x71, 0xE0, 0x47, 0x48, 0xE6, 0x1A, 0x0B, 0xD9, + 0x54, 0x74, 0xB8, 0x39, 0xA1, 0x4C, 0xC7, 0x3C, 0x52, 0x02, 0x07, 0x61, 0x12, 0x1B, 0x49, 0x0B, + 0x7D, 0x08, 0xAA, 0xEA, 0xB0, 0x3A, 0x05, 0x65, 0x9A, 0xEA, 0x68, 0x0C, 0x5B, 0xA6, 0x37, 0xC6, + 0x5F, 0x10, 0x7D, 0xC8, 0xAE, 0xCA, 0x65, 0x1F, 0x16, 0x80, 0x38, 0xF1, 0xB7, 0xB5, 0xDB, 0x1D, + 0x37, 0x5A, 0x1D, 0xEB, 0x7B, 0x2C, 0xA1, 0x7B, 0x72, 0xCE, 0x0D, 0x34, 0xB4, 0x17, 0x23, 0x52, + 0x8B, 0x3A, 0xD6, 0xEC, 0xE5, 0x8D, 0x23, 0x6A, 0xCF, 0x34, 0xDE, 0x02, 0x5A, 0xA4, 0x54, 0xFF, + 0x85, 0x85, 0x3E, 0x33, 0x87, 0xF9, 0x27, 0x59, 0xE2, 0x32, 0xAB, 0x8D, 0xBA, 0x8A, 0x92, 0xEB, + 0x5D, 0xA7, 0xF6, 0x6A, 0xDF, 0x32, 0xAD, 0xAC, 0x70, 0xCF, 0x91, 0xA9, 0x8E, 0x4C, 0x39, 0x71, + 0x4C, 0x1B, 0xBF, 0xD1, 0xD0, 0x68, 0x19, 0x9C, 0x8A, 0x7B, 0x57, 0x52, 0x40, 0xCE, 0xCC, 0x86, + 0xB7, 0x0E, 0x3D, 0x5E, 0xAD, 0xD0, 0x2B, 0xD4, 0x58, 0x5C, 0x5B, 0xD8, 0x00, 0x7F, 0x42, 0x99, + 0x84, 0x5D, 0x2D, 0x86, 0x40, 0x10, 0x35, 0x15, 0x05, 0x67, 0xDE, 0x22, 0x6C, 0xB4, 0x5C, 0x7B, + 0xCA, 0xDF, 0xF4, 0x1D, 0xD2, 0xCB, 0x34, 0x02, 0x6C, 0x22, 0x10, 0x4F, 0x7F, 0xDF, 0x18, 0xFF, + 0x5A, 0x81, 0x4C, 0xAC, 0xF7, 0xF3, 0xF1, 0x5D, 0xBA, 0x72, 0x36, 0x26, 0x88, 0xAE, 0xCA, 0xE0, + 0x79, 0x84, 0x68, 0x86, 0xCE, 0x35, 0xAF, 0x27, 0xB4, 0x21, 0xFD, 0x05, 0xB1, 0x38, 0x17, 0x7D, + 0x9B, 0x5A, 0x12, 0x29, 0x76, 0xE5, 0xA0, 0x39, 0x0B, 0xAD, 0x4C, 0x33, 0xCB, 0x45, 0x59, 0x82, + 0xB7, 0x03, 0xD2, 0x1A, 0xF7, 0x2F, 0x54, 0x43, 0x92, 0xC9, 0x8B, 0x6F, 0x6C, 0x6C, 0x1B, 0x10, + 0xEE, 0x97, 0x38, 0xA5, 0x8B, 0x16, 0xDE, 0xFC, 0xDA, 0x83, 0x4B, 0x39, 0x79, 0x17, 0xB7, 0x5A, + 0x59, 0x01, 0x11, 0xC0, 0xC6, 0x36, 0xD5, 0xBA, 0xB1, 0x46, 0x9E, 0x6B, 0xA1, 0xCB, 0x96, 0x7E, + 0x56, 0x91, 0x87, 0x68, 0x59, 0x8E, 0xCF, 0xB5, 0x58, 0x24, 0x2C, 0xD9, 0x0A, 0x06, 0x25, 0xCB, + 0x8C, 0xE6, 0x02, 0xE3, 0x5A, 0x19, 0x4D, 0x8F, 0x43, 0x5B, 0x40, 0x3F, 0x7D, 0x50, 0x24, 0x90, + 0x71, 0x3E, 0x88, 0x96, 0x3C, 0xCE, 0x2C, 0x80, 0x35, 0x68, 0x3E, 0x21, 0x67, 0x8A, 0x03, 0x68, + 0x49, 0x6B, 0xFA, 0xE2, 0x5A, 0xC7, 0xFF, 0x9C, 0xDF, 0x0D, 0xD9, 0xB5, 0x12, 0x07, 0x35, 0x7B, + 0x35, 0xDC, 0xF7, 0x12, 0x55, 0x71, 0x8A, 0x9F, 0x68, 0x66, 0x2A, 0x72, 0x55, 0x14, 0x82, 0xE2, + 0xBC, 0x3A, 0x39, 0xA7, 0x91, 0xA9, 0x91, 0xC8, 0x2B, 0x5F, 0x0A, 0x09, 0xFD, 0xE0, 0x6B, 0x58, + 0x85, 0x58, 0x1D, 0xCD, 0xEA, 0xAE, 0xBA, 0xA5, 0x49, 0xFF, 0x69, 0x4A, 0x10, 0xDD, 0x5A, 0xE0, + 0x0E, 0xD3, 0x9C, 0x0B, 0xD8, 0x28, 0x2E, 0xCA, 0x8E, 0x9F, 0x29, 0x84, 0xC8, 0xCA, 0x47, 0x79, + 0xB9, 0xCC, 0x71, 0xC6, 0xE1, 0xC1, 0x4D, 0x15, 0xB6, 0x1F, 0x92, 0x13, 0x2C, 0x83, 0xBE, 0x0D, + 0x03, 0x0A, 0x7C, 0x02, 0x7C, 0x2C, 0xFA, 0x8E, 0xC8, 0x23, 0xE1, 0xFD, 0x83, 0xDC, 0x61, 0xDB, + 0x1C, 0xE4, 0x3F, 0xE8, 0xA9, 0x1C, 0x55, 0x1E, 0xB2, 0xF1, 0x47, 0x6C, 0x5A, 0xD8, 0xD9, 0xD4, + 0xA8, 0xBF, 0x4B, 0xF9, 0x0A, 0xD5, 0xBF, 0x1D, 0x88, 0x30, 0x12, 0x80, 0x72, 0x49, 0x6C, 0x91, + 0x70, 0x6A, 0xB7, 0x4D, 0x86, 0x34, 0x8F, 0x57, 0x1A, 0x6A, 0x16, 0x7B, 0xA5, 0x5D, 0x3C, 0x74, + 0x8E, 0x03, 0x1D, 0x53, 0xD6, 0x1C, 0x75, 0x83, 0x2C, 0xF7, 0x5E, 0xF6, 0xE0, 0xC9, 0x25, 0x11, + 0x9F, 0x98, 0x73, 0xD2, 0xBE, 0x50, 0x56, 0xD6, 0x73, 0x38, 0xC8, 0x30, 0x5A, 0xB5, 0xF6, 0x67, + 0x37, 0x75, 0x7E, 0x99, 0x71, 0xC7, 0x30, 0x26, 0x0D, 0x43, 0xA2, 0x0B, 0xF0, 0xC2, 0xCC, 0x38, + 0xDF, 0x0F, 0x37, 0x25, 0xA0, 0x4F, 0x18, 0x5A, 0x40, 0x75, 0x2D, 0xFC, 0x52, 0xFF, 0x37, 0xD5, + 0x38, 0x06, 0xC6, 0x62, 0x13, 0xA0, 0x8E, 0x7A, 0xFA, 0xDD, 0xB9, 0x25, 0xBE, 0xBC, 0x1F, 0x02, + 0x4C, 0x56, 0xA1, 0xBA, 0x08, 0xBB, 0x65, 0xAE, 0xAC, 0x14, 0x4E, 0x65, 0xD7, 0xD1, 0x99, 0xFF, + 0x14, 0x33, 0x9F, 0x18, 0x1D, 0x54, 0x70, 0x6F, 0xBC, 0x85, 0xB4, 0x49, 0x82, 0x4C, 0x0A, 0xA6, + 0xE8, 0x10, 0x61, 0x8F, 0xED, 0xFD, 0x7F, 0x10, 0xAA, 0xAC, 0x13, 0xB5, 0xE2, 0x5D, 0xF3, 0x69, + 0x2B, 0xC3, 0xE1, 0xC2, 0x89, 0x9A, 0x46, 0xF0, 0x97, 0x34, 0xFC, 0x93, 0x31, 0x45, 0xE9, 0x7A, + 0xD4, 0x46, 0x1A, 0x31, 0xFF, 0x65, 0x39, 0xAE, 0xCE, 0xC5, 0x40, 0x2F, 0xD0, 0xCB, 0x1E, 0xC6, + 0x86, 0xDC, 0x2F, 0x72, 0x34, 0x35, 0x28, 0xAD, 0x96, 0xC3, 0xBE, 0xE4, 0xC8, 0xA5, 0xB6, 0x6B, + 0xBD, 0xFB, 0x9B, 0xE5, 0x16, 0x01, 0x4A, 0x55, 0xA2, 0xB0, 0xE8, 0x66, 0x4A, 0xC1, 0xE3, 0xC0, + 0xB9, 0x87, 0xF4, 0xD6, 0x8C, 0xF4, 0x61, 0x42, 0xA4, 0xBF, 0x73, 0x03, 0x67, 0xBD, 0x2F, 0x30, + 0x6E, 0x97, 0x45, 0x0F, 0xC6, 0xBD, 0xCA, 0x2E, 0x69, 0x72, 0x41, 0x07, 0x38, 0x74, 0x18, 0xB1, + 0xCB, 0x5C, 0xD3, 0xC2, 0x1D, 0xB7, 0xF2, 0xAF, 0xEC, 0x00, 0xCD, 0x4F, 0x6F, 0xDE, 0xB2, 0xAC, + 0x44, 0x4C, 0x1A, 0x56, 0xC3, 0x93, 0x21, 0x57, 0x8C, 0x6B, 0x1C, 0xD7, 0xF9, 0xC7, 0xC0, 0xA9, + 0xF7, 0xE4, 0xA3, 0xD8, 0x58, 0x9B, 0x35, 0xE6, 0x00, 0x7C, 0xE2, 0x12, 0xD0, 0x53, 0x61, 0x1F, + 0xC6, 0xA5, 0x81, 0x7A, 0x52, 0xEF, 0x09, 0x36, 0x1A, 0x62, 0x3C, 0x92, 0xD2, 0x65, 0x43, 0xF6, + 0xDF, 0x0B, 0x89, 0x7E, 0xC6, 0xB9, 0x47, 0xF4, 0x52, 0x14, 0x0C, 0x44, 0x4D, 0x23, 0x55, 0x6F, + 0x80, 0xC2, 0xBE, 0xC5, 0x59, 0xF8, 0xB5, 0x27, 0xE6, 0xE8, 0xF0, 0x32, 0x91, 0x3A, 0x59, 0x2B, + 0x1D, 0xF9, 0xAC, 0xF9, 0x2E, 0xF3, 0xB9, 0x36, 0x8C, 0x1A, 0x5D, 0x92, 0x33, 0xEA, 0xA6, 0xAF, + 0x71, 0x24, 0xE2, 0x7F, 0x18, 0xB1, 0x23, 0x3C, 0x53, 0xF3, 0xCC, 0x5D, 0xD4, 0x2D, 0x2B, 0x7A, + 0xF8, 0x94, 0x04, 0xC0, 0x8C, 0x65, 0x4D, 0x3A, 0xFA, 0xCF, 0xF9, 0x07, 0xC2, 0xD7, 0x75, 0x87, + 0x47, 0x9E, 0x6E, 0xA0, 0x79, 0x81, 0x6E, 0x03, 0xC7, 0xD2, 0x75, 0xF6, 0xC3, 0x85, 0x22, 0x28, + 0x1B, 0x39, 0x63, 0xCC, 0x12, 0x7E, 0x4A, 0xC3, 0x2A, 0x45, 0x85, 0xA9, 0x54, 0xDF, 0xB2, 0x33, + 0xEF, 0x76, 0x25, 0x31, 0xC9, 0xCD, 0xDA, 0x14, 0xE7, 0xD8, 0x4D, 0x18, 0xCE, 0xAB, 0xE7, 0x85, + 0xDD, 0x95, 0x8D, 0x36, 0xA1, 0x18, 0x87, 0x5E, 0xB6, 0x75, 0x2F, 0x3B, 0x97, 0x09, 0x18, 0x47, + 0xC8, 0x90, 0x37, 0xA3, 0xB2, 0xD2, 0x09, 0x3C, 0x5E, 0x6C, 0x2E, 0x72, 0x38, 0x08, 0x24, 0x99, + 0x90, 0xD0, 0x86, 0xC7, 0xD3, 0xFB, 0x4E, 0xA2, 0xDF, 0xC7, 0x26, 0x4D, 0x8E, 0x81, 0x98, 0x19, + 0x15, 0xD0, 0x4C, 0xB8, 0x44, 0xF7, 0x53, 0x1C, 0x0F, 0xAF, 0x78, 0x4C, 0x20, 0xB8, 0xCC, 0xBB, + 0x20, 0x60, 0xEC, 0x55, 0x70, 0xBD, 0xE9, 0x02, 0x63, 0x9F, 0x1F, 0xA7, 0xD5, 0x27, 0x18, 0x33, + 0x29, 0xA8, 0x33, 0x6E, 0xCB, 0x80, 0x40, 0x2D, 0x52, 0xDF, 0x6C, 0x78, 0x8F, 0xA6, 0x1D, 0xCF, + 0xE8, 0xB9, 0x54, 0x6B +}; + +uint8 Module_79C0768D657977D697E10BAD956CCED1_Key[16] = +{ + 0xAE, 0x25, 0xBC, 0x51, 0x06, 0x3B, 0x77, 0xBD, 0x36, 0x3C, 0x3E, 0xFE, 0x0F, 0xC1, 0x73, 0xF9 +}; + +#endif diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp new file mode 100644 index 00000000000..3d625df63d0 --- /dev/null +++ b/src/server/game/Warden/Warden.cpp @@ -0,0 +1,234 @@ +/* + * 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 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 "Log.h" +#include "Opcodes.h" +#include "ByteBuffer.h" +#include <openssl/md5.h> +#include <openssl/sha.h> +#include "World.h" +#include "Player.h" +#include "Util.h" +#include "Warden.h" +#include "AccountMgr.h" + +Warden::Warden() : _inputCrypto(16), _outputCrypto(16), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0), _dataSent(false), _initialized(false) +{ +} + +Warden::~Warden() +{ + delete[] _module->CompressedData; + delete _module; + _module = NULL; + _initialized = false; +} + +void Warden::SendModuleToClient() +{ + sLog->outDebug(LOG_FILTER_WARDEN, "Send module to client"); + + // Create packet structure + WardenModuleTransfer packet; + + uint32 sizeLeft = _module->CompressedSize; + uint32 pos = 0; + uint16 burstSize; + while (sizeLeft > 0) + { + burstSize = sizeLeft < 500 ? sizeLeft : 500; + packet.Command = WARDEN_SMSG_MODULE_CACHE; + packet.DataSize = burstSize; + memcpy(packet.Data, &_module->CompressedData[pos], burstSize); + sizeLeft -= burstSize; + pos += burstSize; + + EncryptData((uint8*)&packet, burstSize + 3); + WorldPacket pkt1(SMSG_WARDEN_DATA, burstSize + 3); + pkt1.append((uint8*)&packet, burstSize + 3); + _session->SendPacket(&pkt1); + } +} + +void Warden::RequestModule() +{ + sLog->outDebug(LOG_FILTER_WARDEN, "Request module"); + + // Create packet structure + WardenModuleUse request; + request.Command = WARDEN_SMSG_MODULE_USE; + + memcpy(request.ModuleId, _module->Id, 16); + memcpy(request.ModuleKey, _module->Key, 16); + request.Size = _module->CompressedSize; + + // Encrypt with warden RC4 key. + EncryptData((uint8*)&request, sizeof(WardenModuleUse)); + + WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenModuleUse)); + pkt.append((uint8*)&request, sizeof(WardenModuleUse)); + _session->SendPacket(&pkt); +} + +void Warden::Update() +{ + if (_initialized) + { + uint32 currentTimestamp = getMSTime(); + uint32 diff = currentTimestamp - _previousTimestamp; + _previousTimestamp = currentTimestamp; + + if (_dataSent) + { + uint32 maxClientResponseDelay = sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_RESPONSE_DELAY); + + if (maxClientResponseDelay > 0) + { + // Kick player if client response delays more than set in config + if (_clientResponseTimer > maxClientResponseDelay * IN_MILLISECONDS) + { + sLog->outWarden("WARDEN: Player %s (guid: %u, account: %u, latency: %u, IP: %s) exceeded Warden module response delay for more than %s - disconnecting client", + _session->GetPlayerName(), _session->GetGuidLow(), _session->GetAccountId(), _session->GetLatency(), _session->GetRemoteAddress().c_str(), + secsToTimeString(maxClientResponseDelay, true).c_str()); + _session->KickPlayer(); + } + else + _clientResponseTimer += diff; + } + } + else + { + if (diff >= _checkTimer) + { + RequestData(); + } + else + _checkTimer -= diff; + } + } +} + +void Warden::DecryptData(uint8* buffer, uint32 length) +{ + _inputCrypto.UpdateData(length, buffer); +} + +void Warden::EncryptData(uint8* buffer, uint32 length) +{ + _outputCrypto.UpdateData(length, buffer); +} + +bool Warden::IsValidCheckSum(uint32 checksum, const uint8* data, const uint16 length) +{ + uint32 newChecksum = BuildChecksum(data, length); + + if (checksum != newChecksum) + { + sLog->outDebug(LOG_FILTER_WARDEN, "CHECKSUM IS NOT VALID"); + return false; + } + else + { + sLog->outDebug(LOG_FILTER_WARDEN, "CHECKSUM IS VALID"); + return true; + } +} + +uint32 Warden::BuildChecksum(const uint8* data, uint32 length) +{ + uint8 hash[20]; + SHA1(data, length, hash); + uint32 checkSum = 0; + for (uint8 i = 0; i < 5; ++i) + checkSum = checkSum ^ *(uint32*)(&hash[0] + i * 4); + + return checkSum; +} + +std::string Warden::Penalty(WardenCheck* check /*= NULL*/) +{ + WardenActions action; + + if (check) + action = check->Action; + else + action = WardenActions(sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_FAIL_ACTION)); + + switch (action) + { + case WARDEN_ACTION_LOG: + return "None"; + break; + case WARDEN_ACTION_KICK: + _session->KickPlayer(); + return "Kick"; + break; + case WARDEN_ACTION_BAN: + { + std::stringstream duration; + duration << sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_BAN_DURATION) << "s"; + std::string accountName; + AccountMgr::GetName(_session->GetAccountId(), accountName); + sWorld->BanAccount(BAN_ACCOUNT, accountName, duration.str(), "Warden Anticheat violation","Server"); + + return "Ban"; + break; + } + default: + return "Undefined"; + break; + } +} + +void WorldSession::HandleWardenDataOpcode(WorldPacket& recvData) +{ + _warden->DecryptData(const_cast<uint8*>(recvData.contents()), recvData.size()); + uint8 opcode; + recvData >> opcode; + sLog->outDebug(LOG_FILTER_WARDEN, "Got packet, opcode %02X, size %u", opcode, recvData.size()); + recvData.hexlike(); + + switch(opcode) + { + case WARDEN_CMSG_MODULE_MISSING: + _warden->SendModuleToClient(); + break; + case WARDEN_CMSG_MODULE_OK: + _warden->RequestHash(); + break; + case WARDEN_CMSG_CHEAT_CHECKS_RESULT: + _warden->HandleData(recvData); + break; + case WARDEN_CMSG_MEM_CHECKS_RESULT: + sLog->outDebug(LOG_FILTER_WARDEN, "NYI WARDEN_CMSG_MEM_CHECKS_RESULT received!"); + break; + case WARDEN_CMSG_HASH_RESULT: + _warden->HandleHashResult(recvData); + _warden->InitializeModule(); + break; + case WARDEN_CMSG_MODULE_FAILED: + sLog->outDebug(LOG_FILTER_WARDEN, "NYI WARDEN_CMSG_MODULE_FAILED received!"); + break; + default: + sLog->outDebug(LOG_FILTER_WARDEN, "Got unknown warden opcode %02X of size %u.", opcode, recvData.size() - 1); + break; + } +} diff --git a/src/server/game/Warden/Warden.h b/src/server/game/Warden/Warden.h new file mode 100644 index 00000000000..e06ea7dca25 --- /dev/null +++ b/src/server/game/Warden/Warden.h @@ -0,0 +1,147 @@ +/* + * 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 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 _WARDEN_BASE_H +#define _WARDEN_BASE_H + +#include <map> +#include "Cryptography/ARC4.h" +#include "Cryptography/BigNumber.h" +#include "ByteBuffer.h" +#include "WardenCheckMgr.h" + +enum WardenOpcodes +{ + // Client->Server + WARDEN_CMSG_MODULE_MISSING = 0, + WARDEN_CMSG_MODULE_OK = 1, + WARDEN_CMSG_CHEAT_CHECKS_RESULT = 2, + WARDEN_CMSG_MEM_CHECKS_RESULT = 3, // only sent if MEM_CHECK bytes doesn't match + WARDEN_CMSG_HASH_RESULT = 4, + WARDEN_CMSG_MODULE_FAILED = 5, // this is sent when client failed to load uploaded module due to cache fail + + // Server->Client + WARDEN_SMSG_MODULE_USE = 0, + WARDEN_SMSG_MODULE_CACHE = 1, + WARDEN_SMSG_CHEAT_CHECKS_REQUEST = 2, + WARDEN_SMSG_MODULE_INITIALIZE = 3, + WARDEN_SMSG_MEM_CHECKS_REQUEST = 4, // byte len; while(!EOF) { byte unk(1); byte index(++); string module(can be 0); int offset; byte len; byte[] bytes_to_compare[len]; } + WARDEN_SMSG_HASH_REQUEST = 5 +}; + +enum WardenCheckType +{ + MEM_CHECK = 0xF3, // 243: byte moduleNameIndex + uint Offset + byte Len (check to ensure memory isn't modified) + PAGE_CHECK_A = 0xB2, // 178: uint Seed + byte[20] SHA1 + uint Addr + byte Len (scans all pages for specified hash) + PAGE_CHECK_B = 0xBF, // 191: uint Seed + byte[20] SHA1 + uint Addr + byte Len (scans only pages starts with MZ+PE headers for specified hash) + MPQ_CHECK = 0x98, // 152: byte fileNameIndex (check to ensure MPQ file isn't modified) + LUA_STR_CHECK = 0x8B, // 139: byte luaNameIndex (check to ensure LUA string isn't used) + DRIVER_CHECK = 0x71, // 113: uint Seed + byte[20] SHA1 + byte driverNameIndex (check to ensure driver isn't loaded) + TIMING_CHECK = 0x57, // 87: empty (check to ensure GetTickCount() isn't detoured) + PROC_CHECK = 0x7E, // 126: uint Seed + byte[20] SHA1 + byte moluleNameIndex + byte procNameIndex + uint Offset + byte Len (check to ensure proc isn't detoured) + MODULE_CHECK = 0xD9, // 217: uint Seed + byte[20] SHA1 (check to ensure module isn't injected) +}; + +#if defined(__GNUC__) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +struct WardenModuleUse +{ + uint8 Command; + uint8 ModuleId[16]; + uint8 ModuleKey[16]; + uint32 Size; +}; + +struct WardenModuleTransfer +{ + uint8 Command; + uint16 DataSize; + uint8 Data[500]; +}; + +struct WardenHashRequest +{ + uint8 Command; + uint8 Seed[16]; +}; + +#if defined(__GNUC__) +#pragma pack() +#else +#pragma pack(pop) +#endif + +struct ClientWardenModule +{ + uint8 Id[16]; + uint8 Key[16]; + uint32 CompressedSize; + uint8* CompressedData; +}; + +class WorldSession; + +class Warden +{ + friend class WardenWin; + friend class WardenMac; + + public: + Warden(); + ~Warden(); + + virtual void Init(WorldSession* session, BigNumber* k) = 0; + virtual ClientWardenModule* GetModuleForClient() = 0; + virtual void InitializeModule() = 0; + virtual void RequestHash() = 0; + virtual void HandleHashResult(ByteBuffer &buff) = 0; + virtual void RequestData() = 0; + virtual void HandleData(ByteBuffer &buff) = 0; + + void SendModuleToClient(); + void RequestModule(); + void Update(); + void DecryptData(uint8* buffer, uint32 length); + void EncryptData(uint8* buffer, uint32 length); + + static bool IsValidCheckSum(uint32 checksum, const uint8 *data, const uint16 length); + static uint32 BuildChecksum(const uint8 *data, uint32 length); + + // If no check is passed, the default action from config is executed + std::string Penalty(WardenCheck* check = NULL); + + private: + WorldSession* _session; + uint8 _inputKey[16]; + uint8 _outputKey[16]; + uint8 _seed[16]; + ARC4 _inputCrypto; + ARC4 _outputCrypto; + uint32 _checkTimer; // Timer for sending check requests + uint32 _clientResponseTimer; // Timer for client response delay + bool _dataSent; + uint32 _previousTimestamp; + ClientWardenModule* _module; + bool _initialized; +}; + +#endif diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp new file mode 100644 index 00000000000..77332bd30a8 --- /dev/null +++ b/src/server/game/Warden/WardenCheckMgr.cpp @@ -0,0 +1,196 @@ +/* + * 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 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 "Log.h" +#include "Database/DatabaseEnv.h" +#include "Util.h" +#include "WardenCheckMgr.h" +#include "Warden.h" + + +WardenCheckMgr::WardenCheckMgr() +{ + InternalDataID = 1; +} + +WardenCheckMgr::~WardenCheckMgr() +{ + for (uint16 i = 0; i < CheckStore.size(); ++i) + delete CheckStore[i]; + + for (CheckResultContainer::iterator itr = CheckResultStore.begin(); itr != CheckResultStore.end(); ++itr) + delete itr->second; +} + +void WardenCheckMgr::LoadWardenChecks() +{ + // Check if Warden is enabled by config before loading anything + if (!sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED)) + { + sLog->outString(">> Warden disabled, loading checks skipped."); + sLog->outString(); + return; + } + + // For reload case + for (uint16 i = 0; i < CheckStore.size(); ++i) + delete CheckStore[i]; + + CheckStore.clear(); + + for (CheckResultContainer::iterator itr = CheckResultStore.begin(); itr != CheckResultStore.end(); ++itr) + delete itr->second; + CheckResultStore.clear(); + + + QueryResult result = WorldDatabase.Query("SELECT MAX(id) FROM warden_checks"); + + if (!result) + { + sLog->outString(">> Loaded 0 Warden checks. DB table `warden_checks` is empty!"); + sLog->outString(); + return; + } + + Field* fields = result->Fetch(); + + uint32 maxCheckId = fields[0].GetUInt32(); + + CheckStore.resize(maxCheckId + 1); + + // 0 1 2 3 4 5 6 + result = WorldDatabase.Query("SELECT id, type, data, result, address, length, str FROM warden_checks ORDER BY id ASC"); + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + + uint16 id = fields[0].GetUInt16(); + uint8 checkType = fields[1].GetUInt8(); + std::string data = fields[2].GetString(); + std::string checkResult = fields[3].GetString(); + uint32 address = fields[4].GetUInt32(); + uint8 length = fields[5].GetUInt8(); + std::string str = fields[6].GetString(); + + WardenCheck* wardenCheck = new WardenCheck(); + wardenCheck->Type = checkType; + + // Initialize action with default action from config + wardenCheck->Action = WardenActions(sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_FAIL_ACTION)); + + if (checkType == PAGE_CHECK_A || checkType == PAGE_CHECK_B || checkType == DRIVER_CHECK) + { + wardenCheck->Data.SetHexStr(data.c_str()); + int len = data.size() / 2; + + if (wardenCheck->Data.GetNumBytes() < len) + { + uint8 temp[24]; + memset(temp, 0, len); + memcpy(temp, wardenCheck->Data.AsByteArray(), wardenCheck->Data.GetNumBytes()); + std::reverse(temp, temp + len); + wardenCheck->Data.SetBinary((uint8*)temp, len); + } + } + + if (checkType == MEM_CHECK || checkType == MODULE_CHECK) + MemChecksIdPool.push_back(id); + else + OtherChecksIdPool.push_back(id); + + if (checkType == MEM_CHECK || checkType == PAGE_CHECK_A || checkType == PAGE_CHECK_B || checkType == PROC_CHECK) + { + wardenCheck->Address = address; + wardenCheck->Length = length; + } + + // PROC_CHECK support missing + if (checkType == MEM_CHECK || checkType == MPQ_CHECK || checkType == LUA_STR_CHECK || checkType == DRIVER_CHECK || checkType == MODULE_CHECK) + wardenCheck->Str = str; + + CheckStore[id] = wardenCheck; + + if (checkType == MPQ_CHECK || checkType == MEM_CHECK) + { + WardenCheckResult *wr = new WardenCheckResult(); + wr->Result.SetHexStr(checkResult.c_str()); + int len = checkResult.size() / 2; + if (wr->Result.GetNumBytes() < len) + { + uint8 *temp = new uint8[len]; + memset(temp, 0, len); + memcpy(temp, wr->Result.AsByteArray(), wr->Result.GetNumBytes()); + std::reverse(temp, temp + len); + wr->Result.SetBinary((uint8*)temp, len); + delete [] temp; + } + CheckResultStore[id] = wr; + } + + ++count; + } + while (result->NextRow()); + + // Fetch overrides from char db and overwrite default action in CheckStore + QueryResult overrideResult = CharacterDatabase.Query("SELECT wardenId, action FROM warden_action"); + + uint32 overrideCount = 0; + + if(overrideResult) + { + do + { + Field * fields = overrideResult->Fetch(); + + uint16 checkId = fields[0].GetUInt16(); + + // Check if override check ID actually exists in current Warden checks + if (checkId > maxCheckId) + sLog->outError("Warden check action override for invalid check (ID: %u, action: %u), skipped", checkId, fields[1].GetUInt8()); + else + CheckStore[fields[0].GetUInt16()]->Action = WardenActions(fields[1].GetUInt8()); + + ++overrideCount; + } + while (overrideResult->NextRow()); + } + + sLog->outString(">> Loaded %u warden checks and %u action overrides.", count, overrideCount); + sLog->outString(); +} + +WardenCheck* WardenCheckMgr::GetWardenDataById(uint16 Id) +{ + if (Id < CheckStore.size()) + return CheckStore[Id]; + + return NULL; +} + +WardenCheckResult* WardenCheckMgr::GetWardenResultById(uint16 Id) +{ + CheckResultContainer::const_iterator itr = CheckResultStore.find(Id); + if (itr != CheckResultStore.end()) + return itr->second; + return NULL; +} diff --git a/src/server/game/Warden/WardenCheckMgr.h b/src/server/game/Warden/WardenCheckMgr.h new file mode 100644 index 00000000000..cbe8460db3b --- /dev/null +++ b/src/server/game/Warden/WardenCheckMgr.h @@ -0,0 +1,74 @@ +/* + * 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 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 _WARDENCHECKMGR_H +#define _WARDENCHECKMGR_H + +#include <map> +#include "Cryptography/BigNumber.h" + +enum WardenActions +{ + WARDEN_ACTION_LOG, + WARDEN_ACTION_KICK, + WARDEN_ACTION_BAN +}; + +struct WardenCheck +{ + uint8 Type; + BigNumber Data; + uint32 Address; // PROC_CHECK, MEM_CHECK, PAGE_CHECK + uint8 Length; // PROC_CHECK, MEM_CHECK, PAGE_CHECK + std::string Str; // LUA, MPQ, DRIVER + enum WardenActions Action; +}; + +struct WardenCheckResult +{ + BigNumber Result; // MEM_CHECK +}; + +class WardenCheckMgr +{ + friend class ACE_Singleton<WardenCheckMgr, ACE_Null_Mutex>; + WardenCheckMgr(); + ~WardenCheckMgr(); + + public: + // We have a linear key without any gaps, so we use vector for fast access + typedef std::vector<WardenCheck*> CheckContainer; + typedef std::map<uint32, WardenCheckResult*> CheckResultContainer; + + WardenCheck* GetWardenDataById(uint16 Id); + WardenCheckResult* GetWardenResultById(uint16 Id); + + uint32 InternalDataID; + std::vector<uint16> MemChecksIdPool; + std::vector<uint16> OtherChecksIdPool; + + void LoadWardenChecks(); + + private: + CheckContainer CheckStore; + CheckResultContainer CheckResultStore; +}; + +#define sWardenCheckMgr ACE_Singleton<WardenCheckMgr, ACE_Null_Mutex>::instance() + +#endif diff --git a/src/server/game/Warden/WardenMac.cpp b/src/server/game/Warden/WardenMac.cpp new file mode 100644 index 00000000000..f62aa11a339 --- /dev/null +++ b/src/server/game/Warden/WardenMac.cpp @@ -0,0 +1,260 @@ +/* + * 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 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 "Cryptography/WardenKeyGeneration.h" +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Log.h" +#include "Opcodes.h" +#include "ByteBuffer.h" +#include <openssl/md5.h> +#include "World.h" +#include "Player.h" +#include "Util.h" +#include "WardenMac.h" +#include "WardenModuleMac.h" + +WardenMac::WardenMac() : Warden() +{ +} + +WardenMac::~WardenMac() +{ +} + +void WardenMac::Init(WorldSession *pClient, BigNumber *K) +{ + _session = pClient; + // Generate Warden Key + SHA1Randx WK(K->AsByteArray(), K->GetNumBytes()); + WK.generate(_inputKey, 16); + WK.generate(_outputKey, 16); + /* + Seed: 4D808D2C77D905C41A6380EC08586AFE (0x05 packet) + Hash: <?> (0x04 packet) + Module MD5: 0DBBF209A27B1E279A9FEC5C168A15F7 + New Client Key: <?> + New Cerver Key: <?> + */ + uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE }; + + memcpy(_seed, mod_seed, 16); + + _inputCrypto.Init(_inputKey); + _outputCrypto.Init(_outputKey); + sLog->outDebug(LOG_FILTER_WARDEN, "Server side warden for client %u initializing...", pClient->GetAccountId()); + sLog->outDebug(LOG_FILTER_WARDEN, "C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str()); + sLog->outDebug(LOG_FILTER_WARDEN, "S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str()); + sLog->outDebug(LOG_FILTER_WARDEN, " Seed: %s", ByteArrayToHexStr(_seed, 16).c_str()); + sLog->outDebug(LOG_FILTER_WARDEN, "Loading Module..."); + + _module = GetModuleForClient(); + + sLog->outDebug(LOG_FILTER_WARDEN, "Module Key: %s", ByteArrayToHexStr(_module->Key, 16).c_str()); + sLog->outDebug(LOG_FILTER_WARDEN, "Module ID: %s", ByteArrayToHexStr(_module->Id, 16).c_str()); + RequestModule(); +} + +ClientWardenModule* WardenMac::GetModuleForClient() +{ + ClientWardenModule *mod = new ClientWardenModule; + + uint32 len = sizeof(Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data); + + // data assign + mod->CompressedSize = len; + mod->CompressedData = new uint8[len]; + memcpy(mod->CompressedData, Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data, len); + memcpy(mod->Key, Module_0DBBF209A27B1E279A9FEC5C168A15F7_Key, 16); + + // md5 hash + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, mod->CompressedData, len); + MD5_Final((uint8*)&mod->Id, &ctx); + + return mod; +} + +void WardenMac::InitializeModule() +{ + sLog->outDebug(LOG_FILTER_WARDEN, "Initialize module"); +} + +void WardenMac::RequestHash() +{ + sLog->outDebug(LOG_FILTER_WARDEN, "Request hash"); + + // Create packet structure + WardenHashRequest Request; + Request.Command = WARDEN_SMSG_HASH_REQUEST; + memcpy(Request.Seed, _seed, 16); + + // Encrypt with warden RC4 key. + EncryptData((uint8*)&Request, sizeof(WardenHashRequest)); + + WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenHashRequest)); + pkt.append((uint8*)&Request, sizeof(WardenHashRequest)); + _session->SendPacket(&pkt); +} + +void WardenMac::HandleHashResult(ByteBuffer &buff) +{ + + // test + int keyIn[4]; + + uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE }; + + for(int i = 0; i < 4; ++i) + { + keyIn[i] = *(int*)(&mod_seed[0] + i * 4); + } + + int keyOut[4]; + int keyIn1, keyIn2; + keyOut[0] = keyIn[0]; + keyIn[0] ^= 0xDEADBEEFu; + keyIn1 = keyIn[1]; + keyIn[1] -= 0x35014542u; + keyIn2 = keyIn[2]; + keyIn[2] += 0x5313F22u; + keyIn[3] *= 0x1337F00Du; + keyOut[1] = keyIn1 - 0x6A028A84; + keyOut[2] = keyIn2 + 0xA627E44; + keyOut[3] = 0x1337F00D * keyIn[3]; + // end test + + buff.rpos(buff.wpos()); + + SHA1Hash sha1; + sha1.UpdateData((uint8*)keyIn, 16); + sha1.Finalize(); + + //const uint8 validHash[20] = { 0x56, 0x8C, 0x05, 0x4C, 0x78, 0x1A, 0x97, 0x2A, 0x60, 0x37, 0xA2, 0x29, 0x0C, 0x22, 0xB5, 0x25, 0x71, 0xA0, 0x6F, 0x4E }; + + // Verify key + if (memcmp(buff.contents() + 1, sha1.GetDigest(), 20) != 0) + { + sLog->outDebug(LOG_FILTER_WARDEN, "Request hash reply: failed"); + sLog->outWarden("WARDEN: Player %s (guid: %u, account: %u) failed hash reply. Action: %s", + _session->GetPlayerName(), _session->GetGuidLow(), _session->GetAccountId(), Penalty().c_str()); + return; + } + + sLog->outDebug(LOG_FILTER_WARDEN, "Request hash reply: succeed"); + + // client 7F96EEFDA5B63D20A4DF8E00CBF48304 + //const uint8 client_key[16] = { 0x7F, 0x96, 0xEE, 0xFD, 0xA5, 0xB6, 0x3D, 0x20, 0xA4, 0xDF, 0x8E, 0x00, 0xCB, 0xF4, 0x83, 0x04 }; + + // server C2B7ADEDFCCCA9C2BFB3F85602BA809B + //const uint8 server_key[16] = { 0xC2, 0xB7, 0xAD, 0xED, 0xFC, 0xCC, 0xA9, 0xC2, 0xBF, 0xB3, 0xF8, 0x56, 0x02, 0xBA, 0x80, 0x9B }; + + // change keys here + memcpy(_inputKey, keyIn, 16); + memcpy(_outputKey, keyOut, 16); + + _inputCrypto.Init(_inputKey); + _outputCrypto.Init(_outputKey); + + _initialized = true; + + _previousTimestamp = getMSTime(); +} + +void WardenMac::RequestData() +{ + sLog->outDebug(LOG_FILTER_WARDEN, "Request data"); + + ByteBuffer buff; + buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); + + std::string str = "Test string!"; + + buff << uint8(str.size()); + buff.append(str.c_str(), str.size()); + + buff.hexlike(); + + // Encrypt with warden RC4 key. + EncryptData(const_cast<uint8*>(buff.contents()), buff.size()); + + WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); + pkt.append(buff); + _session->SendPacket(&pkt); + + _dataSent = true; +} + +void WardenMac::HandleData(ByteBuffer &buff) +{ + sLog->outDebug(LOG_FILTER_WARDEN, "Handle data"); + + _dataSent = false; + _clientResponseTimer = 0; + + //uint16 Length; + //buff >> Length; + //uint32 Checksum; + //buff >> Checksum; + + //if (!IsValidCheckSum(Checksum, buff.contents() + buff.rpos(), Length)) + //{ + // buff.rpos(buff.wpos()); + // if (sWorld->getBoolConfig(CONFIG_BOOL_WARDEN_KICK)) + // Client->KickPlayer(); + // return; + //} + + bool found = false; + + std::string str = "Test string!"; + + SHA1Hash sha1; + sha1.UpdateData(str); + uint32 magic = 0xFEEDFACE; // unsure + sha1.UpdateData((uint8*)&magic, 4); + sha1.Finalize(); + + uint8 sha1Hash[20]; + buff.read(sha1Hash, 20); + + if (memcmp(sha1Hash, sha1.GetDigest(), 20)) + { + sLog->outDebug(LOG_FILTER_WARDEN, "Handle data failed: SHA1 hash is wrong!"); + found = true; + } + + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, str.c_str(), str.size()); + uint8 ourMD5Hash[16]; + MD5_Final(ourMD5Hash, &ctx); + + uint8 theirsMD5Hash[16]; + buff.read(theirsMD5Hash, 16); + + if (memcmp(ourMD5Hash, theirsMD5Hash, 16)) + { + sLog->outDebug(LOG_FILTER_WARDEN, "Handle data failed: MD5 hash is wrong!"); + found = true; + } + + _session->KickPlayer(); +} diff --git a/src/server/game/Warden/WardenMac.h b/src/server/game/Warden/WardenMac.h new file mode 100644 index 00000000000..b2ecc72367d --- /dev/null +++ b/src/server/game/Warden/WardenMac.h @@ -0,0 +1,46 @@ +/* + * 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 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 _WARDEN_MAC_H +#define _WARDEN_MAC_H + +#include "Cryptography/ARC4.h" +#include <map> +#include "Cryptography/BigNumber.h" +#include "ByteBuffer.h" +#include "Warden.h" + +class WorldSession; +class Warden; + +class WardenMac : public Warden +{ + public: + WardenMac(); + ~WardenMac(); + + void Init(WorldSession* session, BigNumber* k); + ClientWardenModule* GetModuleForClient(); + void InitializeModule(); + void RequestHash(); + void HandleHashResult(ByteBuffer& buff); + void RequestData(); + void HandleData(ByteBuffer& buff); +}; + +#endif diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp new file mode 100644 index 00000000000..a77c77a3261 --- /dev/null +++ b/src/server/game/Warden/WardenWin.cpp @@ -0,0 +1,523 @@ +/* + * 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 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 "Cryptography/HMACSHA1.h" +#include "Cryptography/WardenKeyGeneration.h" +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Log.h" +#include "Opcodes.h" +#include "ByteBuffer.h" +#include <openssl/md5.h> +#include "Database/DatabaseEnv.h" +#include "World.h" +#include "Player.h" +#include "Util.h" +#include "WardenWin.h" +#include "WardenModuleWin.h" +#include "WardenCheckMgr.h" +#include "AccountMgr.h" + +WardenWin::WardenWin() : Warden() +{ +} + +WardenWin::~WardenWin() +{ +} + +void WardenWin::Init(WorldSession* session, BigNumber *k) +{ + _session = session; + // Generate Warden Key + SHA1Randx WK(k->AsByteArray(), k->GetNumBytes()); + WK.generate(_inputKey, 16); + WK.generate(_outputKey, 16); + /* + Seed: 4D808D2C77D905C41A6380EC08586AFE (0x05 packet) + Hash: 568C054C781A972A6037A2290C22B52571A06F4E (0x04 packet) + Module MD5: 79C0768D657977D697E10BAD956CCED1 + New Client Key: 7F 96 EE FD A5 B6 3D 20 A4 DF 8E 00 CB F4 83 04 + New Cerver Key: C2 B7 AD ED FC CC A9 C2 BF B3 F8 56 02 BA 80 9B + */ + uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE }; + + memcpy(_seed, mod_seed, 16); + + _inputCrypto.Init(_inputKey); + _outputCrypto.Init(_outputKey); + sLog->outDebug(LOG_FILTER_WARDEN, "Server side warden for client %u initializing...", session->GetAccountId()); + sLog->outDebug(LOG_FILTER_WARDEN, "C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str()); + sLog->outDebug(LOG_FILTER_WARDEN, "S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str()); + sLog->outDebug(LOG_FILTER_WARDEN, " Seed: %s", ByteArrayToHexStr(_seed, 16).c_str()); + sLog->outDebug(LOG_FILTER_WARDEN, "Loading Module..."); + + _module = GetModuleForClient(); + + sLog->outDebug(LOG_FILTER_WARDEN, "Module Key: %s", ByteArrayToHexStr(_module->Key, 16).c_str()); + sLog->outDebug(LOG_FILTER_WARDEN, "Module ID: %s", ByteArrayToHexStr(_module->Id, 16).c_str()); + RequestModule(); +} + +ClientWardenModule* WardenWin::GetModuleForClient() +{ + ClientWardenModule *mod = new ClientWardenModule; + + uint32 length = sizeof(Module_79C0768D657977D697E10BAD956CCED1_Data); + + // data assign + mod->CompressedSize = length; + mod->CompressedData = new uint8[length]; + memcpy(mod->CompressedData, Module_79C0768D657977D697E10BAD956CCED1_Data, length); + memcpy(mod->Key, Module_79C0768D657977D697E10BAD956CCED1_Key, 16); + + // md5 hash + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, mod->CompressedData, length); + MD5_Final((uint8*)&mod->Id, &ctx); + + return mod; +} + +void WardenWin::InitializeModule() +{ + sLog->outDebug(LOG_FILTER_WARDEN, "Initialize module"); + + // Create packet structure + WardenInitModuleRequest Request; + Request.Command1 = WARDEN_SMSG_MODULE_INITIALIZE; + Request.Size1 = 20; + Request.CheckSumm1 = BuildChecksum(&Request.Unk1, 20); + Request.Unk1 = 1; + Request.Unk2 = 0; + Request.Type = 1; + Request.String_library1 = 0; + Request.Function1[0] = 0x00024F80; // 0x00400000 + 0x00024F80 SFileOpenFile + Request.Function1[1] = 0x000218C0; // 0x00400000 + 0x000218C0 SFileGetFileSize + Request.Function1[2] = 0x00022530; // 0x00400000 + 0x00022530 SFileReadFile + Request.Function1[3] = 0x00022910; // 0x00400000 + 0x00022910 SFileCloseFile + + Request.Command2 = WARDEN_SMSG_MODULE_INITIALIZE; + Request.Size2 = 8; + Request.CheckSumm2 = BuildChecksum(&Request.Unk2, 8); + Request.Unk3 = 4; + Request.Unk4 = 0; + Request.String_library2 = 0; + Request.Function2 = 0x00419D40; // 0x00400000 + 0x00419D40 FrameScript::GetText + Request.Function2_set = 1; + + Request.Command3 = WARDEN_SMSG_MODULE_INITIALIZE; + Request.Size3 = 8; + Request.CheckSumm3 = BuildChecksum(&Request.Unk5, 8); + Request.Unk5 = 1; + Request.Unk6 = 1; + Request.String_library3 = 0; + Request.Function3 = 0x0046AE20; // 0x00400000 + 0x0046AE20 PerformanceCounter + Request.Function3_set = 1; + + // Encrypt with warden RC4 key. + EncryptData((uint8*)&Request, sizeof(WardenInitModuleRequest)); + + WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenInitModuleRequest)); + pkt.append((uint8*)&Request, sizeof(WardenInitModuleRequest)); + _session->SendPacket(&pkt); +} + +void WardenWin::RequestHash() +{ + sLog->outDebug(LOG_FILTER_WARDEN, "Request hash"); + + // Create packet structure + WardenHashRequest Request; + Request.Command = WARDEN_SMSG_HASH_REQUEST; + memcpy(Request.Seed, _seed, 16); + + // Encrypt with warden RC4 key. + EncryptData((uint8*)&Request, sizeof(WardenHashRequest)); + + WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenHashRequest)); + pkt.append((uint8*)&Request, sizeof(WardenHashRequest)); + _session->SendPacket(&pkt); +} + +void WardenWin::HandleHashResult(ByteBuffer &buff) +{ + buff.rpos(buff.wpos()); + + const uint8 validHash[20] = { 0x56, 0x8C, 0x05, 0x4C, 0x78, 0x1A, 0x97, 0x2A, 0x60, 0x37, 0xA2, 0x29, 0x0C, 0x22, 0xB5, 0x25, 0x71, 0xA0, 0x6F, 0x4E }; + + // Verify key + if (memcmp(buff.contents() + 1, validHash, sizeof(validHash)) != 0) + { + sLog->outDebug(LOG_FILTER_WARDEN, "Request hash reply: failed"); + sLog->outWarden("WARDEN: Player %s (guid: %u, account: %u) failed hash reply. Action: %s", + _session->GetPlayerName(), _session->GetGuidLow(), _session->GetAccountId(), Penalty().c_str()); + return; + } + + sLog->outDebug(LOG_FILTER_WARDEN, "Request hash reply: succeed"); + + // Client 7F96EEFDA5B63D20A4DF8E00CBF48304 + const uint8 client_key[16] = { 0x7F, 0x96, 0xEE, 0xFD, 0xA5, 0xB6, 0x3D, 0x20, 0xA4, 0xDF, 0x8E, 0x00, 0xCB, 0xF4, 0x83, 0x04 }; + + // Server C2B7ADEDFCCCA9C2BFB3F85602BA809B + const uint8 server_key[16] = { 0xC2, 0xB7, 0xAD, 0xED, 0xFC, 0xCC, 0xA9, 0xC2, 0xBF, 0xB3, 0xF8, 0x56, 0x02, 0xBA, 0x80, 0x9B }; + + // Change keys here + memcpy(_inputKey, client_key, 16); + memcpy(_outputKey, server_key, 16); + + _inputCrypto.Init(_inputKey); + _outputCrypto.Init(_outputKey); + + _initialized = true; + + _previousTimestamp = getMSTime(); +} + +void WardenWin::RequestData() +{ + sLog->outDebug(LOG_FILTER_WARDEN, "Request data"); + + // If all checks were done, fill the todo list again + if (_memChecksTodo.empty()) + _memChecksTodo.assign(sWardenCheckMgr->MemChecksIdPool.begin(), sWardenCheckMgr->MemChecksIdPool.end()); + + if (_otherChecksTodo.empty()) + _otherChecksTodo.assign(sWardenCheckMgr->OtherChecksIdPool.begin(), sWardenCheckMgr->OtherChecksIdPool.end()); + + _serverTicks = getMSTime(); + + uint16 id; + uint8 type; + WardenCheck* wd; + _currentChecks.clear(); + + // Build check request + for (uint32 i = 0; i < sWorld->getIntConfig(CONFIG_WARDEN_NUM_MEM_CHECKS); ++i) + { + // If todo list is done break loop (will be filled on next Update() run) + if (_memChecksTodo.empty()) + break; + + // Get check id from the end and remove it from todo + id = _memChecksTodo.back(); + _memChecksTodo.pop_back(); + + // Add the id to the list sent in this cycle + _currentChecks.push_back(id); + } + + ByteBuffer buff; + buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); + + for (uint32 i = 0; i < sWorld->getIntConfig(CONFIG_WARDEN_NUM_OTHER_CHECKS); ++i) + { + // If todo list is done break loop (will be filled on next Update() run) + if (_otherChecksTodo.empty()) + break; + + // Get check id from the end and remove it from todo + id = _otherChecksTodo.back(); + _otherChecksTodo.pop_back(); + + // Add the id to the list sent in this cycle + _currentChecks.push_back(id); + + wd = sWardenCheckMgr->GetWardenDataById(id); + + switch (wd->Type) + { + case MPQ_CHECK: + case LUA_STR_CHECK: + case DRIVER_CHECK: + buff << uint8(wd->Str.size()); + buff.append(wd->Str.c_str(), wd->Str.size()); + break; + default: + break; + } + } + + uint8 xorByte = _inputKey[0]; + + // Add TIMING_CHECK + buff << uint8(0x00); + buff << uint8(TIMING_CHECK ^ xorByte); + + uint8 index = 1; + + for (std::list<uint16>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) + { + wd = sWardenCheckMgr->GetWardenDataById(*itr); + + type = wd->Type; + buff << uint8(type ^ xorByte); + switch (type) + { + case MEM_CHECK: + { + buff << uint8(0x00); + buff << uint32(wd->Address); + buff << uint8(wd->Length); + break; + } + case PAGE_CHECK_A: + case PAGE_CHECK_B: + { + buff.append(wd->Data.AsByteArray(0, false), wd->Data.GetNumBytes()); + buff << uint32(wd->Address); + buff << uint8(wd->Length); + break; + } + case MPQ_CHECK: + case LUA_STR_CHECK: + { + buff << uint8(index++); + break; + } + case DRIVER_CHECK: + { + buff.append(wd->Data.AsByteArray(0, false), wd->Data.GetNumBytes()); + buff << uint8(index++); + break; + } + case MODULE_CHECK: + { + uint32 seed = static_cast<uint32>(rand32()); + buff << uint32(seed); + HmacHash hmac(4, (uint8*)&seed); + hmac.UpdateData(wd->Str); + hmac.Finalize(); + buff.append(hmac.GetDigest(), hmac.GetLength()); + break; + } + /*case PROC_CHECK: + { + buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); + buff << uint8(index++); + buff << uint8(index++); + buff << uint32(wd->Address); + buff << uint8(wd->Length); + break; + }*/ + default: + break; // Should never happen + } + } + buff << uint8(xorByte); + buff.hexlike(); + + // Encrypt with warden RC4 key + EncryptData(const_cast<uint8*>(buff.contents()), buff.size()); + + WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); + pkt.append(buff); + _session->SendPacket(&pkt); + + _dataSent = true; + + std::stringstream stream; + stream << "Sent check id's: "; + for (std::list<uint16>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) + stream << *itr << " "; + + sLog->outWarden("%s", stream.str().c_str()); +} + +void WardenWin::HandleData(ByteBuffer &buff) +{ + sLog->outDebug(LOG_FILTER_WARDEN, "Handle data"); + + _dataSent = false; + _clientResponseTimer = 0; + + uint16 Length; + buff >> Length; + uint32 Checksum; + buff >> Checksum; + + if (!IsValidCheckSum(Checksum, buff.contents() + buff.rpos(), Length)) + { + buff.rpos(buff.wpos()); + sLog->outDebug(LOG_FILTER_WARDEN, "CHECKSUM FAIL"); + sLog->outWarden("WARDEN: Player %s (guid: %u, account: %u) failed checksum. Action: %s", + _session->GetPlayerName(), _session->GetGuidLow(), _session->GetAccountId(), Penalty().c_str()); + return; + } + + // TIMING_CHECK + { + uint8 result; + buff >> result; + // TODO: test it. + if (result == 0x00) + { + sLog->outDebug(LOG_FILTER_WARDEN, "TIMING CHECK FAIL result 0x00"); + sLog->outWarden("WARDEN: Player %s (guid: %u, account: %u) failed timing check. Action: %s", + _session->GetPlayerName(), _session->GetGuidLow(), _session->GetAccountId(), Penalty().c_str()); + return; + } + + uint32 newClientTicks; + buff >> newClientTicks; + + uint32 ticksNow = getMSTime(); + uint32 ourTicks = newClientTicks + (ticksNow - _serverTicks); + + sLog->outDebug(LOG_FILTER_WARDEN, "ServerTicks %u", ticksNow); // Now + sLog->outDebug(LOG_FILTER_WARDEN, "RequestTicks %u", _serverTicks); // At request + sLog->outDebug(LOG_FILTER_WARDEN, "Ticks %u", newClientTicks); // At response + sLog->outDebug(LOG_FILTER_WARDEN, "Ticks diff %u", ourTicks - newClientTicks); + } + + WardenCheckResult *rs; + WardenCheck *rd; + uint8 type; + uint16 checkFailed = 0; + + for (std::list<uint16>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) + { + rd = sWardenCheckMgr->GetWardenDataById(*itr); + rs = sWardenCheckMgr->GetWardenResultById(*itr); + + type = rd->Type; + switch (type) + { + case MEM_CHECK: + { + uint8 Mem_Result; + buff >> Mem_Result; + + if (Mem_Result != 0) + { + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT MEM_CHECK not 0x00, CheckId %u account Id %u", *itr, _session->GetAccountId()); + checkFailed = *itr; + continue; + } + + if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false), rd->Length) != 0) + { + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT MEM_CHECK fail CheckId %u account Id %u", *itr, _session->GetAccountId()); + checkFailed = *itr; + buff.rpos(buff.rpos() + rd->Length); + continue; + } + + buff.rpos(buff.rpos() + rd->Length); + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT MEM_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); + break; + } + case PAGE_CHECK_A: + case PAGE_CHECK_B: + case DRIVER_CHECK: + case MODULE_CHECK: + { + const uint8 byte = 0xE9; + if (memcmp(buff.contents() + buff.rpos(), &byte, sizeof(uint8)) != 0) + { + if (type == PAGE_CHECK_A || type == PAGE_CHECK_B) + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT PAGE_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); + if (type == MODULE_CHECK) + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT MODULE_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); + if (type == DRIVER_CHECK) + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT DRIVER_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); + checkFailed = *itr; + buff.rpos(buff.rpos() + 1); + continue; + } + + buff.rpos(buff.rpos() + 1); + if (type == PAGE_CHECK_A || type == PAGE_CHECK_B) + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT PAGE_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); + else if (type == MODULE_CHECK) + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT MODULE_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); + else if (type == DRIVER_CHECK) + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT DRIVER_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); + break; + } + case LUA_STR_CHECK: + { + uint8 Lua_Result; + buff >> Lua_Result; + + if (Lua_Result != 0) + { + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT LUA_STR_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); + checkFailed = *itr; + continue; + } + + uint8 luaStrLen; + buff >> luaStrLen; + + if (luaStrLen != 0) + { + char *str = new char[luaStrLen + 1]; + memset(str, 0, luaStrLen + 1); + memcpy(str, buff.contents() + buff.rpos(), luaStrLen); + sLog->outDebug(LOG_FILTER_WARDEN, "Lua string: %s", str); + delete[] str; + } + buff.rpos(buff.rpos() + luaStrLen); // Skip string + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT LUA_STR_CHECK passed, CheckId %u account Id %u", *itr, _session->GetAccountId()); + break; + } + case MPQ_CHECK: + { + uint8 Mpq_Result; + buff >> Mpq_Result; + + if (Mpq_Result != 0) + { + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT MPQ_CHECK not 0x00 account id %u", _session->GetAccountId()); + checkFailed = *itr; + continue; + } + + if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false), 20) != 0) // SHA1 + { + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT MPQ_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); + checkFailed = *itr; + buff.rpos(buff.rpos() + 20); // 20 bytes SHA1 + continue; + } + + buff.rpos(buff.rpos() + 20); // 20 bytes SHA1 + sLog->outDebug(LOG_FILTER_WARDEN, "RESULT MPQ_CHECK passed, CheckId %u account Id %u", *itr, _session->GetAccountId()); + break; + } + default: // Should never happen + break; + } + } + + if (checkFailed > 0) + { + WardenCheck* check = sWardenCheckMgr->GetWardenDataById(checkFailed); + + sLog->outWarden("WARDEN: Player %s (guid: %u, account: %u) failed Warden check %u. Action: %s", + _session->GetPlayerName(), _session->GetGuidLow(), _session->GetAccountId(), checkFailed, Penalty(check).c_str()); + } + + // Set hold off timer, minimum timer should at least be 1 second + uint32 holdOff = sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF); + _checkTimer = (holdOff < 1 ? 1 : holdOff) * IN_MILLISECONDS; +} diff --git a/src/server/game/Warden/WardenWin.h b/src/server/game/Warden/WardenWin.h new file mode 100644 index 00000000000..4d859f2b22a --- /dev/null +++ b/src/server/game/Warden/WardenWin.h @@ -0,0 +1,94 @@ +/* + * 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 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 _WARDEN_WIN_H +#define _WARDEN_WIN_H + +#include <map> +#include "Cryptography/ARC4.h" +#include "Cryptography/BigNumber.h" +#include "ByteBuffer.h" +#include "Warden.h" + +#if defined(__GNUC__) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +struct WardenInitModuleRequest +{ + uint8 Command1; + uint16 Size1; + uint32 CheckSumm1; + uint8 Unk1; + uint8 Unk2; + uint8 Type; + uint8 String_library1; + uint32 Function1[4]; + + uint8 Command2; + uint16 Size2; + uint32 CheckSumm2; + uint8 Unk3; + uint8 Unk4; + uint8 String_library2; + uint32 Function2; + uint8 Function2_set; + + uint8 Command3; + uint16 Size3; + uint32 CheckSumm3; + uint8 Unk5; + uint8 Unk6; + uint8 String_library3; + uint32 Function3; + uint8 Function3_set; +}; + +#if defined(__GNUC__) +#pragma pack() +#else +#pragma pack(pop) +#endif + +class WorldSession; +class Warden; + +class WardenWin : public Warden +{ + public: + WardenWin(); + ~WardenWin(); + + void Init(WorldSession* session, BigNumber* K); + ClientWardenModule* GetModuleForClient(); + void InitializeModule(); + void RequestHash(); + void HandleHashResult(ByteBuffer &buff); + void RequestData(); + void HandleData(ByteBuffer &buff); + + private: + uint32 _serverTicks; + std::list<uint16> _otherChecksTodo; + std::list<uint16> _memChecksTodo; + std::list<uint16> _currentChecks; +}; + +#endif diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index f492ff80fae..45b1c4dac64 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -75,6 +75,8 @@ #include "CreatureTextMgr.h" #include "SmartAI.h" #include "Channel.h" +#include "WardenCheckMgr.h" +#include "Warden.h" volatile bool World::m_stopEvent = false; uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE; @@ -970,6 +972,8 @@ void World::LoadConfigSettings(bool reload) if (m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > MAX_LEVEL) m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = MAX_LEVEL; m_bool_configs[CONFIG_QUEST_IGNORE_RAID] = ConfigMgr::GetBoolDefault("Quests.IgnoreRaid", false); + m_bool_configs[CONFIG_QUEST_IGNORE_AUTO_ACCEPT] = ConfigMgr::GetBoolDefault("Quests.IgnoreAutoAccept", false); + m_bool_configs[CONFIG_QUEST_IGNORE_AUTO_COMPLETE] = ConfigMgr::GetBoolDefault("Quests.IgnoreAutoComplete", false); m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] = ConfigMgr::GetIntDefault("Battleground.Random.ResetHour", 6); if (m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] > 23) @@ -1169,6 +1173,15 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_CHATLOG_ADDON] = ConfigMgr::GetBoolDefault("ChatLogs.Addon", false); m_bool_configs[CONFIG_CHATLOG_BGROUND] = ConfigMgr::GetBoolDefault("ChatLogs.Battleground", false); + // Warden + m_bool_configs[CONFIG_WARDEN_ENABLED] = ConfigMgr::GetBoolDefault("Warden.Enabled", false); + m_int_configs[CONFIG_WARDEN_NUM_MEM_CHECKS] = ConfigMgr::GetIntDefault("Warden.NumMemChecks", 3); + m_int_configs[CONFIG_WARDEN_NUM_OTHER_CHECKS] = ConfigMgr::GetIntDefault("Warden.NumOtherChecks", 7); + m_int_configs[CONFIG_WARDEN_CLIENT_BAN_DURATION] = ConfigMgr::GetIntDefault("Warden.BanDuration", 86400); + m_int_configs[CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF] = ConfigMgr::GetIntDefault("Warden.ClientCheckHoldOff", 30); + m_int_configs[CONFIG_WARDEN_CLIENT_FAIL_ACTION] = ConfigMgr::GetIntDefault("Warden.ClientCheckFailAction", 0); + m_int_configs[CONFIG_WARDEN_CLIENT_RESPONSE_DELAY] = ConfigMgr::GetIntDefault("Warden.ClientResponseDelay", 600); + // Dungeon finder m_bool_configs[CONFIG_DUNGEON_FINDER_ENABLE] = ConfigMgr::GetBoolDefault("DungeonFinder.Enable", false); @@ -1193,6 +1206,8 @@ void World::LoadConfigSettings(bool reload) sScriptMgr->OnConfigLoad(reload); } +extern void LoadGameObjectModelList(); + /// Initialize the World void World::SetInitialWorldSettings() { @@ -1267,6 +1282,9 @@ void World::SetInitialWorldSettings() sLog->outString("Loading spell custom attributes..."); sSpellMgr->LoadSpellCustomAttr(); + sLog->outString("Loading GameObject models..."); + LoadGameObjectModelList(); + sLog->outString("Loading Script Names..."); sObjectMgr->LoadScriptNames(); @@ -1575,6 +1593,9 @@ void World::SetInitialWorldSettings() sLog->outString("Loading Creature Formations..."); FormationMgr::LoadCreatureFormations(); + sLog->outString("Loading World States..."); // must be loaded before battleground, outdoor PvP and conditions + LoadWorldStates(); + sLog->outString("Loading Conditions..."); sConditionMgr->LoadConditions(); @@ -1702,9 +1723,6 @@ void World::SetInitialWorldSettings() sTicketMgr->Initialize(); - sLog->outString("Loading World States..."); // must be loaded before battleground and outdoor PvP - LoadWorldStates(); - ///- Initialize Battlegrounds sLog->outString("Starting Battleground System"); sBattlegroundMgr->CreateInitialBattlegrounds(); @@ -1720,6 +1738,10 @@ void World::SetInitialWorldSettings() sLog->outString("Loading Transport NPCs..."); sMapMgr->LoadTransportNPCs(); + ///- Initialize Warden + sLog->outString("Loading Warden Checks..." ); + sWardenCheckMgr->LoadWardenChecks(); + sLog->outString("Deleting expired bans..."); LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index b7ca40f694e..6304699e7e1 100755 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -168,6 +168,9 @@ enum WorldBoolConfigs CONFIG_PRESERVE_CUSTOM_CHANNELS, CONFIG_PDUMP_NO_PATHS, CONFIG_PDUMP_NO_OVERWRITE, + CONFIG_QUEST_IGNORE_AUTO_ACCEPT, + CONFIG_QUEST_IGNORE_AUTO_COMPLETE, + CONFIG_WARDEN_ENABLED, BOOL_CONFIG_VALUE_COUNT }; @@ -317,6 +320,12 @@ enum WorldIntConfigs CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION, CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS, CONFIG_MAX_INSTANCES_PER_HOUR, + CONFIG_WARDEN_CLIENT_RESPONSE_DELAY, + CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF, + CONFIG_WARDEN_CLIENT_FAIL_ACTION, + CONFIG_WARDEN_CLIENT_BAN_DURATION, + CONFIG_WARDEN_NUM_MEM_CHECKS, + CONFIG_WARDEN_NUM_OTHER_CHECKS, INT_CONFIG_VALUE_COUNT }; |
