Core/Players: Fixed pvp talents being reset on login if player is below level 110 (pre level squish code)
Port From (https://github.com/TrinityCore/TrinityCore/commit/9c90a18ee5ecccf597388fe52633813c6d2c5726)
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Framework.Constants
|
||||
public const int MaxArtifactTier = 1;
|
||||
|
||||
public const int MaxHonorLevel = 500;
|
||||
public const byte LevelMinHonor = 20;
|
||||
public const byte LevelMinHonor = 10;
|
||||
public const uint SpellPvpRulesEnabled = 134735;
|
||||
|
||||
//Azerite
|
||||
|
||||
@@ -3153,8 +3153,6 @@ namespace Game.Entities
|
||||
InitTalentForLevel();
|
||||
LearnDefaultSkills();
|
||||
LearnCustomSpells();
|
||||
if (GetLevel() < PlayerConst.LevelMinHonor)
|
||||
ResetPvpTalents();
|
||||
|
||||
// must be before inventory (some items required reputation check)
|
||||
reputationMgr.LoadFromDB(holder.GetResult(PlayerLoginQueryLoad.Reputation));
|
||||
|
||||
@@ -27,7 +27,6 @@ using Game.PvP;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
@@ -308,146 +307,6 @@ namespace Game.Entities
|
||||
public void ActivatePvpItemLevels(bool activate) { _usePvpItemLevels = activate; }
|
||||
public bool IsUsingPvpItemLevels() { return _usePvpItemLevels; }
|
||||
|
||||
void ResetPvpTalents()
|
||||
{
|
||||
foreach (var talentInfo in CliDB.PvpTalentStorage.Values)
|
||||
{
|
||||
if (talentInfo == null)
|
||||
continue;
|
||||
|
||||
RemovePvpTalent(talentInfo);
|
||||
}
|
||||
|
||||
SQLTransaction trans = new();
|
||||
_SaveTalents(trans);
|
||||
_SaveSpells(trans);
|
||||
DB.Characters.CommitTransaction(trans);
|
||||
}
|
||||
|
||||
public TalentLearnResult LearnPvpTalent(uint talentID, byte slot, ref uint spellOnCooldown)
|
||||
{
|
||||
if (slot >= PlayerConst.MaxPvpTalentSlots)
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (IsInCombat())
|
||||
return TalentLearnResult.FailedAffectingCombat;
|
||||
|
||||
if (IsDead())
|
||||
return TalentLearnResult.FailedCantDoThatRightNow;
|
||||
|
||||
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(talentID);
|
||||
if (talentInfo == null)
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (talentInfo.SpecID != GetPrimarySpecialization())
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (talentInfo.LevelRequired > GetLevel())
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (Global.DB2Mgr.GetRequiredLevelForPvpTalentSlot(slot, GetClass()) > GetLevel())
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
PvpTalentCategoryRecord talentCategory = CliDB.PvpTalentCategoryStorage.LookupByKey(talentInfo.PvpTalentCategoryID);
|
||||
if (talentCategory != null)
|
||||
if (!Convert.ToBoolean(talentCategory.TalentSlotMask & (1 << slot)))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
// Check if player doesn't have this talent in other slot
|
||||
if (HasPvpTalent(talentID, GetActiveTalentGroup()))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
|
||||
if (talent != null)
|
||||
{
|
||||
if (!HasPlayerFlag(PlayerFlags.Resting) && !HasUnitFlag2(UnitFlags2.AllowChangingTalents))
|
||||
return TalentLearnResult.FailedRestArea;
|
||||
|
||||
if (GetSpellHistory().HasCooldown(talent.SpellID))
|
||||
{
|
||||
spellOnCooldown = talent.SpellID;
|
||||
return TalentLearnResult.FailedCantRemoveTalent;
|
||||
}
|
||||
|
||||
RemovePvpTalent(talent);
|
||||
}
|
||||
|
||||
if (!AddPvpTalent(talentInfo, GetActiveTalentGroup(), slot))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
return TalentLearnResult.LearnOk;
|
||||
}
|
||||
|
||||
bool AddPvpTalent(PvpTalentRecord talent, byte activeTalentGroup, byte slot)
|
||||
{
|
||||
//ASSERT(talent);
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talent.SpellID, Difficulty.None);
|
||||
if (spellInfo == null)
|
||||
{
|
||||
Log.outError(LogFilter.Spells, $"Player.AddPvpTalent: Spell (ID: {talent.SpellID}) does not exist.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Global.SpellMgr.IsSpellValid(spellInfo, this, false))
|
||||
{
|
||||
Log.outError(LogFilter.Spells, $"Player.AddPvpTalent: Spell (ID: {talent.SpellID}) is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HasPvpRulesEnabled())
|
||||
LearnSpell(talent.SpellID, false);
|
||||
|
||||
// Move this to toggle ?
|
||||
if (talent.OverridesSpellID != 0)
|
||||
AddOverrideSpell(talent.OverridesSpellID, talent.SpellID);
|
||||
|
||||
GetPvpTalentMap(activeTalentGroup)[slot] = talent.Id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemovePvpTalent(PvpTalentRecord talent)
|
||||
{
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talent.SpellID, Difficulty.None);
|
||||
if (spellInfo == null)
|
||||
return;
|
||||
|
||||
RemoveSpell(talent.SpellID, true);
|
||||
|
||||
// Move this to toggle ?
|
||||
if (talent.OverridesSpellID != 0)
|
||||
RemoveOverrideSpell(talent.OverridesSpellID, talent.SpellID);
|
||||
|
||||
// if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted
|
||||
var talents = GetPvpTalentMap(GetActiveTalentGroup());
|
||||
for (var i = 0; i < PlayerConst.MaxPvpTalentSlots; ++i)
|
||||
{
|
||||
if (talents[i] == talent.Id)
|
||||
talents[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void TogglePvpTalents(bool enable)
|
||||
{
|
||||
var pvpTalents = GetPvpTalentMap(GetActiveTalentGroup());
|
||||
foreach (uint pvpTalentId in pvpTalents)
|
||||
{
|
||||
PvpTalentRecord pvpTalentInfo = CliDB.PvpTalentStorage.LookupByKey(pvpTalentId);
|
||||
if (pvpTalentInfo != null)
|
||||
{
|
||||
if (enable)
|
||||
LearnSpell(pvpTalentInfo.SpellID, false);
|
||||
else
|
||||
RemoveSpell(pvpTalentInfo.SpellID, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HasPvpTalent(uint talentID, byte activeTalentGroup)
|
||||
{
|
||||
return GetPvpTalentMap(activeTalentGroup).Contains(talentID);
|
||||
}
|
||||
|
||||
public void EnablePvpRules(bool dueToCombat = false)
|
||||
{
|
||||
if (HasPvpRulesEnabled())
|
||||
|
||||
@@ -20,6 +20,7 @@ using Framework.Database;
|
||||
using Game.DataStorage;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Game.Entities
|
||||
@@ -52,6 +53,19 @@ namespace Game.Entities
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.MaxTalentTiers), talentTiers);
|
||||
|
||||
if (!GetSession().HasPermission(RBACPermissions.SkipCheckMoreTalentsThanAllowed))
|
||||
{
|
||||
for (byte spec = 0; spec < PlayerConst.MaxSpecializations; ++spec)
|
||||
{
|
||||
for (int slot = Global.DB2Mgr.GetPvpTalentNumSlotsAtLevel(level, GetClass()); slot < PlayerConst.MaxPvpTalentSlots; ++slot)
|
||||
{
|
||||
var pvpTalent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(spec)[slot]);
|
||||
if (pvpTalent != null)
|
||||
RemovePvpTalent(pvpTalent, spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetSession().PlayerLoading())
|
||||
SendTalentsInfoData(); // update at client
|
||||
}
|
||||
@@ -167,7 +181,7 @@ namespace Game.Entities
|
||||
|
||||
if (!HasTalent(talent.Id, GetActiveTalentGroup()))
|
||||
continue;
|
||||
|
||||
|
||||
if (!HasPlayerFlag(PlayerFlags.Resting) && HasUnitFlag2(UnitFlags2.AllowChangingTalents))
|
||||
return TalentLearnResult.FailedRestArea;
|
||||
|
||||
@@ -219,6 +233,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
ResetPvpTalents();
|
||||
RemoveSpecializationSpells();
|
||||
|
||||
ChrSpecializationRecord defaultSpec = Global.DB2Mgr.GetDefaultChrSpecializationForClass(GetClass());
|
||||
@@ -530,7 +545,7 @@ namespace Game.Entities
|
||||
continue;
|
||||
|
||||
RemoveTalent(talentInfo);
|
||||
}
|
||||
}
|
||||
|
||||
SQLTransaction trans = new();
|
||||
_SaveTalents(trans);
|
||||
@@ -632,5 +647,143 @@ namespace Game.Entities
|
||||
respecWipeConfirm.RespecType = SpecResetType.Talents;
|
||||
SendPacket(respecWipeConfirm);
|
||||
}
|
||||
|
||||
//Pvp
|
||||
void ResetPvpTalents()
|
||||
{
|
||||
for (byte spec = 0; spec < PlayerConst.MaxSpecializations; ++spec)
|
||||
{
|
||||
foreach (uint talentId in GetPvpTalentMap(spec))
|
||||
{
|
||||
var talentInfo = CliDB.PvpTalentStorage.LookupByKey(talentId);
|
||||
if (talentInfo != null)
|
||||
RemovePvpTalent(talentInfo, spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TalentLearnResult LearnPvpTalent(uint talentID, byte slot, ref uint spellOnCooldown)
|
||||
{
|
||||
if (slot >= PlayerConst.MaxPvpTalentSlots)
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (IsInCombat())
|
||||
return TalentLearnResult.FailedAffectingCombat;
|
||||
|
||||
if (IsDead())
|
||||
return TalentLearnResult.FailedCantDoThatRightNow;
|
||||
|
||||
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(talentID);
|
||||
if (talentInfo == null)
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (talentInfo.SpecID != GetPrimarySpecialization())
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (talentInfo.LevelRequired > GetLevel())
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (Global.DB2Mgr.GetRequiredLevelForPvpTalentSlot(slot, GetClass()) > GetLevel())
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
PvpTalentCategoryRecord talentCategory = CliDB.PvpTalentCategoryStorage.LookupByKey(talentInfo.PvpTalentCategoryID);
|
||||
if (talentCategory != null)
|
||||
if (!Convert.ToBoolean(talentCategory.TalentSlotMask & (1 << slot)))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
// Check if player doesn't have this talent in other slot
|
||||
if (HasPvpTalent(talentID, GetActiveTalentGroup()))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
|
||||
if (talent != null)
|
||||
{
|
||||
if (!HasPlayerFlag(PlayerFlags.Resting) && !HasUnitFlag2(UnitFlags2.AllowChangingTalents))
|
||||
return TalentLearnResult.FailedRestArea;
|
||||
|
||||
if (GetSpellHistory().HasCooldown(talent.SpellID))
|
||||
{
|
||||
spellOnCooldown = talent.SpellID;
|
||||
return TalentLearnResult.FailedCantRemoveTalent;
|
||||
}
|
||||
|
||||
RemovePvpTalent(talent, GetActiveTalentGroup());
|
||||
}
|
||||
|
||||
if (!AddPvpTalent(talentInfo, GetActiveTalentGroup(), slot))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
return TalentLearnResult.LearnOk;
|
||||
}
|
||||
|
||||
bool AddPvpTalent(PvpTalentRecord talent, byte activeTalentGroup, byte slot)
|
||||
{
|
||||
//ASSERT(talent);
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talent.SpellID, Difficulty.None);
|
||||
if (spellInfo == null)
|
||||
{
|
||||
Log.outError(LogFilter.Spells, $"Player.AddPvpTalent: Spell (ID: {talent.SpellID}) does not exist.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Global.SpellMgr.IsSpellValid(spellInfo, this, false))
|
||||
{
|
||||
Log.outError(LogFilter.Spells, $"Player.AddPvpTalent: Spell (ID: {talent.SpellID}) is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HasPvpRulesEnabled())
|
||||
LearnSpell(talent.SpellID, false);
|
||||
|
||||
// Move this to toggle ?
|
||||
if (talent.OverridesSpellID != 0)
|
||||
AddOverrideSpell(talent.OverridesSpellID, talent.SpellID);
|
||||
|
||||
GetPvpTalentMap(activeTalentGroup)[slot] = talent.Id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemovePvpTalent(PvpTalentRecord talent, byte activeTalentGroup)
|
||||
{
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talent.SpellID, Difficulty.None);
|
||||
if (spellInfo == null)
|
||||
return;
|
||||
|
||||
RemoveSpell(talent.SpellID, true);
|
||||
|
||||
// Move this to toggle ?
|
||||
if (talent.OverridesSpellID != 0)
|
||||
RemoveOverrideSpell(talent.OverridesSpellID, talent.SpellID);
|
||||
|
||||
// if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted
|
||||
var talents = GetPvpTalentMap(activeTalentGroup);
|
||||
for (var i = 0; i < PlayerConst.MaxPvpTalentSlots; ++i)
|
||||
{
|
||||
if (talents[i] == talent.Id)
|
||||
talents[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void TogglePvpTalents(bool enable)
|
||||
{
|
||||
var pvpTalents = GetPvpTalentMap(GetActiveTalentGroup());
|
||||
foreach (uint pvpTalentId in pvpTalents)
|
||||
{
|
||||
PvpTalentRecord pvpTalentInfo = CliDB.PvpTalentStorage.LookupByKey(pvpTalentId);
|
||||
if (pvpTalentInfo != null)
|
||||
{
|
||||
if (enable)
|
||||
LearnSpell(pvpTalentInfo.SpellID, false);
|
||||
else
|
||||
RemoveSpell(pvpTalentInfo.SpellID, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HasPvpTalent(uint talentID, byte activeTalentGroup)
|
||||
{
|
||||
return GetPvpTalentMap(activeTalentGroup).Contains(talentID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5379,9 +5379,6 @@ namespace Game.Entities
|
||||
InitTalentForLevel();
|
||||
InitTaxiNodesForLevel();
|
||||
|
||||
if (level < PlayerConst.LevelMinHonor)
|
||||
ResetPvpTalents();
|
||||
|
||||
UpdateAllStats();
|
||||
|
||||
_ApplyAllLevelScaleItemMods(true); // Moved to above SetFullHealth so player will have full health from Heirlooms
|
||||
|
||||
Reference in New Issue
Block a user