Core/PacketIO: Updated packet structures to 9.0.2

Port From (https://github.com/TrinityCore/TrinityCore/commit/96d340f70ccef57fad177a24ca099055d7dce04d)
This commit is contained in:
hondacrx
2020-12-12 23:45:36 -05:00
parent f0037ab99f
commit 4c2106781a
14 changed files with 97 additions and 104 deletions
@@ -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,
@@ -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
@@ -1225,9 +1225,8 @@ namespace Game.Entities
public UpdateFieldArray<int> Resistances = new UpdateFieldArray<int>(7, 167, 168);
public UpdateFieldArray<int> BonusResistanceMods = new UpdateFieldArray<int>(7, 167, 175);
public UpdateFieldArray<int> PowerCostModifier = new UpdateFieldArray<int>(7, 167, 182);
public UpdateFieldArray<float> PowerCostMultiplier = new UpdateFieldArray<float>(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();
}
+3 -3
View File
@@ -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());
-19
View File
@@ -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)
@@ -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<uint> DisabledClassesMask = new Optional<uint>();
@@ -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<string> MailSenders = new List<string>();
public List<uint> MailSenderTypes = new List<uint>();
public struct VisualItemInfo
{
@@ -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();
@@ -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> ItemInstance;
}
struct GarrisonMissionBonusAbility
@@ -582,17 +588,9 @@ namespace Game.Networking.Packets
foreach (List<GarrisonMissionReward> missionReward in MissionRewards)
data.WriteInt32(missionReward.Count);
foreach (List<GarrisonMissionReward> missionReward in MissionRewards)
foreach (GarrisonMissionReward missionRewardItem in missionReward)
missionRewardItem.Write(data);
foreach (List<GarrisonMissionReward> missionReward in MissionOvermaxRewards)
data.WriteInt32(missionReward.Count);
foreach (List<GarrisonMissionReward> 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<GarrisonMissionReward> missionReward in MissionRewards)
foreach (GarrisonMissionReward missionRewardItem in missionReward)
missionRewardItem.Write(data);
foreach (List<GarrisonMissionReward> missionReward in MissionOvermaxRewards)
foreach (GarrisonMissionReward missionRewardItem in missionReward)
missionRewardItem.Write(data);
}
public GarrisonType GarrTypeID;
+9 -3
View File
@@ -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<ClientGossipOptions> GossipOptions = new List<ClientGossipOptions>();
public int FriendshipFactionID = 0;
public int FriendshipFactionID;
public ObjectGuid GossipGUID;
public List<ClientGossipText> GossipText = new List<ClientGossipText>();
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<int> SpellID;
}
public class ClientGossipText
@@ -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);
}
+13 -6
View File
@@ -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
}
}
+4 -1
View File
@@ -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
-31
View File
@@ -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)
{
+23 -7
View File
@@ -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))
{