BFA Update (still lots of testing to do tho)

This commit is contained in:
hondacrx
2018-12-10 12:46:25 -05:00
parent 468b053946
commit 8e20114e10
256 changed files with 35613 additions and 10459 deletions
+53 -65
View File
@@ -37,7 +37,7 @@ namespace Game.Spells
auraBase = abase;
m_spellInfo = abase.GetSpellInfo();
_effectInfo = abase.GetSpellEffectInfo(effindex);
m_baseAmount = baseAmount.HasValue ? baseAmount.Value : abase.GetSpellEffectInfo(effindex).BasePoints;
m_baseAmount = baseAmount.HasValue ? baseAmount.Value : _effectInfo.CalcBaseValue(caster, abase.GetAuraType() == AuraObjectType.Unit ? abase.GetOwner().ToUnit() : null, abase.GetCastItemLevel());
m_donePct = 1.0f;
m_effIndex = (byte)effindex;
m_canBeRecalculated = true;
@@ -78,7 +78,7 @@ namespace Game.Spells
if (!m_spellInfo.HasAttribute(SpellAttr8.MasterySpecialization) || MathFunctions.fuzzyEq(GetSpellEffectInfo().BonusCoefficient, 0.0f))
amount = GetSpellEffectInfo().CalcValue(caster, m_baseAmount, GetBase().GetOwner().ToUnit(), GetBase().GetCastItemLevel());
else if (caster != null && caster.IsTypeId(TypeId.Player))
amount = (int)(caster.GetFloatValue(PlayerFields.Mastery) * GetSpellEffectInfo().BonusCoefficient);
amount = (int)(caster.GetFloatValue(ActivePlayerFields.Mastery) * GetSpellEffectInfo().BonusCoefficient);
// check item enchant aura cast
if (amount == 0 && caster != null)
@@ -1088,7 +1088,7 @@ namespace Game.Spells
{
// apply glow vision
if (target.IsTypeId(TypeId.Player))
target.SetByteFlag(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, PlayerFieldByte2Flags.InvisibilityGlow);
target.SetByteFlag(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, PlayerFieldByte2Flags.InvisibilityGlow);
target.m_invisibility.AddFlag(type);
target.m_invisibility.AddValue(type, GetAmount());
@@ -1100,7 +1100,7 @@ namespace Game.Spells
// if not have different invisibility auras.
// remove glow vision
if (target.IsTypeId(TypeId.Player))
target.RemoveByteFlag(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, PlayerFieldByte2Flags.InvisibilityGlow);
target.RemoveByteFlag(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, PlayerFieldByte2Flags.InvisibilityGlow);
target.m_invisibility.DelFlag(type);
}
@@ -1173,7 +1173,7 @@ namespace Game.Spells
target.m_stealth.AddValue(type, GetAmount());
target.SetStandFlags(UnitStandFlags.Creep);
if (target.IsTypeId(TypeId.Player))
target.SetByteFlag(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, PlayerFieldByte2Flags.Stealth);
target.SetByteFlag(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, PlayerFieldByte2Flags.Stealth);
}
else
{
@@ -1185,7 +1185,7 @@ namespace Game.Spells
target.RemoveStandFlags(UnitStandFlags.Creep);
if (target.IsTypeId(TypeId.Player))
target.RemoveByteFlag(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, PlayerFieldByte2Flags.Stealth);
target.RemoveByteFlag(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, PlayerFieldByte2Flags.Stealth);
}
}
@@ -1623,7 +1623,7 @@ namespace Game.Spells
else
{
uint model_id = 0;
uint modelid = ObjectManager.ChooseDisplayId(ci);
uint modelid = ObjectManager.ChooseDisplayId(ci).CreatureDisplayID;
if (modelid != 0)
model_id = modelid; // Will use the default model here
@@ -1670,10 +1670,10 @@ namespace Game.Spells
CreatureTemplate ci = Global.ObjectMgr.GetCreatureTemplate((uint)cr_id);
if (ci != null)
{
uint displayID = ObjectManager.ChooseDisplayId(ci);
Global.ObjectMgr.GetCreatureModelRandomGender(ref displayID);
CreatureModel model = ObjectManager.ChooseDisplayId(ci);
Global.ObjectMgr.GetCreatureModelRandomGender(ref model, ci);
target.SetUInt32Value(UnitFields.MountDisplayId, displayID);
target.SetUInt32Value(UnitFields.MountDisplayId, model.CreatureDisplayID);
}
}
}
@@ -2025,9 +2025,9 @@ namespace Game.Spells
return;
if (apply)
target.SetFlag(PlayerFields.TrackCreatures, 1 << (GetMiscValue() - 1));
target.SetFlag(ActivePlayerFields.TrackCreatures, 1 << (GetMiscValue() - 1));
else
target.RemoveFlag(PlayerFields.TrackCreatures, 1 << (GetMiscValue() - 1));
target.RemoveFlag(ActivePlayerFields.TrackCreatures, 1 << (GetMiscValue() - 1));
}
[AuraEffectHandler(AuraType.TrackResources)]
@@ -2042,9 +2042,9 @@ namespace Game.Spells
return;
if (apply)
target.SetFlag(PlayerFields.TrackResources, 1 << (GetMiscValue() - 1));
target.SetFlag(ActivePlayerFields.TrackResources, 1 << (GetMiscValue() - 1));
else
target.RemoveFlag(PlayerFields.TrackResources, 1 << (GetMiscValue() - 1));
target.RemoveFlag(ActivePlayerFields.TrackResources, 1 << (GetMiscValue() - 1));
}
[AuraEffectHandler(AuraType.TrackStealthed)]
@@ -2064,7 +2064,7 @@ namespace Game.Spells
if (target.HasAuraType(GetAuraType()))
return;
}
target.ApplyModFlag(PlayerFields.LocalFlags, PlayerLocalFlags.TrackStealthed, apply);
target.ApplyModFlag(ActivePlayerFields.LocalFlags, PlayerLocalFlags.TrackStealthed, apply);
}
[AuraEffectHandler(AuraType.ModStalked)]
@@ -2189,8 +2189,9 @@ namespace Game.Spells
if (displayId == 0)
{
displayId = ObjectManager.ChooseDisplayId(creatureInfo);
Global.ObjectMgr.GetCreatureModelRandomGender(ref displayId);
CreatureModel model = ObjectManager.ChooseDisplayId(creatureInfo);
Global.ObjectMgr.GetCreatureModelRandomGender(ref model, creatureInfo);
displayId = model.CreatureDisplayID;
}
//some spell has one aura of mount and one of vehicle
@@ -2880,20 +2881,14 @@ namespace Game.Spells
Unit target = aurApp.GetTarget();
for (byte x = (byte)SpellSchools.Normal; x < (byte)SpellSchools.Max; x++)
{
if (Convert.ToBoolean(GetMiscValue() & (1 << x)))
{
target.HandleStatModifier((UnitMods.ResistanceStart + x), UnitModifierType.TotalValue, GetAmount(), apply);
if (target.IsTypeId(TypeId.Player) || target.IsPet())
target.ApplyResistanceBuffModsMod((SpellSchools)x, GetAmount() > 0, GetAmount(), apply);
}
}
target.HandleStatModifier(UnitMods.ResistanceStart + x, UnitModifierType.TotalValue, GetAmount(), apply);
}
[AuraEffectHandler(AuraType.ModBaseResistancePct)]
void HandleAuraModBaseResistancePCT(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
{
if (!mode.HasAnyFlag((AuraEffectHandleModes.ChangeAmountMask | AuraEffectHandleModes.Stat)))
if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask | AuraEffectHandleModes.Stat))
return;
Unit target = aurApp.GetTarget();
@@ -2918,7 +2913,7 @@ namespace Game.Spells
[AuraEffectHandler(AuraType.ModResistancePct)]
void HandleModResistancePercent(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
{
if (!mode.HasAnyFlag((AuraEffectHandleModes.ChangeAmountMask | AuraEffectHandleModes.Stat)))
if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask | AuraEffectHandleModes.Stat))
return;
Unit target = aurApp.GetTarget();
@@ -2931,21 +2926,9 @@ namespace Game.Spells
if (Convert.ToBoolean(GetMiscValue() & (1 << i)))
{
if (spellGroupVal != 0)
{
target.HandleStatModifier((UnitMods.ResistanceStart + i), UnitModifierType.TotalPCT, (float)spellGroupVal, !apply);
if (target.IsTypeId(TypeId.Player) || target.IsPet())
{
target.ApplyResistanceBuffModsPercentMod((SpellSchools)i, true, spellGroupVal, !apply);
target.ApplyResistanceBuffModsPercentMod((SpellSchools)i, false, spellGroupVal, !apply);
}
target.HandleStatModifier(UnitMods.ResistanceStart + i, UnitModifierType.TotalPCT, (float)spellGroupVal, !apply);
}
target.HandleStatModifier((UnitMods.ResistanceStart + i), UnitModifierType.TotalPCT, GetAmount(), apply);
if (target.IsTypeId(TypeId.Player) || target.IsPet())
{
target.ApplyResistanceBuffModsPercentMod((SpellSchools)i, true, GetAmount(), apply);
target.ApplyResistanceBuffModsPercentMod((SpellSchools)i, false, GetAmount(), apply);
}
target.HandleStatModifier(UnitMods.ResistanceStart + i, UnitModifierType.TotalPCT, GetAmount(), apply);
}
}
}
@@ -2953,7 +2936,7 @@ namespace Game.Spells
[AuraEffectHandler(AuraType.ModBaseResistance)]
void HandleModBaseResistance(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
{
if (!mode.HasAnyFlag((AuraEffectHandleModes.ChangeAmountMask | AuraEffectHandleModes.Stat)))
if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask | AuraEffectHandleModes.Stat))
return;
Unit target = aurApp.GetTarget();
@@ -2985,11 +2968,11 @@ namespace Game.Spells
// show armor penetration
if (target.IsTypeId(TypeId.Player) && Convert.ToBoolean(GetMiscValue() & (int)SpellSchoolMask.Normal))
target.ApplyModUInt32Value(PlayerFields.ModTargetPhysicalResistance, GetAmount(), apply);
target.ApplyModUInt32Value(ActivePlayerFields.ModTargetPhysicalResistance, GetAmount(), apply);
// show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
if (target.IsTypeId(TypeId.Player) && ((SpellSchoolMask)GetMiscValue() & SpellSchoolMask.Spell) == SpellSchoolMask.Spell)
target.ApplyModUInt32Value(PlayerFields.ModTargetResistance, GetAmount(), apply);
target.ApplyModUInt32Value(ActivePlayerFields.ModTargetResistance, GetAmount(), apply);
}
/********************************/
@@ -3277,7 +3260,7 @@ namespace Game.Spells
if (!target)
return;
target.ApplyModSignedFloatValue(PlayerFields.OverrideSpellPowerByApPct, m_amount, apply);
target.ApplyModSignedFloatValue(ActivePlayerFields.OverrideSpellPowerByApPct, m_amount, apply);
target.UpdateSpellDamageAndHealingBonus();
}
@@ -3291,7 +3274,7 @@ namespace Game.Spells
if (!target)
return;
target.ApplyModSignedFloatValue(PlayerFields.OverrideApBySpellPowerPercent, m_amount, apply);
target.ApplyModSignedFloatValue(ActivePlayerFields.OverrideApBySpellPowerPercent, m_amount, apply);
target.UpdateAttackPowerAndDamage();
target.UpdateAttackPowerAndDamage(true);
}
@@ -3305,7 +3288,7 @@ namespace Game.Spells
Player target = aurApp.GetTarget().ToPlayer();
if (target)
{
target.SetStatFloatValue(PlayerFields.VersatilityBonus, target.GetTotalAuraModifier(AuraType.ModVersatility));
target.SetStatFloatValue(ActivePlayerFields.VersatilityBonus, target.GetTotalAuraModifier(AuraType.ModVersatility));
target.UpdateHealingDonePercentMod();
target.UpdateVersatilityDamageDone();
}
@@ -3951,7 +3934,7 @@ namespace Game.Spells
// This information for client side use only
if (target.IsTypeId(TypeId.Player))
{
PlayerFields baseField = GetAmount() >= 0 ? PlayerFields.ModDamageDonePos : PlayerFields.ModDamageDoneNeg;
ActivePlayerFields baseField = GetAmount() >= 0 ? ActivePlayerFields.ModDamageDonePos : ActivePlayerFields.ModDamageDoneNeg;
for (int i = 0; i < (int)SpellSchools.Max; ++i)
{
if (Convert.ToBoolean(GetMiscValue() & (1 << i)))
@@ -3996,9 +3979,9 @@ namespace Game.Spells
if (Convert.ToBoolean(GetMiscValue() & (1 << i)))
{
if (spellGroupVal != 0)
target.ApplyPercentModFloatValue(PlayerFields.ModDamageDonePct + i, spellGroupVal, !apply);
target.ApplyPercentModFloatValue(ActivePlayerFields.ModDamageDonePct + i, spellGroupVal, !apply);
target.ApplyPercentModFloatValue(PlayerFields.ModDamageDonePct + i, GetAmount(), apply);
target.ApplyPercentModFloatValue(ActivePlayerFields.ModDamageDonePct + i, GetAmount(), apply);
}
}
}
@@ -4095,9 +4078,9 @@ namespace Game.Spells
mask |= effect.SpellClassMask;
}
target.SetUInt32Value(PlayerFields.NoReagentCost1, mask[0]);
target.SetUInt32Value(PlayerFields.NoReagentCost1 + 1, mask[1]);
target.SetUInt32Value(PlayerFields.NoReagentCost1 + 2, mask[2]);
target.SetUInt32Value(ActivePlayerFields.NoReagentCost, mask[0]);
target.SetUInt32Value(ActivePlayerFields.NoReagentCost + 1, mask[1]);
target.SetUInt32Value(ActivePlayerFields.NoReagentCost + 2, mask[2]);
}
[AuraEffectHandler(AuraType.RetainComboPoints)]
@@ -4730,7 +4713,7 @@ namespace Game.Spells
if (apply)
{
target.SetUInt16Value(PlayerFields.FieldBytes3, PlayerFieldOffsets.FieldBytes3OffsetOverrideSpellsIdUint16Offset, (ushort)overrideId);
target.SetUInt16Value(ActivePlayerFields.Bytes3, PlayerFieldOffsets.FieldBytes3OffsetOverrideSpellsIdUint16Offset, (ushort)overrideId);
OverrideSpellDataRecord overrideSpells = CliDB.OverrideSpellDataStorage.LookupByKey(overrideId);
if (overrideSpells != null)
{
@@ -4744,7 +4727,7 @@ namespace Game.Spells
}
else
{
target.SetUInt16Value(PlayerFields.FieldBytes3, PlayerFieldOffsets.FieldBytes3OffsetOverrideSpellsIdUint16Offset, 0);
target.SetUInt16Value(ActivePlayerFields.Bytes3, PlayerFieldOffsets.FieldBytes3OffsetOverrideSpellsIdUint16Offset, 0);
OverrideSpellDataRecord overrideSpells = CliDB.OverrideSpellDataStorage.LookupByKey(overrideId);
if (overrideSpells != null)
{
@@ -4796,9 +4779,9 @@ namespace Game.Spells
return;
if (apply)
aurApp.GetTarget().RemoveByteFlag(PlayerFields.LocalFlags, 0, PlayerLocalFlags.ReleaseTimer);
aurApp.GetTarget().RemoveByteFlag(ActivePlayerFields.LocalFlags, 0, PlayerLocalFlags.ReleaseTimer);
else if (!aurApp.GetTarget().GetMap().Instanceable())
aurApp.GetTarget().SetByteFlag(PlayerFields.LocalFlags, 0, PlayerLocalFlags.ReleaseTimer);
aurApp.GetTarget().SetByteFlag(ActivePlayerFields.LocalFlags, 0, PlayerLocalFlags.ReleaseTimer);
}
[AuraEffectHandler(AuraType.Mastery)]
@@ -5377,8 +5360,10 @@ namespace Game.Spells
if (crit)
damage = caster.SpellCriticalDamageBonus(m_spellInfo, damage, target);
uint dmg = damage;
if (!GetSpellInfo().HasAttribute(SpellAttr4.FixedDamage))
caster.ApplyResilience(target, ref damage);
caster.ApplyResilience(target, ref dmg);
damage = dmg;
DamageInfo damageInfo = new DamageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo().GetSchoolMask(), DamageEffectType.DOT, WeaponAttackType.BaseAttack);
caster.CalcAbsorbResist(damageInfo);
@@ -5403,7 +5388,7 @@ namespace Game.Spells
if (overkill < 0)
overkill = 0;
SpellPeriodicAuraLogInfo pInfo = new SpellPeriodicAuraLogInfo(this, damage, overkill, absorb, resist, 0.0f, crit);
SpellPeriodicAuraLogInfo pInfo = new SpellPeriodicAuraLogInfo(this, damage, dmg, (uint)overkill, absorb, resist, 0.0f, crit);
caster.DealDamage(target, damage, cleanDamage, DamageEffectType.DOT, GetSpellInfo().GetSchoolMask(), GetSpellInfo(), true);
@@ -5465,8 +5450,10 @@ namespace Game.Spells
if (crit)
damage = caster.SpellCriticalDamageBonus(m_spellInfo, damage, target);
uint dmg = damage;
if (!GetSpellInfo().HasAttribute(SpellAttr4.FixedDamage))
caster.ApplyResilience(target, ref damage);
caster.ApplyResilience(target, ref dmg);
damage = dmg;
DamageInfo damageInfo = new DamageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo().GetSchoolMask(), DamageEffectType.DOT, WeaponAttackType.BaseAttack);
caster.CalcAbsorbResist(damageInfo);
@@ -5477,6 +5464,7 @@ namespace Game.Spells
// SendSpellNonMeleeDamageLog expects non-absorbed/non-resisted damage
SpellNonMeleeDamage log = new SpellNonMeleeDamage(caster, target, GetId(), GetBase().GetSpellXSpellVisualId(), GetSpellInfo().GetSchoolMask(), GetBase().GetCastGUID());
log.damage = damage;
log.originalDamage = dmg;
log.absorb = absorb;
log.resist = resist;
log.periodicLog = true;
@@ -5627,7 +5615,7 @@ namespace Game.Spells
caster.CalcHealAbsorb(healInfo);
caster.DealHeal(healInfo);
SpellPeriodicAuraLogInfo pInfo = new SpellPeriodicAuraLogInfo(this, heal, (int)(heal - healInfo.GetEffectiveHeal()), healInfo.GetAbsorb(), 0, 0.0f, crit);
SpellPeriodicAuraLogInfo pInfo = new SpellPeriodicAuraLogInfo(this, heal, (uint)damage, heal - healInfo.GetEffectiveHeal(), healInfo.GetAbsorb(), 0, 0.0f, crit);
target.SendPeriodicAuraLog(pInfo);
target.getHostileRefManager().threatAssist(caster, healInfo.GetEffectiveHeal() * 0.5f, GetSpellInfo());
@@ -5667,7 +5655,7 @@ namespace Game.Spells
int drainedAmount = -target.ModifyPower(powerType, -drainAmount);
float gainMultiplier = GetSpellEffectInfo().CalcValueMultiplier(caster);
SpellPeriodicAuraLogInfo pInfo = new SpellPeriodicAuraLogInfo(this, (uint)drainedAmount, 0, 0, 0, gainMultiplier, false);
SpellPeriodicAuraLogInfo pInfo = new SpellPeriodicAuraLogInfo(this, (uint)drainedAmount, (uint)drainAmount, 0, 0, 0, gainMultiplier, false);
int gainAmount = (int)(drainedAmount * gainMultiplier);
int gainedAmount = 0;
@@ -5719,7 +5707,7 @@ namespace Game.Spells
// ignore negative values (can be result apply spellmods to aura damage
int amount = Math.Max(m_amount, 0) * target.GetMaxPower(powerType) / 100;
SpellPeriodicAuraLogInfo pInfo = new SpellPeriodicAuraLogInfo(this, (uint)amount, 0, 0, 0, 0.0f, false);
SpellPeriodicAuraLogInfo pInfo = new SpellPeriodicAuraLogInfo(this, (uint)amount, (uint)amount, 0, 0, 0, 0.0f, false);
int gain = target.ModifyPower(powerType, amount);
@@ -5748,7 +5736,7 @@ namespace Game.Spells
// ignore negative values (can be result apply spellmods to aura damage
int amount = Math.Max(m_amount, 0);
SpellPeriodicAuraLogInfo pInfo = new SpellPeriodicAuraLogInfo(this, (uint)amount, 0, 0, 0, 0.0f, false);
SpellPeriodicAuraLogInfo pInfo = new SpellPeriodicAuraLogInfo(this, (uint)amount, (uint)amount, 0, 0, 0, 0.0f, false);
int gain = target.ModifyPower(powerType, amount);
if (caster != null)
@@ -5962,9 +5950,9 @@ namespace Game.Spells
return;
if (apply)
aurApp.GetTarget().SetFlag(PlayerFields.LocalFlags, PlayerLocalFlags.CanUseObjectsMounted);
aurApp.GetTarget().SetFlag(ActivePlayerFields.LocalFlags, PlayerLocalFlags.CanUseObjectsMounted);
else if (!aurApp.GetTarget().HasAuraType(AuraType.AllowUsingGameobjectsWhileMounted))
aurApp.GetTarget().RemoveFlag(PlayerFields.LocalFlags, PlayerLocalFlags.CanUseObjectsMounted);
aurApp.GetTarget().RemoveFlag(ActivePlayerFields.LocalFlags, PlayerLocalFlags.CanUseObjectsMounted);
}
[AuraEffectHandler(AuraType.PlayScene)]
+62 -111
View File
@@ -41,7 +41,7 @@ namespace Game.Spells
{
m_spellInfo = info;
m_caster = (info.HasAttribute(SpellAttr6.CastByCharmer) && caster.GetCharmerOrOwner() != null ? caster.GetCharmerOrOwner() : caster);
m_spellValue = new SpellValue(caster.GetMap().GetDifficultyID(), m_spellInfo);
m_spellValue = new SpellValue(caster.GetMap().GetDifficultyID(), m_spellInfo, caster);
m_preGeneratedPath = new PathGenerator(m_caster);
m_castItemLevel = -1;
_effects = info.GetEffectsForDifficulty(caster.GetMap().GetDifficultyID());
@@ -278,29 +278,6 @@ namespace Game.Spells
}
}
}
else if (m_auraScaleMask != 0)
{
bool checkLvl = !m_UniqueTargetInfo.Empty();
for (var i = 0; i < m_UniqueTargetInfo.Count; ++i)
{
var ihit = m_UniqueTargetInfo[i];
// remove targets which did not pass min level check
if (m_auraScaleMask != 0 && ihit.effectMask == m_auraScaleMask)
{
// Do not check for selfcast
if (!ihit.scaleAura && ihit.targetGUID != m_caster.GetGUID())
{
m_UniqueTargetInfo.Remove(ihit);
continue;
}
}
}
if (checkLvl && m_UniqueTargetInfo.Empty())
{
SendCastResult(SpellCastResult.Lowlevel);
finish(false);
}
}
}
if (m_targets.HasDst())
@@ -982,6 +959,9 @@ namespace Game.Spells
if (m_caster.IsTypeId(TypeId.Unit) && m_caster.ToCreature().IsVehicle())
target = m_caster.GetVehicleKit().GetPassenger((sbyte)(targetType.GetTarget() - Targets.UnitPassenger0));
break;
case Targets.UnitOwnCritter:
target = ObjectAccessor.GetCreatureOrPetOrVehicle(m_caster, m_caster.GetCritterGUID());
break;
default:
break;
}
@@ -1481,7 +1461,7 @@ namespace Game.Spells
if (unitTarget != null)
{
uint deficit = (uint)(unitTarget.GetMaxHealth() - unitTarget.GetHealth());
if ((deficit > maxHPDeficit || found == null) && target.IsWithinDist(unitTarget, jumpRadius) && target.IsWithinLOSInMap(unitTarget))
if ((deficit > maxHPDeficit || found == null) && target.IsWithinDist(unitTarget, jumpRadius) && target.IsWithinLOSInMap(unitTarget, ModelIgnoreFlags.M2))
{
found = obj;
maxHPDeficit = deficit;
@@ -1496,10 +1476,10 @@ namespace Game.Spells
{
if (found == null)
{
if ((!isBouncingFar || target.IsWithinDist(obj, jumpRadius)) && target.IsWithinLOSInMap(obj))
if ((!isBouncingFar || target.IsWithinDist(obj, jumpRadius)) && target.IsWithinLOSInMap(obj, ModelIgnoreFlags.M2))
found = obj;
}
else if (target.GetDistanceOrder(obj, found) && target.IsWithinLOSInMap(obj))
else if (target.GetDistanceOrder(obj, found) && target.IsWithinLOSInMap(obj, ModelIgnoreFlags.M2))
found = obj;
}
}
@@ -1565,7 +1545,6 @@ namespace Game.Spells
// For other spells trigger procflags are set in Spell.DoAllEffectOnTarget
// Because spell positivity is dependant on target
}
m_hitMask = ProcFlagsHit.None;
// Hunter trap spells - activation proc for Lock and Load, Entrapment and Misdirection
if (m_spellInfo.SpellFamilyName == SpellFamilyNames.Hunter && (m_spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x18u) || // Freezing and Frost Trap, Freezing Arrow
@@ -1625,13 +1604,6 @@ namespace Game.Spells
if (targetGUID == ihit.targetGUID) // Found in list
{
ihit.effectMask |= effectMask; // Immune effects removed from mask
ihit.scaleAura = false;
if (m_auraScaleMask != 0 && ihit.effectMask == m_auraScaleMask && m_caster != target)
{
SpellInfo auraSpell = Global.SpellMgr.GetSpellInfo(Global.SpellMgr.GetFirstSpellInChain(m_spellInfo.Id));
if (target.GetLevelForTarget(m_caster) + 10 >= auraSpell.SpellLevel)
ihit.scaleAura = true;
}
return;
}
}
@@ -1646,13 +1618,6 @@ namespace Game.Spells
targetInfo.alive = target.IsAlive();
targetInfo.damage = 0;
targetInfo.crit = false;
targetInfo.scaleAura = false;
if (m_auraScaleMask != 0 && targetInfo.effectMask == m_auraScaleMask && m_caster != target)
{
SpellInfo auraSpell = Global.SpellMgr.GetSpellInfo(Global.SpellMgr.GetFirstSpellInChain(m_spellInfo.Id));
if (target.GetLevelForTarget(m_caster) + 10 >= auraSpell.SpellLevel)
targetInfo.scaleAura = true;
}
// Calculate hit result
if (m_originalCaster != null)
@@ -1896,7 +1861,7 @@ namespace Game.Spells
// if target is flagged for pvp also flag caster if a player
if (unit.IsPvP() && m_caster.IsTypeId(TypeId.Player))
enablePvP = true; // Decide on PvP flagging now, but act on it later.
SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask, target.scaleAura);
SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask);
if (missInfo2 != SpellMissInfo.None)
{
if (missInfo2 != SpellMissInfo.Miss)
@@ -2088,7 +2053,7 @@ namespace Game.Spells
}
}
SpellMissInfo DoSpellHitOnUnit(Unit unit, uint effectMask, bool scaleAura)
SpellMissInfo DoSpellHitOnUnit(Unit unit, uint effectMask)
{
if (unit == null || effectMask == 0)
return SpellMissInfo.Evade;
@@ -2175,35 +2140,18 @@ namespace Game.Spells
if (aura_effmask != 0)
{
// Select rank for aura with level requirements only in specific cases
// Unit has to be target only of aura effect, both caster and target have to be players, target has to be other than unit target
SpellInfo aurSpellInfo = m_spellInfo;
int[] basePoints = new int[SpellConst.MaxEffects];
if (scaleAura)
{
aurSpellInfo = m_spellInfo.GetAuraRankForLevel(unitTarget.getLevel());
Cypher.Assert(aurSpellInfo != null);
foreach (SpellEffectInfo effect in aurSpellInfo.GetEffectsForDifficulty(0))
{
if (effect == null)
continue;
basePoints[effect.EffectIndex] = effect.BasePoints;
SpellEffectInfo myEffect = GetEffect(effect.EffectIndex);
if (myEffect != null && myEffect.Effect != effect.Effect)
{
aurSpellInfo = m_spellInfo;
break;
}
}
}
if (m_originalCaster != null)
{
int[] basePoints = new int[SpellConst.MaxEffects];
foreach (SpellEffectInfo auraSpellEffect in GetEffects())
if (auraSpellEffect != null)
basePoints[auraSpellEffect.EffectIndex] = (m_spellValue.CustomBasePointsMask & (1 << (int)auraSpellEffect.EffectIndex)) != 0 ?
m_spellValue.EffectBasePoints[auraSpellEffect.EffectIndex] : auraSpellEffect.CalcBaseValue(m_originalCaster, unit, m_castItemLevel);
bool refresh = false;
bool resetPeriodicTimer = !_triggeredCastFlags.HasAnyFlag(TriggerCastFlags.DontResetPeriodicTimer);
m_spellAura = Aura.TryRefreshStackOrCreate(aurSpellInfo, m_castId, (byte)effectMask, unit,
m_originalCaster, out refresh, (aurSpellInfo == m_spellInfo) ? m_spellValue.EffectBasePoints : basePoints, m_CastItem, ObjectGuid.Empty, resetPeriodicTimer, ObjectGuid.Empty, m_castItemLevel);
m_spellAura = Aura.TryRefreshStackOrCreate(m_spellInfo, m_castId, (byte)effectMask, unit,
m_originalCaster, out refresh, basePoints, m_CastItem, ObjectGuid.Empty, resetPeriodicTimer, ObjectGuid.Empty, m_castItemLevel);
if (m_spellAura != null)
{
// Set aura stack amount to desired value
@@ -2217,7 +2165,7 @@ namespace Game.Spells
// Now Reduce spell duration using data received at spell hit
int duration = m_spellAura.GetMaxDuration();
float diminishMod = unit.ApplyDiminishingToDuration(aurSpellInfo, ref duration, m_originalCaster, diminishLevel);
float diminishMod = unit.ApplyDiminishingToDuration(m_spellInfo, ref duration, m_originalCaster, diminishLevel);
// unit is immune to aura if it was diminished to 0 duration
if (diminishMod == 0.0f)
@@ -2239,13 +2187,13 @@ namespace Game.Spells
if (aurApp != null)
positive = aurApp.IsPositive();
duration = m_originalCaster.ModSpellDuration(aurSpellInfo, unit, duration, positive, effectMask);
duration = m_originalCaster.ModSpellDuration(m_spellInfo, unit, duration, positive, effectMask);
if (duration > 0)
{
// Haste modifies duration of channeled spells
if (m_spellInfo.IsChanneled())
m_originalCaster.ModSpellDurationTime(aurSpellInfo, ref duration, this);
m_originalCaster.ModSpellDurationTime(m_spellInfo, ref duration, this);
else if (m_spellInfo.HasAttribute(SpellAttr5.HasteAffectDuration))
{
int origDuration = duration;
@@ -2404,6 +2352,9 @@ namespace Game.Spells
Player modOwner = m_caster.GetSpellModOwner();
if (modOwner != null)
modOwner.ApplySpellMod(m_spellInfo.Id, SpellModOp.Range, ref range, this);
// add little tolerance level
range += Math.Min(3.0f, range * 0.1f); // 10% but no more than 3.0f
}
foreach (var ihit in m_UniqueTargetInfo)
@@ -2464,27 +2415,6 @@ namespace Game.Spells
InitExplicitTargets(targets);
// Fill aura scaling information
if (m_caster.IsControlledByPlayer() && !m_spellInfo.IsPassive() && m_spellInfo.SpellLevel != 0 && !m_spellInfo.IsChanneled() && !Convert.ToBoolean(_triggeredCastFlags & TriggerCastFlags.IgnoreAuraScaling))
{
foreach (SpellEffectInfo effect in GetEffects())
{
if (effect != null && effect.Effect == SpellEffectName.ApplyAura)
{
// Change aura with ranks only if basepoints are taken from spellInfo and aura is positive
if (m_spellInfo.IsPositiveEffect(effect.EffectIndex))
{
m_auraScaleMask |= (byte)(1 << (int)effect.EffectIndex);
if (m_spellValue.EffectBasePoints[effect.EffectIndex] != effect.BasePoints)
{
m_auraScaleMask = 0;
break;
}
}
}
}
}
m_spellState = SpellState.Preparing;
if (triggeredByAura != null)
@@ -2991,8 +2921,14 @@ namespace Game.Spells
// process immediate effects (items, ground, etc.) also initialize some variables
_handle_immediate_phase();
foreach (var ihit in m_UniqueTargetInfo)
DoAllEffectOnTarget(ihit);
// consider spell hit for some spells without target, so they may proc on finish phase correctly
if (m_UniqueTargetInfo.Empty())
m_hitMask = ProcFlagsHit.Normal;
else
{
foreach (var ihit in m_UniqueTargetInfo)
DoAllEffectOnTarget(ihit);
}
foreach (var ihit in m_UniqueGOTargetInfo)
DoAllEffectOnTarget(ihit);
@@ -3848,7 +3784,7 @@ namespace Game.Spells
{
case ItemSubClassWeapon.Thrown:
ammoDisplayID = Global.DB2Mgr.GetItemDisplayId(itemId, m_caster.GetVirtualItemAppearanceMod(i));
ammoInventoryType = itemEntry.inventoryType;
ammoInventoryType = (InventoryType)itemEntry.inventoryType;
break;
case ItemSubClassWeapon.Bow:
case ItemSubClassWeapon.Crossbow:
@@ -4632,7 +4568,7 @@ namespace Game.Spells
}
if (!m_spellInfo.HasAttribute(SpellAttr2.CanTargetNotInLos) && !Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, DisableFlags.SpellLOS)
&& !unitTarget.IsWithinLOSInMap(losTarget))
&& !unitTarget.IsWithinLOSInMap(losTarget, ModelIgnoreFlags.M2))
return SpellCastResult.LineOfSight;
}
}
@@ -4645,7 +4581,7 @@ namespace Game.Spells
m_targets.GetDstPos().GetPosition(out x, out y, out z);
if (!m_spellInfo.HasAttribute(SpellAttr2.CanTargetNotInLos) && !Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, DisableFlags.SpellLOS)
&& !m_caster.IsWithinLOS(x, y, z))
&& !m_caster.IsWithinLOS(x, y, z, ModelIgnoreFlags.M2))
return SpellCastResult.LineOfSight;
}
@@ -4936,6 +4872,9 @@ namespace Game.Spells
if (target == null)
return SpellCastResult.DontReport;
// first we must check to see if the target is in LoS. A path can usually be built but LoS matters for charge spells
if (!target.IsWithinLOSInMap(m_caster)) //Do full LoS/Path check. Don't exclude m2
return SpellCastResult.LineOfSight;
float objSize = target.GetObjectSize();
float range = m_spellInfo.GetMaxRange(true, m_caster, this) * 1.5f + objSize; // can't be overly strict
@@ -5677,6 +5616,10 @@ namespace Game.Spells
(float minRange, float maxRange) = GetMinMaxRange(strict);
// dont check max_range to strictly after cast
if (m_spellInfo.RangeEntry != null && m_spellInfo.RangeEntry.Flags != SpellRangeFlag.Melee && !strict)
maxRange += Math.Min(3.0f, maxRange * 0.1f); // 10% but no more than 3.0f
// get square values for sqr distance checks
minRange *= minRange;
maxRange *= maxRange;
@@ -6457,8 +6400,9 @@ namespace Game.Spells
return true;
// @todo shit below shouldn't be here, but it's temporary
//Check targets for LOS visibility
if (losPosition != null)
return target.IsWithinLOS(losPosition.GetPositionX(), losPosition.GetPositionY(), losPosition.GetPositionZ());
return target.IsWithinLOS(losPosition.GetPositionX(), losPosition.GetPositionY(), losPosition.GetPositionZ(), ModelIgnoreFlags.M2);
else
{
// Get GO cast coordinates if original caster . GO
@@ -6467,7 +6411,7 @@ namespace Game.Spells
caster = m_caster.GetMap().GetGameObject(m_originalCasterGUID);
if (!caster)
caster = m_caster;
if (target != m_caster && !target.IsWithinLOSInMap(caster))
if (target != m_caster && !target.IsWithinLOSInMap(caster, ModelIgnoreFlags.M2))
return false;
}
@@ -6675,7 +6619,7 @@ namespace Game.Spells
skillId = SharedConst.SkillByLockType((LockType)lockInfo.Index[j]);
if (skillId != SkillType.None || lockInfo.Index[j] == (uint)LockType.Picklock)
if (skillId != SkillType.None || lockInfo.Index[j] == (uint)LockType.Lockpicking)
{
reqSkillValue = lockInfo.Skill[j];
@@ -6683,7 +6627,7 @@ namespace Game.Spells
skillValue = 0;
if (!m_CastItem && m_caster.IsTypeId(TypeId.Player))
skillValue = m_caster.ToPlayer().GetSkillValue(skillId);
else if (lockInfo.Index[j] == (uint)LockType.Picklock)
else if (lockInfo.Index[j] == (uint)LockType.Lockpicking)
skillValue = (int)m_caster.getLevel() * 5;
// skill bonus provided by casting spell (mostly item spells)
@@ -6710,9 +6654,8 @@ namespace Game.Spells
{
if (mod < SpellValueMod.End)
{
SpellEffectInfo effect = GetEffect((uint)mod);
if (effect != null)
m_spellValue.EffectBasePoints[(int)mod] = effect.CalcBaseValue(value);
m_spellValue.EffectBasePoints[(int)mod] = value;
m_spellValue.CustomBasePointsMask |= 1u << (int)mod;
return;
}
@@ -7088,11 +7031,19 @@ namespace Game.Spells
int CalculateDamage(uint i, Unit target)
{
return m_caster.CalculateSpellDamage(target, m_spellInfo, i, m_spellValue.EffectBasePoints[i], m_castItemLevel);
int? basePoint = null;
if ((m_spellValue.CustomBasePointsMask & (1 << (int)i)) != 0)
basePoint = m_spellValue.EffectBasePoints[i];
return m_caster.CalculateSpellDamage(target, m_spellInfo, i, basePoint, m_castItemLevel);
}
int CalculateDamage(uint i, Unit target, out float variance)
{
return m_caster.CalculateSpellDamage(target, m_spellInfo, i, out variance, m_spellValue.EffectBasePoints[i], m_castItemLevel);
int? basePoint = null;
if ((m_spellValue.CustomBasePointsMask & (1 << (int)i)) != 0)
basePoint = m_spellValue.EffectBasePoints[i];
return m_caster.CalculateSpellDamage(target, m_spellInfo, i, out variance, basePoint, m_castItemLevel);
}
public SpellState getState()
{
@@ -7331,7 +7282,6 @@ namespace Game.Spells
SpellEffectInfo[] _effects = new SpellEffectInfo[SpellConst.MaxEffects];
bool m_skipCheck;
byte m_auraScaleMask;
#endregion
}
@@ -7504,7 +7454,6 @@ namespace Game.Spells
public bool processed;
public bool alive;
public bool crit;
public bool scaleAura;
}
public class GOTargetInfo
@@ -7523,20 +7472,22 @@ namespace Game.Spells
public class SpellValue
{
public SpellValue(Difficulty difficulty, SpellInfo proto)
public SpellValue(Difficulty difficulty, SpellInfo proto, Unit caster)
{
var effects = proto.GetEffectsForDifficulty(difficulty);
Cypher.Assert(effects.Length <= SpellConst.MaxEffects);
foreach (SpellEffectInfo effect in effects)
if (effect != null)
EffectBasePoints[effect.EffectIndex] = effect.BasePoints;
EffectBasePoints[effect.EffectIndex] = effect.CalcBaseValue(caster, null, -1);
CustomBasePointsMask = 0;
MaxAffectedTargets = proto.MaxAffectedTargets;
RadiusMod = 1.0f;
AuraStackAmount = 1;
}
public int[] EffectBasePoints = new int[SpellConst.MaxEffects];
public uint CustomBasePointsMask;
public uint MaxAffectedTargets;
public float RadiusMod;
public byte AuraStackAmount;
+37 -7
View File
@@ -134,7 +134,8 @@ namespace Game.Spells
m_caster.CalcAbsorbResist(damageInfo);
SpellNonMeleeDamage log = new SpellNonMeleeDamage(m_caster, unitTarget, m_spellInfo.Id, m_SpellVisual, m_spellInfo.GetSchoolMask(), m_castId);
log.damage = (uint)damage;
log.damage = damageInfo.GetDamage();
log.originalDamage = (uint)damage;
log.absorb = damageInfo.GetAbsorb();
log.resist = damageInfo.GetResist();
@@ -2102,7 +2103,7 @@ namespace Game.Spells
if (!unitTarget.IsTypeId(TypeId.Player))
return;
if (damage < 0)
if (damage < 1)
return;
uint skillid = (uint)effectInfo.MiscValue;
@@ -2114,7 +2115,7 @@ namespace Game.Spells
if (tier == null)
return;
ushort skillval = unitTarget.ToPlayer().GetPureSkillValue((SkillType)skillid);
unitTarget.ToPlayer().SetSkill(skillid, (uint)effectInfo.CalcValue(), Math.Max(skillval, (ushort)1), tier.Value[damage - 1]);
unitTarget.ToPlayer().SetSkill(skillid, (uint)damage, Math.Max(skillval, (ushort)1), tier.Value[damage - 1]);
}
[SpellEffectHandler(SpellEffectName.PlayMovie)]
@@ -4068,12 +4069,41 @@ namespace Game.Spells
creature.RemoveFlag(UnitFields.Flags, UnitFlags.Skinnable);
creature.SetFlag(ObjectFields.DynamicFlags, UnitDynFlags.Lootable);
uint reqValue = (uint)(targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel - 10) * 10 : targetLevel * 5);
if (skill == SkillType.Skinning)
{
int reqValue;
if (targetLevel <= 10)
reqValue = 1;
else if (targetLevel < 20)
reqValue = (targetLevel - 10) * 10;
else if (targetLevel <= 73)
reqValue = targetLevel * 5;
else if (targetLevel < 80)
reqValue = targetLevel * 10 - 365;
else if (targetLevel <= 84)
reqValue = targetLevel * 5 + 35;
else if (targetLevel <= 87)
reqValue = targetLevel * 15 - 805;
else if (targetLevel <= 92)
reqValue = (targetLevel - 62) * 20;
else if (targetLevel <= 104)
reqValue = targetLevel * 5 + 175;
else if (targetLevel <= 107)
reqValue = targetLevel * 15 - 905;
else if (targetLevel <= 112)
reqValue = (targetLevel - 72) * 20;
else if (targetLevel <= 122)
reqValue = (targetLevel - 32) * 10;
else
reqValue = 900;
uint skillValue = m_caster.ToPlayer().GetPureSkillValue(skill);
// TODO: Specialize skillid for each expansion
// new db field?
// tied to one of existing expansion fields in creature_template?
// Double chances for elites
m_caster.ToPlayer().UpdateGatherSkill(skill, skillValue, reqValue, (uint)(creature.isElite() ? 2 : 1));
// Double chances for elites
m_caster.ToPlayer().UpdateGatherSkill(skill, (uint)damage, (uint)reqValue, (uint)(creature.isElite() ? 2 : 1));
}
}
[SpellEffectHandler(SpellEffectName.Charge)]
+1 -1
View File
@@ -953,7 +953,7 @@ namespace Game.Spells
public bool OnHold;
}
struct ChargeEntry
public struct ChargeEntry
{
public ChargeEntry(DateTime startTime, TimeSpan rechargeTime)
{
+209 -141
View File
@@ -107,7 +107,7 @@ namespace Game.Spells
if (_options != null)
{
SpellProcsPerMinuteRecord _ppm = CliDB.SpellProcsPerMinuteStorage.LookupByKey(_options.SpellProcsPerMinuteID);
ProcFlags = (ProcFlags)_options.ProcTypeMask;
ProcFlags = (ProcFlags)_options.ProcTypeMask[0];
ProcChance = _options.ProcChance;
ProcCharges = _options.ProcCharges;
ProcCooldown = _options.ProcCategoryRecovery;
@@ -892,10 +892,34 @@ namespace Game.Spells
// continent limitation (virtual continent)
if (HasAttribute(SpellAttr4.CastOnlyInOutland))
{
uint v_map = Global.DB2Mgr.GetVirtualMapForMapAndZone(map_id, zone_id);
var map = CliDB.MapStorage.LookupByKey(v_map);
if (map == null || map.ExpansionID < 1 || !map.IsContinent())
uint mountFlags = 0;
if (player && player.HasAuraType(AuraType.MountRestrictions))
{
foreach (AuraEffect auraEffect in player.GetAuraEffectsByType(AuraType.MountRestrictions))
mountFlags |= (uint)auraEffect.GetMiscValue();
}
else
{
AreaTableRecord areaTable = CliDB.AreaTableStorage.LookupByKey(area_id);
if (areaTable != null)
mountFlags = areaTable.MountFlags;
}
if (!Convert.ToBoolean(mountFlags & (uint)AreaMountFlags.FlyingAllowed))
return SpellCastResult.IncorrectArea;
if (player)
{
uint mapToCheck = map_id;
MapRecord mapEntry1 = CliDB.MapStorage.LookupByKey(map_id);
if (mapEntry1 != null)
mapToCheck = (uint)mapEntry1.CosmeticParentMapID;
if ((mapToCheck == 1116 || mapToCheck == 1464) && !player.HasSpell(191645)) // Draenor Pathfinder
return SpellCastResult.IncorrectArea;
else if (mapToCheck == 1220 && !player.HasSpell(233368)) // Broken Isles Pathfinder
return SpellCastResult.IncorrectArea;
else if ((mapToCheck == 1642 || mapToCheck == 1643) && !player.HasSpell(278833)) // Battle for Azeroth Pathfinder
return SpellCastResult.IncorrectArea;
}
}
var mapEntry = CliDB.MapStorage.LookupByKey(map_id);
@@ -2905,9 +2929,9 @@ namespace Game.Spells
if (!caster.IsTypeId(TypeId.Player))
return 0.0f;
float crit = caster.GetFloatValue(PlayerFields.CritPercentage);
float rangedCrit = caster.GetFloatValue(PlayerFields.RangedCritPercentage);
float spellCrit = caster.GetFloatValue(PlayerFields.SpellCritPercentage1);
float crit = caster.GetFloatValue(ActivePlayerFields.CritPercentage);
float rangedCrit = caster.GetFloatValue(ActivePlayerFields.RangedCritPercentage);
float spellCrit = caster.GetFloatValue(ActivePlayerFields.SpellCritPercentage1);
switch (mod.Param)
{
@@ -3733,7 +3757,6 @@ namespace Game.Spells
Effect = (SpellEffectName)_effect.Effect;
ApplyAuraName = (AuraType)_effect.EffectAura;
ApplyAuraPeriod = _effect.EffectAuraPeriod;
DieSides = (int)_effect.EffectDieSides;
RealPointsPerLevel = _effect.EffectRealPointsPerLevel;
BasePoints = (int)_effect.EffectBasePoints;
PointsPerResource = _effect.EffectPointsPerResource;
@@ -3828,10 +3851,57 @@ namespace Game.Spells
{
variance = 0.0f;
float basePointsPerLevel = RealPointsPerLevel;
int basePoints = bp.HasValue ? bp.Value : BasePoints;
// TODO: this needs to be a float, not rounded
int basePoints = CalcBaseValue(caster, target, itemLevel);
float value = bp.HasValue ? bp.Value : BasePoints;
float comboDamage = PointsPerResource;
if (Scaling.Variance != 0)
{
float delta = Math.Abs(Scaling.Variance * 0.5f);
float valueVariance = RandomHelper.FRand(-delta, delta);
value += basePoints * valueVariance;
variance = valueVariance;
}
// base amount modification based on spell lvl vs caster lvl
if (Scaling.Coefficient != 0.0f)
{
if (Scaling.ResourceCoefficient != 0)
comboDamage = Scaling.ResourceCoefficient * value;
}
else
{
if (GetScalingExpectedStat() == ExpectedStatType.None)
{
int level = caster ? (int)caster.getLevel() : 0;
if (level > (int)_spellInfo.MaxLevel && _spellInfo.MaxLevel > 0)
level = (int)_spellInfo.MaxLevel;
level -= (int)_spellInfo.BaseLevel;
if (level < 0)
level = 0;
value += level * basePointsPerLevel;
}
}
// random damage
if (caster)
{
// bonus amount from combo points
if (caster.m_playerMovingMe && comboDamage != 0)
{
uint comboPoints = caster.m_playerMovingMe.GetComboPoints();
if (comboPoints != 0)
value += comboDamage * comboPoints;
}
value = caster.ApplyEffectModifiers(_spellInfo, EffectIndex, value);
}
return (int)Math.Round(value);
}
public int CalcBaseValue(Unit caster, Unit target, int itemLevel)
{
if (Scaling.Coefficient != 0.0f)
{
uint level = _spellInfo.SpellLevel;
@@ -3855,153 +3925,57 @@ namespace Game.Spells
if (_spellInfo.Scaling._Class == 0)
return 0;
if (_spellInfo.Scaling.ScalesFromItemLevel == 0)
uint effectiveItemLevel = itemLevel != -1 ? (uint)itemLevel : 1u;
if (_spellInfo.Scaling.ScalesFromItemLevel != 0 || _spellInfo.HasAttribute(SpellAttr11.ScalesWithItemLevel))
{
if (!_spellInfo.HasAttribute(SpellAttr11.ScalesWithItemLevel))
tempValue = CliDB.GetSpellScalingColumnForClass(CliDB.SpellScalingGameTable.GetRow(level), _spellInfo.Scaling._Class);
else
if (_spellInfo.Scaling.ScalesFromItemLevel != 0)
effectiveItemLevel = _spellInfo.Scaling.ScalesFromItemLevel;
if (_spellInfo.Scaling._Class == -8)
{
uint effectiveItemLevel = (uint)(itemLevel != -1 ? itemLevel : 1);
tempValue = ItemEnchantment.GetRandomPropertyPoints(effectiveItemLevel, ItemQuality.Rare, InventoryType.Chest, 0);
if (IsAura() && ApplyAuraName == AuraType.ModRating)
{
GtCombatRatingsMultByILvlRecord ratingMult = CliDB.CombatRatingsMultByILvlGameTable.GetRow(effectiveItemLevel);
if (ratingMult != null)
tempValue *= ratingMult.ArmorMultiplier;
}
RandPropPointsRecord randPropPoints = CliDB.RandPropPointsStorage.LookupByKey(effectiveItemLevel);
if (randPropPoints == null)
randPropPoints = CliDB.RandPropPointsStorage.LookupByKey(CliDB.RandPropPointsStorage.Count - 1);
tempValue = randPropPoints.DamageReplaceStat;
}
else
tempValue = ItemEnchantment.GetRandomPropertyPoints(effectiveItemLevel, ItemQuality.Rare, InventoryType.Chest, 0);
}
else
tempValue = ItemEnchantment.GetRandomPropertyPoints(_spellInfo.Scaling.ScalesFromItemLevel, ItemQuality.Rare, InventoryType.Chest, 0);
tempValue = CliDB.GetSpellScalingColumnForClass(CliDB.SpellScalingGameTable.GetRow(level), _spellInfo.Scaling._Class);
if (_spellInfo.Scaling._Class == -7)
{
// todo: get inventorytype here
GtCombatRatingsMultByILvlRecord ratingMult = CliDB.CombatRatingsMultByILvlGameTable.GetRow(effectiveItemLevel);
if (ratingMult != null)
tempValue *= ratingMult.ArmorMultiplier;
}
}
tempValue *= Scaling.Coefficient;
if (tempValue != 0.0f && tempValue < 1.0f)
tempValue = 1.0f;
if (Scaling.Variance != 0f)
{
float delta = Math.Abs(Scaling.Variance * 0.5f);
float valueVariance = RandomHelper.FRand(-delta, delta);
tempValue += tempValue * valueVariance;
variance = valueVariance;
}
basePoints = (int)Math.Round(tempValue);
if (Scaling.ResourceCoefficient != 0f)
comboDamage = Scaling.ResourceCoefficient * tempValue;
return (int)Math.Round(tempValue);
}
else
{
if (caster != null)
float tempValue = BasePoints;
ExpectedStatType stat = GetScalingExpectedStat();
if (stat != ExpectedStatType.None)
{
int level = (int)caster.getLevel();
if (level > _spellInfo.MaxLevel && _spellInfo.MaxLevel > 0)
level = (int)_spellInfo.MaxLevel;
else if (level < _spellInfo.BaseLevel)
level = (int)_spellInfo.BaseLevel;
if (_spellInfo.HasAttribute(SpellAttr0.LevelDamageCalculation))
stat = ExpectedStatType.CreatureAutoAttackDps;
level -= (int)_spellInfo.SpellLevel;
basePoints += (int)(level * basePointsPerLevel);
// TODO - add expansion and content tuning id args?
uint level = caster ? caster.getLevel() : 1;
tempValue = Global.DB2Mgr.EvaluateExpectedStat(stat, level, -2, 0, Class.None) * BasePoints / 100.0f;
}
// roll in a range <1;EffectDieSides> as of patch 3.3.3
int randomPoints = DieSides;
switch (randomPoints)
{
case 0:
break;
case 1:
basePoints += 1;
break; // range 1..1
default:
{
// range can have positive (1..rand) and negative (rand..1) values, so order its for irand
int randvalue = (randomPoints >= 1) ? RandomHelper.IRand(1, randomPoints) : RandomHelper.IRand(randomPoints, 1);
basePoints += randvalue;
break;
}
}
return (int)Math.Round(tempValue);
}
float value = (float)basePoints;
// random damage
if (caster != null)
{
// bonus amount from combo points
if (caster.m_playerMovingMe != null && comboDamage != 0)
{
byte comboPoints = caster.m_playerMovingMe.GetComboPoints();
if (comboPoints != 0)
value += comboDamage * comboPoints;
}
value = caster.ApplyEffectModifiers(_spellInfo, EffectIndex, value);
if (!caster.IsControlledByPlayer() && _spellInfo.SpellLevel != 0 && _spellInfo.SpellLevel != caster.getLevel() &&
basePointsPerLevel == 0 && _spellInfo.HasAttribute(SpellAttr0.LevelDamageCalculation))
{
bool canEffectScale = false;
switch (Effect)
{
case SpellEffectName.SchoolDamage:
case SpellEffectName.Dummy:
case SpellEffectName.PowerDrain:
case SpellEffectName.HealthLeech:
case SpellEffectName.Heal:
case SpellEffectName.WeaponDamage:
case SpellEffectName.PowerBurn:
case SpellEffectName.ScriptEffect:
case SpellEffectName.NormalizedWeaponDmg:
case SpellEffectName.ForceCastWithValue:
case SpellEffectName.TriggerSpellWithValue:
case SpellEffectName.TriggerMissileSpellWithValue:
canEffectScale = true;
break;
default:
break;
}
switch (ApplyAuraName)
{
case AuraType.PeriodicDamage:
case AuraType.Dummy:
case AuraType.PeriodicHeal:
case AuraType.DamageShield:
case AuraType.ProcTriggerDamage:
case AuraType.PeriodicLeech:
case AuraType.PeriodicManaLeech:
case AuraType.SchoolAbsorb:
case AuraType.PeriodicTriggerSpellWithValue:
canEffectScale = true;
break;
default:
break;
}
if (canEffectScale)
{
GtNpcManaCostScalerRecord spellScaler = CliDB.NpcManaCostScalerGameTable.GetRow(_spellInfo.SpellLevel);
GtNpcManaCostScalerRecord casterScaler = CliDB.NpcManaCostScalerGameTable.GetRow(caster.getLevel());
if (spellScaler != null && casterScaler != null)
value *= casterScaler.Scaler / spellScaler.Scaler;
}
}
}
return (int)value;
}
public int CalcBaseValue(int value)
{
if (DieSides == 0)
return value;
else
return value - 1;
}
public float CalcValueMultiplier(Unit caster, Spell spell = null)
@@ -4098,6 +4072,94 @@ namespace Game.Spells
return _data[(int)Effect].UsedTargetObjectType;
}
ExpectedStatType GetScalingExpectedStat()
{
switch (Effect)
{
case SpellEffectName.SchoolDamage:
case SpellEffectName.EnvironmentalDamage:
case SpellEffectName.HealthLeech:
case SpellEffectName.WeaponDamageNoschool:
case SpellEffectName.WeaponDamage:
return ExpectedStatType.CreatureSpellDamage;
case SpellEffectName.Heal:
case SpellEffectName.HealMechanical:
return ExpectedStatType.PlayerHealth;
case SpellEffectName.Energize:
case SpellEffectName.PowerBurn:
if (MiscValue == 0)
return ExpectedStatType.PlayerMana;
return ExpectedStatType.None;
case SpellEffectName.PowerDrain:
return ExpectedStatType.PlayerMana;
case SpellEffectName.ApplyAura:
case SpellEffectName.PersistentAreaAura:
case SpellEffectName.ApplyAreaAuraParty:
case SpellEffectName.ApplyAreaAuraRaid:
case SpellEffectName.ApplyAreaAuraPet:
case SpellEffectName.ApplyAreaAuraFriend:
case SpellEffectName.ApplyAreaAuraEnemy:
case SpellEffectName.ApplyAreaAuraOwner:
case SpellEffectName.ApllyAuraOnPet:
case SpellEffectName.Unk202:
switch (ApplyAuraName)
{
case AuraType.PeriodicDamage:
case AuraType.ModDamageDone:
case AuraType.DamageShield:
case AuraType.ProcTriggerDamage:
case AuraType.PeriodicLeech:
case AuraType.ModDamageDoneCreature:
case AuraType.PeriodicHealthFunnel:
case AuraType.ModMeleeAttackPowerVersus:
case AuraType.ModRangedAttackPowerVersus:
case AuraType.ModFlatSpellDamageVersus:
return ExpectedStatType.CreatureSpellDamage;
case AuraType.PeriodicHeal:
case AuraType.ModDamageTaken:
case AuraType.ModIncreaseHealth:
case AuraType.SchoolAbsorb:
case AuraType.ModRegen:
case AuraType.ManaShield:
case AuraType.ModHealing:
case AuraType.ModHealingDone:
case AuraType.ModHealthRegenInCombat:
case AuraType.ModMaxHealth:
case AuraType.ModIncreaseHealth2:
case AuraType.SchoolHealAbsorb:
return ExpectedStatType.PlayerHealth;
case AuraType.PeriodicManaLeech:
return ExpectedStatType.PlayerMana;
case AuraType.ModStat:
case AuraType.ModAttackPower:
case AuraType.ModRangedAttackPower:
return ExpectedStatType.PlayerPrimaryStat;
case AuraType.ModRating:
return ExpectedStatType.PlayerSecondaryStat;
case AuraType.ModResistance:
case AuraType.ModBaseResistance:
case AuraType.ModTargetResistance:
case AuraType.ModBonusArmor:
return ExpectedStatType.ArmorConstant;
case AuraType.PeriodicEnergize:
case AuraType.ModIncreaseEnergy:
case AuraType.ModPowerCostSchool:
case AuraType.ModPowerRegen:
case AuraType.PowerBurn:
case AuraType.ModMaxPower:
if (MiscValue == 0)
return ExpectedStatType.PlayerMana;
return ExpectedStatType.None;
default:
break;
}
break;
default:
break;
}
return ExpectedStatType.None;
}
public ImmunityInfo GetImmunityInfo() { return _immunityInfo; }
public class StaticData
@@ -4370,7 +4432,13 @@ namespace Game.Spells
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 252 SPELL_EFFECT_252
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 253 SPELL_EFFECT_GIVE_HONOR
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 254 SPELL_EFFECT_254
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit) // 255 SPELL_EFFECT_LEARN_TRANSMOG_SET
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 255 SPELL_EFFECT_LEARN_TRANSMOG_SET
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 256 SPELL_EFFECT_256
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 257 SPELL_EFFECT_257
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 258 SPELL_EFFECT_MODIFY_KEYSTONE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 259 SPELL_EFFECT_RESPEC_AZERITE_EMPOWERED_ITEM
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 260 SPELL_EFFECT_SUMMON_STABLED_PET
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 261 SPELL_EFFECT_SCRAP_ITEM
};
#region Fields
@@ -4380,7 +4448,6 @@ namespace Game.Spells
public SpellEffectName Effect;
public AuraType ApplyAuraName;
public uint ApplyAuraPeriod;
public int DieSides;
public float RealPointsPerLevel;
public int BasePoints;
public float PointsPerResource;
@@ -4741,8 +4808,9 @@ namespace Game.Spells
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 145
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 146
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 147
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 148)
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Random), // 149)
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 148
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Random), // 149
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 150
};
}
+42 -13
View File
@@ -1356,14 +1356,30 @@ namespace Game.Entities
procEntry.SpellPhaseMask = ProcFlagsSpellPhase.Hit;
procEntry.HitMask = ProcFlagsHit.None; // uses default proc @see SpellMgr::CanSpellTriggerProcOnEvent
// Reflect auras should only proc off reflects
foreach (SpellEffectInfo effect in spellInfo.GetEffectsForDifficulty(Difficulty.None))
{
if (effect != null && (effect.IsAura(AuraType.ReflectSpells) || effect.IsAura(AuraType.ReflectSpellsSchool)))
if (effect == null || !effect.IsAura())
continue;
switch (effect.ApplyAuraName)
{
procEntry.HitMask = ProcFlagsHit.Reflect;
break;
// Reflect auras should only proc off reflects
case AuraType.ReflectSpells:
case AuraType.ReflectSpellsSchool:
procEntry.HitMask = ProcFlagsHit.Reflect;
break;
// Only drop charge on crit
case AuraType.ModWeaponCritPercent:
procEntry.HitMask = ProcFlagsHit.Critical;
break;
// Only drop charge on block
case AuraType.ModBlockPercent:
procEntry.HitMask = ProcFlagsHit.Block;
break;
default:
continue;
}
break;
}
procEntry.AttributesMask = 0;
@@ -1633,7 +1649,7 @@ namespace Game.Entities
if (skillLine.SkillLine != creatureFamily.SkillLine[j])
continue;
if (skillLine.AcquireMethod != AbilytyLearnType.OnSkillLearn)
if (skillLine.AcquireMethod != AbilityLearnType.OnSkillLearn)
continue;
SpellInfo spell = GetSpellInfo(skillLine.Spell);
@@ -1783,7 +1799,7 @@ namespace Game.Entities
spellArea.questEndStatus = result.Read<uint>(4);
spellArea.questEnd = result.Read<uint>(5);
spellArea.auraSpell = result.Read<int>(6);
spellArea.raceMask = result.Read<uint>(7);
spellArea.raceMask = result.Read<ulong>(7);
spellArea.gender = (Gender)result.Read<uint>(8);
spellArea.flags = (SpellAreaFlag)result.Read<byte>(9);
@@ -1971,7 +1987,7 @@ namespace Game.Entities
effectsBySpell[effect.SpellID][effect.DifficultyID][effect.EffectIndex] = effect;
}
foreach (var spell in CliDB.SpellStorage.Values)
foreach (var spell in CliDB.SpellNameStorage.Values)
loadData[spell.Id] = new SpellInfoLoadHelper();
foreach (SpellAuraOptionsRecord auraOptions in CliDB.SpellAuraOptionsStorage.Values)
@@ -2068,13 +2084,13 @@ namespace Game.Entities
visualsBySpell[visual.SpellID].Add(visual.DifficultyID, visual);
}
foreach (var spellEntry in CliDB.SpellStorage.Values)
foreach (var spellEntry in CliDB.SpellNameStorage.Values)
{
loadData[spellEntry.Id].Entry = spellEntry;
mSpellInfoMap[spellEntry.Id] = new SpellInfo(loadData[spellEntry.Id], effectsBySpell.LookupByKey(spellEntry.Id), visualsBySpell.LookupByKey(spellEntry.Id));
}
CliDB.SpellStorage.Clear();
CliDB.SpellNameStorage.Clear();
Log.outInfo(LogFilter.ServerLoading, "Loaded SpellInfo store in {0} ms", Time.GetMSTimeDiffToNow(oldMSTime));
}
@@ -2483,6 +2499,8 @@ namespace Game.Entities
break;
case 50661:// Weakened Resolve
case 68979:// Unleashed Souls
case 48714:// Compelled
case 7853: // The Art of Being a Water Terror: Force Cast on Player
spellInfo.RangeEntry = CliDB.SpellRangeStorage.LookupByKey(13); // 50000yd
break;
// VIOLET HOLD SPELLS
@@ -2903,7 +2921,7 @@ namespace Game.Entities
if (skillLine.SkillLine != cFamily.SkillLine[0] && skillLine.SkillLine != cFamily.SkillLine[1])
continue;
if (skillLine.AcquireMethod != AbilytyLearnType.OnSkillLearn)
if (skillLine.AcquireMethod != AbilityLearnType.OnSkillLearn)
continue;
Global.SpellMgr.PetFamilySpellsStorage.Add(cFamily.Id, spellInfo.Id);
@@ -2998,6 +3016,15 @@ namespace Game.Entities
case AuraType.ProcTriggerSpellWithValue:
case AuraType.ModSpellDamageFromCaster:
case AuraType.AbilityIgnoreAurastate:
case AuraType.ModInvisibility:
case AuraType.ForceReaction:
case AuraType.ModTaunt:
case AuraType.ModDetaunt:
case AuraType.ModDamagePercentDone:
case AuraType.ModAttackPowerPct:
case AuraType.ModHitChance:
case AuraType.ModWeaponCritPercent:
case AuraType.ModBlockPercent:
case AuraType.ModRoot2:
return true;
}
@@ -3014,6 +3041,7 @@ namespace Game.Entities
case AuraType.ModRoot:
case AuraType.ModStun:
case AuraType.Transform:
case AuraType.ModInvisibility:
case AuraType.SpellMagnet:
case AuraType.SchoolAbsorb:
case AuraType.ModRoot2:
@@ -3033,6 +3061,7 @@ namespace Game.Entities
case AuraType.ModRoot2:
case AuraType.ModStun:
case AuraType.Transform:
case AuraType.ModInvisibility:
return ProcFlagsSpellType.Damage;
default:
return ProcFlagsSpellType.MaskAll;
@@ -3117,7 +3146,7 @@ namespace Game.Entities
public bool IsProfessionSkill(uint skill)
{
return IsPrimaryProfessionSkill(skill) || skill == (uint)SkillType.Fishing || skill == (uint)SkillType.Cooking || skill == (uint)SkillType.FirstAid;
return IsPrimaryProfessionSkill(skill) || skill == (uint)SkillType.Fishing || skill == (uint)SkillType.Cooking;
}
public bool IsPartOfSkillLine(SkillType skillId, uint spellId)
@@ -3209,7 +3238,7 @@ namespace Game.Entities
public class SpellInfoLoadHelper
{
public SpellRecord Entry;
public SpellNameRecord Entry;
public SpellAuraOptionsRecord AuraOptions;
public SpellAuraRestrictionsRecord AuraRestrictions;
@@ -3263,7 +3292,7 @@ namespace Game.Entities
public uint questStart; // quest start (quest must be active or rewarded for spell apply)
public uint questEnd; // quest end (quest must not be rewarded for spell apply)
public int auraSpell; // spell aura must be applied for spell apply)if possitive) and it must not be applied in other case
public uint raceMask; // can be applied only to races
public ulong raceMask; // can be applied only to races
public Gender gender; // can be applied only to gender
public uint questStartStatus; // QuestStatus that quest_start must have in order to keep the spell
public uint questEndStatus; // QuestStatus that the quest_end must have in order to keep the spell (if the quest_end's status is different than this, the spell will be dropped)