diff options
author | Matan Shukry <matanshukry@gmail.com> | 2021-03-28 02:22:34 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-28 00:22:34 +0100 |
commit | 1c852af7f2c820e429eaf8389822e8c910f961a1 (patch) | |
tree | ab90c6a1c692029e43ec94b2864799f5d7706655 /src | |
parent | 3ef50d6a1b6f49f1896d38ae9106cdf8228f1785 (diff) |
Core/Spells: Implement SPELL_EFFECT_TELEPORT_TO_RETURN_POINT (#26217)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.cpp | 7 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.h | 5 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 100 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 20 | ||||
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraDefines.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 17 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.h | 1 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 1 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 12 |
10 files changed, 166 insertions, 3 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 7f8273170b3..3f811766ea9 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -800,6 +800,13 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_SCENARIO_INSTANCE_CRITERIA, "DELETE FROM instance_scenario_progress WHERE id = ? AND criteria = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_SCENARIO_INSTANCE_CRITERIA, "INSERT INTO instance_scenario_progress (id, criteria, counter, date) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE, "DELETE FROM instance_scenario_progress WHERE id = ?", CONNECTION_ASYNC); + + // Spell Location + PrepareStatement(CHAR_SEL_CHARACTER_AURA_STORED_LOCATIONS, "SELECT Spell, MapId, PositionX, PositionY, PositionZ, Orientation FROM character_aura_stored_location WHERE Guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CHARACTER_AURA_STORED_LOCATIONS_BY_GUID, "DELETE FROM character_aura_stored_location WHERE Guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CHARACTER_AURA_STORED_LOCATION, "DELETE FROM character_aura_stored_location WHERE Guid = ? AND Spell = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_CHARACTER_AURA_STORED_LOCATION, "INSERT INTO character_aura_stored_location (Guid, Spell, MapId, PositionX, PositionY, PositionZ, Orientation) " + "VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); } CharacterDatabaseConnection::CharacterDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index c756578c206..d05554f1219 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -671,6 +671,11 @@ enum CharacterDatabaseStatements : uint32 CHAR_INS_SCENARIO_INSTANCE_CRITERIA, CHAR_DEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE, + CHAR_SEL_CHARACTER_AURA_STORED_LOCATIONS, + CHAR_DEL_CHARACTER_AURA_STORED_LOCATIONS_BY_GUID, + CHAR_DEL_CHARACTER_AURA_STORED_LOCATION, + CHAR_INS_CHARACTER_AURA_STORED_LOCATION, + MAX_CHARACTERDATABASE_STATEMENTS }; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 565c03d0fac..21a3d787310 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2735,6 +2735,27 @@ void Player::RemoveTalent(TalentEntry const* talent) plrTalent->second = PLAYERSPELL_REMOVED; } +void Player::AddStoredAuraTeleportLocation(uint32 spellId) +{ + StoredAuraTeleportLocation& storedLocation = m_storedAuraTeleportLocations[spellId]; + storedLocation.Loc.WorldRelocate(this); + storedLocation.State = StoredAuraTeleportLocation::CHANGED; +} + +void Player::RemoveStoredAuraTeleportLocation(uint32 spellId) +{ + if (StoredAuraTeleportLocation* storedLocation = Trinity::Containers::MapGetValuePtr(m_storedAuraTeleportLocations, spellId)) + storedLocation->State = StoredAuraTeleportLocation::DELETED; +} + +WorldLocation const* Player::GetStoredAuraTeleportLocation(uint32 spellId) const +{ + if (StoredAuraTeleportLocation const* auraLocation = Trinity::Containers::MapGetValuePtr(m_storedAuraTeleportLocations, spellId)) + return &auraLocation->Loc; + + return nullptr; +} + bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading /*= false*/, int32 fromSkill /*= 0*/) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE); @@ -4128,6 +4149,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe stmt->setUInt64(0, guid); trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_AURA_STORED_LOCATIONS_BY_GUID); + stmt->setUInt64(0, guid); + trans->Append(stmt); + Corpse::DeleteFromDB(playerguid, trans); Garrison::DeleteFromDB(guid, trans); @@ -18654,6 +18679,9 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) if (HasPlayerFlag(PLAYER_FLAGS_GHOST)) m_deathState = DEAD; + // Load spell locations - must be after loading auras + _LoadStoredAuraTeleportLocations(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_AURA_STORED_LOCATIONS)); + // after spell load, learn rewarded spell if need also _LoadQuestStatus(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS)); _LoadQuestStatusObjectives(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES)); @@ -19964,6 +19992,42 @@ void Player::_LoadSpells(PreparedQueryResult result) } } +void Player::_LoadStoredAuraTeleportLocations(PreparedQueryResult result) +{ + // 0 1 2 3 4 5 + //QueryResult* result = CharacterDatabase.PQuery("SELECT Spell, MapId, PositionX, PositionY, PositionZ, Orientation FROM character_spell_location WHERE Guid = ?", GetGUIDLow()); + + m_storedAuraTeleportLocations.clear(); + if (result) + { + do + { + Field* fields = result->Fetch(); + uint32 spellId = fields[0].GetUInt32(); + + if (!sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE)) + { + TC_LOG_ERROR("spells", "Player::_LoadStoredAuraTeleportLocations: Player %s (%s) spell (ID: %u) does not exist", + GetName().c_str(), GetGUID().ToString().c_str(), spellId); + continue; + } + + WorldLocation location(fields[1].GetUInt32(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat()); + if (!MapManager::IsValidMapCoord(location)) + { + TC_LOG_ERROR("spells", "Player::_LoadStoredAuraTeleportLocations: Player %s (%s) spell (ID: %u) has invalid position on map %u, {%s}.", + GetName().c_str(), GetGUID().ToString().c_str(), spellId, location.GetMapId(), location.ToString().c_str()); + continue; + } + + StoredAuraTeleportLocation& storedLocation = m_storedAuraTeleportLocations[spellId]; + storedLocation.Loc = location; + storedLocation.State = StoredAuraTeleportLocation::UNCHANGED; + } + while (result->NextRow()); + } +} + void Player::_LoadGroup(PreparedQueryResult result) { //QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM group_member WHERE memberGuid=%u", GetGUIDLow()); @@ -20864,6 +20928,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba _SaveActions(trans); _SaveAuras(trans); _SaveSkills(trans); + _SaveStoredAuraTeleportLocations(trans); m_achievementMgr->SaveToDB(trans); m_reputationMgr->SaveToDB(trans); m_questObjectiveCriteriaMgr->SaveToDB(trans); @@ -21624,6 +21689,41 @@ void Player::_SaveSpells(CharacterDatabaseTransaction& trans) } } +void Player::_SaveStoredAuraTeleportLocations(CharacterDatabaseTransaction& trans) +{ + for (auto itr = m_storedAuraTeleportLocations.begin(); itr != m_storedAuraTeleportLocations.end(); ) + { + StoredAuraTeleportLocation& storedLocation = itr->second; + if (storedLocation.State == StoredAuraTeleportLocation::DELETED) + { + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_AURA_STORED_LOCATION); + stmt->setUInt64(0, GetGUID().GetCounter()); + trans->Append(stmt); + itr = m_storedAuraTeleportLocations.erase(itr); + continue; + } + + if (storedLocation.State == StoredAuraTeleportLocation::CHANGED) + { + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_AURA_STORED_LOCATION); + stmt->setUInt64(0, GetGUID().GetCounter()); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_AURA_STORED_LOCATION); + stmt->setUInt64(0, GetGUID().GetCounter()); + stmt->setUInt32(1, itr->first); + stmt->setUInt32(2, storedLocation.Loc.GetMapId()); + stmt->setFloat(3, storedLocation.Loc.GetPositionX()); + stmt->setFloat(4, storedLocation.Loc.GetPositionY()); + stmt->setFloat(5, storedLocation.Loc.GetPositionZ()); + stmt->setFloat(6, storedLocation.Loc.GetOrientation()); + trans->Append(stmt); + } + + ++itr; + } +} + // save player stats -- only for external usage // real stats will be recalculated on player login void Player::_SaveStats(CharacterDatabaseTransaction& trans) const diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 8a29cc05a0c..8124399b1f3 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -178,6 +178,18 @@ struct PlayerSpell bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks }; +struct StoredAuraTeleportLocation +{ + WorldLocation Loc; + + enum + { + UNCHANGED, + CHANGED, + DELETED, + } State; +}; + enum TalentSpecialization // talent tabs { TALENT_SPEC_MAGE_ARCANE = 62, @@ -769,6 +781,7 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOAD_BOUND_INSTANCES, PLAYER_LOGIN_QUERY_LOAD_AURAS, PLAYER_LOGIN_QUERY_LOAD_AURA_EFFECTS, + PLAYER_LOGIN_QUERY_LOAD_AURA_STORED_LOCATIONS, PLAYER_LOGIN_QUERY_LOAD_SPELLS, PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS, PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES, @@ -1614,6 +1627,10 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void RemoveSpecializationSpells(); void SendSpellCategoryCooldowns() const; + void AddStoredAuraTeleportLocation(uint32 spellId); + void RemoveStoredAuraTeleportLocation(uint32 spellId); + WorldLocation const* GetStoredAuraTeleportLocation(uint32 spellId) const; + void SetReputation(uint32 factionentry, int32 value); int32 GetReputation(uint32 factionentry) const; std::string GetGuildName() const; @@ -2622,6 +2639,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void _LoadGroup(PreparedQueryResult result); void _LoadSkills(PreparedQueryResult result); void _LoadSpells(PreparedQueryResult result); + void _LoadStoredAuraTeleportLocations(PreparedQueryResult result); bool _LoadHomeBind(PreparedQueryResult result); void _LoadDeclinedNames(PreparedQueryResult result); void _LoadArenaTeamInfo(PreparedQueryResult result); @@ -2652,6 +2670,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void _SaveSeasonalQuestStatus(CharacterDatabaseTransaction& trans); void _SaveSkills(CharacterDatabaseTransaction& trans); void _SaveSpells(CharacterDatabaseTransaction& trans); + void _SaveStoredAuraTeleportLocations(CharacterDatabaseTransaction& trans); void _SaveEquipmentSets(CharacterDatabaseTransaction& trans); void _SaveBGData(CharacterDatabaseTransaction& trans); void _SaveGlyphs(CharacterDatabaseTransaction& trans) const; @@ -2732,6 +2751,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> PlayerSpellMap m_spells; std::unordered_map<uint32 /*overridenSpellId*/, std::unordered_set<uint32> /*newSpellId*/> m_overrideSpells; uint32 m_lastPotionId; // last used health/mana potion in combat, that block next potion use + std::unordered_map<uint32, StoredAuraTeleportLocation> m_storedAuraTeleportLocations; SpecializationInfo _specializationInfo; diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index c49fcbac361..a38f7477d70 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -109,6 +109,10 @@ bool LoginQueryHolder::Initialize() stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_AURA_EFFECTS, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AURA_STORED_LOCATIONS); + stmt->setUInt64(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_AURA_STORED_LOCATIONS, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SPELL); stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_SPELLS, stmt); diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index e1496fbc123..ec87dc3eb3e 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -149,7 +149,7 @@ enum AuraType : uint32 SPELL_AURA_MOD_STALKED = 68, SPELL_AURA_SCHOOL_ABSORB = 69, SPELL_AURA_PERIODIC_WEAPON_PERCENT_DAMAGE = 70, - SPELL_AURA_STORE_TELEPORT_RETURN_POINT = 71, // NYI + SPELL_AURA_STORE_TELEPORT_RETURN_POINT = 71, SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT = 72, SPELL_AURA_MOD_POWER_COST_SCHOOL = 73, SPELL_AURA_REFLECT_SPELLS_SCHOOL = 74, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index cbd6bf70309..515badef5aa 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -138,7 +138,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED &AuraEffect::HandleNoImmediateEffect, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist &AuraEffect::HandleNoImmediateEffect, // 70 SPELL_AURA_PERIODIC_WEAPON_PERCENT_DAMAGE implemented in AuraEffect::PeriodicTick - &AuraEffect::HandleNULL, // 71 SPELL_AURA_STORE_TELEPORT_RETURN_POINT + &AuraEffect::HandleStoreTeleportReturnPoint, // 71 SPELL_AURA_STORE_TELEPORT_RETURN_POINT &AuraEffect::HandleNoImmediateEffect, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT &AuraEffect::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL &AuraEffect::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult @@ -5958,6 +5958,21 @@ void AuraEffect::HandleBattlegroundPlayerPosition(AuraApplication const* aurApp, bg->RemovePlayerPosition(target->GetGUID()); } +void AuraEffect::HandleStoreTeleportReturnPoint(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Player* playerTarget = aurApp->GetTarget()->ToPlayer(); + if (!playerTarget) + return; + + if (apply) + playerTarget->AddStoredAuraTeleportLocation(GetSpellInfo()->Id); + else if (!playerTarget->GetSession()->isLogingOut()) + playerTarget->RemoveStoredAuraTeleportLocation(GetSpellInfo()->Id); +} + template TC_GAME_API void AuraEffect::GetTargetList(std::list<Unit*>&) const; template TC_GAME_API void AuraEffect::GetTargetList(std::deque<Unit*>&) const; template TC_GAME_API void AuraEffect::GetTargetList(std::vector<Unit*>&) const; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 71fbfe49364..12e9547b4d6 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -324,6 +324,7 @@ class TC_GAME_API AuraEffect void HandleBattlegroundPlayerPosition(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleTriggerSpellOnPowerAmount(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleTriggerSpellOnPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleStoreTeleportReturnPoint(AuraApplication const* aurApp, uint8 mode, bool apply) const; // aura effect periodic tick handlers void HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) const; diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index dbe43173b38..2fa9b377b08 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -349,6 +349,7 @@ class TC_GAME_API Spell void EffectPowerDrain(SpellEffIndex effIndex); void EffectHeal(SpellEffIndex effIndex); void EffectBind(SpellEffIndex effIndex); + void EffectTeleportToReturnPoint(SpellEffIndex effIndex); void EffectHealthLeech(SpellEffIndex effIndex); void EffectQuestComplete(SpellEffIndex effIndex); void EffectCreateItem(SpellEffIndex effIndex); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 336de46e33a..11570ee6e86 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -91,7 +91,7 @@ NonDefaultConstructible<pEffect> SpellEffects[TOTAL_SPELL_EFFECTS] = &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL &Spell::EffectBind, // 11 SPELL_EFFECT_BIND &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL - &Spell::EffectNULL, // 13 SPELL_EFFECT_TELEPORT_TO_RETURN_POINT + &Spell::EffectTeleportToReturnPoint, // 13 SPELL_EFFECT_TELEPORT_TO_RETURN_POINT &Spell::EffectNULL, // 14 SPELL_EFFECT_INCREASE_CURRENCY_CAP &Spell::EffectNULL, // 15 SPELL_EFFECT_TELEPORT_WITH_SPELL_VISUAL_KIT_LOADING_SCREEN &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE @@ -5334,6 +5334,16 @@ void Spell::EffectBind(SpellEffIndex /*effIndex*/) player->SendDirectMessage(packet.Write()); } +void Spell::EffectTeleportToReturnPoint(SpellEffIndex /*effIndex*/) +{ + if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) + return; + + if (Player* player = unitTarget->ToPlayer()) + if (WorldLocation const* dest = player->GetStoredAuraTeleportLocation(effectInfo->MiscValue)) + player->TeleportTo(*dest, unitTarget == m_caster ? TELE_TO_SPELL | TELE_TO_NOT_LEAVE_COMBAT : 0); +} + void Spell::EffectSummonRaFFriend(SpellEffIndex /*effIndex*/) { if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) |