diff options
Diffstat (limited to 'src')
93 files changed, 704 insertions, 377 deletions
diff --git a/src/server/collision/Maps/MapTree.h b/src/server/collision/Maps/MapTree.h index 90d61cbb88b..62fa3c97987 100644 --- a/src/server/collision/Maps/MapTree.h +++ b/src/server/collision/Maps/MapTree.h @@ -81,6 +81,10 @@ namespace VMAP bool isTiled() const { return iIsTiled; } uint32 numLoadedTiles() const { return iLoadedTiles.size(); } void getModelInstances(ModelInstance* &models, uint32 &count); + + private: + StaticMapTree(StaticMapTree const& right) DELETE_MEMBER; + StaticMapTree& operator=(StaticMapTree const& right) DELETE_MEMBER; }; struct AreaInfo diff --git a/src/server/collision/Models/WorldModel.h b/src/server/collision/Models/WorldModel.h index 8778998a6b7..da1f58a79c6 100644 --- a/src/server/collision/Models/WorldModel.h +++ b/src/server/collision/Models/WorldModel.h @@ -59,7 +59,7 @@ namespace VMAP bool writeToFile(FILE* wf); static bool readFromFile(FILE* rf, WmoLiquid* &liquid); private: - WmoLiquid(): iTilesX(0), iTilesY(0), iType(0), iHeight(0), iFlags(0) { } + WmoLiquid() : iTilesX(0), iTilesY(0), iCorner(), iType(0), iHeight(NULL), iFlags(NULL) { } uint32 iTilesX; //!< number of tiles in x direction, each uint32 iTilesY; G3D::Vector3 iCorner; //!< the lower corner @@ -74,10 +74,10 @@ namespace VMAP class GroupModel { public: - GroupModel(): iMogpFlags(0), iGroupWMOID(0), iLiquid(0) { } + GroupModel() : iBound(), iMogpFlags(0), iGroupWMOID(0), iLiquid(NULL) { } GroupModel(const GroupModel &other); GroupModel(uint32 mogpFlags, uint32 groupWMOID, const G3D::AABox &bound): - iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(0) { } + iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(NULL) { } ~GroupModel() { delete iLiquid; } //! pass mesh data to object and create BIH. Passed vectors get get swapped with old geometry! diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp index 943919451a9..27144728a3e 100644 --- a/src/server/game/AI/CoreAI/CombatAI.cpp +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -151,7 +151,7 @@ void CasterAI::UpdateAI(uint32 diff) events.Update(diff); - if (me->GetVictim()->HasBreakableByDamageCrowdControlAura(me)) + if (me->GetVictim() && me->EnsureVictim()->HasBreakableByDamageCrowdControlAura(me)) { me->InterruptNonMeleeSpells(false); return; diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index d6e749b942a..e2eeaf880ad 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -86,10 +86,10 @@ void PetAI::UpdateAI(uint32 diff) else m_updateAlliesTimer -= diff; - if (me->GetVictim() && me->GetVictim()->IsAlive()) + if (me->GetVictim() && me->EnsureVictim()->IsAlive()) { // is only necessary to stop casting, the pet must not exit combat - if (me->GetVictim()->HasBreakableByDamageCrowdControlAura(me)) + if (me->EnsureVictim()->HasBreakableByDamageCrowdControlAura(me)) { me->InterruptNonMeleeSpells(false); return; @@ -345,7 +345,7 @@ void PetAI::OwnerAttackedBy(Unit* attacker) return; // Prevent pet from disengaging from current target - if (me->GetVictim() && me->GetVictim()->IsAlive()) + if (me->GetVictim() && me->EnsureVictim()->IsAlive()) return; // Continue to evaluate and attack if necessary @@ -366,7 +366,7 @@ void PetAI::OwnerAttacked(Unit* target) return; // Prevent pet from disengaging from current target - if (me->GetVictim() && me->GetVictim()->IsAlive()) + if (me->GetVictim() && me->EnsureVictim()->IsAlive()) return; // Continue to evaluate and attack if necessary @@ -627,7 +627,7 @@ void PetAI::AttackedBy(Unit* attacker) return; // Prevent pet from disengaging from current target - if (me->GetVictim() && me->GetVictim()->IsAlive()) + if (me->GetVictim() && me->EnsureVictim()->IsAlive()) return; // Continue to evaluate and attack if necessary diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index 960d9f8903b..92e72dcfc53 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -262,6 +262,10 @@ class UnitAI virtual void sQuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) { } virtual bool sOnDummyEffect(Unit* /*caster*/, uint32 /*spellId*/, SpellEffIndex /*effIndex*/) { return false; } virtual void sOnGameEvent(bool /*start*/, uint16 /*eventId*/) { } + + private: + UnitAI(UnitAI const& right) DELETE_MEMBER; + UnitAI& operator=(UnitAI const& right) DELETE_MEMBER; }; class PlayerAI : public UnitAI diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index dcf5bd56fa6..43596ffb4cb 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -77,7 +77,7 @@ bool npc_escortAI::AssistPlayerInCombat(Unit* who) return false; //not a player - if (!who->GetVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) + if (!who->EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) return false; //never attack friendly diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp index 0fbfc2cebac..df6bee51642 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -74,7 +74,7 @@ bool FollowerAI::AssistPlayerInCombat(Unit* who) return false; //not a player - if (!who->GetVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) + if (!who->EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) return false; //never attack friendly diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 23dea877776..3b055cabbfa 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -499,7 +499,7 @@ bool SmartAI::AssistPlayerInCombat(Unit* who) return false; //not a player - if (!who->GetVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) + if (!who->EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) return false; //never attack friendly diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 231f3808aa9..92007a16569 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -38,25 +38,29 @@ #include "MoveSplineInit.h" #include "GameEventMgr.h" -class TrinityStringTextBuilder +class BroadcastTextBuilder { public: - TrinityStringTextBuilder(WorldObject* obj, ChatMsg msgtype, int32 id, uint32 language, WorldObject* target) - : _source(obj), _msgType(msgtype), _textId(id), _language(language), _target(target) + BroadcastTextBuilder(WorldObject const* obj, ChatMsg msgtype, uint32 id, WorldObject const* target, uint32 gender = GENDER_MALE) + : _source(obj), _msgType(msgtype), _textId(id), _target(target), _gender(gender) { } size_t operator()(WorldPacket* data, LocaleConstant locale) const { - std::string text = sObjectMgr->GetTrinityString(_textId, locale); - return ChatHandler::BuildChatPacket(*data, _msgType, Language(_language), _source, _target, text, 0, "", locale); + BroadcastText const* bct = sObjectMgr->GetBroadcastText(_textId); + std::string text = ""; + if (bct) + ObjectMgr::GetLocaleString(_gender == GENDER_MALE ? bct->MaleText : bct->FemaleText, locale, text); + + return ChatHandler::BuildChatPacket(*data, _msgType, bct ? Language(bct->Language) : LANG_UNIVERSAL, _source, _target, text, 0, "", locale); } - WorldObject* _source; + WorldObject const* _source; ChatMsg _msgType; - int32 _textId; - uint32 _language; - WorldObject* _target; + uint32 _textId; + WorldObject const* _target; + uint32 _gender; }; SmartScript::SmartScript() @@ -760,7 +764,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u me->DoFleeToGetAssistance(); if (e.action.flee.withEmote) { - TrinityStringTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, LANG_FLEE, LANG_UNIVERSAL, NULL); + BroadcastTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, BROADCAST_TEXT_FLEE_FOR_ASSIST, NULL, me->getGender()); sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE); } TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature %u DoFleeToGetAssistance", me->GetGUIDLow()); @@ -1003,7 +1007,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u me->CallForHelp((float)e.action.callHelp.range); if (e.action.callHelp.withEmote) { - TrinityStringTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, LANG_CALL_FOR_HELP, LANG_UNIVERSAL, NULL); + BroadcastTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, BROADCAST_TEXT_CALL_FOR_HELP, NULL, me->getGender()); sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE); } TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_FOR_HELP: Creature %u", me->GetGUIDLow()); @@ -2691,9 +2695,9 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_TARGET_HEALTH_PCT: { - if (!me || !me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->GetMaxHealth()) + if (!me || !me->IsInCombat() || !me->GetVictim() || !me->EnsureVictim()->GetMaxHealth()) return; - uint32 perc = (uint32)me->GetVictim()->GetHealthPct(); + uint32 perc = (uint32)me->EnsureVictim()->GetHealthPct(); if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) return; ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim()); @@ -2711,9 +2715,9 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_TARGET_MANA_PCT: { - if (!me || !me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->GetMaxPower(POWER_MANA)) + if (!me || !me->IsInCombat() || !me->GetVictim() || !me->EnsureVictim()->GetMaxPower(POWER_MANA)) return; - uint32 perc = uint32(100.0f * me->GetVictim()->GetPower(POWER_MANA) / me->GetVictim()->GetMaxPower(POWER_MANA)); + uint32 perc = uint32(100.0f * me->EnsureVictim()->GetPower(POWER_MANA) / me->EnsureVictim()->GetMaxPower(POWER_MANA)); if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) return; ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim()); @@ -2793,7 +2797,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui { if (!me || !me->GetVictim()) return; - uint32 count = me->GetVictim()->GetAuraCount(e.event.aura.spell); + uint32 count = me->EnsureVictim()->GetAuraCount(e.event.aura.spell); if (count < e.event.aura.count) return; ProcessTimedAction(e, e.event.aura.repeatMin, e.event.aura.repeatMax); diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index dc5a2768668..9b84d7ddb7d 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -702,7 +702,7 @@ class RBACPermission { public: RBACPermission(uint32 id = 0, std::string const& name = ""): - _id(id), _name(name) { } + _id(id), _name(name), _perms() { } /// Gets the Name of the Object std::string const& GetName() const { return _name; } @@ -737,7 +737,8 @@ class RBACData { public: RBACData(uint32 id, std::string const& name, int32 realmId, uint8 secLevel = 255): - _id(id), _name(name), _realmId(realmId), _secLevel(secLevel) { } + _id(id), _name(name), _realmId(realmId), _secLevel(secLevel), + _grantedPerms(), _deniedPerms(), _globalPerms() { } /// Gets the Name of the Object std::string const& GetName() const { return _name; } diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index a99da4050f6..5c7a4eb77b7 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -47,20 +47,24 @@ namespace Trinity class AchievementChatBuilder { public: - AchievementChatBuilder(Player const& player, ChatMsg msgtype, int32 textId, uint32 ach_id) - : i_player(player), i_msgtype(msgtype), i_textId(textId), i_achievementId(ach_id) { } + AchievementChatBuilder(Player const* player, ChatMsg msgType, uint32 textId, uint32 achievementId) + : _player(player), _msgType(msgType), _textId(textId), _achievementId(achievementId) { } - void operator()(WorldPacket& data, LocaleConstant loc_idx) + void operator()(WorldPacket& data, LocaleConstant locale) { - std::string text = sObjectMgr->GetTrinityString(i_textId, loc_idx); - ChatHandler::BuildChatPacket(data, i_msgtype, LANG_UNIVERSAL, &i_player, &i_player, text, i_achievementId); + std::string text = ""; + BroadcastText const* bct = sObjectMgr->GetBroadcastText(_textId); + if (bct) + ObjectMgr::GetLocaleString(_player->getGender() == GENDER_MALE ? bct->MaleText : bct->FemaleText, locale, text); + + ChatHandler::BuildChatPacket(data, _msgType, LANG_UNIVERSAL, _player, _player, text, _achievementId); } private: - Player const& i_player; - ChatMsg i_msgtype; - int32 i_textId; - uint32 i_achievementId; + Player const* _player; + ChatMsg _msgType; + int32 _textId; + uint32 _achievementId; }; } // namespace Trinity @@ -660,9 +664,9 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId())) { - Trinity::AchievementChatBuilder say_builder(*GetPlayer(), CHAT_MSG_GUILD_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID); - Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> say_do(say_builder); - guild->BroadcastWorker(say_do, GetPlayer()); + Trinity::AchievementChatBuilder _builder(GetPlayer(), CHAT_MSG_GUILD_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, achievement->ID); + Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> _localizer(_builder); + guild->BroadcastWorker(_localizer, GetPlayer()); } if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH)) @@ -678,16 +682,10 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) // if player is in world he can tell his friends about new achievement else if (GetPlayer()->IsInWorld()) { - CellCoord p = Trinity::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()); - - Cell cell(p); - cell.SetNoCreate(); - - Trinity::AchievementChatBuilder say_builder(*GetPlayer(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID); - Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> say_do(say_builder); - Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> > say_worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), say_do); - TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> >, WorldTypeMapContainer > message(say_worker); - cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY)); + Trinity::AchievementChatBuilder _builder(GetPlayer(), CHAT_MSG_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, achievement->ID); + Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> _localizer(_builder); + Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> > _worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _localizer); + GetPlayer()->VisitNearbyWorldObject(sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _worker); } WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8); diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 98ca9222e67..d353efb58c7 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -257,10 +257,6 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */) if (reload) { CachedDungeonMapStore.clear(); - // Recalculate locked dungeons - for (LfgPlayerDataContainer::const_iterator it = PlayersStore.begin(); it != PlayersStore.end(); ++it) - if (Player* player = ObjectAccessor::FindPlayer(it->first)) - InitializeLockedDungeons(player); } } @@ -368,74 +364,6 @@ void LFGMgr::Update(uint32 diff) } /** - Generate the dungeon lock map for a given player - - @param[in] player Player we need to initialize the lock status map -*/ -void LFGMgr::InitializeLockedDungeons(Player* player, uint8 level /* = 0 */) -{ - uint64 guid = player->GetGUID(); - if (!level) - level = player->getLevel(); - uint8 expansion = player->GetSession()->Expansion(); - LfgDungeonSet const& dungeons = GetDungeonsByRandom(0); - LfgLockMap lock; - bool denyJoin = !player->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER); - - for (LfgDungeonSet::const_iterator it = dungeons.begin(); it != dungeons.end(); ++it) - { - LFGDungeonData const* dungeon = GetLFGDungeon(*it); - if (!dungeon) // should never happen - We provide a list from sLFGDungeonStore - continue; - - uint32 lockData = 0; - if (denyJoin) - lockData = LFG_LOCKSTATUS_RAID_LOCKED; - else if (dungeon->expansion > expansion) - lockData = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; - else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player)) - lockData = LFG_LOCKSTATUS_RAID_LOCKED; - else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) - lockData = LFG_LOCKSTATUS_RAID_LOCKED; - else if (dungeon->minlevel > level) - lockData = LFG_LOCKSTATUS_TOO_LOW_LEVEL; - else if (dungeon->maxlevel < level) - lockData = LFG_LOCKSTATUS_TOO_HIGH_LEVEL; - else if (dungeon->seasonal && !IsSeasonActive(dungeon->id)) - lockData = LFG_LOCKSTATUS_NOT_IN_SEASON; - else if (AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty))) - { - if (ar->item_level && player->GetAverageItemLevel() < ar->item_level) - lockData = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE; - else if (ar->achievement && !player->HasAchieved(ar->achievement)) - lockData = LFG_LOCKSTATUS_MISSING_ACHIEVEMENT; - else if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A)) - lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; - else if (player->GetTeam() == HORDE && ar->quest_H && !player->GetQuestRewardStatus(ar->quest_H)) - lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; - else - if (ar->item) - { - if (!player->HasItemCount(ar->item) && (!ar->item2 || !player->HasItemCount(ar->item2))) - lockData = LFG_LOCKSTATUS_MISSING_ITEM; - } - else if (ar->item2 && !player->HasItemCount(ar->item2)) - lockData = LFG_LOCKSTATUS_MISSING_ITEM; - } - - /* @todo VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED) - lockData = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE; - lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL; - lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL; - */ - - if (lockData) - lock[dungeon->Entry()] = lockData; - } - SetLockedDungeons(guid, lock); -} - -/** Adds the player/group to lfg queue. If player is in a group then it is the leader of the group tying to join the group. Join conditions are checked before adding to the new queue. @@ -1610,10 +1538,74 @@ LfgDungeonSet const& LFGMgr::GetSelectedDungeons(uint64 guid) return PlayersStore[guid].GetSelectedDungeons(); } -LfgLockMap const& LFGMgr::GetLockedDungeons(uint64 guid) +LfgLockMap const LFGMgr::GetLockedDungeons(uint64 guid) { TC_LOG_TRACE("lfg.data.player.dungeons.locked.get", "Player: %u, LockedDungeons.", GUID_LOPART(guid)); - return PlayersStore[guid].GetLockedDungeons(); + LfgLockMap lock; + Player* player = ObjectAccessor::FindPlayer(guid); + if (!player) + { + TC_LOG_WARN("lfg.data.player.dungeons.locked.get", "Player: %u not ingame while retrieving his LockedDungeons.", GUID_LOPART(guid)); + return lock; + } + + uint8 level = player->getLevel(); + uint8 expansion = player->GetSession()->Expansion(); + LfgDungeonSet const& dungeons = GetDungeonsByRandom(0); + bool denyJoin = !player->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER); + + for (LfgDungeonSet::const_iterator it = dungeons.begin(); it != dungeons.end(); ++it) + { + LFGDungeonData const* dungeon = GetLFGDungeon(*it); + if (!dungeon) // should never happen - We provide a list from sLFGDungeonStore + continue; + + uint32 lockData = 0; + if (denyJoin) + lockData = LFG_LOCKSTATUS_RAID_LOCKED; + else if (dungeon->expansion > expansion) + lockData = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; + else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player)) + lockData = LFG_LOCKSTATUS_RAID_LOCKED; + else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) + lockData = LFG_LOCKSTATUS_RAID_LOCKED; + else if (dungeon->minlevel > level) + lockData = LFG_LOCKSTATUS_TOO_LOW_LEVEL; + else if (dungeon->maxlevel < level) + lockData = LFG_LOCKSTATUS_TOO_HIGH_LEVEL; + else if (dungeon->seasonal && !IsSeasonActive(dungeon->id)) + lockData = LFG_LOCKSTATUS_NOT_IN_SEASON; + else if (AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty))) + { + if (ar->item_level && player->GetAverageItemLevel() < ar->item_level) + lockData = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE; + else if (ar->achievement && !player->HasAchieved(ar->achievement)) + lockData = LFG_LOCKSTATUS_MISSING_ACHIEVEMENT; + else if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A)) + lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; + else if (player->GetTeam() == HORDE && ar->quest_H && !player->GetQuestRewardStatus(ar->quest_H)) + lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; + else + if (ar->item) + { + if (!player->HasItemCount(ar->item) && (!ar->item2 || !player->HasItemCount(ar->item2))) + lockData = LFG_LOCKSTATUS_MISSING_ITEM; + } + else if (ar->item2 && !player->HasItemCount(ar->item2)) + lockData = LFG_LOCKSTATUS_MISSING_ITEM; + } + + /* @todo VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED) + lockData = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE; + lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL; + lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL; + */ + + if (lockData) + lock[dungeon->Entry()] = lockData; + } + + return lock; } uint8 LFGMgr::GetKicksLeft(uint64 guid) @@ -1691,12 +1683,6 @@ void LFGMgr::SetSelectedDungeons(uint64 guid, LfgDungeonSet const& dungeons) PlayersStore[guid].SetSelectedDungeons(dungeons); } -void LFGMgr::SetLockedDungeons(uint64 guid, LfgLockMap const& lock) -{ - TC_LOG_TRACE("lfg.data.player.dungeon.locked.set", "Player: %u, LockedDungeons", GUID_LOPART(guid)); - PlayersStore[guid].SetLockedDungeons(lock); -} - void LFGMgr::DecreaseKicksLeft(uint64 guid) { GroupsStore[guid].DecreaseKicksLeft(); diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 8e33ba0a2f6..7d998997401 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -351,8 +351,6 @@ class LFGMgr // LFGScripts /// Get leader of the group (using internal data) uint64 GetLeader(uint64 guid); - /// Initializes locked dungeons for given player (called at login or level change) - void InitializeLockedDungeons(Player* player, uint8 level = 0); /// Sets player team void SetTeam(uint64 guid, uint8 team); /// Sets player group @@ -370,7 +368,7 @@ class LFGMgr // LFGHandler /// Get locked dungeons - LfgLockMap const& GetLockedDungeons(uint64 guid); + LfgLockMap const GetLockedDungeons(uint64 guid); /// Returns current lfg status LfgUpdateData GetLfgStatus(uint64 guid); /// Checks if Seasonal dungeon is active @@ -422,7 +420,6 @@ class LFGMgr void ClearState(uint64 guid, char const* debugMsg); void SetDungeon(uint64 guid, uint32 dungeon); void SetSelectedDungeons(uint64 guid, LfgDungeonSet const& dungeons); - void SetLockedDungeons(uint64 guid, LfgLockMap const& lock); void DecreaseKicksLeft(uint64 guid); void SetState(uint64 guid, LfgState state); void RemovePlayerData(uint64 guid); diff --git a/src/server/game/DungeonFinding/LFGPlayerData.cpp b/src/server/game/DungeonFinding/LFGPlayerData.cpp index 0553d4ac4fe..84b93543d7f 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.cpp +++ b/src/server/game/DungeonFinding/LFGPlayerData.cpp @@ -54,11 +54,6 @@ void LfgPlayerData::RestoreState() m_State = m_OldState; } -void LfgPlayerData::SetLockedDungeons(LfgLockMap const& lockStatus) -{ - m_LockedDungeons = lockStatus; -} - void LfgPlayerData::SetTeam(uint8 team) { m_Team = team; @@ -94,11 +89,6 @@ LfgState LfgPlayerData::GetOldState() const return m_OldState; } -const LfgLockMap& LfgPlayerData::GetLockedDungeons() const -{ - return m_LockedDungeons; -} - uint8 LfgPlayerData::GetTeam() const { return m_Team; diff --git a/src/server/game/DungeonFinding/LFGPlayerData.h b/src/server/game/DungeonFinding/LFGPlayerData.h index e20e914a9c9..996764e7620 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.h +++ b/src/server/game/DungeonFinding/LFGPlayerData.h @@ -35,7 +35,6 @@ class LfgPlayerData // General void SetState(LfgState state); void RestoreState(); - void SetLockedDungeons(LfgLockMap const& lock); void SetTeam(uint8 team); void SetGroup(uint64 group); @@ -47,7 +46,6 @@ class LfgPlayerData // General LfgState GetState() const; LfgState GetOldState() const; - LfgLockMap const& GetLockedDungeons() const; uint8 GetTeam() const; uint64 GetGroup() const; @@ -61,7 +59,6 @@ class LfgPlayerData LfgState m_State; ///< State if group in LFG LfgState m_OldState; ///< Old State - Used to restore state after failed Rolecheck/Proposal // Player - LfgLockMap m_LockedDungeons; ///< Dungeons player can't do and reason uint8 m_Team; ///< Player team - determines the queue to join uint64 m_Group; ///< Original group of player when joined LFG diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 1f182ce0761..aadf1529ffd 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -34,14 +34,6 @@ namespace lfg LFGPlayerScript::LFGPlayerScript() : PlayerScript("LFGPlayerScript") { } -void LFGPlayerScript::OnLevelChanged(Player* player, uint8 /*oldLevel*/) -{ - if (!sLFGMgr->isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER)) - return; - - sLFGMgr->InitializeLockedDungeons(player); -} - void LFGPlayerScript::OnLogout(Player* player) { if (!sLFGMgr->isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER)) @@ -74,18 +66,10 @@ void LFGPlayerScript::OnLogin(Player* player) } } - sLFGMgr->InitializeLockedDungeons(player); sLFGMgr->SetTeam(player->GetGUID(), player->GetTeam()); /// @todo - Restore LfgPlayerData and send proper status to player if it was in a group } -void LFGPlayerScript::OnBindToInstance(Player* player, Difficulty difficulty, uint32 mapId, bool /*permanent*/) -{ - MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); - if (mapEntry->IsDungeon() && difficulty > DUNGEON_DIFFICULTY_NORMAL) - sLFGMgr->InitializeLockedDungeons(player); -} - void LFGPlayerScript::OnMapChanged(Player* player) { Map const* map = player->GetMap(); diff --git a/src/server/game/DungeonFinding/LFGScripts.h b/src/server/game/DungeonFinding/LFGScripts.h index c4e1cf0a203..87881ed7524 100644 --- a/src/server/game/DungeonFinding/LFGScripts.h +++ b/src/server/game/DungeonFinding/LFGScripts.h @@ -35,10 +35,8 @@ class LFGPlayerScript : public PlayerScript LFGPlayerScript(); // Player Hooks - void OnLevelChanged(Player* player, uint8 oldLevel); void OnLogout(Player* player); void OnLogin(Player* player); - void OnBindToInstance(Player* player, Difficulty difficulty, uint32 mapId, bool permanent); void OnMapChanged(Player* player); }; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index e4bdc2d58fe..58a55d263df 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -562,8 +562,8 @@ void Creature::Update(uint32 diff) break; bool bInCombat = IsInCombat() && (!GetVictim() || // if IsInCombat() is true and this has no victim - !GetVictim()->GetCharmerOrOwnerPlayerOrPlayerItself() || // or the victim/owner/charmer is not a player - !GetVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()->IsGameMaster()); // or the victim/owner/charmer is not a GameMaster + !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself() || // or the victim/owner/charmer is not a player + !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()->IsGameMaster()); // or the victim/owner/charmer is not a GameMaster /*if (m_regenTimer <= diff) {*/ @@ -693,7 +693,7 @@ void Creature::DoFleeToGetAssistance() UpdateSpeed(MOVE_RUN, false); if (!creature) - //SetFeared(true, GetVictim()->GetGUID(), 0, sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_FLEE_DELAY)); + //SetFeared(true, EnsureVictim()->GetGUID(), 0, sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_FLEE_DELAY)); /// @todo use 31365 SetControlled(true, UNIT_STATE_FLEEING); else @@ -1845,7 +1845,7 @@ void Creature::CallAssistance() if (!assistList.empty()) { - AssistDelayEvent* e = new AssistDelayEvent(GetVictim()->GetGUID(), *this); + AssistDelayEvent* e = new AssistDelayEvent(EnsureVictim()->GetGUID(), *this); while (!assistList.empty()) { // Pushing guids because in delay can happen some creature gets despawned => invalid pointer diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index bb6686aa2ad..208077e51cb 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -268,8 +268,8 @@ class Object // for output helpfull error messages from asserts bool PrintIndexError(uint32 index, bool set) const; - Object(const Object&); // prevent generation copy constructor - Object& operator=(Object const&); // prevent generation assigment operator + Object(Object const& right) DELETE_MEMBER; + Object& operator=(Object const& right) DELETE_MEMBER; }; struct Position @@ -498,6 +498,8 @@ template<class T> class GridObject { public: + virtual ~GridObject() { } + bool IsInGrid() const { return _gridRef.isValid(); } void AddToGrid(GridRefManager<T>& m) { ASSERT(!IsInGrid()); _gridRef.link(&m, (T*)this); } void RemoveFromGrid() { ASSERT(IsInGrid()); _gridRef.unlink(); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 13635424cf0..94f212e6051 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -5149,8 +5149,9 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) // remove death flag + set aura SetByteValue(UNIT_FIELD_BYTES_1, 3, 0x00); - if (getRace() == RACE_NIGHTELF) - RemoveAurasDueToSpell(20584); // speed bonuses + + // This must be called always even on Players with race != RACE_NIGHTELF in case of faction change + RemoveAurasDueToSpell(20584); // RACE_NIGHTELF speed bonuses RemoveAurasDueToSpell(8326); // SPELL_AURA_GHOST if (GetSession()->IsARecruiter() || (GetSession()->GetRecruiterId() != 0)) @@ -17182,6 +17183,14 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) bytes0 |= gender << 16; // gender SetUInt32Value(UNIT_FIELD_BYTES_0, bytes0); + // check if race/class combination is valid + PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); + if (!info) + { + TC_LOG_ERROR("entities.player", "Player (GUID: %u) has wrong race/class (%u/%u), can't be loaded.", guid, getRace(), getClass()); + return false; + } + SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8()); SetUInt32Value(PLAYER_XP, fields[7].GetUInt32()); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 06628de4050..979edcdafc7 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -8635,6 +8635,9 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, Au void Unit::setPowerType(Powers new_powertype) { + if (getPowerType() == new_powertype) + return; + SetByteValue(UNIT_FIELD_BYTES_0, 3, new_powertype); if (GetTypeId() == TYPEID_PLAYER) @@ -15559,7 +15562,7 @@ void Unit::SetStunned(bool apply) else { if (IsAlive() && GetVictim()) - SetTarget(GetVictim()->GetGUID()); + SetTarget(EnsureVictim()->GetGUID()); // don't remove UNIT_FLAG_STUNNED for pet when owner is mounted (disabled pet's interface) Unit* owner = GetOwner(); @@ -15650,7 +15653,7 @@ void Unit::SetFeared(bool apply) if (GetMotionMaster()->GetCurrentMovementGeneratorType() == FLEEING_MOTION_TYPE) GetMotionMaster()->MovementExpired(); if (GetVictim()) - SetTarget(GetVictim()->GetGUID()); + SetTarget(EnsureVictim()->GetGUID()); } } @@ -15672,7 +15675,7 @@ void Unit::SetConfused(bool apply) if (GetMotionMaster()->GetCurrentMovementGeneratorType() == CONFUSED_MOTION_TYPE) GetMotionMaster()->MovementExpired(); if (GetVictim()) - SetTarget(GetVictim()->GetGUID()); + SetTarget(EnsureVictim()->GetGUID()); } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 6b6d844472a..22c6d6b272e 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1328,6 +1328,12 @@ class Unit : public WorldObject AttackerSet const& getAttackers() const { return m_attackers; } bool isAttackingPlayer() const; Unit* GetVictim() const { return m_attacking; } + // Use this only when 100% sure there is a victim + Unit* EnsureVictim() const + { + ASSERT(m_attacking); + return m_attacking; + } void CombatStop(bool includingCast = false); void CombatStopWithPets(bool includingCast = false); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index e4dbe60535d..e37513d0917 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -357,7 +357,8 @@ void ObjectMgr::LoadGossipMenuItemsLocales() AddLocaleString(fields[2 + 2 * (i - 1)].GetString(), locale, data.OptionText); AddLocaleString(fields[2 + 2 * (i - 1) + 1].GetString(), locale, data.BoxText); } - } while (result->NextRow()); + } + while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %lu gossip_menu_option locale strings in %u ms", (unsigned long)_gossipMenuItemsLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime)); } @@ -5203,17 +5204,28 @@ void ObjectMgr::LoadGossipText() { uint32 oldMSTime = getMSTime(); - QueryResult result = WorldDatabase.Query("SELECT * FROM npc_text"); + QueryResult result = WorldDatabase.Query("SELECT ID, " + "text0_0, text0_1, BroadcastTextID0, lang0, prob0, em0_0, em0_1, em0_2, em0_3, em0_4, em0_5, " + "text1_0, text1_1, BroadcastTextID1, lang1, prob1, em1_0, em1_1, em1_2, em1_3, em1_4, em1_5, " + "text2_0, text2_1, BroadcastTextID2, lang2, prob2, em2_0, em2_1, em2_2, em2_3, em2_4, em2_5, " + "text3_0, text3_1, BroadcastTextID3, lang3, prob3, em3_0, em3_1, em3_2, em3_3, em3_4, em3_5, " + "text4_0, text4_1, BroadcastTextID4, lang4, prob4, em4_0, em4_1, em4_2, em4_3, em4_4, em4_5, " + "text5_0, text5_1, BroadcastTextID5, lang5, prob5, em5_0, em5_1, em5_2, em5_3, em5_4, em5_5, " + "text6_0, text6_1, BroadcastTextID6, lang6, prob6, em6_0, em6_1, em6_2, em6_3, em6_4, em6_5, " + "text7_0, text7_1, BroadcastTextID7, lang7, prob7, em7_0, em7_1, em7_2, em7_3, em7_4, em7_5 " + "FROM npc_text"); + - int count = 0; if (!result) { - TC_LOG_INFO("server.loading", ">> Loaded %u npc texts", count); + TC_LOG_INFO("server.loading", ">> Loaded 0 npc texts, table is empty!"); return; } + _gossipTextStore.rehash(result->GetRowCount()); - int cic; + uint32 count = 0; + uint8 cic; do { @@ -5222,32 +5234,44 @@ void ObjectMgr::LoadGossipText() Field* fields = result->Fetch(); - uint32 Text_ID = fields[cic++].GetUInt32(); - if (!Text_ID) + uint32 id = fields[cic++].GetUInt32(); + if (!id) { - TC_LOG_ERROR("sql.sql", "Table `npc_text` has record wit reserved id 0, ignore."); + TC_LOG_ERROR("sql.sql", "Table `npc_text` has record with reserved id 0, ignore."); continue; } - GossipText& gText = _gossipTextStore[Text_ID]; + GossipText& gText = _gossipTextStore[id]; - for (int i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; i++) + for (uint8 i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i) { gText.Options[i].Text_0 = fields[cic++].GetString(); gText.Options[i].Text_1 = fields[cic++].GetString(); - - gText.Options[i].BroadcastTextID = fields[cic++].GetUInt32(); // Need for correct loading order - + gText.Options[i].BroadcastTextID = fields[cic++].GetUInt32(); gText.Options[i].Language = fields[cic++].GetUInt8(); gText.Options[i].Probability = fields[cic++].GetFloat(); - for (uint8 j=0; j < MAX_GOSSIP_TEXT_EMOTES; ++j) + for (uint8 j = 0; j < MAX_GOSSIP_TEXT_EMOTES; ++j) { - gText.Options[i].Emotes[j]._Delay = fields[cic++].GetUInt16(); - gText.Options[i].Emotes[j]._Emote = fields[cic++].GetUInt16(); + gText.Options[i].Emotes[j]._Delay = fields[cic++].GetUInt16(); + gText.Options[i].Emotes[j]._Emote = fields[cic++].GetUInt16(); } } - } while (result->NextRow()); + + for (uint8 i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; i++) + { + if (gText.Options[i].BroadcastTextID) + { + if (!sObjectMgr->GetBroadcastText(gText.Options[i].BroadcastTextID)) + { + TC_LOG_ERROR("sql.sql", "GossipText (Id: %u) in table `npc_text` has non-existing or incompatible BroadcastTextID%u %u.", id, i, gText.Options[i].BroadcastTextID); + gText.Options[i].BroadcastTextID = 0; + } + } + } + + } + while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u npc texts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } @@ -8266,8 +8290,8 @@ void ObjectMgr::LoadGossipMenuItems() _gossipMenuItemsStore.clear(); QueryResult result = WorldDatabase.Query( - // 0 1 2 3 4 5 6 7 8 9 10 - "SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, action_menu_id, action_poi_id, box_coded, box_money, box_text " + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + "SELECT menu_id, id, option_icon, option_text, OptionBroadcastTextID, option_id, npc_option_npcflag, action_menu_id, action_poi_id, box_coded, box_money, box_text, BoxBroadcastTextID " "FROM gossip_menu_option ORDER BY menu_id, id"); if (!result) @@ -8288,29 +8312,49 @@ void ObjectMgr::LoadGossipMenuItems() gMenuItem.OptionIndex = fields[1].GetUInt16(); gMenuItem.OptionIcon = fields[2].GetUInt32(); gMenuItem.OptionText = fields[3].GetString(); - gMenuItem.OptionType = fields[4].GetUInt8(); - gMenuItem.OptionNpcflag = fields[5].GetUInt32(); - gMenuItem.ActionMenuId = fields[6].GetUInt32(); - gMenuItem.ActionPoiId = fields[7].GetUInt32(); - gMenuItem.BoxCoded = fields[8].GetBool(); - gMenuItem.BoxMoney = fields[9].GetUInt32(); - gMenuItem.BoxText = fields[10].GetString(); + gMenuItem.OptionBroadcastTextId = fields[4].GetUInt32(); + gMenuItem.OptionType = fields[5].GetUInt8(); + gMenuItem.OptionNpcflag = fields[6].GetUInt32(); + gMenuItem.ActionMenuId = fields[7].GetUInt32(); + gMenuItem.ActionPoiId = fields[8].GetUInt32(); + gMenuItem.BoxCoded = fields[9].GetBool(); + gMenuItem.BoxMoney = fields[10].GetUInt32(); + gMenuItem.BoxText = fields[11].GetString(); + gMenuItem.BoxBroadcastTextId = fields[12].GetUInt32(); if (gMenuItem.OptionIcon >= GOSSIP_ICON_MAX) { - TC_LOG_ERROR("sql.sql", "Table gossip_menu_option for menu %u, id %u has unknown icon id %u. Replacing with GOSSIP_ICON_CHAT", gMenuItem.MenuId, gMenuItem.OptionIndex, gMenuItem.OptionIcon); + TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u has unknown icon id %u. Replacing with GOSSIP_ICON_CHAT", gMenuItem.MenuId, gMenuItem.OptionIndex, gMenuItem.OptionIcon); gMenuItem.OptionIcon = GOSSIP_ICON_CHAT; } + if (gMenuItem.OptionBroadcastTextId) + { + if (!GetBroadcastText(gMenuItem.OptionBroadcastTextId)) + { + TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u has non-existing or incompatible OptionBroadcastTextId %u, ignoring.", gMenuItem.MenuId, gMenuItem.OptionIndex, gMenuItem.OptionBroadcastTextId); + gMenuItem.OptionBroadcastTextId = 0; + } + } + if (gMenuItem.OptionType >= GOSSIP_OPTION_MAX) - TC_LOG_ERROR("sql.sql", "Table gossip_menu_option for menu %u, id %u has unknown option id %u. Option will not be used", gMenuItem.MenuId, gMenuItem.OptionIndex, gMenuItem.OptionType); + TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u has unknown option id %u. Option will not be used", gMenuItem.MenuId, gMenuItem.OptionIndex, gMenuItem.OptionType); if (gMenuItem.ActionPoiId && !GetPointOfInterest(gMenuItem.ActionPoiId)) { - TC_LOG_ERROR("sql.sql", "Table gossip_menu_option for menu %u, id %u use non-existing action_poi_id %u, ignoring", gMenuItem.MenuId, gMenuItem.OptionIndex, gMenuItem.ActionPoiId); + TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u use non-existing action_poi_id %u, ignoring", gMenuItem.MenuId, gMenuItem.OptionIndex, gMenuItem.ActionPoiId); gMenuItem.ActionPoiId = 0; } + if (gMenuItem.BoxBroadcastTextId) + { + if (!GetBroadcastText(gMenuItem.BoxBroadcastTextId)) + { + TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u has non-existing or incompatible BoxBroadcastTextId %u, ignoring.", gMenuItem.MenuId, gMenuItem.OptionIndex, gMenuItem.BoxBroadcastTextId); + gMenuItem.BoxBroadcastTextId = 0; + } + } + _gossipMenuItemsStore.insert(GossipMenuItemsContainer::value_type(gMenuItem.MenuId, gMenuItem)); ++count; } @@ -8528,6 +8572,140 @@ void ObjectMgr::CheckScripts(ScriptsType type, std::set<int32>& ids) } } +void ObjectMgr::LoadBroadcastTexts() +{ + uint32 oldMSTime = getMSTime(); + + _broadcastTextStore.clear(); // for reload case + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + QueryResult result = WorldDatabase.Query("SELECT ID, Language, MaleText, FemaleText, EmoteID0, EmoteID1, EmoteID2, EmoteDelay0, EmoteDelay1, EmoteDelay2, SoundId, Unk1, Unk2 FROM broadcast_text"); + if (!result) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 broadcast texts. DB table `broadcast_text` is empty."); + return; + } + + uint32 count = 0; + + do + { + Field* fields = result->Fetch(); + + BroadcastText bct; + + bct.Id = fields[0].GetUInt32(); + bct.Language = fields[1].GetUInt32(); + AddLocaleString(fields[2].GetString(), DEFAULT_LOCALE, bct.MaleText); + AddLocaleString(fields[3].GetString(), DEFAULT_LOCALE, bct.FemaleText); + bct.EmoteId0 = fields[4].GetUInt32(); + bct.EmoteId1 = fields[5].GetUInt32(); + bct.EmoteId2 = fields[6].GetUInt32(); + bct.EmoteDelay0 = fields[7].GetUInt32(); + bct.EmoteDelay1 = fields[8].GetUInt32(); + bct.EmoteDelay2 = fields[9].GetUInt32(); + bct.SoundId = fields[10].GetUInt32(); + bct.Unk1 = fields[11].GetUInt32(); + bct.Unk2 = fields[12].GetUInt32(); + + if (bct.SoundId) + { + if (!sSoundEntriesStore.LookupEntry(bct.SoundId)) + { + TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `broadcast_text` has SoundId %u but sound does not exist. Skipped.", bct.Id, bct.SoundId); + // don't load bct of higher expansions + continue; + } + } + + if (!GetLanguageDescByID(bct.Language)) + { + TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `broadcast_text` using Language %u but Language does not exist. Skipped.", bct.Id, bct.Language); + // don't load bct of higher expansions + continue; + } + + if (bct.EmoteId0) + { + if (!sEmotesStore.LookupEntry(bct.EmoteId0)) + { + TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `broadcast_text` has EmoteId0 %u but emote does not exist. Skipped.", bct.Id, bct.EmoteId0); + // don't load bct of higher expansions + continue; + } + } + + if (bct.EmoteId1) + { + if (!sEmotesStore.LookupEntry(bct.EmoteId1)) + { + TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `broadcast_text` has EmoteId1 %u but emote does not exist. Skipped.", bct.Id, bct.EmoteId1); + // don't load bct of higher expansions + continue; + } + } + + if (bct.EmoteId2) + { + if (!sEmotesStore.LookupEntry(bct.EmoteId2)) + { + TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `broadcast_text` has EmoteId2 %u but emote does not exist. Skipped.", bct.Id, bct.EmoteId2); + // don't load bct of higher expansions + continue; + } + } + + _broadcastTextStore[bct.Id] = bct; + + ++count; + } + while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded %u broadcast texts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); +} + +void ObjectMgr::LoadBroadcastTextLocales() +{ + uint32 oldMSTime = getMSTime(); + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + QueryResult result = WorldDatabase.Query("SELECT Id, MaleText_loc1, MaleText_loc2, MaleText_loc3, MaleText_loc4, MaleText_loc5, MaleText_loc6, MaleText_loc7, MaleText_loc8, FemaleText_loc1, FemaleText_loc2, FemaleText_loc3, FemaleText_loc4, FemaleText_loc5, FemaleText_loc6, FemaleText_loc7, FemaleText_loc8 FROM locales_broadcast_text"); + + if (!result) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 broadcast text locales. DB table `locales_broadcast_text` is empty."); + return; + } + + uint32 count = 0; + + do + { + Field* fields = result->Fetch(); + + uint32 id = fields[0].GetUInt32(); + BroadcastTextContainer::iterator bct = _broadcastTextStore.find(id); + if (bct == _broadcastTextStore.end()) + { + TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `locales_broadcast_text` does not exist or is incompatible. Skipped!", id); + // don't load bct of higher expansions + continue; + } + + for (uint8 i = 1; i < TOTAL_LOCALES; ++i) + { + LocaleConstant locale = LocaleConstant(i); + ObjectMgr::AddLocaleString(fields[1 + (i - 1)].GetString(), locale, bct->second.MaleText); + ObjectMgr::AddLocaleString(fields[9 + (i - 1)].GetString(), locale, bct->second.FemaleText); + } + + ++count; + } + while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded %u broadcast text locales in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); +} + void ObjectMgr::LoadDbScriptStrings() { LoadTrinityStrings("db_script_string", MIN_DB_SCRIPT_STRING_ID, MAX_DB_SCRIPT_STRING_ID); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index b1f80af0567..825ff3a740f 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -410,6 +410,26 @@ struct AreaTrigger float target_Orientation; }; +struct BroadcastText +{ + uint32 Id; + uint32 Language; + StringVector MaleText; + StringVector FemaleText; + uint32 EmoteId0; + uint32 EmoteId1; + uint32 EmoteId2; + uint32 EmoteDelay0; + uint32 EmoteDelay1; + uint32 EmoteDelay2; + uint32 SoundId; + uint32 Unk1; + uint32 Unk2; + // uint32 WDBVerified; +}; + +typedef UNORDERED_MAP<uint32, BroadcastText> BroadcastTextContainer; + typedef std::set<uint32> CellGuidSet; typedef std::map<uint32/*player guid*/, uint32/*instance*/> CellCorpseSet; struct CellObjectGuids @@ -527,6 +547,7 @@ struct GossipMenuItems uint32 OptionIndex; uint8 OptionIcon; std::string OptionText; + uint32 OptionBroadcastTextId; uint32 OptionType; uint32 OptionNpcflag; uint32 ActionMenuId; @@ -534,6 +555,7 @@ struct GossipMenuItems bool BoxCoded; uint32 BoxMoney; std::string BoxText; + uint32 BoxBroadcastTextId; ConditionList Conditions; }; @@ -905,6 +927,8 @@ class ObjectMgr void LoadSpellScriptNames(); void ValidateSpellScripts(); + void LoadBroadcastTexts(); + void LoadBroadcastTextLocales(); bool LoadTrinityStrings(char const* table, int32 min_value, int32 max_value); bool LoadTrinityStrings() { return LoadTrinityStrings("trinity_string", MIN_TRINITY_STRING_ID, MAX_TRINITY_STRING_ID); } void LoadDbScriptStrings(); @@ -1042,6 +1066,14 @@ class ObjectMgr return NULL; } + BroadcastText const* GetBroadcastText(uint32 id) const + { + BroadcastTextContainer::const_iterator itr = _broadcastTextStore.find(id); + if (itr != _broadcastTextStore.end()) + return &itr->second; + return NULL; + } + CreatureData const* GetCreatureData(uint32 guid) const { CreatureDataContainer::const_iterator itr = _creatureDataStore.find(guid); @@ -1361,6 +1393,7 @@ class ObjectMgr /// Stores temp summon data grouped by summoner's entry, summoner's type and group id TempSummonDataContainer _tempSummonDataStore; + BroadcastTextContainer _broadcastTextStore; ItemTemplateContainer _itemTemplateStore; ItemLocaleContainer _itemLocaleStore; ItemSetNameLocaleContainer _itemSetNameLocaleStore; diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index d9e4feb7f85..86fa0429cce 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -119,7 +119,9 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) recvData >> itemsCount; uint64 itemGUIDs[MAX_AUCTION_ITEMS]; // 160 slot = 4x 36 slot bag + backpack 16 slot + memset(itemGUIDs, 0, sizeof(itemGUIDs)); uint32 count[MAX_AUCTION_ITEMS]; + memset(count, 0, sizeof(count)); if (itemsCount > MAX_AUCTION_ITEMS) { @@ -187,6 +189,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) Item* items[MAX_AUCTION_ITEMS]; uint32 finalCount = 0; + uint32 itemEntry = 0; for (uint32 i = 0; i < itemsCount; ++i) { @@ -198,9 +201,12 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) return; } + if (itemEntry == 0) + itemEntry = item->GetTemplate()->ItemId; + 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]) + item->GetCount() < count[i] || itemEntry != item->GetTemplate()->ItemId) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; @@ -216,6 +222,19 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) return; } + // check if there are 2 identical guids, in this case user is most likely cheating + for (uint32 i = 0; i < itemsCount - 1; ++i) + { + for (uint32 j = i + 1; j < itemsCount; ++j) + { + if (itemGUIDs[i] == itemGUIDs[j]) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); + return; + } + } + } + for (uint32 i = 0; i < itemsCount; ++i) { Item* item = items[i]; diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index f9a5ec2d53b..f4ea4971190 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1768,6 +1768,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) } } + // resurrect the character in case he's dead + sObjectAccessor->ConvertCorpseForPlayer(guid); + CharacterDatabase.EscapeString(newname); Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair); SQLTransaction trans = CharacterDatabase.BeginTransaction(); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 3102e2c6854..51ce8250f89 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -19,6 +19,13 @@ #ifndef __TRINITY_LANGUAGE_H #define __TRINITY_LANGUAGE_H +enum BroadcastTextIds +{ + BROADCAST_TEXT_ACHIEVEMENT_EARNED = 29245, + BROADCAST_TEXT_CALL_FOR_HELP = 2541, + BROADCAST_TEXT_FLEE_FOR_ASSIST = 1150 +}; + enum TrinityStrings { // for chat commands @@ -753,7 +760,7 @@ enum TrinityStrings LANG_NEED_CHARACTER_NAME = 807, LANG_PLAYER_NOT_EXIST_OR_OFFLINE = 808, LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND = 809, - LANG_ACHIEVEMENT_EARNED = 810, + // unused = 810, LANG_GUILD_MASTER = 811, LANG_GUILD_OFFICER = 812, LANG_GUILD_VETERAN = 813, @@ -1074,12 +1081,12 @@ enum TrinityStrings LANG_GOINFO_NAME = 5027, LANG_GOINFO_LOOTID = 5028, LANG_COMMAND_LOOKUP_MAX_RESULTS = 5029, - LANG_FLEE = 5030, + // unused = 5030, LANG_NPCINFO_AIINFO = 5031, LANG_COMMAND_NO_BATTLEGROUND_FOUND = 5032, LANG_COMMAND_NO_ACHIEVEMENT_CRITERIA_FOUND = 5033, LANG_COMMAND_NO_OUTDOOR_PVP_FORUND = 5034, - LANG_CALL_FOR_HELP = 5035, + // unused = 5035, LANG_NPCINFO_EQUIPMENT = 5036, LANG_NPCINFO_MECHANIC_IMMUNE = 5037, LANG_NPCINFO_UNIT_FIELD_FLAGS = 5038, diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index 61f3a04bc5d..2ab408965c1 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -118,7 +118,7 @@ void ConfusedMovementGenerator<Creature>::DoFinalize(Creature* unit) unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); unit->ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); if (unit->GetVictim()) - unit->SetTarget(unit->GetVictim()->GetGUID()); + unit->SetTarget(unit->EnsureVictim()->GetGUID()); } template void ConfusedMovementGenerator<Player>::DoInitialize(Player*); diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 572d65b07c7..a34d09c3721 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -141,7 +141,7 @@ void FleeingMovementGenerator<Creature>::DoFinalize(Creature* owner) owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); if (owner->GetVictim()) - owner->SetTarget(owner->GetVictim()->GetGUID()); + owner->SetTarget(owner->EnsureVictim()->GetGUID()); } template<class T> diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 8ed8a2b3c49..e63e44d5ed5 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -183,6 +183,8 @@ template<class TObject> class UpdatableScript { } + virtual ~UpdatableScript() { } + public: virtual void OnUpdate(TObject* /*obj*/, uint32 /*diff*/) { } diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 58e7ba02f47..89242bada6e 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -46,6 +46,7 @@ #include "Transport.h" #include "WardenWin.h" #include "WardenMac.h" +#include "MoveSpline.h" namespace { @@ -891,6 +892,9 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi) REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY) && mi->HasMovementFlag(MOVEMENTFLAG_FALLING), MOVEMENTFLAG_FALLING); + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ENABLED) && + (!GetPlayer()->movespline->Initialized() || GetPlayer()->movespline->Finalized()), MOVEMENTFLAG_SPLINE_ENABLED); + #undef REMOVE_VIOLATING_FLAGS } diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 0af6069a0e5..71703cb944f 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -138,6 +138,10 @@ public: protected: WorldSession* const m_pSession; + +private: + PacketFilter(PacketFilter const& right) DELETE_MEMBER; + PacketFilter& operator=(PacketFilter const& right) DELETE_MEMBER; }; //process only thread-safe packets in Map::Update() class MapSessionFilter : public PacketFilter @@ -950,6 +954,9 @@ class WorldSession typedef UNORDERED_MAP<uint16, bool> OpcodeStatusMap; OpcodeStatusMap _isOpcodeAllowed; // could be bool array, but wouldn't be practical for game versions with non-linear opcodes Policy _policy; + + DosProtection(DosProtection const& right) DELETE_MEMBER; + DosProtection& operator=(DosProtection const& right) DELETE_MEMBER; } AntiDOS; private: @@ -1003,6 +1010,9 @@ class WorldSession ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue; time_t timeLastWhoCommand; rbac::RBACData* _RBACData; + + WorldSession(WorldSession const& right) DELETE_MEMBER; + WorldSession& operator=(WorldSession const& right) DELETE_MEMBER; }; #endif /// @} diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 103d60346e8..4e356df4d94 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -208,6 +208,8 @@ class WorldSocket : public WorldHandler uint32 m_Seed; + WorldSocket(WorldSocket const& right) DELETE_MEMBER; + WorldSocket& operator=(WorldSocket const& right) DELETE_MEMBER; }; #endif /* _WORLDSOCKET_H */ diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 06bd12911ad..b87524357d2 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5373,12 +5373,12 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const { // Feeding Frenzy Rank 1 case 53511: - if (target->GetVictim() && target->GetVictim()->HealthBelowPct(35)) + if (target->GetVictim() && target->EnsureVictim()->HealthBelowPct(35)) target->CastSpell(target, 60096, true, 0, this); return; // Feeding Frenzy Rank 2 case 53512: - if (target->GetVictim() && target->GetVictim()->HealthBelowPct(35)) + if (target->GetVictim() && target->EnsureVictim()->HealthBelowPct(35)) target->CastSpell(target, 60097, true, 0, this); return; default: diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index e87e2c2085a..a65aa6b589f 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -688,6 +688,9 @@ class Spell double rand_norm() { return m_caster->GetMap()->mtRand.randExc(); } double rand_chance() { return m_caster->GetMap()->mtRand.randExc(100.0); } #endif + + Spell(Spell const& right) DELETE_MEMBER; + Spell& operator=(Spell const& right) DELETE_MEMBER; }; namespace Trinity diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 28bc659050a..35930906307 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -5468,13 +5468,23 @@ void Spell::EffectQuestStart(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) return; - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + if (!unitTarget) return; Player* player = unitTarget->ToPlayer(); - if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(m_spellInfo->Effects[effIndex].MiscValue)) - if (player->CanTakeQuest(qInfo, false) && player->CanAddQuest(qInfo, false)) - player->AddQuestAndCheckCompletion(qInfo, NULL); + if (!player) + return; + + if (Quest const* quest = sObjectMgr->GetQuestTemplate(m_spellInfo->Effects[effIndex].MiscValue)) + { + if (!player->CanTakeQuest(quest, false)) + return; + + if (quest->IsAutoAccept() && player->CanAddQuest(quest, false)) + player->AddQuestAndCheckCompletion(quest, player); + + player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, player->GetGUID(), true); + } } void Spell::EffectActivateRune(SpellEffIndex effIndex) diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp index b89c64165c3..dd790cf9072 100644 --- a/src/server/game/Texts/CreatureTextMgr.cpp +++ b/src/server/game/Texts/CreatureTextMgr.cpp @@ -28,10 +28,8 @@ class CreatureTextBuilder { public: - CreatureTextBuilder(WorldObject* obj, ChatMsg msgtype, uint8 textGroup, uint32 id, uint32 language, WorldObject const* target) - : _source(obj), _msgType(msgtype), _textGroup(textGroup), _textId(id), _language(language), _target(target) - { - } + CreatureTextBuilder(WorldObject const* obj, ChatMsg msgtype, uint8 textGroup, uint32 id, uint32 language, WorldObject const* target) + : _source(obj), _msgType(msgtype), _textGroup(textGroup), _textId(id), _language(language), _target(target) { } size_t operator()(WorldPacket* data, LocaleConstant locale) const { @@ -40,7 +38,8 @@ class CreatureTextBuilder return ChatHandler::BuildChatPacket(*data, _msgType, Language(_language), _source, _target, text, 0, "", locale); } - WorldObject* _source; + private: + WorldObject const* _source; ChatMsg _msgType; uint8 _textGroup; uint32 _textId; @@ -51,10 +50,8 @@ class CreatureTextBuilder class PlayerTextBuilder { public: - PlayerTextBuilder(WorldObject* obj, WorldObject* speaker, ChatMsg msgtype, uint8 textGroup, uint32 id, uint32 language, WorldObject const* target) - : _source(obj), _talker(speaker), _msgType(msgtype), _textGroup(textGroup), _textId(id), _language(language), _target(target) - { - } + PlayerTextBuilder(WorldObject const* obj, WorldObject const* speaker, ChatMsg msgtype, uint8 textGroup, uint32 id, uint32 language, WorldObject const* target) + : _source(obj), _talker(speaker), _msgType(msgtype), _textGroup(textGroup), _textId(id), _language(language), _target(target) { } size_t operator()(WorldPacket* data, LocaleConstant locale) const { @@ -63,8 +60,9 @@ class PlayerTextBuilder return ChatHandler::BuildChatPacket(*data, _msgType, Language(_language), _talker, _target, text, 0, "", locale); } - WorldObject* _source; - WorldObject* _talker; + private: + WorldObject const* _source; + WorldObject const* _talker; ChatMsg _msgType; uint8 _textGroup; uint32 _textId; @@ -97,34 +95,39 @@ void CreatureTextMgr::LoadCreatureTexts() Field* fields = result->Fetch(); CreatureTextEntry temp; - temp.entry = fields[0].GetUInt32(); - temp.group = fields[1].GetUInt8(); - temp.id = fields[2].GetUInt8(); - temp.text = fields[3].GetString(); - temp.type = ChatMsg(fields[4].GetUInt8()); - temp.lang = Language(fields[5].GetUInt8()); - temp.probability = fields[6].GetFloat(); - temp.emote = Emote(fields[7].GetUInt32()); - temp.duration = fields[8].GetUInt32(); - temp.sound = fields[9].GetUInt32(); + temp.entry = fields[0].GetUInt32(); + temp.group = fields[1].GetUInt8(); + temp.id = fields[2].GetUInt8(); + temp.text = fields[3].GetString(); + temp.type = ChatMsg(fields[4].GetUInt8()); + temp.lang = Language(fields[5].GetUInt8()); + temp.probability = fields[6].GetFloat(); + temp.emote = Emote(fields[7].GetUInt32()); + temp.duration = fields[8].GetUInt32(); + temp.sound = fields[9].GetUInt32(); + temp.BroadcastTextId = fields[10].GetUInt32(); if (temp.sound) { - if (!sSoundEntriesStore.LookupEntry(temp.sound)){ + if (!sSoundEntriesStore.LookupEntry(temp.sound)) + { TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry %u, Group %u in table `creature_texts` has Sound %u but sound does not exist.", temp.entry, temp.group, temp.sound); temp.sound = 0; } } + if (!GetLanguageDescByID(temp.lang)) { TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry %u, Group %u in table `creature_texts` using Language %u but Language does not exist.", temp.entry, temp.group, uint32(temp.lang)); temp.lang = LANG_UNIVERSAL; } + if (temp.type >= MAX_CHAT_MSG_TYPE) { TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry %u, Group %u in table `creature_texts` has Type %u but this Chat Type does not exist.", temp.entry, temp.group, uint32(temp.type)); temp.type = CHAT_MSG_SAY; } + if (temp.emote) { if (!sEmotesStore.LookupEntry(temp.emote)) @@ -133,18 +136,28 @@ void CreatureTextMgr::LoadCreatureTexts() temp.emote = EMOTE_ONESHOT_NONE; } } - //entry not yet added, add empty TextHolder (list of groups) + + if (temp.BroadcastTextId) + { + if (!sObjectMgr->GetBroadcastText(temp.BroadcastTextId)) + { + TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry %u, Group %u, Id %u in table `creature_texts` has non-existing or incompatible BroadcastTextId %u.", temp.entry, temp.group, temp.id, temp.BroadcastTextId); + temp.BroadcastTextId = 0; + } + } + + // entry not yet added, add empty TextHolder (list of groups) if (mTextMap.find(temp.entry) == mTextMap.end()) ++creatureCount; - //add the text into our entry's group + // add the text into our entry's group mTextMap[temp.entry][temp.group].push_back(temp); ++textCount; - } while (result->NextRow()); + } + while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u creature texts for %u creatures in %u ms", textCount, creatureCount, GetMSTimeDiffToNow(oldMSTime)); - } void CreatureTextMgr::LoadCreatureTextLocales() @@ -315,14 +328,12 @@ void CreatureTextMgr::SendSound(Creature* source, uint32 sound, ChatMsg msgType, void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket* data, ChatMsg msgType, WorldObject const* whisperTarget, CreatureTextRange range, Team team, bool gmOnly) const { - float dist = GetRangeForChatType(msgType); - switch (msgType) { case CHAT_MSG_MONSTER_WHISPER: case CHAT_MSG_RAID_BOSS_WHISPER: { - if (range == TEXT_RANGE_NORMAL)//ignores team and gmOnly + if (range == TEXT_RANGE_NORMAL) // ignores team and gmOnly { if (!whisperTarget || whisperTarget->GetTypeId() != TYPEID_PLAYER) return; @@ -378,6 +389,7 @@ void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket* data, break; } + float dist = GetRangeForChatType(msgType); source->SendMessageToSetInRange(data, dist, true); } @@ -457,18 +469,17 @@ std::string CreatureTextMgr::GetLocalizedChatString(uint32 entry, uint8 textGrou if (groupItr == holderItr->second.end()) return ""; - std::string baseText = groupItr->text; - if (locale == DEFAULT_LOCALE) - return baseText; - if (locale > MAX_LOCALES) - return baseText; + locale = DEFAULT_LOCALE; - LocaleCreatureTextMap::const_iterator locItr = mLocaleTextMap.find(CreatureTextId(entry, uint32(textGroup), id)); - if (locItr == mLocaleTextMap.end()) - return baseText; + std::string baseText = groupItr->text; - ObjectMgr::GetLocaleString(locItr->second.Text, locale, baseText); + if (locale != DEFAULT_LOCALE) + { + LocaleCreatureTextMap::const_iterator locItr = mLocaleTextMap.find(CreatureTextId(entry, uint32(textGroup), id)); + if (locItr != mLocaleTextMap.end()) + ObjectMgr::GetLocaleString(locItr->second.Text, locale, baseText); + } return baseText; } diff --git a/src/server/game/Texts/CreatureTextMgr.h b/src/server/game/Texts/CreatureTextMgr.h index 12236844828..c3bc8966563 100644 --- a/src/server/game/Texts/CreatureTextMgr.h +++ b/src/server/game/Texts/CreatureTextMgr.h @@ -36,6 +36,7 @@ struct CreatureTextEntry Emote emote; uint32 duration; uint32 sound; + uint32 BroadcastTextId; }; enum CreatureTextRange @@ -186,7 +187,7 @@ void CreatureTextMgr::SendChatPacket(WorldObject* source, Builder const& builder case CHAT_MSG_MONSTER_WHISPER: case CHAT_MSG_RAID_BOSS_WHISPER: { - if (range == TEXT_RANGE_NORMAL) //ignores team and gmOnly + if (range == TEXT_RANGE_NORMAL) // ignores team and gmOnly { if (!whisperTarget || whisperTarget->GetTypeId() != TYPEID_PLAYER) return; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 8f2941865fa..e40e2f7e6d1 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1352,6 +1352,10 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading instances..."); sInstanceSaveMgr->LoadInstances(); + TC_LOG_INFO("server.loading", "Loading Broadcast texts..."); + sObjectMgr->LoadBroadcastTexts(); + sObjectMgr->LoadBroadcastTextLocales(); + TC_LOG_INFO("server.loading", "Loading Localization strings..."); uint32 oldMSTime = getMSTime(); sObjectMgr->LoadCreatureLocales(); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index a58dcc82acc..7de093f66ea 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -491,14 +491,15 @@ struct CliCommandHolder CommandFinished* m_commandFinished; CliCommandHolder(void* callbackArg, const char *command, Print* zprint, CommandFinished* commandFinished) - : m_callbackArg(callbackArg), m_print(zprint), m_commandFinished(commandFinished) + : m_callbackArg(callbackArg), m_command(strdup(command)), m_print(zprint), m_commandFinished(commandFinished) { - size_t len = strlen(command)+1; - m_command = new char[len]; - memcpy(m_command, command, len); } - ~CliCommandHolder() { delete[] m_command; } + ~CliCommandHolder() { free(m_command); } + +private: + CliCommandHolder(CliCommandHolder const& right) DELETE_MEMBER; + CliCommandHolder& operator=(CliCommandHolder const& right) DELETE_MEMBER; }; typedef UNORDERED_MAP<uint32, WorldSession*> SessionMap; diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp index 369a8e87289..51eea4c2c6f 100644 --- a/src/server/scripts/Commands/cs_quest.cpp +++ b/src/server/scripts/Commands/cs_quest.cpp @@ -91,13 +91,8 @@ public: // ok, normal (creature/GO starting) quest if (player->CanAddQuest(quest, true)) - { player->AddQuestAndCheckCompletion(quest, NULL); - if (player->CanCompleteQuest(entry)) - player->CompleteQuest(entry); - } - return true; } diff --git a/src/server/scripts/Commands/cs_rbac.cpp b/src/server/scripts/Commands/cs_rbac.cpp index df4ce993433..47fa01837f6 100644 --- a/src/server/scripts/Commands/cs_rbac.cpp +++ b/src/server/scripts/Commands/cs_rbac.cpp @@ -320,7 +320,7 @@ public: handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str());
}
}
- handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_DENIED, command->rbac->GetId(), command->rbac->GetName().c_str());
+ handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_BY_SEC_LEVEL, command->rbac->GetId(), command->rbac->GetName().c_str(), command->rbac->GetSecurityLevel());
rbac::RBACPermissionContainer const& defaultPermissions = sAccountMgr->GetRBACDefaultPermissions(command->rbac->GetSecurityLevel());
if (defaultPermissions.empty())
handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_EMPTY));
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp index b1bc34b0437..eda2dbbcdaa 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp @@ -138,7 +138,7 @@ public: break; case EVENT_CONFLAGRATION: DoCastVictim(SPELL_CONFLAGRATION); - if (me->GetVictim() && me->GetVictim()->HasAura(SPELL_CONFLAGRATION)) + if (me->GetVictim() && me->EnsureVictim()->HasAura(SPELL_CONFLAGRATION)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) me->TauntApply(target); events.ScheduleEvent(EVENT_CONFLAGRATION, 30000); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp index f8e00e4ed74..870e11c215c 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp @@ -200,7 +200,7 @@ public: break; case EVENT_BURNINGADRENALINE_TANK: // have the victim cast the spell on himself otherwise the third effect aura will be applied to Vael instead of the player - me->GetVictim()->CastSpell(me->GetVictim(), SPELL_BURNINGADRENALINE, true); + me->EnsureVictim()->CastSpell(me->GetVictim(), SPELL_BURNINGADRENALINE, true); events.ScheduleEvent(EVENT_BURNINGADRENALINE_TANK, 45000); break; } diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp index 2b50c525f78..7d80d0c20b7 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -24,17 +24,13 @@ Script Data End */ #include "ScriptMgr.h" #include "ScriptedCreature.h" -#include "ScriptedGossip.h" -#include "gnomeregan.h" #include "ScriptedEscortAI.h" +#include "ScriptedGossip.h" #include "Player.h" - -#define GOSSIP_START_EVENT "I am ready to being" +#include "gnomeregan.h" enum BlastmasterEmi { - GOSSIP_TEXT_EMI = 1693, - SAY_BLASTMASTER_0 = 0, SAY_BLASTMASTER_1 = 1, SAY_BLASTMASTER_2 = 2, @@ -93,34 +89,6 @@ public: return GetInstanceAI<npc_blastmaster_emi_shortfuseAI>(creature); } - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - if (npc_escortAI* pEscortAI = CAST_AI(npc_blastmaster_emi_shortfuse::npc_blastmaster_emi_shortfuseAI, creature->AI())) - pEscortAI->Start(true, false, player->GetGUID()); - - creature->setFaction(player->getFaction()); - creature->AI()->SetData(1, 0); - - player->CLOSE_GOSSIP_MENU(); - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) OVERRIDE - { - InstanceScript* instance = creature->GetInstanceScript(); - - if (instance && instance->GetData(TYPE_EVENT) == NOT_STARTED) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(GOSSIP_TEXT_EMI, creature->GetGUID()); - - return true; - } - struct npc_blastmaster_emi_shortfuseAI : public npc_escortAI { npc_blastmaster_emi_shortfuseAI(Creature* creature) : npc_escortAI(creature) @@ -152,6 +120,19 @@ public: } } + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) OVERRIDE + { + if (gossipListId == 0) + { + Start(true, false, player->GetGUID()); + + me->setFaction(player->getFaction()); + SetData(1, 0); + + player->PlayerTalkClass->SendCloseGossip(); + } + } + void NextStep(uint32 uiTimerStep, bool bNextStep = true, uint8 uiPhaseStep = 0) { uiTimer = uiTimerStep; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp index 14cc3083d59..0387d7b776b 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp @@ -191,7 +191,7 @@ public: if (pAttumen->GetVictim()) { pAttumen->GetMotionMaster()->MoveChase(pAttumen->GetVictim()); - pAttumen->SetTarget(pAttumen->GetVictim()->GetGUID()); + pAttumen->SetTarget(pAttumen->EnsureVictim()->GetGUID()); } pAttumen->SetObjectScale(1); } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp index bde326a5c37..92cdb40dc7b 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp @@ -391,8 +391,8 @@ public: if (me->HasUnitState(UNIT_STATE_STUNNED)) // While shifting to phase 2 malchezaar stuns himself return; - if (me->GetUInt64Value(UNIT_FIELD_TARGET) != me->GetVictim()->GetGUID()) - me->SetTarget(me->GetVictim()->GetGUID()); + if (me->GetVictim() && me->GetUInt64Value(UNIT_FIELD_TARGET) != me->EnsureVictim()->GetGUID()) + me->SetTarget(me->EnsureVictim()->GetGUID()); if (phase == 1) { diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index a3d4d6669a3..936bf51e456 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -484,10 +484,10 @@ public: EnterEvadeMode(); return; } - else if (me->GetVictim()->GetTypeId() == TYPEID_PLAYER && me->GetVictim()->HealthBelowPct(10)) + else if (me->GetVictim() && me->EnsureVictim()->GetTypeId() == TYPEID_PLAYER && me->EnsureVictim()->HealthBelowPct(10)) { - me->GetVictim()->CastSpell(me->GetVictim(), 7267, true); // beg - me->GetVictim()->RemoveGameObject(SPELL_DUEL_FLAG, true); + me->EnsureVictim()->CastSpell(me->GetVictim(), 7267, true); // beg + me->EnsureVictim()->RemoveGameObject(SPELL_DUEL_FLAG, true); EnterEvadeMode(); return; } @@ -832,12 +832,12 @@ public: } } - if (!UpdateVictim()) + if (!UpdateVictim() || !me->GetVictim()) return; //ScriptedAI::UpdateAI(diff); //Check if we have a current target - if (me->GetVictim()->GetEntry() == NPC_GHOSTS) + if (me->EnsureVictim()->GetEntry() == NPC_GHOSTS) { if (me->isAttackReady()) { diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp index 46bd5bcbfdc..b57ffa7bc9c 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp @@ -298,7 +298,7 @@ public: Unit* target = (*itr)->getTarget(); if (target && target->GetTypeId() == TYPEID_PLAYER - && target->GetGUID() != me->GetVictim()->GetGUID() + && (!target->GetVictim() || target->GetGUID() != me->EnsureVictim()->GetGUID()) && target->GetPositionZ() > me->GetPositionZ() - 5 && !target->HasAura(AURA_SPECTRAL_EXHAUSTION)) { diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp index e8b112aa1cd..5a2c23d1c0f 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -1255,7 +1255,7 @@ public: if ((victimClass == 0) && me->GetVictim()) { - victimClass = me->GetVictim()->getClass(); + victimClass = me->EnsureVictim()->getClass(); switch (victimClass) { case CLASS_DRUID: diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp index d6657ac0986..d6c67ea2ea6 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp @@ -887,7 +887,8 @@ class boss_fenstalker : public CreatureScript if (volatileinf_timer <= diff) { // core bug - me->GetVictim()->CastSpell(me->GetVictim(), SPELL_VOLATILE_INFECTION, false); + if (me->GetVictim()) + me->EnsureVictim()->CastSpell(me->GetVictim(), SPELL_VOLATILE_INFECTION, false); volatileinf_timer = 12000; } else volatileinf_timer -= diff; diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp index 5bd78006f95..edf3196104e 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -405,7 +405,7 @@ class boss_nalorakk : public CreatureScript if (Mangle_Timer <= diff) { - if (me->GetVictim() && !me->GetVictim()->HasAura(SPELL_MANGLEEFFECT)) + if (me->GetVictim() && !me->EnsureVictim()->HasAura(SPELL_MANGLEEFFECT)) { DoCastVictim(SPELL_MANGLE); Mangle_Timer = 1000; diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp index 9af8eeccc5c..d3f724ad539 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp @@ -249,9 +249,9 @@ class boss_zuljin : public CreatureScript { if (Phase == 1 && !Overpower_Timer) { - uint32 health = me->GetVictim()->GetHealth(); + uint32 health = me->EnsureVictim()->GetHealth(); me->AttackerStateUpdate(me->GetVictim()); - if (me->GetVictim() && health == me->GetVictim()->GetHealth()) + if (me->GetVictim() && health == me->EnsureVictim()->GetHealth()) { DoCastVictim(SPELL_OVERPOWER, false); Overpower_Timer = 5000; @@ -428,7 +428,8 @@ class boss_zuljin : public CreatureScript { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { - TankGUID = me->GetVictim()->GetGUID(); + if (me->GetVictim()) + TankGUID = me->EnsureVictim()->GetGUID(); me->SetSpeed(MOVE_RUN, 5.0f); AttackStart(target); // change victim Claw_Rage_Timer = 0; @@ -477,7 +478,7 @@ class boss_zuljin : public CreatureScript { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { - TankGUID = me->GetVictim()->GetGUID(); + TankGUID = me->EnsureVictim()->GetGUID(); me->SetSpeed(MOVE_RUN, 5.0f); AttackStart(target); // change victim Lynx_Rush_Timer = 0; diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp index bb2a17704ed..e13445bc59b 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp @@ -238,7 +238,7 @@ class boss_mandokir : public CreatureScript events.ScheduleEvent(EVENT_OVERPOWER, urand(6000, 12000)); break; case EVENT_MORTAL_STRIKE: - if (me->GetVictim() && me->GetVictim()->HealthBelowPct(50)) + if (me->GetVictim() && me->EnsureVictim()->HealthBelowPct(50)) DoCastVictim(SPELL_MORTAL_STRIKE, true); events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(12000, 18000)); break; diff --git a/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp b/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp index 6cfef015450..8dd8d8a2c65 100644 --- a/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp +++ b/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp @@ -100,7 +100,7 @@ public: if (me->IsInCombat() && me->GetVictim()) { - if (Player* player = me->GetVictim()->ToPlayer()) + if (Player* player = me->EnsureVictim()->ToPlayer()) { if (player->GetTeam() == HORDE) { diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp index cbace6df028..bfe4db137f3 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp @@ -1351,7 +1351,7 @@ public: if (MoveTimer <= diff) { float x, y, z; - me->GetVictim()->GetPosition(x, y, z); + me->EnsureVictim()->GetPosition(x, y, z); me->GetMotionMaster()->MovePoint(0, x, y, z+Zpos); Zpos -= 1.0f; if (Zpos <= 0) diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp index a12a400ea8e..04e5f031589 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp @@ -156,9 +156,12 @@ class boss_ayamiss : public CreatureScript _phase = PHASE_GROUND; SetCombatMovement(true); me->SetCanFly(false); - Position VictimPos; - me->GetVictim()->GetPosition(&VictimPos); - me->GetMotionMaster()->MovePoint(POINT_GROUND, VictimPos); + if (me->GetVictim()) + { + Position VictimPos; + me->EnsureVictim()->GetPosition(&VictimPos); + me->GetMotionMaster()->MovePoint(POINT_GROUND, VictimPos); + } DoResetThreat(); events.ScheduleEvent(EVENT_LASH, urand(5000, 8000)); events.ScheduleEvent(EVENT_TRASH, urand(3000, 6000)); diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp index 44c70075a94..20100dfc5dd 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp @@ -272,7 +272,8 @@ class npc_glob_of_viscidus : public CreatureScript if (Viscidus->IsAlive() && Viscidus->GetHealthPct() < 5.0f) { Viscidus->SetVisible(true); - Viscidus->GetVictim()->Kill(Viscidus); + if (Viscidus->GetVictim()) + Viscidus->EnsureVictim()->Kill(Viscidus); } else { diff --git a/src/server/scripts/Kalimdor/zone_tanaris.cpp b/src/server/scripts/Kalimdor/zone_tanaris.cpp index 3ced3c7115d..013e6099457 100644 --- a/src/server/scripts/Kalimdor/zone_tanaris.cpp +++ b/src/server/scripts/Kalimdor/zone_tanaris.cpp @@ -123,7 +123,7 @@ public: { if (SendItemTimer <= diff) { - if (me->GetVictim()->GetTypeId() == TYPEID_PLAYER) + if (me->GetVictim() && me->EnsureVictim()->GetTypeId() == TYPEID_PLAYER) SendItem(me->GetVictim()); SendItemTimer = 5000; } else SendItemTimer -= diff; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp index c0e49fa43fb..9e02bb9bcf6 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp @@ -586,7 +586,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript case 5060: case 5070: case 5080: - return NPC_LICH_KING_1; + return NPC_LICH_KING; break; case 120: case 122: diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp index fdefde10b4f..6e835345d8b 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp @@ -275,7 +275,7 @@ class boss_lich_king_toc : public CreatureScript if (!_instance) return; - if (_instance->GetData(TYPE_EVENT_NPC) != NPC_LICH_KING_1) + if (_instance->GetData(TYPE_EVENT_NPC) != NPC_LICH_KING) return; _updateTimer = _instance->GetData(TYPE_EVENT_TIMER); @@ -764,7 +764,7 @@ class npc_tirion_toc : public CreatureScript case 5005: _updateTimer = 8*IN_MILLISECONDS; _instance->SetData(TYPE_EVENT, 5010); - me->SummonCreature(NPC_LICH_KING_1, ToCCommonLoc[2].GetPositionX(), ToCCommonLoc[2].GetPositionY(), ToCCommonLoc[2].GetPositionZ(), 5); + me->SummonCreature(NPC_LICH_KING, ToCCommonLoc[2].GetPositionX(), ToCCommonLoc[2].GetPositionY(), ToCCommonLoc[2].GetPositionZ(), 5); break; case 5020: Talk(SAY_STAGE_4_03); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h index 17e4f2869c6..562105c0866 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h @@ -184,8 +184,7 @@ enum CreatureIds NPC_FIZZLEBANG = 35458, NPC_GARROSH = 34995, NPC_VARIAN = 34990, - NPC_LICH_KING_0 = 16980, - NPC_LICH_KING_1 = 35877, + NPC_LICH_KING = 35877, NPC_THRALL = 34994, NPC_PROUDMOORE = 34992, diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index bbf3e8afc0f..197a4fc5414 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -374,7 +374,7 @@ class boss_blood_queen_lana_thel : public CreatureScript // both spells have SPELL_ATTR5_SINGLE_TARGET_SPELL, no manual removal needed newOfftank->CastSpell(me->GetVictim(), SPELL_BLOOD_MIRROR_DAMAGE, true); - me->GetVictim()->CastSpell(newOfftank, SPELL_BLOOD_MIRROR_DUMMY, true); + me->EnsureVictim()->CastSpell(newOfftank, SPELL_BLOOD_MIRROR_DUMMY, true); DoCastVictim(SPELL_BLOOD_MIRROR_VISUAL); if (Is25ManRaid() && newOfftank->GetQuestStatus(QUEST_BLOOD_INFUSION) == QUEST_STATUS_INCOMPLETE && newOfftank->HasAura(SPELL_UNSATED_CRAVING) && !newOfftank->HasAura(SPELL_THIRST_QUENCHED) && diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index 6b81bcc46a5..f80afd055e9 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -890,7 +890,7 @@ class npc_darnavan : public CreatureScript if (me->HasUnitState(UNIT_STATE_CASTING)) return; - if (_canShatter && me->GetVictim() && me->GetVictim()->IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL)) + if (_canShatter && me->GetVictim() && me->EnsureVictim()->IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL)) { DoCastVictim(SPELL_SHATTERING_THROW); _canShatter = false; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp index d33d218fab9..e586feb1070 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -136,7 +136,7 @@ public: } } - if (me->GetVictim() && me->GetVictim()->GetEntry() == NPC_ZOMBIE) + if (me->GetVictim() && me->EnsureVictim()->GetEntry() == NPC_ZOMBIE) { if (me->IsWithinMeleeRange(me->GetVictim())) { diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp index 8cc198a0d84..0a2ebb549f8 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp @@ -230,11 +230,14 @@ class boss_urom : public CreatureScript { if (arcaneExplosionTimer <= diff) { - Position pos; - me->GetVictim()->GetPosition(&pos); - - me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); - me->GetMotionMaster()->MoveChase(me->GetVictim()); + if (me->GetVictim()) + { + Position pos; + me->EnsureVictim()->GetPosition(&pos); + + me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); + me->GetMotionMaster()->MoveChase(me->GetVictim()); + } me->SetWalk(true); Talk(EMOTE_ARCANE_EXPLOSION); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index 578a51fa1f8..ce6e99401a5 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -199,10 +199,13 @@ class npc_flash_freeze : public CreatureScript void UpdateAI(uint32 diff) OVERRIDE { - if (!UpdateVictim() || me->GetVictim()->HasAura(SPELL_BLOCK_OF_ICE) || me->GetVictim()->HasAura(SPELL_FLASH_FREEZE_HELPER)) + if (!UpdateVictim() + || !me->GetVictim() + || me->EnsureVictim()->HasAura(SPELL_BLOCK_OF_ICE) + || me->EnsureVictim()->HasAura(SPELL_FLASH_FREEZE_HELPER)) return; - if (me->GetVictim()->GetGUID() != targetGUID || instance->GetBossState(BOSS_HODIR) != IN_PROGRESS) + if (me->EnsureVictim()->GetGUID() != targetGUID || instance->GetBossState(BOSS_HODIR) != IN_PROGRESS) me->DespawnOrUnsummon(); if (checkDespawnTimer <= diff) diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index d74aecb9b25..b3d59c390c0 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -2074,15 +2074,15 @@ public: void UpdateAI(uint32 /*diff*/) OVERRIDE { - if (!UpdateVictim()) + if (!UpdateVictim() || !me->GetVictim()) return; - if (me->GetVictim()->GetTypeId() != TYPEID_PLAYER) + if (me->EnsureVictim()->GetTypeId() != TYPEID_PLAYER) return; // Only cast the below on players. - if (!me->GetVictim()->HasAura(SPELL_PARALYZE)) + if (!me->EnsureVictim()->HasAura(SPELL_PARALYZE)) { - TargetGUID = me->GetVictim()->GetGUID(); + TargetGUID = me->EnsureVictim()->GetGUID(); me->AddThreat(me->GetVictim(), 10000000.0f); DoCastVictim(SPELL_PURPLE_BEAM, true); DoCastVictim(SPELL_PARALYZE, true); @@ -2154,8 +2154,8 @@ public: { if (me->isAttackReady() && me->IsWithinMeleeRange(me->GetVictim())) { - if (!me->GetVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND) - && !me->GetVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND2)) + if (!me->EnsureVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND) + && !me->EnsureVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND2)) { if (Creature* illidan = Unit::GetCreature((*me), IllidanGUID))// summon only in 1. phase if (CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->Phase == PHASE_NORMAL) diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp index d92d8aaf5db..ed742a56ecd 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp @@ -668,22 +668,22 @@ public: void UpdateAI(uint32 diff) OVERRIDE { //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim() || !me->GetVictim()) return; if (!CheckedAggro) { - AggroTargetGUID = me->GetVictim()->GetGUID(); + AggroTargetGUID = me->EnsureVictim()->GetGUID(); CheckedAggro = true; } if (CheckTankTimer <= diff) { - if (me->GetVictim()->GetGUID() != AggroTargetGUID) + if (me->EnsureVictim()->GetGUID() != AggroTargetGUID) { Talk(ANGER_SAY_BEFORE); DoCast(me, SPELL_SELF_SEETHE, true); - AggroTargetGUID = me->GetVictim()->GetGUID(); + AggroTargetGUID = me->EnsureVictim()->GetGUID(); } CheckTankTimer = 2000; } else CheckTankTimer -= diff; diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp index 9055bb1862d..3cb9ca26599 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp @@ -626,7 +626,8 @@ public: { DoCastVictim(SPELL_TIDAL_SURGE); // Hacky way to do it - won't trigger elseways - me->GetVictim()->CastSpell(me->GetVictim(), SPELL_TIDAL_SURGE_FREEZE, true); + if (me->GetVictim()) + me->EnsureVictim()->CastSpell(me->GetVictim(), SPELL_TIDAL_SURGE_FREEZE, true); TidalSurge_Timer = 15000+rand()%5000; } else TidalSurge_Timer -= diff; diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp index f9370b44c20..4df431b91ac 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp @@ -135,10 +135,10 @@ public: void UpdateAI(uint32 diff) OVERRIDE { //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim() || !me->GetVictim()) return; - if (me->GetVictim()->GetGUID() != victimGUID) + if (me->EnsureVictim()->GetGUID() != victimGUID) { DoModifyThreatPercent(me->GetVictim(), -100); Unit* owner = Unit::GetUnit(*me, victimGUID); @@ -519,7 +519,7 @@ public: for (ThreatContainer::StorageType::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) { Unit* tempTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (tempTarget && tempTarget->GetTypeId() == TYPEID_PLAYER && tempTarget->GetGUID() != me->GetVictim()->GetGUID() && TargetList.size()<5) + if (tempTarget && tempTarget->GetTypeId() == TYPEID_PLAYER && tempTarget->GetGUID() != me->EnsureVictim()->GetGUID() && TargetList.size()<5) TargetList.push_back(tempTarget); } //SpellInfo* spell = GET_SPELL(SPELL_INSIDIOUS_WHISPER); diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp index 7b83fa7009d..78a7d71732a 100644 --- a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp +++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp @@ -93,7 +93,7 @@ class npc_warp_splinter_treant : public CreatureScript void UpdateAI(uint32 diff) OVERRIDE { - if (!UpdateVictim()) + if (!UpdateVictim() || !me->GetVictim()) { if (WarpGuid && check_Timer <= diff) { @@ -115,7 +115,7 @@ class npc_warp_splinter_treant : public CreatureScript return; } - if (me->GetVictim()->GetGUID() != WarpGuid) + if (me->EnsureVictim()->GetGUID() != WarpGuid) DoMeleeAttackIfReady(); } }; diff --git a/src/server/scripts/Pet/pet_hunter.cpp b/src/server/scripts/Pet/pet_hunter.cpp index 8a0b78b5478..87458fdc4dc 100644 --- a/src/server/scripts/Pet/pet_hunter.cpp +++ b/src/server/scripts/Pet/pet_hunter.cpp @@ -93,10 +93,10 @@ class npc_pet_hunter_snake_trap : public CreatureScript void UpdateAI(uint32 diff) OVERRIDE { - if (!UpdateVictim()) + if (!UpdateVictim() || !me->GetVictim()) return; - if (me->GetVictim()->HasBreakableByDamageCrowdControlAura(me)) + if (me->EnsureVictim()->HasBreakableByDamageCrowdControlAura(me)) { me->InterruptNonMeleeSpells(false); return; diff --git a/src/server/shared/DataStores/DBCFileLoader.h b/src/server/shared/DataStores/DBCFileLoader.h index c5194d20530..f26e07f8b50 100644 --- a/src/server/shared/DataStores/DBCFileLoader.h +++ b/src/server/shared/DataStores/DBCFileLoader.h @@ -106,5 +106,8 @@ class DBCFileLoader uint32 *fieldsOffset; unsigned char *data; unsigned char *stringTable; + + DBCFileLoader(DBCFileLoader const& right) DELETE_MEMBER; + DBCFileLoader& operator=(DBCFileLoader const& right) DELETE_MEMBER; }; #endif diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h index 78f7bb28580..b337fb4be59 100644 --- a/src/server/shared/DataStores/DBCStore.h +++ b/src/server/shared/DataStores/DBCStore.h @@ -63,6 +63,10 @@ struct SqlDbc } } } + +private: + SqlDbc(SqlDbc const& right) DELETE_MEMBER; + SqlDbc& operator=(SqlDbc const& right) DELETE_MEMBER; }; template<class T> @@ -291,6 +295,9 @@ class DBCStorage T* dataTable; StringPoolList stringPoolList; + + DBCStorage(DBCStorage const& right) DELETE_MEMBER; + DBCStorage& operator=(DBCStorage const& right) DELETE_MEMBER; }; #endif diff --git a/src/server/shared/Database/DatabaseWorker.h b/src/server/shared/Database/DatabaseWorker.h index 14e92924ed2..734ec790027 100644 --- a/src/server/shared/Database/DatabaseWorker.h +++ b/src/server/shared/Database/DatabaseWorker.h @@ -18,6 +18,7 @@ #ifndef _WORKERTHREAD_H #define _WORKERTHREAD_H +#include "Define.h" #include <ace/Task.h> #include <ace/Activation_Queue.h> @@ -33,9 +34,11 @@ class DatabaseWorker : protected ACE_Task_Base int wait() { return ACE_Task_Base::wait(); } private: - DatabaseWorker() : ACE_Task_Base() { } ACE_Activation_Queue* m_queue; MySQLConnection* m_conn; + + DatabaseWorker(DatabaseWorker const& right) DELETE_MEMBER; + DatabaseWorker& operator=(DatabaseWorker const& right) DELETE_MEMBER; }; #endif diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h index e2ebda9e8ae..c60458323f7 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -49,8 +49,7 @@ class DatabaseWorkerPool { public: /* Activity state */ - DatabaseWorkerPool() : - _queue(new ACE_Activation_Queue()) + DatabaseWorkerPool() : _queue(new ACE_Activation_Queue()), _connectionInfo(NULL) { memset(_connectionCount, 0, sizeof(_connectionCount)); _connections.resize(IDX_SIZE); @@ -66,7 +65,7 @@ class DatabaseWorkerPool bool Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads) { bool res = true; - _connectionInfo = MySQLConnectionInfo(infoString); + _connectionInfo = new MySQLConnectionInfo(infoString); TC_LOG_INFO("sql.driver", "Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.", GetDatabaseName(), async_threads, synch_threads); @@ -75,7 +74,7 @@ class DatabaseWorkerPool _connections[IDX_ASYNC].resize(async_threads); for (uint8 i = 0; i < async_threads; ++i) { - T* t = new T(_queue, _connectionInfo); + T* t = new T(_queue, *_connectionInfo); res &= t->Open(); if (res) // only check mysql version if connection is valid WPFatal(mysql_get_server_version(t->GetHandle()) >= MIN_MYSQL_SERVER_VERSION, "TrinityCore does not support MySQL versions below 5.1"); @@ -87,7 +86,7 @@ class DatabaseWorkerPool _connections[IDX_SYNCH].resize(synch_threads); for (uint8 i = 0; i < synch_threads; ++i) { - T* t = new T(_connectionInfo); + T* t = new T(*_connectionInfo); res &= t->Open(); _connections[IDX_SYNCH][i] = t; ++_connectionCount[IDX_SYNCH]; @@ -134,6 +133,9 @@ class DatabaseWorkerPool delete _queue; TC_LOG_INFO("sql.driver", "All connections on DatabasePool '%s' closed.", GetDatabaseName()); + + delete _connectionInfo; + _connectionInfo = NULL; } /** @@ -507,7 +509,7 @@ class DatabaseWorkerPool char const* GetDatabaseName() const { - return _connectionInfo.database.c_str(); + return _connectionInfo->database.c_str(); } private: @@ -521,7 +523,7 @@ class DatabaseWorkerPool ACE_Activation_Queue* _queue; //! Queue shared by async worker threads. std::vector< std::vector<T*> > _connections; uint32 _connectionCount[2]; //! Counter of MySQL connections; - MySQLConnectionInfo _connectionInfo; + MySQLConnectionInfo* _connectionInfo; }; #endif diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp index 644d3b330fb..78fd859ea8f 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp @@ -25,7 +25,7 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_SEL_QUEST_POOLS, "SELECT entry, pool_entry FROM pool_quest", CONNECTION_SYNCH); PrepareStatement(WORLD_DEL_CRELINKED_RESPAWN, "DELETE FROM linked_respawn WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_REP_CREATURE_LINKED_RESPAWN, "REPLACE INTO linked_respawn (guid, linkedGuid) VALUES (?, ?)", CONNECTION_ASYNC); - PrepareStatement(WORLD_SEL_CREATURE_TEXT, "SELECT entry, groupid, id, text, type, language, probability, emote, duration, sound FROM creature_text", CONNECTION_SYNCH); + PrepareStatement(WORLD_SEL_CREATURE_TEXT, "SELECT entry, groupid, id, text, type, language, probability, emote, duration, sound, BroadcastTextID FROM creature_text", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_SMART_SCRIPTS, "SELECT entryorguid, source_type, id, link, event_type, event_phase_mask, event_chance, event_flags, event_param1, event_param2, event_param3, event_param4, action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6, target_type, target_param1, target_param2, target_param3, target_x, target_y, target_z, target_o FROM smart_scripts ORDER BY entryorguid, source_type, id, link", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_SMARTAI_WP, "SELECT entry, pointid, position_x, position_y, position_z FROM waypoints ORDER BY entry, pointid", CONNECTION_SYNCH); PrepareStatement(WORLD_DEL_GAMEOBJECT, "DELETE FROM gameobject WHERE guid = ?", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/MySQLConnection.h b/src/server/shared/Database/MySQLConnection.h index 161f459a7ad..e55e3dfc23a 100644 --- a/src/server/shared/Database/MySQLConnection.h +++ b/src/server/shared/Database/MySQLConnection.h @@ -38,8 +38,7 @@ enum ConnectionFlags struct MySQLConnectionInfo { - MySQLConnectionInfo() { } - MySQLConnectionInfo(const std::string& infoString) + explicit MySQLConnectionInfo(std::string const& infoString) { Tokenizer tokens(infoString, ';'); @@ -132,6 +131,9 @@ class MySQLConnection MySQLConnectionInfo& m_connectionInfo; //! Connection info (used for logging) ConnectionFlags m_connectionFlags; //! Connection flags (for preparing relevant statements) ACE_Thread_Mutex m_Mutex; + + MySQLConnection(MySQLConnection const& right) DELETE_MEMBER; + MySQLConnection& operator=(MySQLConnection const& right) DELETE_MEMBER; }; #endif diff --git a/src/server/shared/Database/PreparedStatement.h b/src/server/shared/Database/PreparedStatement.h index 6a4d03bfb4d..9ccd16e3d5c 100644 --- a/src/server/shared/Database/PreparedStatement.h +++ b/src/server/shared/Database/PreparedStatement.h @@ -101,6 +101,9 @@ class PreparedStatement MySQLPreparedStatement* m_stmt; uint32 m_index; std::vector<PreparedStatementData> statement_data; //- Buffer of parameters, not tied to MySQL in any way yet + + PreparedStatement(PreparedStatement const& right) DELETE_MEMBER; + PreparedStatement& operator=(PreparedStatement const& right) DELETE_MEMBER; }; //- Class of which the instances are unique per MySQLConnection @@ -145,6 +148,9 @@ class MySQLPreparedStatement uint32 m_paramCount; std::vector<bool> m_paramsSet; MYSQL_BIND* m_bind; + + MySQLPreparedStatement(MySQLPreparedStatement const& right) DELETE_MEMBER; + MySQLPreparedStatement& operator=(MySQLPreparedStatement const& right) DELETE_MEMBER; }; typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture; diff --git a/src/server/shared/Database/QueryResult.h b/src/server/shared/Database/QueryResult.h index 74320aeba19..a09506c6621 100644 --- a/src/server/shared/Database/QueryResult.h +++ b/src/server/shared/Database/QueryResult.h @@ -55,6 +55,9 @@ class ResultSet void CleanUp(); MYSQL_RES* _result; MYSQL_FIELD* _fields; + + ResultSet(ResultSet const& right) DELETE_MEMBER; + ResultSet& operator=(ResultSet const& right) DELETE_MEMBER; }; typedef Trinity::AutoPtr<ResultSet, ACE_Thread_Mutex> QueryResult; @@ -100,6 +103,8 @@ class PreparedResultSet void CleanUp(); bool _NextRow(); + PreparedResultSet(PreparedResultSet const& right) DELETE_MEMBER; + PreparedResultSet& operator=(PreparedResultSet const& right) DELETE_MEMBER; }; typedef Trinity::AutoPtr<PreparedResultSet, ACE_Thread_Mutex> PreparedQueryResult; diff --git a/src/server/shared/Database/SQLOperation.h b/src/server/shared/Database/SQLOperation.h index 2c404c131ae..eb32b60c74d 100644 --- a/src/server/shared/Database/SQLOperation.h +++ b/src/server/shared/Database/SQLOperation.h @@ -69,6 +69,10 @@ class SQLOperation : public ACE_Method_Request virtual void SetConnection(MySQLConnection* con) { m_conn = con; } MySQLConnection* m_conn; + + private: + SQLOperation(SQLOperation const& right) DELETE_MEMBER; + SQLOperation& operator=(SQLOperation const& right) DELETE_MEMBER; }; #endif diff --git a/src/server/shared/Define.h b/src/server/shared/Define.h index 27973694818..1534e7e6354 100644 --- a/src/server/shared/Define.h +++ b/src/server/shared/Define.h @@ -73,9 +73,11 @@ #if COMPILER_HAS_CPP11_SUPPORT # define OVERRIDE override # define FINAL final +# define DELETE_MEMBER = delete #else # define OVERRIDE # define FINAL +# define DELETE_MEMBER #endif //COMPILER_HAS_CPP11_SUPPORT #define UI64FMTD ACE_UINT64_FORMAT_SPECIFIER diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 33d33519c8f..bc46b87fa27 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -85,6 +85,8 @@ class ByteBuffer { } + virtual ~ByteBuffer() { } + void clear() { _storage.clear(); diff --git a/src/server/shared/Threading/Callback.h b/src/server/shared/Threading/Callback.h index b074ff49c3c..c3717228870 100644 --- a/src/server/shared/Threading/Callback.h +++ b/src/server/shared/Threading/Callback.h @@ -109,6 +109,9 @@ class QueryCallback ACE_Future<Result> _result; ParamType _param; uint8 _stage; + + QueryCallback(QueryCallback const& right) DELETE_MEMBER; + QueryCallback& operator=(QueryCallback const& right) DELETE_MEMBER; }; template <typename Result, typename ParamType1, typename ParamType2, bool chain = false> @@ -201,6 +204,9 @@ class QueryCallback_2 ParamType1 _param_1; ParamType2 _param_2; uint8 _stage; + + QueryCallback_2(QueryCallback_2 const& right) DELETE_MEMBER; + QueryCallback_2& operator=(QueryCallback_2 const& right) DELETE_MEMBER; }; #endif
\ No newline at end of file diff --git a/src/tools/map_extractor/adt.h b/src/tools/map_extractor/adt.h index 5cb45d488d5..10894c7a697 100644 --- a/src/tools/map_extractor/adt.h +++ b/src/tools/map_extractor/adt.h @@ -40,6 +40,8 @@ enum LiquidType #define ADT_CELL_SIZE 8 #define ADT_GRID_SIZE (ADT_CELLS_PER_GRID*ADT_CELL_SIZE) +#pragma pack(push, 1) + // // Adt file height map chunk // @@ -304,4 +306,6 @@ public: adt_MHDR *a_grid; }; +#pragma pack(pop) + #endif diff --git a/src/tools/map_extractor/dbcfile.h b/src/tools/map_extractor/dbcfile.h index 526c553e0f0..9e2e6670f89 100644 --- a/src/tools/map_extractor/dbcfile.h +++ b/src/tools/map_extractor/dbcfile.h @@ -82,6 +82,8 @@ public: friend class DBCFile; friend class DBCFile::Iterator; + + Record& operator=(Record const& right); }; /** Iterator that iterates over records */ @@ -111,6 +113,8 @@ public: } private: Record record; + + Iterator& operator=(Iterator const& right); }; // Get record by id diff --git a/src/tools/map_extractor/loadlib/loadlib.h b/src/tools/map_extractor/loadlib/loadlib.h index 724c41ef3c9..39f800d9b4c 100644 --- a/src/tools/map_extractor/loadlib/loadlib.h +++ b/src/tools/map_extractor/loadlib/loadlib.h @@ -47,6 +47,8 @@ typedef uint8_t uint8; #define FILE_FORMAT_VERSION 18 +#pragma pack(push, 1) + union u_map_fcc { char fcc_txt[4]; @@ -80,4 +82,7 @@ public: bool loadFile(char *filename, bool log = true); virtual void free(); }; + +#pragma pack(pop) + #endif diff --git a/src/tools/map_extractor/wdt.h b/src/tools/map_extractor/wdt.h index a55598105b3..9b7fc53cb34 100644 --- a/src/tools/map_extractor/wdt.h +++ b/src/tools/map_extractor/wdt.h @@ -25,6 +25,8 @@ //************************************************************************************** #define WDT_MAP_SIZE 64 +#pragma pack(push, 1) + class wdt_MWMO{ union{ uint32 fcc; @@ -83,4 +85,6 @@ public: wdt_MWMO *wmo; }; +#pragma pack(pop) + #endif
\ No newline at end of file diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index 246b448380a..c792524eec1 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -159,7 +159,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) ADT.read(buf, size); char* p=buf; int q = 0; - WmoInstansName = new string[size]; + WmoInstansName = new std::string[size]; while (p<buf+size) { char* s = GetPlainName(p); diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h index aafcb46ce84..ac04074375f 100644 --- a/src/tools/vmap4_extractor/adtfile.h +++ b/src/tools/vmap4_extractor/adtfile.h @@ -113,14 +113,14 @@ private: //size_t mcnk_offsets[256], mcnk_sizes[256]; MPQFile ADT; //mcell Mcell; - string Adtfilename; + std::string Adtfilename; public: ADTFile(char* filename); ~ADTFile(); int nWMO; int nMDX; - string* WmoInstansName; - string* ModelInstansName; + std::string* WmoInstansName; + std::string* ModelInstansName; bool init(uint32 map_num, uint32 tileX, uint32 tileY); //void LoadMapChunks(); diff --git a/src/tools/vmap4_extractor/loadlib/loadlib.h b/src/tools/vmap4_extractor/loadlib/loadlib.h index 1b44d13a9d3..b26d39fbbf8 100644 --- a/src/tools/vmap4_extractor/loadlib/loadlib.h +++ b/src/tools/vmap4_extractor/loadlib/loadlib.h @@ -47,6 +47,8 @@ typedef uint8_t uint8; #define FILE_FORMAT_VERSION 18 +#pragma pack(push, 1) + // // File version chunk // @@ -74,4 +76,7 @@ public: bool loadFile(char *filename, bool log = true); virtual void free(); }; + +#pragma pack(pop) + #endif diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index 0f1f0772bd3..a5bb7d518e8 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -67,6 +67,8 @@ struct WMOLiquidHeader short type; }; +#pragma pack(push, 1) + struct WMOLiquidVert { uint16 unk1; @@ -74,6 +76,8 @@ struct WMOLiquidVert float height; }; +#pragma pack(pop) + class WMOGroup { private: |