mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-20 06:59:46 -04:00
Core/Totems: update select display for shaman totems (#23583)
(cherry picked from commit 8ca6a20e73)
# Conflicts:
# src/server/game/Entities/Totem/Totem.cpp
# src/server/game/Entities/Unit/Unit.cpp
# src/server/game/Entities/Unit/Unit.h
# src/server/game/Spells/SpellMgr.cpp
# src/server/game/Spells/SpellMgr.h
# src/server/game/World/World.cpp
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
DROP TABLE IF EXISTS `player_totem_model`;
|
||||
CREATE TABLE `player_totem_model` (
|
||||
`TotemSlot` TINYINT(3) UNSIGNED NOT NULL,
|
||||
`RaceId` TINYINT(3) UNSIGNED NOT NULL,
|
||||
`DisplayId` INT(10) UNSIGNED NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`TotemSlot`,`RaceID`)
|
||||
) ENGINE=MYISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `player_totem_model` (`TotemSlot`, `RaceId`, `DisplayId`) VALUES
|
||||
-- Orc
|
||||
(1, 2, 30758),
|
||||
(2, 2, 30757),
|
||||
(3, 2, 30759),
|
||||
(4, 2, 30756),
|
||||
-- Dwarf
|
||||
(1, 3, 30754),
|
||||
(2, 3, 30753),
|
||||
(3, 3, 30755),
|
||||
(4, 3, 30736),
|
||||
-- Tauren
|
||||
(1, 6, 4589),
|
||||
(2, 6, 4588),
|
||||
(3, 6, 4587),
|
||||
(4, 6, 4590),
|
||||
-- Troll
|
||||
(1, 8, 30762),
|
||||
(2, 8, 30761),
|
||||
(3, 8, 30763),
|
||||
(4, 8, 30760),
|
||||
-- Draenei
|
||||
(1, 11, 19074),
|
||||
(2, 11, 19073),
|
||||
(3, 11, 19075),
|
||||
(4, 11, 19071);
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user