From a6a063d526c171dce7b5c6c9bb35967837265509 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Wed, 4 Jan 2023 16:25:50 -0500 Subject: [PATCH] Core/Players: Implemented setting tradeskill recipes as favorite Port From (https://github.com/TrinityCore/TrinityCore/commit/0555ab2f56e5ad326948df96f5c2e35254e0cf4f) --- .../Database/Databases/CharacterDatabase.cs | 8 +++ Source/Game/Entities/Creature/CreatureData.cs | 3 - Source/Game/Entities/Player/Player.DB.cs | 58 ++++++++++++++----- Source/Game/Entities/Player/Player.Spells.cs | 26 ++++++++- Source/Game/Handlers/CharacterHandler.cs | 5 ++ Source/Game/Handlers/SkillHandler.cs | 9 +++ .../Game/Networking/Packets/SpellPackets.cs | 14 +++++ 7 files changed, 101 insertions(+), 22 deletions(-) diff --git a/Source/Framework/Database/Databases/CharacterDatabase.cs b/Source/Framework/Database/Databases/CharacterDatabase.cs index 27407aa8b..c0d1bf437 100644 --- a/Source/Framework/Database/Databases/CharacterDatabase.cs +++ b/Source/Framework/Database/Databases/CharacterDatabase.cs @@ -92,6 +92,7 @@ namespace Framework.Database PrepareStatement(CharStatements.SEL_CHARACTER_AURAS, "SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, difficulty, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel FROM character_aura WHERE guid = ?"); PrepareStatement(CharStatements.SEL_CHARACTER_AURA_EFFECTS, "SELECT casterGuid, itemGuid, spell, effectMask, effectIndex, amount, baseAmount FROM character_aura_effect WHERE guid = ?"); PrepareStatement(CharStatements.SEL_CHARACTER_SPELL, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?"); + PrepareStatement(CharStatements.SEL_CHARACTER_SPELL_FAVORITES, "SELECT spell FROM character_spell_favorite WHERE guid = ?"); PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS, "SELECT quest, status, explored, acceptTime, endTime FROM character_queststatus WHERE guid = ? AND status <> 0"); PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_OBJECTIVES, "SELECT quest, objective, data FROM character_queststatus_objectives WHERE guid = ?"); PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA, "SELECT questObjectiveId FROM character_queststatus_objectives_criteria WHERE guid = ?"); @@ -627,6 +628,9 @@ namespace Framework.Database PrepareStatement(CharStatements.INS_CHAR_SKILLS, "INSERT INTO character_skills (guid, skill, value, max) VALUES (?, ?, ?, ?)"); PrepareStatement(CharStatements.UPD_CHAR_SKILLS, "UPDATE character_skills SET value = ?, max = ? WHERE guid = ? AND skill = ?"); PrepareStatement(CharStatements.INS_CHAR_SPELL, "INSERT INTO character_spell (guid, spell, active, disabled) VALUES (?, ?, ?, ?)"); + PrepareStatement(CharStatements.DEL_CHAR_SPELL_FAVORITE, "DELETE FROM character_spell_favorite WHERE guid = ? AND spell = ?"); + PrepareStatement(CharStatements.DEL_CHAR_SPELL_FAVORITE_BY_CHAR, "DELETE FROM character_spell_favorite WHERE guid = ?"); + PrepareStatement(CharStatements.INS_CHAR_SPELL_FAVORITE, "INSERT INTO character_spell_favorite (guid, spell) VALUES (?, ?)"); PrepareStatement(CharStatements.DEL_CHAR_STATS, "DELETE FROM character_stats WHERE guid = ?"); PrepareStatement(CharStatements.INS_CHAR_STATS, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, maxpower6, maxpower7, strength, agility, stamina, intellect, " + "armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, blockPct, dodgePct, parryPct, critPct, rangedCritPct, spellCritPct, attackPower, rangedAttackPower, " + @@ -805,6 +809,7 @@ namespace Framework.Database SEL_CHARACTER_AURAS, SEL_CHARACTER_AURA_EFFECTS, SEL_CHARACTER_SPELL, + SEL_CHARACTER_SPELL_FAVORITES, SEL_CHARACTER_QUESTSTATUS, SEL_CHARACTER_QUESTSTATUS_OBJECTIVES, @@ -1260,6 +1265,9 @@ namespace Framework.Database INS_CHAR_SKILLS, UPD_CHAR_SKILLS, INS_CHAR_SPELL, + DEL_CHAR_SPELL_FAVORITE, + DEL_CHAR_SPELL_FAVORITE_BY_CHAR, + INS_CHAR_SPELL_FAVORITE, DEL_CHAR_STATS, INS_CHAR_STATS, DEL_PETITION_BY_OWNER, diff --git a/Source/Game/Entities/Creature/CreatureData.cs b/Source/Game/Entities/Creature/CreatureData.cs index 63243f4f3..af789cc5f 100644 --- a/Source/Game/Entities/Creature/CreatureData.cs +++ b/Source/Game/Entities/Creature/CreatureData.cs @@ -451,9 +451,6 @@ namespace Game.Entities public List BonusListIDs = new(); public uint PlayerConditionId; public bool IgnoreFiltering; - - //helpers - public bool IsGoldRequired(ItemTemplate pProto) { return pProto.HasFlag(ItemFlags2.DontIgnoreBuyPrice) || ExtendedCost == 0; } } public class VendorItemData diff --git a/Source/Game/Entities/Player/Player.DB.cs b/Source/Game/Entities/Player/Player.DB.cs index d0483b623..205ec43c9 100644 --- a/Source/Game/Entities/Player/Player.DB.cs +++ b/Source/Game/Entities/Player/Player.DB.cs @@ -450,7 +450,7 @@ namespace Game.Entities if (HasSkill(SkillType.FistWeapons)) SetSkill(SkillType.FistWeapons, 0, GetSkillValue(SkillType.Unarmed), GetMaxSkillValueForLevel()); } - void _LoadSpells(SQLResult result) + void _LoadSpells(SQLResult result, SQLResult favoritesResult) { if (!result.IsEmpty()) { @@ -460,6 +460,16 @@ namespace Game.Entities } while (result.NextRow()); } + + if (!favoritesResult.IsEmpty()) + { + do + { + var spell = m_spells.LookupByKey(favoritesResult.Read(0)); + if (spell !=null) + spell.Favorite = true; + } while (favoritesResult.NextRow()); + } } void _LoadAuras(SQLResult auraResult, SQLResult effectResult, uint timediff) @@ -1823,35 +1833,51 @@ namespace Game.Entities { PreparedStatement stmt; - foreach (var spell in m_spells.ToList()) + foreach (var (id, spell) in m_spells.ToList()) { - if (spell.Value.State == PlayerSpellState.Removed || spell.Value.State == PlayerSpellState.Changed) + if (spell.State == PlayerSpellState.Removed || spell.State == PlayerSpellState.Changed) { stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_SPELL_BY_SPELL); - stmt.AddValue(0, spell.Key); + stmt.AddValue(0, id); stmt.AddValue(1, GetGUID().GetCounter()); trans.Append(stmt); } - // add only changed/new not dependent spells - if (!spell.Value.Dependent && (spell.Value.State == PlayerSpellState.New || spell.Value.State == PlayerSpellState.Changed)) + if (spell.State == PlayerSpellState.New || spell.State == PlayerSpellState.Changed) { - stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_SPELL); - stmt.AddValue(0, GetGUID().GetCounter()); - stmt.AddValue(1, spell.Key); - stmt.AddValue(2, spell.Value.Active); - stmt.AddValue(3, spell.Value.Disabled); + // add only changed/new not dependent spells + if (!spell.Dependent) + { + stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_SPELL); + stmt.AddValue(0, GetGUID().GetCounter()); + stmt.AddValue(1, id); + stmt.AddValue(2, spell.Active); + stmt.AddValue(3, spell.Disabled); + trans.Append(stmt); + } + + stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_SPELL_FAVORITE); + stmt.AddValue(0, id); + stmt.AddValue(1, GetGUID().GetCounter()); trans.Append(stmt); + + if (spell.Favorite) + { + stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_SPELL_FAVORITE); + stmt.AddValue(0, GetGUID().GetCounter()); + stmt.AddValue(1, id); + trans.Append(stmt); + } } - if (spell.Value.State == PlayerSpellState.Removed) + if (spell.State == PlayerSpellState.Removed) { - m_spells.Remove(spell.Key); + m_spells.Remove(id); continue; } - if (spell.Value.State != PlayerSpellState.Temporary) - spell.Value.State = PlayerSpellState.Unchanged; + if (spell.State != PlayerSpellState.Temporary) + spell.State = PlayerSpellState.Unchanged; } } void _SaveAuras(SQLTransaction trans) @@ -3294,7 +3320,7 @@ namespace Game.Entities UpdateDisplayPower(); _LoadTalents(holder.GetResult(PlayerLoginQueryLoad.Talents)); _LoadPvpTalents(holder.GetResult(PlayerLoginQueryLoad.PvpTalents)); - _LoadSpells(holder.GetResult(PlayerLoginQueryLoad.Spells)); + _LoadSpells(holder.GetResult(PlayerLoginQueryLoad.Spells), holder.GetResult(PlayerLoginQueryLoad.SpellFavorites)); GetSession().GetCollectionMgr().LoadToys(); GetSession().GetCollectionMgr().LoadHeirlooms(); GetSession().GetCollectionMgr().LoadMounts(); diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index 326ef0369..8afe5e0da 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -2029,7 +2029,7 @@ namespace Game.Entities void SendKnownSpells() { SendKnownSpells knownSpells = new(); - knownSpells.InitialLogin = false; // @todo + knownSpells.InitialLogin = IsLoading(); foreach (var spell in m_spells.ToList()) { @@ -2040,6 +2040,8 @@ namespace Game.Entities continue; knownSpells.KnownSpells.Add(spell.Key); + if (spell.Value.Favorite) + knownSpells.FavoriteSpells.Add(spell.Key); } SendPacket(knownSpells); @@ -2056,8 +2058,9 @@ namespace Game.Entities bool disabled = (spell != null) && spell.Disabled; bool active = !disabled || spell.Active; + bool favorite = spell != null ? spell.Favorite : false; - bool learning = AddSpell(spellId, active, true, dependent, false, false, fromSkill, traitDefinitionId); + bool learning = AddSpell(spellId, active, true, dependent, false, false, fromSkill, favorite, traitDefinitionId); // prevent duplicated entires in spell book, also not send if not in world (loading) if (learning && IsInWorld) @@ -2065,6 +2068,7 @@ namespace Game.Entities LearnedSpells learnedSpells = new(); LearnedSpellInfo learnedSpellInfo = new(); learnedSpellInfo.SpellID = spellId; + learnedSpellInfo.IsFavorite = favorite; learnedSpellInfo.TraitDefinitionID = traitDefinitionId; learnedSpells.SuppressMessaging = suppressMessaging; learnedSpells.ClientLearnedSpellData.Add(learnedSpellInfo); @@ -2268,6 +2272,18 @@ namespace Game.Entities SendPacket(unlearnedSpells); } } + + public void SetSpellFavorite(uint spellId, bool favorite) + { + var spell = m_spells.LookupByKey(spellId); + if (spell == null) + return; + + spell.Favorite = favorite; + if (spell.State == PlayerSpellState.Unchanged) + spell.State = PlayerSpellState.Changed; + } + bool HandlePassiveSpellLearn(SpellInfo spellInfo) { // note: form passives activated with shapeshift spells be implemented by HandleShapeshiftBoosts instead of spell_learn_spell @@ -2320,7 +2336,7 @@ namespace Game.Entities return null; } - bool AddSpell(uint spellId, bool active, bool learning, bool dependent, bool disabled, bool loading = false, uint fromSkill = 0, int? traitDefinitionId = null) + bool AddSpell(uint spellId, bool active, bool learning, bool dependent, bool disabled, bool loading = false, uint fromSkill = 0, bool favorite = false, int? traitDefinitionId = null) { SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, Difficulty.None); if (spellInfo == null) @@ -2411,6 +2427,8 @@ namespace Game.Entities spell.TraitDefinitionId = traitDefinitionId; } + spell.Favorite = favorite; + // update active state for known spell if (spell.Active != active && spell.State != PlayerSpellState.Removed && !spell.Disabled) { @@ -2492,6 +2510,7 @@ namespace Game.Entities newspell.Active = active; newspell.Dependent = dependent; newspell.Disabled = disabled; + newspell.Favorite = favorite; if (traitDefinitionId.HasValue) newspell.TraitDefinitionId = traitDefinitionId.Value; @@ -3591,6 +3610,7 @@ namespace Game.Entities public bool Active; public bool Dependent; public bool Disabled; + public bool Favorite; public int? TraitDefinitionId; } } diff --git a/Source/Game/Handlers/CharacterHandler.cs b/Source/Game/Handlers/CharacterHandler.cs index bc10f3d9a..9242bb1e2 100644 --- a/Source/Game/Handlers/CharacterHandler.cs +++ b/Source/Game/Handlers/CharacterHandler.cs @@ -2659,6 +2659,10 @@ namespace Game stmt.AddValue(0, lowGuid); SetQuery(PlayerLoginQueryLoad.Spells, stmt); + stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHARACTER_SPELL_FAVORITES); + stmt.AddValue(0, lowGuid); + SetQuery(PlayerLoginQueryLoad.SpellFavorites, stmt); + stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS); stmt.AddValue(0, lowGuid); SetQuery(PlayerLoginQueryLoad.QuestStatus, stmt); @@ -2930,6 +2934,7 @@ namespace Game AuraEffects, AuraStoredLocations, Spells, + SpellFavorites, QuestStatus, QuestStatusObjectives, QuestStatusObjectivesCriteria, diff --git a/Source/Game/Handlers/SkillHandler.cs b/Source/Game/Handlers/SkillHandler.cs index cd36c1f14..203f54ef0 100644 --- a/Source/Game/Handlers/SkillHandler.cs +++ b/Source/Game/Handlers/SkillHandler.cs @@ -117,5 +117,14 @@ namespace Game GetPlayer().SetSkill(packet.SkillLine, 0, 0, 0); } + + [WorldPacketHandler(ClientOpcodes.TradeSkillSetFavorite, Processing = PacketProcessing.Inplace)] + void HandleTradeSkillSetFavorite(TradeSkillSetFavorite tradeSkillSetFavorite) + { + if (!_player.HasSpell(tradeSkillSetFavorite.RecipeID)) + return; + + _player.SetSpellFavorite(tradeSkillSetFavorite.RecipeID, tradeSkillSetFavorite.IsFavorite); + } } } diff --git a/Source/Game/Networking/Packets/SpellPackets.cs b/Source/Game/Networking/Packets/SpellPackets.cs index 67fad6368..bdc7798c8 100644 --- a/Source/Game/Networking/Packets/SpellPackets.cs +++ b/Source/Game/Networking/Packets/SpellPackets.cs @@ -1160,6 +1160,20 @@ namespace Game.Networking.Packets public bool Reverse; public uint SpellID; } + + class TradeSkillSetFavorite : ClientPacket + { + public uint RecipeID; + public bool IsFavorite; + + public TradeSkillSetFavorite(WorldPacket packet) : base(packet) { } + + public override void Read() + { + RecipeID = _worldPacket.ReadUInt32(); + IsFavorite = _worldPacket.HasBit(); + } + } //Structs public struct SpellLogPowerData