aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp88
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h5
-rw-r--r--src/server/game/Entities/Player/Player.cpp4
-rw-r--r--src/server/game/Handlers/LootHandler.cpp6
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp33
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h3
-rw-r--r--src/server/game/Spells/Spell.cpp5
7 files changed, 81 insertions, 63 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index b023fef1d5f..ea6f340863a 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -2800,14 +2800,35 @@ float GameObject::GetInteractionDistance() const
{
switch (GetGoType())
{
- /// @todo find out how the client calculates the maximal usage distance to spellless working
- // gameobjects like guildbanks and mailboxes - 10.0 is a just an abitrary choosen number
- case GAMEOBJECT_TYPE_GUILD_BANK:
- case GAMEOBJECT_TYPE_MAILBOX:
+ case GAMEOBJECT_TYPE_AREADAMAGE:
+ return 0.0f;
+ case GAMEOBJECT_TYPE_QUESTGIVER:
+ case GAMEOBJECT_TYPE_TEXT:
+ case GAMEOBJECT_TYPE_FLAGSTAND:
+ case GAMEOBJECT_TYPE_FLAGDROP:
+ case GAMEOBJECT_TYPE_MINI_GAME:
+ return 5.5555553f;
+ case GAMEOBJECT_TYPE_BINDER:
return 10.0f;
- case GAMEOBJECT_TYPE_FISHINGHOLE:
+ case GAMEOBJECT_TYPE_CHAIR:
+ case GAMEOBJECT_TYPE_BARBER_CHAIR:
+ return 3.0f;
case GAMEOBJECT_TYPE_FISHINGNODE:
+ return 100.0f;
+ case GAMEOBJECT_TYPE_FISHINGHOLE:
return 20.0f + CONTACT_DISTANCE; // max spell range
+ case GAMEOBJECT_TYPE_CAMERA:
+ case GAMEOBJECT_TYPE_MAP_OBJECT:
+ case GAMEOBJECT_TYPE_DUNGEON_DIFFICULTY:
+ case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING:
+ case GAMEOBJECT_TYPE_DOOR:
+ return 5.0f;
+ // Following values are not blizzlike
+ case GAMEOBJECT_TYPE_GUILD_BANK:
+ case GAMEOBJECT_TYPE_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.
+ return 10.0f; // 5.0f is blizzlike
default:
return INTERACTION_DISTANCE;
}
@@ -2900,51 +2921,11 @@ bool GameObject::IsAtInteractDistance(Player const* player, SpellInfo const* spe
if (GetGoType() == GAMEOBJECT_TYPE_SPELL_FOCUS)
return maxRange * maxRange >= GetExactDistSq(player);
- if (GameObjectDisplayInfoEntry const* displayInfo = sGameObjectDisplayInfoStore.LookupEntry(GetGOInfo()->displayId))
+ if (sGameObjectDisplayInfoStore.LookupEntry(GetGOInfo()->displayId))
return IsAtInteractDistance(*player, maxRange);
}
- float distance;
- switch (GetGoType())
- {
- case GAMEOBJECT_TYPE_AREADAMAGE:
- distance = 0.0f;
- break;
- case GAMEOBJECT_TYPE_QUESTGIVER:
- case GAMEOBJECT_TYPE_TEXT:
- case GAMEOBJECT_TYPE_FLAGSTAND:
- case GAMEOBJECT_TYPE_FLAGDROP:
- case GAMEOBJECT_TYPE_MINI_GAME:
- distance = 5.5555553f;
- break;
- case GAMEOBJECT_TYPE_BINDER:
- distance = 10.0f;
- break;
- case GAMEOBJECT_TYPE_CHAIR:
- case GAMEOBJECT_TYPE_BARBER_CHAIR:
- distance = 3.0f;
- break;
- case GAMEOBJECT_TYPE_FISHINGNODE:
- distance = 100.0f;
- break;
- case GAMEOBJECT_TYPE_CAMERA:
- case GAMEOBJECT_TYPE_MAP_OBJECT:
- case GAMEOBJECT_TYPE_DUNGEON_DIFFICULTY:
- case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING:
- case GAMEOBJECT_TYPE_DOOR:
- default:
- distance = 5.0f;
- break;
-
- // Following values are not blizzlike
- case GAMEOBJECT_TYPE_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);
+ return IsAtInteractDistance(*player, GetInteractionDistance());
}
bool GameObject::IsAtInteractDistance(Position const& pos, float radius) const
@@ -2960,10 +2941,10 @@ bool GameObject::IsAtInteractDistance(Position const& pos, float radius) const
float maxY = displayInfo->GeoBoxMax.Y * scale + radius;
float maxZ = displayInfo->GeoBoxMax.Z * scale + radius;
- QuaternionData localRotation = GetLocalRotation();
- G3D::Quat localRotationQuat(localRotation.x, localRotation.y, localRotation.z, localRotation.w);
+ QuaternionData worldRotation = GetWorldRotation();
+ G3D::Quat worldRotationQuat(worldRotation.x, worldRotation.y, worldRotation.z, worldRotation.w);
- return G3D::CoordinateFrame { { localRotationQuat }, { GetPositionX(), GetPositionY(), GetPositionZ() } }
+ return G3D::CoordinateFrame { { worldRotationQuat }, { GetPositionX(), GetPositionY(), GetPositionZ() } }
.toWorldSpace(G3D::Box { { minX, minY, minZ }, { maxX, maxY, maxZ } })
.contains({ pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() });
}
@@ -2971,6 +2952,11 @@ bool GameObject::IsAtInteractDistance(Position const& pos, float radius) const
return GetExactDist(&pos) <= radius;
}
+bool GameObject::IsWithinDistInMap(Player const* player) const
+{
+ return IsInMap(player) && IsInPhase(player) && IsAtInteractDistance(player);
+}
+
SpellInfo const* GameObject::GetSpellForLock(Player const* player) const
{
if (!player)
@@ -2989,7 +2975,7 @@ SpellInfo const* GameObject::GetSpellForLock(Player const* player) const
if (!lock->Type[i])
continue;
- if (lock->Type[i] == LOCK_KEY_SKILL)
+ if (lock->Type[i] == LOCK_KEY_SPELL)
if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(lock->Index[i], GetMap()->GetDifficultyID()))
return spell;
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 39323bcb34d..f6ad0fc2eac 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -300,7 +300,10 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void UpdateModelPosition();
bool IsAtInteractDistance(Position const& pos, float radius) const;
- bool IsAtInteractDistance(Player const* player, SpellInfo const* spell) const;
+ bool IsAtInteractDistance(Player const* player, SpellInfo const* spell = nullptr) const;
+
+ bool IsWithinDistInMap(Player const* player) const;
+ using WorldObject::IsWithinDistInMap;
SpellInfo const* GetSpellForLock(Player const* player) const;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index f24f12540e4..df0101c7101 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2055,7 +2055,7 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid const& guid) const
if (!go)
return nullptr;
- if (!go->IsWithinDistInMap(this, go->GetInteractionDistance()))
+ if (!go->IsWithinDistInMap(this))
return nullptr;
return go;
@@ -8763,7 +8763,7 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type, bool aeLooting/* = fa
}
else
{
- if (lootType != LOOT_FISHINGHOLE && ((lootType != LOOT_FISHING && lootType != LOOT_FISHING_JUNK) || go->GetOwnerGUID() != GetGUID()) && !go->IsWithinDistInMap(this, INTERACTION_DISTANCE))
+ if (lootType != LOOT_FISHINGHOLE && ((lootType != LOOT_FISHING && lootType != LOOT_FISHING_JUNK) || go->GetOwnerGUID() != GetGUID()) && !go->IsWithinDistInMap(this))
return true;
if (lootType == LOOT_CORPSE && go->GetRespawnTime() && go->isSpawnedByDefault())
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index 93f0b1947e0..f2c5ad4f15c 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -78,7 +78,7 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& p
GameObject* go = player->GetMap()->GetGameObject(lguid);
// 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() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE)))
+ if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player)))
{
player->SendLootRelease(lguid);
continue;
@@ -158,7 +158,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet
GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid);
// 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, INTERACTION_DISTANCE))))
+ if (go && ((go->GetOwnerGUID() == player->GetGUID() || go->IsWithinDistInMap(player))))
loot = &go->loot;
break;
@@ -328,7 +328,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid);
// 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() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE)))
+ if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player)))
return;
loot = &go->loot;
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index ec9d24d02d3..cfc2b1cefcd 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -299,9 +299,35 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& cast)
caster = _player;
}
+ TriggerCastFlags triggerFlag = TRIGGERED_NONE;
+
+ // client provided targets
+ SpellCastTargets targets(caster, cast.Cast);
+
// check known spell or raid marker spell (which not requires player to know it)
if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(spellInfo->Id) && !spellInfo->HasEffect(SPELL_EFFECT_CHANGE_RAID_MARKER) && !spellInfo->HasAttribute(SPELL_ATTR8_RAID_MARKER))
- return;
+ {
+ bool allow = false;
+
+
+ // allow casting of unknown spells for special lock cases
+ if (GameObject* go = targets.GetGOTarget())
+ 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
spellInfo = caster->GetCastSpellInfo(spellInfo);
@@ -310,9 +336,6 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& cast)
if (_player->isPossessing())
return;
- // client provided targets
- SpellCastTargets targets(caster, cast.Cast);
-
// Client is resending autoshot cast opcode when other spell is cast during shoot rotation
// Skip it to prevent "interrupt" message
// Also check targets! target may have changed and we need to interrupt current spell
@@ -334,7 +357,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& cast)
if (cast.Cast.MoveUpdate)
HandleMovementOpcode(CMSG_MOVE_STOP, *cast.Cast.MoveUpdate);
- Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE);
+ Spell* spell = new Spell(caster, spellInfo, triggerFlag);
WorldPackets::Spells::SpellPrepare spellPrepare;
spellPrepare.ClientCastID = cast.Cast.CastID;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 241f1fe0495..a4a73b8fe61 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -4326,7 +4326,8 @@ enum LockKeyType
{
LOCK_KEY_NONE = 0,
LOCK_KEY_ITEM = 1,
- LOCK_KEY_SKILL = 2
+ LOCK_KEY_SKILL = 2,
+ LOCK_KEY_SPELL = 3,
};
// LockType.dbc (9.0.2.37176)
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 8083c08479f..8e755f1cb2e 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -7782,6 +7782,11 @@ SpellCastResult Spell::CanOpenLock(SpellEffectInfo const& effect, uint32 lockId,
return SPELL_CAST_OK;
}
+ case LOCK_KEY_SPELL:
+ if (m_spellInfo->Id == uint32(lockInfo->Index[j]))
+ return SPELL_CAST_OK;
+ reqKey = true;
+ break;
}
}