From 02535a0d47429b502d7b44c12cabcccb1b286e3e Mon Sep 17 00:00:00 2001 From: hondacrx Date: Mon, 13 Nov 2017 14:12:42 -0500 Subject: [PATCH] Fixed DK runes and runic power --- Source/Game/Entities/Object/WorldObject.cs | 49 ++++++++------ Source/Game/Entities/Player/Player.DB.cs | 12 ++++ Source/Game/Entities/Player/Player.Fields.cs | 11 ++-- Source/Game/Entities/Player/Player.Spells.cs | 69 ++++++-------------- Source/Game/Entities/Player/Player.cs | 33 +--------- Source/Game/Entities/Unit/Unit.Combat.cs | 10 --- Source/Game/Spells/Spell.cs | 17 +++-- Source/Game/Spells/SpellInfo.cs | 2 - Source/Scripts/Spells/DeathKnight.cs | 7 +- 9 files changed, 80 insertions(+), 130 deletions(-) diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 47eeb465e..ded192762 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -329,7 +329,7 @@ namespace Game.Entities bool ThisIsYou = flags.HasAnyFlag(UpdateFlag.Self); bool SmoothPhasing = false; bool SceneObjCreate = false; - bool PlayerCreateData = false; + bool PlayerCreateData = GetTypeId() == TypeId.Player && ToUnit().GetPowerIndex(PowerType.Runes) != (int)PowerType.Max; int PauseTimesCount = 0; GameObject go = ToGameObject(); @@ -787,26 +787,33 @@ namespace Game.Entities // } //} - //if (PlayerCreateData) - //{ - // data.WriteBit(HasSceneInstanceIDs); - // data.WriteBit(HasRuneState); - // data.FlushBits(); - // if (HasSceneInstanceIDs) - // { - // *data << uint32(SceneInstanceIDs.size()); - // for (std::size_t i = 0; i < SceneInstanceIDs.size(); ++i) - // *data << uint32(SceneInstanceIDs[i]); - // } - // if (HasRuneState) - // { - // *data << uint8(RechargingRuneMask); - // *data << uint8(UsableRuneMask); - // *data << uint32(ToUnit().GetMaxPower(POWER_RUNES)); - // for (uint32 i = 0; i < ToUnit().GetMaxPower(POWER_RUNES); ++i) - // *data << uint8(255 - (ToUnit().ToPlayer().GetRuneCooldown(i) * 51)); - // } - //} + if (PlayerCreateData) + { + bool HasSceneInstanceIDs = false; + bool HasRuneState = ToUnit().GetPowerIndex(PowerType.Runes) != (int)PowerType.Max; + + data.WriteBit(HasSceneInstanceIDs); + data.WriteBit(HasRuneState); + data.FlushBits(); + //if (HasSceneInstanceIDs) + //{ + // *data << uint32(SceneInstanceIDs.size()); + // for (std::size_t i = 0; i < SceneInstanceIDs.size(); ++i) + // *data << uint32(SceneInstanceIDs[i]); + //} + if (HasRuneState) + { + Player player = ToPlayer(); + float baseCd = player.GetRuneBaseCooldown(); + uint maxRunes = (uint)player.GetMaxPower(PowerType.Runes); + + data.WriteUInt8((1 << (int)maxRunes) - 1u); + data.WriteUInt8(player.GetRunesState()); + data.WriteUInt32(maxRunes); + for (byte i = 0; i < maxRunes; ++i) + data.WriteUInt8((baseCd - (float)player.GetRuneCooldown(i)) / baseCd * 255); + } + } } public virtual void BuildValuesUpdate(UpdateType updatetype, ByteBuffer data, Player target) diff --git a/Source/Game/Entities/Player/Player.DB.cs b/Source/Game/Entities/Player/Player.DB.cs index 31d8754c9..de5a821c6 100644 --- a/Source/Game/Entities/Player/Player.DB.cs +++ b/Source/Game/Entities/Player/Player.DB.cs @@ -2942,6 +2942,18 @@ namespace Game.Entities SetUInt32Value(UnitFields.Power + loadedPowers, 0); SetPower(PowerType.LunarPower, 0); + // Init rune recharge + if (GetPowerIndex(PowerType.Runes) != (int)PowerType.Max) + { + int runes = GetPower(PowerType.Runes); + int maxRunes = GetMaxPower(PowerType.Runes); + uint runeCooldown = GetRuneBaseCooldown(); + while (runes < maxRunes) + { + SetRuneCooldown((byte)runes, runeCooldown, false); + ++runes; + } + } Log.outDebug(LogFilter.Player, "The value of player {0} after load item and aura is: ", GetName()); diff --git a/Source/Game/Entities/Player/Player.Fields.cs b/Source/Game/Entities/Player/Player.Fields.cs index 61dfc43f0..2af6f1672 100644 --- a/Source/Game/Entities/Player/Player.Fields.cs +++ b/Source/Game/Entities/Player/Player.Fields.cs @@ -117,9 +117,6 @@ namespace Game.Entities MultiMap m_overrideSpells = new MultiMap(); public Spell m_spellModTakingSpell; uint m_oldpetspell; - // Rune type / Rune timer - uint[] m_runeGraceCooldown = new uint[PlayerConst.MaxRunes]; - uint[] m_lastRuneGraceTimers = new uint[PlayerConst.MaxRunes]; //Mail List m_mail = new List(); @@ -347,14 +344,14 @@ namespace Game.Entities if (set) { RuneState |= (byte)(1 << index); // usable - if (id == 0) - CooldownOrder.Add(index); + if (id != 0) + CooldownOrder.RemoveAt(index); } else { RuneState &= (byte)~(1 << index); // on cooldown - if (id != 0) - CooldownOrder.Remove(id); + if (id == 0) + CooldownOrder.Add(index); } } diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index b3fc75347..be6e6e94b 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -2852,22 +2852,16 @@ namespace Game.Entities /**********************************/ public void SetRuneCooldown(byte index, uint cooldown, bool casted = false) { - uint gracePeriod = GetRuneTimer(index); - - if (casted && IsInCombat()) - { - if (gracePeriod < 0xFFFFFFFF && cooldown > 0) - { - uint lessCd = Math.Min(2500, gracePeriod); - cooldown = (cooldown > lessCd) ? (cooldown - lessCd) : 0; - SetLastRuneGraceTimer(index, lessCd); - } - - SetRuneTimer(index, 0); - } - m_runes.Cooldown[index] = cooldown; m_runes.SetRuneState(index, (cooldown == 0) ? true : false); + uint activeRunes = m_runes.Cooldown[Math.Min(GetMaxPower(PowerType.Runes), (int)PowerType.Max)]; + if (activeRunes != GetPower(PowerType.Runes)) + SetPower(PowerType.Runes, (int)activeRunes); + } + + public byte GetRunesState() + { + return (byte)(m_runes.RuneState & ((1 << GetMaxPower(PowerType.Runes)) - 1)); } public uint GetRuneBaseCooldown() @@ -2894,28 +2888,15 @@ namespace Game.Entities public void ResyncRunes() { - ResyncRunes data = new ResyncRunes(); - data.Runes.Start = 0; + int maxRunes = GetMaxPower(PowerType.Runes); + + ResyncRunes data = new ResyncRunes(maxRunes); + data.Runes.Start = (byte)((1 << maxRunes) - 1); data.Runes.Count = GetRunesState(); - for (byte i = 0; i < PlayerConst.MaxRunes; ++i) - data.Runes.Cooldowns.Add((byte)(255 - (GetRuneCooldown(i) * 51))); - - // calculate mask of recharging runes - uint regeneratedRunes = 0; - int regenIndex = 0; - while (regeneratedRunes < PlayerConst.MaxRechargingRunes && !m_runes.CooldownOrder.Empty()) - { - byte runeToRegen = m_runes.CooldownOrder[regenIndex++]; - uint runeCooldown = GetRuneCooldown(runeToRegen); - if (runeCooldown > m_regenTimer) - { - data.Runes.Start |= (byte)(1 << runeToRegen); - ++regenIndex; - } - - ++regeneratedRunes; - } + float baseCd = GetRuneBaseCooldown(); + for (byte i = 0; i < maxRunes; ++i) + data.Runes.Cooldowns.Add((byte)((baseCd - GetRuneCooldown(i)) / baseCd * 255)); SendPacket(data); } @@ -2940,15 +2921,11 @@ namespace Game.Entities m_runes.RuneState = 0; for (byte i = 0; i < PlayerConst.MaxRunes; ++i) - { SetRuneCooldown(i, 0); // reset cooldowns - SetRuneTimer(i, 0xFFFFFFFF); // Reset rune flags - SetLastRuneGraceTimer(i, 0); - } // set a base regen timer equal to 10 sec - SetStatFloatValue(UnitFields.PowerRegenFlatModifier + runeIndex, 0.1f); - SetStatFloatValue(UnitFields.PowerRegenInterruptedFlatModifier + runeIndex, 0.1f); + SetStatFloatValue(UnitFields.PowerRegenFlatModifier + runeIndex, 0.0f); + SetStatFloatValue(UnitFields.PowerRegenInterruptedFlatModifier + runeIndex, 0.0f); } public void UpdateAllRunesRegen() @@ -2960,19 +2937,15 @@ namespace Game.Entities if (runeIndex == (int)PowerType.Max) return; + PowerTypeRecord runeEntry = Global.DB2Mgr.GetPowerTypeEntry(PowerType.Runes); + uint cooldown = GetRuneBaseCooldown(); - SetStatFloatValue(UnitFields.PowerRegenFlatModifier + runeIndex, (float)(1 * Time.InMilliseconds) / cooldown); - SetStatFloatValue(UnitFields.PowerRegenInterruptedFlatModifier + runeIndex, (float)(1 * Time.InMilliseconds) / cooldown); + SetStatFloatValue(UnitFields.PowerRegenFlatModifier + runeIndex, (float)(1 * Time.InMilliseconds) / (float)cooldown - runeEntry.RegenerationPeace); + SetStatFloatValue(UnitFields.PowerRegenInterruptedFlatModifier + runeIndex, (float)(1 * Time.InMilliseconds) / (float)cooldown - runeEntry.RegenerationCombat); } - public byte GetRunesState() { return m_runes.RuneState; } public uint GetRuneCooldown(byte index) { return m_runes.Cooldown[index]; } - public uint GetRuneTimer(byte index) { return m_runeGraceCooldown[index]; } - public void SetRuneTimer(byte index, uint timer) { m_runeGraceCooldown[index] = timer; } - public uint GetLastRuneGraceTimer(byte index) { return m_lastRuneGraceTimers[index]; } - public void SetLastRuneGraceTimer(byte index, uint timer) { m_lastRuneGraceTimers[index] = timer; } - public bool CanNoReagentCast(SpellInfo spellInfo) { // don't take reagents for spells with SPELL_ATTR5_NO_REAGENT_WHILE_PREP diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index d7628a29c..a7cc45ebe 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -66,13 +66,6 @@ namespace Game.Entities PlayerTalkClass = new PlayerMenu(session); m_currentBuybackSlot = InventorySlots.BuyBackStart; - // Init rune flags - for (byte i = 0; i < PlayerConst.MaxRunes; ++i) - { - SetRuneTimer(i, 0xFFFFFFFF); - SetLastRuneGraceTimer(i, 0); - } - for (byte i = 0; i < (int)MirrorTimerType.Max; i++) m_MirrorTimer[i] = -1; @@ -744,26 +737,6 @@ namespace Game.Entities } } - if (GetClass() == Class.Deathknight) - { - // Update rune timers - for (byte i = 0; i < PlayerConst.MaxRunes; ++i) - { - uint timer = GetRuneTimer(i); - - // Don't update timer if rune is disabled - if (GetRuneCooldown(i) != 0) - continue; - - // Timer has began - if (timer < 0xFFFFFFFF) - { - timer += diff; - SetRuneTimer(i, Math.Min(2500, timer)); - } - } - } - // group update SendUpdateToOutOfRangeGroupMembers(); @@ -3745,9 +3718,9 @@ namespace Game.Entities { uint regeneratedRunes = 0; int regenIndex = 0; - while (regeneratedRunes < PlayerConst.MaxRechargingRunes && !m_runes.CooldownOrder.Empty()) + while (regeneratedRunes < PlayerConst.MaxRechargingRunes && m_runes.CooldownOrder.Count > regenIndex) { - byte runeToRegen = m_runes.CooldownOrder[regenIndex++]; + byte runeToRegen = m_runes.CooldownOrder[regenIndex]; uint runeCooldown = GetRuneCooldown(runeToRegen); if (runeCooldown > m_regenTimer) { @@ -3755,7 +3728,7 @@ namespace Game.Entities ++regenIndex; } else - SetRuneCooldown((byte)runeCooldown, 0); + SetRuneCooldown(runeToRegen, 0); ++regeneratedRunes; } diff --git a/Source/Game/Entities/Unit/Unit.Combat.cs b/Source/Game/Entities/Unit/Unit.Combat.cs index a36e46a81..fbc93bd0e 100644 --- a/Source/Game/Entities/Unit/Unit.Combat.cs +++ b/Source/Game/Entities/Unit/Unit.Combat.cs @@ -251,16 +251,6 @@ namespace Game.Entities m_CombatTimer = 0; RemoveFlag(UnitFields.Flags, UnitFlags.InCombat); - // Reset rune flags after combat - if (IsTypeId(TypeId.Player) && GetClass() == Class.Deathknight) - { - for (byte i = 0; i < PlayerConst.MaxRunes; ++i) - { - ToPlayer().SetRuneTimer(i, 0xFFFFFFFF); - ToPlayer().SetLastRuneGraceTimer(i, 0); - } - } - // Player's state will be cleared in Player.UpdateContestedPvP Creature creature = ToCreature(); if (creature != null) diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 140a0a9f6..726c35119 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -3543,7 +3543,7 @@ namespace Game.Spells { runeData.Start = m_runesState; // runes state before runeData.Count = player.GetRunesState(); // runes state after - for (byte i = 0; i < PlayerConst.MaxRunes; ++i) + for (byte i = 0; i < player.GetMaxPower(PowerType.Runes); ++i) { // float casts ensure the division is performed on floats as we need float result float baseCd = player.GetRuneBaseCooldown(); @@ -3554,7 +3554,7 @@ namespace Game.Spells { runeData.Start = 0; runeData.Count = 0; - for (byte i = 0; i < PlayerConst.MaxRunes; ++i) + for (byte i = 0; i < player.GetMaxPower(PowerType.Runes); ++i) runeData.Cooldowns.Add(0); } } @@ -3659,7 +3659,7 @@ namespace Game.Spells { runeData.Start = m_runesState; // runes state before runeData.Count = player.GetRunesState(); // runes state after - for (byte i = 0; i < PlayerConst.MaxRunes; ++i) + for (byte i = 0; i < player.GetMaxPower(PowerType.Runes); ++i) { // float casts ensure the division is performed on floats as we need float result float baseCd = player.GetRuneBaseCooldown(); @@ -3670,7 +3670,7 @@ namespace Game.Spells { runeData.Start = 0; runeData.Count = 0; - for (byte i = 0; i < PlayerConst.MaxRunes; ++i) + for (byte i = 0; i < player.GetMaxPower(PowerType.Runes); ++i) runeData.Cooldowns.Add(0); } } @@ -4148,8 +4148,8 @@ namespace Game.Spells SpellCastResult CheckRuneCost() { - var runeCost = m_powerCost.Find(cost => cost.Power == PowerType.Runes); - if (runeCost == null) + int runeCost = m_powerCost.Sum(cost => cost.Power == PowerType.Runes ? cost.Amount : 0); + if (runeCost == 0) return SpellCastResult.SpellCastOk; Player player = m_caster.ToPlayer(); @@ -4164,7 +4164,7 @@ namespace Game.Spells if (player.GetRuneCooldown(i) == 0) ++readyRunes; - if (readyRunes < runeCost.Amount) + if (readyRunes < runeCost) return SpellCastResult.NoPower; // not sure if result code is correct return SpellCastResult.SpellCastOk; @@ -4178,8 +4178,7 @@ namespace Game.Spells Player player = m_caster.ToPlayer(); m_runesState = player.GetRunesState(); // store previous state - int runeCost = m_powerCost.Find(cost => cost.Power == PowerType.Runes).Amount; - + int runeCost = m_powerCost.Sum(cost => cost.Power == PowerType.Runes ? cost.Amount : 0); for (byte i = 0; i < player.GetMaxPower(PowerType.Runes); ++i) { if (player.GetRuneCooldown(i) == 0 && runeCost > 0) diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index 8fff5e947..e3e2637a9 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -2308,8 +2308,6 @@ namespace Game.Spells else collector(Global.DB2Mgr.GetSpellPowers(Id, caster.GetMap().GetDifficultyID())); - // POWER_RUNES is handled by SpellRuneCost.db2, and cost.Amount is always 0 (see Spell.TakeRunePower) - costs.RemoveAll(cost => cost.Power != PowerType.Runes && cost.Amount <= 0); return costs; } diff --git a/Source/Scripts/Spells/DeathKnight.cs b/Source/Scripts/Spells/DeathKnight.cs index 7d56589b7..af7a1c280 100644 --- a/Source/Scripts/Spells/DeathKnight.cs +++ b/Source/Scripts/Spells/DeathKnight.cs @@ -88,11 +88,12 @@ namespace Scripts.Spells.DeathKnight Unit caster = eventInfo.GetActor(); if (caster) { - if (!caster.IsTypeId(TypeId.Player) || caster.GetClass() != Class.Deathknight) + Player player = caster.ToPlayer(); + if (!player || caster.GetClass() != Class.Deathknight) return false; - for (byte i = 0; i < PlayerConst.MaxRunes; ++i) - if (caster.ToPlayer().GetRuneCooldown(i) == 0) + for (byte i = 0; i < player.GetMaxPower(PowerType.Runes); ++i) + if (player.GetRuneCooldown(i) == 0) return false; return true;