Core/Player: Implement PvP Talents

This commit is contained in:
hondacrx
2018-03-06 11:10:51 -05:00
parent 42fc86c400
commit c842332393
26 changed files with 631 additions and 68 deletions
@@ -393,6 +393,9 @@ namespace Game.Entities
SendMessageToSet(duelWinner, true);
}
duel.opponent.DisablePvpRules();
DisablePvpRules();
Global.ScriptMgr.OnPlayerDuelEnd(duel.opponent, this, type);
switch (type)
+40
View File
@@ -948,6 +948,20 @@ namespace Game.Entities
while (result.NextRow());
}
}
void _LoadPvpTalents(SQLResult result)
{
// "SELECT TalentID, TalentGroup FROM character_pvp_talent WHERE guid = ?"
if (!result.IsEmpty())
{
do
{
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(result.Read<uint>(0));
if (talent != null)
AddPvpTalent(talent, result.Read<byte>(1), false);
}
while (result.NextRow());
}
}
void _LoadGlyphs(SQLResult result)
{
// SELECT talentGroup, glyphId from character_glyphs WHERE guid = ?
@@ -1977,6 +1991,29 @@ namespace Game.Entities
trans.Append(stmt);
}
}
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_PVP_TALENT);
stmt.AddValue(0, GetGUID().GetCounter());
trans.Append(stmt);
for (byte group = 0; group < PlayerConst.MaxSpecializations; ++group)
{
talents = GetPvpTalentMap(group);
foreach (var pair in talents.ToList())
{
if (pair.Value == PlayerSpellState.Removed)
{
talents.Remove(pair.Key);
continue;
}
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_PVP_TALENT);
stmt.AddValue(0, GetGUID().GetCounter());
stmt.AddValue(1, pair.Key);
stmt.AddValue(2, group);
trans.Append(stmt);
}
}
}
public void _SaveMail(SQLTransaction trans)
{
@@ -2852,6 +2889,7 @@ namespace Game.Entities
SetUInt32Value(PlayerFields.CurrentSpecId, spec.Id);
_LoadTalents(holder.GetResult(PlayerLoginQueryLoad.Talents));
_LoadPvpTalents(holder.GetResult(PlayerLoginQueryLoad.PvpTalents));
_LoadSpells(holder.GetResult(PlayerLoginQueryLoad.Spells));
GetSession().GetCollectionMgr().LoadToys();
GetSession().GetCollectionMgr().LoadHeirlooms();
@@ -2880,6 +2918,8 @@ 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));
@@ -317,11 +317,13 @@ namespace Game.Entities
for (byte i = 0; i < PlayerConst.MaxSpecializations; ++i)
{
Talents[i] = new Dictionary<uint, PlayerSpellState>();
PvpTalents[i] = new Dictionary<uint, PlayerSpellState>();
Glyphs[i] = new List<uint>();
}
}
public Dictionary<uint, PlayerSpellState>[] Talents = new Dictionary<uint, PlayerSpellState>[PlayerConst.MaxSpecializations];
public Dictionary<uint, PlayerSpellState>[] PvpTalents = new Dictionary<uint, PlayerSpellState>[PlayerConst.MaxSpecializations];
public List<uint>[] Glyphs = new List<uint>[PlayerConst.MaxSpecializations];
public uint ResetTalentsCost;
public long ResetTalentsTime;
@@ -122,6 +122,11 @@ namespace Game.Entities
UpdateAreaDependentAuras(newArea);
UpdateAreaAndZonePhase();
if (IsAreaThatActivatesPvpTalents(newArea))
EnablePvpRules();
else
DisablePvpRules();
// previously this was in UpdateZone (but after UpdateArea) so nothing will break
pvpInfo.IsInNoPvPArea = false;
if (area != null && area.IsSanctuary()) // in sanctuary
+212
View File
@@ -23,6 +23,7 @@ using Game.BattleGrounds;
using Game.DataStorage;
using Game.Network.Packets;
using Game.PvP;
using Game.Spells;
using System;
using System.Collections.Generic;
@@ -333,6 +334,217 @@ namespace Game.Entities
public uint GetHonorLevel() { return GetUInt32Value(PlayerFields.HonorLevel); }
public bool IsMaxHonorLevelAndPrestige() { return IsMaxPrestige() && GetHonorLevel() == PlayerConst.MaxHonorLevel; }
void ResetPvpTalents()
{
foreach (var talentInfo in CliDB.PvpTalentStorage.Values)
{
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
continue;
RemovePvpTalent(talentInfo);
}
SQLTransaction trans = new SQLTransaction();
_SaveTalents(trans);
_SaveSpells(trans);
DB.Characters.CommitTransaction(trans);
}
public TalentLearnResult LearnPvpTalent(uint talentID, ref uint spellOnCooldown)
{
if (IsInCombat())
return TalentLearnResult.FailedAffectingCombat;
if (getLevel() < PlayerConst.LevelMinHonor)
return TalentLearnResult.FailedUnknown;
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(talentID);
if (talentInfo == null)
return TalentLearnResult.FailedUnknown;
if (talentInfo.SpecID != 0)
{
if (talentInfo.SpecID != GetInt32Value(PlayerFields.CurrentSpecId))
return TalentLearnResult.FailedUnknown;
}
else if (talentInfo.Role < 7)
{
if (talentInfo.Role != CliDB.ChrSpecializationStorage.LookupByKey(GetUInt32Value(PlayerFields.CurrentSpecId)).Role)
return TalentLearnResult.FailedUnknown;
}
// prevent learn talent for different class (cheating)
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
return TalentLearnResult.FailedUnknown;
if (GetPrestigeLevel() == 0)
if (Global.DB2Mgr.GetRequiredHonorLevelForPvpTalent(talentInfo) > GetHonorLevel())
return TalentLearnResult.FailedUnknown;
// Check if player doesn't have any talent in current tier
for (uint c = 0; c < PlayerConst.MaxPvpTalentColumns; ++c)
{
foreach (PvpTalentRecord talent in Global.DB2Mgr.GetPvpTalentsByPosition((uint)GetClass(), (uint)talentInfo.TierID, c))
{
if (HasPvpTalent(talent.Id, GetActiveTalentGroup()) && !HasFlag(PlayerFields.Flags, PlayerFlags.Resting) && HasFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc))
return TalentLearnResult.FailedRestArea;
if (GetSpellHistory().HasCooldown(talent.SpellID))
{
spellOnCooldown = talent.SpellID;
return TalentLearnResult.FailedCantRemoveTalent;
}
RemovePvpTalent(talent);
}
}
if (!AddPvpTalent(talentInfo, GetActiveTalentGroup(), true))
return TalentLearnResult.FailedUnknown;
return TalentLearnResult.LearnOk;
}
bool AddPvpTalent(PvpTalentRecord talent, byte activeTalentGroup, bool learning)
{
//ASSERT(talent);
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talent.SpellID);
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);
if (learning)
GetPvpTalentMap(activeTalentGroup)[talent.Id] = PlayerSpellState.New;
else
GetPvpTalentMap(activeTalentGroup)[talent.Id] = PlayerSpellState.Unchanged;
return true;
}
void RemovePvpTalent(PvpTalentRecord talent)
{
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talent.SpellID);
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
if (!GetPvpTalentMap(GetActiveTalentGroup()).ContainsKey(talent.Id))
GetPvpTalentMap(GetActiveTalentGroup())[talent.Id] = PlayerSpellState.Removed;
}
public void TogglePvpTalents(bool enable)
{
var pvpTalents = GetPvpTalentMap(GetActiveTalentGroup());
foreach (var pair in pvpTalents)
{
PvpTalentRecord pvpTalentInfo = CliDB.PvpTalentStorage.LookupByKey(pair.Key);
if (enable && pair.Value != PlayerSpellState.Removed)
LearnSpell(pvpTalentInfo.SpellID, false);
else
RemoveSpell(pvpTalentInfo.SpellID, true);
}
}
bool HasPvpTalent(uint talentID, byte activeTalentGroup)
{
return GetPvpTalentMap(activeTalentGroup).ContainsKey(talentID) && GetPvpTalentMap(activeTalentGroup)[talentID] != PlayerSpellState.Removed;
}
public void EnablePvpRules(bool dueToCombat = false)
{
if (HasPvpRulesEnabled())
return;
if (!HasSpell(195710)) // Honorable Medallion
CastSpell(this, 208682); // Learn Gladiator's Medallion
CastSpell(this, PlayerConst.SpellPvpRulesEnabled);
if (!dueToCombat)
{
Aura aura = GetAura(PlayerConst.SpellPvpRulesEnabled);
if (aura != null)
{
aura.SetMaxDuration(-1);
aura.SetDuration(-1);
}
}
}
void DisablePvpRules()
{
// Don't disable pvp rules when in pvp zone.
if (IsInAreaThatActivatesPvpTalents())
return;
if (GetCombatTimer() == 0)
RemoveAurasDueToSpell(PlayerConst.SpellPvpRulesEnabled);
else
{
Aura aura = GetAura(PlayerConst.SpellPvpRulesEnabled);
if (aura != null)
aura.SetDuration(aura.GetSpellInfo().GetMaxDuration());
}
}
bool HasPvpRulesEnabled()
{
return HasAura(PlayerConst.SpellPvpRulesEnabled);
}
bool IsInAreaThatActivatesPvpTalents()
{
return IsAreaThatActivatesPvpTalents(GetAreaId());
}
bool IsAreaThatActivatesPvpTalents(uint areaID)
{
if (InBattleground())
return true;
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(areaID);
if (area != null)
{
do
{
if (area.IsSanctuary())
return false;
if (area.Flags[0].HasAnyFlag(AreaFlags.Arena))
return true;
if (Global.BattleFieldMgr.GetBattlefieldToZoneId(area.Id) != null)
return true;
area = CliDB.AreaTableStorage.LookupByKey(area.ParentAreaID);
} while (area != null);
}
return false;
}
public Dictionary<uint, PlayerSpellState> GetPvpTalentMap(uint spec) { return _specializationInfo.PvpTalents[spec]; }
//BGs
public Battleground GetBattleground()
+65 -1
View File
@@ -306,6 +306,32 @@ namespace Game.Entities
RemoveOverrideSpell(talentInfo.OverridesSpellID, talentInfo.SpellID);
}
foreach (var talentInfo in CliDB.PvpTalentStorage.Values)
{
// unlearn only talents for character class
// some spell learned by one class as normal spells or know at creation but another class learn it as talent,
// to prevent unexpected lost normal learned spell skip another class talents
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
continue;
if (talentInfo.SpellID == 0)
continue;
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talentInfo.SpellID);
if (spellInfo == null)
continue;
RemoveSpell(talentInfo.SpellID, true);
// search for spells that the talent teaches and unlearn them
foreach (SpellEffectInfo effect in spellInfo.GetEffectsForDifficulty(Difficulty.None))
if (effect != null && effect.TriggerSpell > 0 && effect.Effect == SpellEffectName.LearnSpell)
RemoveSpell(effect.TriggerSpell, true);
if (talentInfo.OverridesSpellID != 0)
RemoveOverrideSpell(talentInfo.OverridesSpellID, talentInfo.SpellID);
}
// Remove spec specific spells
RemoveSpecializationSpells();
@@ -334,6 +360,19 @@ namespace Game.Entities
}
}
foreach (var talentInfo in CliDB.PvpTalentStorage.Values)
{
// learn only talents for character class (or x-class talents)
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
continue;
if (talentInfo.SpellID == 0)
continue;
if (HasPvpTalent(talentInfo.Id, GetActiveTalentGroup()))
AddPvpTalent(talentInfo, GetActiveTalentGroup(), true);
}
LearnSpecializationSpells();
if (CanUseMastery())
@@ -498,7 +537,7 @@ namespace Game.Entities
continue;
var talents = GetTalentMap(i);
var pvpTalents = GetPvpTalentMap(i);
UpdateTalentData.TalentGroupInfo groupInfoPkt = new UpdateTalentData.TalentGroupInfo();
groupInfoPkt.SpecID = spec.Id;
@@ -528,6 +567,31 @@ namespace Game.Entities
groupInfoPkt.TalentIDs.Add((ushort)pair.Key);
}
foreach (var pair in pvpTalents)
{
if (pair.Value == PlayerSpellState.Removed)
continue;
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(pair.Key);
if (talentInfo == null)
{
Log.outError(LogFilter.Player, $"Player.SendTalentsInfoData: Player '{GetName()}' ({GetGUID().ToString()}) has unknown pvp talent id: {pair.Key}");
continue;
}
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
continue;
SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(talentInfo.SpellID);
if (spellEntry == null)
{
Log.outError(LogFilter.Player, $"Player.SendTalentsInfoData: Player '{GetName()}' ({GetGUID().ToString()}) has unknown pvp talent spell: {talentInfo.SpellID}");
continue;
}
groupInfoPkt.PvPTalentIDs.Add((ushort)pair.Key);
}
packet.Info.TalentGroups.Add(groupInfoPkt);
}
+11
View File
@@ -494,6 +494,14 @@ namespace Game.Entities
UpdateAfkReport(now);
if (GetCombatTimer() != 0) // Only set when in pvp combat
{
Aura aura = GetAura(PlayerConst.SpellPvpRulesEnabled);
if (aura != null)
if (!aura.IsPermanent())
aura.SetDuration(aura.GetSpellInfo().GetMaxDuration());
}
if (IsAIEnabled && GetAI() != null)
GetAI().UpdateAI(diff);
else if (NeedChangeAI)
@@ -5307,6 +5315,9 @@ namespace Game.Entities
InitTalentForLevel();
InitTaxiNodesForLevel();
if (level < PlayerConst.LevelMinHonor)
ResetPvpTalents();
UpdateAllStats();
if (WorldConfig.GetBoolValue(WorldCfg.AlwaysMaxskill)) // Max weapon skill when leveling up
+5
View File
@@ -1279,7 +1279,12 @@ namespace Game.Entities
return;
if (PvP)
{
m_CombatTimer = 5000;
Player me = ToPlayer();
if (me)
me.EnablePvpRules(true);
}
if (IsInCombat() || HasUnitState(UnitState.Evade))
return;