Core/Spells: Reimplemented target type 106 as random point from points predefined in database
Port From (https://github.com/TrinityCore/TrinityCore/commit/2a51a6454912df635099572d07789a1d6789ff4d)
This commit is contained in:
@@ -2916,7 +2916,7 @@ namespace Framework.Constants
|
|||||||
UnitPassenger7 = 103,
|
UnitPassenger7 = 103,
|
||||||
UnitConeCasterToDestEnemy = 104,
|
UnitConeCasterToDestEnemy = 104,
|
||||||
UnitCasterAndPassengers = 105,
|
UnitCasterAndPassengers = 105,
|
||||||
DestChannelCaster = 106,
|
DestNearbyDb = 106,
|
||||||
DestNearbyEntry2 = 107,
|
DestNearbyEntry2 = 107,
|
||||||
GameobjectConeCasterToDestEnemy = 108,
|
GameobjectConeCasterToDestEnemy = 108,
|
||||||
GameobjectConeCasterToDestAlly = 109,
|
GameobjectConeCasterToDestAlly = 109,
|
||||||
|
|||||||
+19
-10
@@ -567,16 +567,6 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Targets.DestChannelCaster:
|
|
||||||
{
|
|
||||||
SpellDestination dest = new(channeledSpell.GetCaster());
|
|
||||||
if (m_spellInfo.HasAttribute(SpellAttr4.UseFacingFromSpell))
|
|
||||||
dest.Position.SetOrientation(spellEffectInfo.PositionFacing);
|
|
||||||
|
|
||||||
CallScriptDestinationTargetSelectHandlers(ref dest, spellEffectInfo.EffectIndex, targetType);
|
|
||||||
m_targets.SetDst(dest);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
Cypher.Assert(false, "Spell.SelectImplicitChannelTargets: received not implemented target type");
|
Cypher.Assert(false, "Spell.SelectImplicitChannelTargets: received not implemented target type");
|
||||||
break;
|
break;
|
||||||
@@ -1139,6 +1129,25 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Targets.DestNearbyDb:
|
||||||
|
{
|
||||||
|
var radiusBounds = spellEffectInfo.CalcRadiusBounds(m_caster, targetIndex, this);
|
||||||
|
List<WorldLocation> positionsInRange = new();
|
||||||
|
foreach (var position in Global.SpellMgr.GetSpellTargetPositions(m_spellInfo.Id, spellEffectInfo.EffectIndex))
|
||||||
|
if (m_caster.GetMapId() == position.GetMapId() && (radiusBounds == default || (!m_caster.IsInDist(position, radiusBounds.Item1) && m_caster.IsInDist(position, radiusBounds.Item2))))
|
||||||
|
positionsInRange.Add(position);
|
||||||
|
|
||||||
|
if (positionsInRange.Empty())
|
||||||
|
{
|
||||||
|
Log.outDebug(LogFilter.Spells, $"SPELL: unknown target coordinates for spell ID {m_spellInfo.Id}");
|
||||||
|
SendCastResult(SpellCastResult.NoValidTargets);
|
||||||
|
Finish(SpellCastResult.NoValidTargets);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest = new(positionsInRange.SelectRandom().GetPosition());
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
float dist = spellEffectInfo.CalcRadius(m_caster, targetIndex);
|
float dist = spellEffectInfo.CalcRadius(m_caster, targetIndex);
|
||||||
|
|||||||
@@ -4312,6 +4312,41 @@ namespace Game.Spells
|
|||||||
return radius;
|
return radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (float, float) CalcRadiusBounds(WorldObject caster, SpellTargetIndex targetIndex, Spell spell)
|
||||||
|
{
|
||||||
|
// TargetA -> TargetARadiusEntry
|
||||||
|
// TargetB -> TargetBRadiusEntry
|
||||||
|
// Aura effects have TargetARadiusEntry == TargetBRadiusEntry (mostly)
|
||||||
|
SpellRadiusRecord entry = TargetARadiusEntry;
|
||||||
|
if (targetIndex == SpellTargetIndex.TargetB && HasRadius(targetIndex))
|
||||||
|
entry = TargetBRadiusEntry;
|
||||||
|
|
||||||
|
(float, float) bounds = default;
|
||||||
|
if (entry == null)
|
||||||
|
return bounds;
|
||||||
|
|
||||||
|
bounds = (entry.RadiusMin, entry.RadiusMax);
|
||||||
|
|
||||||
|
if (caster != null)
|
||||||
|
{
|
||||||
|
Player modOwner = caster.GetSpellModOwner();
|
||||||
|
if (modOwner != null)
|
||||||
|
modOwner.ApplySpellMod(_spellInfo, SpellModOp.Radius, ref bounds.Item2, spell);
|
||||||
|
|
||||||
|
if (!_spellInfo.HasAttribute(SpellAttr9.NoMovementRadiusBonus))
|
||||||
|
{
|
||||||
|
Unit casterUnit = caster.ToUnit(); ;
|
||||||
|
if (casterUnit != null && Spell.CanIncreaseRangeByMovement(casterUnit))
|
||||||
|
{
|
||||||
|
bounds.Item1 = Math.Max(bounds.Item1 - 2.0f, 0.0f);
|
||||||
|
bounds.Item2 += 2.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
public SpellCastTargetFlags GetProvidedTargetMask()
|
public SpellCastTargetFlags GetProvidedTargetMask()
|
||||||
{
|
{
|
||||||
return SpellInfo.GetTargetFlagMask(TargetA.GetObjectType()) | SpellInfo.GetTargetFlagMask(TargetB.GetObjectType());
|
return SpellInfo.GetTargetFlagMask(TargetA.GetObjectType()) | SpellInfo.GetTargetFlagMask(TargetB.GetObjectType());
|
||||||
@@ -5123,7 +5158,7 @@ namespace Game.Spells
|
|||||||
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 103 TARGET_UNIT_PASSENGER_7
|
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 103 TARGET_UNIT_PASSENGER_7
|
||||||
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.Front), // 104 TARGET_UNIT_CONE_CASTER_TO_DEST_ENEMY
|
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.Front), // 104 TARGET_UNIT_CONE_CASTER_TO_DEST_ENEMY
|
||||||
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 105 TARGET_UNIT_CASTER_AND_PASSENGERS
|
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 105 TARGET_UNIT_CASTER_AND_PASSENGERS
|
||||||
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Channel, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 106 TARGET_DEST_CHANNEL_CASTER
|
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 106 TARGET_DEST_NEARBY_DB
|
||||||
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Nearby, SpellTargetCheckTypes.Entry, SpellTargetDirectionTypes.None), // 107 TARGET_DEST_NEARBY_ENTRY_2
|
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Nearby, SpellTargetCheckTypes.Entry, SpellTargetDirectionTypes.None), // 107 TARGET_DEST_NEARBY_ENTRY_2
|
||||||
new StaticData(SpellTargetObjectTypes.Gobj, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.Front), // 108 TARGET_GAMEOBJECT_CONE_CASTER_TO_DEST_ENEMY
|
new StaticData(SpellTargetObjectTypes.Gobj, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.Front), // 108 TARGET_GAMEOBJECT_CONE_CASTER_TO_DEST_ENEMY
|
||||||
new StaticData(SpellTargetObjectTypes.Gobj, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Ally, SpellTargetDirectionTypes.Front), // 109 TARGET_GAMEOBJECT_CONE_CASTER_TO_DEST_ALLY
|
new StaticData(SpellTargetObjectTypes.Gobj, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Ally, SpellTargetDirectionTypes.Front), // 109 TARGET_GAMEOBJECT_CONE_CASTER_TO_DEST_ALLY
|
||||||
|
|||||||
@@ -296,7 +296,12 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public WorldLocation GetSpellTargetPosition(uint spell_id, uint effIndex)
|
public WorldLocation GetSpellTargetPosition(uint spell_id, uint effIndex)
|
||||||
{
|
{
|
||||||
return mSpellTargetPositions.LookupByKey(new KeyValuePair<uint, uint>(spell_id, effIndex));
|
return mSpellTargetPositions.LookupByKey((spell_id, effIndex)).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<WorldLocation> GetSpellTargetPositions(uint spell_id, uint effIndex)
|
||||||
|
{
|
||||||
|
return mSpellTargetPositions.LookupByKey((spell_id, effIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SpellGroup> GetSpellSpellGroupMapBounds(uint spell_id)
|
public List<SpellGroup> GetSpellSpellGroupMapBounds(uint spell_id)
|
||||||
@@ -1006,21 +1011,20 @@ namespace Game.Entities
|
|||||||
|
|
||||||
mSpellTargetPositions.Clear(); // need for reload case
|
mSpellTargetPositions.Clear(); // need for reload case
|
||||||
|
|
||||||
// 0 1 2 3 4 5 6
|
// 0 1 2 3 4 5 6 7
|
||||||
SQLResult result = DB.World.Query("SELECT ID, EffectIndex, MapID, PositionX, PositionY, PositionZ, Orientation FROM spell_target_position");
|
SQLResult result = DB.World.Query("SELECT ID, EffectIndex, OrderIndex, MapID, PositionX, PositionY, PositionZ, Orientation FROM spell_target_position");
|
||||||
if (result.IsEmpty())
|
if (result.IsEmpty())
|
||||||
{
|
{
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 spell target coordinates. DB table `spell_target_position` is empty.");
|
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 spell target coordinates. DB table `spell_target_position` is empty.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint count = 0;
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
uint spellId = result.Read<uint>(0);
|
uint spellId = result.Read<uint>(0);
|
||||||
uint effIndex = result.Read<byte>(1);
|
uint effIndex = result.Read<byte>(1);
|
||||||
|
|
||||||
WorldLocation st = new(result.Read<uint>(2), result.Read<float>(3), result.Read<float>(4), result.Read<float>(5));
|
WorldLocation st = new(result.Read<uint>(3), result.Read<float>(4), result.Read<float>(5), result.Read<float>(6));
|
||||||
|
|
||||||
var mapEntry = CliDB.MapStorage.LookupByKey(st.GetMapId());
|
var mapEntry = CliDB.MapStorage.LookupByKey(st.GetMapId());
|
||||||
if (mapEntry == null)
|
if (mapEntry == null)
|
||||||
@@ -1048,38 +1052,39 @@ namespace Game.Entities
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.IsNull(6))
|
SpellEffectInfo spellEffectInfo = spellInfo.GetEffect(effIndex);
|
||||||
st.SetOrientation(result.Read<float>(6));
|
if (!result.IsNull(7))
|
||||||
|
st.SetOrientation(result.Read<float>(7));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// target facing is in degrees for 6484 & 9268...
|
// target facing is in degrees for 6484 & 9268...
|
||||||
if (spellInfo.GetEffect(effIndex).PositionFacing > 2 * MathF.PI)
|
if (spellEffectInfo.PositionFacing > 2 * MathF.PI)
|
||||||
st.SetOrientation(spellInfo.GetEffect(effIndex).PositionFacing * MathF.PI / 180);
|
st.SetOrientation(spellEffectInfo.PositionFacing * MathF.PI / 180);
|
||||||
else
|
else
|
||||||
st.SetOrientation(spellInfo.GetEffect(effIndex).PositionFacing);
|
st.SetOrientation(spellEffectInfo.PositionFacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasTarget(Targets target)
|
bool hasTarget(Targets target) => spellEffectInfo.TargetA.GetTarget() == target || spellEffectInfo.TargetB.GetTarget() == target;
|
||||||
|
|
||||||
|
if (!hasTarget(Targets.DestNearbyDb))
|
||||||
{
|
{
|
||||||
SpellEffectInfo spellEffectInfo = spellInfo.GetEffect(effIndex);
|
if (!hasTarget(Targets.DestDb) && !hasTarget(Targets.DestNearbyEntryOrDB))
|
||||||
return spellEffectInfo.TargetA.GetTarget() == target || spellEffectInfo.TargetB.GetTarget() == target;
|
{
|
||||||
}
|
Log.outError(LogFilter.Sql, $"Spell (Id: {spellId}, effIndex: {effIndex}) listed in `spell_target_position` does not have a target TARGET_DEST_DB or TARGET_DEST_NEARBY_DB or TARGET_DEST_NEARBY_ENTRY_OR_DB.");
|
||||||
|
continue;
|
||||||
if (hasTarget(Targets.DestDb) || hasTarget(Targets.DestNearbyEntryOrDB))
|
}
|
||||||
{
|
if (result.Read<uint>(2) != 0)
|
||||||
mSpellTargetPositions[(spellId, effIndex)] = st;
|
{
|
||||||
++count;
|
Log.outError(LogFilter.Sql, $"Spell (Id: {spellId}, effIndex: {effIndex}) listed in `spell_target_position` does not have a target TARGET_DEST_NEARBY_DB but lists multiple points, only one is allowed.");
|
||||||
}
|
continue;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
Log.outError(LogFilter.Sql, "Spell (Id: {0}, effIndex: {1}) listed in `spell_target_position` does not have target TARGET_DEST_DB (17).", spellId, effIndex);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mSpellTargetPositions.Add((spellId, effIndex), st);
|
||||||
}
|
}
|
||||||
while (result.NextRow());
|
while (result.NextRow());
|
||||||
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} spell teleport coordinates in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
Log.outInfo(LogFilter.ServerLoading, $"Loaded {mSpellTargetPositions.Count} spell teleport coordinates in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadSpellGroups()
|
public void LoadSpellGroups()
|
||||||
@@ -4942,7 +4947,7 @@ namespace Game.Entities
|
|||||||
Dictionary<uint, SpellLearnSkillNode> mSpellLearnSkills = new();
|
Dictionary<uint, SpellLearnSkillNode> mSpellLearnSkills = new();
|
||||||
MultiMap<uint, SpellLearnSpellNode> mSpellLearnSpells = new();
|
MultiMap<uint, SpellLearnSpellNode> mSpellLearnSpells = new();
|
||||||
MultiMap<uint, SpellLearnSpellNode> mSpellLearnedBySpells = new();
|
MultiMap<uint, SpellLearnSpellNode> mSpellLearnedBySpells = new();
|
||||||
Dictionary<(uint, uint), WorldLocation> mSpellTargetPositions = new();
|
MultiMap<(uint, uint), WorldLocation> mSpellTargetPositions = new();
|
||||||
MultiMap<uint, SpellGroup> mSpellSpellGroup = new();
|
MultiMap<uint, SpellGroup> mSpellSpellGroup = new();
|
||||||
MultiMap<SpellGroup, int> mSpellGroupSpell = new();
|
MultiMap<SpellGroup, int> mSpellGroupSpell = new();
|
||||||
Dictionary<SpellGroup, SpellGroupStackRule> mSpellGroupStack = new();
|
Dictionary<SpellGroup, SpellGroupStackRule> mSpellGroupStack = new();
|
||||||
|
|||||||
Reference in New Issue
Block a user