From 73f7c1118d17c72b12db76ea80fda30dcf5b8975 Mon Sep 17 00:00:00 2001 From: joschiwald Date: Wed, 14 Aug 2013 18:22:28 +0200 Subject: Core/Spells: implemented SPELL_ATTR0_CU_TRIGGERED_BY_CASTER to correct some triggered spells, which will wrongly triggered by target instead of caster Closes #1972 --- src/server/game/Spells/SpellInfo.cpp | 17 +++++++++++------ src/server/game/Spells/SpellInfo.h | 2 +- src/server/game/Spells/SpellMgr.cpp | 3 +++ 3 files changed, 15 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index a58c2ee19e4..3ac1351c135 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1006,8 +1006,12 @@ bool SpellInfo::NeedsExplicitUnitTarget() const bool SpellInfo::NeedsToBeTriggeredByCaster() const { + if (AttributesCu & SPELL_ATTR0_CU_TRIGGERED_BY_CASTER) + return true; + if (NeedsExplicitUnitTarget()) return true; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (Effects[i].IsEffect()) @@ -1017,6 +1021,7 @@ bool SpellInfo::NeedsToBeTriggeredByCaster() const return true; } } + return false; } @@ -1714,7 +1719,7 @@ uint32 SpellInfo::GetAllEffectsMechanicMask() const uint32 mask = 0; if (Mechanic) mask |= 1 << Mechanic; - for (int i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (Effects[i].IsEffect() && Effects[i].Mechanic) mask |= 1 << Effects[i].Mechanic; return mask; @@ -1724,9 +1729,9 @@ uint32 SpellInfo::GetEffectMechanicMask(uint8 effIndex) const { uint32 mask = 0; if (Mechanic) - mask |= 1<< Mechanic; + mask |= 1 << Mechanic; if (Effects[effIndex].IsEffect() && Effects[effIndex].Mechanic) - mask |= 1<< Effects[effIndex].Mechanic; + mask |= 1 << Effects[effIndex].Mechanic; return mask; } @@ -1734,10 +1739,10 @@ uint32 SpellInfo::GetSpellMechanicMaskByEffectMask(uint32 effectMask) const { uint32 mask = 0; if (Mechanic) - mask |= 1<< Mechanic; - for (int i = 0; i < MAX_SPELL_EFFECTS; ++i) + mask |= 1 << Mechanic; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if ((effectMask & (1 << i)) && Effects[i].Mechanic) - mask |= 1<< Effects[i].Mechanic; + mask |= 1 << Effects[i].Mechanic; return mask; } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 6ed742a3b8e..82fa1129429 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -176,7 +176,7 @@ enum SpellCustomAttributes SPELL_ATTR0_CU_CONE_LINE = 0x00000004, SPELL_ATTR0_CU_SHARE_DAMAGE = 0x00000008, SPELL_ATTR0_CU_NO_INITIAL_THREAT = 0x00000010, - SPELL_ATTR0_CU_NONE2 = 0x00000020, // UNUSED + SPELL_ATTR0_CU_TRIGGERED_BY_CASTER = 0x00000020, // @todo: need generic solution, some triggered spells will be casted by target instead of caster SPELL_ATTR0_CU_AURA_CC = 0x00000040, SPELL_ATTR0_CU_DIRECT_DAMAGE = 0x00000100, SPELL_ATTR0_CU_CHARGE = 0x00000200, diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 24bd19d2d24..d8094488fcd 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2972,6 +2972,9 @@ void SpellMgr::LoadSpellInfoCustomAttributes() case 72293: // Mark of the Fallen Champion (Deathbringer Saurfang) spellInfo->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF0; break; + case 38729: // Rod of Purification + spellInfo->AttributesCu |= SPELL_ATTR0_CU_TRIGGERED_BY_CASTER; + break; default: break; } -- cgit v1.2.3 From 8c961687a00970eb7c3f347262e56f0e9a58cf83 Mon Sep 17 00:00:00 2001 From: Discover- Date: Thu, 15 Aug 2013 01:18:10 +0100 Subject: Core/SmartAI: Implement SMART_EVENT_FRIENDLY_HEALTH_PCT. On current clean TDB, there are a total of 106 creatures using SMART_EVENT_FRIENDLY_HEALTH (non-PCT) which has a flat first parameter, but only 8 of these use the event correctly (and therefore only 8 of them actually work). Closes #10520 --- sql/updates/world/2013_08_15_00_world_sai.sql | 5 +++ src/server/game/AI/SmartScripts/SmartScript.cpp | 52 +++++++++++++++++++++- src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 25 +++++++++++ src/server/game/AI/SmartScripts/SmartScriptMgr.h | 14 +++++- 4 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 sql/updates/world/2013_08_15_00_world_sai.sql (limited to 'src') diff --git a/sql/updates/world/2013_08_15_00_world_sai.sql b/sql/updates/world/2013_08_15_00_world_sai.sql new file mode 100644 index 00000000000..36ee8fb12cf --- /dev/null +++ b/sql/updates/world/2013_08_15_00_world_sai.sql @@ -0,0 +1,5 @@ +-- SELECT `entryorguid`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`comment` FROM `smart_scripts` WHERE `event_type`=14; +UPDATE `smart_scripts` SET `event_type`=74,`event_param2`=`event_param1`,`event_param1`=0,`target_type`=9 WHERE `entryorguid`=20049 AND `id`=4; +UPDATE `smart_scripts` SET `event_type`=74,`event_param2`=`event_param1`,`event_param1`=0,`target_type`=9 WHERE `entryorguid`=9045 AND `id`=3; +UPDATE `smart_scripts` SET `event_type`=74,`target_type`=9 WHERE `event_type`=14 AND `event_param1`=0 AND `event_param2` > 0 AND `event_param2` < 100; +UPDATE `smart_scripts` SET `event_param1`=`event_param2`,`event_param2`=30 WHERE `event_type`=14 AND `event_param2` >= 100; diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 65b1e6c331e..755b4afe5db 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2623,7 +2623,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui return; Unit* target = DoSelectLowestHpFriendly((float)e.event.friendlyHealt.radius, e.event.friendlyHealt.hpDeficit); - if (!target) + if (!target || !target->IsInCombat()) return; ProcessTimedAction(e, e.event.friendlyHealt.repeatMin, e.event.friendlyHealt.repeatMax, target); break; @@ -2940,6 +2940,55 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui ProcessAction(e, unit, var0); break; } + case SMART_EVENT_FRIENDLY_HEALTH_PCT: + { + if (!me || !me->IsInCombat()) + return; + + ObjectList* _targets = NULL; + + switch (e.GetTargetType()) + { + case SMART_TARGET_CREATURE_RANGE: + case SMART_TARGET_CREATURE_GUID: + case SMART_TARGET_CREATURE_DISTANCE: + case SMART_TARGET_CLOSEST_CREATURE: + case SMART_TARGET_CLOSEST_PLAYER: + case SMART_TARGET_PLAYER_RANGE: + case SMART_TARGET_PLAYER_DISTANCE: + _targets = GetTargets(e); + break; + default: + return; + } + + if (!_targets) + return; + + Unit* target = NULL; + + for (ObjectList::const_iterator itr = _targets->begin(); itr != _targets->end(); ++itr) + { + if (IsUnit(*itr) && me->IsFriendlyTo((*itr)->ToUnit()) && (*itr)->ToUnit()->IsAlive() && (*itr)->ToUnit()->IsInCombat()) + { + uint32 healthPct = uint32((*itr)->ToUnit()->GetHealthPct()); + + if (healthPct > e.event.friendlyHealtPct.maxHpPct || healthPct < e.event.friendlyHealtPct.minHpPct) + continue; + + target = (*itr)->ToUnit(); + break; + } + } + + delete _targets; + + if (!target) + return; + + ProcessTimedAction(e, e.event.friendlyHealtPct.repeatMin, e.event.friendlyHealtPct.repeatMax, target); + break; + } default: TC_LOG_ERROR(LOG_FILTER_SQL, "SmartScript::ProcessEvent: Unhandled Event type %u", e.GetEventType()); break; @@ -3019,6 +3068,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff) case SMART_EVENT_HAS_AURA: case SMART_EVENT_TARGET_BUFFED: case SMART_EVENT_IS_BEHIND_TARGET: + case SMART_EVENT_FRIENDLY_HEALTH_PCT: { ProcessEvent(e); if (e.GetScriptType() == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST) diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 99693355d70..52585309cf9 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -544,6 +544,31 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } break; } + case SMART_EVENT_FRIENDLY_HEALTH_PCT: + if (!IsMinMaxValid(e, e.event.friendlyHealtPct.repeatMin, e.event.friendlyHealtPct.repeatMax)) + return false; + + if (e.event.friendlyHealtPct.maxHpPct > 100 || e.event.friendlyHealtPct.minHpPct > 100) + { + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u has pct value above 100, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + return false; + } + + switch (e.GetTargetType()) + { + case SMART_TARGET_CREATURE_RANGE: + case SMART_TARGET_CREATURE_GUID: + case SMART_TARGET_CREATURE_DISTANCE: + case SMART_TARGET_CLOSEST_CREATURE: + case SMART_TARGET_CLOSEST_PLAYER: + case SMART_TARGET_PLAYER_RANGE: + case SMART_TARGET_PLAYER_DISTANCE: + break; + default: + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid target_type %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); + return false; + } + break; case SMART_EVENT_GO_STATE_CHANGED: case SMART_EVENT_GO_EVENT_INFORM: case SMART_EVENT_TIMED_EVENT_TRIGGERED: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 740be9276b2..ac4865c8fcb 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -155,8 +155,9 @@ enum SMART_EVENT SMART_EVENT_GO_EVENT_INFORM = 71, // eventId SMART_EVENT_ACTION_DONE = 72, // eventId (SharedDefines.EventId) SMART_EVENT_ON_SPELLCLICK = 73, // clicker (unit) + SMART_EVENT_FRIENDLY_HEALTH_PCT = 74, // minHpPct, maxHpPct, repeatMin, repeatMax - SMART_EVENT_END = 74 + SMART_EVENT_END = 75 }; struct SmartEvent @@ -361,6 +362,14 @@ struct SmartEvent uint32 eventId; } doAction; + struct + { + uint32 minHpPct; + uint32 maxHpPct; + uint32 repeatMin; + uint32 repeatMax; + } friendlyHealtPct; + struct { uint32 param1; @@ -1225,7 +1234,8 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] = {SMART_EVENT_GO_STATE_CHANGED, SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, {SMART_EVENT_GO_EVENT_INFORM, SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, {SMART_EVENT_ACTION_DONE, SMART_SCRIPT_TYPE_MASK_CREATURE }, - {SMART_EVENT_ON_SPELLCLICK, SMART_SCRIPT_TYPE_MASK_CREATURE } + {SMART_EVENT_ON_SPELLCLICK, SMART_SCRIPT_TYPE_MASK_CREATURE }, + {SMART_EVENT_FRIENDLY_HEALTH_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE }, }; enum SmartEventFlags -- cgit v1.2.3 From a0ff0233c59a4c12c229a0d02d728819b18c7ed0 Mon Sep 17 00:00:00 2001 From: Discover- Date: Thu, 15 Aug 2013 01:22:22 +0100 Subject: Core/SmartAI: Implement SMART_TARGET_CLOSEST_FRIENDLY. Parameter is distance to search for. Closes #10521 --- src/server/game/AI/SmartScripts/SmartScript.cpp | 22 +++++++++++++++++++++- src/server/game/AI/SmartScripts/SmartScript.h | 1 + src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 1 + src/server/game/AI/SmartScripts/SmartScriptMgr.h | 9 ++++++++- 4 files changed, 31 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 755b4afe5db..b4e18b66a69 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -1401,7 +1401,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u e.GetTargetType() == SMART_TARGET_GAMEOBJECT_GUID || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_DISTANCE || e.GetTargetType() == SMART_TARGET_CLOSEST_CREATURE || e.GetTargetType() == SMART_TARGET_CLOSEST_GAMEOBJECT || e.GetTargetType() == SMART_TARGET_OWNER_OR_SUMMONER || e.GetTargetType() == SMART_TARGET_ACTION_INVOKER || - e.GetTargetType() == SMART_TARGET_CLOSEST_ENEMY) + e.GetTargetType() == SMART_TARGET_CLOSEST_ENEMY || e.GetTargetType() == SMART_TARGET_CLOSEST_FRIENDLY) { ObjectList* targets = GetTargets(e, unit); if (!targets) @@ -2506,6 +2506,14 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* break; } + case SMART_TARGET_CLOSEST_FRIENDLY: + { + if (me) + if (Unit* target = DoFindClosestFriendlyInRange(e.target.closestFriendly.maxDist)) + l->push_back(target); + + break; + } case SMART_TARGET_POSITION: default: break; @@ -3374,6 +3382,18 @@ void SmartScript::DoFindFriendlyMissingBuff(std::list& list, float ra cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range); } +Unit* SmartScript::DoFindClosestFriendlyInRange(float range) +{ + if (!me) + return NULL; + + Unit* unit = NULL; + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(me, me, range); + Trinity::UnitLastSearcher searcher(me, unit, u_check); + me->VisitNearbyObject(range, searcher); + return unit; +} + void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry) { mTimedActionList.clear(); diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 6801c132331..b22f2d81b26 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -89,6 +89,7 @@ class SmartScript Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff); void DoFindFriendlyCC(std::list& _list, float range); void DoFindFriendlyMissingBuff(std::list& list, float range, uint32 spellid); + Unit* DoFindClosestFriendlyInRange(float range); void StoreTargetList(ObjectList* targets, uint32 id) { diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 52585309cf9..1e20d2e6fbb 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -301,6 +301,7 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e) case SMART_TARGET_CLOSEST_GAMEOBJECT: case SMART_TARGET_CLOSEST_CREATURE: case SMART_TARGET_CLOSEST_ENEMY: + case SMART_TARGET_CLOSEST_FRIENDLY: case SMART_TARGET_STORED: break; default: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index ac4865c8fcb..05880c07ff4 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -1010,7 +1010,9 @@ enum SMARTAI_TARGETS SMART_TARGET_OWNER_OR_SUMMONER = 23, // Unit's owner or summoner SMART_TARGET_THREAT_LIST = 24, // All units on creature's threat list SMART_TARGET_CLOSEST_ENEMY = 25, // maxDist - SMART_TARGET_END = 26 + SMART_TARGET_CLOSEST_FRIENDLY = 26, // maxDist + + SMART_TARGET_END = 27 }; struct SmartTarget @@ -1097,6 +1099,11 @@ struct SmartTarget uint32 maxDist; } closestAttackable; + struct + { + uint32 maxDist; + } closestFriendly; + struct { uint32 param1; -- cgit v1.2.3