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
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ namespace Framework.Constants
|
|||||||
public const int MaxArtifactTier = 1;
|
public const int MaxArtifactTier = 1;
|
||||||
|
|
||||||
public const int MaxHonorLevel = 500;
|
public const int MaxHonorLevel = 500;
|
||||||
public const byte LevelMinHonor = 20;
|
public const byte LevelMinHonor = 10;
|
||||||
public const uint SpellPvpRulesEnabled = 134735;
|
public const uint SpellPvpRulesEnabled = 134735;
|
||||||
|
|
||||||
//Azerite
|
//Azerite
|
||||||
|
|||||||
@@ -3153,8 +3153,6 @@ namespace Game.Entities
|
|||||||
InitTalentForLevel();
|
InitTalentForLevel();
|
||||||
LearnDefaultSkills();
|
LearnDefaultSkills();
|
||||||
LearnCustomSpells();
|
LearnCustomSpells();
|
||||||
if (GetLevel() < PlayerConst.LevelMinHonor)
|
|
||||||
ResetPvpTalents();
|
|
||||||
|
|
||||||
// must be before inventory (some items required reputation check)
|
// must be before inventory (some items required reputation check)
|
||||||
reputationMgr.LoadFromDB(holder.GetResult(PlayerLoginQueryLoad.Reputation));
|
reputationMgr.LoadFromDB(holder.GetResult(PlayerLoginQueryLoad.Reputation));
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ using Game.PvP;
|
|||||||
using Game.Spells;
|
using Game.Spells;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Game.Entities
|
namespace Game.Entities
|
||||||
{
|
{
|
||||||
@@ -308,146 +307,6 @@ namespace Game.Entities
|
|||||||
public void ActivatePvpItemLevels(bool activate) { _usePvpItemLevels = activate; }
|
public void ActivatePvpItemLevels(bool activate) { _usePvpItemLevels = activate; }
|
||||||
public bool IsUsingPvpItemLevels() { return _usePvpItemLevels; }
|
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)
|
public void EnablePvpRules(bool dueToCombat = false)
|
||||||
{
|
{
|
||||||
if (HasPvpRulesEnabled())
|
if (HasPvpRulesEnabled())
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ using Framework.Database;
|
|||||||
using Game.DataStorage;
|
using Game.DataStorage;
|
||||||
using Game.Networking.Packets;
|
using Game.Networking.Packets;
|
||||||
using Game.Spells;
|
using Game.Spells;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Game.Entities
|
namespace Game.Entities
|
||||||
@@ -52,6 +53,19 @@ namespace Game.Entities
|
|||||||
|
|
||||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.MaxTalentTiers), talentTiers);
|
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())
|
if (!GetSession().PlayerLoading())
|
||||||
SendTalentsInfoData(); // update at client
|
SendTalentsInfoData(); // update at client
|
||||||
}
|
}
|
||||||
@@ -219,6 +233,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResetPvpTalents();
|
||||||
RemoveSpecializationSpells();
|
RemoveSpecializationSpells();
|
||||||
|
|
||||||
ChrSpecializationRecord defaultSpec = Global.DB2Mgr.GetDefaultChrSpecializationForClass(GetClass());
|
ChrSpecializationRecord defaultSpec = Global.DB2Mgr.GetDefaultChrSpecializationForClass(GetClass());
|
||||||
@@ -632,5 +647,143 @@ namespace Game.Entities
|
|||||||
respecWipeConfirm.RespecType = SpecResetType.Talents;
|
respecWipeConfirm.RespecType = SpecResetType.Talents;
|
||||||
SendPacket(respecWipeConfirm);
|
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();
|
InitTalentForLevel();
|
||||||
InitTaxiNodesForLevel();
|
InitTaxiNodesForLevel();
|
||||||
|
|
||||||
if (level < PlayerConst.LevelMinHonor)
|
|
||||||
ResetPvpTalents();
|
|
||||||
|
|
||||||
UpdateAllStats();
|
UpdateAllStats();
|
||||||
|
|
||||||
_ApplyAllLevelScaleItemMods(true); // Moved to above SetFullHealth so player will have full health from Heirlooms
|
_ApplyAllLevelScaleItemMods(true); // Moved to above SetFullHealth so player will have full health from Heirlooms
|
||||||
|
|||||||
Reference in New Issue
Block a user