diff --git a/src/game/DBScripts/ScriptMgr.cpp b/src/game/DBScripts/ScriptMgr.cpp index 97b34dbb638..535d7a54405 100644 --- a/src/game/DBScripts/ScriptMgr.cpp +++ b/src/game/DBScripts/ScriptMgr.cpp @@ -1331,7 +1331,7 @@ bool ScriptAction::GetScriptCommandObject(const ObjectGuid guid, bool includeIte /// Select source and target for a script command /// Returns false if an error happened -bool ScriptAction::GetScriptProcessTargets(WorldObject* originalSource, WorldObject* originalTarget, std::vector& finalSources, std::vector& finalTargets) const +std::pair ScriptAction::GetScriptProcessTargets(WorldObject* originalSource, WorldObject* originalTarget, std::vector& finalSources, std::vector& finalTargets) const { std::vector buddies; @@ -1349,7 +1349,7 @@ bool ScriptAction::GetScriptProcessTargets(WorldObject* originalSource, WorldObj if (m_script->command != SCRIPT_COMMAND_TERMINATE_SCRIPT) { sLog.outError(" DB-SCRIPTS: Process table `%s` id %u, command %u has buddy %u by guid %u but buddy is dead, skipping.", m_table, m_script->id, m_script->command, buddy->GetEntry(), m_script->searchRadiusOrGuid); - return false; + return { false, false }; } } } @@ -1360,10 +1360,11 @@ bool ScriptAction::GetScriptProcessTargets(WorldObject* originalSource, WorldObj if (!buddy && m_script->command != SCRIPT_COMMAND_TERMINATE_SCRIPT) { DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, " DB-SCRIPTS: Process table `%s` id %u, command %u has buddy by guid %u not loaded in map %u (data-flags %u), skipping.", m_table, m_script->id, m_script->command, m_script->searchRadiusOrGuid, m_map->GetId(), m_script->data_flags); - return false; + return { false, false }; } - // this type can only have one buddy result - buddies.push_back(buddy); + if (buddy) + // this type can only have one buddy result + buddies.push_back(buddy); } else if (m_script->data_flags & SCRIPT_FLAG_BUDDY_BY_POOL) { @@ -1403,13 +1404,14 @@ bool ScriptAction::GetScriptProcessTargets(WorldObject* originalSource, WorldObj } } - if (!buddy) + if (!buddy && m_script->command != SCRIPT_COMMAND_TERMINATE_SCRIPT) { sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, command %u has buddy %u by pool id %u and no creature found in map %u (data-flags %u), skipping.", m_table, m_script->id, m_script->command, m_script->buddyEntry, m_script->searchRadiusOrGuid, m_map->GetId(), m_script->data_flags); - return false; + return { false, false }; } - // this type can only have one buddy result - buddies.push_back(buddy); + if (buddy) + // this type can only have one buddy result + buddies.push_back(buddy); } else if (m_script->data_flags & SCRIPT_FLAG_BUDDY_BY_SPAWN_GROUP) // Buddy by group { @@ -1469,7 +1471,7 @@ bool ScriptAction::GetScriptProcessTargets(WorldObject* originalSource, WorldObj origin = originalTarget; auto worldObjects = m_map->GetWorldObjects(m_script->buddyEntry); if (worldObjects == nullptr) - return false; + return { false, false }; if ((m_script->data_flags & SCRIPT_FLAG_ALL_ELIGIBLE_BUDDIES) != 0) { for (WorldObject* wo : *worldObjects) @@ -1490,15 +1492,21 @@ bool ScriptAction::GetScriptProcessTargets(WorldObject* originalSource, WorldObj } if (m_script->searchRadiusOrGuid > 0) for (WorldObject* buddy : buddies) - if (buddy->IsWithinDist(origin, m_script->searchRadiusOrGuid)) + if (!buddy->IsWithinDist(origin, m_script->searchRadiusOrGuid)) buddies.erase(std::remove(buddies.begin(), buddies.end(), buddy), buddies.end()); + + if (buddies.empty() && m_script->command != SCRIPT_COMMAND_TERMINATE_SCRIPT) + { + sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, command %u has buddy %u by pool id %u and no creature found in map %u (data-flags %u), skipping.", m_table, m_script->id, m_script->command, m_script->buddyEntry, m_script->searchRadiusOrGuid, m_map->GetId(), m_script->data_flags); + return { false, false }; + } } else // Buddy by entry { if (!originalSource && !originalTarget) { sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, command %u called without buddy %u, but no source for search available, skipping.", m_table, m_script->id, m_script->command, m_script->buddyEntry); - return false; + return { false, false }; } // Prefer non-players as searcher @@ -1580,7 +1588,7 @@ bool ScriptAction::GetScriptProcessTargets(WorldObject* originalSource, WorldObj if (buddies.empty() && m_script->command != SCRIPT_COMMAND_TERMINATE_SCRIPT) { sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, command %u has buddy %u not found in range %u of searcher %s (data-flags %u), skipping.", m_table, m_script->id, m_script->command, m_script->buddyEntry, m_script->searchRadiusOrGuid, origin->GetGuidStr().c_str(), m_script->data_flags); - return false; + return { false, false }; } } } @@ -1601,7 +1609,7 @@ bool ScriptAction::GetScriptProcessTargets(WorldObject* originalSource, WorldObj if (m_script->data_flags & SCRIPT_FLAG_SOURCE_TARGETS_SELF) finalTargets = finalSources; - return true; + return { true, buddies.size() }; } /// Helper to log error information @@ -1668,6 +1676,7 @@ bool ScriptAction::HandleScriptStep() std::vector targets; Object* itemSource = nullptr; + bool buddyFound; { // Add scope for source & target variables so that they are not used below @@ -1686,7 +1695,9 @@ bool ScriptAction::HandleScriptStep() sources.push_back(static_cast(source)); if (target && target->isType(TYPEMASK_WORLDOBJECT)) targets.push_back(static_cast(target)); - if (!GetScriptProcessTargets(dynamic_cast(source), dynamic_cast(target), sources, targets)) + bool success; + std::tie(success, buddyFound) = GetScriptProcessTargets(dynamic_cast(source), dynamic_cast(target), sources, targets); + if (!success) return false; if (source && source->isType(TYPEMASK_ITEM)) @@ -1714,7 +1725,7 @@ bool ScriptAction::HandleScriptStep() WorldObject* pTarget = data.second; Object* pSourceOrItem = pSource ? pSource : itemSource; - bool result = ExecuteDbscriptCommand(pSource, pTarget, pSourceOrItem); + bool result = ExecuteDbscriptCommand(pSource, pTarget, pSourceOrItem, buddyFound); if (result == true) finalResult = true; } @@ -1722,7 +1733,7 @@ bool ScriptAction::HandleScriptStep() return finalResult; } -bool ScriptAction::ExecuteDbscriptCommand(WorldObject* pSource, WorldObject* pTarget, Object* pSourceOrItem) +bool ScriptAction::ExecuteDbscriptCommand(WorldObject* pSource, WorldObject* pTarget, Object* pSourceOrItem, bool buddyFound) { if (m_script->condition_id && !sObjectMgr.IsConditionSatisfied(m_script->condition_id, pTarget, m_map, pSource, CONDITION_FROM_DBSCRIPTS)) return false; @@ -2536,6 +2547,7 @@ bool ScriptAction::ExecuteDbscriptCommand(WorldObject* pSource, WorldObject* pTa } bool result = false; + bool terminationBuddyFound = false; if (m_script->terminateScript.npcOrGOEntry || m_script->terminateScript.poolId || (m_script->data_flags & (SCRIPT_FLAG_BUDDY_BY_GUID))) { WorldObject* terminationBuddy = nullptr; @@ -2626,25 +2638,27 @@ bool ScriptAction::ExecuteDbscriptCommand(WorldObject* pSource, WorldObject* pTa } } - if (!(m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL) && !terminationBuddy) - { - if (m_script->terminateScript.npcOrGOEntry) - DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, "DB-SCRIPTS: Process table `%s` id %u, terminate further steps of this script! (as searched npc entry(%u) was not found alive)", m_table, m_script->id, m_script->terminateScript.npcOrGOEntry); - else - DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, "DB-SCRIPTS: Process table `%s` id %u, terminate further steps of this script! (as no npc in pool id(%u) was found alive)", m_table, m_script->id, m_script->terminateScript.poolId); - result = true; - } - else if (m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL && terminationBuddy) - { - if (m_script->terminateScript.npcOrGOEntry) - DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, "DB-SCRIPTS: Process table `%s` id %u, terminate further steps of this script! (as searched npc entry(%u) was found alive)", m_table, m_script->id, m_script->terminateScript.npcOrGOEntry); - else - DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, "DB-SCRIPTS: Process table `%s` id %u, terminate further steps of this script! (as searched npc in pool id(%u) was found alive)", m_table, m_script->id, m_script->terminateScript.poolId); - result = true; - } + terminationBuddyFound = terminationBuddy; } else + terminationBuddyFound = buddyFound; + + if (!(m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL) && !terminationBuddyFound) + { + if (m_script->terminateScript.npcOrGOEntry) + DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, "DB-SCRIPTS: Process table `%s` id %u, terminate further steps of this script! (as searched npc entry(%u) was not found alive)", m_table, m_script->id, m_script->terminateScript.npcOrGOEntry); + else + DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, "DB-SCRIPTS: Process table `%s` id %u, terminate further steps of this script! (as no npc in pool id(%u) was found alive)", m_table, m_script->id, m_script->terminateScript.poolId); + result = true; + } + else if (m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL && terminationBuddyFound) + { + if (m_script->terminateScript.npcOrGOEntry) + DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, "DB-SCRIPTS: Process table `%s` id %u, terminate further steps of this script! (as searched npc entry(%u) was found alive)", m_table, m_script->id, m_script->terminateScript.npcOrGOEntry); + else + DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, "DB-SCRIPTS: Process table `%s` id %u, terminate further steps of this script! (as searched npc in pool id(%u) was found alive)", m_table, m_script->id, m_script->terminateScript.poolId); result = true; + } if (result) // Terminate further steps of this script { diff --git a/src/game/DBScripts/ScriptMgr.h b/src/game/DBScripts/ScriptMgr.h index e6197f3edb3..94d32543879 100644 --- a/src/game/DBScripts/ScriptMgr.h +++ b/src/game/DBScripts/ScriptMgr.h @@ -611,7 +611,7 @@ class ScriptAction ScriptAction(ScriptMapType scriptType, Map* _map, ObjectGuid _sourceGuid, ObjectGuid _targetGuid, ObjectGuid _ownerGuid, std::shared_ptr _script); bool HandleScriptStep(); // return true IF AND ONLY IF the script should be terminated - bool ExecuteDbscriptCommand(WorldObject* pSource, WorldObject* pTarget, Object* pSourceOrItem); + bool ExecuteDbscriptCommand(WorldObject* pSource, WorldObject* pTarget, Object* pSourceOrItem, bool buddyFound); const char* GetTableName() const { return m_table; } uint32 GetId() const { return m_script->id; } @@ -638,7 +638,7 @@ class ScriptAction // Helper functions bool GetScriptCommandObject(const ObjectGuid guid, bool includeItem, Object*& resultObject) const; - bool GetScriptProcessTargets(WorldObject* originalSource, WorldObject* originalTarget, std::vector& finalSources, std::vector& finalTargets) const; + std::pair GetScriptProcessTargets(WorldObject* originalSource, WorldObject* originalTarget, std::vector& finalSources, std::vector& finalTargets) const; bool LogIfNotCreature(WorldObject* pWorldObject) const; bool LogIfNotUnit(WorldObject* pWorldObject) const; bool LogIfNotGameObject(WorldObject* pWorldObject) const;