aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/9999_99_99_00_world.sql12
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.cpp2
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp8
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp9
-rw-r--r--src/server/game/Entities/Creature/Creature.h4
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp31
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp193
-rw-r--r--src/server/game/Globals/ObjectMgr.h1
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp2
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp2
-rw-r--r--src/server/game/World/World.cpp3
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp6
-rw-r--r--src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp9
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp6
18 files changed, 194 insertions, 104 deletions
diff --git a/sql/updates/world/master/9999_99_99_00_world.sql b/sql/updates/world/master/9999_99_99_00_world.sql
new file mode 100644
index 00000000000..7287d23d45b
--- /dev/null
+++ b/sql/updates/world/master/9999_99_99_00_world.sql
@@ -0,0 +1,12 @@
+--
+DROP TABLE IF EXISTS `creature_template_gossip`;
+CREATE TABLE `creature_template_gossip` (
+ `CreatureID` int UNSIGNED NOT NULL,
+ `MenuID` int UNSIGNED NOT NULL,
+ `VerifiedBuild` int NOT NULL DEFAULT 0,
+ PRIMARY KEY (`CreatureID`, `MenuID`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+INSERT INTO `creature_template_gossip` SELECT `entry`, `gossip_menu_id`, `VerifiedBuild` FROM `creature_template` WHERE `gossip_menu_id` <> 0;
+
+ALTER TABLE `creature_template` DROP COLUMN `gossip_menu_id`;
diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp
index 251789d8cfb..b53e2738911 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/database/Database/Implementation/WorldDatabase.cpp
@@ -77,7 +77,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, help FROM command", CONNECTION_SYNCH);
- PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, TitleAlt, IconName, gossip_menu_id, HealthScalingExpansion, RequiredExpansion, VignetteID, faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, CreatureDifficultyID, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName, StringId FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ? OR 1 = ?", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, TitleAlt, IconName, HealthScalingExpansion, RequiredExpansion, VignetteID, faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, CreatureDifficultyID, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName, StringId FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ? OR 1 = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH);
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 4f80e811e03..125610378fd 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -1530,12 +1530,10 @@ bool ConditionMgr::addToGossipMenus(Condition* cond) const
{
for (GossipMenusContainer::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
{
- if ((*itr).second.MenuID == cond->SourceGroup && (*itr).second.TextID == uint32(cond->SourceEntry))
- {
- (*itr).second.Conditions.push_back(cond);
- return true;
- }
+ if (itr->second.MenuID == cond->SourceGroup && (itr->second.TextID == uint32(cond->SourceEntry) || cond->SourceEntry == 0))
+ itr->second.Conditions.push_back(cond);
}
+ return true;
}
TC_LOG_ERROR("sql.sql", "{} GossipMenu {} not found.", cond->ToString(), cond->SourceGroup);
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 038aa5e2bb0..5210e4be33e 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -294,7 +294,7 @@ Creature::Creature(bool isWorldObject) : Unit(isWorldObject), MapObject(), m_Pla
m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(UI64LIT(0)), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_cannotReachTarget(false), m_cannotReachTimer(0),
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), _waypointPathId(0), _currentWaypointNodeInfo(0, 0),
m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false), _lastDamagedTime(0),
- _regenerateHealth(true), _isMissingCanSwimFlagOutOfCombat(false)
+ _regenerateHealth(true), _isMissingCanSwimFlagOutOfCombat(false), _gossipMenuId(0)
{
m_regenTimer = CREATURE_REGEN_INTERVAL;
@@ -3525,13 +3525,10 @@ void Creature::ExitVehicle(Position const* /*exitPosition*/)
uint32 Creature::GetGossipMenuId() const
{
- if (_gossipMenuId)
- return *_gossipMenuId;
-
- return GetCreatureTemplate()->GossipMenuId;
+ return _gossipMenuId;
}
-void Creature::SetGossipMenuId(Optional<uint32> gossipMenuId)
+void Creature::SetGossipMenuId(uint32 gossipMenuId)
{
_gossipMenuId = gossipMenuId;
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index c5ea0be20e9..c77feb358e9 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -413,7 +413,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool HasFlag(CreatureStaticFlags8 flag) const { return _staticFlags.HasFlag(flag); }
uint32 GetGossipMenuId() const;
- void SetGossipMenuId(Optional<uint32> gossipMenuId);
+ void SetGossipMenuId(uint32 gossipMenuId);
uint32 GetTrainerId() const;
void SetTrainerId(Optional<uint32> trainerId);
@@ -507,7 +507,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool _isMissingCanSwimFlagOutOfCombat;
- Optional<uint32> _gossipMenuId;
+ uint32 _gossipMenuId;
Optional<uint32> _trainerId;
};
diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h
index 851fcaac76b..b147c2ad04b 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -478,7 +478,7 @@ struct TC_GAME_API CreatureTemplate
std::string SubName;
std::string TitleAlt;
std::string IconName;
- uint32 GossipMenuId;
+ std::vector<uint32> GossipMenuIds;
std::unordered_map<Difficulty, CreatureLevelScaling> scalingStore;
int32 HealthScalingExpansion;
uint32 RequiredExpansion;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 9037c15c88b..bba11970aa1 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -14233,7 +14233,7 @@ uint32 Player::GetGossipTextId(WorldObject* source)
if (!source)
return DEFAULT_GOSSIP_MESSAGE;
- return GetGossipTextId(GetDefaultGossipMenuForSource(source), source);
+ return GetGossipTextId(GetGossipMenuForSource(source), source);
}
uint32 Player::GetGossipTextId(uint32 menuId, WorldObject* source)
@@ -14247,6 +14247,10 @@ uint32 Player::GetGossipTextId(uint32 menuId, WorldObject* source)
for (GossipMenusContainer::const_iterator itr = menuBounds.first; itr != menuBounds.second; ++itr)
{
+ // continue if only checks menuid instead of text
+ if (!itr->second.TextID)
+ continue;
+
if (sConditionMgr->IsObjectMeetToConditions(this, source, itr->second.Conditions))
textId = itr->second.TextID;
}
@@ -14254,12 +14258,33 @@ uint32 Player::GetGossipTextId(uint32 menuId, WorldObject* source)
return textId;
}
-uint32 Player::GetDefaultGossipMenuForSource(WorldObject* source)
+uint32 Player::GetGossipMenuForSource(WorldObject* source)
{
switch (source->GetTypeId())
{
case TYPEID_UNIT:
- return source->ToCreature()->GetGossipMenuId();
+ {
+ uint32 menuIdToShow = source->ToCreature()->GetGossipMenuId();
+
+ // if menu id is set by script
+ if (menuIdToShow)
+ return menuIdToShow;
+
+ // otherwise pick from db based on conditions
+ for (uint32 menuId : source->ToCreature()->GetCreatureTemplate()->GossipMenuIds)
+ {
+ GossipMenusMapBounds menuBounds = sObjectMgr->GetGossipMenusMapBounds(menuId);
+
+ for (GossipMenusContainer::const_iterator itr = menuBounds.first; itr != menuBounds.second; ++itr)
+ {
+ if (!sConditionMgr->IsObjectMeetToConditions(this, source, itr->second.Conditions))
+ continue;
+
+ menuIdToShow = menuId;
+ }
+ }
+ return menuIdToShow;
+ }
case TYPEID_GAMEOBJECT:
return source->ToGameObject()->GetGOInfo()->GetGossipMenuId();
default:
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index c4e6bce850c..76862cfd9e6 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1542,7 +1542,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 GetGossipTextId(uint32 menuId, WorldObject* source);
uint32 GetGossipTextId(WorldObject* source);
- static uint32 GetDefaultGossipMenuForSource(WorldObject* source);
+ uint32 GetGossipMenuForSource(WorldObject* source);
/*********************************************************/
/*** QUEST SYSTEM ***/
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 209f08a92ab..f75365fe390 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -352,21 +352,21 @@ void ObjectMgr::LoadCreatureTemplates()
// 0 1 2 3 4 5 6 7 8
// "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, "
- // 9 10 11 12 13 14
- // "TitleAlt, IconName, gossip_menu_id, HealthScalingExpansion, RequiredExpansion, VignetteID, "
- // 15 16 17 18 19 20 21 22 23 24 25
+ // 9 10 11 12 13
+ // "TitleAlt, IconName, HealthScalingExpansion, RequiredExpansion, VignetteID, "
+ // 14 15 16 17 18 19 20 21 22 23 24
// "faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, "
- // 26 27 28 29 30 31 32 33
+ // 25 26 27 28 29 30 31 32
// "unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, "
- // 34 35 36 37 38 39 40 41 42 43
+ // 33 34 35 36 37 38 39 40 41 42
// "type_flags, type_flags2, lootid, pickpocketloot, skinloot, VehicleId, mingold, maxgold, AIName, MovementType, "
- // 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
+ // 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
// "ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, "
- // 59 60 61 62 63 64
+ // 58 59 60 61 62 63
// "RacialLeader, movementId, CreatureDifficultyID, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, "
- // 65 66 67
+ // 64 65 66
// "mechanic_immune_mask, spell_school_immune_mask, flags_extra, "
- // 68 69
+ // 67 68
// "ScriptName, StringId FROM creature_template WHERE entry = ? OR 1 = ?");
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEMPLATE);
@@ -420,34 +420,33 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
creatureTemplate.SubName = fields[8].GetString();
creatureTemplate.TitleAlt = fields[9].GetString();
creatureTemplate.IconName = fields[10].GetString();
- creatureTemplate.GossipMenuId = fields[11].GetUInt32();
- creatureTemplate.HealthScalingExpansion = fields[12].GetInt32();
- creatureTemplate.RequiredExpansion = fields[13].GetUInt32();
- creatureTemplate.VignetteID = fields[14].GetUInt32();
- creatureTemplate.faction = fields[15].GetUInt16();
- creatureTemplate.npcflag = fields[16].GetUInt64();
- creatureTemplate.speed_walk = fields[17].GetFloat();
- creatureTemplate.speed_run = fields[18].GetFloat();
- creatureTemplate.scale = fields[19].GetFloat();
- creatureTemplate.rank = uint32(fields[20].GetUInt8());
- creatureTemplate.dmgschool = uint32(fields[21].GetInt8());
- creatureTemplate.BaseAttackTime = fields[22].GetUInt32();
- creatureTemplate.RangeAttackTime = fields[23].GetUInt32();
- creatureTemplate.BaseVariance = fields[24].GetFloat();
- creatureTemplate.RangeVariance = fields[25].GetFloat();
- creatureTemplate.unit_class = uint32(fields[26].GetUInt8());
- creatureTemplate.unit_flags = fields[27].GetUInt32();
- creatureTemplate.unit_flags2 = fields[28].GetUInt32();
- creatureTemplate.unit_flags3 = fields[29].GetUInt32();
- creatureTemplate.dynamicflags = fields[30].GetUInt32();
- creatureTemplate.family = CreatureFamily(fields[31].GetInt32());
- creatureTemplate.trainer_class = uint32(fields[32].GetUInt8());
- creatureTemplate.type = uint32(fields[33].GetUInt8());
- creatureTemplate.type_flags = fields[34].GetUInt32();
- creatureTemplate.type_flags2 = fields[35].GetUInt32();
- creatureTemplate.lootid = fields[36].GetUInt32();
- creatureTemplate.pickpocketLootId = fields[37].GetUInt32();
- creatureTemplate.SkinLootId = fields[38].GetUInt32();
+ creatureTemplate.HealthScalingExpansion = fields[11].GetInt32();
+ creatureTemplate.RequiredExpansion = fields[12].GetUInt32();
+ creatureTemplate.VignetteID = fields[13].GetUInt32();
+ creatureTemplate.faction = fields[14].GetUInt16();
+ creatureTemplate.npcflag = fields[15].GetUInt64();
+ creatureTemplate.speed_walk = fields[16].GetFloat();
+ creatureTemplate.speed_run = fields[17].GetFloat();
+ creatureTemplate.scale = fields[18].GetFloat();
+ creatureTemplate.rank = uint32(fields[19].GetUInt8());
+ creatureTemplate.dmgschool = uint32(fields[20].GetInt8());
+ creatureTemplate.BaseAttackTime = fields[21].GetUInt32();
+ creatureTemplate.RangeAttackTime = fields[22].GetUInt32();
+ creatureTemplate.BaseVariance = fields[23].GetFloat();
+ creatureTemplate.RangeVariance = fields[24].GetFloat();
+ creatureTemplate.unit_class = uint32(fields[25].GetUInt8());
+ creatureTemplate.unit_flags = fields[26].GetUInt32();
+ creatureTemplate.unit_flags2 = fields[27].GetUInt32();
+ creatureTemplate.unit_flags3 = fields[28].GetUInt32();
+ creatureTemplate.dynamicflags = fields[29].GetUInt32();
+ creatureTemplate.family = CreatureFamily(fields[30].GetInt32());
+ creatureTemplate.trainer_class = uint32(fields[31].GetUInt8());
+ creatureTemplate.type = uint32(fields[32].GetUInt8());
+ creatureTemplate.type_flags = fields[33].GetUInt32();
+ creatureTemplate.type_flags2 = fields[34].GetUInt32();
+ creatureTemplate.lootid = fields[35].GetUInt32();
+ creatureTemplate.pickpocketLootId = fields[36].GetUInt32();
+ creatureTemplate.SkinLootId = fields[37].GetUInt32();
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
creatureTemplate.resistance[i] = 0;
@@ -455,51 +454,97 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
creatureTemplate.spells[i] = 0;
- creatureTemplate.VehicleId = fields[39].GetUInt32();
- creatureTemplate.mingold = fields[40].GetUInt32();
- creatureTemplate.maxgold = fields[41].GetUInt32();
- creatureTemplate.AIName = fields[42].GetString();
- creatureTemplate.MovementType = uint32(fields[43].GetUInt8());
+ creatureTemplate.VehicleId = fields[38].GetUInt32();
+ creatureTemplate.mingold = fields[39].GetUInt32();
+ creatureTemplate.maxgold = fields[40].GetUInt32();
+ creatureTemplate.AIName = fields[41].GetString();
+ creatureTemplate.MovementType = uint32(fields[42].GetUInt8());
+ if (!fields[43].IsNull())
+ creatureTemplate.Movement.Ground = static_cast<CreatureGroundMovementType>(fields[43].GetUInt8());
+
if (!fields[44].IsNull())
- creatureTemplate.Movement.Ground = static_cast<CreatureGroundMovementType>(fields[44].GetUInt8());
+ creatureTemplate.Movement.Swim = fields[44].GetBool();
if (!fields[45].IsNull())
- creatureTemplate.Movement.Swim = fields[45].GetBool();
+ creatureTemplate.Movement.Flight = static_cast<CreatureFlightMovementType>(fields[45].GetUInt8());
if (!fields[46].IsNull())
- creatureTemplate.Movement.Flight = static_cast<CreatureFlightMovementType>(fields[46].GetUInt8());
+ creatureTemplate.Movement.Rooted = fields[46].GetBool();
if (!fields[47].IsNull())
- creatureTemplate.Movement.Rooted = fields[47].GetBool();
+ creatureTemplate.Movement.Chase = static_cast<CreatureChaseMovementType>(fields[47].GetUInt8());
if (!fields[48].IsNull())
- creatureTemplate.Movement.Chase = static_cast<CreatureChaseMovementType>(fields[48].GetUInt8());
+ creatureTemplate.Movement.Random = static_cast<CreatureRandomMovementType>(fields[48].GetUInt8());
if (!fields[49].IsNull())
- creatureTemplate.Movement.Random = static_cast<CreatureRandomMovementType>(fields[49].GetUInt8());
-
- if (!fields[50].IsNull())
- creatureTemplate.Movement.InteractionPauseTimer = fields[50].GetUInt32();
-
- creatureTemplate.HoverHeight = fields[51].GetFloat();
- creatureTemplate.ModHealth = fields[52].GetFloat();
- creatureTemplate.ModHealthExtra = fields[53].GetFloat();
- creatureTemplate.ModMana = fields[54].GetFloat();
- creatureTemplate.ModManaExtra = fields[55].GetFloat();
- creatureTemplate.ModArmor = fields[56].GetFloat();
- creatureTemplate.ModDamage = fields[57].GetFloat();
- creatureTemplate.ModExperience = fields[58].GetFloat();
- creatureTemplate.RacialLeader = fields[59].GetBool();
- creatureTemplate.movementId = fields[60].GetUInt32();
- creatureTemplate.CreatureDifficultyID = fields[61].GetInt32();
- creatureTemplate.WidgetSetID = fields[62].GetInt32();
- creatureTemplate.WidgetSetUnitConditionID = fields[63].GetInt32();
- creatureTemplate.RegenHealth = fields[64].GetBool();
- creatureTemplate.MechanicImmuneMask = fields[65].GetUInt64();
- creatureTemplate.SpellSchoolImmuneMask = fields[66].GetUInt32();
- creatureTemplate.flags_extra = fields[67].GetUInt32();
- creatureTemplate.ScriptID = GetScriptId(fields[68].GetString());
- creatureTemplate.StringId = fields[69].GetString();
+ creatureTemplate.Movement.InteractionPauseTimer = fields[49].GetUInt32();
+
+ creatureTemplate.HoverHeight = fields[50].GetFloat();
+ creatureTemplate.ModHealth = fields[51].GetFloat();
+ creatureTemplate.ModHealthExtra = fields[52].GetFloat();
+ creatureTemplate.ModMana = fields[53].GetFloat();
+ creatureTemplate.ModManaExtra = fields[54].GetFloat();
+ creatureTemplate.ModArmor = fields[55].GetFloat();
+ creatureTemplate.ModDamage = fields[56].GetFloat();
+ creatureTemplate.ModExperience = fields[57].GetFloat();
+ creatureTemplate.RacialLeader = fields[58].GetBool();
+ creatureTemplate.movementId = fields[59].GetUInt32();
+ creatureTemplate.CreatureDifficultyID = fields[60].GetInt32();
+ creatureTemplate.WidgetSetID = fields[61].GetInt32();
+ creatureTemplate.WidgetSetUnitConditionID = fields[62].GetInt32();
+ creatureTemplate.RegenHealth = fields[63].GetBool();
+ creatureTemplate.MechanicImmuneMask = fields[64].GetUInt64();
+ creatureTemplate.SpellSchoolImmuneMask = fields[65].GetUInt32();
+ creatureTemplate.flags_extra = fields[66].GetUInt32();
+ creatureTemplate.ScriptID = GetScriptId(fields[67].GetString());
+ creatureTemplate.StringId = fields[68].GetString();
+}
+
+void ObjectMgr::LoadCreatureTemplateGossip()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1
+ QueryResult result = WorldDatabase.Query("SELECT CreatureID, MenuID FROM creature_template_gossip");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 creature template gossip definitions. DB table `creature_template_gossip` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 creatureID = fields[0].GetUInt32();
+ uint32 menuID = fields[1].GetUInt32();
+
+ CreatureTemplateContainer::iterator itr = _creatureTemplateStore.find(creatureID);
+ if (itr == _creatureTemplateStore.end())
+ {
+ TC_LOG_ERROR("sql.sql", "creature_template_gossip has gossip definitions for creature %u but this creature doesn't exist", creatureID);
+ continue;
+ }
+
+ GossipMenusMapBounds menuBounds = sObjectMgr->GetGossipMenusMapBounds(menuID);
+ if (menuBounds.first == menuBounds.second)
+ {
+ TC_LOG_ERROR("sql.sql", "creature_template_gossip has gossip definitions for menu id %u but this menu doesn't exist", menuID);
+ continue;
+ }
+
+ CreatureTemplate& creatureTemplate = itr->second;
+ creatureTemplate.GossipMenuIds.push_back(menuID);
+
+ ++count;
+
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u creature template gossip menus in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadCreatureTemplateResistances()
@@ -1243,9 +1288,9 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
const_cast<CreatureTemplate*>(cInfo)->ModDamage *= Creature::_GetDamageMod(cInfo->rank);
- if (cInfo->GossipMenuId && !(cInfo->npcflag & UNIT_NPC_FLAG_GOSSIP))
- TC_LOG_INFO("sql.sql", "Creature (Entry: {}) has assigned gossip menu {}, but npcflag does not include UNIT_NPC_FLAG_GOSSIP.", cInfo->Entry, cInfo->GossipMenuId);
- else if (!cInfo->GossipMenuId && cInfo->npcflag & UNIT_NPC_FLAG_GOSSIP)
+ if (!cInfo->GossipMenuIds.empty() && !(cInfo->npcflag & UNIT_NPC_FLAG_GOSSIP))
+ TC_LOG_INFO("sql.sql", "Creature (Entry: {}) has assigned gossip menu, but npcflag does not include UNIT_NPC_FLAG_GOSSIP.", cInfo->Entry);
+ else if (cInfo->GossipMenuIds.empty() && cInfo->npcflag & UNIT_NPC_FLAG_GOSSIP)
TC_LOG_INFO("sql.sql", "Creature (Entry: {}) has npcflag UNIT_NPC_FLAG_GOSSIP, but gossip menu is unassigned.", cInfo->Entry);
}
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index e397b035994..cb81f9903ad 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -1326,6 +1326,7 @@ class TC_GAME_API ObjectMgr
void LoadCreatureTemplates();
void LoadCreatureTemplateAddons();
void LoadCreatureTemplate(Field* fields);
+ void LoadCreatureTemplateGossip();
void LoadCreatureTemplateResistances();
void LoadCreatureTemplateSpells();
void LoadCreatureTemplateModels();
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index a2274a3b6e0..23249272a41 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -183,7 +183,7 @@ void WorldSession::HandleGossipHelloOpcode(WorldPackets::NPC::Hello& packet)
if (!unit->AI()->OnGossipHello(_player))
{
// _player->TalkedToCreature(unit->GetEntry(), unit->GetGUID());
- _player->PrepareGossipMenu(unit, unit->GetGossipMenuId(), true);
+ _player->PrepareGossipMenu(unit, _player->GetGossipMenuForSource(unit), true);
_player->SendPreparedGossip(unit);
}
}
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 18eb7daa947..aa80e11e1cd 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -98,7 +98,7 @@ void WorldSession::HandleQuestgiverHelloOpcode(WorldPackets::Quest::QuestGiverHe
if (creature->AI()->OnGossipHello(_player))
return;
- _player->PrepareGossipMenu(creature, creature->GetGossipMenuId(), true);
+ _player->PrepareGossipMenu(creature, _player->GetGossipMenuForSource(creature), true);
_player->SendPreparedGossip(creature);
}
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index b5a73e3feeb..0f4cde86499 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2256,6 +2256,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Gossip menu addon...");
sObjectMgr->LoadGossipMenuAddon();
+ TC_LOG_INFO("server.loading", "Loading Creature Template Gossip...");
+ sObjectMgr->LoadCreatureTemplateGossip();
+
TC_LOG_INFO("server.loading", "Loading Creature trainers...");
sObjectMgr->LoadCreatureTrainers(); // must be after LoadGossipMenuItems
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index ac65e640ade..67f23cf43ba 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -678,7 +678,7 @@ public:
bool OnGossipHello(Player* player) override
{
- uint32 gossipMenuId = Player::GetDefaultGossipMenuForSource(me);
+ uint32 gossipMenuId = player->GetGossipMenuForSource(me);
InitGossipMenuFor(player, gossipMenuId);
if (player->GetQuestStatus(QUEST_DEATH_CHALLENGE) == QUEST_STATUS_INCOMPLETE && me->IsFullHealth())
{
@@ -688,7 +688,7 @@ public:
if (player->IsInCombat() || me->IsInCombat())
return true;
- AddGossipItemFor(player, gossipMenuId, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ AddGossipItemFor(player, player->GetGossipMenuForSource(me), 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
}
return true;
diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp
index 4f6dfe7f7d7..992163dfa3a 100644
--- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp
+++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp
@@ -130,7 +130,7 @@ public:
bool OnGossipHello(Player* player) override
{
- uint32 gossipMenuId = Player::GetDefaultGossipMenuForSource(me);
+ uint32 gossipMenuId = player->GetGossipMenuForSource(me);
InitGossipMenuFor(player, gossipMenuId);
if (instance->GetData(TYPE_FREE_NPC) != DONE && instance->GetData(TYPE_RETHILGORE) == DONE)
AddGossipItemFor(player, gossipMenuId, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp
index c520cdd56d7..4041d02be1e 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp
@@ -69,7 +69,9 @@ enum Points
enum Misc
{
- ITEM_VIRTUAL_ITEM = 5301
+ ITEM_VIRTUAL_ITEM = 5301,
+
+ GOSSIP_MENU_START_INTRO = 12797,
};
Position const VoljinIntroWaypoint[4] =
@@ -104,7 +106,7 @@ class npc_voljin_zulaman : public CreatureScript
if (_instance->GetData(DATA_ZULAMAN_STATE) != NOT_STARTED)
return true;
- if (me->GetGossipMenuId() == menuId && !gossipListId)
+ if (menuId == GOSSIP_MENU_START_INTRO && !gossipListId)
{
_events.Reset();
me->SetMountDisplayId(0);
diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
index 9258359eb16..b9fcfc779c4 100644
--- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
+++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
@@ -104,6 +104,11 @@ enum Points
MAX_BRANN_WAYPOINTS_INTRO = 17
};
+enum GossipMenuIds
+{
+ GOSSIP_MENU_START_INTRO = 11339,
+};
+
Position const AnraphetActivatePos = {-193.656f, 366.689f, 75.91001f, 3.138207f};
Position const BrannIntroWaypoint[MAX_BRANN_WAYPOINTS_INTRO] =
@@ -331,12 +336,12 @@ class npc_brann_bronzebeard_anraphet : public CreatureScript
{
npc_brann_bronzebeard_anraphetAI(Creature* creature) : CreatureAI(creature), _currentPoint(0), _instance(creature->GetInstanceScript()) { }
- bool OnGossipSelect(Player* /*player*/, uint32 sender, uint32 action) override
+ bool OnGossipSelect(Player* /*player*/, uint32 menuId, uint32 action) override
{
if (_instance->GetBossState(DATA_VAULT_OF_LIGHTS) == DONE)
return true;
- if (me->GetGossipMenuId() == sender && !action)
+ if (menuId == GOSSIP_MENU_START_INTRO && !action)
{
_instance->SetBossState(DATA_VAULT_OF_LIGHTS, IN_PROGRESS);
_currentPoint = 0;
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 eadbf4252cb..cbff6530c4f 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -364,7 +364,9 @@ enum MiscData
enum Misc
{
DATA_PLAGUE_STACK = 70337,
- DATA_VILE = 45814622
+ DATA_VILE = 45814622,
+
+ GOSSIP_MENU_START_INTRO = 10993
};
class NecroticPlagueTargetCheck
@@ -1193,7 +1195,7 @@ struct npc_tirion_fordring_tft : public ScriptedAI
bool OnGossipSelect(Player* /*player*/, uint32 menuId, uint32 gossipListId) override
{
- if (me->GetGossipMenuId() == menuId && !gossipListId)
+ if (menuId == GOSSIP_MENU_START_INTRO && !gossipListId)
{
_events.SetPhase(PHASE_INTRO);
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);