diff options
author | Traesh <Traesh@users.noreply.github.com> | 2021-08-15 11:09:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-15 11:09:46 +0200 |
commit | fb6761c273d518eae6bab72fc9c2a2b6f93eec83 (patch) | |
tree | c2dc8907691bf0da898a62448058df38892d9333 /src/server | |
parent | 4725941567f9dae583fc27b52b51a23aa84cd098 (diff) |
Core/Spells Implement targets 133, 134, 135 : TARGET_UNIT_LINE_CASTER_TO_DEST_*** (#26786)
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/game/Conditions/ConditionMgr.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Position.cpp | 10 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Position.h | 5 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 292 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 83 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 11 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 3 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.cpp | 1 |
10 files changed, 259 insertions, 157 deletions
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 10717ff302d..cb1fd600fa1 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -1759,6 +1759,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const case TARGET_SELECT_CATEGORY_CONE: case TARGET_SELECT_CATEGORY_AREA: case TARGET_SELECT_CATEGORY_TRAJ: + case TARGET_SELECT_CATEGORY_LINE: continue; default: break; @@ -1770,6 +1771,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const case TARGET_SELECT_CATEGORY_CONE: case TARGET_SELECT_CATEGORY_AREA: case TARGET_SELECT_CATEGORY_TRAJ: + case TARGET_SELECT_CATEGORY_LINE: continue; default: break; diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp index 6afdb283c1b..daffd7a9b52 100644 --- a/src/server/game/Entities/Object/Position.cpp +++ b/src/server/game/Entities/Object/Position.cpp @@ -154,7 +154,7 @@ bool Position::IsWithinDoubleVerticalCylinder(Position const* center, float radi return IsInDist2d(center, radius) && std::abs(verticalDelta) <= height; } -bool Position::HasInArc(float arc, Position const* obj, float border) const +bool Position::HasInArc(float arc, Position const* obj, float border, Optional<float> orientation) const { // always have self in arc if (obj == this) @@ -164,7 +164,7 @@ bool Position::HasInArc(float arc, Position const* obj, float border) const arc = NormalizeOrientation(arc); float angle = GetAngle(obj); - angle -= m_orientation; + angle -= orientation.is_initialized() ? *orientation : GetOrientation(); // move angle to range -pi ... +pi angle = NormalizeOrientation(angle); @@ -176,13 +176,13 @@ bool Position::HasInArc(float arc, Position const* obj, float border) const return ((angle >= lborder) && (angle <= rborder)); } -bool Position::HasInLine(Position const* pos, float objSize, float width) const +bool Position::HasInLine(Position const* pos, float objSize, float width, Optional<float> orientation) const { - if (!HasInArc(float(M_PI), pos)) + if (!HasInArc(float(M_PI), pos, 2.0f, orientation)) return false; width += objSize; - float angle = GetRelativeAngle(pos); + float angle = GetAngle(pos) - (orientation.is_initialized() ? *orientation : GetOrientation()); return std::fabs(std::sin(angle)) * GetExactDist2d(pos->GetPositionX(), pos->GetPositionY()) < width; } diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index 9f2218397e9..fbf9f87d753 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -19,6 +19,7 @@ #define Trinity_game_Position_h__ #include "Define.h" +#include "Optional.h" #include <string> #include <cmath> @@ -215,8 +216,8 @@ public: search using this relation: dist2d < radius && abs(dz) < height */ bool IsWithinDoubleVerticalCylinder(Position const* center, float radius, float height) const; - bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const; - bool HasInLine(Position const* pos, float objSize, float width) const; + bool HasInArc(float arcangle, Position const* pos, float border = 2.0f, Optional<float> orientation = Optional<float>()) const; + bool HasInLine(Position const* pos, float objSize, float width, Optional<float> orientation = Optional<float>()) const; std::string ToString() const; // modulos a radian orientation to the range of 0..2PI diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 6d79e1d5037..49a9d48cbe7 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -2418,152 +2418,152 @@ enum SpellImmunity // TARGET_[OBJECT_TYPE]_[REFERENCE_TYPE(skipped for caster)]_[SELECTION_TYPE(skipped for default)]_[additional specifiers(friendly, BACK_LEFT, etc.] enum Targets { - TARGET_UNIT_CASTER = 1, - TARGET_UNIT_NEARBY_ENEMY = 2, - TARGET_UNIT_NEARBY_PARTY = 3, - TARGET_UNIT_NEARBY_ALLY = 4, - TARGET_UNIT_PET = 5, - TARGET_UNIT_TARGET_ENEMY = 6, - TARGET_UNIT_SRC_AREA_ENTRY = 7, - TARGET_UNIT_DEST_AREA_ENTRY = 8, - TARGET_DEST_HOME = 9, - TARGET_UNIT_SRC_AREA_UNK_11 = 11, - TARGET_UNIT_SRC_AREA_ENEMY = 15, - TARGET_UNIT_DEST_AREA_ENEMY = 16, - TARGET_DEST_DB = 17, - TARGET_DEST_CASTER = 18, - TARGET_UNIT_CASTER_AREA_PARTY = 20, - TARGET_UNIT_TARGET_ALLY = 21, - TARGET_SRC_CASTER = 22, - TARGET_GAMEOBJECT_TARGET = 23, - TARGET_UNIT_CONE_ENEMY_24 = 24, - TARGET_UNIT_TARGET_ANY = 25, - TARGET_GAMEOBJECT_ITEM_TARGET = 26, - TARGET_UNIT_MASTER = 27, - TARGET_DEST_DYNOBJ_ENEMY = 28, - TARGET_DEST_DYNOBJ_ALLY = 29, - TARGET_UNIT_SRC_AREA_ALLY = 30, - TARGET_UNIT_DEST_AREA_ALLY = 31, - TARGET_DEST_CASTER_SUMMON = 32, // front left, doesn't use radius - TARGET_UNIT_SRC_AREA_PARTY = 33, - TARGET_UNIT_DEST_AREA_PARTY = 34, - TARGET_UNIT_TARGET_PARTY = 35, - TARGET_DEST_CASTER_UNK_36 = 36, - TARGET_UNIT_LASTTARGET_AREA_PARTY = 37, - TARGET_UNIT_NEARBY_ENTRY = 38, - TARGET_DEST_CASTER_FISHING = 39, - TARGET_GAMEOBJECT_NEARBY_ENTRY = 40, - TARGET_DEST_CASTER_FRONT_RIGHT = 41, - TARGET_DEST_CASTER_BACK_RIGHT = 42, - TARGET_DEST_CASTER_BACK_LEFT = 43, - TARGET_DEST_CASTER_FRONT_LEFT = 44, - TARGET_UNIT_TARGET_CHAINHEAL_ALLY = 45, - TARGET_DEST_NEARBY_ENTRY = 46, - TARGET_DEST_CASTER_FRONT = 47, - TARGET_DEST_CASTER_BACK = 48, - TARGET_DEST_CASTER_RIGHT = 49, - TARGET_DEST_CASTER_LEFT = 50, - TARGET_GAMEOBJECT_SRC_AREA = 51, - TARGET_GAMEOBJECT_DEST_AREA = 52, - TARGET_DEST_TARGET_ENEMY = 53, - TARGET_UNIT_CONE_ENEMY_54 = 54, - TARGET_DEST_CASTER_FRONT_LEAP = 55, // for a leap spell - TARGET_UNIT_CASTER_AREA_RAID = 56, - TARGET_UNIT_TARGET_RAID = 57, - TARGET_UNIT_NEARBY_RAID = 58, - TARGET_UNIT_CONE_ALLY = 59, - TARGET_UNIT_CONE_ENTRY = 60, - TARGET_UNIT_TARGET_AREA_RAID_CLASS = 61, - TARGET_UNK_62 = 62, - TARGET_DEST_TARGET_ANY = 63, - TARGET_DEST_TARGET_FRONT = 64, - TARGET_DEST_TARGET_BACK = 65, - TARGET_DEST_TARGET_RIGHT = 66, - TARGET_DEST_TARGET_LEFT = 67, - TARGET_DEST_TARGET_FRONT_RIGHT = 68, - TARGET_DEST_TARGET_BACK_RIGHT = 69, - TARGET_DEST_TARGET_BACK_LEFT = 70, - TARGET_DEST_TARGET_FRONT_LEFT = 71, - TARGET_DEST_CASTER_RANDOM = 72, - TARGET_DEST_CASTER_RADIUS = 73, - TARGET_DEST_TARGET_RANDOM = 74, - TARGET_DEST_TARGET_RADIUS = 75, - TARGET_DEST_CHANNEL_TARGET = 76, - TARGET_UNIT_CHANNEL_TARGET = 77, - TARGET_DEST_DEST_FRONT = 78, - TARGET_DEST_DEST_BACK = 79, - TARGET_DEST_DEST_RIGHT = 80, - TARGET_DEST_DEST_LEFT = 81, - TARGET_DEST_DEST_FRONT_RIGHT = 82, - TARGET_DEST_DEST_BACK_RIGHT = 83, - TARGET_DEST_DEST_BACK_LEFT = 84, - TARGET_DEST_DEST_FRONT_LEFT = 85, - TARGET_DEST_DEST_RANDOM = 86, - TARGET_DEST_DEST = 87, - TARGET_DEST_DYNOBJ_NONE = 88, - TARGET_DEST_TRAJ = 89, - TARGET_UNIT_TARGET_MINIPET = 90, - TARGET_DEST_DEST_RADIUS = 91, - TARGET_UNIT_SUMMONER = 92, - TARGET_CORPSE_SRC_AREA_ENEMY = 93, // NYI - TARGET_UNIT_VEHICLE = 94, - TARGET_UNIT_TARGET_PASSENGER = 95, - TARGET_UNIT_PASSENGER_0 = 96, - TARGET_UNIT_PASSENGER_1 = 97, - TARGET_UNIT_PASSENGER_2 = 98, - TARGET_UNIT_PASSENGER_3 = 99, - TARGET_UNIT_PASSENGER_4 = 100, - TARGET_UNIT_PASSENGER_5 = 101, - TARGET_UNIT_PASSENGER_6 = 102, - TARGET_UNIT_PASSENGER_7 = 103, - TARGET_UNIT_CONE_ENEMY_104 = 104, - TARGET_UNIT_UNK_105 = 105, // 1 spell - TARGET_DEST_CHANNEL_CASTER = 106, - TARGET_UNK_DEST_AREA_UNK_107 = 107, // not enough info - only generic spells avalible - TARGET_GAMEOBJECT_CONE_108 = 108, - TARGET_GAMEOBJECT_CONE_109 = 109, - TARGET_UNIT_CONE_ENTRY_110 = 110, - TARGET_UNK_111 = 111, - TARGET_UNK_112 = 112, - TARGET_UNK_113 = 113, - TARGET_UNK_114 = 114, - TARGET_UNK_115 = 115, - TARGET_UNK_116 = 116, - TARGET_UNK_117 = 117, - TARGET_UNIT_TARGET_ALLY_OR_RAID = 118, // If target is in your party or raid, all party and raid members will be affected - TARGET_CORPSE_SRC_AREA_RAID = 119, - TARGET_UNIT_CASTER_AND_SUMMONS = 120, - TARGET_UNK_121 = 121, - TARGET_UNIT_AREA_THREAT_LIST = 122, // any unit on threat list - TARGET_UNIT_AREA_TAP_LIST = 123, - TARGET_UNK_124 = 124, - TARGET_DEST_CASTER_GROUND = 125, - TARGET_UNK_126 = 126, - TARGET_UNK_127 = 127, - TARGET_UNK_128 = 128, - TARGET_UNIT_CONE_ENTRY_129 = 129, - TARGET_UNK_130 = 130, - TARGET_DEST_SUMMONER = 131, - TARGET_DEST_TARGET_ALLY = 132, - TARGET_UNK_133 = 133, - TARGET_UNK_134 = 134, - TARGET_UNK_135 = 135, - TARGET_UNK_136 = 136, - TARGET_UNK_137 = 137, - TARGET_UNK_138 = 138, - TARGET_UNK_139 = 139, - TARGET_UNK_140 = 140, - TARGET_UNK_141 = 141, - TARGET_UNK_142 = 142, - TARGET_UNK_143 = 143, - TARGET_UNK_144 = 144, - TARGET_UNK_145 = 145, - TARGET_UNK_146 = 146, - TARGET_UNK_147 = 147, - TARGET_UNK_148 = 148, - TARGET_UNK_149 = 149, - TARGET_UNIT_OWN_CRITTER = 150, // own battle pet from UNIT_FIELD_CRITTER - TARGET_UNK_151 = 151, + TARGET_UNIT_CASTER = 1, + TARGET_UNIT_NEARBY_ENEMY = 2, + TARGET_UNIT_NEARBY_PARTY = 3, + TARGET_UNIT_NEARBY_ALLY = 4, + TARGET_UNIT_PET = 5, + TARGET_UNIT_TARGET_ENEMY = 6, + TARGET_UNIT_SRC_AREA_ENTRY = 7, + TARGET_UNIT_DEST_AREA_ENTRY = 8, + TARGET_DEST_HOME = 9, + TARGET_UNIT_SRC_AREA_UNK_11 = 11, + TARGET_UNIT_SRC_AREA_ENEMY = 15, + TARGET_UNIT_DEST_AREA_ENEMY = 16, + TARGET_DEST_DB = 17, + TARGET_DEST_CASTER = 18, + TARGET_UNIT_CASTER_AREA_PARTY = 20, + TARGET_UNIT_TARGET_ALLY = 21, + TARGET_SRC_CASTER = 22, + TARGET_GAMEOBJECT_TARGET = 23, + TARGET_UNIT_CONE_ENEMY_24 = 24, + TARGET_UNIT_TARGET_ANY = 25, + TARGET_GAMEOBJECT_ITEM_TARGET = 26, + TARGET_UNIT_MASTER = 27, + TARGET_DEST_DYNOBJ_ENEMY = 28, + TARGET_DEST_DYNOBJ_ALLY = 29, + TARGET_UNIT_SRC_AREA_ALLY = 30, + TARGET_UNIT_DEST_AREA_ALLY = 31, + TARGET_DEST_CASTER_SUMMON = 32, // front left, doesn't use radius + TARGET_UNIT_SRC_AREA_PARTY = 33, + TARGET_UNIT_DEST_AREA_PARTY = 34, + TARGET_UNIT_TARGET_PARTY = 35, + TARGET_DEST_CASTER_UNK_36 = 36, + TARGET_UNIT_LASTTARGET_AREA_PARTY = 37, + TARGET_UNIT_NEARBY_ENTRY = 38, + TARGET_DEST_CASTER_FISHING = 39, + TARGET_GAMEOBJECT_NEARBY_ENTRY = 40, + TARGET_DEST_CASTER_FRONT_RIGHT = 41, + TARGET_DEST_CASTER_BACK_RIGHT = 42, + TARGET_DEST_CASTER_BACK_LEFT = 43, + TARGET_DEST_CASTER_FRONT_LEFT = 44, + TARGET_UNIT_TARGET_CHAINHEAL_ALLY = 45, + TARGET_DEST_NEARBY_ENTRY = 46, + TARGET_DEST_CASTER_FRONT = 47, + TARGET_DEST_CASTER_BACK = 48, + TARGET_DEST_CASTER_RIGHT = 49, + TARGET_DEST_CASTER_LEFT = 50, + TARGET_GAMEOBJECT_SRC_AREA = 51, + TARGET_GAMEOBJECT_DEST_AREA = 52, + TARGET_DEST_TARGET_ENEMY = 53, + TARGET_UNIT_CONE_ENEMY_54 = 54, + TARGET_DEST_CASTER_FRONT_LEAP = 55, // for a leap spell + TARGET_UNIT_CASTER_AREA_RAID = 56, + TARGET_UNIT_TARGET_RAID = 57, + TARGET_UNIT_NEARBY_RAID = 58, + TARGET_UNIT_CONE_ALLY = 59, + TARGET_UNIT_CONE_ENTRY = 60, + TARGET_UNIT_TARGET_AREA_RAID_CLASS = 61, + TARGET_UNK_62 = 62, + TARGET_DEST_TARGET_ANY = 63, + TARGET_DEST_TARGET_FRONT = 64, + TARGET_DEST_TARGET_BACK = 65, + TARGET_DEST_TARGET_RIGHT = 66, + TARGET_DEST_TARGET_LEFT = 67, + TARGET_DEST_TARGET_FRONT_RIGHT = 68, + TARGET_DEST_TARGET_BACK_RIGHT = 69, + TARGET_DEST_TARGET_BACK_LEFT = 70, + TARGET_DEST_TARGET_FRONT_LEFT = 71, + TARGET_DEST_CASTER_RANDOM = 72, + TARGET_DEST_CASTER_RADIUS = 73, + TARGET_DEST_TARGET_RANDOM = 74, + TARGET_DEST_TARGET_RADIUS = 75, + TARGET_DEST_CHANNEL_TARGET = 76, + TARGET_UNIT_CHANNEL_TARGET = 77, + TARGET_DEST_DEST_FRONT = 78, + TARGET_DEST_DEST_BACK = 79, + TARGET_DEST_DEST_RIGHT = 80, + TARGET_DEST_DEST_LEFT = 81, + TARGET_DEST_DEST_FRONT_RIGHT = 82, + TARGET_DEST_DEST_BACK_RIGHT = 83, + TARGET_DEST_DEST_BACK_LEFT = 84, + TARGET_DEST_DEST_FRONT_LEFT = 85, + TARGET_DEST_DEST_RANDOM = 86, + TARGET_DEST_DEST = 87, + TARGET_DEST_DYNOBJ_NONE = 88, + TARGET_DEST_TRAJ = 89, + TARGET_UNIT_TARGET_MINIPET = 90, + TARGET_DEST_DEST_RADIUS = 91, + TARGET_UNIT_SUMMONER = 92, + TARGET_CORPSE_SRC_AREA_ENEMY = 93, // NYI + TARGET_UNIT_VEHICLE = 94, + TARGET_UNIT_TARGET_PASSENGER = 95, + TARGET_UNIT_PASSENGER_0 = 96, + TARGET_UNIT_PASSENGER_1 = 97, + TARGET_UNIT_PASSENGER_2 = 98, + TARGET_UNIT_PASSENGER_3 = 99, + TARGET_UNIT_PASSENGER_4 = 100, + TARGET_UNIT_PASSENGER_5 = 101, + TARGET_UNIT_PASSENGER_6 = 102, + TARGET_UNIT_PASSENGER_7 = 103, + TARGET_UNIT_CONE_ENEMY_104 = 104, + TARGET_UNIT_UNK_105 = 105, // 1 spell + TARGET_DEST_CHANNEL_CASTER = 106, + TARGET_UNK_DEST_AREA_UNK_107 = 107, // not enough info - only generic spells avalible + TARGET_GAMEOBJECT_CONE_108 = 108, + TARGET_GAMEOBJECT_CONE_109 = 109, + TARGET_UNIT_CONE_ENTRY_110 = 110, + TARGET_UNK_111 = 111, + TARGET_UNK_112 = 112, + TARGET_UNK_113 = 113, + TARGET_UNK_114 = 114, + TARGET_UNK_115 = 115, + TARGET_UNK_116 = 116, + TARGET_UNK_117 = 117, + TARGET_UNIT_TARGET_ALLY_OR_RAID = 118, // If target is in your party or raid, all party and raid members will be affected + TARGET_CORPSE_SRC_AREA_RAID = 119, + TARGET_UNIT_CASTER_AND_SUMMONS = 120, + TARGET_UNK_121 = 121, + TARGET_UNIT_AREA_THREAT_LIST = 122, // any unit on threat list + TARGET_UNIT_AREA_TAP_LIST = 123, + TARGET_UNK_124 = 124, + TARGET_DEST_CASTER_GROUND = 125, + TARGET_UNK_126 = 126, + TARGET_UNK_127 = 127, + TARGET_UNK_128 = 128, + TARGET_UNIT_CONE_ENTRY_129 = 129, + TARGET_UNK_130 = 130, + TARGET_DEST_SUMMONER = 131, + TARGET_DEST_TARGET_ALLY = 132, + TARGET_UNIT_LINE_CASTER_TO_DEST_ALLY = 133, + TARGET_UNIT_LINE_CASTER_TO_DEST_ENEMY = 134, + TARGET_UNIT_LINE_CASTER_TO_DEST = 135, + TARGET_UNK_136 = 136, + TARGET_UNK_137 = 137, + TARGET_UNK_138 = 138, + TARGET_UNK_139 = 139, + TARGET_UNK_140 = 140, + TARGET_UNK_141 = 141, + TARGET_UNK_142 = 142, + TARGET_UNK_143 = 143, + TARGET_UNK_144 = 144, + TARGET_UNK_145 = 145, + TARGET_UNK_146 = 146, + TARGET_UNK_147 = 147, + TARGET_UNK_148 = 148, + TARGET_UNK_149 = 149, + TARGET_UNIT_OWN_CRITTER = 150, // own battle pet from UNIT_FIELD_CRITTER + TARGET_UNK_151 = 151, TOTAL_SPELL_TARGETS }; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index b62aaf65bc0..d5454d9065e 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -852,6 +852,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar case TARGET_SELECT_CATEGORY_NEARBY: case TARGET_SELECT_CATEGORY_CONE: case TARGET_SELECT_CATEGORY_AREA: + case TARGET_SELECT_CATEGORY_LINE: // targets for effect already selected if (effectMask & processedEffectMask) return; @@ -900,6 +901,9 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar SelectImplicitTrajTargets(effIndex, targetType); break; + case TARGET_SELECT_CATEGORY_LINE: + SelectImplicitLineTargets(effIndex, targetType, effectMask); + break; case TARGET_SELECT_CATEGORY_DEFAULT: switch (targetType.GetObjectType()) { @@ -1731,6 +1735,69 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge veh->SetLastShootPos(*m_targets.GetDstPos()); } +void Spell::SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +{ + std::list<WorldObject*> targets; + SpellTargetObjectTypes objectType = targetType.GetObjectType(); + SpellTargetCheckTypes selectionType = targetType.GetCheckType(); + SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); + if (!effect) + return; + + Position const* dst = nullptr; + switch (targetType.GetReferenceType()) + { + case TARGET_REFERENCE_TYPE_SRC: + dst = m_targets.GetSrcPos(); + break; + case TARGET_REFERENCE_TYPE_DEST: + dst = m_targets.GetDstPos(); + break; + case TARGET_REFERENCE_TYPE_CASTER: + dst = m_caster; + break; + case TARGET_REFERENCE_TYPE_TARGET: + dst = m_targets.GetUnitTarget(); + break; + default: + ASSERT(false, "Spell::SelectImplicitLineTargets: received not implemented target reference type"); + return; + } + + ConditionContainer* condList = effect->ImplicitTargetConditions; + float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod; + + if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList)) + { + Trinity::WorldObjectSpellLineTargetCheck check(m_caster, dst, m_spellInfo->Width ? m_spellInfo->Width : m_caster->GetCombatReach(), radius, m_caster, m_spellInfo, selectionType, condList, objectType); + Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellLineTargetCheck> searcher(m_caster, targets, check, containerTypeMask); + SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellLineTargetCheck>>(searcher, containerTypeMask, m_caster, m_caster, radius); + + CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + + if (!targets.empty()) + { + // Other special target selection goes here + if (uint32 maxTargets = m_spellValue->MaxAffectedTargets) + { + if (maxTargets < targets.size()) + { + targets.sort(Trinity::ObjectDistanceOrderPred(m_caster)); + targets.resize(maxTargets); + } + } + + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + { + if (Unit* unit = (*itr)->ToUnit()) + AddUnitTarget(unit, effMask, false); + else if (GameObject* gObjTarget = (*itr)->ToGameObject()) + AddGOTarget(gObjTarget, effMask); + } + } + } +} + void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) { // special case for SPELL_EFFECT_SUMMON_RAF_FRIEND and SPELL_EFFECT_SUMMON_PLAYER @@ -8181,6 +8248,22 @@ bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target) return WorldObjectSpellTargetCheck::operator ()(target); } +WorldObjectSpellLineTargetCheck::WorldObjectSpellLineTargetCheck(Position const* srcPosition, Position const* dstPosition, float lineWidth, float range, Unit* caster, + SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer* condList, SpellTargetObjectTypes objectType) + : WorldObjectSpellAreaTargetCheck(range, caster, caster, caster, spellInfo, selectionType, condList, objectType), _srcPosition(srcPosition), _dstPosition(dstPosition), _lineWidth(lineWidth) { } + +bool WorldObjectSpellLineTargetCheck::operator()(WorldObject* target) +{ + float angle = _caster->GetOrientation(); + if (*_srcPosition != *_dstPosition) + angle = _srcPosition->GetAngle(_dstPosition); + + if (!_caster->HasInLine(target, target->GetCombatReach(), _lineWidth, angle)) + return false; + + return WorldObjectSpellTargetCheck::operator ()(target); +} + } //namespace Trinity SpellCastVisual::operator UF::SpellCastVisual() const diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index cce4c750358..adaa408b65c 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -513,6 +513,7 @@ class TC_GAME_API Spell void SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); void SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask); void SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); + void SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); void SelectEffectTypeImplicitTargets(uint32 effIndex); @@ -966,6 +967,16 @@ namespace Trinity SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer* condList, SpellTargetObjectTypes objectType); bool operator()(WorldObject* target); }; + + struct TC_GAME_API WorldObjectSpellLineTargetCheck : public WorldObjectSpellAreaTargetCheck + { + Position const* _srcPosition; + Position const* _dstPosition; + float _lineWidth; + WorldObjectSpellLineTargetCheck(Position const* srcPosition, Position const* dstPosition, float lineWidth, float range, Unit* caster, + SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer* condList, SpellTargetObjectTypes objectType); + bool operator()(WorldObject* target); + }; } typedef void(Spell::*pEffect)(SpellEffIndex effIndex); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 9bca5fcf1c0..bbde23941f9 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -350,9 +350,9 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 130 {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 131 TARGET_DEST_SUMMONER {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 132 TARGET_DEST_TARGET_ALLY - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 133 - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 134 - {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 135 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_LINE, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 133 TARGET_UNIT_LINE_CASTER_TO_DEST_ALLY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_LINE, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 134 TARGET_UNIT_LINE_CASTER_TO_DEST_ENEMY + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_LINE, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 135 TARGET_UNIT_LINE_CASTER_TO_DEST {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 136 {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 137 {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 138 diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 9e4265efac9..f4bd559d494 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -86,7 +86,8 @@ enum SpellTargetSelectionCategories TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CATEGORY_AREA, - TARGET_SELECT_CATEGORY_TRAJ + TARGET_SELECT_CATEGORY_TRAJ, + TARGET_SELECT_CATEGORY_LINE }; enum SpellTargetReferenceTypes diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index c7df86abfe5..8422ff6360c 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -4553,6 +4553,9 @@ void SpellMgr::LoadSpellInfoCorrections() if (spellInfo->ActiveIconFileDataId == 135754) // flight spellInfo->Attributes |= SPELL_ATTR0_PASSIVE; + + if (spellInfo->IsSingleTarget()) + spellInfo->MaxAffectedTargets = 1; } if (SummonPropertiesEntry* properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(121))) diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 29d559cf0be..7213776011f 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -286,6 +286,7 @@ bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 eff return true; case TARGET_SELECT_CATEGORY_CONE: // AREA case TARGET_SELECT_CATEGORY_AREA: // AREA + case TARGET_SELECT_CATEGORY_LINE: // AREA return area; case TARGET_SELECT_CATEGORY_DEFAULT: switch (targetInfo.GetObjectType()) |