diff --git a/Source/Framework/Constants/Spells/SpellAuraConst.cs b/Source/Framework/Constants/Spells/SpellAuraConst.cs index 8b3a31d1b..3db9614d9 100644 --- a/Source/Framework/Constants/Spells/SpellAuraConst.cs +++ b/Source/Framework/Constants/Spells/SpellAuraConst.cs @@ -241,7 +241,7 @@ namespace Framework.Constants ModMeleeHaste2 = 217, Unk218 = 218, // old SPELL_AURA_HASTE_RANGED ModManaRegenFromStat = 219, - ModRatingFromStat = 220, + ModAbilitySchoolMask = 220, //NYI ModDetaunt = 221, Unk222 = 222, Unk223 = 223, diff --git a/Source/Framework/Constants/Spells/SpellConst.cs b/Source/Framework/Constants/Spells/SpellConst.cs index 037cdc6a1..5a011a598 100644 --- a/Source/Framework/Constants/Spells/SpellConst.cs +++ b/Source/Framework/Constants/Spells/SpellConst.cs @@ -355,8 +355,9 @@ namespace Framework.Constants // spellmod 36 StackAmount2 = 37, // same as SPELLMOD_STACK_AMOUNT but affects tooltips // spellmod 38 + SpellCost3 = 39, - Max = 39 + Max = 40 } // Note: SPELLMOD_* values is aura types in fact public enum SpellModType diff --git a/Source/Game/Entities/Object/Update/UpdateFields.cs b/Source/Game/Entities/Object/Update/UpdateFields.cs index 3cedbbd5b..288d18688 100644 --- a/Source/Game/Entities/Object/Update/UpdateFields.cs +++ b/Source/Game/Entities/Object/Update/UpdateFields.cs @@ -1225,9 +1225,8 @@ namespace Game.Entities public UpdateFieldArray Resistances = new UpdateFieldArray(7, 167, 168); public UpdateFieldArray BonusResistanceMods = new UpdateFieldArray(7, 167, 175); public UpdateFieldArray PowerCostModifier = new UpdateFieldArray(7, 167, 182); - public UpdateFieldArray PowerCostMultiplier = new UpdateFieldArray(7, 167, 189); - public UnitData() : base(0, TypeId.Unit, 196) { } + public UnitData() : base(0, TypeId.Unit, 189) { } public void WriteCreate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, Unit owner, Player receiver) { @@ -1358,7 +1357,6 @@ namespace Game.Entities { data.WriteInt32(BonusResistanceMods[i]); data.WriteInt32(PowerCostModifier[i]); - data.WriteFloat(PowerCostMultiplier[i]); } } data.WriteUInt32(BaseMana); @@ -1421,7 +1419,7 @@ namespace Game.Entities public void WriteUpdate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, Unit owner, Player receiver) { - UpdateMask allowedMaskForTarget = new UpdateMask(192, new uint[] { 0xFFFFDFFFu, 0xE1FF7FFFu, 0x001EFFFFu, 0xFBFFFF81u, 0x03F8007Fu, 0x00000000u, 0x00000000u }); + UpdateMask allowedMaskForTarget = new UpdateMask(192, new uint[] { 0xFFFFDFFFu, 0xE1FF7FFFu, 0x001EFFFFu, 0xFBFFFF81u, 0x03F8007Fu, 0x00000000u }); AppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags); WriteUpdate(data, _changesMask & allowedMaskForTarget, false, owner, receiver); } @@ -1429,27 +1427,27 @@ namespace Game.Entities public void AppendAllowedFieldsMaskForFlag(UpdateMask allowedMaskForTarget, UpdateFieldFlag fieldVisibilityFlags) { if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag.Owner)) - allowedMaskForTarget |= new UpdateMask(192, new uint[] { 0x00002000u, 0x1E008000u, 0xFFE10000u, 0x0400007Eu, 0xFC07FF80u, 0xFFFFFFFFu, 0x0000000Fu }); + allowedMaskForTarget |= new UpdateMask(192, new uint[] { 0x00002000u, 0x1E008000u, 0xFFE10000u, 0x0400007Eu, 0xFC07FF80u, 0x1FFFFFFFu }); if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag.UnitAll)) - allowedMaskForTarget |= new UpdateMask(192, new uint[] { 0x00000000u, 0x00000000u, 0x00000000u, 0x04000000u, 0x0007FF80u, 0x00000000u, 0x00000000 }); + allowedMaskForTarget |= new UpdateMask(192, new uint[] { 0x00000000u, 0x00000000u, 0x00000000u, 0x04000000u, 0x0007FF80u, 0x00000000u }); if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag.Empath)) - allowedMaskForTarget |= new UpdateMask(192, new uint[] { 0x00000000u, 0x1E000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00007F80u, 0x00000000u }); + allowedMaskForTarget |= new UpdateMask(192, new uint[] { 0x00000000u, 0x1E000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00007F80u }); } public void FilterDisallowedFieldsMaskForFlag(UpdateMask changesMask, UpdateFieldFlag fieldVisibilityFlags) { if (!fieldVisibilityFlags.HasFlag(UpdateFieldFlag.Owner)) - changesMask &= new UpdateMask(192, new uint[] { 0xFFFFDFFFu, 0xE1FF7FFFu, 0x001EFFFFu, 0xFBFFFF81u, 0x03F8007Fu, 0x00000000u, 0xFFFFFFF0u }); + changesMask &= new UpdateMask(192, new uint[] { 0xFFFFDFFFu, 0xE1FF7FFFu, 0x001EFFFFu, 0xFBFFFF81u, 0x03F8007Fu, 0xE0000000u }); if (!fieldVisibilityFlags.HasFlag(UpdateFieldFlag.UnitAll)) - changesMask &= new UpdateMask(192, new uint[] { 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFBFFFFFFu, 0xFFF8007Fu, 0xFFFFFFFFu, 0xFFFFFFFFu }); + changesMask &= new UpdateMask(192, new uint[] { 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFBFFFFFFu, 0xFFF8007Fu, 0xFFFFFFFFu }); if (!fieldVisibilityFlags.HasFlag(UpdateFieldFlag.Empath)) - changesMask &= new UpdateMask(192, new uint[] { 0xFFFFFFFFu, 0xE1FFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFF807Fu, 0xFFFFFFFFu }); + changesMask &= new UpdateMask(192, new uint[] { 0xFFFFFFFFu, 0xE1FFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFF807Fu }); } public void WriteUpdate(WorldPacket data, UpdateMask changesMask, bool ignoreNestedChangesMask, Unit owner, Player receiver) { - data.WriteBits(changesMask.GetBlocksMask(0), 7); - for (uint i = 0; i < 7; ++i) + data.WriteBits(changesMask.GetBlocksMask(0), 6); + for (uint i = 0; i < 6; ++i) if (changesMask.GetBlock(i) != 0) data.WriteBits(changesMask.GetBlock(i), 32); @@ -2196,7 +2194,6 @@ namespace Game.Entities ClearChangesMask(Resistances); ClearChangesMask(BonusResistanceMods); ClearChangesMask(PowerCostModifier); - ClearChangesMask(PowerCostMultiplier); _changesMask.ResetAll(); } diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index fcd40f403..f1a8a08fe 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -5652,6 +5652,8 @@ namespace Game.Entities SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.MaxLevel), WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel)); SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.NextLevelXP), Global.ObjectMgr.GetXPForLevel(GetLevel())); + if (m_activePlayerData.XP >= m_activePlayerData.NextLevelXP) + SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.XP), m_activePlayerData.NextLevelXP - 1); // reset before any aura state sources (health set/aura apply) SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AuraState), 0u); @@ -5753,10 +5755,8 @@ namespace Game.Entities SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModTargetResistance), 0); SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModTargetPhysicalResistance), 0); for (int i = 0; i < (int)SpellSchools.Max; ++i) - { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerCostModifier, i), 0); - SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerCostMultiplier, i), 0.0f); - } + // Reset no reagent cost field SetNoRegentCostMask(new Framework.Dynamic.FlagArray128()); diff --git a/Source/Game/Entities/StatSystem.cs b/Source/Game/Entities/StatSystem.cs index f6ccee3ae..fa0b3c574 100644 --- a/Source/Game/Entities/StatSystem.cs +++ b/Source/Game/Entities/StatSystem.cs @@ -933,7 +933,6 @@ namespace Game.Entities } public void ApplyModPowerCostModifier(SpellSchools school, int mod, bool apply) { ApplyModUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerCostModifier, (int)school), mod, apply); } - public void ApplyModPowerCostMultiplier(SpellSchools school, float pct, bool apply) { ApplyModUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.PowerCostMultiplier, (int)school), pct, apply); } } public partial class Player @@ -1013,18 +1012,6 @@ namespace Game.Entities UpdateSpellDamageAndHealingBonus(); UpdateManaRegen(); - // Update ratings in exist SPELL_AURA_MOD_RATING_FROM_STAT and only depends from stat - uint mask = 0; - var modRatingFromStat = GetAuraEffectsByType(AuraType.ModRatingFromStat); - foreach (var eff in modRatingFromStat) - if ((Stats)eff.GetMiscValueB() == stat) - mask |= (uint)eff.GetMiscValue(); - if (mask != 0) - { - for (int rating = 0; rating < (int)CombatRating.Max; ++rating) - if (Convert.ToBoolean(mask & (1 << rating))) - ApplyRatingMod((CombatRating)rating, 0, true); - } return true; } @@ -1322,12 +1309,6 @@ namespace Game.Entities public void UpdateRating(CombatRating cr) { int amount = baseRatingValue[(int)cr]; - // Apply bonus from SPELL_AURA_MOD_RATING_FROM_STAT - // stat used stored in miscValueB for this aura - var modRatingFromStat = GetAuraEffectsByType(AuraType.ModRatingFromStat); - foreach (var aurEff in modRatingFromStat) - if (Convert.ToBoolean(aurEff.GetMiscValue() & (1 << (int)cr))) - amount += (int)MathFunctions.CalculatePct(GetStat((Stats)aurEff.GetMiscValueB()), aurEff.GetAmount()); var modRatingPct = GetAuraEffectsByType(AuraType.ModRatingPct); foreach (var aurEff in modRatingPct) diff --git a/Source/Game/Networking/Packets/CharacterPackets.cs b/Source/Game/Networking/Packets/CharacterPackets.cs index fa3f7f0d6..b08043182 100644 --- a/Source/Game/Networking/Packets/CharacterPackets.cs +++ b/Source/Game/Networking/Packets/CharacterPackets.cs @@ -42,6 +42,7 @@ namespace Game.Networking.Packets _worldPacket.WriteBit(Success); _worldPacket.WriteBit(IsDeletedCharacters); _worldPacket.WriteBit(IsNewPlayerRestrictionSkipped); + _worldPacket.WriteBit(IsNewPlayerRestricted); _worldPacket.WriteBit(IsNewPlayer); _worldPacket.WriteBit(DisabledClassesMask.HasValue); _worldPacket.WriteBit(IsAlliedRacesCreationAllowed); @@ -65,9 +66,10 @@ namespace Game.Networking.Packets public bool Success; public bool IsDeletedCharacters; // used for character undelete list - public bool IsNewPlayerRestrictionSkipped = false; // allows client to skip new player restrictions - public bool IsNewPlayer = false; // forbids hero classes and allied races - public bool IsAlliedRacesCreationAllowed = false; + public bool IsNewPlayerRestrictionSkipped; // allows client to skip new player restrictions + public bool IsNewPlayerRestricted; // forbids using level boost and class trials + public bool IsNewPlayer; // forbids hero classes and allied races + public bool IsAlliedRacesCreationAllowed; public int MaxCharacterLevel = 1; public Optional DisabledClassesMask = new Optional(); @@ -192,6 +194,7 @@ namespace Game.Networking.Packets data.WriteUInt32(LastLoginVersion); data.WriteUInt32(Flags4); data.WriteInt32(MailSenders.Count); + data.WriteInt32(MailSenderTypes.Count); data.WriteUInt32(OverrideSelectScreenFileDataID); foreach (ChrCustomizationChoice customization in Customizations) @@ -200,6 +203,9 @@ namespace Game.Networking.Packets data.WriteUInt32(customization.ChrCustomizationChoiceID); } + foreach (var mailSenderType in MailSenderTypes) + data.WriteUInt32(mailSenderType); + data.WriteBits(Name.GetByteCount(), 6); data.WriteBit(FirstLogin); data.WriteBit(BoostInProgress); @@ -248,6 +254,7 @@ namespace Game.Networking.Packets public uint[] ProfessionIds = new uint[2]; // @todo public VisualItemInfo[] VisualItems = new VisualItemInfo[InventorySlots.BagEnd]; public List MailSenders = new List(); + public List MailSenderTypes = new List(); public struct VisualItemInfo { diff --git a/Source/Game/Networking/Packets/CombatLogPackets.cs b/Source/Game/Networking/Packets/CombatLogPackets.cs index 057987b11..716ca6c8c 100644 --- a/Source/Game/Networking/Packets/CombatLogPackets.cs +++ b/Source/Game/Networking/Packets/CombatLogPackets.cs @@ -581,7 +581,7 @@ namespace Game.Networking.Packets attackRoundInfo.WriteFloat(ContentTuning.PlayerItemLevel); attackRoundInfo.WriteFloat(ContentTuning.TargetItemLevel); attackRoundInfo.WriteUInt16(ContentTuning.ScalingHealthItemLevelCurveID); - attackRoundInfo.WriteUInt8((byte)(ContentTuning.ScalesWithItemLevel ? 1 : 0)); + attackRoundInfo.WriteUInt32((uint)ContentTuning.Flags); WriteLogDataBit(); FlushBits(); diff --git a/Source/Game/Networking/Packets/GarrisonPackets.cs b/Source/Game/Networking/Packets/GarrisonPackets.cs index 413c899ae..176410476 100644 --- a/Source/Game/Networking/Packets/GarrisonPackets.cs +++ b/Source/Game/Networking/Packets/GarrisonPackets.cs @@ -435,21 +435,27 @@ namespace Game.Networking.Packets public void Write(WorldPacket data) { data.WriteInt32(ItemID); - data.WriteUInt32(Quantity); + data.WriteUInt32(ItemQuantity); data.WriteInt32(CurrencyID); data.WriteUInt32(CurrencyQuantity); data.WriteUInt32(FollowerXP); - data.WriteUInt32(BonusAbilityID); - data.WriteInt32(Unknown); + data.WriteUInt32(GarrMssnBonusAbilityID); + data.WriteInt32(ItemFileDataID); + data.WriteBit(ItemInstance.HasValue); + data.FlushBits(); + + if (ItemInstance.HasValue) + ItemInstance.Value.Write(data); } public int ItemID; - public uint Quantity; + public uint ItemQuantity; public int CurrencyID; public uint CurrencyQuantity; public uint FollowerXP; - public uint BonusAbilityID; - public int Unknown; + public uint GarrMssnBonusAbilityID; + public int ItemFileDataID; + public Optional ItemInstance; } struct GarrisonMissionBonusAbility @@ -582,17 +588,9 @@ namespace Game.Networking.Packets foreach (List missionReward in MissionRewards) data.WriteInt32(missionReward.Count); - foreach (List missionReward in MissionRewards) - foreach (GarrisonMissionReward missionRewardItem in missionReward) - missionRewardItem.Write(data); - foreach (List missionReward in MissionOvermaxRewards) data.WriteInt32(missionReward.Count); - foreach (List missionReward in MissionOvermaxRewards) - foreach (GarrisonMissionReward missionRewardItem in missionReward) - missionRewardItem.Write(data); - foreach (GarrisonMissionBonusAbility areaBonus in MissionAreaBonuses) areaBonus.Write(data); @@ -621,6 +619,14 @@ namespace Game.Networking.Packets foreach (GarrisonTalent talent in Talents) talent.Write(data); + + foreach (List missionReward in MissionRewards) + foreach (GarrisonMissionReward missionRewardItem in missionReward) + missionRewardItem.Write(data); + + foreach (List missionReward in MissionOvermaxRewards) + foreach (GarrisonMissionReward missionRewardItem in missionReward) + missionRewardItem.Write(data); } public GarrisonType GarrTypeID; diff --git a/Source/Game/Networking/Packets/NPCPackets.cs b/Source/Game/Networking/Packets/NPCPackets.cs index 628b18b06..b87bc9b81 100644 --- a/Source/Game/Networking/Packets/NPCPackets.cs +++ b/Source/Game/Networking/Packets/NPCPackets.cs @@ -20,6 +20,7 @@ using Framework.GameMath; using Game.Entities; using System; using System.Collections.Generic; +using Framework.Dynamic; namespace Game.Networking.Packets { @@ -66,12 +67,16 @@ namespace Game.Networking.Packets _worldPacket.WriteBits(options.Text.GetByteCount(), 12); _worldPacket.WriteBits(options.Confirm.GetByteCount(), 12); _worldPacket.WriteBits((byte)options.Status, 2); + _worldPacket.WriteBit(options.SpellID.HasValue); _worldPacket.FlushBits(); options.Treasure.Write(_worldPacket); _worldPacket.WriteString(options.Text); _worldPacket.WriteString(options.Confirm); + + if (options.SpellID.HasValue) + _worldPacket.WriteInt32(options.SpellID.Value); } foreach (ClientGossipText text in GossipText) @@ -79,11 +84,11 @@ namespace Game.Networking.Packets } public List GossipOptions = new List(); - public int FriendshipFactionID = 0; + public int FriendshipFactionID; public ObjectGuid GossipGUID; public List GossipText = new List(); - public int TextID = 0; - public int GossipID = 0; + public int TextID; + public int GossipID; } public class GossipSelectOption : ClientPacket @@ -323,6 +328,7 @@ namespace Game.Networking.Packets public string Text; public string Confirm; public TreasureLootList Treasure; + public Optional SpellID; } public class ClientGossipText diff --git a/Source/Game/Networking/Packets/PartyPackets.cs b/Source/Game/Networking/Packets/PartyPackets.cs index d24df372e..f033eb49f 100644 --- a/Source/Game/Networking/Packets/PartyPackets.cs +++ b/Source/Game/Networking/Packets/PartyPackets.cs @@ -718,7 +718,7 @@ namespace Game.Networking.Packets public override void Write() { _worldPacket.WriteInt8(PartyIndex); - _worldPacket.WriteBits(Name.GetByteCount(), 6); + _worldPacket.WriteBits(Name.GetByteCount(), 9); _worldPacket.WriteString(Name); } diff --git a/Source/Game/Networking/Packets/SpellPackets.cs b/Source/Game/Networking/Packets/SpellPackets.cs index b0ee462e8..9a63d293f 100644 --- a/Source/Game/Networking/Packets/SpellPackets.cs +++ b/Source/Game/Networking/Packets/SpellPackets.cs @@ -1325,9 +1325,9 @@ namespace Game.Networking.Packets data.WriteUInt8(Expansion); data.WriteUInt8(TargetMinScalingLevel); data.WriteUInt8(TargetMaxScalingLevel); - data.WriteInt8(TargetScalingLevelDelta); + data.WriteInt8(TargetScalingLevelDelta); + data.WriteUInt32((uint)Flags); data.WriteBits(TuningType, 4); - data.WriteBit(ScalesWithItemLevel); data.FlushBits(); } @@ -1341,14 +1341,21 @@ namespace Game.Networking.Packets public byte TargetMinScalingLevel; public byte TargetMaxScalingLevel; public sbyte TargetScalingLevelDelta; - public bool ScalesWithItemLevel; + public ContentTuningFlags Flags = ContentTuningFlags.NoLevelScaling | ContentTuningFlags.NoItemLevelScaling; public enum ContentTuningType - { - PlayerToPlayer = 7, // NYI + { CreatureToPlayerDamage = 1, PlayerToCreatureDamage = 2, - CreatureToCreatureDamage = 4 + CreatureToCreatureDamage = 4, + PlayerToSandboxScaling = 7, // NYI + PlayerToPlayerExpectedStat = 8 + } + + public enum ContentTuningFlags + { + NoLevelScaling = 0x1, + NoItemLevelScaling = 0x2 } } diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index 5ff6e67f4..1192971e2 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -53,7 +53,10 @@ namespace Game.Spells Duration = 0x04, Scalable = 0x08, Negative = 0x10, - Unk20 = 0x20 + Unk20 = 0x20, + Unk40 = 0x40, + Unk80 = 0x80, + MawPower = 0x100 } public class AuraApplication diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index a42be08f8..df2ca4e51 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -3947,23 +3947,6 @@ namespace Game.Spells target.ToPlayer().ApplyRatingMod((CombatRating)rating, GetAmount(), apply); } - [AuraEffectHandler(AuraType.ModRatingFromStat)] - void HandleModRatingFromStat(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) - { - if (!mode.HasAnyFlag((AuraEffectHandleModes.ChangeAmountMask | AuraEffectHandleModes.Stat))) - return; - - Unit target = aurApp.GetTarget(); - - if (!target.IsTypeId(TypeId.Player)) - return; - - // Just recalculate ratings - for (int rating = 0; rating < (int)CombatRating.Max; ++rating) - if (Convert.ToBoolean(GetMiscValue() & (1 << rating))) - target.ToPlayer().UpdateRating((CombatRating)rating); - } - [AuraEffectHandler(AuraType.ModRatingPct)] void HandleModRatingPct(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) { @@ -4155,20 +4138,6 @@ namespace Game.Spells /********************************/ /*** POWER COST ***/ /********************************/ - [AuraEffectHandler(AuraType.ModPowerCostSchoolPct)] - void HandleModPowerCostPCT(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) - { - if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask)) - return; - - Unit target = aurApp.GetTarget(); - - float amount = MathFunctions.CalculatePct(1.0f, GetAmount()); - for (int i = 0; i < (int)SpellSchools.Max; ++i) - if (Convert.ToBoolean(GetMiscValue() & (1 << i))) - target.ApplyModPowerCostMultiplier((SpellSchools)i, amount, apply); - } - [AuraEffectHandler(AuraType.ModPowerCostSchool)] void HandleModPowerCost(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) { diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index c23121103..f74bd7db2 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -2753,6 +2753,7 @@ namespace Game.Spells if (power.PowerType != PowerType.Health) { // Flat mod from caster auras by spell school and power type + int flatMod = 0; var auras = caster.GetAuraEffectsByType(AuraType.ModPowerCostSchool); foreach (var eff in auras) { @@ -2762,8 +2763,13 @@ namespace Game.Spells if (!Convert.ToBoolean(eff.GetMiscValueB() & (1 << (int)power.PowerType))) continue; - powerCost += eff.GetAmount(); + flatMod += eff.GetAmount(); } + + if (power.PowerType == PowerType.Mana) + flatMod *= (int)(1.0f + caster.m_unitData.ManaCostModifierModifier); + + powerCost += flatMod; } // Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost) @@ -2776,7 +2782,7 @@ namespace Game.Spells else { WeaponAttackType slot = WeaponAttackType.BaseAttack; - if (HasAttribute(SpellAttr3.ReqOffhand)) + if (!HasAttribute(SpellAttr3.MainHand) && HasAttribute(SpellAttr3.ReqOffhand)) slot = WeaponAttackType.OffAttack; speed = caster.GetBaseAttackTime(slot); @@ -2789,13 +2795,23 @@ namespace Game.Spells Player modOwner = caster.GetSpellModOwner(); if (modOwner) { - if (power.OrderIndex == 0) - modOwner.ApplySpellMod(Id, SpellModOp.Cost, ref powerCost, spell); - else if (power.OrderIndex == 1) - modOwner.ApplySpellMod(Id, SpellModOp.SpellCost2, ref powerCost, spell); + switch (power.OrderIndex) + { + case 0: + modOwner.ApplySpellMod(Id, SpellModOp.Cost, ref powerCost, spell); + break; + case 1: + modOwner.ApplySpellMod(Id, SpellModOp.SpellCost2, ref powerCost, spell); + break; + case 2: + modOwner.ApplySpellMod(Id, SpellModOp.SpellCost3, ref powerCost, spell); + break; + default: + break; + } } - if (!caster.IsControlledByPlayer() && MathFunctions.fuzzyEq(power.PowerCostPct, 0.0f) && SpellLevel != 0) + if (!caster.IsControlledByPlayer() && MathFunctions.fuzzyEq(power.PowerCostPct, 0.0f) && SpellLevel != 0 && power.PowerType == PowerType.Mana) { if (HasAttribute(SpellAttr0.LevelDamageCalculation)) {