aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Totem/Totem.cpp26
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp83
-rw-r--r--src/server/game/Entities/Unit/Unit.h18
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp59
-rw-r--r--src/server/game/Globals/ObjectMgr.h7
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
-rw-r--r--src/server/game/World/World.cpp3
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp4
-rw-r--r--src/server/shared/SharedDefines.h16
9 files changed, 103 insertions, 115 deletions
diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp
index 47d1cceb7fa..294306bd9a5 100644
--- a/src/server/game/Entities/Totem/Totem.cpp
+++ b/src/server/game/Entities/Totem/Totem.cpp
@@ -18,6 +18,7 @@
#include "Totem.h"
#include "Group.h"
+#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
#include "SpellHistory.h"
@@ -54,19 +55,22 @@ void Totem::Update(uint32 time)
void Totem::InitStats(uint32 duration)
{
// client requires SMSG_TOTEM_CREATED to be sent before adding to world and before removing old totem
- if (GetOwner()->GetTypeId() == TYPEID_PLAYER
- && m_Properties->Slot >= SUMMON_SLOT_TOTEM
- && m_Properties->Slot < MAX_TOTEM_SLOT)
+ if (Player* owner = GetOwner()->ToPlayer())
{
- WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4);
- data << uint8(m_Properties->Slot - 1);
- data << uint64(GetGUID());
- data << uint32(duration);
- data << uint32(GetUInt32Value(UNIT_CREATED_BY_SPELL));
- GetOwner()->ToPlayer()->SendDirectMessage(&data);
+ uint32 slot = m_Properties->Slot;
+ if (slot >= SUMMON_SLOT_TOTEM_FIRE && slot < MAX_TOTEM_SLOT)
+ {
+ WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4);
+ data << uint8(m_Properties->Slot - 1);
+ data << uint64(GetGUID());
+ data << uint32(duration);
+ data << uint32(GetUInt32Value(UNIT_CREATED_BY_SPELL));
+ GetOwner()->ToPlayer()->SendDirectMessage(&data);
+ }
// set display id depending on caster's race
- SetDisplayId(GetOwner()->GetModelForTotem(PlayerTotemType(m_Properties->Id)));
+ if (uint32 totemDisplayId = sObjectMgr->GetModelForTotem(SummonSlot(slot), Races(owner->GetRace())))
+ SetDisplayId(totemDisplayId);
}
Minion::InitStats(duration);
@@ -108,7 +112,7 @@ void Totem::UnSummon(uint32 msTime)
RemoveAurasDueToSpell(GetSpell(), GetGUID());
// clear owner's totem slot
- for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
+ for (uint8 i = SUMMON_SLOT_TOTEM_FIRE; i < MAX_TOTEM_SLOT; ++i)
{
if (GetOwner()->m_SummonSlot[i] == GetGUID())
{
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index dee11e65a3b..e864a17117d 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -12266,89 +12266,6 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form, uint32 spellId) const
return modelid;
}
-uint32 Unit::GetModelForTotem(PlayerTotemType totemType)
-{
- switch (GetRace())
- {
- case RACE_ORC:
- {
- switch (totemType)
- {
- case SUMMON_TYPE_TOTEM_FIRE: // fire
- return 30758;
- case SUMMON_TYPE_TOTEM_EARTH: // earth
- return 30757;
- case SUMMON_TYPE_TOTEM_WATER: // water
- return 30759;
- case SUMMON_TYPE_TOTEM_AIR: // air
- return 30756;
- }
- break;
- }
- case RACE_DWARF:
- {
- switch (totemType)
- {
- case SUMMON_TYPE_TOTEM_FIRE: // fire
- return 30754;
- case SUMMON_TYPE_TOTEM_EARTH: // earth
- return 30753;
- case SUMMON_TYPE_TOTEM_WATER: // water
- return 30755;
- case SUMMON_TYPE_TOTEM_AIR: // air
- return 30736;
- }
- break;
- }
- case RACE_TROLL:
- {
- switch (totemType)
- {
- case SUMMON_TYPE_TOTEM_FIRE: // fire
- return 30762;
- case SUMMON_TYPE_TOTEM_EARTH: // earth
- return 30761;
- case SUMMON_TYPE_TOTEM_WATER: // water
- return 30763;
- case SUMMON_TYPE_TOTEM_AIR: // air
- return 30760;
- }
- break;
- }
- case RACE_TAUREN:
- {
- switch (totemType)
- {
- case SUMMON_TYPE_TOTEM_FIRE: // fire
- return 4589;
- case SUMMON_TYPE_TOTEM_EARTH: // earth
- return 4588;
- case SUMMON_TYPE_TOTEM_WATER: // water
- return 4587;
- case SUMMON_TYPE_TOTEM_AIR: // air
- return 4590;
- }
- break;
- }
- case RACE_DRAENEI:
- {
- switch (totemType)
- {
- case SUMMON_TYPE_TOTEM_FIRE: // fire
- return 19074;
- case SUMMON_TYPE_TOTEM_EARTH: // earth
- return 19073;
- case SUMMON_TYPE_TOTEM_WATER: // water
- return 19075;
- case SUMMON_TYPE_TOTEM_AIR: // air
- return 19071;
- }
- break;
- }
- }
- return 0;
-}
-
void Unit::JumpTo(float speedXY, float speedZ, bool forward)
{
float angle = forward ? 0 : float(M_PI);
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 16d1ffb5e34..aefbacecb12 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -715,23 +715,6 @@ enum ReactiveType
MAX_REACTIVE
};
-#define SUMMON_SLOT_PET 0
-#define SUMMON_SLOT_TOTEM 1
-#define MAX_TOTEM_SLOT 5
-#define SUMMON_SLOT_MINIPET 5
-#define SUMMON_SLOT_QUEST 6
-#define MAX_SUMMON_SLOT 7
-
-#define MAX_GAMEOBJECT_SLOT 4
-
-enum PlayerTotemType
-{
- SUMMON_TYPE_TOTEM_FIRE = 63,
- SUMMON_TYPE_TOTEM_EARTH = 81,
- SUMMON_TYPE_TOTEM_WATER = 82,
- SUMMON_TYPE_TOTEM_AIR = 83
-};
-
// delay time next attack to prevent client attack animation problems
#define ATTACK_DISPLAY_DELAY 200
#define MAX_PLAYER_STEALTH_DETECT_RANGE 30.0f // max distance for detection targets by player
@@ -1605,7 +1588,6 @@ class TC_GAME_API Unit : public WorldObject
void SetCantProc(bool apply);
uint32 GetModelForForm(ShapeshiftForm form, uint32 spellId) const;
- uint32 GetModelForTotem(PlayerTotemType totemType);
friend class VehicleJoinEvent;
ObjectGuid LastCharmerGUID;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 2b7d2f2cd14..745599897a7 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -1679,6 +1679,65 @@ void ObjectMgr::LoadCreatureModelInfo()
TC_LOG_INFO("server.loading", ">> Loaded %u creature model based info in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+void ObjectMgr::LoadPlayerTotemModels()
+{
+ uint32 oldMSTime = getMSTime();
+
+ QueryResult result = WorldDatabase.Query("SELECT TotemSlot, RaceId, DisplayId from player_totem_model");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 player totem model records. DB table `player_totem_model` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+
+ SummonSlot totemSlot = SummonSlot(fields[0].GetUInt8());
+ uint8 race = fields[1].GetUInt8();
+ uint32 displayId = fields[2].GetUInt32();
+
+ if (totemSlot < SUMMON_SLOT_TOTEM_FIRE || totemSlot >= MAX_TOTEM_SLOT)
+ {
+ TC_LOG_ERROR("sql.sql", "Wrong TotemSlot %u in `player_totem_model` table, skipped.", totemSlot);
+ continue;
+ }
+
+ ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race);
+ if (!raceEntry)
+ {
+ TC_LOG_ERROR("sql.sql", "Race %u defined in `player_totem_model` does not exists, skipped.", uint32(race));
+ continue;
+ }
+
+ CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(displayId);
+ if (!displayEntry)
+ {
+ TC_LOG_ERROR("sql.sql", "TotemSlot: %u defined in `player_totem_model` has non-existing model (%u), skipped.", totemSlot, displayId);
+ continue;
+ }
+
+ _playerTotemModel[std::make_pair(totemSlot, Races(race))] = displayId;
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u player totem model records in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+uint32 ObjectMgr::GetModelForTotem(SummonSlot totemSlot, Races race) const
+{
+ auto itr = _playerTotemModel.find(std::make_pair(totemSlot, race));
+ if (itr != _playerTotemModel.end())
+ return itr->second;
+
+ TC_LOG_ERROR("misc", "TotemSlot %u with RaceID (%u) have no totem model data defined, set to default model.", totemSlot, race);
+ return 0;
+}
+
void ObjectMgr::LoadLinkedRespawn()
{
uint32 oldMSTime = getMSTime();
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 9d18188d014..7f0f930acc1 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -876,6 +876,8 @@ struct DungeonEncounter
typedef std::vector<std::unique_ptr<DungeonEncounter const>> DungeonEncounterList;
typedef std::unordered_map<uint32, DungeonEncounterList> DungeonEncounterContainer;
+typedef std::map<std::pair<SummonSlot /*TotemSlot*/, Races /*RaceId*/>, uint32 /*DisplayId*/> PlayerTotemModelMap;
+
enum QueryDataGroup
{
QUERY_DATA_CREATURES = 0x01,
@@ -948,6 +950,8 @@ class TC_GAME_API ObjectMgr
ItemTemplate const* GetItemTemplate(uint32 entry) const;
ItemTemplateContainer const& GetItemTemplateStore() const { return _itemTemplateStore; }
+ uint32 GetModelForTotem(SummonSlot totemSlot, Races race) const;
+
ItemSetNameEntry const* GetItemSetNameEntry(uint32 itemId) const
{
ItemSetNameContainer::const_iterator itr = _itemSetNameStore.find(itemId);
@@ -1154,6 +1158,7 @@ class TC_GAME_API ObjectMgr
void LoadCreatureAddons();
void LoadGameObjectAddons();
void LoadCreatureModelInfo();
+ void LoadPlayerTotemModels();
void LoadEquipmentTemplates();
void LoadCreatureMovementOverrides();
void LoadGameObjectLocales();
@@ -1684,6 +1689,8 @@ class TC_GAME_API ObjectMgr
std::set<uint32> _hasDifficultyEntries[MAX_DIFFICULTY - 1]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate
std::set<uint32> _transportMaps; // Helper container storing map ids that are for transports only, loaded from gameobject_template
+
+ PlayerTotemModelMap _playerTotemModel;
};
#define sObjectMgr ObjectMgr::instance()
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 4b68744fc0a..1e6cccc2255 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -4536,7 +4536,7 @@ void Spell::EffectDestroyAllTotems(SpellEffIndex /*effIndex*/)
return;
int32 mana = 0;
- for (uint8 slot = SUMMON_SLOT_TOTEM; slot < MAX_TOTEM_SLOT; ++slot)
+ for (uint8 slot = SUMMON_SLOT_TOTEM_FIRE; slot < MAX_TOTEM_SLOT; ++slot)
{
if (!unitCaster->m_SummonSlot[slot])
continue;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index d719442f9f7..973fd3fac26 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1614,6 +1614,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading SpellInfo immunity infos...");
sSpellMgr->LoadSpellInfoImmunities();
+ TC_LOG_INFO("server.loading", "Loading Player Totem models...");
+ sObjectMgr->LoadPlayerTotemModels();
+
TC_LOG_INFO("server.loading", "Loading GameObject models...");
LoadGameObjectModelList(m_dataPath);
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index 886a18fc6cf..27e3aade686 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -1791,7 +1791,7 @@ class spell_sha_stoneclaw_totem : public SpellScript
Unit* target = GetHitUnit();
// Cast Absorb on totems
- for (uint8 slot = SUMMON_SLOT_TOTEM; slot < MAX_TOTEM_SLOT; ++slot)
+ for (uint8 slot = SUMMON_SLOT_TOTEM_FIRE; slot < MAX_TOTEM_SLOT; ++slot)
{
if (!target->m_SummonSlot[slot])
continue;
@@ -1988,7 +1988,7 @@ public:
void HandleDummy(AuraEffect const* aurEff)
{
Unit* target = GetTarget();
- for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
+ for (uint8 i = SUMMON_SLOT_TOTEM_FIRE; i < MAX_TOTEM_SLOT; ++i)
if (!target->m_SummonSlot[i])
return;
diff --git a/src/server/shared/SharedDefines.h b/src/server/shared/SharedDefines.h
index b270220113d..32dd46cdb09 100644
--- a/src/server/shared/SharedDefines.h
+++ b/src/server/shared/SharedDefines.h
@@ -3304,6 +3304,22 @@ enum SummonType
SUMMON_TYPE_JEEVES = 12
};
+enum SummonSlot
+{
+ SUMMON_SLOT_PET = 0,
+ SUMMON_SLOT_TOTEM_FIRE = 1,
+ SUMMON_SLOT_TOTEM_EARTH = 2,
+ SUMMON_SLOT_TOTEM_WATER = 3,
+ SUMMON_SLOT_TOTEM_AIR = 4,
+ SUMMON_SLOT_MINIPET = 5,
+ SUMMON_SLOT_QUEST = 6,
+
+ MAX_SUMMON_SLOT
+};
+
+#define MAX_TOTEM_SLOT 5
+#define MAX_GAMEOBJECT_SLOT 4
+
enum EventId
{
EVENT_CHARGE = 1003,