diff options
author | Shauren <shauren.trinity@gmail.com> | 2020-11-05 19:37:35 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2020-12-08 18:16:46 +0100 |
commit | 4ca29f3cb050896a8a6c1fea5b2364b2b11c22cd (patch) | |
tree | 7508b9ea8fe5fc393c65bb207479f99e68182ebe | |
parent | 56c097c12957b9f803b01b85a851aec0ae0761e2 (diff) |
Core/Misc: First set of required db changes for 9.0
-rw-r--r-- | sql/updates/world/master/2020_11_05_00_world.sql | 80 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/WorldDatabase.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/CreatureData.h | 1 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 323 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.h | 29 | ||||
-rw-r--r-- | src/server/game/Quests/QuestDef.cpp | 194 | ||||
-rw-r--r-- | src/server/game/Quests/QuestDef.h | 74 | ||||
-rw-r--r-- | src/server/game/Scenarios/Scenario.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Scenarios/ScenarioMgr.cpp | 46 | ||||
-rw-r--r-- | src/server/game/Scenarios/ScenarioMgr.h | 6 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_go.cpp | 1 |
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 { |