From b7d7089da6302d6ed487c850267476f6a7ec63f9 Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Fri, 10 Oct 2025 11:37:14 -0400 Subject: [PATCH 01/10] fix(Core/Entities): Daily and other quests should grant XP when rewarded on subsequent completions. (#23160) --- src/server/game/Entities/Player/PlayerQuest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/game/Entities/Player/PlayerQuest.cpp b/src/server/game/Entities/Player/PlayerQuest.cpp index 9f663ff2fa..a8307c7887 100644 --- a/src/server/game/Entities/Player/PlayerQuest.cpp +++ b/src/server/game/Entities/Player/PlayerQuest.cpp @@ -740,9 +740,9 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, if (log_slot < MAX_QUEST_LOG_SIZE) SetQuestSlot(log_slot, 0); - bool rewarded = IsQuestRewarded(quest_id) && !quest->IsDFQuest(); + bool const rewarded = IsQuestRewarded(quest_id) && !quest->IsDFQuest() && !(quest->IsDaily() || quest->IsWeekly() || quest->IsMonthly()); - // Not give XP in case already completed once repeatable quest + // Repeatable quests (not time-based reset ones) should not give XP on subsequent completions uint32 XP = rewarded ? 0 : CalculateQuestRewardXP(quest); sScriptMgr->OnPlayerQuestComputeXP(this, quest, XP); From dd1f6f776cf7c9dba989706fc668deb97aaea611 Mon Sep 17 00:00:00 2001 From: privatecore Date: Fri, 10 Oct 2025 21:53:36 +0200 Subject: [PATCH 02/10] fix(Core/Player): Fix NotAvoidSatisfy script hook to reference the current player (#23004) --- src/server/game/Entities/Player/PlayerStorage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/game/Entities/Player/PlayerStorage.cpp b/src/server/game/Entities/Player/PlayerStorage.cpp index d45533ad63..a932af812d 100644 --- a/src/server/game/Entities/Player/PlayerStorage.cpp +++ b/src/server/game/Entities/Player/PlayerStorage.cpp @@ -6833,7 +6833,7 @@ bool Player::Satisfy(DungeonProgressionRequirements const* ar, uint32 target_map || missingPlayerItems.size() || missingPlayerQuests.size() || missingPlayerAchievements.size() || missingLeaderItems.size() || missingLeaderQuests.size() || missingLeaderAchievements.size()) { - if (!sScriptMgr->OnPlayerNotAvoidSatisfy(partyLeader, ar, target_map, report)) + if (!sScriptMgr->OnPlayerNotAvoidSatisfy(this, ar, target_map, report)) return true; if (report) From 4867510cac89e12b56e95d5a60b7f88bfb4ecca6 Mon Sep 17 00:00:00 2001 From: grace-of-hainaut <104199792+grace-of-hainaut@users.noreply.github.com> Date: Fri, 10 Oct 2025 21:14:58 +0100 Subject: [PATCH 03/10] fix(Core): Correct fishing catch calculations (#23171) --- .../game/Entities/GameObject/GameObject.cpp | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index f258db1caf..d8897ab120 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1731,34 +1731,40 @@ void GameObject::Use(Unit* user) uint32 zone, subzone; GetZoneAndAreaId(zone, subzone); - int32 zone_skill = sObjectMgr->GetFishingBaseSkillLevel(subzone); - if (!zone_skill) - zone_skill = sObjectMgr->GetFishingBaseSkillLevel(zone); + int32 zoneSkill = sObjectMgr->GetFishingBaseSkillLevel(subzone); + if (!zoneSkill) + zoneSkill = sObjectMgr->GetFishingBaseSkillLevel(zone); //provide error, no fishable zone or area should be 0 - if (!zone_skill) + if (!zoneSkill) LOG_ERROR("sql.sql", "Fishable areaId {} are not properly defined in `skill_fishing_base_level`.", subzone); - int32 skill = player->GetSkillValue(SKILL_FISHING); + // no miss skill is zone skill + 95 since at least patch 2.1 + int32 const noMissSkill = zoneSkill + 95; + + int32 const skill = player->GetSkillValue(SKILL_FISHING); int32 chance; - if (skill < zone_skill) + // fishing pool catches are 100% + //TODO: find reasonable value for fishing hole search + GameObject* fishingHole = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE); + if (fishingHole) + chance = 100; + else if (skill < noMissSkill) { - chance = int32(pow((double)skill / zone_skill, 2) * 100); + chance = int32(pow((double)skill / noMissSkill, 2) * 100); if (chance < 1) chance = 1; } else chance = 100; - int32 roll = irand(1, 100); + int32 const roll = irand(1, 100); - LOG_DEBUG("entities.gameobject", "Fishing check (skill: {} zone min skill: {} chance {} roll: {}", skill, zone_skill, chance, roll); + LOG_DEBUG("entities.gameobject", "Fishing check (skill: {} zone min skill: {} no-miss skill: {} chance {} roll: {})", skill, zoneSkill, noMissSkill, chance, roll); - if (sScriptMgr->OnPlayerUpdateFishingSkill(player, skill, zone_skill, chance, roll)) - { + if (sScriptMgr->OnPlayerUpdateFishingSkill(player, skill, zoneSkill, chance, roll)) player->UpdateFishingSkill(); - } // but you will likely cause junk in areas that require a high fishing skill (not yet implemented) if (chance >= roll) { @@ -1768,11 +1774,10 @@ void GameObject::Use(Unit* user) SetOwnerGUID(player->GetGUID()); SetSpellId(0); // prevent removing unintended auras at Unit::RemoveGameObject - //TODO: find reasonable value for fishing hole search - GameObject* ok = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE); - if (ok) + // fishing pool catch + if (fishingHole) { - ok->Use(player); + fishingHole->Use(player); SetLootState(GO_JUST_DEACTIVATED); } else From 8a64eb05f71c14079fc788307de1889316edaea5 Mon Sep 17 00:00:00 2001 From: zeb139 <37308742+zeb139@users.noreply.github.com> Date: Fri, 10 Oct 2025 16:55:59 -0400 Subject: [PATCH 04/10] fix(Core): Deeprun Tram Subway timer/syncronization by loading grid (#23009) --- src/server/game/Maps/TransportMgr.cpp | 42 ++++++++++++++++++--------- src/server/game/Maps/TransportMgr.h | 2 ++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp index f065ccf56a..a024a02b97 100644 --- a/src/server/game/Maps/TransportMgr.cpp +++ b/src/server/game/Maps/TransportMgr.cpp @@ -448,31 +448,45 @@ void TransportMgr::SpawnContinentTransports() LOG_INFO("server.loading", ">> Spawned {} continent motion transports in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); } + // Preloads Deeprun Tram to fix issues with Subway carts syncronization + /// @todo: This is a temporary workaround. Consider removing TransportMgr::PreloadGridsFromQuery() as part of fix. + /** + Takenbacon: "In the long run the most likely ideal fix would be to always spawn all transport types (and thus loading their grid) on map creation" + See https://github.com/azerothcore/azerothcore-wotlk/pull/23009 for more details. + */ + PreloadGridsFromQuery("SELECT map, position_x, position_y FROM gameobject g JOIN gameobject_template t ON g.id = t.entry WHERE t.type = 11 AND g.map = 369", count); + if (sWorld->getBoolConfig(CONFIG_ENABLE_CONTINENT_TRANSPORT_PRELOADING)) { // pussywizard: preload grids for continent static transports - QueryResult result2 = WorldDatabase.Query("SELECT map, position_x, position_y FROM gameobject g JOIN gameobject_template t ON g.id = t.entry WHERE t.type = 11"); + PreloadGridsFromQuery("SELECT map, position_x, position_y FROM gameobject g JOIN gameobject_template t ON g.id = t.entry WHERE t.type = 11 AND g.map != 369", count); + LOG_INFO("server.loading", ">> Preloaded grids for {} continent static transports in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); + } +} - if (result2) +void TransportMgr::PreloadGridsFromQuery(std::string const& query, uint32& count) +{ + if (QueryResult result = WorldDatabase.Query(query)) + { + do { - do - { - Field* fields = result2->Fetch(); - uint16 mapId = fields[0].Get(); - float x = fields[1].Get(); - float y = fields[2].Get(); + Field* fields = result->Fetch(); + uint16 mapId = fields[0].Get(); + float x = fields[1].Get(); + float y = fields[2].Get(); - MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); - if (mapEntry && !mapEntry->Instanceable()) + if (MapEntry const* mapEntry = sMapStore.LookupEntry(mapId)) + { + if (!mapEntry->Instanceable()) + { if (Map* map = sMapMgr->CreateBaseMap(mapId)) { map->LoadGrid(x, y); ++count; } - } while (result2->NextRow()); - } - - LOG_INFO("server.loading", ">> Preloaded grids for {} continent static transports in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); + } + } + } while (result->NextRow()); } } diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h index 9767ab3359..6f712657e0 100644 --- a/src/server/game/Maps/TransportMgr.h +++ b/src/server/game/Maps/TransportMgr.h @@ -158,6 +158,8 @@ private: TransportInstanceMap _instanceTransports; TransportAnimationContainer _transportAnimations; + + void PreloadGridsFromQuery(std::string const& query, uint32& count); }; #define sTransportMgr TransportMgr::instance() From 864ca5a3244e94e4f16021ca1dcc4aeae01990f8 Mon Sep 17 00:00:00 2001 From: Annamaria <20357406+Annamaria-CC@users.noreply.github.com> Date: Fri, 10 Oct 2025 22:56:12 +0200 Subject: [PATCH 05/10] fix (db/smartscripts) : Milton Beats should be male (#22748) --- data/sql/updates/pending_db_world/miltonbeats.sql | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 data/sql/updates/pending_db_world/miltonbeats.sql diff --git a/data/sql/updates/pending_db_world/miltonbeats.sql b/data/sql/updates/pending_db_world/miltonbeats.sql new file mode 100644 index 0000000000..a460ae17e8 --- /dev/null +++ b/data/sql/updates/pending_db_world/miltonbeats.sql @@ -0,0 +1,3 @@ +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 13082) AND (`source_type` = 0) AND (`id` = 2); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(13082, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 3, 0, 4016, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Milton Beats - On Respawn - Morph To Model 4016'); From 4bd945e950f3a5f4bbeda5e910b8fb0c8f65a708 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 10 Oct 2025 20:57:02 +0000 Subject: [PATCH 06/10] chore(DB): import pending files Referenced commit(s): 8a64eb05f71c14079fc788307de1889316edaea5 --- .../miltonbeats.sql => db_world/2025_10_10_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/miltonbeats.sql => db_world/2025_10_10_00.sql} (94%) diff --git a/data/sql/updates/pending_db_world/miltonbeats.sql b/data/sql/updates/db_world/2025_10_10_00.sql similarity index 94% rename from data/sql/updates/pending_db_world/miltonbeats.sql rename to data/sql/updates/db_world/2025_10_10_00.sql index a460ae17e8..19c84c018a 100644 --- a/data/sql/updates/pending_db_world/miltonbeats.sql +++ b/data/sql/updates/db_world/2025_10_10_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_10_09_04 -> 2025_10_10_00 DELETE FROM `smart_scripts` WHERE (`entryorguid` = 13082) AND (`source_type` = 0) AND (`id` = 2); INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES (13082, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 3, 0, 4016, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Milton Beats - On Respawn - Morph To Model 4016'); From a89e9899954dc759d196c586201ae44a4ca58740 Mon Sep 17 00:00:00 2001 From: Annamaria <20357406+Annamaria-CC@users.noreply.github.com> Date: Fri, 10 Oct 2025 22:59:31 +0200 Subject: [PATCH 07/10] fix(DB/SAI): Sergeant Lukas should be male (#22747) --- data/sql/updates/pending_db_world/sergeantlukas.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 data/sql/updates/pending_db_world/sergeantlukas.sql diff --git a/data/sql/updates/pending_db_world/sergeantlukas.sql b/data/sql/updates/pending_db_world/sergeantlukas.sql new file mode 100644 index 0000000000..21f1d65d00 --- /dev/null +++ b/data/sql/updates/pending_db_world/sergeantlukas.sql @@ -0,0 +1,4 @@ +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23723; +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 23723) AND (`source_type` = 0) AND (`id` = 0); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(23723, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2981, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Sergeant Lukas - On Respawn - Morph To Model 2981'); From c52d99bfc49008a377394e954eecd23059f76b53 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 10 Oct 2025 21:00:36 +0000 Subject: [PATCH 08/10] chore(DB): import pending files Referenced commit(s): a89e9899954dc759d196c586201ae44a4ca58740 --- .../sergeantlukas.sql => db_world/2025_10_10_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/sergeantlukas.sql => db_world/2025_10_10_01.sql} (94%) diff --git a/data/sql/updates/pending_db_world/sergeantlukas.sql b/data/sql/updates/db_world/2025_10_10_01.sql similarity index 94% rename from data/sql/updates/pending_db_world/sergeantlukas.sql rename to data/sql/updates/db_world/2025_10_10_01.sql index 21f1d65d00..1bc945774b 100644 --- a/data/sql/updates/pending_db_world/sergeantlukas.sql +++ b/data/sql/updates/db_world/2025_10_10_01.sql @@ -1,3 +1,4 @@ +-- DB update 2025_10_10_00 -> 2025_10_10_01 UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23723; DELETE FROM `smart_scripts` WHERE (`entryorguid` = 23723) AND (`source_type` = 0) AND (`id` = 0); INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES From 9ce8bd0cc69242c409ad78857c690905f5011449 Mon Sep 17 00:00:00 2001 From: Tereneckla Date: Fri, 10 Oct 2025 21:37:36 +0000 Subject: [PATCH 09/10] fix(Core/Module): don't fallback to .dist for module configs (#22874) --- modules/CMakeLists.txt | 1 + src/common/Configuration/Config.cpp | 49 +++++++++++------------------ 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 46c9d5e16f..6c631988e7 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -342,6 +342,7 @@ foreach(ModuleName ${MODULE_LIST__}) foreach(configFileName ${MODULE_CONFIG_LIST}) CopyModuleConfig("${MODULE_CONFIG_PATH}/${configFileName}") + string(REGEX REPLACE "\.dist$" "" configFileName ${configFileName}) set(CONFIG_LIST ${CONFIG_LIST}${configFileName},) message(STATUS " | * ${configFileName}") endforeach() diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp index 5f653fa968..258d15d653 100644 --- a/src/common/Configuration/Config.cpp +++ b/src/common/Configuration/Config.cpp @@ -412,8 +412,14 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog LOG_FATAL("server.loading", "> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable\n\nYour server cannot start without this option!", name, _filename, name, Acore::ToString(def), envVarName); else + { + std::string configs = _filename; + if (!_moduleConfigFiles.empty()) + configs += " or module config"; + LOG_WARN("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.", - name, _filename, name, Acore::ToString(def), envVarName); + name, configs, name, def, envVarName); + } } return def; } @@ -471,8 +477,14 @@ std::string ConfigMgr::GetValueDefault(std::string const& name, std LOG_FATAL("server.loading", "> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.\n\nYour server cannot start without this option!", name, _filename, name, def, envVarName); else + { + std::string configs = _filename; + if (!_moduleConfigFiles.empty()) + configs += " or module config"; + LOG_WARN("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.", - name, _filename, name, def, envVarName); + name, configs, name, def, envVarName); + } } return def; @@ -588,38 +600,13 @@ bool ConfigMgr::LoadModulesConfigs(bool isReload /*= false*/, bool isNeedPrintIn // Start loading module configs std::string const& moduleConfigPath = GetConfigPath() + "modules/"; - bool isExistDefaultConfig = true; - bool isExistDistConfig = true; - for (auto const& distFileName : _additonalFiles) + for (auto const& fileName : _additonalFiles) { - std::string defaultFileName = distFileName; + bool isExistConfig = LoadAdditionalFile(moduleConfigPath + fileName, false, isReload); - if (!defaultFileName.empty()) - { - defaultFileName.erase(defaultFileName.end() - 5, defaultFileName.end()); - } - - // Load .conf.dist config - isExistDistConfig = LoadAdditionalFile(moduleConfigPath + distFileName, false, isReload); - - if (!isReload && !isExistDistConfig) - { - LOG_FATAL("server.loading", "> ConfigMgr::LoadModulesConfigs: Not found original config '{}'. Stop loading", distFileName); - ABORT(); - } - - // Load .conf config - isExistDefaultConfig = LoadAdditionalFile(moduleConfigPath + defaultFileName, true, isReload); - - if (isExistDefaultConfig && isExistDistConfig) - { - _moduleConfigFiles.emplace_back(defaultFileName); - } - else if (!isExistDefaultConfig && isExistDistConfig) - { - _moduleConfigFiles.emplace_back(distFileName); - } + if (isExistConfig) + _moduleConfigFiles.emplace_back(fileName); } if (isNeedPrintInfo) From 292f1a417d0906353eceeaa4cc1df8e8d1b1755f Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Fri, 10 Oct 2025 19:07:56 -0400 Subject: [PATCH 10/10] fix(Scripts/Spells): Add checks for Relief for the Fallen script. (#23168) --- src/server/scripts/Spells/spell_quest.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 127bd957aa..704a354248 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -1364,6 +1364,9 @@ class spell_q12937_relief_for_the_fallen : public AuraScript void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { + if (!GetCaster() || !GetCaster()->IsPlayer()) + return; + Player* caster = GetCaster()->ToPlayer(); Unit* target = GetUnitOwner(); if (target && target->ToCreature())