Core/Object: Range check vol. 2
Port From (https://github.com/TrinityCore/TrinityCore/commit/a13a765610d964a3aa1bab1b41331c05e24a1f78)
This commit is contained in:
@@ -1505,7 +1505,8 @@ namespace Framework.Constants
|
|||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
Item = 1,
|
Item = 1,
|
||||||
Skill = 2
|
Skill = 2,
|
||||||
|
Spell = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum LockType
|
public enum LockType
|
||||||
|
|||||||
@@ -2258,7 +2258,7 @@ namespace Game.Entities
|
|||||||
return localRotation;
|
return localRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsAtInteractDistance(Player player, SpellInfo spell)
|
public bool IsAtInteractDistance(Player player, SpellInfo spell = null)
|
||||||
{
|
{
|
||||||
if (spell != null || (spell = GetSpellForLock(player)) != null)
|
if (spell != null || (spell = GetSpellForLock(player)) != null)
|
||||||
{
|
{
|
||||||
@@ -2267,52 +2267,11 @@ namespace Game.Entities
|
|||||||
if (GetGoType() == GameObjectTypes.SpellFocus)
|
if (GetGoType() == GameObjectTypes.SpellFocus)
|
||||||
return maxRange * maxRange >= GetExactDistSq(player);
|
return maxRange * maxRange >= GetExactDistSq(player);
|
||||||
|
|
||||||
var displayInfo = CliDB.GameObjectDisplayInfoStorage.LookupByKey(GetGoInfo().displayId);
|
if (CliDB.GameObjectDisplayInfoStorage.ContainsKey(GetGoInfo().displayId))
|
||||||
if (displayInfo != null)
|
|
||||||
return IsAtInteractDistance(player, maxRange);
|
return IsAtInteractDistance(player, maxRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
float distance;
|
return IsAtInteractDistance(player, GetInteractionDistance());
|
||||||
switch (GetGoType())
|
|
||||||
{
|
|
||||||
case GameObjectTypes.AreaDamage:
|
|
||||||
distance = 0.0f;
|
|
||||||
break;
|
|
||||||
case GameObjectTypes.QuestGiver:
|
|
||||||
case GameObjectTypes.Text:
|
|
||||||
case GameObjectTypes.FlagStand:
|
|
||||||
case GameObjectTypes.FlagDrop:
|
|
||||||
case GameObjectTypes.MiniGame:
|
|
||||||
distance = 5.5555553f;
|
|
||||||
break;
|
|
||||||
case GameObjectTypes.Binder:
|
|
||||||
distance = 10.0f;
|
|
||||||
break;
|
|
||||||
case GameObjectTypes.Chair:
|
|
||||||
case GameObjectTypes.BarberChair:
|
|
||||||
distance = 3.0f;
|
|
||||||
break;
|
|
||||||
case GameObjectTypes.FishingNode:
|
|
||||||
distance = 100.0f;
|
|
||||||
break;
|
|
||||||
case GameObjectTypes.Camera:
|
|
||||||
case GameObjectTypes.MapObject:
|
|
||||||
case GameObjectTypes.DungeonDifficulty:
|
|
||||||
case GameObjectTypes.DestructibleBuilding:
|
|
||||||
case GameObjectTypes.Door:
|
|
||||||
default:
|
|
||||||
distance = 5.0f;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Following values are not blizzlike
|
|
||||||
case GameObjectTypes.Mailbox:
|
|
||||||
// Successful mailbox interaction is rather critical to the client, failing it will start a minute-long cooldown until the next mail query may be executed.
|
|
||||||
// And since movement info update is not sent with mailbox interaction query, server may find the player outside of interaction range. Thus we increase it.
|
|
||||||
distance = 10.0f; // 5.0f is blizzlike
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return IsAtInteractDistance(player, distance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsAtInteractDistance(Position pos, float radius)
|
bool IsAtInteractDistance(Position pos, float radius)
|
||||||
@@ -2329,17 +2288,22 @@ namespace Game.Entities
|
|||||||
float maxY = displayInfo.GeoBoxMax.Y * scale + radius;
|
float maxY = displayInfo.GeoBoxMax.Y * scale + radius;
|
||||||
float maxZ = displayInfo.GeoBoxMax.Z * scale + radius;
|
float maxZ = displayInfo.GeoBoxMax.Z * scale + radius;
|
||||||
|
|
||||||
Quaternion localRotation = GetLocalRotation();
|
Quaternion worldRotation = GetLocalRotation();
|
||||||
|
|
||||||
//Todo Test this. Needs checked.
|
//Todo Test this. Needs checked.
|
||||||
var worldSpaceBox = MathFunctions.toWorldSpace(Matrix4x4.CreateFromQuaternion(localRotation), new Vector3(GetPositionX(), GetPositionY(), GetPositionZ()), new Box(new Vector3(minX, minY, minZ), new Vector3(maxX, maxY, maxZ)));
|
var worldSpaceBox = MathFunctions.toWorldSpace(Matrix4x4.CreateFromQuaternion(worldRotation), new Vector3(GetPositionX(), GetPositionY(), GetPositionZ()), new Box(new Vector3(minX, minY, minZ), new Vector3(maxX, maxY, maxZ)));
|
||||||
return worldSpaceBox.Contains(new Vector3(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()));
|
return worldSpaceBox.Contains(new Vector3(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetExactDist(pos) <= radius;
|
return GetExactDist(pos) <= radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellInfo GetSpellForLock(Player player)
|
public bool IsWithinDistInMap(Player player)
|
||||||
|
{
|
||||||
|
return IsInMap(player) && IsInPhase(player) && IsAtInteractDistance(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpellInfo GetSpellForLock(Player player)
|
||||||
{
|
{
|
||||||
if (!player)
|
if (!player)
|
||||||
return null;
|
return null;
|
||||||
@@ -2357,7 +2321,7 @@ namespace Game.Entities
|
|||||||
if (lockEntry.LockType[i] == 0)
|
if (lockEntry.LockType[i] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (lockEntry.LockType[i] == (byte)LockKeyType.Skill)
|
if (lockEntry.LockType[i] == (byte)LockKeyType.Spell)
|
||||||
{
|
{
|
||||||
SpellInfo spell = Global.SpellMgr.GetSpellInfo((uint)lockEntry.Index[i], GetMap().GetDifficultyID());
|
SpellInfo spell = Global.SpellMgr.GetSpellInfo((uint)lockEntry.Index[i], GetMap().GetDifficultyID());
|
||||||
if (spell != null)
|
if (spell != null)
|
||||||
@@ -2807,14 +2771,33 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
switch (GetGoType())
|
switch (GetGoType())
|
||||||
{
|
{
|
||||||
// @todo find out how the client calculates the maximal usage distance to spellless working
|
case GameObjectTypes.AreaDamage:
|
||||||
// gameobjects like guildbanks and mailboxes - 10.0 is a just an abitrary choosen number
|
return 0.0f;
|
||||||
|
case GameObjectTypes.QuestGiver:
|
||||||
|
case GameObjectTypes.Text:
|
||||||
|
case GameObjectTypes.FlagStand:
|
||||||
|
case GameObjectTypes.FlagDrop:
|
||||||
|
case GameObjectTypes.MiniGame:
|
||||||
|
return 5.5555553f;
|
||||||
|
case GameObjectTypes.Chair:
|
||||||
|
case GameObjectTypes.BarberChair:
|
||||||
|
return 3.0f;
|
||||||
|
case GameObjectTypes.FishingNode:
|
||||||
|
return 100.0f;
|
||||||
|
case GameObjectTypes.FishingHole:
|
||||||
|
return 20.0f + SharedConst.ContactDistance; // max spell range
|
||||||
|
case GameObjectTypes.Camera:
|
||||||
|
case GameObjectTypes.MapObject:
|
||||||
|
case GameObjectTypes.DungeonDifficulty:
|
||||||
|
case GameObjectTypes.DestructibleBuilding:
|
||||||
|
case GameObjectTypes.Door:
|
||||||
|
return 5.0f;
|
||||||
|
// Following values are not blizzlike
|
||||||
case GameObjectTypes.GuildBank:
|
case GameObjectTypes.GuildBank:
|
||||||
case GameObjectTypes.Mailbox:
|
case GameObjectTypes.Mailbox:
|
||||||
return 10.0f;
|
// Successful mailbox interaction is rather critical to the client, failing it will start a minute-long cooldown until the next mail query may be executed.
|
||||||
case GameObjectTypes.FishingHole:
|
// And since movement info update is not sent with mailbox interaction query, server may find the player outside of interaction range. Thus we increase it.
|
||||||
case GameObjectTypes.FishingNode:
|
return 10.0f; // 5.0f is blizzlike
|
||||||
return 20.0f + SharedConst.ContactDistance; // max spell range
|
|
||||||
default:
|
default:
|
||||||
return SharedConst.InteractionDistance;
|
return SharedConst.InteractionDistance;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6029,7 +6029,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lootType != LootType.Fishinghole && ((lootType != LootType.Fishing && lootType != LootType.FishingJunk) || go.GetOwnerGUID() != GetGUID()) && !go.IsWithinDistInMap(this, SharedConst.InteractionDistance))
|
if (lootType != LootType.Fishinghole && ((lootType != LootType.Fishing && lootType != LootType.FishingJunk) || go.GetOwnerGUID() != GetGUID()) && !go.IsWithinDistInMap(this))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (lootType == LootType.Corpse && go.GetRespawnTime() != 0 && go.IsSpawnedByDefault())
|
if (lootType == LootType.Corpse && go.GetRespawnTime() != 0 && go.IsSpawnedByDefault())
|
||||||
|
|||||||
@@ -5405,7 +5405,7 @@ namespace Game.Entities
|
|||||||
if (go == null)
|
if (go == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (!go.IsWithinDistInMap(this, go.GetInteractionDistance()))
|
if (!go.IsWithinDistInMap(this))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return go;
|
return go;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace Game
|
|||||||
GameObject go = player.GetMap().GetGameObject(lguid);
|
GameObject go = player.GetMap().GetGameObject(lguid);
|
||||||
|
|
||||||
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
|
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
|
||||||
if (!go || ((go.GetOwnerGUID() != player.GetGUID() && go.GetGoType() != GameObjectTypes.FishingHole) && !go.IsWithinDistInMap(player, SharedConst.InteractionDistance)))
|
if (!go || ((go.GetOwnerGUID() != player.GetGUID() && go.GetGoType() != GameObjectTypes.FishingHole) && !go.IsWithinDistInMap(player)))
|
||||||
{
|
{
|
||||||
player.SendLootRelease(lguid);
|
player.SendLootRelease(lguid);
|
||||||
continue;
|
continue;
|
||||||
@@ -129,7 +129,7 @@ namespace Game
|
|||||||
GameObject go = player.GetMap().GetGameObject(guid);
|
GameObject go = player.GetMap().GetGameObject(guid);
|
||||||
|
|
||||||
// do not check distance for GO if player is the owner of it (ex. fishing bobber)
|
// do not check distance for GO if player is the owner of it (ex. fishing bobber)
|
||||||
if (go && ((go.GetOwnerGUID() == player.GetGUID() || go.IsWithinDistInMap(player, SharedConst.InteractionDistance))))
|
if (go && (go.GetOwnerGUID() == player.GetGUID() || go.IsWithinDistInMap(player)))
|
||||||
loot = go.loot;
|
loot = go.loot;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -331,7 +331,7 @@ namespace Game
|
|||||||
GameObject go = player.GetMap().GetGameObject(lguid);
|
GameObject go = player.GetMap().GetGameObject(lguid);
|
||||||
|
|
||||||
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
|
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
|
||||||
if (!go || ((go.GetOwnerGUID() != player.GetGUID() && go.GetGoType() != GameObjectTypes.FishingHole) && !go.IsWithinDistInMap(player, SharedConst.InteractionDistance)))
|
if (!go || ((go.GetOwnerGUID() != player.GetGUID() && go.GetGoType() != GameObjectTypes.FishingHole) && !go.IsWithinDistInMap(player)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
loot = go.loot;
|
loot = go.loot;
|
||||||
|
|||||||
@@ -297,9 +297,36 @@ namespace Game
|
|||||||
caster = GetPlayer();
|
caster = GetPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TriggerCastFlags triggerFlag = TriggerCastFlags.None;
|
||||||
|
|
||||||
|
// client provided targets
|
||||||
|
SpellCastTargets targets = new(caster, cast.Cast);
|
||||||
|
|
||||||
// check known spell or raid marker spell (which not requires player to know it)
|
// check known spell or raid marker spell (which not requires player to know it)
|
||||||
if (caster.IsTypeId(TypeId.Player) && !caster.ToPlayer().HasActiveSpell(spellInfo.Id) && !spellInfo.HasEffect(SpellEffectName.ChangeRaidMarker) && !spellInfo.HasAttribute(SpellAttr8.RaidMarker))
|
if (caster.IsTypeId(TypeId.Player) && !caster.ToPlayer().HasActiveSpell(spellInfo.Id) && !spellInfo.HasEffect(SpellEffectName.ChangeRaidMarker) && !spellInfo.HasAttribute(SpellAttr8.RaidMarker))
|
||||||
return;
|
{
|
||||||
|
bool allow = false;
|
||||||
|
|
||||||
|
|
||||||
|
// allow casting of unknown spells for special lock cases
|
||||||
|
GameObject go = targets.GetGOTarget();
|
||||||
|
if (go != null)
|
||||||
|
if (go.GetSpellForLock(caster.ToPlayer()) == spellInfo)
|
||||||
|
allow = true;
|
||||||
|
|
||||||
|
// TODO: Preparation for #23204
|
||||||
|
// allow casting of spells triggered by clientside periodic trigger auras
|
||||||
|
/*
|
||||||
|
if (caster->HasAuraTypeWithTriggerSpell(SPELL_AURA_PERIODIC_TRIGGER_SPELL_FROM_CLIENT, spellId))
|
||||||
|
{
|
||||||
|
allow = true;
|
||||||
|
triggerFlag = TRIGGERED_FULL_MASK;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!allow)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check possible spell cast overrides
|
// Check possible spell cast overrides
|
||||||
spellInfo = caster.GetCastSpellInfo(spellInfo);
|
spellInfo = caster.GetCastSpellInfo(spellInfo);
|
||||||
@@ -308,9 +335,6 @@ namespace Game
|
|||||||
if (GetPlayer().IsPossessing())
|
if (GetPlayer().IsPossessing())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// client provided targets
|
|
||||||
SpellCastTargets targets = new(caster, cast.Cast);
|
|
||||||
|
|
||||||
// Client is resending autoshot cast opcode when other spell is cast during shoot rotation
|
// Client is resending autoshot cast opcode when other spell is cast during shoot rotation
|
||||||
// Skip it to prevent "interrupt" message
|
// Skip it to prevent "interrupt" message
|
||||||
// Also check targets! target may have changed and we need to interrupt current spell
|
// Also check targets! target may have changed and we need to interrupt current spell
|
||||||
@@ -335,7 +359,7 @@ namespace Game
|
|||||||
if (cast.Cast.MoveUpdate.HasValue)
|
if (cast.Cast.MoveUpdate.HasValue)
|
||||||
HandleMovementOpcode(ClientOpcodes.MoveStop, cast.Cast.MoveUpdate.Value);
|
HandleMovementOpcode(ClientOpcodes.MoveStop, cast.Cast.MoveUpdate.Value);
|
||||||
|
|
||||||
Spell spell = new(caster, spellInfo, TriggerCastFlags.None);
|
Spell spell = new(caster, spellInfo, triggerFlag);
|
||||||
|
|
||||||
SpellPrepare spellPrepare = new();
|
SpellPrepare spellPrepare = new();
|
||||||
spellPrepare.ClientCastID = cast.Cast.CastID;
|
spellPrepare.ClientCastID = cast.Cast.CastID;
|
||||||
|
|||||||
@@ -6892,6 +6892,11 @@ namespace Game.Spells
|
|||||||
|
|
||||||
return SpellCastResult.SpellCastOk;
|
return SpellCastResult.SpellCastOk;
|
||||||
}
|
}
|
||||||
|
case LockKeyType.Spell:
|
||||||
|
if (m_spellInfo.Id == lockInfo.Index[j])
|
||||||
|
return SpellCastResult.SpellCastOk;
|
||||||
|
reqKey = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user