diff --git a/src/game/DBScripts/ScriptMgr.cpp b/src/game/DBScripts/ScriptMgr.cpp index 58385f84e2..e8f865ac45 100644 --- a/src/game/DBScripts/ScriptMgr.cpp +++ b/src/game/DBScripts/ScriptMgr.cpp @@ -1326,7 +1326,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; @@ -1344,7 +1344,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 }; } } } @@ -1355,10 +1355,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) { @@ -1398,13 +1399,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 { @@ -1464,7 +1466,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) @@ -1485,15 +1487,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 @@ -1575,7 +1583,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 }; } } } @@ -1596,7 +1604,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 @@ -1663,6 +1671,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 @@ -1681,7 +1690,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)) @@ -1709,7 +1720,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; } @@ -1717,7 +1728,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; @@ -2508,6 +2519,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; @@ -2598,25 +2610,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 bffd3514c7..89444d045d 100644 --- a/src/game/DBScripts/ScriptMgr.h +++ b/src/game/DBScripts/ScriptMgr.h @@ -600,7 +600,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; } @@ -627,7 +627,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;