aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2020_11_05_00_world.sql80
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.cpp2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp1
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h1
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp323
-rw-r--r--src/server/game/Globals/ObjectMgr.h29
-rw-r--r--src/server/game/Quests/QuestDef.cpp194
-rw-r--r--src/server/game/Quests/QuestDef.h74
-rw-r--r--src/server/game/Scenarios/Scenario.cpp3
-rw-r--r--src/server/game/Scenarios/ScenarioMgr.cpp46
-rw-r--r--src/server/game/Scenarios/ScenarioMgr.h6
-rw-r--r--src/server/scripts/Commands/cs_go.cpp1
12 files changed, 495 insertions, 265 deletions
diff --git a/sql/updates/world/master/2020_11_05_00_world.sql b/sql/updates/world/master/2020_11_05_00_world.sql
new file mode 100644
index 00000000000..dcdfdbaeb7d
--- /dev/null
+++ b/sql/updates/world/master/2020_11_05_00_world.sql
@@ -0,0 +1,80 @@
+ALTER TABLE `creature_template` DROP `FadeRegionRadius`;
+
+ALTER TABLE `playerchoice_response`
+ ADD `ResponseIdentifier` smallint(5) unsigned NOT NULL AFTER `ResponseId`,
+ ADD `UiTextureKitID` int(11) NOT NULL DEFAULT '0' AFTER `GroupID`;
+
+--
+-- Table structure for table `playerchoice_response_reward_item_choice`
+--
+DROP TABLE IF EXISTS `playerchoice_response_reward_item_choice`;
+CREATE TABLE `playerchoice_response_reward_item_choice` (
+ `ChoiceId` int(11) NOT NULL,
+ `ResponseId` int(11) NOT NULL,
+ `Index` int(10) unsigned NOT NULL,
+ `ItemId` int(10) unsigned NOT NULL DEFAULT '0',
+ `BonusListIDs` text,
+ `Quantity` int(11) NOT NULL DEFAULT '0',
+ `VerifiedBuild` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ChoiceId`,`ResponseId`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Table structure for table `playerchoice_response_maw_power`
+--
+DROP TABLE IF EXISTS `playerchoice_response_maw_power`;
+CREATE TABLE `playerchoice_response_maw_power` (
+ `ChoiceId` int(11) NOT NULL,
+ `ResponseId` int(11) NOT NULL,
+ `TypeArtFileID` int(11) DEFAULT '0',
+ `Rarity` int(11) DEFAULT '0',
+ `RarityColor` int(10) unsigned DEFAULT '0',
+ `SpellID` int(11) DEFAULT '0',
+ `MaxStacks` int(11) DEFAULT '0',
+ `VerifiedBuild` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ChoiceId`,`ResponseId`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+ALTER TABLE `quest_poi` ADD `NavigationPlayerConditionID` int(11) NOT NULL DEFAULT '0' AFTER `PlayerConditionID`;
+
+ALTER TABLE `quest_poi_points` ADD `Z` int(11) NOT NULL DEFAULT '0' AFTER `Y`;
+
+--
+-- Table structure for table `quest_reward_choice_items`
+--
+DROP TABLE IF EXISTS `quest_reward_choice_items`;
+CREATE TABLE `quest_reward_choice_items` (
+ `QuestID` int(10) unsigned NOT NULL,
+ `Type1` tinyint(3) unsigned DEFAULT '0',
+ `Type2` tinyint(3) unsigned DEFAULT '0',
+ `Type3` tinyint(3) unsigned DEFAULT '0',
+ `Type4` tinyint(3) unsigned DEFAULT '0',
+ `Type5` tinyint(3) unsigned DEFAULT '0',
+ `Type6` tinyint(3) unsigned DEFAULT '0',
+ `VerifiedBuild` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`QuestID`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Table structure for table `quest_reward_display_spell`
+--
+DROP TABLE IF EXISTS `quest_reward_display_spell`;
+CREATE TABLE `quest_reward_display_spell` (
+ `QuestID` int(10) unsigned NOT NULL,
+ `Idx` int(10) unsigned NOT NULL,
+ `SpellID` int(10) unsigned DEFAULT '0',
+ `PlayerConditionID` int(10) unsigned DEFAULT '0',
+ `VerifiedBuild` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`QuestID`,`Idx`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+ALTER TABLE `quest_template`
+ ADD `ContentTuningID` int(10) unsigned NOT NULL DEFAULT '0' AFTER `QuestPackageID`,
+ DROP `QuestLevel`,
+ DROP `ScalingFactionGroup`,
+ DROP `MaxScalingLevel`,
+ DROP `MinLevel`;
+
+ALTER TABLE `scenario_poi` ADD `NavigationPlayerConditionID` int(11) NOT NULL DEFAULT '0' AFTER `PlayerConditionID`;
+
+ALTER TABLE `scenario_poi_points` ADD `Z` int(11) NOT NULL DEFAULT '0' AFTER `Y`;
diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp
index 4ae8a47b03d..be89f9d483f 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, permission, 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, minlevel, maxlevel, 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, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, FadeRegionRadius, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template 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, gossip_menu_id, minlevel, maxlevel, 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, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template 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/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 95b329a6af7..a75919adba2 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -208,7 +208,6 @@ WorldPacket CreatureTemplate::BuildQueryData(LocaleConstant loc) const
stats.HealthScalingExpansion = HealthScalingExpansion;
stats.VignetteID = VignetteID;
stats.Class = unit_class;
- stats.FadeRegionRadius = FadeRegionRadius;
stats.WidgetSetID = WidgetSetID;
stats.WidgetSetUnitConditionID = WidgetSetUnitConditionID;
diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h
index 0fc310f1fce..2219c2f79fd 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -395,7 +395,6 @@ struct TC_GAME_API CreatureTemplate
float ModExperience;
bool RacialLeader;
uint32 movementId;
- float FadeRegionRadius;
int32 WidgetSetID;
int32 WidgetSetUnitConditionID;
bool RegenHealth;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 52884fd4110..6831a01a1f7 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -430,9 +430,9 @@ void ObjectMgr::LoadCreatureTemplates()
// "spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, "
// 60 61 62 63 64 65 66 67 68
// "InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, "
- // 69 70 71 72 73 74 75 76
- // "RacialLeader, movementId, FadeRegionRadius, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, mechanic_immune_mask, flags_extra, "
- // 77
+ // 69 70 71 72 73 74 75
+ // "RacialLeader, movementId, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, mechanic_immune_mask, flags_extra, "
+ // 76
// "ScriptName FROM creature_template WHERE entry = ? OR 1 = ?");
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEMPLATE);
@@ -536,13 +536,12 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
creatureTemplate.ModExperience = fields[68].GetFloat();
creatureTemplate.RacialLeader = fields[69].GetBool();
creatureTemplate.movementId = fields[70].GetUInt32();
- creatureTemplate.FadeRegionRadius = fields[71].GetFloat();
- creatureTemplate.WidgetSetID = fields[72].GetInt32();
- creatureTemplate.WidgetSetUnitConditionID = fields[73].GetInt32();
- creatureTemplate.RegenHealth = fields[74].GetBool();
- creatureTemplate.MechanicImmuneMask = fields[75].GetUInt32();
- creatureTemplate.flags_extra = fields[76].GetUInt32();
- creatureTemplate.ScriptID = GetScriptId(fields[77].GetString());
+ creatureTemplate.WidgetSetID = fields[71].GetInt32();
+ creatureTemplate.WidgetSetUnitConditionID = fields[72].GetInt32();
+ creatureTemplate.RegenHealth = fields[73].GetBool();
+ creatureTemplate.MechanicImmuneMask = fields[74].GetUInt32();
+ creatureTemplate.flags_extra = fields[75].GetUInt32();
+ creatureTemplate.ScriptID = GetScriptId(fields[76].GetString());
}
void ObjectMgr::LoadCreatureTemplateModels()
@@ -4083,6 +4082,7 @@ void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, Play
info->stats[STAT_STAMINA] += (lvl > 32 ? 2: (lvl > 4 ? 1: 0));
info->stats[STAT_AGILITY] += (lvl > 38 ? 2: (lvl > 8 && (lvl%2) ? 1: 0));
info->stats[STAT_INTELLECT] += (lvl > 38 ? 3: (lvl > 4 ? 1: 0));
+ break;
}
}
}
@@ -4100,35 +4100,35 @@ void ObjectMgr::LoadQuests()
_exclusiveQuestGroups.clear();
QueryResult result = WorldDatabase.Query("SELECT "
- //0 1 2 3 4 5 6 7 8 9 10 11 12
- "ID, QuestType, QuestLevel, ScalingFactionGroup, MaxScalingLevel, QuestPackageID, MinLevel, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, RewardXPMultiplier, "
- //13 14 15 16 17 18 19 20 21 22 23
- "RewardMoney, RewardMoneyDifficulty, RewardMoneyMultiplier, RewardBonusMoney, RewardDisplaySpell1, RewardDisplaySpell2, RewardDisplaySpell3, RewardSpell, RewardHonor, RewardKillHonor, StartItem, "
- //24 25 26 27 28 29
+ //0 1 2 3 4 5 6 7 8 9
+ "ID, QuestType, QuestPackageID, ContentTuningID, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, RewardXPMultiplier, "
+ //10 11 12 13 14 15 16 17
+ "RewardMoney, RewardMoneyDifficulty, RewardMoneyMultiplier, RewardBonusMoney, RewardSpell, RewardHonor, RewardKillHonor, StartItem, "
+ //18 19 20 21 22 23
"RewardArtifactXPDifficulty, RewardArtifactXPMultiplier, RewardArtifactCategoryID, Flags, FlagsEx, FlagsEx2, "
- //30 31 32 33 34 35 36 37
+ //24 25 26 27 28 29 30 31
"RewardItem1, RewardAmount1, ItemDrop1, ItemDropQuantity1, RewardItem2, RewardAmount2, ItemDrop2, ItemDropQuantity2, "
- //38 39 40 41 42 43 44 45
+ //32 33 34 35 36 37 38 39
"RewardItem3, RewardAmount3, ItemDrop3, ItemDropQuantity3, RewardItem4, RewardAmount4, ItemDrop4, ItemDropQuantity4, "
- //46 47 48 49 50 51
+ //40 41 42 43 44 45
"RewardChoiceItemID1, RewardChoiceItemQuantity1, RewardChoiceItemDisplayID1, RewardChoiceItemID2, RewardChoiceItemQuantity2, RewardChoiceItemDisplayID2, "
- //52 53 54 55 56 57
+ //46 47 48 49 50 51
"RewardChoiceItemID3, RewardChoiceItemQuantity3, RewardChoiceItemDisplayID3, RewardChoiceItemID4, RewardChoiceItemQuantity4, RewardChoiceItemDisplayID4, "
- //58 59 60 61 62 63
+ //52 53 54 55 56 57
"RewardChoiceItemID5, RewardChoiceItemQuantity5, RewardChoiceItemDisplayID5, RewardChoiceItemID6, RewardChoiceItemQuantity6, RewardChoiceItemDisplayID6, "
- //64 65 66 67 68 69 70 71 72 73 74
+ //58 59 60 61 62 63 64 65 66 67 68
"POIContinent, POIx, POIy, POIPriority, RewardTitle, RewardArenaPoints, RewardSkillLineID, RewardNumSkillUps, PortraitGiver, PortraitGiverMount, PortraitTurnIn, "
- //75 76 77 78 79 80 81 82
+ //69 70 71 72 73 74 75 76
"RewardFactionID1, RewardFactionValue1, RewardFactionOverride1, RewardFactionCapIn1, RewardFactionID2, RewardFactionValue2, RewardFactionOverride2, RewardFactionCapIn2, "
- //83 84 85 86 87 88 89 90
+ //77 78 79 80 81 82 83 84
"RewardFactionID3, RewardFactionValue3, RewardFactionOverride3, RewardFactionCapIn3, RewardFactionID4, RewardFactionValue4, RewardFactionOverride4, RewardFactionCapIn4, "
- //91 92 93 94 95
+ //85 86 87 88 89
"RewardFactionID5, RewardFactionValue5, RewardFactionOverride5, RewardFactionCapIn5, RewardFactionFlags, "
- //96 97 98 99 100 101 102 103
+ //90 91 92 93 94 95 96 97
"RewardCurrencyID1, RewardCurrencyQty1, RewardCurrencyID2, RewardCurrencyQty2, RewardCurrencyID3, RewardCurrencyQty3, RewardCurrencyID4, RewardCurrencyQty4, "
- //104 105 106 107 108 109 110 111 112
+ //98 99 100 101 102 103 104 105 106
"AcceptedSoundKitID, CompleteSoundKitID, AreaGroupID, TimeAllowed, AllowableRaces, TreasurePickerID, Expansion, ManagedWorldStateID, QuestSessionBonus, "
- //113 114 115 116 117 118 119 120 121
+ //107 108 109 110 111 112 113 114 115
"LogTitle, LogDescription, QuestDescription, AreaDescription, PortraitGiverText, PortraitGiverName, PortraitTurnInText, PortraitTurnInName, QuestCompletionLog"
" FROM quest_template");
if (!result)
@@ -4159,8 +4159,15 @@ void ObjectMgr::LoadQuests()
QuestLoaderFunction LoaderFunction;
};
- static std::vector<QuestLoaderHelper> const QuestLoaderHelpers =
+ // QuestID needs to be fields[0]
+ QuestLoaderHelper const QuestLoaderHelpers[] =
{
+ // 0 1 2 3 4 5 6
+ { "QuestID, Type1, Type2, Type3, Type4, Type5, Type6", "quest_reward_choice_items", "", "reward choice items", &Quest::LoadRewardChoiceItems },
+
+ // 0 1 2
+ { "QuestID, SpellID, PlayerConditionID", "quest_reward_display_spell", "ORDER BY QuestID ASC, Idx ASC", "reward display spells", &Quest::LoadRewardDisplaySpell },
+
// 0 1 2 3 4 5 6 7 8
{ "ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4", "quest_details", "", "details", &Quest::LoadQuestDetails },
@@ -4180,14 +4187,13 @@ void ObjectMgr::LoadQuests()
// 0 1
{ "QuestId, RewardMailSenderEntry", "quest_mail_sender", "", "mail sender entries", &Quest::LoadQuestMailSender },
- // QuestID needs to be fields[0]
// 0 1 2 3 4 5 6 7 8 9
{ "QuestID, ID, Type, StorageIndex, ObjectID, Amount, Flags, Flags2, ProgressBarWeight, Description", "quest_objectives", "ORDER BY `Order` ASC, StorageIndex ASC", "quest objectives", &Quest::LoadQuestObjective }
};
for (QuestLoaderHelper const& loader : QuestLoaderHelpers)
{
- QueryResult result = WorldDatabase.PQuery("SELECT %s FROM %s", loader.QueryFields, loader.TableName, loader.QueryExtra);
+ QueryResult result = WorldDatabase.PQuery("SELECT %s FROM %s %s", loader.QueryFields, loader.TableName, loader.QueryExtra);
if (!result)
TC_LOG_ERROR("server.loading", ">> Loaded 0 quest %s. DB table `%s` is empty.", loader.TableDesc, loader.TableName);
@@ -4315,10 +4321,10 @@ void ObjectMgr::LoadQuests()
}
}
- if (qinfo->_minLevel == -1 || qinfo->_minLevel > DEFAULT_MAX_LEVEL)
+ if (qinfo->_contentTuningID && !sContentTuningStore.LookupEntry(qinfo->_contentTuningID))
{
- TC_LOG_ERROR("sql.sql", "Quest %u should be disabled because `MinLevel` = %i", qinfo->GetQuestId(), int32(qinfo->_minLevel));
- // no changes needed, sending -1 in SMSG_QUEST_QUERY_RESPONSE is valid
+ TC_LOG_ERROR("sql.sql", "Quest %u has `ContentTuningID` = %u but content tuning with this id does not exist.",
+ qinfo->GetQuestId(), qinfo->_contentTuningID);
}
// client quest log visual (area case)
@@ -4603,27 +4609,43 @@ void ObjectMgr::LoadQuests()
for (uint8 j = 0; j < QUEST_REWARD_CHOICES_COUNT; ++j)
{
- uint32 id = qinfo->RewardChoiceItemId[j];
- if (id)
+ if (uint32 id = qinfo->RewardChoiceItemId[j])
{
- if (!sObjectMgr->GetItemTemplate(id))
+ switch (qinfo->RewardChoiceItemType[j])
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `RewardChoiceItemId%d` = %u but item with entry %u does not exist, quest will not reward this item.",
- qinfo->GetQuestId(), j+1, id, id);
- qinfo->RewardChoiceItemId[j] = 0; // no changes, quest will not reward this
+ case LootItemType::Item:
+ if (!sObjectMgr->GetItemTemplate(id))
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardChoiceItemId%d` = %u but item with entry %u does not exist, quest will not reward this item.",
+ qinfo->GetQuestId(), j + 1, id, id);
+ qinfo->RewardChoiceItemId[j] = 0; // no changes, quest will not reward this
+ }
+ break;
+ case LootItemType::Currency:
+ if (!sCurrencyTypesStore.HasRecord(id))
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardChoiceItemId%d` = %u but currency with id %u does not exist, quest will not reward this currency.",
+ qinfo->GetQuestId(), j + 1, id, id);
+ qinfo->RewardChoiceItemId[j] = 0; // no changes, quest will not reward this
+ }
+ break;
+ default:
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardChoiceItemType%d` = %u but it is not a valid item type, reward removed.",
+ qinfo->GetQuestId(), j + 1, uint32(qinfo->RewardChoiceItemType[j]));
+ qinfo->RewardChoiceItemId[j] = 0;
+ break;
}
if (!qinfo->RewardChoiceItemCount[j])
{
- TC_LOG_ERROR("sql.sql", "Quest %u has `RewardChoiceItemId%d` = %u but `RewardChoiceItemCount%d` = 0, quest can't be done.",
- qinfo->GetQuestId(), j+1, id, j+1);
- // no changes, quest can't be done
+ TC_LOG_ERROR("sql.sql", "Quest %u has `RewardChoiceItemId%d` = %u but `RewardChoiceItemCount%d` = 0.",
+ qinfo->GetQuestId(), j + 1, id, j + 1);
}
}
- else if (qinfo->RewardChoiceItemCount[j]>0)
+ else if (qinfo->RewardChoiceItemCount[j] > 0)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardChoiceItemId%d` = 0 but `RewardChoiceItemCount%d` = %u.",
- qinfo->GetQuestId(), j+1, j+1, qinfo->RewardChoiceItemCount[j]);
+ qinfo->GetQuestId(), j + 1, j + 1, qinfo->RewardChoiceItemCount[j]);
// no changes, quest ignore this data
}
}
@@ -4678,28 +4700,6 @@ void ObjectMgr::LoadQuests()
}
}
- for (uint32 i = 0; i < QUEST_REWARD_DISPLAY_SPELL_COUNT; ++i)
- {
- if (qinfo->RewardDisplaySpell[i])
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardDisplaySpell[i], DIFFICULTY_NONE);
-
- if (!spellInfo)
- {
- TC_LOG_ERROR("sql.sql", "Quest %u has `RewardDisplaySpell%u` = %u but spell %u does not exist, spell removed as display reward.",
- qinfo->GetQuestId(), i, qinfo->RewardDisplaySpell[i], qinfo->RewardDisplaySpell[i]);
- qinfo->RewardDisplaySpell[i] = 0; // no spell reward will display for this quest
- }
-
- else if (!SpellMgr::IsSpellValid(spellInfo))
- {
- TC_LOG_ERROR("sql.sql", "Quest %u has `RewardDisplaySpell%u` = %u but spell %u is broken, quest will not have a spell reward.",
- qinfo->GetQuestId(), i, qinfo->RewardDisplaySpell[i], qinfo->RewardDisplaySpell[i]);
- qinfo->RewardDisplaySpell[i] = 0; // no spell reward will display for this quest
- }
- }
- }
-
if (qinfo->_rewardSpell > 0)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->_rewardSpell, DIFFICULTY_NONE);
@@ -7892,41 +7892,33 @@ void ObjectMgr::LoadQuestPOI()
uint32 count = 0;
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
- QueryResult result = WorldDatabase.Query("SELECT QuestID, BlobIndex, Idx1, ObjectiveIndex, QuestObjectiveID, QuestObjectID, MapID, UiMapID, Priority, Flags, WorldEffectID, PlayerConditionID, SpawnTrackingID, AlwaysAllowMergingBlobs FROM quest_poi order by QuestID, Idx1");
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+ QueryResult result = WorldDatabase.Query("SELECT QuestID, BlobIndex, Idx1, ObjectiveIndex, QuestObjectiveID, QuestObjectID, MapID, UiMapID, Priority, Flags, WorldEffectID, PlayerConditionID, NavigationPlayerConditionID, SpawnTrackingID, AlwaysAllowMergingBlobs FROM quest_poi order by QuestID, Idx1");
if (!result)
{
TC_LOG_ERROR("server.loading", ">> Loaded 0 quest POI definitions. DB table `quest_poi` is empty.");
return;
}
- // 0 1 2 3
- QueryResult points = WorldDatabase.Query("SELECT QuestID, Idx1, X, Y FROM quest_poi_points ORDER BY QuestID DESC, Idx1, Idx2");
+ // 0 1 2 3 4
+ QueryResult pointsResult = WorldDatabase.Query("SELECT QuestID, Idx1, X, Y, Z FROM quest_poi_points ORDER BY QuestID DESC, Idx1, Idx2");
- std::vector<std::vector<std::vector<QuestPOIBlobPoint>>> POIs;
+ std::unordered_map<int32, std::map<int32, std::vector<QuestPOIBlobPoint>>> allPoints;
- if (points)
+ if (pointsResult)
{
- // The first result should have the highest questId
- Field* fields = points->Fetch();
- uint32 questIdMax = fields[0].GetInt32();
- POIs.resize(questIdMax + 1);
-
do
{
- fields = points->Fetch();
+ Field* fields = pointsResult->Fetch();
int32 QuestID = fields[0].GetInt32();
int32 Idx1 = fields[1].GetInt32();
- int32 X = fields[2].GetInt32();
- int32 Y = fields[3].GetInt32();
-
- if (int32(POIs[QuestID].size()) <= Idx1 + 1)
- POIs[QuestID].resize(Idx1 + 10);
+ int32 x = fields[2].GetInt32();
+ int32 y = fields[3].GetInt32();
+ int32 z = fields[4].GetInt32();
- QuestPOIBlobPoint point(X, Y);
- POIs[QuestID][Idx1].push_back(point);
- } while (points->NextRow());
+ allPoints[QuestID][Idx1].emplace_back(x, y, z);
+ } while (pointsResult->NextRow());
}
do
@@ -7945,23 +7937,28 @@ void ObjectMgr::LoadQuestPOI()
int32 flags = fields[9].GetInt32();
int32 worldEffectID = fields[10].GetInt32();
int32 playerConditionID = fields[11].GetInt32();
- int32 spawnTrackingID = fields[12].GetInt32();
- bool alwaysAllowMergingBlobs = fields[13].GetBool();
+ int32 navigationPlayerConditionID = fields[12].GetInt32();
+ int32 spawnTrackingID = fields[13].GetInt32();
+ bool alwaysAllowMergingBlobs = fields[14].GetBool();
if (!sObjectMgr->GetQuestTemplate(questID))
TC_LOG_ERROR("sql.sql", "`quest_poi` quest id (%u) Idx1 (%u) does not exist in `quest_template`", questID, idx1);
- if (questID < int32(POIs.size()) && idx1 < int32(POIs[questID].size()))
+ if (std::map<int32, std::vector<QuestPOIBlobPoint>>* blobs = Trinity::Containers::MapGetValuePtr(allPoints, questID))
{
- QuestPOIData& poiData = _questPOIStore[questID];
- poiData.QuestID = questID;
- poiData.Blobs.emplace_back(blobIndex, objectiveIndex, questObjectiveID, questObjectID, mapID, uiMapID, priority, flags,
- worldEffectID, playerConditionID, spawnTrackingID, std::move(POIs[questID][idx1]), alwaysAllowMergingBlobs);
+ if (std::vector<QuestPOIBlobPoint>* points = Trinity::Containers::MapGetValuePtr(*blobs, idx1))
+ {
+ QuestPOIData& poiData = _questPOIStore[questID];
+ poiData.QuestID = questID;
+ poiData.Blobs.emplace_back(blobIndex, objectiveIndex, questObjectiveID, questObjectID, mapID, uiMapID, priority, flags,
+ worldEffectID, playerConditionID, navigationPlayerConditionID, spawnTrackingID, std::move(*points), alwaysAllowMergingBlobs);
+ ++count;
+ continue;
+ }
}
- else
- TC_LOG_ERROR("sql.sql", "Table quest_poi references unknown quest points for quest %i POI id %i", questID, blobIndex);
- ++count;
+ TC_LOG_ERROR("sql.sql", "Table quest_poi references unknown quest points for quest %i POI id %i", questID, blobIndex);
+
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u quest POI definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
@@ -10384,6 +10381,8 @@ void ObjectMgr::LoadPlayerChoices()
uint32 itemRewardCount = 0;
uint32 currencyRewardCount = 0;
uint32 factionRewardCount = 0;
+ uint32 itemChoiceRewardCount = 0;
+ uint32 mawPowersCount = 0;
do
{
@@ -10401,7 +10400,11 @@ void ObjectMgr::LoadPlayerChoices()
} while (choices->NextRow());
- if (QueryResult responses = WorldDatabase.Query("SELECT ChoiceId, ResponseId, ChoiceArtFileId, Flags, WidgetSetID, UiTextureAtlasElementID, SoundKitID, GroupID, Answer, Header, SubHeader, ButtonTemplate, Description, Confirmation, RewardQuestID FROM playerchoice_response ORDER BY `Index` ASC"))
+ // 0 1 2 3 4 5
+ if (QueryResult responses = WorldDatabase.Query("SELECT ChoiceId, ResponseId, ResponseIdentifier, ChoiceArtFileId, Flags, WidgetSetID, "
+ // 6 7 8 9 10 11 12 13 14 15 16
+ "UiTextureAtlasElementID, SoundKitID, GroupID, UiTextureKitID, Answer, Header, SubHeader, ButtonTemplate, Description, Confirmation, RewardQuestID "
+ "FROM playerchoice_response ORDER BY `Index` ASC"))
{
do
{
@@ -10421,20 +10424,22 @@ void ObjectMgr::LoadPlayerChoices()
PlayerChoiceResponse& response = choice->Responses.back();
response.ResponseId = responseId;
- response.ChoiceArtFileId = fields[2].GetInt32();
- response.Flags = fields[3].GetInt32();
- response.WidgetSetID = fields[4].GetUInt32();
- response.UiTextureAtlasElementID = fields[5].GetUInt32();
- response.SoundKitID = fields[6].GetUInt32();
- response.GroupID = fields[7].GetUInt8();
- response.Answer = fields[8].GetString();
- response.Header = fields[9].GetString();
- response.SubHeader = fields[10].GetString();
- response.ButtonTooltip = fields[11].GetString();
- response.Description = fields[12].GetString();
- response.Confirmation = fields[13].GetString();
- if (!fields[14].IsNull())
- response.RewardQuestID = fields[14].GetUInt32();
+ response.ResponseId = fields[2].GetUInt16();
+ response.ChoiceArtFileId = fields[3].GetInt32();
+ response.Flags = fields[4].GetInt32();
+ response.WidgetSetID = fields[5].GetUInt32();
+ response.UiTextureAtlasElementID = fields[6].GetUInt32();
+ response.SoundKitID = fields[7].GetUInt32();
+ response.GroupID = fields[8].GetUInt8();
+ response.UiTextureKitID = fields[9].GetInt32();
+ response.Answer = fields[10].GetString();
+ response.Header = fields[11].GetString();
+ response.SubHeader = fields[12].GetString();
+ response.ButtonTooltip = fields[13].GetString();
+ response.Description = fields[14].GetString();
+ response.Confirmation = fields[15].GetString();
+ if (!fields[16].IsNull())
+ response.RewardQuestID = fields[16].GetUInt32();
++responseCount;
@@ -10548,6 +10553,7 @@ void ObjectMgr::LoadPlayerChoices()
}
responseItr->Reward->Items.emplace_back(itemId, std::move(bonusListIds), quantity);
+ ++itemRewardCount;
} while (rewards->NextRow());
}
@@ -10593,6 +10599,7 @@ void ObjectMgr::LoadPlayerChoices()
}
responseItr->Reward->Currency.emplace_back(currencyId, quantity);
+ ++currencyRewardCount;
} while (rewards->NextRow());
}
@@ -10638,12 +10645,102 @@ void ObjectMgr::LoadPlayerChoices()
}
responseItr->Reward->Faction.emplace_back(factionId, quantity);
+ ++factionRewardCount;
+
+ } while (rewards->NextRow());
+ }
+
+ if (QueryResult rewards = WorldDatabase.Query("SELECT ChoiceId, ResponseId, ItemId, BonusListIDs, Quantity FROM playerchoice_response_reward_item_choice ORDER BY `Index` ASC"))
+ {
+ do
+ {
+ Field* fields = rewards->Fetch();
+
+ int32 choiceId = fields[0].GetInt32();
+ int32 responseId = fields[1].GetInt32();
+ uint32 itemId = fields[2].GetUInt32();
+ Tokenizer bonusListIDsTok(fields[3].GetString(), ' ');
+ std::vector<int32> bonusListIds;
+ for (char const* token : bonusListIDsTok)
+ bonusListIds.push_back(int32(atol(token)));
+ int32 quantity = fields[4].GetInt32();
+
+ PlayerChoice* choice = Trinity::Containers::MapGetValuePtr(_playerChoices, choiceId);
+ if (!choice)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `playerchoice_response_reward_item_choice` references non-existing ChoiceId: %d (ResponseId: %d), skipped", choiceId, responseId);
+ continue;
+ }
+
+ auto responseItr = std::find_if(choice->Responses.begin(), choice->Responses.end(),
+ [responseId](PlayerChoiceResponse const& playerChoiceResponse) { return playerChoiceResponse.ResponseId == responseId; });
+ if (responseItr == choice->Responses.end())
+ {
+ TC_LOG_ERROR("sql.sql", "Table `playerchoice_response_reward_item_choice` references non-existing ResponseId: %d for ChoiceId %d, skipped", responseId, choiceId);
+ continue;
+ }
+
+ if (!responseItr->Reward)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `playerchoice_response_reward_item_choice` references non-existing player choice reward for ChoiceId %d, ResponseId: %d, skipped",
+ choiceId, responseId);
+ continue;
+ }
+
+ if (!GetItemTemplate(itemId))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `playerchoice_response_reward_item_choice` references non-existing item %u for ChoiceId %d, ResponseId: %d, skipped",
+ itemId, choiceId, responseId);
+ continue;
+ }
+
+ responseItr->Reward->ItemChoices.emplace_back(itemId, std::move(bonusListIds), quantity);
+ ++itemChoiceRewardCount;
} while (rewards->NextRow());
}
- TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " player choices, %u responses, %u rewards, %u item rewards, %u currency rewards and %u faction rewards in %u ms.",
- _playerChoices.size(), responseCount, rewardCount, itemRewardCount, currencyRewardCount, factionRewardCount, GetMSTimeDiffToNow(oldMSTime));
+ if (QueryResult mawPowersResult = WorldDatabase.Query("SELECT ChoiceId, ResponseId, TypeArtFileID, Rarity, RarityColor, SpellID, MaxStacks FROM playerchoice_response_maw_power"))
+ {
+ do
+ {
+ Field* fields = mawPowersResult->Fetch();
+ int32 choiceId = fields[0].GetInt32();
+ int32 responseId = fields[1].GetInt32();
+
+ PlayerChoice* choice = Trinity::Containers::MapGetValuePtr(_playerChoices, choiceId);
+ if (!choice)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `playerchoice_response_maw_power` references non-existing ChoiceId: %d (ResponseId: %d), skipped", choiceId, responseId);
+ continue;
+ }
+
+ auto responseItr = std::find_if(choice->Responses.begin(), choice->Responses.end(),
+ [responseId](PlayerChoiceResponse const& playerChoiceResponse)
+ {
+ return playerChoiceResponse.ResponseId == responseId;
+ });
+ if (responseItr == choice->Responses.end())
+ {
+ TC_LOG_ERROR("sql.sql", "Table `playerchoice_response_maw_power` references non-existing ResponseId: %d for ChoiceId %d, skipped", responseId, choiceId);
+ continue;
+ }
+
+ responseItr->MawPower.emplace();
+ PlayerChoiceResponseMawPower& mawPower = responseItr->MawPower.get();
+ mawPower.TypeArtFileID = fields[2].GetInt32();
+ mawPower.Rarity = fields[3].GetInt32();
+ mawPower.RarityColor = fields[4].GetUInt32();
+ mawPower.SpellID = fields[5].GetInt32();
+ mawPower.MaxStacks = fields[6].GetInt32();
+
+ ++mawPowersCount;
+
+ } while (mawPowersResult->NextRow());
+ }
+
+ TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " player choices, %u responses, %u rewards, %u item rewards, %u currency rewards, %u faction rewards, %u item choice rewards and %u maw powers in %u ms.",
+ _playerChoices.size(), responseCount, rewardCount, itemRewardCount, currencyRewardCount, factionRewardCount, itemChoiceRewardCount, mawPowersCount, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadPlayerChoicesLocale()
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 0a113095374..45756e922dd 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -722,7 +722,7 @@ struct QuestPOIBlobPoint
int32 Z;
QuestPOIBlobPoint() : X(0), Y(0), Z(0) { }
- QuestPOIBlobPoint(int32 x, int32 y) : X(x), Y(y), Z(0) { }
+ QuestPOIBlobPoint(int32 x, int32 y, int32 z) : X(x), Y(y), Z(z) { }
};
struct QuestPOIBlobData
@@ -745,10 +745,10 @@ struct QuestPOIBlobData
QuestPOIBlobData() : BlobIndex(0), ObjectiveIndex(0), QuestObjectiveID(0), QuestObjectID(0), MapID(0), UiMapID(0), Priority(0), Flags(0), WorldEffectID(0),
PlayerConditionID(0), NavigationPlayerConditionID(0), SpawnTrackingID(0), AlwaysAllowMergingBlobs(false) { }
QuestPOIBlobData(int32 blobIndex, int32 objectiveIndex, int32 questObjectiveID, int32 questObjectID, int32 mapID, int32 uiMapID, int32 priority,
- int32 flags, int32 worldEffectID, int32 playerConditionID, int32 spawnTrackingID, std::vector<QuestPOIBlobPoint> points,
+ int32 flags, int32 worldEffectID, int32 playerConditionID, int32 navigationPlayerConditionID, int32 spawnTrackingID, std::vector<QuestPOIBlobPoint> points,
bool alwaysAllowMergingBlobs) : BlobIndex(blobIndex), ObjectiveIndex(objectiveIndex), QuestObjectiveID(questObjectiveID),
QuestObjectID(questObjectID), MapID(mapID), UiMapID(uiMapID), Priority(priority), Flags(flags), WorldEffectID(worldEffectID),
- PlayerConditionID(playerConditionID), NavigationPlayerConditionID(0), SpawnTrackingID(spawnTrackingID), Points(std::move(points)),
+ PlayerConditionID(playerConditionID), NavigationPlayerConditionID(navigationPlayerConditionID), SpawnTrackingID(spawnTrackingID), Points(std::move(points)),
AlwaysAllowMergingBlobs(alwaysAllowMergingBlobs) { }
};
@@ -828,17 +828,29 @@ struct PlayerChoiceResponseReward
std::vector<PlayerChoiceResponseRewardItem> Items;
std::vector<PlayerChoiceResponseRewardEntry> Currency;
std::vector<PlayerChoiceResponseRewardEntry> Faction;
+ std::vector<PlayerChoiceResponseRewardItem> ItemChoices;
+};
+
+struct PlayerChoiceResponseMawPower
+{
+ int32 TypeArtFileID = 0;
+ int32 Rarity = 0;
+ uint32 RarityColor = 0;
+ int32 SpellID = 0;
+ int32 MaxStacks = 0;
};
struct PlayerChoiceResponse
{
- int32 ResponseId;
- int32 ChoiceArtFileId;
- int32 Flags;
- uint32 WidgetSetID;
+ int32 ResponseId = 0;
+ uint16 ResponseIdentifier = 0;
+ int32 ChoiceArtFileId = 0;
+ int32 Flags = 0;
+ uint32 WidgetSetID = 0;
uint32 UiTextureAtlasElementID = 0;
uint32 SoundKitID = 0;
- uint8 GroupID;
+ uint8 GroupID = 0;
+ int32 UiTextureKitID = 0;
std::string Answer;
std::string Header;
std::string SubHeader;
@@ -847,6 +859,7 @@ struct PlayerChoiceResponse
std::string Confirmation;
Optional<PlayerChoiceResponseReward> Reward;
Optional<uint32> RewardQuestID;
+ Optional<PlayerChoiceResponseMawPower> MawPower;
};
struct PlayerChoice
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index b23c1ae1ff1..55285fe0394 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -16,6 +16,7 @@
*/
#include "QuestDef.h"
+#include "ConditionMgr.h"
#include "DB2Stores.h"
#include "Field.h"
#include "GameTables.h"
@@ -23,47 +24,42 @@
#include "ObjectMgr.h"
#include "Player.h"
#include "QuestPackets.h"
+#include "SpellMgr.h"
#include "World.h"
Quest::Quest(Field* questRecord)
{
_id = questRecord[0].GetUInt32();
_type = questRecord[1].GetUInt8();
- _level = questRecord[2].GetInt32();
- _scalingFactionGroup = questRecord[3].GetInt32();
- _maxScalingLevel = questRecord[4].GetInt32();
- _packageID = questRecord[5].GetUInt32();
- _minLevel = questRecord[6].GetInt32();
- _questSortID = questRecord[7].GetInt16();
- _questInfoID = questRecord[8].GetUInt16();
- _suggestedPlayers = questRecord[9].GetUInt8();
- _nextQuestInChain = questRecord[10].GetUInt32();
- _rewardXPDifficulty = questRecord[11].GetUInt32();
- _rewardXPMultiplier = questRecord[12].GetFloat();
- _rewardMoney = questRecord[13].GetUInt32();
- _rewardMoneyDifficulty = questRecord[14].GetUInt32();
- _rewardMoneyMultiplier = questRecord[15].GetFloat();
- _rewardBonusMoney = questRecord[16].GetUInt32();
- for (uint32 i = 0; i < QUEST_REWARD_DISPLAY_SPELL_COUNT; ++i)
- RewardDisplaySpell[i] = questRecord[17 + i].GetUInt32();
-
- _rewardSpell = questRecord[20].GetUInt32();
- _rewardHonor = questRecord[21].GetUInt32();
- _rewardKillHonor = questRecord[22].GetUInt32();
- _sourceItemId = questRecord[23].GetUInt32();
- _rewardArtifactXPDifficulty = questRecord[24].GetUInt32();
- _rewardArtifactXPMultiplier = questRecord[25].GetFloat();
- _rewardArtifactCategoryID = questRecord[26].GetUInt32();
- _flags = questRecord[27].GetUInt32();
- _flagsEx = questRecord[28].GetUInt32();
- _flagsEx2 = questRecord[29].GetUInt32();
+ _packageID = questRecord[2].GetUInt32();
+ _contentTuningID = questRecord[3].GetInt32();
+ _questSortID = questRecord[4].GetInt16();
+ _questInfoID = questRecord[5].GetUInt16();
+ _suggestedPlayers = questRecord[6].GetUInt8();
+ _nextQuestInChain = questRecord[7].GetUInt32();
+ _rewardXPDifficulty = questRecord[8].GetUInt32();
+ _rewardXPMultiplier = questRecord[9].GetFloat();
+ _rewardMoney = questRecord[10].GetUInt32();
+ _rewardMoneyDifficulty = questRecord[11].GetUInt32();
+ _rewardMoneyMultiplier = questRecord[12].GetFloat();
+ _rewardBonusMoney = questRecord[13].GetUInt32();
+ _rewardSpell = questRecord[14].GetUInt32();
+ _rewardHonor = questRecord[15].GetUInt32();
+ _rewardKillHonor = questRecord[16].GetUInt32();
+ _sourceItemId = questRecord[17].GetUInt32();
+ _rewardArtifactXPDifficulty = questRecord[18].GetUInt32();
+ _rewardArtifactXPMultiplier = questRecord[19].GetFloat();
+ _rewardArtifactCategoryID = questRecord[20].GetUInt32();
+ _flags = questRecord[21].GetUInt32();
+ _flagsEx = questRecord[22].GetUInt32();
+ _flagsEx2 = questRecord[23].GetUInt32();
for (uint32 i = 0; i < QUEST_ITEM_DROP_COUNT; ++i)
{
- RewardItemId[i] = questRecord[30 + i * 4].GetUInt32();
- RewardItemCount[i] = questRecord[31 + i * 4].GetUInt32();
- ItemDrop[i] = questRecord[32 + i * 4].GetUInt32();
- ItemDropQuantity[i] = questRecord[33 + i * 4].GetUInt32();
+ RewardItemId[i] = questRecord[24 + i * 4].GetUInt32();
+ RewardItemCount[i] = questRecord[25 + i * 4].GetUInt32();
+ ItemDrop[i] = questRecord[26 + i * 4].GetUInt32();
+ ItemDropQuantity[i] = questRecord[27 + i * 4].GetUInt32();
if (RewardItemId[i])
++_rewItemsCount;
@@ -71,66 +67,92 @@ Quest::Quest(Field* questRecord)
for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
{
- RewardChoiceItemId[i] = questRecord[46 + i * 3].GetUInt32();
- RewardChoiceItemCount[i] = questRecord[47 + i * 3].GetUInt32();
- RewardChoiceItemDisplayId[i] = questRecord[48 + i * 3].GetUInt32();
+ RewardChoiceItemId[i] = questRecord[40 + i * 3].GetUInt32();
+ RewardChoiceItemCount[i] = questRecord[41 + i * 3].GetUInt32();
+ RewardChoiceItemDisplayId[i] = questRecord[42 + i * 3].GetUInt32();
if (RewardChoiceItemId[i])
++_rewChoiceItemsCount;
}
- _poiContinent = questRecord[64].GetUInt32();
- _poix = questRecord[65].GetFloat();
- _poiy = questRecord[66].GetFloat();
- _poiPriority = questRecord[67].GetUInt32();
+ _poiContinent = questRecord[58].GetUInt32();
+ _poix = questRecord[59].GetFloat();
+ _poiy = questRecord[60].GetFloat();
+ _poiPriority = questRecord[61].GetUInt32();
- _rewardTitleId = questRecord[68].GetUInt32();
- _rewardArenaPoints = questRecord[69].GetUInt32();
- _rewardSkillId = questRecord[70].GetUInt32();
- _rewardSkillPoints = questRecord[71].GetUInt32();
+ _rewardTitleId = questRecord[62].GetUInt32();
+ _rewardArenaPoints = questRecord[63].GetUInt32();
+ _rewardSkillId = questRecord[64].GetUInt32();
+ _rewardSkillPoints = questRecord[65].GetUInt32();
- _questGiverPortrait = questRecord[72].GetUInt32();
- _questGiverPortraitMount = questRecord[73].GetUInt32();
- _questTurnInPortrait = questRecord[74].GetUInt32();
+ _questGiverPortrait = questRecord[66].GetUInt32();
+ _questGiverPortraitMount = questRecord[67].GetUInt32();
+ _questTurnInPortrait = questRecord[68].GetUInt32();
for (uint32 i = 0; i < QUEST_REWARD_REPUTATIONS_COUNT; ++i)
{
- RewardFactionId[i] = questRecord[75 + i * 4].GetUInt32();
- RewardFactionValue[i] = questRecord[76 + i * 4].GetInt32();
- RewardFactionOverride[i] = questRecord[77 + i * 4].GetInt32();
- RewardFactionCapIn[i] = questRecord[78 + i * 4].GetUInt32();
+ RewardFactionId[i] = questRecord[69 + i * 4].GetUInt32();
+ RewardFactionValue[i] = questRecord[70 + i * 4].GetInt32();
+ RewardFactionOverride[i] = questRecord[71 + i * 4].GetInt32();
+ RewardFactionCapIn[i] = questRecord[72 + i * 4].GetUInt32();
}
- _rewardReputationMask = questRecord[95].GetUInt32();
+ _rewardReputationMask = questRecord[89].GetUInt32();
for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
{
- RewardCurrencyId[i] = questRecord[96 + i * 2].GetUInt32();
- RewardCurrencyCount[i] = questRecord[97 + i * 2].GetUInt32();
+ RewardCurrencyId[i] = questRecord[90 + i * 2].GetUInt32();
+ RewardCurrencyCount[i] = questRecord[91 + i * 2].GetUInt32();
if (RewardCurrencyId[i])
++_rewCurrencyCount;
}
- _soundAccept = questRecord[104].GetUInt32();
- _soundTurnIn = questRecord[105].GetUInt32();
- _areaGroupID = questRecord[106].GetUInt32();
- _limitTime = questRecord[107].GetUInt32();
- _allowableRaces.RawValue = questRecord[108].GetUInt64();
- _treasurePickerID = questRecord[109].GetInt32();
- _expansion = questRecord[110].GetInt32();
- _managedWorldStateID = questRecord[111].GetInt32();
- _questSessionBonus = questRecord[112].GetInt32();
-
- _logTitle = questRecord[113].GetString();
- _logDescription = questRecord[114].GetString();
- _questDescription = questRecord[115].GetString();
- _areaDescription = questRecord[116].GetString();
- _portraitGiverText = questRecord[117].GetString();
- _portraitGiverName = questRecord[118].GetString();
- _portraitTurnInText = questRecord[119].GetString();
- _portraitTurnInName = questRecord[120].GetString();
- _questCompletionLog = questRecord[121].GetString();
+ _soundAccept = questRecord[98].GetUInt32();
+ _soundTurnIn = questRecord[99].GetUInt32();
+ _areaGroupID = questRecord[100].GetUInt32();
+ _limitTime = questRecord[101].GetUInt32();
+ _allowableRaces.RawValue = questRecord[102].GetUInt64();
+ _treasurePickerID = questRecord[103].GetInt32();
+ _expansion = questRecord[104].GetInt32();
+ _managedWorldStateID = questRecord[105].GetInt32();
+ _questSessionBonus = questRecord[106].GetInt32();
+
+ _logTitle = questRecord[107].GetString();
+ _logDescription = questRecord[108].GetString();
+ _questDescription = questRecord[109].GetString();
+ _areaDescription = questRecord[111].GetString();
+ _portraitGiverText = questRecord[111].GetString();
+ _portraitGiverName = questRecord[112].GetString();
+ _portraitTurnInText = questRecord[113].GetString();
+ _portraitTurnInName = questRecord[114].GetString();
+ _questCompletionLog = questRecord[115].GetString();
+}
+
+void Quest::LoadRewardDisplaySpell(Field* fields)
+{
+ uint32 spellId = fields[1].GetUInt32();
+ uint32 playerConditionId = fields[2].GetUInt32();
+
+ if (!sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `quest_reward_display_spell` has non-existing Spell (%u) set for quest %u. Skipped.", spellId, fields[0].GetUInt32());
+ return;
+ }
+
+ if (playerConditionId && !sPlayerConditionStore.LookupEntry(playerConditionId))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `quest_reward_display_spell` has non-existing PlayerCondition (%u) set for quest %u. Set to 0.", spellId, fields[0].GetUInt32());
+ playerConditionId = 0;
+ }
+
+ RewardDisplaySpell.emplace_back(spellId, playerConditionId);
+}
+
+void Quest::LoadRewardChoiceItems(Field* fields)
+{
+ for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
+ RewardChoiceItemType[i] = LootItemType(fields[1 + i].GetUInt8());
}
void Quest::LoadQuestDetails(Field* fields)
@@ -262,7 +284,7 @@ uint32 Quest::XPValue(Player const* player) const
if (questLevel != player->getLevel())
multiplier = sXpGameTable.GetRow(std::min<int32>(player->getLevel(), questLevel))->Divisor / sXpGameTable.GetRow(player->getLevel())->Divisor;
- int32 diffFactor = 2 * (questLevel + (_level == -1 ? 0 : 5) - player->getLevel()) + 10;
+ int32 diffFactor = 2 * (questLevel + (GetQuestLevel() == -1 ? 0 : 5) - player->getLevel()) + 10;
if (diffFactor < 1)
diffFactor = 1;
else if (diffFactor > 10)
@@ -301,8 +323,17 @@ void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player
rewards.ArtifactCategoryID = GetArtifactCategoryId();
rewards.Title = GetRewTitle();
rewards.FactionFlags = GetRewardReputationMask();
- for (uint32 i = 0; i < QUEST_REWARD_DISPLAY_SPELL_COUNT; ++i)
- rewards.SpellCompletionDisplayID[i] = RewardDisplaySpell[i];
+ auto displaySpellItr = rewards.SpellCompletionDisplayID.begin();
+ for (QuestRewardDisplaySpell displaySpell : RewardDisplaySpell)
+ {
+ if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(displaySpell.PlayerConditionId))
+ if (!ConditionMgr::IsPlayerMeetingCondition(player, playerCondition))
+ continue;
+
+ *displaySpellItr = displaySpell.SpellId;
+ if (++displaySpellItr == rewards.SpellCompletionDisplayID.end())
+ break;
+ }
rewards.SpellCompletionID = GetRewSpell();
rewards.SkillLineID = GetRewardSkillId();
@@ -311,6 +342,7 @@ void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player
for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
{
+ rewards.ChoiceItems[i].LootItemType = RewardChoiceItemType[i];
rewards.ChoiceItems[i].Item.ItemID = RewardChoiceItemId[i];
rewards.ChoiceItems[i].Quantity = RewardChoiceItemCount[i];
}
@@ -452,16 +484,10 @@ WorldPacket Quest::BuildQueryData(LocaleConstant loc) const
}
}
- if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS))
- AddQuestLevelToTitle(response.Info.LogTitle, GetQuestLevel());
-
response.Info.QuestID = GetQuestId();
response.Info.QuestType = GetQuestType();
- response.Info.QuestLevel = GetQuestLevel();
- response.Info.QuestScalingFactionGroup = GetQuestScalingFactionGroup();
- response.Info.QuestMaxScalingLevel = GetQuestMaxScalingLevel();
+ response.Info.ContentTuningID = GetContentTuningId();
response.Info.QuestPackageID = GetQuestPackageID();
- response.Info.QuestMinLevel = GetMinLevel();
response.Info.QuestSortID = GetZoneOrSort();
response.Info.QuestInfoID = GetQuestInfoID();
response.Info.SuggestedGroupNum = GetSuggestedPlayers();
@@ -475,8 +501,8 @@ WorldPacket Quest::BuildQueryData(LocaleConstant loc) const
response.Info.RewardMoneyDifficulty = GetRewMoneyDifficulty();
response.Info.RewardMoneyMultiplier = GetMoneyMultiplier();
response.Info.RewardBonusMoney = GetRewMoneyMaxLevel();
- for (uint8 i = 0; i < QUEST_REWARD_DISPLAY_SPELL_COUNT; ++i)
- response.Info.RewardDisplaySpell[i] = RewardDisplaySpell[i];
+ for (QuestRewardDisplaySpell displaySpell : RewardDisplaySpell)
+ response.Info.RewardDisplaySpell.push_back({ int32(displaySpell.SpellId), int32(displaySpell.PlayerConditionId) });
response.Info.RewardSpell = GetRewSpell();
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 43bd9e33e9a..b61a8edbe22 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -27,6 +27,7 @@
#include <vector>
class Player;
+enum class LootItemType : uint8;
namespace WorldPackets
{
@@ -337,6 +338,15 @@ struct QuestObjective
typedef std::vector<QuestObjective> QuestObjectives;
+struct QuestRewardDisplaySpell
+{
+ QuestRewardDisplaySpell() : SpellId(0), PlayerConditionId(0) { }
+ QuestRewardDisplaySpell(uint32 spellId, uint32 playerConditionId) : SpellId(spellId), PlayerConditionId(playerConditionId) { }
+
+ uint32 SpellId;
+ uint32 PlayerConditionId;
+};
+
// This Quest class provides a convenient way to access a few pretotaled (cached) quest details,
// all base quest information, and any utility functions such as generating the amount of
// xp to give
@@ -347,7 +357,9 @@ class TC_GAME_API Quest
friend class PlayerMenu;
public:
// Loading data. All queries are in ObjectMgr::LoadQuests()
- Quest(Field* questRecord);
+ explicit Quest(Field* questRecord);
+ void LoadRewardDisplaySpell(Field* fields);
+ void LoadRewardChoiceItems(Field* fields);
void LoadQuestDetails(Field* fields);
void LoadQuestRequestItems(Field* fields);
void LoadQuestOfferReward(Field* fields);
@@ -366,17 +378,19 @@ class TC_GAME_API Quest
bool HasSpecialFlag(uint32 flag) const { return (_specialFlags & flag) != 0; }
void SetSpecialFlag(uint32 flag) { _specialFlags |= flag; }
+ // DEPRECATED
+ int32 GetMinLevel() const { return 0; }
+ int32 GetQuestLevel() const { return 0; }
+ int32 GetQuestScalingFactionGroup() const { return 0; }
+ int32 GetQuestMaxScalingLevel() const { return 0; }
+
// table data accessors:
uint32 GetQuestId() const { return _id; }
uint32 GetQuestType() const { return _type; }
uint32 GetQuestPackageID() const { return _packageID; }
+ uint32 GetContentTuningId() const { return _contentTuningID; }
int32 GetZoneOrSort() const { return _questSortID; }
- int32 GetMinLevel() const { return _minLevel; }
uint32 GetMaxLevel() const { return _maxLevel; }
- int32 GetQuestLevel() const { return _level; }
- int32 GetQuestScalingFactionGroup() const { return _scalingFactionGroup; }
- int32 GetQuestMaxScalingLevel() const { return _maxScalingLevel; }
- int32 GetContentTuningId() const { return 0; }
uint32 GetQuestInfoID() const { return _questInfoID; }
uint32 GetAllowableClasses() const { return _allowableClasses; }
Trinity::RaceMask<uint64> GetAllowableRaces() const { return _allowableRaces; }
@@ -465,25 +479,26 @@ class TC_GAME_API Quest
bool CanIncreaseRewardedQuestCounters() const;
// multiple values
- uint32 RewardDisplaySpell[QUEST_REWARD_DISPLAY_SPELL_COUNT] = { };
- uint32 RewardItemId[QUEST_REWARD_ITEM_COUNT] = { };
- uint32 RewardItemCount[QUEST_REWARD_ITEM_COUNT] = { };
- uint32 ItemDrop[QUEST_ITEM_DROP_COUNT] = { };
- uint32 ItemDropQuantity[QUEST_ITEM_DROP_COUNT] = { };
- uint32 RewardChoiceItemId[QUEST_REWARD_CHOICES_COUNT] = { };
- uint32 RewardChoiceItemCount[QUEST_REWARD_CHOICES_COUNT] = { };
- uint32 RewardChoiceItemDisplayId[QUEST_REWARD_CHOICES_COUNT] = { };
- uint32 RewardFactionId[QUEST_REWARD_REPUTATIONS_COUNT] = { };
- int32 RewardFactionValue[QUEST_REWARD_REPUTATIONS_COUNT] = { };
- int32 RewardFactionOverride[QUEST_REWARD_REPUTATIONS_COUNT] = { };
- uint32 RewardFactionCapIn[QUEST_REWARD_REPUTATIONS_COUNT] = { };
- uint32 RewardCurrencyId[QUEST_REWARD_CURRENCY_COUNT] = { };
- uint32 RewardCurrencyCount[QUEST_REWARD_CURRENCY_COUNT] = { };
- QuestObjectives Objectives = { };
- uint32 DetailsEmote[QUEST_EMOTE_COUNT] = { };
- uint32 DetailsEmoteDelay[QUEST_EMOTE_COUNT] = { };
- uint32 OfferRewardEmote[QUEST_EMOTE_COUNT] = { };
- uint32 OfferRewardEmoteDelay[QUEST_EMOTE_COUNT] = { };
+ std::vector<QuestRewardDisplaySpell> RewardDisplaySpell;
+ std::array<uint32, QUEST_REWARD_ITEM_COUNT> RewardItemId = { };
+ std::array<uint32, QUEST_REWARD_ITEM_COUNT> RewardItemCount = { };
+ std::array<uint32, QUEST_ITEM_DROP_COUNT> ItemDrop = { };
+ std::array<uint32, QUEST_ITEM_DROP_COUNT> ItemDropQuantity = { };
+ std::array<LootItemType, QUEST_REWARD_CHOICES_COUNT> RewardChoiceItemType = { };
+ std::array<uint32, QUEST_REWARD_CHOICES_COUNT> RewardChoiceItemId = { };
+ std::array<uint32, QUEST_REWARD_CHOICES_COUNT> RewardChoiceItemCount = { };
+ std::array<uint32, QUEST_REWARD_CHOICES_COUNT> RewardChoiceItemDisplayId = { };
+ std::array<uint32, QUEST_REWARD_REPUTATIONS_COUNT> RewardFactionId = { };
+ std::array<int32, QUEST_REWARD_REPUTATIONS_COUNT> RewardFactionValue = { };
+ std::array<int32, QUEST_REWARD_REPUTATIONS_COUNT> RewardFactionOverride = { };
+ std::array<uint32, QUEST_REWARD_REPUTATIONS_COUNT> RewardFactionCapIn = { };
+ std::array<uint32, QUEST_REWARD_CURRENCY_COUNT> RewardCurrencyId = { };
+ std::array<uint32, QUEST_REWARD_CURRENCY_COUNT> RewardCurrencyCount = { };
+ QuestObjectives Objectives;
+ std::array<uint32, QUEST_EMOTE_COUNT> DetailsEmote = { };
+ std::array<uint32, QUEST_EMOTE_COUNT> DetailsEmoteDelay = { };
+ std::array<uint32, QUEST_EMOTE_COUNT> OfferRewardEmote = { };
+ std::array<uint32, QUEST_EMOTE_COUNT> OfferRewardEmoteDelay = { };
uint32 GetRewChoiceItemsCount() const { return _rewChoiceItemsCount; }
uint32 GetRewItemsCount() const { return _rewItemsCount; }
@@ -498,7 +513,7 @@ class TC_GAME_API Quest
void BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player* player) const;
std::vector<uint32> DependentPreviousQuests;
- WorldPacket QueryData[TOTAL_LOCALES];
+ std::array<WorldPacket, TOTAL_LOCALES> QueryData;
private:
uint32 _rewChoiceItemsCount = 0;
@@ -509,11 +524,8 @@ class TC_GAME_API Quest
// wdb data (quest query response)
uint32 _id = 0;
uint32 _type = 0;
- int32 _level = 0;
- int32 _scalingFactionGroup = 0;
- int32 _maxScalingLevel = 0;
uint32 _packageID = 0;
- int32 _minLevel = 0;
+ uint32 _contentTuningID = 0;
int32 _questSortID = 0;
uint32 _questInfoID = 0;
uint32 _suggestedPlayers = 0;
@@ -600,7 +612,7 @@ struct QuestStatusData
{
QuestStatus Status = QUEST_STATUS_NONE;
uint32 Timer = 0;
- std::vector<int32> ObjectiveData = { };
+ std::vector<int32> ObjectiveData;
};
#endif
diff --git a/src/server/game/Scenarios/Scenario.cpp b/src/server/game/Scenarios/Scenario.cpp
index 65720d324e9..da6ee2c216f 100644
--- a/src/server/game/Scenarios/Scenario.cpp
+++ b/src/server/game/Scenarios/Scenario.cpp
@@ -18,6 +18,7 @@
#include "Scenario.h"
#include "InstanceSaveMgr.h"
#include "Log.h"
+#include "LootMgr.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Player.h"
@@ -57,7 +58,7 @@ void Scenario::CompleteStep(ScenarioStepEntry const* step)
if (Quest const* quest = sObjectMgr->GetQuestTemplate(step->RewardQuestID))
for (ObjectGuid guid : _players)
if (Player* player = ObjectAccessor::FindPlayer(guid))
- player->RewardQuest(quest, 0, nullptr, false);
+ player->RewardQuest(quest, LootItemType::Item, 0, nullptr, false);
if (step->IsBonusObjective())
return;
diff --git a/src/server/game/Scenarios/ScenarioMgr.cpp b/src/server/game/Scenarios/ScenarioMgr.cpp
index e06315bf973..36152089b2a 100644
--- a/src/server/game/Scenarios/ScenarioMgr.cpp
+++ b/src/server/game/Scenarios/ScenarioMgr.cpp
@@ -16,6 +16,7 @@
*/
#include "ScenarioMgr.h"
+#include "Containers.h"
#include "DatabaseEnv.h"
#include "DB2Stores.h"
#include "InstanceScenario.h"
@@ -147,41 +148,35 @@ void ScenarioMgr::LoadScenarioPOI()
uint32 count = 0;
- // 0 1 2 3 4 5 6 7 8
- QueryResult result = WorldDatabase.Query("SELECT CriteriaTreeID, BlobIndex, Idx1, MapID, UiMapID, Priority, Flags, WorldEffectID, PlayerConditionID FROM scenario_poi ORDER BY CriteriaTreeID, Idx1");
+ // 0 1 2 3 4 5 6 7 8 9
+ QueryResult result = WorldDatabase.Query("SELECT CriteriaTreeID, BlobIndex, Idx1, MapID, UiMapID, Priority, Flags, WorldEffectID, PlayerConditionID, NavigationPlayerConditionID FROM scenario_poi ORDER BY CriteriaTreeID, Idx1");
if (!result)
{
TC_LOG_ERROR("server.loading", ">> Loaded 0 scenario POI definitions. DB table `scenario_poi` is empty.");
return;
}
- // 0 1 2 3
- QueryResult points = WorldDatabase.Query("SELECT CriteriaTreeID, Idx1, X, Y FROM scenario_poi_points ORDER BY CriteriaTreeID DESC, Idx1, Idx2");
+ // 0 1 2 3 4
+ QueryResult pointsResult = WorldDatabase.Query("SELECT CriteriaTreeID, Idx1, X, Y, Z FROM scenario_poi_points ORDER BY CriteriaTreeID DESC, Idx1, Idx2");
- std::vector<std::vector<std::vector<ScenarioPOIPoint>>> POIs;
+ std::unordered_map<int32, std::map<int32, std::vector<ScenarioPOIPoint>>> allPoints;
- if (points)
+ if (pointsResult)
{
- // The first result should have the highest criteriaTreeId
- Field* fields = points->Fetch();
- uint32 criteriaTreeIdMax = fields[0].GetInt32();
- POIs.resize(criteriaTreeIdMax + 1);
+ Field* fields = pointsResult->Fetch();
do
{
- fields = points->Fetch();
+ fields = pointsResult->Fetch();
int32 CriteriaTreeID = fields[0].GetInt32();
int32 Idx1 = fields[1].GetInt32();
int32 X = fields[2].GetInt32();
int32 Y = fields[3].GetInt32();
+ int32 Z = fields[4].GetInt32();
- if (int32(POIs[CriteriaTreeID].size()) <= Idx1 + 1)
- POIs[CriteriaTreeID].resize(Idx1 + 10);
-
- ScenarioPOIPoint point(X, Y);
- POIs[CriteriaTreeID][Idx1].push_back(point);
- } while (points->NextRow());
+ allPoints[CriteriaTreeID][Idx1].emplace_back(X, Y, Z);
+ } while (pointsResult->NextRow());
}
do
@@ -197,16 +192,23 @@ void ScenarioMgr::LoadScenarioPOI()
int32 flags = fields[6].GetInt32();
int32 worldEffectID = fields[7].GetInt32();
int32 playerConditionID = fields[8].GetInt32();
+ int32 navigationPlayerConditionID = fields[9].GetInt32();
if (!sCriteriaMgr->GetCriteriaTree(criteriaTreeID))
TC_LOG_ERROR("sql.sql", "`scenario_poi` CriteriaTreeID (%u) Idx1 (%u) does not correspond to a valid criteria tree", criteriaTreeID, idx1);
- if (criteriaTreeID < int32(POIs.size()) && idx1 < int32(POIs[criteriaTreeID].size()))
- _scenarioPOIStore[criteriaTreeID].emplace_back(blobIndex, mapID, uiMapID, priority, flags, worldEffectID, playerConditionID, POIs[criteriaTreeID][idx1]);
- else
- TC_LOG_ERROR("server.loading", "Table scenario_poi references unknown scenario poi points for criteria tree id %i POI id %i", criteriaTreeID, blobIndex);
+ if (std::map<int32, std::vector<ScenarioPOIPoint>>* blobs = Trinity::Containers::MapGetValuePtr(allPoints, criteriaTreeID))
+ {
+ if (std::vector<ScenarioPOIPoint>* points = Trinity::Containers::MapGetValuePtr(*blobs, idx1))
+ {
+ _scenarioPOIStore[criteriaTreeID].emplace_back(blobIndex, mapID, uiMapID, priority, flags, worldEffectID, playerConditionID, navigationPlayerConditionID, std::move(*points));
+ ++count;
+ continue;
+ }
+ }
+
+ TC_LOG_ERROR("server.loading", "Table scenario_poi references unknown scenario poi points for criteria tree id %i POI id %i", criteriaTreeID, blobIndex);
- ++count;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u scenario POI definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
diff --git a/src/server/game/Scenarios/ScenarioMgr.h b/src/server/game/Scenarios/ScenarioMgr.h
index 62b51871754..4445879d42c 100644
--- a/src/server/game/Scenarios/ScenarioMgr.h
+++ b/src/server/game/Scenarios/ScenarioMgr.h
@@ -68,7 +68,7 @@ struct ScenarioPOIPoint
int32 Z;
ScenarioPOIPoint() : X(0), Y(0), Z(0) { }
- ScenarioPOIPoint(int32 x, int32 y) : X(x), Y(y), Z(0) { }
+ ScenarioPOIPoint(int32 x, int32 y, int32 z) : X(x), Y(y), Z(z) { }
};
struct ScenarioPOI
@@ -86,9 +86,9 @@ struct ScenarioPOI
ScenarioPOI() : BlobIndex(0), MapID(0), UiMapID(0), Priority(0), Flags(0), WorldEffectID(0), PlayerConditionID(0), NavigationPlayerConditionID(0) { }
ScenarioPOI(int32 blobIndex, int32 mapID, int32 uiMapID, int32 priority, int32 flags, int32 worldEffectID,
- int32 playerConditionID, std::vector<ScenarioPOIPoint> points) :
+ int32 playerConditionID, int32 navigationPlayerConditionID, std::vector<ScenarioPOIPoint> points) :
BlobIndex(blobIndex), MapID(mapID), UiMapID(uiMapID), Priority(priority), Flags(flags), WorldEffectID(worldEffectID),
- PlayerConditionID(playerConditionID), NavigationPlayerConditionID(0), Points(std::move(points)) { }
+ PlayerConditionID(playerConditionID), NavigationPlayerConditionID(navigationPlayerConditionID), Points(std::move(points)) { }
ScenarioPOI(ScenarioPOI&& scenarioPOI) = default;
};
diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp
index 40df5986092..e49e81c7e83 100644
--- a/src/server/scripts/Commands/cs_go.cpp
+++ b/src/server/scripts/Commands/cs_go.cpp
@@ -334,6 +334,7 @@ public:
x = data.Points.front().X;
y = data.Points.front().Y;
+ z = data.Points.front().Z;
}
else
{