diff options
Diffstat (limited to 'src/server')
68 files changed, 1156 insertions, 736 deletions
diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp index 81b97f5f352..62abc31831a 100644 --- a/src/server/collision/Management/VMapManager2.cpp +++ b/src/server/collision/Management/VMapManager2.cpp @@ -245,7 +245,7 @@ namespace VMAP          return false;      } -    WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */) +    WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename)      {          //! Critical section, thread safe access to iLoadedModelFiles          TRINITY_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock); @@ -261,7 +261,6 @@ namespace VMAP                  return NULL;              }              sLog->outDebug(LOG_FILTER_MAPS, "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str()); -            worldmodel->Flags = flags;              model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;              model->second.setModel(worldmodel);          } diff --git a/src/server/collision/Management/VMapManager2.h b/src/server/collision/Management/VMapManager2.h index 4b66a2e9fc7..1fba108388a 100755 --- a/src/server/collision/Management/VMapManager2.h +++ b/src/server/collision/Management/VMapManager2.h @@ -103,7 +103,7 @@ namespace VMAP              bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;              bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const; -            WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags = 0); +            WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename);              void releaseModelInstance(const std::string& filename);              // what's the use of this? o.O diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp index f94f9bbf52b..f4a3f1c7b30 100644 --- a/src/server/collision/Maps/MapTree.cpp +++ b/src/server/collision/Maps/MapTree.cpp @@ -309,7 +309,7 @@ namespace VMAP  #endif              if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn))              { -                WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags); +                WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);                  sLog->outDebug(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading %s", spawn.name.c_str());                  if (model)                  { @@ -380,7 +380,7 @@ namespace VMAP                  if (result)                  {                      // acquire model instance -                    WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags); +                    WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);                      if (!model)                          sLog->outError("StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY); diff --git a/src/server/collision/Models/WorldModel.cpp b/src/server/collision/Models/WorldModel.cpp index cda34510058..d4b08dde5dd 100644 --- a/src/server/collision/Models/WorldModel.cpp +++ b/src/server/collision/Models/WorldModel.cpp @@ -421,9 +421,6 @@ namespace VMAP      bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const      { -        // M2 models are not taken into account for LoS calculation -        if (Flags & MOD_M2) -            return false;          // small M2 workaround, maybe better make separate class with virtual intersection funcs          // in any case, there's no need to use a bound tree if we only have one submodel          if (groupModels.size() == 1) diff --git a/src/server/collision/Models/WorldModel.h b/src/server/collision/Models/WorldModel.h index dbaccb58573..ebf828e4935 100755 --- a/src/server/collision/Models/WorldModel.h +++ b/src/server/collision/Models/WorldModel.h @@ -113,7 +113,6 @@ namespace VMAP              bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const;              bool writeFile(const std::string &filename);              bool readFile(const std::string &filename); -            uint32 Flags;          protected:              uint32 RootWMOID;              std::vector<GroupModel> groupModels; diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 30ebd06745f..eedba4d8b7e 100755 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -174,7 +174,7 @@ void PetAI::UpdateAI(const uint32 diff)                      if (spell->CanAutoCast(target))                      { -                        targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(target, spell)); +                        targetSpellStore.push_back(std::make_pair(target, spell));                          spellUsed = true;                          break;                      } @@ -186,7 +186,7 @@ void PetAI::UpdateAI(const uint32 diff)              {                  Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);                  if (spell->CanAutoCast(me->getVictim())) -                    targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(me->getVictim(), spell)); +                    targetSpellStore.push_back(std::make_pair(me->getVictim(), spell));                  else                      delete spell;              } diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index c8818f84e5b..9c236cbd039 100755 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -25,6 +25,7 @@  #include "Log.h"  #include "MapReference.h"  #include "Player.h" +#include "CreatureTextMgr.h"  //Disable CreatureAI when charmed  void CreatureAI::OnCharmed(bool /*apply*/) diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index dafd3e4e137..423b00291e7 100755 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -19,9 +19,9 @@  #ifndef TRINITY_CREATUREAI_H  #define TRINITY_CREATUREAI_H +#include "Creature.h"  #include "UnitAI.h"  #include "Common.h" -#include "CreatureTextMgr.h"  class WorldObject;  class Unit; diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index e82b35ec87a..c2501199f77 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -23,7 +23,6 @@  #include "CreatureAI.h"  #include "Unit.h"  #include "ConditionMgr.h" -#include "CreatureTextMgr.h"  #include "Spell.h"  #include "SmartScript.h" diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 67d26ea06dd..0523f59da5d 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -33,6 +33,47 @@  #include "Group.h"  #include "Vehicle.h"  #include "ScriptedGossip.h" +#include "CreatureTextMgr.h" + +class TrinityStringTextBuilder +{ +    public: +        TrinityStringTextBuilder(WorldObject* obj, ChatMsg msgtype, int32 id, uint32 language, uint64 targetGUID) +            : _source(obj), _msgType(msgtype), _textId(id), _language(language), _targetGUID(targetGUID) +        { +        } + +        size_t operator()(WorldPacket* data, LocaleConstant locale) const +        { +            std::string text = sObjectMgr->GetTrinityString(_textId, locale); +            char const* localizedName = _source->GetNameForLocaleIdx(locale); + +            *data << uint8(_msgType); +            *data << uint32(_language); +            *data << uint64(_source->GetGUID()); +            *data << uint32(1);                                      // 2.1.0 +            *data << uint32(strlen(localizedName)+1); +            *data << localizedName; +            size_t whisperGUIDpos = data->wpos(); +            *data << uint64(_targetGUID);                           // Unit Target +            if (_targetGUID && !IS_PLAYER_GUID(_targetGUID)) +            { +                *data << uint32(1);                                  // target name length +                *data << uint8(0);                                   // target name +            } +            *data << uint32(text.length() + 1); +            *data << text; +            *data << uint8(0);                                       // ChatTag + +            return whisperGUIDpos; +        } + +        WorldObject* _source; +        ChatMsg _msgType; +        int32 _textId; +        uint32 _language; +        uint64 _targetGUID; +};  SmartScript::SmartScript()  { @@ -695,7 +736,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u              me->DoFleeToGetAssistance();              if (e.action.flee.withEmote) -                sCreatureTextMgr->SendChatString(me, sObjectMgr->GetTrinityStringForDBCLocale(LANG_FLEE), CHAT_MSG_MONSTER_EMOTE); +            { +                TrinityStringTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, LANG_FLEE, LANG_UNIVERSAL, 0); +                sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE); +            }              sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature %u DoFleeToGetAssistance", me->GetGUIDLow());              break;          } @@ -1329,10 +1373,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u                  target = targets->front();              } -            if(!target) -                me->GetMotionMaster()->MovePoint(0, e.target.x, e.target.y, e.target.z); +            if (!target) +                me->GetMotionMaster()->MovePoint(e.action.MoveToPos.pointId, e.target.x, e.target.y, e.target.z);              else -                me->GetMotionMaster()->MovePoint(0, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); +                me->GetMotionMaster()->MovePoint(e.action.MoveToPos.pointId, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());              break;          }          case SMART_ACTION_RESPAWN_TARGET: diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index f7524582ab7..faba3c05394 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -23,7 +23,6 @@  #include "CreatureAI.h"  #include "Unit.h"  #include "ConditionMgr.h" -#include "CreatureTextMgr.h"  #include "Spell.h"  #include "GridNotifiers.h" diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 3fc3f233b4b..fe2a89de9aa 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -27,6 +27,7 @@  #include "InstanceScript.h"  #include "ScriptedCreature.h"  #include "GameEventMgr.h" +#include "CreatureTextMgr.h"  #include "SmartScriptMgr.h" diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 0d182e1beb3..007b57b52d7 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -23,7 +23,6 @@  #include "CreatureAI.h"  #include "Unit.h"  #include "ConditionMgr.h" -#include "CreatureTextMgr.h"  #include "Spell.h"  //#include "SmartScript.h" @@ -442,7 +441,7 @@ enum SMART_ACTION      SMART_ACTION_CREATE_TIMED_EVENT                 = 67,     // id, InitialMin, InitialMax, RepeatMin(only if it repeats), RepeatMax(only if it repeats), chance      SMART_ACTION_PLAYMOVIE                          = 68,     // entry -    SMART_ACTION_MOVE_TO_POS                        = 69,     // xyz +    SMART_ACTION_MOVE_TO_POS                        = 69,     // PointId, xyz      SMART_ACTION_RESPAWN_TARGET                     = 70,     //      SMART_ACTION_EQUIP                              = 71,     // entry, slotmask slot1, slot2, slot3   , only slots with mask set will be sent to client, bits are 1, 2, 4, leaving mask 0 is defaulted to mask 7 (send all), slots1-3 are only used if no entry is set      SMART_ACTION_CLOSE_GOSSIP                       = 72,     // none @@ -875,6 +874,11 @@ struct SmartAction          struct          { +            uint8 pointId; +        } MoveToPos; + +        struct +        {              uint32 gossipMenuId;              uint32 gossipNpcTextId;          } sendGossipMenu; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp index 43a29e93c55..034de38fd9c 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -437,8 +437,8 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target      ChatMsg type = CHAT_MSG_BG_SYSTEM_NEUTRAL;      //alliance flag picked up from base -    if (Source->GetTeam() == HORDE && this->GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE -        && this->BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID()) +    if (Source->GetTeam() == HORDE && GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE +        && BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID())      {          message_id = LANG_BG_WS_PICKEDUP_AF;          type = CHAT_MSG_BG_SYSTEM_HORDE; @@ -456,8 +456,8 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target      }      //horde flag picked up from base -    if (Source->GetTeam() == ALLIANCE && this->GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE -        && this->BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID()) +    if (Source->GetTeam() == ALLIANCE && GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE +        && BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID())      {          message_id = LANG_BG_WS_PICKEDUP_HF;          type = CHAT_MSG_BG_SYSTEM_ALLIANCE; @@ -475,7 +475,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target      }      //Alliance flag on ground(not in base) (returned or picked up again from ground!) -    if (GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10)) +    if (GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10) && BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID())      {          if (Source->GetTeam() == ALLIANCE)          { @@ -509,7 +509,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target      }      //Horde flag on ground(not in base) (returned or picked up again) -    if (GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10)) +    if (GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10) && BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID())      {          if (Source->GetTeam() == HORDE)          { diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp index b286abba81e..761bbb9b496 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -375,7 +375,7 @@ void CalendarMgr::AddAction(CalendarAction const& action)              uint64 eventId = action.Invite.GetEventId();              uint64 inviteId = action.Invite.GetInviteId(); -            CalendarEvent* calendarEvent; +            CalendarEvent* calendarEvent = NULL;              if (action.GetInviteId() != action.Invite.GetInviteId())                  calendarEvent = CheckPermisions(eventId, action.GetPlayer(), action.GetInviteId(), CALENDAR_RANK_MODERATOR);              else @@ -395,7 +395,7 @@ void CalendarMgr::AddAction(CalendarAction const& action)              uint64 eventId = action.Invite.GetEventId();              uint64 inviteId = action.Invite.GetInviteId(); -            CalendarEvent* calendarEvent; +            CalendarEvent* calendarEvent = NULL;              if (action.GetInviteId() != action.Invite.GetInviteId())                  calendarEvent = CheckPermisions(eventId, action.GetPlayer(), action.GetInviteId(), CALENDAR_RANK_OWNER);              else @@ -420,6 +420,9 @@ void CalendarMgr::AddAction(CalendarAction const& action)              // already checked in CheckPermisions              CalendarInvite* invite = GetInvite(inviteId); +            if (!invite) +                return; +              if (calendarEvent->GetCreatorGUID() == invite->GetInvitee())              {                  action.GetPlayer()->GetSession()->SendCalendarCommandResult(CALENDAR_ERROR_DELETE_CREATOR_FAILED); diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 7d21f94f372..755b9299352 100755 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -114,7 +114,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)          case CONDITION_QUESTREWARDED:          {              if (Player* player = object->ToPlayer()) -                condMeets = (player->GetQuestRewardStatus(ConditionValue1) == !ConditionValue2); +                condMeets = player->GetQuestRewardStatus(ConditionValue1);              break;          }          case CONDITION_QUESTTAKEN: @@ -122,7 +122,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)              if (Player* player = object->ToPlayer())              {                  QuestStatus status = player->GetQuestStatus(ConditionValue1); -                condMeets = ((status == QUEST_STATUS_INCOMPLETE) == !ConditionValue2); +                condMeets = (status == QUEST_STATUS_INCOMPLETE);              }              break;          } @@ -131,7 +131,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)              if (Player* player = object->ToPlayer())              {                  QuestStatus status = player->GetQuestStatus(ConditionValue1); -                condMeets = ((status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(ConditionValue1)) == !ConditionValue2); +                condMeets = (status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(ConditionValue1));              }              break;          } @@ -140,7 +140,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)              if (Player* player = object->ToPlayer())              {                  QuestStatus status = player->GetQuestStatus(ConditionValue1); -                condMeets = ((status == QUEST_STATUS_NONE) == !ConditionValue2); +                condMeets = (status == QUEST_STATUS_NONE);              }              break;          } @@ -515,7 +515,9 @@ bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo,          sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsPlayerMeetToConditionList condType: %u val1: %u", (*i)->ConditionType, (*i)->ConditionValue1);          if ((*i)->isLoaded())          { +            //! Find ElseGroup in ElseGroupStore              std::map<uint32, bool>::const_iterator itr = ElseGroupStore.find((*i)->ElseGroup); +            //! If not found, add an entry in the store and set to true (placeholder)              if (itr == ElseGroupStore.end())                  ElseGroupStore[(*i)->ElseGroup] = true;              else if (!(*itr).second) @@ -854,18 +856,6 @@ void ConditionMgr::LoadConditions(bool isReload)                      break;                  case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:                  { -                    //if no list for npc create one -                    if (SpellClickEventConditionStore.find(cond->SourceGroup) == SpellClickEventConditionStore.end()) -                    { -                        ConditionTypeContainer cmap; -                        SpellClickEventConditionStore[cond->SourceGroup] = cmap; -                    } -                    //if no list for spellclick spell create one -                    if (SpellClickEventConditionStore[cond->SourceGroup].find(cond->SourceEntry) == SpellClickEventConditionStore[cond->SourceGroup].end()) -                    { -                        ConditionList clist; -                        SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry] = clist; -                    }                      SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);                      valid = true;                      ++count; @@ -877,18 +867,6 @@ void ConditionMgr::LoadConditions(bool isReload)                      break;                  case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:                  { -                    //if no list for vehicle create one -                    if (VehicleSpellConditionStore.find(cond->SourceGroup) == VehicleSpellConditionStore.end()) -                    { -                        ConditionTypeContainer cmap; -                        VehicleSpellConditionStore[cond->SourceGroup] = cmap; -                    } -                    //if no list for vehicle's spell create one -                    if (VehicleSpellConditionStore[cond->SourceGroup].find(cond->SourceEntry) == VehicleSpellConditionStore[cond->SourceGroup].end()) -                    { -                        ConditionList clist; -                        VehicleSpellConditionStore[cond->SourceGroup][cond->SourceEntry] = clist; -                    }                      VehicleSpellConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);                      valid = true;                      ++count; @@ -896,18 +874,8 @@ void ConditionMgr::LoadConditions(bool isReload)                  }                  case CONDITION_SOURCE_TYPE_SMART_EVENT:                  { -                    // If the entry does not exist, create a new list +                    //! TODO: PAIR_32 ?                      std::pair<int32, uint32> key = std::make_pair(cond->SourceEntry, cond->SourceId); -                    if (SmartEventConditionStore.find(key) == SmartEventConditionStore.end()) -                    { -                        ConditionTypeContainer cmap; -                        SmartEventConditionStore[key] = cmap; -                    } -                    if (SmartEventConditionStore[key].find(cond->SourceGroup) == SmartEventConditionStore[key].end()) -                    { -                        ConditionList clist; -                        SmartEventConditionStore[key][cond->SourceGroup] = clist; -                    }                      SmartEventConditionStore[key][cond->SourceGroup].push_back(cond);                      valid = true;                      ++count; @@ -1929,6 +1897,19 @@ void ConditionMgr::Clean()      SmartEventConditionStore.clear(); +    for (CreatureSpellConditionContainer::iterator itr = SpellClickEventConditionStore.begin(); itr != SpellClickEventConditionStore.end(); ++itr) +    { +        for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it) +        { +            for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i) +                delete *i; +            it->second.clear(); +        } +        itr->second.clear(); +    } + +    SpellClickEventConditionStore.clear(); +      // this is a BIG hack, feel free to fix it if you can figure out the ConditionMgr ;)      for (std::list<Condition*>::const_iterator itr = AllocatedMemoryStore.begin(); itr != AllocatedMemoryStore.end(); ++itr)          delete *itr; diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index 5a5e2dd1c2e..ec6d6dd8453 100755 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -72,6 +72,33 @@ enum ConditionTypes      CONDITION_MAX                   = 39                    // MAX  }; +/*! Documentation on implementing a new ConditionSourceType: +    Step 1: Check for the lowest free ID. Look for CONDITION_SOURCE_TYPE_UNUSED_XX in the enum. +            Then define the new source type. + +    Step 2: Determine and map the parameters for the new condition type. + +    Step 3: Add a case block to ConditionMgr::isSourceTypeValid with the new condition type +            and validate the parameters. + +    Step 4: If your condition can be grouped (determined in step 2), add a rule for it in +            ConditionMgr::CanHaveSourceGroupSet, following the example of the existing types. + +    Step 5: Define the maximum available condition targets in ConditionMgr::GetMaxAvailableConditionTargets. + +    The following steps only apply if your condition can be grouped: + +    Step 6: Determine how you are going to store your conditions. You need to add a new storage container +            for it in ConditionMgr class, along with a function like:  +            ConditionList GetConditionsForXXXYourNewSourceTypeXXX(parameters...) + +            The above function should be placed in upper level (practical) code that actually  +            checks the conditions. + +    Step 7: Implement loading for your source type in ConditionMgr::LoadConditions. + +    Step 8: Implement memory cleaning for your source type in ConditionMgr::Clean. +*/  enum ConditionSourceType  {      CONDITION_SOURCE_TYPE_NONE                           = 0, diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index da5975aafbe..5b7c40e5494 100755 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -32,7 +32,7 @@ Corpse::Corpse(CorpseType type) : WorldObject(type != CORPSE_BONES)      m_objectType |= TYPEMASK_CORPSE;      m_objectTypeId = TYPEID_CORPSE; -    m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION); +    m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_POSITION);      m_valuesCount = CORPSE_END; diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp index fa975e0cd39..0a4e4c73f42 100755 --- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp +++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp @@ -33,7 +33,7 @@ DynamicObject::DynamicObject(bool isWorldObject) : WorldObject(isWorldObject),      m_objectType |= TYPEMASK_DYNAMICOBJECT;      m_objectTypeId = TYPEID_DYNAMICOBJECT; -    m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION); +    m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_POSITION);      m_valuesCount = DYNAMICOBJECT_END;  } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index a06cee891e7..c7101e918ba 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -38,7 +38,7 @@ GameObject::GameObject() : WorldObject(false), m_model(NULL), m_goValue(new Game      m_objectType |= TYPEMASK_GAMEOBJECT;      m_objectTypeId = TYPEID_GAMEOBJECT; -    m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION | UPDATEFLAG_ROTATION); +    m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_POSITION | UPDATEFLAG_ROTATION);      m_valuesCount = GAMEOBJECT_END;      m_respawnTime = 0; diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 0fc53a65258..90f6f4a217c 100755 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -237,7 +237,7 @@ Item::Item()      m_objectType |= TYPEMASK_ITEM;      m_objectTypeId = TYPEID_ITEM; -    m_updateFlag = UPDATEFLAG_HIGHGUID; +    m_updateFlag = UPDATEFLAG_LOWGUID;      m_valuesCount = ITEM_END;      m_slot = 0; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index c1ecc3b74e7..2a2b78f4630 100755 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -209,7 +209,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c      if (target == this)                                      // building packet for yourself          flags |= UPDATEFLAG_SELF; -    if (flags & UPDATEFLAG_HAS_POSITION) +    if (flags & UPDATEFLAG_STATIONARY_POSITION)      {          // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...          if (isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER)) @@ -293,19 +293,21 @@ void Object::BuildOutOfRangeUpdateBlock(UpdateData* data) const      data->AddOutOfRangeGUID(GetGUID());  } -void Object::DestroyForPlayer(Player* target, bool anim) const +void Object::DestroyForPlayer(Player* target, bool onDeath) const  {      ASSERT(target);      WorldPacket data(SMSG_DESTROY_OBJECT, 8 + 1);      data << uint64(GetGUID()); -    data << uint8(anim ? 1 : 0);                            // WotLK (bool), may be despawn animation +    //! If the following bool is true, the client will call "void CGUnit_C::OnDeath()" for this object. +    //! OnDeath() does for eg trigger death animation and interrupts certain spells/missiles/auras/sounds... +    data << uint8(onDeath ? 1 : 0);      target->GetSession()->SendPacket(&data);  } -void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const +void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const  { -    *data << (uint16)flags;                                  // update flags +    *data << uint16(flags);                                  // update flags      // 0x20      if (flags & UPDATEFLAG_LIVING) @@ -330,13 +332,29 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const      {          if (flags & UPDATEFLAG_POSITION)          { -            *data << uint8(0);                              // unk PGUID! -            *data << ((WorldObject*)this)->GetPositionX(); -            *data << ((WorldObject*)this)->GetPositionY(); -            *data << ((WorldObject*)this)->GetPositionZ(); +            Transport* transport = ((WorldObject*)this)->GetTransport(); +            if (transport) +                data->append(transport->GetPackGUID()); +            else +                *data << uint8(0); +              *data << ((WorldObject*)this)->GetPositionX();              *data << ((WorldObject*)this)->GetPositionY();              *data << ((WorldObject*)this)->GetPositionZ(); + +            if (transport) +            { +                *data << ((WorldObject*)this)->GetTransOffsetX(); +                *data << ((WorldObject*)this)->GetTransOffsetY(); +                *data << ((WorldObject*)this)->GetTransOffsetZ(); +            } +            else +            { +                *data << ((WorldObject*)this)->GetPositionX(); +                *data << ((WorldObject*)this)->GetPositionY(); +                *data << ((WorldObject*)this)->GetPositionZ(); +            } +              *data << ((WorldObject*)this)->GetOrientation();              if (GetTypeId() == TYPEID_CORPSE) @@ -347,28 +365,23 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const          else          {              // 0x40 -            if (flags & UPDATEFLAG_HAS_POSITION) +            if (flags & UPDATEFLAG_STATIONARY_POSITION)              { -                // 0x02 -                if (flags & UPDATEFLAG_TRANSPORT && ((GameObject*)this)->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT) -                { -                    *data << (float)0; -                    *data << (float)0; -                    *data << (float)0; -                    *data << ((WorldObject*)this)->GetOrientation(); -                } -                else -                { -                    *data << ((WorldObject*)this)->GetPositionX(); -                    *data << ((WorldObject*)this)->GetPositionY(); -                    *data << ((WorldObject*)this)->GetPositionZ(); -                    *data << ((WorldObject*)this)->GetOrientation(); -                } +                *data << ((WorldObject*)this)->GetPositionX(); +                *data << ((WorldObject*)this)->GetPositionY(); +                *data << ((WorldObject*)this)->GetPositionZ(); +                *data << ((WorldObject*)this)->GetOrientation();              }          }      }      // 0x8 +    if (flags & UPDATEFLAG_UNKNOWN) +    { +        *data << uint32(0); +    } + +    // 0x10      if (flags & UPDATEFLAG_LOWGUID)      {          switch (GetTypeId()) @@ -381,14 +394,16 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const              case TYPEID_CORPSE:                  *data << uint32(GetGUIDLow());              // GetGUIDLow()                  break; +            //! Unit, Player and default here are sending wrong values. +            //! TODO: Research the proper formula              case TYPEID_UNIT: -                *data << uint32(0x0000000B);                // unk, can be 0xB or 0xC +                *data << uint32(0x0000000B);                // unk                  break;              case TYPEID_PLAYER:                  if (flags & UPDATEFLAG_SELF) -                    *data << uint32(0x0000002F);            // unk, can be 0x15 or 0x22 +                    *data << uint32(0x0000002F);            // unk                  else -                    *data << uint32(0x00000008);            // unk, can be 0x7 or 0x8 +                    *data << uint32(0x00000008);            // unk                  break;              default:                  *data << uint32(0x00000000);                // unk @@ -396,15 +411,8 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const          }      } -    // 0x10 -    if (flags & UPDATEFLAG_HIGHGUID) -    { -        // not high guid -        *data << uint32(GetUInt32Value(OBJECT_FIELD_GUID));                // unk -    } -      // 0x4 -    if (flags & UPDATEFLAG_HAS_TARGET)                       // packed guid (current target guid) +    if (flags & UPDATEFLAG_HAS_TARGET)      {          if (Unit* victim = ((Unit*)this)->getVictim())              data->append(victim->GetPackGUID()); @@ -415,14 +423,15 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const      // 0x2      if (flags & UPDATEFLAG_TRANSPORT)      { -        *data << uint32(getMSTime());                       // ms time +        *data << uint32(getMSTime());                       // Unknown - getMSTime is wrong.      }      // 0x80 -    if (flags & UPDATEFLAG_VEHICLE)                          // unused for now +    if (flags & UPDATEFLAG_VEHICLE)      { -        *data << uint32(((Unit*)this)->GetVehicleKit()->GetVehicleInfo()->m_ID);  // vehicle id -        *data << float(((Creature*)this)->GetOrientation());  // facing adjustment +        // TODO: Allow players to aquire this updateflag. +        *data << uint32(((Unit*)this)->GetVehicleKit()->GetVehicleInfo()->m_ID); +        *data << float(((Creature*)this)->GetOrientation());      }      // 0x200 @@ -581,7 +590,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask*                  {                      uint32 dynamicFlags = m_uint32Values[index]; -                    if (const Creature* creature = ToCreature()) +                    if (Creature const* creature = ToCreature())                      {                          if (creature->hasLootRecipient())                          { diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 7b3fcc4a337..c243527570b 100755 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -147,7 +147,7 @@ class Object          void BuildOutOfRangeUpdateBlock(UpdateData* data) const;          void BuildMovementUpdateBlock(UpdateData* data, uint32 flags = 0) const; -        virtual void DestroyForPlayer(Player* target, bool anim = false) const; +        virtual void DestroyForPlayer(Player* target, bool onDeath = false) const;          int32 GetInt32Value(uint16 index) const          { @@ -299,18 +299,18 @@ class Object          // FG: some hacky helpers          void ForceValuesUpdateAtIndex(uint32); -        Player* ToPlayer(){ if (GetTypeId() == TYPEID_PLAYER)  return reinterpret_cast<Player*>(this); else return NULL;  } -        const Player* ToPlayer() const { if (GetTypeId() == TYPEID_PLAYER)  return (const Player*)((Player*)this); else return NULL;  } -        Creature* ToCreature(){ if (GetTypeId() == TYPEID_UNIT) return reinterpret_cast<Creature*>(this); else return NULL; } -        const Creature* ToCreature() const {if (GetTypeId() == TYPEID_UNIT) return (const Creature*)((Creature*)this); else return NULL; } +        Player* ToPlayer() { if (GetTypeId() == TYPEID_PLAYER) return reinterpret_cast<Player*>(this); else return NULL; } +        Player const* ToPlayer() const { if (GetTypeId() == TYPEID_PLAYER) return (Player const*)((Player*)this); else return NULL; } +        Creature* ToCreature() { if (GetTypeId() == TYPEID_UNIT) return reinterpret_cast<Creature*>(this); else return NULL; } +        Creature const* ToCreature() const { if (GetTypeId() == TYPEID_UNIT) return (Creature const*)((Creature*)this); else return NULL; } -        Unit* ToUnit(){ if (GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER) return reinterpret_cast<Unit*>(this); else return NULL; } -        const Unit* ToUnit() const {if (GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER) return (const Unit*)((Unit*)this); else return NULL; } -        GameObject* ToGameObject(){ if (GetTypeId() == TYPEID_GAMEOBJECT) return reinterpret_cast<GameObject*>(this); else return NULL; } -        const GameObject* ToGameObject() const {if (GetTypeId() == TYPEID_GAMEOBJECT) return (const GameObject*)((GameObject*)this); else return NULL; } +        Unit* ToUnit() { if (GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER) return reinterpret_cast<Unit*>(this); else return NULL; } +        Unit const* ToUnit() const { if (GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER) return (const Unit*)((Unit*)this); else return NULL; } +        GameObject* ToGameObject() { if (GetTypeId() == TYPEID_GAMEOBJECT) return reinterpret_cast<GameObject*>(this); else return NULL; } +        GameObject const* ToGameObject() const { if (GetTypeId() == TYPEID_GAMEOBJECT) return (const GameObject*)((GameObject*)this); else return NULL; } -        Corpse* ToCorpse(){ if (GetTypeId() == TYPEID_CORPSE) return reinterpret_cast<Corpse*>(this); else return NULL; } -        const Corpse* ToCorpse() const {if (GetTypeId() == TYPEID_CORPSE) return (const Corpse*)((Corpse*)this); else return NULL; } +        Corpse* ToCorpse() { if (GetTypeId() == TYPEID_CORPSE) return reinterpret_cast<Corpse*>(this); else return NULL; } +        Corpse const* ToCorpse() const { if (GetTypeId() == TYPEID_CORPSE) return (const Corpse*)((Corpse*)this); else return NULL; }      protected:          Object (); diff --git a/src/server/game/Entities/Object/Updates/UpdateData.h b/src/server/game/Entities/Object/Updates/UpdateData.h index e4caaec3117..ff649b7cb2f 100755 --- a/src/server/game/Entities/Object/Updates/UpdateData.h +++ b/src/server/game/Entities/Object/Updates/UpdateData.h @@ -34,17 +34,17 @@ enum OBJECT_UPDATE_TYPE  enum OBJECT_UPDATE_FLAGS  { -    UPDATEFLAG_NONE         = 0x0000, -    UPDATEFLAG_SELF         = 0x0001, -    UPDATEFLAG_TRANSPORT    = 0x0002, -    UPDATEFLAG_HAS_TARGET   = 0x0004, -    UPDATEFLAG_LOWGUID      = 0x0008, -    UPDATEFLAG_HIGHGUID     = 0x0010, -    UPDATEFLAG_LIVING       = 0x0020, -    UPDATEFLAG_HAS_POSITION = 0x0040, -    UPDATEFLAG_VEHICLE      = 0x0080, -    UPDATEFLAG_POSITION     = 0x0100, -    UPDATEFLAG_ROTATION     = 0x0200 +    UPDATEFLAG_NONE                 = 0x0000, +    UPDATEFLAG_SELF                 = 0x0001, +    UPDATEFLAG_TRANSPORT            = 0x0002, +    UPDATEFLAG_HAS_TARGET           = 0x0004, +    UPDATEFLAG_UNKNOWN              = 0x0008, +    UPDATEFLAG_LOWGUID              = 0x0010, +    UPDATEFLAG_LIVING               = 0x0020, +    UPDATEFLAG_STATIONARY_POSITION  = 0x0040, +    UPDATEFLAG_VEHICLE              = 0x0080, +    UPDATEFLAG_POSITION             = 0x0100, +    UPDATEFLAG_ROTATION             = 0x0200  };  class UpdateData diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 857ae4d845b..870b6f683b8 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -143,8 +143,9 @@ static uint32 copseReclaimDelay[MAX_DEATH_COUNT] = { 30, 60, 120 };  // == PlayerTaxi ================================================  PlayerTaxi::PlayerTaxi() -    : m_taximask() -{ } +{ +    memset(m_taximask, 0, sizeof(m_taximask)); +}  void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level)  { @@ -4623,9 +4624,9 @@ void Player::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c      Unit::BuildCreateUpdateBlockForPlayer(data, target);  } -void Player::DestroyForPlayer(Player* target, bool anim) const +void Player::DestroyForPlayer(Player* target, bool onDeath) const  { -    Unit::DestroyForPlayer(target, anim); +    Unit::DestroyForPlayer(target, onDeath);      for (uint8 i = 0; i < INVENTORY_SLOT_BAG_END; ++i)      { @@ -7420,6 +7421,8 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)          }      } +    sScriptMgr->OnPlayerUpdateZone(this, newZone, newArea); +      // in PvP, any not controlled zone (except zone->team == 6, default case)      // in PvE, only opposition team capital      switch (zone->team) @@ -17780,12 +17783,19 @@ void Player::_LoadQuestStatus(PreparedQueryResult result)                  QuestStatusData& questStatusData = m_QuestStatus[quest_id];                  uint8 qstatus = fields[1].GetUInt8(); -                if (qstatus < MAX_QUEST_STATUS) +                if (qstatus < MAX_QUEST_STATUS && qstatus > QUEST_STATUS_NONE)                      questStatusData.Status = QuestStatus(qstatus); +                else if (qstatus == QUEST_STATUS_NONE) +                { +                    sLog->outError("Player %s (GUID: %u) has QUEST_STATUS_NONE for quest %u and should be removed from character_queststatus.", +                        GetName(), GetGUIDLow(), quest_id); +                    continue; +                }                  else                  {                      questStatusData.Status = QUEST_STATUS_INCOMPLETE; -                    sLog->outError("Player %s have invalid quest %d status (%u), replaced by QUEST_STATUS_INCOMPLETE(3).", GetName(), quest_id, qstatus); +                    sLog->outError("Player %s (GUID: %u) has invalid quest %d status (%u), replaced by QUEST_STATUS_INCOMPLETE(3).", +                        GetName(), GetGUIDLow(), quest_id, qstatus);                  }                  questStatusData.Explored = (fields[2].GetUInt8() > 0); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index db055088808..3d510148aa4 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -687,9 +687,9 @@ enum TransferAbortReason      TRANSFER_ABORT_UNIQUE_MESSAGE           = 0x09,         // Until you've escaped TLK's grasp, you cannot leave this place!      TRANSFER_ABORT_TOO_MANY_REALM_INSTANCES = 0x0A,         // Additional instances cannot be launched, please try again later.      TRANSFER_ABORT_NEED_GROUP               = 0x0B,         // 3.1 -    TRANSFER_ABORT_NOT_FOUND2               = 0x0C,         // 3.1 -    TRANSFER_ABORT_NOT_FOUND3               = 0x0D,         // 3.1 -    TRANSFER_ABORT_NOT_FOUND4               = 0x0E,         // 3.2 +    TRANSFER_ABORT_NOT_FOUND1               = 0x0C,         // 3.1 +    TRANSFER_ABORT_NOT_FOUND2               = 0x0D,         // 3.1 +    TRANSFER_ABORT_NOT_FOUND3               = 0x0E,         // 3.2      TRANSFER_ABORT_REALM_ONLY               = 0x0F,         // All players on party must be from the same realm.      TRANSFER_ABORT_MAP_NOT_ALLOWED          = 0x10,         // Map can't be entered at this time.  }; @@ -1915,7 +1915,7 @@ class Player : public Unit, public GridObject<Player>          WorldSession* GetSession() const { return m_session; }          void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const; -        void DestroyForPlayer(Player* target, bool anim = false) const; +        void DestroyForPlayer(Player* target, bool onDeath = false) const;          void SendLogXPGain(uint32 GivenXP, Unit* victim, uint32 BonusXP, bool recruitAFriend = false, float group_rate=1.0f);          // notifiers diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index a425640e36d..24fe75605d2 100755 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -173,7 +173,7 @@ void MapManager::LoadTransportNPCs()  Transport::Transport(uint32 period, uint32 script) : GameObject(), m_pathTime(0), m_timer(0),  currenttguid(0), m_period(period), ScriptId(script), m_nextNodeTime(0)  { -    m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_ROTATION); +    m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION);  }  Transport::~Transport() diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 3af6d388ba9..3411d285b1e 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -158,7 +158,7 @@ m_HostileRefManager(this)      m_objectType |= TYPEMASK_UNIT;      m_objectTypeId = TYPEID_UNIT; -    m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION); +    m_updateFlag = (UPDATEFLAG_LIVING | UPDATEFLAG_STATIONARY_POSITION);      m_attackTimer[BASE_ATTACK] = 0;      m_attackTimer[OFF_ATTACK] = 0; @@ -430,7 +430,7 @@ void Unit::SendMonsterMoveTransport(Unit* vehicleOwner)      data.append(GetPackGUID());      data.append(vehicleOwner->GetPackGUID());      data << int8(GetTransSeat()); -    data << uint8(GetTypeId() == TYPEID_PLAYER ? 1 : 0); // boolean +    data << uint8(0);      data << GetPositionX() - vehicleOwner->GetPositionX();      data << GetPositionY() - vehicleOwner->GetPositionY();      data << GetPositionZ() - vehicleOwner->GetPositionZ(); @@ -784,20 +784,9 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam          // last damage from duel opponent          if (duel_hasEnded)          { -            Player* he; +            Player* he = duel_wasMounted ? victim->GetCharmer()->ToPlayer() : victim->ToPlayer(); -            if (duel_wasMounted) -            { -                ASSERT(victim->GetCharmer()->GetTypeId() == TYPEID_PLAYER); -                he = victim->GetCharmer()->ToPlayer(); -            } -            else -            { -                ASSERT(victim->GetTypeId() == TYPEID_PLAYER); -                he = victim->ToPlayer(); -            } - -            ASSERT(he->duel); +            ASSERT(he && he->duel);              if (duel_wasMounted) // In this case victim==mount                  victim->SetHealth(1); @@ -16991,7 +16980,7 @@ void Unit::ChangeSeat(int8 seatId, bool next)          ASSERT(false);  } -void Unit::ExitVehicle(Position const* exitPosition) +void Unit::ExitVehicle(Position const* /*exitPosition*/)  {      //! This function can be called at upper level code to initialize an exit from the passenger's side.      if (!m_vehicle) @@ -17171,14 +17160,18 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel              GetMap()->CreatureRelocation(ToCreature(), x, y, z, orientation);      }      else if (turn) -        SetOrientation(orientation); - -    if ((relocated || turn) && IsVehicle()) -        GetVehicleKit()->RelocatePassengers(x, y, z, orientation); +        UpdateOrientation(orientation);      return (relocated || turn);  } +void Unit::UpdateOrientation(float orientation) +{ +    SetOrientation(orientation); +    if (IsVehicle()) +        GetVehicleKit()->RelocatePassengers(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); +} +  void Unit::SendThreatListUpdate()  {      if (!getThreatManager().isThreatListEmpty()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 0fe5f3d8ca3..b07f2ae1c16 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1614,6 +1614,7 @@ class Unit : public WorldObject          virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport = false);          // returns true if unit's position really changed          bool UpdatePosition(const Position &pos, bool teleport = false) { return UpdatePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teleport); } +        void UpdateOrientation(float orientation);          void KnockbackFrom(float x, float y, float speedXY, float speedZ);          void JumpTo(float speedXY, float speedZ, bool forward = true); diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 6693af5c91f..2f552eddb9f 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -431,6 +431,7 @@ void Vehicle::RemovePassenger(Unit* unit)          sScriptMgr->OnRemovePassenger(this, unit);  } +//! Must be called after m_base::Relocate  void Vehicle::RelocatePassengers(float x, float y, float z, float ang)  {      ASSERT(_me->GetMap()); @@ -440,8 +441,6 @@ void Vehicle::RelocatePassengers(float x, float y, float z, float ang)          if (Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), itr->second.Passenger))          {              ASSERT(passenger->IsInWorld()); -            ASSERT(passenger->IsOnVehicle(GetBase())); -            ASSERT(GetSeatForPassenger(passenger));              float px = x + passenger->m_movementInfo.t_pos.m_positionX;              float py = y + passenger->m_movementInfo.t_pos.m_positionY; diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp index 1a069a27825..9a99a28c7aa 100755 --- a/src/server/game/Globals/ObjectAccessor.cpp +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -166,10 +166,18 @@ Unit* ObjectAccessor::FindUnit(uint64 guid)  Player* ObjectAccessor::FindPlayerByName(const char* name)  {      TRINITY_READ_GUARD(HashMapHolder<Player>::LockType, *HashMapHolder<Player>::GetLock()); +    std::string nameStr = name; +    std::transform(nameStr.begin(), nameStr.end(), nameStr.begin(), ::tolower);      HashMapHolder<Player>::MapType const& m = GetPlayers();      for (HashMapHolder<Player>::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter) -        if (iter->second->IsInWorld() && strcmp(name, iter->second->GetName()) == 0) +    { +        if (!iter->second->IsInWorld()) +            continue; +        std::string currentName = iter->second->GetName(); +        std::transform(currentName.begin(), currentName.end(), currentName.begin(), ::tolower); +        if (nameStr.compare(currentName) == 0)              return iter->second; +    }      return NULL;  } @@ -400,4 +408,4 @@ template Pet* ObjectAccessor::GetObjectInWorld<Pet>(uint32 mapid, float x, float  template Creature* ObjectAccessor::GetObjectInWorld<Creature>(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/);  template Corpse* ObjectAccessor::GetObjectInWorld<Corpse>(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/);  template GameObject* ObjectAccessor::GetObjectInWorld<GameObject>(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/); -template DynamicObject* ObjectAccessor::GetObjectInWorld<DynamicObject>(uint32 mapid, float x, float y, uint64 guid, DynamicObject* /*fake*/);
\ No newline at end of file +template DynamicObject* ObjectAccessor::GetObjectInWorld<DynamicObject>(uint32 mapid, float x, float y, uint64 guid, DynamicObject* /*fake*/); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 7834a1cc4a3..11977280177 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7079,7 +7079,7 @@ void ObjectMgr::LoadNPCSpellClickSpells()      uint32 oldMSTime = getMSTime();      _spellClickInfoStore.clear(); -    //                                                0          1         2            3  +    //                                                0          1         2            3      QueryResult result = WorldDatabase.Query("SELECT npc_entry, spell_id, cast_flags, user_type FROM npc_spellclick_spells");      if (!result) diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index 223bb7dd5c7..f82c52204fb 100755 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -241,6 +241,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data)          else              AH->auctioneer = GUID_LOPART(auctioneer); +        // Required stack size of auction matches to current item stack size, just move item to auctionhouse          if (itemsCount == 1 && item->GetCount() == count[i])          {              if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) @@ -278,7 +279,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data)              GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);              return;          } -        else +        else // Required stack size of auction does not match to current item stack size, clone item and set correct stack size          {              Item* newItem = item->CloneItem(finalCount, _player);              if (!newItem) @@ -313,16 +314,17 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data)              {                  Item* item2 = items[j]; +                // Item stack count equals required count, ready to delete item - cloned item will be used for auction                  if (item2->GetCount() == count[j])                  {                      _player->MoveItemFromInventory(item2->GetBagSlot(), item2->GetSlot(), true);                      SQLTransaction trans = CharacterDatabase.BeginTransaction();                      item2->DeleteFromInventoryDB(trans); -                    item2->SaveToDB(trans); +                    item2->DeleteFromDB(trans);                      CharacterDatabase.CommitTransaction(trans);                  } -                else +                else // Item stack count is bigger than required count, update item stack count and save to database - cloned item will be used for auction                  {                      item2->SetCount(item2->GetCount() - count[j]);                      item2->SetState(ITEM_CHANGED, _player); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 31dc622a724..00b52bf746b 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -32,6 +32,7 @@  #include "Group.h"  #include "LFGMgr.h"  #include "DynamicTree.h" +#include "Vehicle.h"  union u_map_magic  { @@ -702,6 +703,8 @@ void Map::PlayerRelocation(Player* player, float x, float y, float z, float orie      Cell new_cell(x, y);      player->Relocate(x, y, z, orientation); +    if (player->IsVehicle()) +        player->GetVehicleKit()->RelocatePassengers(x, y, z, orientation);      if (old_cell.DiffGrid(new_cell) || old_cell.DiffCell(new_cell))      { @@ -740,6 +743,8 @@ void Map::CreatureRelocation(Creature* creature, float x, float y, float z, floa      else      {          creature->Relocate(x, y, z, ang); +        if (creature->IsVehicle()) +            creature->GetVehicleKit()->RelocatePassengers(x, y, z, ang);          creature->UpdateObjectVisibility(false);          RemoveCreatureFromMoveList(creature);      } diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index fbe609bee23..5543251e115 100755 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -116,19 +116,21 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player)          return NULL;      Map* map = NULL; -    uint32 NewInstanceId = 0;                       // instanceId of the resulting map +    uint32 newInstanceId = 0;                       // instanceId of the resulting map      if (IsBattlegroundOrArena())      {          // instantiate or find existing bg map for player          // the instance id is set in battlegroundid -        NewInstanceId = player->GetBattlegroundId(); -        if (!NewInstanceId) return NULL; -        map = sMapMgr->FindMap(mapId, NewInstanceId); +        newInstanceId = player->GetBattlegroundId(); +        if (!newInstanceId) +            return NULL; + +        map = sMapMgr->FindMap(mapId, newInstanceId);          if (!map)          {              if (Battleground* bg = player->GetBattleground()) -                map = CreateBattleground(NewInstanceId, bg); +                map = CreateBattleground(newInstanceId, bg);              else              {                  player->TeleportToBGEntryPoint(); @@ -158,24 +160,24 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player)          if (pSave)          {              // solo/perm/group -            NewInstanceId = pSave->GetInstanceId(); -            map = FindInstanceMap(NewInstanceId); +            newInstanceId = pSave->GetInstanceId(); +            map = FindInstanceMap(newInstanceId);              // it is possible that the save exists but the map doesn't              if (!map) -                map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty()); +                map = CreateInstance(newInstanceId, pSave, pSave->GetDifficulty());          }          else          {              // if no instanceId via group members or instance saves is found              // the instance will be created for the first time -            NewInstanceId = sMapMgr->GenerateInstanceId(); +            newInstanceId = sMapMgr->GenerateInstanceId();              Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid());              //Seems it is now possible, but I do not know if it should be allowed              //ASSERT(!FindInstanceMap(NewInstanceId)); -            map = FindInstanceMap(NewInstanceId); +            map = FindInstanceMap(newInstanceId);              if (!map) -                map = CreateInstance(NewInstanceId, NULL, diff); +                map = CreateInstance(newInstanceId, NULL, diff);          }      } diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index e751dbf92fe..547f1679b61 100755 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -811,7 +811,9 @@ enum TrinityStrings      LANG_MOVEGENS_FOLLOW_CREATURE       = 1140,      LANG_MOVEGENS_FOLLOW_NULL           = 1141,      LANG_MOVEGENS_EFFECT                = 1142, -    // Room for more level 3              1143-1199 not used +    LANG_MOVEFLAGS_GET                  = 1143, +    LANG_MOVEFLAGS_SET                  = 1144, +    // Room for more level 3              1144-1199 not used      // Debug commands      LANG_CINEMATIC_NOT_EXIST            = 1200, diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 47751338d66..ac15bd5c985 100755 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -1295,6 +1295,11 @@ void ScriptMgr::OnPlayerBindToInstance(Player* player, Difficulty difficulty, ui      FOREACH_SCRIPT(PlayerScript)->OnBindToInstance(player, difficulty, mapid, permanent);  } +void ScriptMgr::OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea) +{ +    FOREACH_SCRIPT(PlayerScript)->OnUpdateZone(player, newZone, newArea); +} +  // Guild  void ScriptMgr::OnGuildAddMember(Guild* guild, Player* player, uint8& plRank)  { diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 048a7581215..3b65a5cf256 100755 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -724,6 +724,9 @@ class PlayerScript : public ScriptObject          // Called when a player is bound to an instance          virtual void OnBindToInstance(Player* /*player*/, Difficulty /*difficulty*/, uint32 /*mapId*/, bool /*permanent*/) { } + +        // Called when a player switches to a new zone +        virtual void OnUpdateZone(Player* /*player*/, uint32 /*newZone*/, uint32 /*newArea*/) { }  };  class GuildScript : public ScriptObject @@ -993,6 +996,7 @@ class ScriptMgr          void OnPlayerCreate(Player* player);          void OnPlayerDelete(uint64 guid);          void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent); +        void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea);      public: /* GuildScript */ diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index e2e6772f230..e5b5b20dcfa 100755 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -769,7 +769,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =      /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME",                 STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },      /*0x2E5*/ { "CMSG_GM_UNTEACH",                              STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },      /*0x2E6*/ { "SMSG_WARDEN_DATA",                             STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               }, -    /*0x2E7*/ { "CMSG_WARDEN_DATA",                             STATUS_AUTHED,   PROCESS_THREADUNSAFE, &WorldSession::HandleWardenDataOpcode          }, +    /*0x2E7*/ { "CMSG_WARDEN_DATA",                             STATUS_AUTHED,   PROCESS_THREADSAFE,   &WorldSession::HandleWardenDataOpcode          },      /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND",               STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },      /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS",            STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlegroundPlayerPositionsOpcode},      /*0x2EA*/ { "CMSG_PET_STOP_ATTACK",                         STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetStopAttack             }, diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 4f4de7c72cd..2ffa94371f9 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -56,6 +56,35 @@  extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS]; +SpellDestination::SpellDestination() +{ +    _position.Relocate(0, 0, 0, 0); +    _transportGUID = 0; +    _transportOffset.Relocate(0, 0, 0, 0); +} + +SpellDestination::SpellDestination(float x, float y, float z, float orientation, uint32 mapId) +{ +    _position.Relocate(x, y, z, orientation); +    _transportGUID = 0; +    _position.m_mapId = mapId; +} + +SpellDestination::SpellDestination(Position const& pos) +{ +    _position.Relocate(pos); +    _transportGUID = 0; +} + +SpellDestination::SpellDestination(WorldObject const& wObj) +{ +    _transportGUID = wObj.GetTransGUID(); +    _transportOffset.Relocate(wObj.GetTransOffsetX(), wObj.GetTransOffsetY(), wObj.GetTransOffsetZ(), wObj.GetTransOffsetO()); +    _position.Relocate(wObj); +    _position.SetOrientation(wObj.GetOrientation()); +} + +  SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0)  {      m_objectTarget = NULL; @@ -65,12 +94,6 @@ SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0)      m_itemTargetGUID   = 0;      m_itemTargetEntry  = 0; -    m_srcTransGUID = 0; -    m_srcTransOffset.Relocate(0, 0, 0, 0); -    m_srcPos.Relocate(0, 0, 0, 0); -    m_dstTransGUID = 0; -    m_dstTransOffset.Relocate(0, 0, 0, 0); -    m_dstPos.Relocate(0, 0, 0, 0);      m_strTarget = "";      m_targetMask = 0;  } @@ -94,36 +117,36 @@ void SpellCastTargets::Read(ByteBuffer& data, Unit* caster)      if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)      { -        data.readPackGUID(m_srcTransGUID); -        if (m_srcTransGUID) -            data >> m_srcTransOffset.PositionXYZStream(); +        data.readPackGUID(m_src._transportGUID); +        if (m_src._transportGUID) +            data >> m_src._transportOffset.PositionXYZStream();          else -            data >> m_srcPos.PositionXYZStream(); +            data >> m_src._position.PositionXYZStream();      }      else      { -        m_srcTransGUID = caster->GetTransGUID(); -        if (m_srcTransGUID) -            m_srcTransOffset.Relocate(caster->GetTransOffsetX(), caster->GetTransOffsetY(), caster->GetTransOffsetZ(), caster->GetTransOffsetO()); +        m_src._transportGUID = caster->GetTransGUID(); +        if (m_src._transportGUID) +            m_src._transportOffset.Relocate(caster->GetTransOffsetX(), caster->GetTransOffsetY(), caster->GetTransOffsetZ(), caster->GetTransOffsetO());          else -            m_srcPos.Relocate(caster); +            m_src._position.Relocate(caster);      }      if (m_targetMask & TARGET_FLAG_DEST_LOCATION)      { -        data.readPackGUID(m_dstTransGUID); -        if (m_dstTransGUID) -            data >> m_dstTransOffset.PositionXYZStream(); +        data.readPackGUID(m_dst._transportGUID); +        if (m_dst._transportGUID) +            data >> m_dst._transportOffset.PositionXYZStream();          else -            data >> m_dstPos.PositionXYZStream(); +            data >> m_dst._position.PositionXYZStream();      }      else      { -        m_dstTransGUID = caster->GetTransGUID(); -        if (m_dstTransGUID) -            m_dstTransOffset.Relocate(caster->GetTransOffsetX(), caster->GetTransOffsetY(), caster->GetTransOffsetZ(), caster->GetTransOffsetO()); +        m_dst._transportGUID = caster->GetTransGUID(); +        if (m_dst._transportGUID) +            m_dst._transportOffset.Relocate(caster->GetTransOffsetX(), caster->GetTransOffsetY(), caster->GetTransOffsetZ(), caster->GetTransOffsetO());          else -            m_dstPos.Relocate(caster); +            m_dst._position.Relocate(caster);      }      if (m_targetMask & TARGET_FLAG_STRING) @@ -149,20 +172,20 @@ void SpellCastTargets::Write(ByteBuffer& data)      if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)      { -        data.appendPackGUID(m_srcTransGUID); // relative position guid here - transport for example -        if (m_srcTransGUID) -            data << m_srcTransOffset.PositionXYZStream(); +        data.appendPackGUID(m_src._transportGUID); // relative position guid here - transport for example +        if (m_src._transportGUID) +            data << m_src._transportOffset.PositionXYZStream();          else -            data << m_srcPos.PositionXYZStream(); +            data << m_src._position.PositionXYZStream();      }      if (m_targetMask & TARGET_FLAG_DEST_LOCATION)      { -        data.appendPackGUID(m_dstTransGUID); // relative position guid here - transport for example -        if (m_dstTransGUID) -            data << m_dstTransOffset.PositionXYZStream(); +        data.appendPackGUID(m_dst._transportGUID); // relative position guid here - transport for example +        if (m_dst._transportGUID) +            data << m_dst._transportOffset.PositionXYZStream();          else -            data << m_dstPos.PositionXYZStream(); +            data << m_dst._position.PositionXYZStream();      }      if (m_targetMask & TARGET_FLAG_STRING) @@ -295,31 +318,31 @@ void SpellCastTargets::UpdateTradeSlotItem()      }  } -Position const* SpellCastTargets::GetSrc() const +SpellDestination const* SpellCastTargets::GetSrc() const  { -    return &m_srcPos; +    return &m_src; +} + +Position const* SpellCastTargets::GetSrcPos() const +{ +    return &m_src._position;  }  void SpellCastTargets::SetSrc(float x, float y, float z)  { -    m_srcPos.Relocate(x, y, z); -    m_srcTransGUID = 0; +    m_src = SpellDestination(x, y, z);      m_targetMask |= TARGET_FLAG_SOURCE_LOCATION;  }  void SpellCastTargets::SetSrc(Position const& pos)  { -    m_srcPos.Relocate(pos); -    m_srcTransGUID = 0; +    m_src = SpellDestination(pos);      m_targetMask |= TARGET_FLAG_SOURCE_LOCATION;  }  void SpellCastTargets::SetSrc(WorldObject const& wObj)  { -    uint64 guid = wObj.GetTransGUID(); -    m_srcTransGUID = guid; -    m_srcTransOffset.Relocate(wObj.GetTransOffsetX(), wObj.GetTransOffsetY(), wObj.GetTransOffsetZ(), wObj.GetTransOffsetO()); -    m_srcPos.Relocate(wObj); +    m_src = SpellDestination(wObj);      m_targetMask |= TARGET_FLAG_SOURCE_LOCATION;  } @@ -327,13 +350,13 @@ void SpellCastTargets::ModSrc(Position const& pos)  {      ASSERT(m_targetMask & TARGET_FLAG_SOURCE_LOCATION); -    if (m_srcTransGUID) +    if (m_src._transportGUID)      {          Position offset; -        m_srcPos.GetPositionOffsetTo(pos, offset); -        m_srcTransOffset.RelocateOffset(offset); +        m_src._position.GetPositionOffsetTo(pos, offset); +        m_src._transportOffset.RelocateOffset(offset);      } -    m_srcPos.Relocate(pos); +    m_src._position.Relocate(pos);  }  void SpellCastTargets::RemoveSrc() @@ -341,41 +364,37 @@ void SpellCastTargets::RemoveSrc()      m_targetMask &= ~(TARGET_FLAG_SOURCE_LOCATION);  } -WorldLocation const* SpellCastTargets::GetDst() const +SpellDestination const* SpellCastTargets::GetDst() const  { -    return &m_dstPos; +    return &m_dst; +} + +WorldLocation const* SpellCastTargets::GetDstPos() const +{ +    return &m_dst._position;  }  void SpellCastTargets::SetDst(float x, float y, float z, float orientation, uint32 mapId)  { -    m_dstPos.Relocate(x, y, z, orientation); -    m_dstTransGUID = 0; +    m_dst = SpellDestination(x, y, z, orientation, mapId);      m_targetMask |= TARGET_FLAG_DEST_LOCATION; -    if (mapId != MAPID_INVALID) -        m_dstPos.m_mapId = mapId;  }  void SpellCastTargets::SetDst(Position const& pos)  { -    m_dstPos.Relocate(pos); -    m_dstTransGUID = 0; +    m_dst = SpellDestination(pos);      m_targetMask |= TARGET_FLAG_DEST_LOCATION;  }  void SpellCastTargets::SetDst(WorldObject const& wObj)  { -    uint64 guid = wObj.GetTransGUID(); -    m_dstTransGUID = guid; -    m_dstTransOffset.Relocate(wObj.GetTransOffsetX(), wObj.GetTransOffsetY(), wObj.GetTransOffsetZ(), wObj.GetTransOffsetO()); -    m_dstPos.Relocate(wObj); +    m_dst = SpellDestination(wObj);      m_targetMask |= TARGET_FLAG_DEST_LOCATION;  }  void SpellCastTargets::SetDst(SpellCastTargets const& spellTargets)  { -    m_dstTransGUID = spellTargets.m_dstTransGUID; -    m_dstTransOffset.Relocate(spellTargets.m_dstTransOffset); -    m_dstPos.Relocate(spellTargets.m_dstPos); +    m_dst = spellTargets.m_dst;      m_targetMask |= TARGET_FLAG_DEST_LOCATION;  } @@ -383,13 +402,13 @@ void SpellCastTargets::ModDst(Position const& pos)  {      ASSERT(m_targetMask & TARGET_FLAG_DEST_LOCATION); -    if (m_dstTransGUID) +    if (m_dst._transportGUID)      {          Position offset; -        m_dstPos.GetPositionOffsetTo(pos, offset); -        m_dstTransOffset.RelocateOffset(offset); +        m_dst._position.GetPositionOffsetTo(pos, offset); +        m_dst._transportOffset.RelocateOffset(offset);      } -    m_dstPos.Relocate(pos); +    m_dst._position.Relocate(pos);  }  void SpellCastTargets::RemoveDst() @@ -417,21 +436,21 @@ void SpellCastTargets::Update(Unit* caster)      }      // update positions by transport move -    if (HasSrc() && m_srcTransGUID) +    if (HasSrc() && m_src._transportGUID)      { -        if (WorldObject* transport = ObjectAccessor::GetWorldObject(*caster, m_srcTransGUID)) +        if (WorldObject* transport = ObjectAccessor::GetWorldObject(*caster, m_src._transportGUID))          { -            m_srcPos.Relocate(transport); -            m_srcPos.RelocateOffset(m_srcTransOffset); +            m_src._position.Relocate(transport); +            m_src._position.RelocateOffset(m_src._transportOffset);          }      } -    if (HasDst() && m_dstTransGUID) +    if (HasDst() && m_dst._transportGUID)      { -        if (WorldObject* transport = ObjectAccessor::GetWorldObject(*caster, m_dstTransGUID)) +        if (WorldObject* transport = ObjectAccessor::GetWorldObject(*caster, m_dst._transportGUID))          { -            m_dstPos.Relocate(transport); -            m_dstPos.RelocateOffset(m_dstTransOffset); +            m_dst._position.Relocate(transport); +            m_dst._position.RelocateOffset(m_dst._transportOffset);          }      }  } @@ -449,9 +468,9 @@ void SpellCastTargets::OutDebug() const      if (m_targetMask & TARGET_FLAG_TRADE_ITEM)          sLog->outString("Trade item target: " UI64FMTD, m_itemTargetGUID);      if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION) -        sLog->outString("Source location: transport guid:" UI64FMTD " trans offset: %s position: %s", m_srcTransGUID, m_srcTransOffset.ToString().c_str(), m_srcPos.ToString().c_str()); +        sLog->outString("Source location: transport guid:" UI64FMTD " trans offset: %s position: %s", m_src._transportGUID, m_src._transportOffset.ToString().c_str(), m_src._position.ToString().c_str());      if (m_targetMask & TARGET_FLAG_DEST_LOCATION) -        sLog->outString("Destination location: transport guid:" UI64FMTD " trans offset: %s position: %s", m_dstTransGUID, m_dstTransOffset.ToString().c_str(), m_dstPos.ToString().c_str()); +        sLog->outString("Destination location: transport guid:" UI64FMTD " trans offset: %s position: %s", m_dst._transportGUID, m_dst._transportOffset.ToString().c_str(), m_dst._position.ToString().c_str());      if (m_targetMask & TARGET_FLAG_STRING)          sLog->outString("String: %s", m_strTarget.c_str());      sLog->outString("speed: %f", m_speed); @@ -564,6 +583,11 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme      CleanupTargetList();      CleanupEffectExecuteData(); + +    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) +    { +        m_destTargets[i] = SpellDestination(*m_caster); +    }  }  Spell::~Spell() @@ -720,6 +744,9 @@ void Spell::SelectSpellTargets()          // some spell effects don't add anything to target map (confirmed with sniffs) (like SPELL_EFFECT_DESTROY_ALL_TOTEMS)          SelectEffectTypeImplicitTargets(i); +        if (m_targets.HasDst()) +            AddDestTarget(*m_targets.GetDst(), i); +          if (m_spellInfo->IsChanneled())          {              uint8 mask = (1 << i); @@ -767,7 +794,7 @@ void Spell::SelectSpellTargets()          }          else if (m_spellInfo->Speed > 0.0f)          { -            float dist = m_caster->GetDistance(*m_targets.GetDst()); +            float dist = m_caster->GetDistance(*m_targets.GetDstPos());              m_delayMoment = (uint64) floor(dist / m_spellInfo->Speed * 1000.0f);          }      } @@ -826,7 +853,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar                              m_targets.SetSrc(*m_caster);                              break;                          default: -                            ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_SRC"); +                            ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_SRC");                              break;                      }                      break; @@ -843,7 +870,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar                               SelectImplicitDestDestTargets(effIndex, targetType);                               break;                           default: -                             ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST"); +                             ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST");                               break;                       }                       break; @@ -857,7 +884,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar                              SelectImplicitTargetObjectTargets(effIndex, targetType);                              break;                          default: -                            ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT"); +                            ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT");                              break;                      }                      break; @@ -1092,10 +1119,10 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge      switch (targetType.GetReferenceType())      {          case TARGET_REFERENCE_TYPE_SRC: -            center = m_targets.GetSrc(); +            center = m_targets.GetSrcPos();              break;          case TARGET_REFERENCE_TYPE_DEST: -            center = m_targets.GetDst(); +            center = m_targets.GetDstPos();              break;          case TARGET_REFERENCE_TYPE_CASTER:          case TARGET_REFERENCE_TYPE_TARGET: @@ -1467,7 +1494,7 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT      if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM)          dist *= (float)rand_norm(); -    Position pos = *m_targets.GetDst(); +    Position pos = *m_targets.GetDstPos();      m_caster->MovePosition(pos, dist, angle);      m_targets.ModDst(pos);  } @@ -1581,12 +1608,12 @@ void Spell::SelectImplicitTrajTargets()      if (!dist2d)          return; -    float srcToDestDelta = m_targets.GetDst()->m_positionZ - m_targets.GetSrc()->m_positionZ; +    float srcToDestDelta = m_targets.GetDstPos()->m_positionZ - m_targets.GetSrcPos()->m_positionZ;      std::list<WorldObject*> targets; -    Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, m_targets.GetSrc(), m_caster, m_spellInfo); +    Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, m_targets.GetSrcPos(), m_caster, m_spellInfo);      Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> searcher(m_caster, targets, check, GRID_MAP_TYPE_MASK_ALL); -    SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, m_targets.GetSrc(), dist2d); +    SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, m_targets.GetSrcPos(), dist2d);      if (targets.empty())          return; @@ -1609,8 +1636,8 @@ void Spell::SelectImplicitTrajTargets()          const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3)          // TODO: all calculation should be based on src instead of m_caster -        const float objDist2d = m_targets.GetSrc()->GetExactDist2d(*itr) * cos(m_targets.GetSrc()->GetRelativeAngle(*itr)); -        const float dz = (*itr)->GetPositionZ() - m_targets.GetSrc()->m_positionZ; +        const float objDist2d = m_targets.GetSrcPos()->GetExactDist2d(*itr) * cos(m_targets.GetSrcPos()->GetRelativeAngle(*itr)); +        const float dz = (*itr)->GetPositionZ() - m_targets.GetSrcPos()->m_positionZ;          DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: check %u, dist between %f %f, height between %f %f.", (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size);) @@ -1675,11 +1702,11 @@ void Spell::SelectImplicitTrajTargets()          }      } -    if (m_targets.GetSrc()->GetExactDist2d(m_targets.GetDst()) > bestDist) +    if (m_targets.GetSrcPos()->GetExactDist2d(m_targets.GetDstPos()) > bestDist)      { -        float x = m_targets.GetSrc()->m_positionX + cos(m_caster->GetOrientation()) * bestDist; -        float y = m_targets.GetSrc()->m_positionY + sin(m_caster->GetOrientation()) * bestDist; -        float z = m_targets.GetSrc()->m_positionZ + bestDist * (a * bestDist + b); +        float x = m_targets.GetSrcPos()->m_positionX + cos(m_caster->GetOrientation()) * bestDist; +        float y = m_targets.GetSrcPos()->m_positionY + sin(m_caster->GetOrientation()) * bestDist; +        float z = m_targets.GetSrcPos()->m_positionZ + bestDist * (a * bestDist + b);          if (itr != targets.end())          { @@ -2216,12 +2243,6 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask)      m_UniqueGOTargetInfo.push_back(target);  } -void Spell::AddGOTarget(uint64 goGUID, uint32 effectMask) -{ -    if (GameObject* go = m_caster->GetMap()->GetGameObject(goGUID)) -        AddGOTarget(go, effectMask); -} -  void Spell::AddItemTarget(Item* item, uint32 effectMask)  {      for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) @@ -2251,6 +2272,11 @@ void Spell::AddItemTarget(Item* item, uint32 effectMask)      m_UniqueItemInfo.push_back(target);  } +void Spell::AddDestTarget(SpellDestination const& dest, uint32 effIndex) +{ +    m_destTargets[effIndex] = dest; +} +  void Spell::DoAllEffectOnTarget(TargetInfo* target)  {      if (!target || target->processed) @@ -2861,34 +2887,6 @@ bool Spell::UpdateChanneledTargetList()      return channelTargetEffectMask == 0;  } -// Helper for Chain Healing -// Spell target first -// Raidmates then descending by injury suffered (MaxHealth - Health) -// Other players/mobs then descending by injury suffered (MaxHealth - Health) -struct ChainHealingOrder : public std::binary_function<const Unit*, const Unit*, bool> -{ -    const Unit* MainTarget; -    ChainHealingOrder(Unit const* Target) : MainTarget(Target) {}; -    // functor for operator ">" -    bool operator()(Unit const* _Left, Unit const* _Right) const -    { -        return (ChainHealingHash(_Left) < ChainHealingHash(_Right)); -    } - -    int32 ChainHealingHash(Unit const* Target) const -    { -        if (Target->GetTypeId() == TYPEID_PLAYER && MainTarget->GetTypeId() == TYPEID_PLAYER && Target->ToPlayer()->IsInSameRaidWith(MainTarget->ToPlayer())) -        { -            if (Target->IsFullHealth()) -                return 40000; -            else -                return 20000 - Target->GetMaxHealth() + Target->GetHealth(); -        } -        else -            return 40000 - Target->GetMaxHealth() + Target->GetHealth(); -    } -}; -  void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura)  {      if (m_CastItem) @@ -4605,6 +4603,7 @@ void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOT      unitTarget = pUnitTarget;      itemTarget = pItemTarget;      gameObjTarget = pGOTarget; +    destTarget = &m_destTargets[i]._position;      uint8 eff = m_spellInfo->Effects[i].Effect; @@ -4845,7 +4844,7 @@ SpellCastResult Spell::CheckCast(bool strict)      if (m_targets.HasDst())      {          float x, y, z; -        m_targets.GetDst()->GetPosition(x, y, z); +        m_targets.GetDstPos()->GetPosition(x, y, z);          if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOS(x, y, z))              return SPELL_FAILED_LINE_OF_SIGHT; @@ -5782,9 +5781,9 @@ SpellCastResult Spell::CheckRange(bool strict)      if (m_targets.HasDst() && !m_targets.HasTraj())      { -        if (!m_caster->IsWithinDist3d(m_targets.GetDst(), max_range)) +        if (!m_caster->IsWithinDist3d(m_targets.GetDstPos(), max_range))              return SPELL_FAILED_OUT_OF_RANGE; -        if (min_range && m_caster->IsWithinDist3d(m_targets.GetDst(), min_range)) +        if (min_range && m_caster->IsWithinDist3d(m_targets.GetDstPos(), min_range))              return SPELL_FAILED_TOO_CLOSE;      } @@ -6431,6 +6430,30 @@ void Spell::UpdatePointers()          m_CastItem = m_caster->ToPlayer()->GetItemByGuid(m_castItemGUID);      m_targets.Update(m_caster); + +    // further actions done only for dest targets +    if (!m_targets.HasDst()) +        return; + +    // cache last transport +    WorldObject* transport = NULL; + +    // update effect destinations (in case of moved transport dest target) +    for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) +    { +        SpellDestination& dest = m_destTargets[effIndex]; +        if (!dest._transportGUID) +            continue; +         +        if (!transport || transport->GetGUID() != dest._transportGUID) +            transport = ObjectAccessor::GetWorldObject(*m_caster, dest._transportGUID); + +        if (transport) +        { +            dest._position.Relocate(transport); +            dest._position.RelocateOffset(dest._transportOffset); +        } +    }  }  CurrentSpellTypes Spell::GetCurrentContainer() const diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 971bc1989ab..f897092e519 100755 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -79,6 +79,18 @@ enum SpellRangeFlag      SPELL_RANGE_RANGED              = 2,     //hunter range and ranged weapon  }; +struct SpellDestination +{ +    SpellDestination(); +    SpellDestination(float x, float y, float z, float orientation = 0.0f, uint32 mapId = MAPID_INVALID); +    SpellDestination(Position const& pos); +    SpellDestination(WorldObject const& wObj); + +    WorldLocation _position; +    uint64 _transportGUID; +    Position _transportOffset; +}; +  class SpellCastTargets  {      public: @@ -115,14 +127,16 @@ class SpellCastTargets          void SetTradeItemTarget(Player* caster);          void UpdateTradeSlotItem(); -        Position const* GetSrc() const; +        SpellDestination const* GetSrc() const; +        Position const* GetSrcPos() const;          void SetSrc(float x, float y, float z);          void SetSrc(Position const& pos);          void SetSrc(WorldObject const& wObj);          void ModSrc(Position const& pos);          void RemoveSrc(); -        WorldLocation const* GetDst() const; +        SpellDestination const* GetDst() const; +        WorldLocation const* GetDstPos() const;          void SetDst(float x, float y, float z, float orientation, uint32 mapId = MAPID_INVALID);          void SetDst(Position const& pos);          void SetDst(WorldObject const& wObj); @@ -139,7 +153,7 @@ class SpellCastTargets          float GetSpeed() const { return m_speed; }          void SetSpeed(float speed) { m_speed = speed; } -        float GetDist2d() const { return m_srcPos.GetExactDist2d(&m_dstPos); } +        float GetDist2d() const { return m_src._position.GetExactDist2d(&m_dst._position); }          float GetSpeedXY() const { return m_speed * cos(m_elevation); }          float GetSpeedZ() const { return m_speed * sin(m_elevation); } @@ -158,13 +172,8 @@ class SpellCastTargets          uint64 m_itemTargetGUID;          uint32 m_itemTargetEntry; -        uint64 m_srcTransGUID; -        Position m_srcTransOffset; -        Position m_srcPos; - -        uint64 m_dstTransGUID; -        Position m_dstTransOffset; -        WorldLocation m_dstPos; +        SpellDestination m_src; +        SpellDestination m_dst;          float m_elevation, m_speed;          std::string m_strTarget; @@ -197,11 +206,6 @@ enum SpellEffectHandleMode      SPELL_EFFECT_HANDLE_HIT_TARGET,  }; -namespace Trinity -{ -    struct SpellNotifierCreatureAndPlayer; -} -  class Spell  {      friend void Unit::SetCurrentCastedSpell(Spell* pSpell); @@ -529,6 +533,7 @@ class Spell          Unit* unitTarget;          Item* itemTarget;          GameObject* gameObjTarget; +        WorldLocation* destTarget;          int32 damage;          SpellEffectHandleMode effectHandleMode;          // used in effects handlers @@ -589,10 +594,13 @@ class Spell          };          std::list<ItemTargetInfo> m_UniqueItemInfo; +        SpellDestination m_destTargets[MAX_SPELL_EFFECTS]; +          void AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid = true);          void AddGOTarget(GameObject* target, uint32 effectMask); -        void AddGOTarget(uint64 goGUID, uint32 effectMask);          void AddItemTarget(Item* item, uint32 effectMask); +        void AddDestTarget(SpellDestination const& dest, uint32 effIndex); +          void DoAllEffectOnTarget(TargetInfo* target);          SpellMissInfo DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleAura);          void DoTriggersOnSpellHit(Unit* unit, uint8 effMask); @@ -631,7 +639,6 @@ class Spell          HitTriggerSpells m_hitTriggerSpells;          // effect helpers -        void GetSummonPosition(uint32 i, Position &pos, float radius = 0.0f, uint32 count = 0);          void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numSummons);          void CalculateJumpSpeeds(uint8 i, float dist, float & speedxy, float & speedz); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 511d2877f24..59b6d8971cf 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -800,7 +800,7 @@ void Spell::EffectDummy(SpellEffIndex effIndex)                          bp = 46585;                      if (m_targets.HasDst()) -                        targets.SetDst(*m_targets.GetDst()); +                        targets.SetDst(*m_targets.GetDstPos());                      else                      {                          targets.SetDst(*m_caster); @@ -814,8 +814,7 @@ void Spell::EffectDummy(SpellEffIndex effIndex)                  // Raise dead - take reagents and trigger summon spells                  case 48289:                      if (m_targets.HasDst()) -                        targets.SetDst(*m_targets.GetDst()); - +                        targets.SetDst(*m_targets.GetDstPos());                      spell_id = CalculateDamage(0, NULL);                      break;              } @@ -1177,7 +1176,7 @@ void Spell::EffectJumpDest(SpellEffIndex effIndex)      // Init dest coordinates      float x, y, z; -    m_targets.GetDst()->GetPosition(x, y, z); +    destTarget->GetPosition(x, y, z);      float speedXY, speedZ;      CalculateJumpSpeeds(effIndex, m_caster->GetExactDist2d(x, y), speedXY, speedZ); @@ -1250,11 +1249,11 @@ void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/)      }      // Init dest coordinates -    uint32 mapid = m_targets.GetDst()->GetMapId(); +    uint32 mapid = destTarget->GetMapId();      if (mapid == MAPID_INVALID)          mapid = unitTarget->GetMapId();      float x, y, z, orientation; -    m_targets.GetDst()->GetPosition(x, y, z, orientation); +    destTarget->GetPosition(x, y, z, orientation);      if (!orientation && m_targets.GetUnitTarget())          orientation = m_targets.GetUnitTarget()->GetOrientation();      sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTeleportUnits - teleport unit to %u %f %f %f %f\n", mapid, x, y, z, orientation); @@ -1883,7 +1882,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex)          if (!caster->IsInWorld())              return;          DynamicObject* dynObj = new DynamicObject(false); -        if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, *m_targets.GetDst(), radius, DYNAMIC_OBJECT_AREA_SPELL)) +        if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL))          {              delete dynObj;              return; @@ -2357,9 +2356,6 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)      if (Player* modOwner = m_originalCaster->GetSpellModOwner())          modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration); -    Position pos; -    GetSummonPosition(effIndex, pos); -      TempSummon* summon = NULL;      // determine how many units should be summoned @@ -2413,11 +2409,11 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)                  // Summons a vehicle, but doesn't force anyone to enter it (see SUMMON_CATEGORY_VEHICLE)                  case SUMMON_TYPE_VEHICLE:                  case SUMMON_TYPE_VEHICLE2: -                    summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_originalCaster, m_spellInfo->Id); +                    summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);                      break;                  case SUMMON_TYPE_TOTEM:                  { -                    summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_originalCaster, m_spellInfo->Id); +                    summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);                      if (!summon || !summon->isTotem())                          return; @@ -2434,7 +2430,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)                  }                  case SUMMON_TYPE_MINIPET:                  { -                    summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_originalCaster, m_spellInfo->Id); +                    summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);                      if (!summon || !summon->HasUnitTypeMask(UNIT_MASK_MINION))                          return; @@ -2454,9 +2450,14 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)                      for (uint32 count = 0; count < numSummons; ++count)                      { -                        GetSummonPosition(effIndex, pos, radius, count); +                        Position pos; +                        if (count == 0) +                            pos = *destTarget; +                        else +                            // randomize position for multiple summons +                            m_caster->GetRandomPoint(*destTarget, radius, pos); -                        summon = m_originalCaster->SummonCreature(entry, pos, summonType, duration); +                        summon = m_originalCaster->SummonCreature(entry, *destTarget, summonType, duration);                          if (!summon)                              continue; @@ -2477,14 +2478,14 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)              SummonGuardian(effIndex, entry, properties, numSummons);              break;          case SUMMON_CATEGORY_PUPPET: -            summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_originalCaster, m_spellInfo->Id); +            summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);              break;          case SUMMON_CATEGORY_VEHICLE:              // Summoning spells (usually triggered by npc_spellclick) that spawn a vehicle and that cause the clicker              // to cast a ride vehicle spell on the summoned unit.              float x, y, z;              m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); -            summon = m_originalCaster->GetMap()->SummonCreature(entry, pos, properties, duration, m_caster, m_spellInfo->Id); +            summon = m_originalCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_caster, m_spellInfo->Id);              if (!summon || !summon->IsVehicle())                  return; @@ -2706,7 +2707,7 @@ void Spell::EffectDistract(SpellEffIndex /*effIndex*/)      if (unitTarget->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING))          return; -    unitTarget->SetFacingTo(unitTarget->GetAngle(m_targets.GetDst())); +    unitTarget->SetFacingTo(unitTarget->GetAngle(destTarget));      unitTarget->ClearUnitState(UNIT_STATE_MOVING);      if (unitTarget->GetTypeId() == TYPEID_UNIT) @@ -2745,7 +2746,7 @@ void Spell::EffectAddFarsight(SpellEffIndex effIndex)          return;      DynamicObject* dynObj = new DynamicObject(true); -    if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, *m_targets.GetDst(), radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS)) +    if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))      {          delete dynObj;          return; @@ -3689,7 +3690,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)      float x, y, z;      if (m_targets.HasDst()) -        m_targets.GetDst()->GetPosition(x, y, z); +        destTarget->GetPosition(x, y, z);      else          m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); @@ -4232,7 +4233,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)                      float radius = m_spellInfo->Effects[effIndex].CalcRadius();                      for (uint8 i = 0; i < 15; ++i)                      { -                        m_caster->GetRandomPoint(*m_targets.GetDst(), radius, x, y, z); +                        m_caster->GetRandomPoint(*destTarget, radius, x, y, z);                          m_caster->CastSpell(x, y, z, 54522, true);                      }                      break; @@ -5268,7 +5269,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex)      float x, y, z;      // If dest location if present      if (m_targets.HasDst()) -        m_targets.GetDst()->GetPosition(x, y, z); +        destTarget->GetPosition(x, y, z);      // Summon in random point all other units if location present      else          m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); @@ -5398,7 +5399,7 @@ void Spell::EffectLeap(SpellEffIndex /*effIndex*/)          return;      Position pos; -    m_targets.GetDst()->GetPosition(&pos); +    destTarget->GetPosition(&pos);      unitTarget->GetFirstCollisionPosition(pos, unitTarget->GetDistance(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() + 2.0f), 0.0f);      unitTarget->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), unitTarget == m_caster);  } @@ -5569,7 +5570,7 @@ void Spell::EffectChargeDest(SpellEffIndex /*effIndex*/)      if (m_targets.HasDst())      {          Position pos; -        m_targets.GetDst()->GetPosition(&pos); +        destTarget->GetPosition(&pos);          float angle = m_caster->GetRelativeAngle(pos.GetPositionX(), pos.GetPositionY());          float dist = m_caster->GetDistance(pos);          m_caster->GetFirstCollisionPosition(pos, dist, angle); @@ -5620,7 +5621,7 @@ void Spell::EffectKnockBack(SpellEffIndex effIndex)      if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_KNOCK_BACK_DEST)      {          if (m_targets.HasDst()) -            m_targets.GetDst()->GetPosition(x, y); +            destTarget->GetPosition(x, y);          else              return;      } @@ -5708,7 +5709,7 @@ void Spell::EffectPullTowards(SpellEffIndex effIndex)      if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_PULL_TOWARDS_DEST)      {          if (m_targets.HasDst()) -            pos.Relocate(*m_targets.GetDst()); +            pos.Relocate(*destTarget);          else              return;      } @@ -5895,7 +5896,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)      float fx, fy, fz;      if (m_targets.HasDst()) -        m_targets.GetDst()->GetPosition(fx, fy, fz); +        destTarget->GetPosition(fx, fy, fz);      //FIXME: this can be better check for most objects but still hack      else if (m_spellInfo->Effects[effIndex].HasRadius() && m_spellInfo->Speed == 0)      { @@ -6476,7 +6477,11 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const*      for (uint32 count = 0; count < numGuardians; ++count)      {          Position pos; -        GetSummonPosition(i, pos, radius, count); +        if (count == 0) +            pos = *destTarget; +        else +            // randomize position for multiple summons +            m_caster->GetRandomPoint(*destTarget, radius, pos);          TempSummon* summon = map->SummonCreature(entry, pos, properties, duration, caster, m_spellInfo->Id);          if (!summon) @@ -6507,44 +6512,6 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const*      }  } -void Spell::GetSummonPosition(uint32 i, Position &pos, float radius, uint32 count) -{ -    pos.SetOrientation(m_caster->GetOrientation()); - -    if (m_targets.HasDst()) -    { -        // Summon 1 unit in dest location -        if (count == 0) -            pos.Relocate(*m_targets.GetDst()); -        // Summon in random point all other units if location present -        else -        { -            //This is a workaround. Do not have time to write much about it -            switch (m_spellInfo->Effects[i].TargetA.GetTarget()) -            { -                case TARGET_DEST_CASTER_SUMMON: -                case TARGET_DEST_CASTER_RANDOM: -                    m_caster->GetNearPosition(pos, radius * (float)rand_norm(), (float)rand_norm()*static_cast<float>(2*M_PI)); -                    break; -                case TARGET_DEST_DEST_RANDOM: -                case TARGET_DEST_TARGET_RANDOM: -                    m_caster->GetRandomPoint(*m_targets.GetDst(), radius, pos); -                    break; -                default: -                    pos.Relocate(*m_targets.GetDst()); -                    break; -            } -        } -    } -    // Summon if dest location not present near caster -    else -    { -        float x, y, z; -        m_caster->GetClosePoint(x, y, z, 3.0f); -        pos.Relocate(x, y, z); -    } -} -  void Spell::EffectRenamePet(SpellEffIndex /*effIndex*/)  {      if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 626e0a3653e..b95ee766f38 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -99,7 +99,7 @@ float SpellImplicitTargetInfo::CalcDirectionAngle() const          case TARGET_DIR_LEFT:              return static_cast<float>(M_PI/2);          case TARGET_DIR_FRONT_RIGHT: -            return static_cast<float>(M_PI/4); +            return static_cast<float>(-M_PI/4);          case TARGET_DIR_BACK_RIGHT:              return static_cast<float>(-3*M_PI/4);          case TARGET_DIR_BACK_LEFT: @@ -614,7 +614,7 @@ SpellEffectInfo::StaticData  SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =      {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 66 SPELL_EFFECT_CREATE_MANA_GEM      {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH      {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 68 SPELL_EFFECT_INTERRUPT_CAST -    {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 69 SPELL_EFFECT_DISTRACT +    {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 69 SPELL_EFFECT_DISTRACT      {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 70 SPELL_EFFECT_PULL      {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 71 SPELL_EFFECT_PICKPOCKET      {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 72 SPELL_EFFECT_ADD_FARSIGHT @@ -1192,7 +1192,6 @@ bool SpellInfo::IsAuraExclusiveBySpecificWith(SpellInfo const* spellInfo) const      SpellSpecificType spellSpec2 = spellInfo->GetSpellSpecific();      switch (spellSpec1)      { -        case SPELL_SPECIFIC_PHASE:          case SPELL_SPECIFIC_TRACKER:          case SPELL_SPECIFIC_WARLOCK_ARMOR:          case SPELL_SPECIFIC_MAGE_ARMOR: @@ -1911,8 +1910,6 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const                  case SPELL_AURA_TRACK_RESOURCES:                  case SPELL_AURA_TRACK_STEALTHED:                      return SPELL_SPECIFIC_TRACKER; -                case SPELL_AURA_PHASE: -                    return SPELL_SPECIFIC_PHASE;              }          }      } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 9c33db7f708..b82f7dbd61d 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -166,7 +166,6 @@ enum SpellSpecificType      SPELL_SPECIFIC_WARRIOR_ENRAGE                = 26,      SPELL_SPECIFIC_PRIEST_DIVINE_SPIRIT          = 27,      SPELL_SPECIFIC_HAND                          = 28, -    SPELL_SPECIFIC_PHASE                         = 29,  };  enum SpellCustomAttributes diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 03fea614c0d..81f8bbd78c5 100755 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -323,7 +323,7 @@ SpellInfo const* SpellScript::GetSpellInfo()  WorldLocation const* SpellScript::GetTargetDest()  {      if (m_spell->m_targets.HasDst()) -        return m_spell->m_targets.GetDst(); +        return m_spell->m_targets.GetDstPos();      return NULL;  } @@ -403,6 +403,16 @@ GameObject* SpellScript::GetHitGObj()      return m_spell->gameObjTarget;  } +WorldLocation const* SpellScript::GetHitDest() +{ +    if (!IsInEffectHook()) +    { +        sLog->outError("TSCR: Script: `%s` Spell: `%u`: function SpellScript::GetHitGObj was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); +        return NULL; +    } +    return m_spell->destTarget; +} +  int32 SpellScript::GetHitDamage()  {      if (!IsInTargetHook()) @@ -468,11 +478,6 @@ void SpellScript::PreventHitAura()          m_spell->m_spellAura->Remove();  } -void SpellScript::GetSummonPosition(uint32 i, Position &pos, float radius = 0.0f, uint32 count = 0) -{ -    m_spell->GetSummonPosition(i, pos, radius, count); -} -  void SpellScript::PreventHitEffect(SpellEffIndex effIndex)  {      if (!IsInHitPhase() && !IsInEffectHook()) diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 1bf8d25adef..e84a56c8dbb 100755 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -324,6 +324,8 @@ class SpellScript : public _SpellScript          Item* GetHitItem();          // returns: target of current effect if it was GameObject otherwise NULL          GameObject* GetHitGObj(); +        // returns: destination of current effect +        WorldLocation const* GetHitDest();          // setter/getter for for damage done by spell to target of spell hit          // returns damage calculated before hit, and real dmg done after hit          int32 GetHitDamage(); @@ -335,7 +337,6 @@ class SpellScript : public _SpellScript          void SetHitHeal(int32 heal);          void PreventHitHeal() { SetHitHeal(0); }          Spell* GetSpell() { return m_spell; } -        void GetSummonPosition(uint32 i, Position &pos, float radius, uint32 count);          // returns current spell hit target aura          Aura* GetHitAura();          // prevents applying aura on current spell hit target diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp index e5a12693aa7..f1088f54007 100755 --- a/src/server/game/Texts/CreatureTextMgr.cpp +++ b/src/server/game/Texts/CreatureTextMgr.cpp @@ -17,8 +17,53 @@  #include "Common.h"  #include "DatabaseEnv.h" -#include "CreatureTextMgr.h"  #include "ObjectMgr.h" +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CreatureTextMgr.h" + +class CreatureTextBuilder +{ +    public: +        CreatureTextBuilder(WorldObject* obj, ChatMsg msgtype, uint8 textGroup, uint32 id, uint32 language, uint64 targetGUID) +            : _source(obj), _msgType(msgtype), _textGroup(textGroup), _textId(id), _language(language), _targetGUID(targetGUID) +        { +        } + +        size_t operator()(WorldPacket* data, LocaleConstant locale) const +        { +            std::string text = sCreatureTextMgr->GetLocalizedChatString(_source->GetEntry(), _textGroup, _textId, locale); +            char const* localizedName = _source->GetNameForLocaleIdx(locale); + +            *data << uint8(_msgType); +            *data << uint32(_language); +            *data << uint64(_source->GetGUID()); +            *data << uint32(1);                                      // 2.1.0 +            *data << uint32(strlen(localizedName)+1); +            *data << localizedName; +            size_t whisperGUIDpos = data->wpos(); +            *data << uint64(_targetGUID);                           // Unit Target +            if (_targetGUID && !IS_PLAYER_GUID(_targetGUID)) +            { +                *data << uint32(1);                                  // target name length +                *data << uint8(0);                                   // target name +            } +            *data << uint32(text.length() + 1); +            *data << text; +            *data << uint8(0);                                       // ChatTag + +            return whisperGUIDpos; +        } + +        WorldObject* _source; +        ChatMsg _msgType; +        uint8 _textGroup; +        uint32 _textId; +        uint32 _language; +        uint64 _targetGUID; +};  void CreatureTextMgr::LoadCreatureTexts()  { @@ -83,17 +128,8 @@ void CreatureTextMgr::LoadCreatureTexts()          }          //entry not yet added, add empty TextHolder (list of groups)          if (mTextMap.find(temp.entry) == mTextMap.end()) -        {              ++creatureCount; -            CreatureTextHolder TextHolder; -            mTextMap[temp.entry] = TextHolder; -        } -        //group not yet added, add empty TextGroup (list of texts) -        if (mTextMap[temp.entry].find(temp.group) == mTextMap[temp.entry].end()) -        { -            CreatureTextGroup TextGroup; -            mTextMap[temp.entry][temp.group] = TextGroup; -        } +          //add the text into our entry's group          mTextMap[temp.entry][temp.group].push_back(temp); @@ -104,42 +140,76 @@ void CreatureTextMgr::LoadCreatureTexts()      sLog->outString();  } +void CreatureTextMgr::LoadCreatureTextLocales() +{ +    uint32 oldMSTime = getMSTime(); + +    mLocaleTextMap.clear(); // for reload case + +    QueryResult result = WorldDatabase.Query("SELECT entry, textGroup, id, text_loc1, text_loc2, text_loc3, text_loc4, text_loc5, text_loc6, text_loc7, text_loc8 FROM locales_creature_text"); + +    if (!result) +        return; + +    uint32 textCount = 0; + +    do +    { +        Field* fields = result->Fetch(); +        CreatureTextLocale& loc = mLocaleTextMap[CreatureTextId(fields[0].GetUInt32(), uint32(fields[1].GetUInt8()), fields[2].GetUInt32())]; +        for (uint8 i = 1; i < TOTAL_LOCALES; ++i) +        { +            LocaleConstant locale = LocaleConstant(i); +            ObjectMgr::AddLocaleString(fields[2 + i - 1].GetString(), locale, loc.Text); +        } + +        ++textCount; +    } while (result->NextRow()); + +    sLog->outString(">> Loaded %u creature localized texts in %u ms", textCount, GetMSTimeDiffToNow(oldMSTime)); +    sLog->outString(); +} +  uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, uint64 whisperGuid /*= 0*/, ChatMsg msgType /*= CHAT_MSG_ADDON*/, Language language /*= LANG_ADDON*/, TextRange range /*= TEXT_RANGE_NORMAL*/, uint32 sound /*= 0*/, Team team /*= TEAM_OTHER*/, bool gmOnly /*= false*/, Player* srcPlr /*= NULL*/)  {      if (!source)          return 0; +      CreatureTextMap::const_iterator sList = mTextMap.find(source->GetEntry());      if (sList == mTextMap.end())      {          sLog->outErrorDb("CreatureTextMgr: Could not find Text for Creature(%s) Entry %u in 'creature_text' table. Ignoring.", source->GetName(), source->GetEntry());          return 0;      } -    CreatureTextHolder TextHolder = (*sList).second; -    CreatureTextHolder::const_iterator itr = TextHolder.find(textGroup); -    if (itr == TextHolder.end()) + +    CreatureTextHolder const& textHolder = sList->second; +    CreatureTextHolder::const_iterator itr = textHolder.find(textGroup); +    if (itr == textHolder.end())      {          sLog->outErrorDb("CreatureTextMgr: Could not find TextGroup %u for Creature(%s) GuidLow %u Entry %u. Ignoring.", uint32(textGroup), source->GetName(), source->GetGUIDLow(), source->GetEntry());          return 0;      } -    CreatureTextGroup TextGroup = (*itr).second;//has all texts in the group + +    CreatureTextGroup const& textGroupContainer = itr->second;  //has all texts in the group      CreatureTextRepeatIds repeatGroup = GetRepeatGroup(source, textGroup);//has all textIDs from the group that were already said      CreatureTextGroup tempGroup;//will use this to talk after sorting repeatGroup -    for (CreatureTextGroup::const_iterator giter = TextGroup.begin(); giter != TextGroup.end(); ++giter) -    { -        if (std::find(repeatGroup.begin(), repeatGroup.end(), (*giter).id) == repeatGroup.end()) -            tempGroup.push_back((*giter)); -    } +    for (CreatureTextGroup::const_iterator giter = textGroupContainer.begin(); giter != textGroupContainer.end(); ++giter) +        if (std::find(repeatGroup.begin(), repeatGroup.end(), giter->id) == repeatGroup.end()) +            tempGroup.push_back(*giter); +      if (tempGroup.empty())      {          CreatureTextRepeatMap::iterator mapItr = mTextRepeatMap.find(source->GetGUID());          if (mapItr != mTextRepeatMap.end())          { -            CreatureTextRepeatGroup::iterator groupItr = (*mapItr).second.find(textGroup); -            (*groupItr).second.clear(); +            CreatureTextRepeatGroup::iterator groupItr = mapItr->second.find(textGroup); +            groupItr->second.clear();          } -        tempGroup = TextGroup; + +        tempGroup = textGroupContainer;      } +      uint8 count = 0;      float lastChance = -1;      bool isEqualChanced = true; @@ -148,173 +218,92 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, uint64 whisp      for (CreatureTextGroup::const_iterator iter = tempGroup.begin(); iter != tempGroup.end(); ++iter)      { -        if (lastChance >= 0 && lastChance != (*iter).probability) +        if (lastChance >= 0 && lastChance != iter->probability)              isEqualChanced = false; -        lastChance = (*iter).probability; -        totalChance += (*iter).probability; -        count++; +        lastChance = iter->probability; +        totalChance += iter->probability; +        ++count;      } +      int32 offset = -1;      if (!isEqualChanced)      {          for (CreatureTextGroup::const_iterator iter = tempGroup.begin(); iter != tempGroup.end(); ++iter)          { -            uint32 chance = uint32((*iter).probability); +            uint32 chance = uint32(iter->probability);              uint32 r = urand(0, 100); -            offset++; +            ++offset;              if (r <= chance)                  break;          }      } +      uint32 pos = 0;      if (isEqualChanced || offset < 0)          pos = urand(0, count - 1);      else if (offset >= 0)          pos = offset; +      CreatureTextGroup::const_iterator iter = tempGroup.begin() + pos; -    ChatMsg finalType = (msgType == CHAT_MSG_ADDON) ? (*iter).type : msgType; -    Language finalLang = (language == LANG_ADDON) ? (*iter).lang : language; -    uint32 finalSound = sound ? sound : (*iter).sound; +    ChatMsg finalType = (msgType == CHAT_MSG_ADDON) ? iter->type : msgType; +    Language finalLang = (language == LANG_ADDON) ? iter->lang : language; +    uint32 finalSound = sound ? sound : iter->sound;      if (finalSound)          SendSound(source, finalSound, finalType, whisperGuid, range, team, gmOnly); -    if ((*iter).emote) -        SendEmote(srcPlr ? srcPlr->ToUnit() : source, (*iter).emote); - -    SendChatString(srcPlr ? srcPlr->ToUnit() : source, (*iter).text.c_str(), finalType, finalLang, whisperGuid, range, team, gmOnly); -    if (isEqualChanced || (!isEqualChanced && totalChance == 100.0f)) -        SetRepeatId(source, textGroup, (*iter).id); - -    return (*iter).duration; -} - -void CreatureTextMgr::SendSound(Creature* source, uint32 sound, ChatMsg msgType, uint64 whisperGuid, TextRange range, Team team, bool gmOnly) -{ -    if (!sound || !source) -        return; -    WorldPacket data(SMSG_PLAY_SOUND, 4); -    data << uint32(sound); -    SendChatPacket(&data, source, msgType, whisperGuid, range, team, gmOnly); -} - -void CreatureTextMgr::SendEmote(Unit* source, uint32 emote) -{ -    if (!source) return; -    source->HandleEmoteCommand(emote); -} - -void CreatureTextMgr::SetRepeatId(Creature* source, uint8 textGroup, uint8 id) -{ -    if (!source) -        return; - -    if (mTextRepeatMap.find(source->GetGUID()) == mTextRepeatMap.end()) -    { -        CreatureTextRepeatGroup TextGroup; -        mTextRepeatMap[source->GetGUID()] = TextGroup; -    } -    if (mTextRepeatMap[source->GetGUID()].find(textGroup) == mTextRepeatMap[source->GetGUID()].end()) -    { -        CreatureTextRepeatIds ids; -        mTextRepeatMap[source->GetGUID()][textGroup] = ids; -    } -    if (std::find(mTextRepeatMap[source->GetGUID()][textGroup].begin(), mTextRepeatMap[source->GetGUID()][textGroup].end(), id) == mTextRepeatMap[source->GetGUID()][textGroup].end()) -    { -        mTextRepeatMap[source->GetGUID()][textGroup].push_back(id); -    } -    else -        sLog->outErrorDb("CreatureTextMgr: TextGroup %u for Creature(%s) GuidLow %u Entry %u, id %u already added", uint32(textGroup), source->GetName(), source->GetGUIDLow(), source->GetEntry(), uint32(id)); -} - -CreatureTextRepeatIds CreatureTextMgr::GetRepeatGroup(Creature* source, uint8 textGroup) -{ -    ASSERT(source);//should never happen -    CreatureTextRepeatIds ids; +    Unit* finalSource = source; +    if (srcPlr) +        finalSource = srcPlr; -    CreatureTextRepeatMap::const_iterator mapItr = mTextRepeatMap.find(source->GetGUID()); -    if (mapItr != mTextRepeatMap.end()) -    { -        CreatureTextRepeatGroup::const_iterator groupItr = (*mapItr).second.find(textGroup); -        if (groupItr != (*mapItr).second.end()) -        { -            ids = (*groupItr).second; -        } -    } -    return ids; -} +    if (iter->emote) +        SendEmote(finalSource, iter->emote); -void CreatureTextMgr::SendChatString(WorldObject* source, char const* text, ChatMsg msgtype /*= CHAT_MSG_MONSTER_SAY*/, Language language /*= LANG_UNIVERSAL*/, uint64 whisperGuid /*= 0*/, TextRange range /*= TEXT_RANGE_NORMAL*/, Team team /*= TEAM_OTHER*/, bool gmOnly /*= false*/) const -{ -    if (!source) -        return; +    CreatureTextBuilder builder(finalSource, finalType, iter->group, iter->id, finalLang, whisperGuid); +    SendChatPacket(finalSource, builder, finalType, whisperGuid, range, team, gmOnly); +    if (isEqualChanced || (!isEqualChanced && totalChance == 100.0f)) +        SetRepeatId(source, textGroup, iter->id); -    WorldPacket data(SMSG_MESSAGECHAT, 200); -    BuildMonsterChat(&data, source, msgtype, text, language, whisperGuid);//build our packet -    SendChatPacket(&data, source, msgtype, whisperGuid, range, team, gmOnly);//send our packet +    return iter->duration;  } -void CreatureTextMgr::BuildMonsterChat(WorldPacket* data, WorldObject* source, ChatMsg msgType, char const* text, Language language, uint64 whisperGuid) const +float CreatureTextMgr::GetRangeForChatType(ChatMsg msgType) const  { -    if (!source) -        return; - +    float dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY);      switch (msgType)      { -        case CHAT_MSG_MONSTER_WHISPER: -            if (!whisperGuid) -            { -                sLog->outError("CreatureTextMgr: WorldObject(%s) TypeId %u GuidLow %u sent CHAT_TYPE_WHISPER with targetGuid 0. Ignoring.", source->GetName(), uint32(source->GetTypeId()), source->GetGUIDLow()); -                return; -            } +        case CHAT_MSG_MONSTER_YELL: +            dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL);              break; -        case CHAT_MSG_RAID_BOSS_WHISPER: -            if (!whisperGuid) -            { -                sLog->outError("CreatureTextMgr: WorldObject(%s) TypeId %u GuidLow %u sent CHAT_TYPE_BOSS_WHISPER with targetGuid 0. Ignoring.", source->GetName(), uint32(source->GetTypeId()), source->GetGUIDLow()); -                return; -            } +        case CHAT_MSG_MONSTER_EMOTE: +        case CHAT_MSG_RAID_BOSS_EMOTE: +            dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE);              break;          default:              break;      } -    *data << uint8(msgType); -    *data << uint32(language); -    *data << uint64(source->GetGUID()); -    *data << uint32(0);                                     // 2.1.0 -    *data << uint32(strlen(source->GetName()) + 1); -    *data << source->GetName(); -    *data << uint64(whisperGuid);                           // Unit Target -    if (whisperGuid && !IS_PLAYER_GUID(whisperGuid))        //can only whisper players -    { -        sLog->outError("CreatureTextMgr: WorldObject(%s) TypeId %u GuidLow %u sent WHISPER msg to Non-Player target. Ignoring.", source->GetName(), uint32(source->GetTypeId()), source->GetGUIDLow()); -        return; -        // *data << (uint32)1;                                 // target name length -        // *data << (uint8)0;                                  // target name -    } -    *data << uint32(strlen(text) + 1); -    *data << text; -    *data << uint8(0);                                      // ChatTag + +    return dist;  } -void CreatureTextMgr::SendChatPacket(WorldPacket* data, WorldObject* source, ChatMsg msgType, uint64 whisperGuid, TextRange range, Team team, bool gmOnly) const +void CreatureTextMgr::SendSound(Creature* source, uint32 sound, ChatMsg msgType, uint64 whisperGuid, TextRange range, Team team, bool gmOnly)  { -    if (!source) +    if (!sound || !source)          return; -    float dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY); +    WorldPacket data(SMSG_PLAY_SOUND, 4); +    data << uint32(sound); +    SendNonChatPacket(source, &data, msgType, whisperGuid, range, team, gmOnly); +} + +void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket* data, ChatMsg msgType, uint64 whisperGuid, TextRange range, Team team, bool gmOnly) const +{ +    float dist = GetRangeForChatType(msgType);      switch (msgType)      { -        case CHAT_MSG_MONSTER_YELL: -            dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL); -            break; -        case CHAT_MSG_MONSTER_EMOTE: -        case CHAT_MSG_RAID_BOSS_EMOTE: -            dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE); -            break;          case CHAT_MSG_MONSTER_WHISPER:          case CHAT_MSG_RAID_BOSS_WHISPER:          { @@ -337,83 +326,135 @@ void CreatureTextMgr::SendChatPacket(WorldPacket* data, WorldObject* source, Cha          case TEXT_RANGE_AREA:          {              uint32 areaId = source->GetAreaId(); -            Map::PlayerList const& pList = source->GetMap()->GetPlayers(); -            for (Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr) -            { +            Map::PlayerList const& players = source->GetMap()->GetPlayers(); +            for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)                  if (itr->getSource()->GetAreaId() == areaId && (!team || Team(itr->getSource()->GetTeam()) == team) && (!gmOnly || itr->getSource()->isGameMaster())) -                { -                    if (data->GetOpcode() == SMSG_MESSAGECHAT)//override whisperguid with actual player's guid -                        data->put<uint64>(1+4+8+4+4+(int32)(strlen(source->GetName())+1), uint64(itr->getSource()->GetGUID())); -                    (itr->getSource())->GetSession()->SendPacket(data); -                } -            } +                    itr->getSource()->GetSession()->SendPacket(data);              return;          }          case TEXT_RANGE_ZONE:          {              uint32 zoneId = source->GetZoneId(); -            Map::PlayerList const& pList = source->GetMap()->GetPlayers(); -            for (Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr) -            { +            Map::PlayerList const& players = source->GetMap()->GetPlayers(); +            for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)                  if (itr->getSource()->GetZoneId() == zoneId && (!team || Team(itr->getSource()->GetTeam()) == team) && (!gmOnly || itr->getSource()->isGameMaster())) -                { -                    if (data->GetOpcode() == SMSG_MESSAGECHAT)//override whisperguid with actual player's guid -                        data->put<uint64>(1+4+8+4+4+(int32)(strlen(source->GetName())+1), uint64(itr->getSource()->GetGUID())); -                    (itr->getSource())->GetSession()->SendPacket(data); -                } -            } +                    itr->getSource()->GetSession()->SendPacket(data);              return;          }          case TEXT_RANGE_MAP:          { -            Map::PlayerList const& pList = source->GetMap()->GetPlayers(); -            for (Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr) -            { -                if (data->GetOpcode() == SMSG_MESSAGECHAT)//override whisperguid with actual player's guid -                    data->put<uint64>(1+4+8+4+4+(int32)(strlen(source->GetName())+1), uint64(itr->getSource()->GetGUID())); +            Map::PlayerList const& players = source->GetMap()->GetPlayers(); +            for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)                  if ((!team || Team(itr->getSource()->GetTeam()) == team) && (!gmOnly || itr->getSource()->isGameMaster())) -                    (itr->getSource())->GetSession()->SendPacket(data); -            } +                    itr->getSource()->GetSession()->SendPacket(data);              return;          }          case TEXT_RANGE_WORLD:          { -            const SessionMap smap = sWorld->GetAllSessions(); +            SessionMap const& smap = sWorld->GetAllSessions();              for (SessionMap::const_iterator iter = smap.begin(); iter != smap.end(); ++iter) -            { -                if (Player* player = (*iter).second->GetPlayer()) -                { -                    if (data->GetOpcode() == SMSG_MESSAGECHAT)//override whisperguid with actual player's guid -                        data->put<uint64>(1+4+8+4+4+(int32)(strlen(source->GetName())+1), uint64(player->GetGUID())); +                if (Player* player = iter->second->GetPlayer())                      if (player->GetSession()  && (!team || Team(player->GetTeam()) == team) && (!gmOnly || player->isGameMaster()))                          player->GetSession()->SendPacket(data); -                } -            }              return;          }          case TEXT_RANGE_NORMAL:          default:              break;      } +      source->SendMessageToSetInRange(data, dist, true);  } +void CreatureTextMgr::SendEmote(Unit* source, uint32 emote) +{ +    if (!source) +        return; + +    source->HandleEmoteCommand(emote); +} + +void CreatureTextMgr::SetRepeatId(Creature* source, uint8 textGroup, uint8 id) +{ +    if (!source) +        return; + +    CreatureTextRepeatIds& repeats = mTextRepeatMap[source->GetGUID()][textGroup]; +    if (std::find(repeats.begin(), repeats.end(), id) == repeats.end()) +        repeats.push_back(id); +    else +        sLog->outErrorDb("CreatureTextMgr: TextGroup %u for Creature(%s) GuidLow %u Entry %u, id %u already added", uint32(textGroup), source->GetName(), source->GetGUIDLow(), source->GetEntry(), uint32(id)); +} + +CreatureTextRepeatIds CreatureTextMgr::GetRepeatGroup(Creature* source, uint8 textGroup) +{ +    ASSERT(source);//should never happen +    CreatureTextRepeatIds ids; + +    CreatureTextRepeatMap::const_iterator mapItr = mTextRepeatMap.find(source->GetGUID()); +    if (mapItr != mTextRepeatMap.end()) +    { +        CreatureTextRepeatGroup::const_iterator groupItr = (*mapItr).second.find(textGroup); +        if (groupItr != mapItr->second.end()) +            ids = groupItr->second; +    } +    return ids; +} +  bool CreatureTextMgr::TextExist(uint32 sourceEntry, uint8 textGroup)  {      if (!sourceEntry)          return false; +      CreatureTextMap::const_iterator sList = mTextMap.find(sourceEntry);      if (sList == mTextMap.end())      {          sLog->outDebug(LOG_FILTER_UNITS, "CreatureTextMgr::TextExist: Could not find Text for Creature (entry %u) in 'creature_text' table.", sourceEntry);          return false;      } -    CreatureTextHolder TextHolder = (*sList).second; -    CreatureTextHolder::const_iterator itr = TextHolder.find(textGroup); -    if (itr == TextHolder.end()) + +    CreatureTextHolder const& textHolder = sList->second; +    CreatureTextHolder::const_iterator itr = textHolder.find(textGroup); +    if (itr == textHolder.end())      {          sLog->outDebug(LOG_FILTER_UNITS, "CreatureTextMgr::TextExist: Could not find TextGroup %u for Creature (entry %u).", uint32(textGroup), sourceEntry);          return false;      } +      return true;  } + +std::string CreatureTextMgr::GetLocalizedChatString(uint32 entry, uint8 textGroup, uint32 id, LocaleConstant locale) const +{ +    CreatureTextMap::const_iterator mapitr = mTextMap.find(entry); +    if (mapitr == mTextMap.end()) +        return ""; + +    CreatureTextHolder::const_iterator holderItr = mapitr->second.find(textGroup); +    if (holderItr == mapitr->second.end()) +        return ""; + +    CreatureTextGroup::const_iterator groupItr = holderItr->second.begin(); +    for (; groupItr != holderItr->second.end(); ++groupItr) +        if (groupItr->id == id) +            break; + +    if (groupItr == holderItr->second.end()) +        return ""; + +    std::string baseText = groupItr->text; +    if (locale == DEFAULT_LOCALE) +        return baseText; + +    if (locale > MAX_LOCALES) +        return baseText; + +    LocaleCreatureTextMap::const_iterator locItr = mLocaleTextMap.find(CreatureTextId(entry, uint32(textGroup), id)); +    if (locItr == mLocaleTextMap.end()) +        return baseText; + +    if (locItr->second.Text[locale].length()) +        return locItr->second.Text[locale]; + +    return baseText; +} diff --git a/src/server/game/Texts/CreatureTextMgr.h b/src/server/game/Texts/CreatureTextMgr.h index 0c80e2d568f..ddf10568411 100755 --- a/src/server/game/Texts/CreatureTextMgr.h +++ b/src/server/game/Texts/CreatureTextMgr.h @@ -19,6 +19,8 @@  #define TRINITY_CREATURE_TEXT_MGR_H  #include "Creature.h" +#include "GridNotifiers.h" +#include "ObjectAccessor.h"  #include "SharedDefines.h"  struct CreatureTextEntry @@ -44,10 +46,33 @@ enum TextRange      TEXT_RANGE_WORLD    = 4  }; +struct CreatureTextLocale +{ +    StringVector Text; +}; + +struct CreatureTextId +{ +    CreatureTextId(uint32 e, uint32 g, uint32 i) :  entry(e), textGroup(g), textId(i) +    { +    } + +    bool operator<(CreatureTextId const& right) const +    { +        return memcmp(this, &right, sizeof(CreatureTextId)) < 0; +    } + +    uint32 entry; +    uint32 textGroup; +    uint32 textId; +}; +  typedef std::vector<CreatureTextEntry> CreatureTextGroup;              //texts in a group  typedef UNORDERED_MAP<uint8, CreatureTextGroup> CreatureTextHolder;    //groups for a creature by groupid  typedef UNORDERED_MAP<uint32, CreatureTextHolder> CreatureTextMap;     //all creatures by entry +typedef std::map<CreatureTextId, CreatureTextLocale> LocaleCreatureTextMap; +  //used for handling non-repeatable random texts  typedef std::vector<uint8> CreatureTextRepeatIds;  typedef UNORDERED_MAP<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup; @@ -57,9 +82,11 @@ class CreatureTextMgr  {      friend class ACE_Singleton<CreatureTextMgr, ACE_Null_Mutex>;      CreatureTextMgr() {}; +      public:          ~CreatureTextMgr() {};          void LoadCreatureTexts(); +        void LoadCreatureTextLocales();          CreatureTextMap  const& GetTextMap() const { return mTextMap; }          void SendSound(Creature* source, uint32 sound, ChatMsg msgType, uint64 whisperGuid, TextRange range, Team team, bool gmOnly); @@ -67,17 +94,154 @@ class CreatureTextMgr          //if sent, returns the 'duration' of the text else 0 if error          uint32 SendChat(Creature* source, uint8 textGroup, uint64 whisperGuid = 0, ChatMsg msgType = CHAT_MSG_ADDON, Language language = LANG_ADDON, TextRange range = TEXT_RANGE_NORMAL, uint32 sound = 0, Team team = TEAM_OTHER, bool gmOnly = false, Player* srcPlr = NULL); -        void SendChatString(WorldObject* source, char const* text, ChatMsg msgtype = CHAT_MSG_MONSTER_SAY, Language language = LANG_UNIVERSAL, uint64 whisperGuid = 0, TextRange range = TEXT_RANGE_NORMAL, Team team = TEAM_OTHER, bool gmOnly = false) const;          bool TextExist(uint32 sourceEntry, uint8 textGroup); +        std::string GetLocalizedChatString(uint32 entry, uint8 textGroup, uint32 id, LocaleConstant locale) const; + +        template<class Builder> +        void SendChatPacket(WorldObject* source, Builder const& builder, ChatMsg msgType, uint64 whisperGuid = 0, TextRange range = TEXT_RANGE_NORMAL, Team team = TEAM_OTHER, bool gmOnly = false) const;      private:          CreatureTextRepeatIds GetRepeatGroup(Creature* source, uint8 textGroup);          void SetRepeatId(Creature* source, uint8 textGroup, uint8 id); -        void BuildMonsterChat(WorldPacket* data, WorldObject* source, ChatMsg msgType, char const* text, Language language, uint64 whisperGuid) const; -        void SendChatPacket(WorldPacket* data, WorldObject* source, ChatMsg msgType, uint64 whisperGuid, TextRange range, Team team, bool gmOnly) const; + +        void SendNonChatPacket(WorldObject* source, WorldPacket* data, ChatMsg msgType, uint64 whisperGuid, TextRange range, Team team, bool gmOnly) const; +        float GetRangeForChatType(ChatMsg msgType) const;          CreatureTextMap mTextMap;          CreatureTextRepeatMap mTextRepeatMap; +        LocaleCreatureTextMap mLocaleTextMap;  };  #define sCreatureTextMgr ACE_Singleton<CreatureTextMgr, ACE_Null_Mutex>::instance() + +template<class Builder> +class CreatureTextLocalizer +{ +    public: +        CreatureTextLocalizer(Builder const& builder, ChatMsg msgType) : _builder(builder), _msgType(msgType) +        { +            _packetCache.resize(TOTAL_LOCALES, NULL); +        } + +        ~CreatureTextLocalizer() +        { +            for (size_t i = 0; i < _packetCache.size(); ++i) +            { +                if (_packetCache[i]) +                    delete _packetCache[i]->first; +                delete _packetCache[i]; +            } +        } + +        void operator()(Player* player) +        { +            LocaleConstant loc_idx = player->GetSession()->GetSessionDbLocaleIndex(); +            WorldPacket* messageTemplate; +            size_t whisperGUIDpos; + +            // create if not cached yet +            if (!_packetCache[loc_idx]) +            { +                messageTemplate = new WorldPacket(SMSG_MESSAGECHAT, 200); +                whisperGUIDpos = _builder(messageTemplate, loc_idx); +                _packetCache[loc_idx] = new std::pair<WorldPacket*, size_t>(messageTemplate, whisperGUIDpos); +            } +            else +            { +                messageTemplate = _packetCache[loc_idx]->first; +                whisperGUIDpos = _packetCache[loc_idx]->second; +            } + +            WorldPacket data(*messageTemplate); +            switch (_msgType) +            { +                case CHAT_MSG_MONSTER_WHISPER: +                case CHAT_MSG_RAID_BOSS_WHISPER: +                    data.put<uint64>(whisperGUIDpos, player->GetGUID()); +                    break; +            } + +            player->SendDirectMessage(&data); +        } + +    private: +        std::vector<std::pair<WorldPacket*, size_t>* > _packetCache; +        Builder const& _builder; +        ChatMsg _msgType; +}; + +template<class Builder> +void CreatureTextMgr::SendChatPacket(WorldObject* source, Builder const& builder, ChatMsg msgType, uint64 whisperGuid, TextRange range, Team team, bool gmOnly) const +{ +    if (!source) +        return; + +    CreatureTextLocalizer<Builder> localizer(builder, msgType); + +    switch (msgType) +    { +        case CHAT_MSG_MONSTER_WHISPER: +        case CHAT_MSG_RAID_BOSS_WHISPER: +        { +            if (range == TEXT_RANGE_NORMAL) //ignores team and gmOnly +            { +                Player* player = ObjectAccessor::FindPlayer(whisperGuid); +                if (!player || !player->GetSession()) +                    return; + +                localizer(player); +                return; +            } +            break; +        } +        default: +            break; +    } + +    switch (range) +    { +        case TEXT_RANGE_AREA: +        { +            uint32 areaId = source->GetAreaId(); +            Map::PlayerList const& players = source->GetMap()->GetPlayers(); +            for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) +                if (itr->getSource()->GetAreaId() == areaId && (!team || Team(itr->getSource()->GetTeam()) == team) && (!gmOnly || itr->getSource()->isGameMaster())) +                    localizer(itr->getSource()); +            return; +        } +        case TEXT_RANGE_ZONE: +        { +            uint32 zoneId = source->GetZoneId(); +            Map::PlayerList const& players = source->GetMap()->GetPlayers(); +            for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) +                if (itr->getSource()->GetZoneId() == zoneId && (!team || Team(itr->getSource()->GetTeam()) == team) && (!gmOnly || itr->getSource()->isGameMaster())) +                    localizer(itr->getSource()); +            return; +        } +        case TEXT_RANGE_MAP: +        { +            Map::PlayerList const& players = source->GetMap()->GetPlayers(); +            for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) +                if ((!team || Team(itr->getSource()->GetTeam()) == team) && (!gmOnly || itr->getSource()->isGameMaster())) +                    localizer(itr->getSource()); +            return; +        } +        case TEXT_RANGE_WORLD: +        { +            SessionMap const& smap = sWorld->GetAllSessions(); +            for (SessionMap::const_iterator iter = smap.begin(); iter != smap.end(); ++iter) +                if (Player* player = iter->second->GetPlayer()) +                    if (player->GetSession()  && (!team || Team(player->GetTeam()) == team) && (!gmOnly || player->isGameMaster())) +                        localizer(player); +            return; +        } +        case TEXT_RANGE_NORMAL: +        default: +            break; +    } + +    float dist = GetRangeForChatType(msgType); +    Trinity::PlayerDistWorker<CreatureTextLocalizer<Builder> > worker(source, dist, localizer); +    source->VisitNearbyWorldObject(dist, worker); +} +  #endif diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp index 29f29fe5b88..7567b3976db 100644 --- a/src/server/game/Warden/WardenCheckMgr.cpp +++ b/src/server/game/Warden/WardenCheckMgr.cpp @@ -25,7 +25,6 @@  #include "WardenCheckMgr.h"  #include "Warden.h" -  WardenCheckMgr::WardenCheckMgr()  {  } @@ -49,17 +48,6 @@ void WardenCheckMgr::LoadWardenChecks()          return;      } -    // For reload case -    for (uint16 i = 0; i < CheckStore.size(); ++i) -        delete CheckStore[i]; - -    CheckStore.clear(); - -    for (CheckResultContainer::iterator itr = CheckResultStore.begin(); itr != CheckResultStore.end(); ++itr) -        delete itr->second; -    CheckResultStore.clear(); - -      QueryResult result = WorldDatabase.Query("SELECT MAX(id) FROM warden_checks");      if (!result) @@ -166,13 +154,13 @@ void WardenCheckMgr::LoadWardenOverrides()          return;      } -    Field* fields = result->Fetch(); -      uint32 count = 0; +    ACE_WRITE_GUARD(ACE_RW_Mutex, g, _checkStoreLock); +      do      { -        fields = result->Fetch(); +        Field* fields = result->Fetch();          uint16 checkId = fields[0].GetUInt16();          uint8  action  = fields[1].GetUInt8(); diff --git a/src/server/game/Warden/WardenCheckMgr.h b/src/server/game/Warden/WardenCheckMgr.h index 1b790d16716..45de18081c2 100644 --- a/src/server/game/Warden/WardenCheckMgr.h +++ b/src/server/game/Warden/WardenCheckMgr.h @@ -64,6 +64,8 @@ class WardenCheckMgr          void LoadWardenChecks();          void LoadWardenOverrides(); +        ACE_RW_Mutex _checkStoreLock; +      private:          CheckContainer CheckStore;          CheckResultContainer CheckResultStore; diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp index 53d167082d6..3e028254f28 100644 --- a/src/server/game/Warden/WardenWin.cpp +++ b/src/server/game/Warden/WardenWin.cpp @@ -212,6 +212,8 @@ void WardenWin::RequestData()      ByteBuffer buff;      buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); +    ACE_READ_GUARD(ACE_RW_Mutex, g, sWardenCheckMgr->_checkStoreLock); +      for (uint32 i = 0; i < sWorld->getIntConfig(CONFIG_WARDEN_NUM_OTHER_CHECKS); ++i)      {          // If todo list is done break loop (will be filled on next Update() run) @@ -377,6 +379,8 @@ void WardenWin::HandleData(ByteBuffer &buff)      uint8 type;      uint16 checkFailed = 0; +    ACE_READ_GUARD(ACE_RW_Mutex, g, sWardenCheckMgr->_checkStoreLock); +      for (std::list<uint16>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr)      {          rd = sWardenCheckMgr->GetWardenDataById(*itr); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index fcdb6b7fcd6..3efa976e1d3 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1651,6 +1651,9 @@ void World::SetInitialWorldSettings()      sLog->outString("Loading Creature Texts...");      sCreatureTextMgr->LoadCreatureTexts(); +    sLog->outString("Loading Creature Text Locales..."); +    sCreatureTextMgr->LoadCreatureTextLocales(); +      sLog->outString("Initializing Scripts...");      sScriptMgr->Initialize(); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 8ca40231090..9646a881fc0 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -89,6 +89,7 @@ public:              { "itemexpire",     SEC_ADMINISTRATOR,  false, &HandleDebugItemExpireCommand,      "", NULL },              { "areatriggers",   SEC_ADMINISTRATOR,  false, &HandleDebugAreaTriggersCommand,    "", NULL },              { "los",            SEC_MODERATOR,      false, &HandleDebugLoSCommand,             "", NULL }, +            { "moveflags",      SEC_ADMINISTRATOR,  false, &HandleDebugMoveflagsCommand,       "", NULL },              { NULL,             0,                  false, NULL,                               "", NULL }          };          static ChatCommand commandTable[] = @@ -1283,6 +1284,41 @@ public:          handler->PSendSysMessage(LANG_SET_32BIT_FIELD, opcode, value);          return true;      } + +    static bool HandleDebugMoveflagsCommand(ChatHandler* handler, char const* args) +    { +        Unit* target = handler->getSelectedUnit(); +        if (!target) +            target = handler->GetSession()->GetPlayer(); + +        if (!*args) +        { +            //! Display case +            handler->PSendSysMessage(LANG_MOVEFLAGS_GET, target->GetUnitMovementFlags(), target->GetExtraUnitMovementFlags()); +        } +        else +        { +            char* mask1 = strtok((char*)args, " "); +            if (!mask1) +                return false; + +            char* mask2 = strtok(NULL, " \n"); +             +            uint32 moveFlags = (uint32)atoi(mask1); +            target->SetUnitMovementFlags(moveFlags); +             +            if (mask2) +            { +                uint32 moveFlagsExtra = uint32(atoi(mask2)); +                target->SetExtraUnitMovementFlags(moveFlagsExtra); +            } + +            target->SendMovementFlagUpdate(); +            handler->PSendSysMessage(LANG_MOVEFLAGS_SET, target->GetUnitMovementFlags(), target->GetExtraUnitMovementFlags()); +        } +         +        return true; +    }  };  void AddSC_debug_commandscript() diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp index 8f5e862555c..9249cb3fdbc 100644 --- a/src/server/scripts/Commands/cs_wp.cpp +++ b/src/server/scripts/Commands/cs_wp.cpp @@ -223,6 +223,7 @@ public:          sWaypointMgr->ReloadPath(id);          return true;      } +      static bool HandleWpUnLoadCommand(ChatHandler* handler, const char* /*args*/)      { @@ -605,7 +606,7 @@ public:              return false;          } -        if (show == "del" && target) +        if (show == "del")          {              handler->PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid); @@ -615,9 +616,12 @@ public:              if (wpGuid != 0)              {                  wpCreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); -                wpCreature->CombatStop(); -                wpCreature->DeleteFromDB(); -                wpCreature->AddObjectToRemoveList(); +                if (wpCreature) +                { +                    wpCreature->CombatStop(); +                    wpCreature->DeleteFromDB(); +                    wpCreature->AddObjectToRemoveList(); +                }              }              PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_DATA); @@ -638,7 +642,7 @@ public:              return true;          }                                                       // del -        if (show == "move" && target) +        if (show == "move")          {              handler->PSendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff%u|r", pathid); @@ -652,16 +656,20 @@ public:                  // Respawn the owner of the waypoints                  if (wpGuid != 0)                  { -                    wpCreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); -                    wpCreature->CombatStop(); -                    wpCreature->DeleteFromDB(); -                    wpCreature->AddObjectToRemoveList(); +                    wpCreature = map->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); +                    if (wpCreature) +                    { +                        wpCreature->CombatStop(); +                        wpCreature->DeleteFromDB(); +                        wpCreature->AddObjectToRemoveList(); +                    }                      // re-create                      Creature* wpCreature2 = new Creature;                      if (!wpCreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()))                      {                          handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);                          delete wpCreature2; +                        wpCreature2 = NULL;                          return false;                      } @@ -672,6 +680,7 @@ public:                      {                          handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);                          delete wpCreature2; +                        wpCreature2 = NULL;                          return false;                      }                      //sMapMgr->GetMap(npcCreature->GetMapId())->Add(wpCreature2); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp index 9a91e1e232b..b232cae4657 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp @@ -16,6 +16,7 @@   */  #include "ScriptPCH.h" +#include "CreatureTextMgr.h"  #include "culling_of_stratholme.h"  #define MAX_ENCOUNTER 5 diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index e0fa0e2b75a..19a8e42e14b 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -26,6 +26,7 @@  #include "CellImpl.h"  #include "GridNotifiers.h"  #include "GridNotifiersImpl.h" +#include "CreatureTextMgr.h"  #include "icecrown_citadel.h"  enum Texts diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp index c6f72890d1f..284babb7193 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp @@ -29,17 +29,15 @@ EndScriptData */  enum eEnums  {      //Yell -    SAY_AGGRO                               = -1602000, -    SAY_SLAY_1                              = -1602001, -    SAY_SLAY_2                              = -1602002, -    SAY_SLAY_3                              = -1602003, -    SAY_DEATH                               = -1602004, -    SAY_BATTLE_STANCE                       = -1602005, -    EMOTE_BATTLE_STANCE                     = -1602006, -    SAY_BERSEKER_STANCE                     = -1602007, -    EMOTE_BERSEKER_STANCE                   = -1602008, -    SAY_DEFENSIVE_STANCE                    = -1602009, -    EMOTE_DEFENSIVE_STANCE                  = -1602010, +    SAY_AGGRO                               = 0, +    SAY_DEFENSIVE_STANCE                    = 1, +    SAY_BATTLE_STANCE                       = 2, +    SAY_BERSEKER_STANCE                     = 3, +    SAY_SLAY                                = 4, +    SAY_DEATH                               = 5, +    EMOTE_DEFENSIVE_STANCE                  = 6, +    EMOTE_BATTLE_STANCE                     = 7, +    EMOTE_BERSEKER_STANCE                   = 8,      SPELL_DEFENSIVE_STANCE                  = 53790,      //SPELL_DEFENSIVE_AURA                    = 41105, @@ -185,7 +183,7 @@ public:          void EnterCombat(Unit* /*who*/)          { -            DoScriptText(SAY_AGGRO, me); +            Talk(SAY_AGGRO);              //must get both lieutenants here and make sure they are with him              me->CallForHelp(30.0f); @@ -196,12 +194,12 @@ public:          void KilledUnit(Unit* /*victim*/)          { -            DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2, SAY_SLAY_3), me); +            Talk(SAY_SLAY);          }          void JustDied(Unit* /*killer*/)          { -            DoScriptText(SAY_DEATH, me); +            Talk(SAY_DEATH);              if (m_instance)                  m_instance->SetData(TYPE_BJARNGRIM, DONE); @@ -249,20 +247,20 @@ public:                  switch (m_uiStance)                  {                      case STANCE_DEFENSIVE: -                        DoScriptText(SAY_DEFENSIVE_STANCE, me); -                        DoScriptText(EMOTE_DEFENSIVE_STANCE, me); +                        Talk(SAY_DEFENSIVE_STANCE); +                        Talk(EMOTE_DEFENSIVE_STANCE);                          DoCast(me, SPELL_DEFENSIVE_STANCE);                          SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE);                          break;                      case STANCE_BERSERKER: -                        DoScriptText(SAY_BERSEKER_STANCE, me); -                        DoScriptText(EMOTE_BERSEKER_STANCE, me); +                        Talk(SAY_BERSEKER_STANCE); +                        Talk(EMOTE_BERSEKER_STANCE);                          DoCast(me, SPELL_BERSEKER_STANCE);                          SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE);                          break;                      case STANCE_BATTLE: -                        DoScriptText(SAY_BATTLE_STANCE, me); -                        DoScriptText(EMOTE_BATTLE_STANCE, me); +                        Talk(SAY_BATTLE_STANCE); +                        Talk(EMOTE_BATTLE_STANCE);                          DoCast(me, SPELL_BATTLE_STANCE);                          SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);                          break; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index 016c4d27cfa..abdf5ecb1e1 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -41,13 +41,10 @@ enum Spells  enum Yells  { -    SAY_AGGRO                                     = -1602011, -    SAY_SLAY_1                                    = -1602012, -    SAY_SLAY_2                                    = -1602013, -    SAY_SLAY_3                                    = -1602014, -    SAY_DEATH                                     = -1602015, -    SAY_SPLIT_1                                   = -1602016, -    SAY_SPLIT_2                                   = -1602017 +    SAY_AGGRO                                     = 0, +    SAY_SPLIT                                     = 1, +    SAY_SLAY                                      = 2, +    SAY_DEATH                                     = 3  };  enum Creatures @@ -122,7 +119,7 @@ public:          void EnterCombat(Unit* /*who*/)          { -            DoScriptText(SAY_AGGRO, me); +            Talk(SAY_AGGRO);              if (instance)                  instance->SetData(TYPE_IONAR, IN_PROGRESS); @@ -130,7 +127,7 @@ public:          void JustDied(Unit* /*killer*/)          { -            DoScriptText(SAY_DEATH, me); +            Talk(SAY_DEATH);              lSparkList.DespawnAll(); @@ -140,7 +137,7 @@ public:          void KilledUnit(Unit* /*victim*/)          { -            DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2, SAY_SLAY_3), me); +            Talk(SAY_SLAY);          }          void SpellHit(Unit* /*caster*/, const SpellInfo* spell) @@ -278,7 +275,7 @@ public:              {                  bHasDispersed = true; -                DoScriptText(RAND(SAY_SPLIT_1, SAY_SPLIT_2), me); +                Talk(SAY_SPLIT);                  if (me->IsNonMeleeSpellCasted(false))                      me->InterruptNonMeleeSpells(false); diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp index 171215c605a..e4f2bb5ce01 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -30,20 +30,16 @@ enum eEnums  {      ACHIEV_TIMELY_DEATH_START_EVENT               = 20384, -    SAY_AGGRO                                     = -1602018, -    SAY_INTRO_1                                   = -1602019, -    SAY_INTRO_2                                   = -1602020, -    SAY_SLAY_1                                    = -1602021, -    SAY_SLAY_2                                    = -1602022, -    SAY_SLAY_3                                    = -1602023, -    SAY_DEATH                                     = -1602024, -    SAY_NOVA_1                                    = -1602025, -    SAY_NOVA_2                                    = -1602026, -    SAY_NOVA_3                                    = -1602027, -    SAY_75HEALTH                                  = -1602028, -    SAY_50HEALTH                                  = -1602029, -    SAY_25HEALTH                                  = -1602030, -    EMOTE_NOVA                                    = -1602031, +    SAY_INTRO_1                                   = 0, +    SAY_INTRO_2                                   = 1, +    SAY_AGGRO                                     = 2, +    SAY_NOVA                                      = 3, +    SAY_SLAY                                      = 4, +    SAY_75HEALTH                                  = 5, +    SAY_50HEALTH                                  = 6, +    SAY_25HEALTH                                  = 7, +    SAY_DEATH                                     = 8, +    EMOTE_NOVA                                    = 9,      SPELL_ARC_LIGHTNING                           = 52921,      SPELL_LIGHTNING_NOVA_N                        = 52960, @@ -106,7 +102,7 @@ public:          void EnterCombat(Unit* /*who*/)          { -            DoScriptText(SAY_AGGRO, me); +            Talk(SAY_AGGRO);              if (m_instance)              { @@ -117,7 +113,7 @@ public:          void JustDied(Unit* /*killer*/)          { -            DoScriptText(SAY_DEATH, me); +            Talk(SAY_DEATH);              if (m_instance)                  m_instance->SetData(TYPE_LOKEN, DONE); @@ -125,7 +121,7 @@ public:          void KilledUnit(Unit* /*victim*/)          { -            DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2, SAY_SLAY_3), me); +            Talk(SAY_SLAY);          }          void UpdateAI(const uint32 uiDiff) @@ -190,8 +186,8 @@ public:              if (m_uiLightningNova_Timer <= uiDiff)              { -                DoScriptText(RAND(SAY_NOVA_1, SAY_NOVA_2, SAY_NOVA_3), me); -                DoScriptText(EMOTE_NOVA, me); +                Talk(SAY_NOVA); +                Talk(EMOTE_NOVA);                  DoCast(me, SPELL_LIGHTNING_NOVA_N);                  m_bIsAura = false; @@ -206,9 +202,9 @@ public:              {                  switch (m_uiHealthAmountModifier)                  { -                    case 1: DoScriptText(SAY_75HEALTH, me); break; -                    case 2: DoScriptText(SAY_50HEALTH, me); break; -                    case 3: DoScriptText(SAY_25HEALTH, me); break; +                    case 1: Talk(SAY_75HEALTH); break; +                    case 2: Talk(SAY_50HEALTH); break; +                    case 3: Talk(SAY_25HEALTH); break;                  }                  ++m_uiHealthAmountModifier; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index 1fc724c8b6c..83604ed4153 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -28,17 +28,13 @@ EndScriptData */  enum eEnums  { -    SAY_AGGRO                               = -1602032, -    SAY_SLAY_1                              = -1602033, -    SAY_SLAY_2                              = -1602034, -    SAY_SLAY_3                              = -1602035, -    SAY_DEATH                               = -1602036, -    SAY_STOMP_1                             = -1602037, -    SAY_STOMP_2                             = -1602038, -    SAY_FORGE_1                             = -1602039, -    SAY_FORGE_2                             = -1602040, -    EMOTE_TO_ANVIL                          = -1602041, -    EMOTE_SHATTER                           = -1602042, +    SAY_AGGRO                               = 0, +    SAY_FORGE                               = 1, +    SAY_STOMP                               = 2, +    SAY_SLAY                                = 3, +    SAY_DEATH                               = 4, +    EMOTE_TO_ANVIL                          = 5, +    EMOTE_SHATTER                           = 6,      SPELL_HEAT_N                            = 52387,      SPELL_HEAT_H                            = 59528, @@ -127,7 +123,7 @@ public:          void EnterCombat(Unit* /*who*/)          { -            DoScriptText(SAY_AGGRO, me); +            Talk(SAY_AGGRO);              if (m_instance)                  m_instance->SetData(TYPE_VOLKHAN, IN_PROGRESS); @@ -148,7 +144,7 @@ public:          void JustDied(Unit* /*killer*/)          { -            DoScriptText(SAY_DEATH, me); +            Talk(SAY_DEATH);              DespawnGolem();              if (m_instance) @@ -172,7 +168,7 @@ public:          void KilledUnit(Unit* /*victim*/)          { -            DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2, SAY_SLAY_3), me); +            Talk(SAY_SLAY);          }          void DespawnGolem() @@ -263,11 +259,11 @@ public:                  if (m_uiShatteringStomp_Timer <= uiDiff)                  {                      // Should he stomp even if he has no brittle golem to shatter? -                    DoScriptText(RAND(SAY_STOMP_1, SAY_STOMP_2), me); +                    Talk(SAY_STOMP);                      DoCast(me, SPELL_SHATTERING_STOMP_N); -                    DoScriptText(EMOTE_SHATTER, me); +                    Talk(EMOTE_SHATTER);                      m_uiShatteringStomp_Timer = 30000;                      m_bCanShatterGolem = true; @@ -297,7 +293,7 @@ public:                  if (me->IsNonMeleeSpellCasted(false))                      me->InterruptNonMeleeSpells(false); -                DoScriptText(RAND(SAY_FORGE_1, SAY_FORGE_2), me); +                Talk(SAY_FORGE);                  m_bHasTemper = true; @@ -308,7 +304,7 @@ public:              {                  case 1:                      // 1 - Start run to Anvil -                    DoScriptText(EMOTE_TO_ANVIL, me); +                    Talk(EMOTE_TO_ANVIL);                      me->GetMotionMaster()->MoveTargetedHome();                      m_uiSummonPhase = 2;        // Set Next Phase                      break; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 408ebf3cc96..98b20f1c424 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -1756,7 +1756,7 @@ class spell_vehicle_throw_passenger : public SpellScriptLoader                                                  if (Unit* device = seat->GetPassenger(2))                                                      if (!device->GetCurrentSpell(CURRENT_CHANNELED_SPELL))                                                      { -                                                        float dist = unit->GetExactDistSq(targets.GetDst()); +                                                        float dist = unit->GetExactDistSq(targets.GetDstPos());                                                          if (dist < minDist)                                                          {                                                              minDist = dist; @@ -1764,13 +1764,13 @@ class spell_vehicle_throw_passenger : public SpellScriptLoader                                                          }                                                      }                              } -                            if (target && target->IsWithinDist2d(targets.GetDst(), GetSpellInfo()->Effects[effIndex].CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct +                            if (target && target->IsWithinDist2d(targets.GetDstPos(), GetSpellInfo()->Effects[effIndex].CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct                                  passenger->EnterVehicle(target, 0);                              else                              {                                  passenger->ExitVehicle();                                  float x, y, z; -                                targets.GetDst()->GetPosition(x, y, z); +                                targets.GetDstPos()->GetPosition(x, y, z);                                  passenger->GetMotionMaster()->MoveJump(x, y, z, targets.GetSpeedXY(), targets.GetSpeedZ());                              }                          } diff --git a/src/server/scripts/Northrend/zuldrak.cpp b/src/server/scripts/Northrend/zuldrak.cpp index 835ad144501..4cea6d8d8aa 100644 --- a/src/server/scripts/Northrend/zuldrak.cpp +++ b/src/server/scripts/Northrend/zuldrak.cpp @@ -617,9 +617,9 @@ public:                  pWhisker->RemoveFromWorld();          } -        void MovementInform(uint32 uiType, uint32 /*uiId*/) +        void MovementInform(uint32 type, uint32 /*pointId*/)          { -            if (uiType != POINT_MOTION_TYPE) +            if (type != EFFECT_MOTION_TYPE)                  return;              me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index ee554f4875a..e6db50f3f5a 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -769,16 +769,14 @@ class spell_dk_death_grip : public SpellScriptLoader          {              PrepareSpellScript(spell_dk_death_grip_SpellScript); -            void HandleDummy(SpellEffIndex effIndex) +            void HandleDummy(SpellEffIndex /*effIndex*/)              {                  int32 damage = GetEffectValue(); -                Position pos; +                Position const* pos = GetTargetDest();                  if (Unit* target = GetHitUnit())                  { -                    GetSummonPosition(effIndex, pos, 0.0f, 0); -                      if (!target->HasAuraType(SPELL_AURA_DEFLECT_SPELLS)) // Deterrence -                        target->CastSpell(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), damage, true); +                        target->CastSpell(pos->GetPositionX(), pos->GetPositionY(), pos->GetPositionZ(), damage, true);                  }              } diff --git a/src/server/scripts/World/areatrigger_scripts.cpp b/src/server/scripts/World/areatrigger_scripts.cpp index 8f86f760775..d8a90b2ffd5 100644 --- a/src/server/scripts/World/areatrigger_scripts.cpp +++ b/src/server/scripts/World/areatrigger_scripts.cpp @@ -32,6 +32,7 @@ at_sholazar_waygate             q12548  at_nats_landing                 q11209  at_bring_your_orphan_to         q910 q910 q1800 q1479 q1687 q1558 q10951 q10952  at_brewfest +at_area_52_entrance  EndContentData */  #include "ScriptPCH.h" @@ -420,6 +421,75 @@ class AreaTrigger_at_brewfest : public AreaTriggerScript          std::map<uint32, time_t> _triggerTimes;  }; +/*###### +## at_area_52_entrance +######*/ + +enum Area52Entrance +{ +    SPELL_A52_NEURALYZER  = 34400, +    NPC_SPOTLIGHT         = 19913, +    SUMMON_COOLDOWN       = 5, + +    AT_AREA_52_SOUTH      = 4472, +    AT_AREA_52_NORTH      = 4466, +    AT_AREA_52_WEST       = 4471, +    AT_AREA_52_EAST       = 4422, +}; + +class AreaTrigger_at_area_52_entrance : public AreaTriggerScript +{ +    public: +        AreaTrigger_at_area_52_entrance() : AreaTriggerScript("at_area_52_entrance") +        { +            _triggerTimes[AT_AREA_52_SOUTH] = _triggerTimes[AT_AREA_52_NORTH] = _triggerTimes[AT_AREA_52_WEST] = _triggerTimes[AT_AREA_52_EAST] = 0; +        } + +        bool OnTrigger(Player* player, AreaTriggerEntry const* trigger) +        { +            float x, y, z; + +            if (!player->isAlive()) +                return false; + +            uint32 triggerId = trigger->id; +            if (sWorld->GetGameTime() - _triggerTimes[trigger->id] < SUMMON_COOLDOWN) +                return false; + +            switch (triggerId) +            { +                case AT_AREA_52_EAST: +                    x = 3044.176f; +                    y = 3610.692f; +                    z = 143.61f; +                    break; +                case AT_AREA_52_NORTH: +                    x = 3114.87f; +                    y = 3687.619f; +                    z = 143.62f; +                    break; +                case AT_AREA_52_WEST: +                    x = 3017.79f; +                    y = 3746.806f; +                    z = 144.27f; +                    break; +                case AT_AREA_52_SOUTH: +                    x = 2950.63f; +                    y = 3719.905f; +                    z = 143.33f; +                    break; +            } + +            player->SummonCreature(NPC_SPOTLIGHT, x, y, z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 5000); +            player->AddAura(SPELL_A52_NEURALYZER, player); +            _triggerTimes[trigger->id] = sWorld->GetGameTime(); +            return false; +        } + +    private: +        std::map<uint32, time_t> _triggerTimes; +}; +  void AddSC_areatrigger_scripts()  {      new AreaTrigger_at_coilfang_waterfall(); @@ -431,4 +501,5 @@ void AddSC_areatrigger_scripts()      new AreaTrigger_at_nats_landing();      new AreaTrigger_at_bring_your_orphan_to();      new AreaTrigger_at_brewfest(); -} +    new AreaTrigger_at_area_52_entrance(); +}
\ No newline at end of file diff --git a/src/server/shared/Cryptography/HMACSHA1.cpp b/src/server/shared/Cryptography/HMACSHA1.cpp index 447d0b58efc..c9de1191464 100755 --- a/src/server/shared/Cryptography/HMACSHA1.cpp +++ b/src/server/shared/Cryptography/HMACSHA1.cpp @@ -31,19 +31,9 @@ HmacHash::~HmacHash()      HMAC_CTX_cleanup(&m_ctx);  } -void HmacHash::UpdateBigNumber(BigNumber* bn) -{ -    UpdateData(bn->AsByteArray(), bn->GetNumBytes()); -} - -void HmacHash::UpdateData(const uint8 *data, int length) -{ -    HMAC_Update(&m_ctx, data, length); -} -  void HmacHash::UpdateData(const std::string &str)  { -    UpdateData((uint8 const*)str.c_str(), str.length()); +    HMAC_Update(&m_ctx, (uint8 const*)str.c_str(), str.length());  }  void HmacHash::Finalize() diff --git a/src/server/shared/Cryptography/HMACSHA1.h b/src/server/shared/Cryptography/HMACSHA1.h index bd0418b600e..4b7667968ca 100755 --- a/src/server/shared/Cryptography/HMACSHA1.h +++ b/src/server/shared/Cryptography/HMACSHA1.h @@ -33,8 +33,6 @@ class HmacHash      public:          HmacHash(uint32 len, uint8 *seed);          ~HmacHash(); -        void UpdateBigNumber(BigNumber* bn); -        void UpdateData(const uint8 *data, int length);          void UpdateData(const std::string &str);          void Finalize();          uint8 *ComputeHash(BigNumber* bn); diff --git a/src/server/shared/Cryptography/SHA1.h b/src/server/shared/Cryptography/SHA1.h index b5bf97fd7d9..7c77defebfa 100755 --- a/src/server/shared/Cryptography/SHA1.h +++ b/src/server/shared/Cryptography/SHA1.h @@ -31,7 +31,6 @@ class SHA1Hash          SHA1Hash();          ~SHA1Hash(); -        void UpdateFinalizeBigNumbers(BigNumber* bn0, ...);          void UpdateBigNumbers(BigNumber* bn0, ...);          void UpdateData(const uint8 *dta, int len); diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 6b99b79625d..35cb62240d8 100755 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -27,22 +27,52 @@  class ByteBufferException  {      public: -        ByteBufferException(bool _add, size_t _pos, size_t _esize, size_t _size) -            : add(_add), pos(_pos), esize(_esize), size(_size) +        ByteBufferException(size_t pos, size_t size, size_t valueSize) +            : Pos(pos), Size(size), ValueSize(valueSize)          { -            PrintPosError();          } -        void PrintPosError() const +    protected: +        size_t Pos; +        size_t Size; +        size_t ValueSize; +}; + +class ByteBufferPositionException : public ByteBufferException +{ +    public: +        ByteBufferPositionException(bool add, size_t pos, size_t size, size_t valueSize) +        : ByteBufferException(pos, size, valueSize), _add(add) +        { +            PrintError(); +        } + +    protected: +        void PrintError() const          { -            sLog->outError("Attempted to %s in ByteBuffer (pos: " SIZEFMTD " size: "SIZEFMTD") value with size: " SIZEFMTD, -                (add ? "put" : "get"), pos, size, esize); +            sLog->outError("Attempted to %s value with size: "SIZEFMTD" in ByteBuffer (pos: " SIZEFMTD " size: "SIZEFMTD") " , +                (_add ? "put" : "get"), ValueSize, Pos, Size);          } +      private: -        bool add; -        size_t pos; -        size_t esize; -        size_t size; +        bool _add; +}; + +class ByteBufferSourceException : public ByteBufferException +{ +    public: +        ByteBufferSourceException(size_t pos, size_t size, size_t valueSize) +        : ByteBufferException(pos, size, valueSize) +        { +            PrintError(); +        } + +    protected: +        void PrintError() const +        { +            sLog->outError("Attempted to put a %s in ByteBuffer (pos: "SIZEFMTD" size: "SIZEFMTD")", +                (ValueSize > 0 ? "NULL-pointer" : "zero-sized value"), Pos, Size); +        }  };  class ByteBuffer @@ -147,14 +177,17 @@ class ByteBuffer          ByteBuffer &operator<<(const std::string &value)          { -            append((uint8 const*)value.c_str(), value.length()); +            if (size_t len = value.length()) +                append((uint8 const*)value.c_str(), len);              append((uint8)0);              return *this;          }          ByteBuffer &operator<<(const char *str)          { -            append((uint8 const*)str, str ? strlen(str) : 0); +            size_t len = 0; +            if (str && (len = strlen(str))) +                append((uint8 const*)str, len);              append((uint8)0);              return *this;          } @@ -271,7 +304,7 @@ class ByteBuffer          void read_skip(size_t skip)          {              if (_rpos + skip > size()) -                throw ByteBufferException(false, _rpos, skip, size()); +                throw ByteBufferPositionException(false, _rpos, skip, size());              _rpos += skip;          } @@ -285,7 +318,7 @@ class ByteBuffer          template <typename T> T read(size_t pos) const          {              if (pos + sizeof(T) > size()) -                throw ByteBufferException(false, pos, sizeof(T), size()); +                throw ByteBufferPositionException(false, pos, sizeof(T), size());              T val = *((T const*)&_storage[pos]);              EndianConvert(val);              return val; @@ -294,7 +327,7 @@ class ByteBuffer          void read(uint8 *dest, size_t len)          {              if (_rpos  + len > size()) -               throw ByteBufferException(false, _rpos, len, size()); +               throw ByteBufferPositionException(false, _rpos, len, size());              memcpy(dest, &_storage[_rpos], len);              _rpos += len;          } @@ -302,7 +335,7 @@ class ByteBuffer          void readPackGUID(uint64& guid)          {              if (rpos() + 1 > size()) -                throw ByteBufferException(false, _rpos, 1, size()); +                throw ByteBufferPositionException(false, _rpos, 1, size());              guid = 0; @@ -314,7 +347,7 @@ class ByteBuffer                  if (guidmark & (uint8(1) << i))                  {                      if (rpos() + 1 > size()) -                        throw ByteBufferException(false, _rpos, 1, size()); +                        throw ByteBufferPositionException(false, _rpos, 1, size());                      uint8 bit;                      (*this) >> bit; @@ -341,11 +374,6 @@ class ByteBuffer                  _storage.reserve(ressize);          } -        void append(const std::string& str) -        { -            append((uint8 const*)str.c_str(), str.size() + 1); -        } -          void append(const char *src, size_t cnt)          {              return append((const uint8 *)src, cnt); @@ -359,7 +387,10 @@ class ByteBuffer          void append(const uint8 *src, size_t cnt)          {              if (!cnt) -                return; +                throw ByteBufferSourceException(_wpos, size(), cnt); + +            if (!src) +                throw ByteBufferSourceException(_wpos, size(), cnt);              ASSERT(size() < 10000000); @@ -407,7 +438,11 @@ class ByteBuffer          void put(size_t pos, const uint8 *src, size_t cnt)          {              if (pos + cnt > size()) -               throw ByteBufferException(true, pos, cnt, size()); +                throw ByteBufferPositionException(true, pos, cnt, size()); + +            if (!src) +                throw ByteBufferSourceException(_wpos, size(), cnt); +              memcpy(&_storage[pos], src, cnt);          }  | 
